1 /* $NetBSD: bivideo.c,v 1.27 2007/10/19 11:59:42 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 1999-2001 5 * Shin Takemura and PocketBSD Project. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the PocketBSD project 18 * and its contributors. 19 * 4. Neither the name of the project nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: bivideo.c,v 1.27 2007/10/19 11:59:42 ad Exp $"); 39 40 #ifdef _KERNEL_OPT 41 #include "opt_hpcfb.h" 42 #endif 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/device.h> 47 #include <sys/buf.h> 48 #include <sys/ioctl.h> 49 #include <sys/reboot.h> 50 51 #include <uvm/uvm_extern.h> 52 53 #include <sys/bus.h> 54 #include <machine/autoconf.h> 55 #include <machine/bootinfo.h> 56 #include <machine/config_hook.h> 57 58 #include <dev/wscons/wsconsio.h> 59 #include <dev/wscons/wsdisplayvar.h> 60 61 #include <dev/rasops/rasops.h> 62 63 #include <dev/hpc/hpcfbvar.h> 64 #include <dev/hpc/hpcfbio.h> 65 #include <dev/hpc/bivideovar.h> 66 #include <dev/hpc/hpccmapvar.h> 67 68 #ifdef FBDEBUG 69 #define VPRINTF(arg) do { if (bootverbose) printf arg; } while (0) 70 #else 71 #define VPRINTF(arg) /* nothing */ 72 #endif 73 74 /* 75 * global variables 76 */ 77 int bivideo_dont_attach = 0; 78 79 /* 80 * function prototypes 81 */ 82 int bivideomatch(struct device *, struct cfdata *, void *); 83 void bivideoattach(struct device *, struct device *, void *); 84 int bivideo_ioctl(void *, u_long, void *, int, struct lwp *); 85 paddr_t bivideo_mmap(void *, off_t, int); 86 87 struct bivideo_softc { 88 struct device sc_dev; 89 struct hpcfb_fbconf sc_fbconf; 90 struct hpcfb_dspconf sc_dspconf; 91 void *sc_powerhook; /* power management hook */ 92 int sc_powerstate; 93 #define PWRSTAT_SUSPEND (1<<0) 94 #define PWRSTAT_VIDEOOFF (1<<1) 95 #define PWRSTAT_LCD (1<<2) 96 #define PWRSTAT_BACKLIGHT (1<<3) 97 #define PWRSTAT_ALL (0xffffffff) 98 int sc_lcd_inited; 99 #define BACKLIGHT_INITED (1<<0) 100 #define BRIGHTNESS_INITED (1<<1) 101 #define CONTRAST_INITED (1<<2) 102 int sc_brightness; 103 int sc_brightness_save; 104 int sc_max_brightness; 105 int sc_contrast; 106 int sc_max_contrast; 107 108 }; 109 110 static int bivideo_init(struct hpcfb_fbconf *); 111 static void bivideo_power(int, void *); 112 static void bivideo_update_powerstate(struct bivideo_softc *, int); 113 void bivideo_init_backlight(struct bivideo_softc *, int); 114 void bivideo_init_brightness(struct bivideo_softc *, int); 115 void bivideo_init_contrast(struct bivideo_softc *, int); 116 void bivideo_set_brightness(struct bivideo_softc *, int); 117 void bivideo_set_contrast(struct bivideo_softc *, int); 118 119 #if defined __mips__ || defined __sh__ || defined __arm__ 120 #define __BTOP(x) ((paddr_t)(x) >> PGSHIFT) 121 #define __PTOB(x) ((paddr_t)(x) << PGSHIFT) 122 #else 123 #error "define btop, ptob." 124 #endif 125 126 /* 127 * static variables 128 */ 129 CFATTACH_DECL(bivideo, sizeof(struct bivideo_softc), 130 bivideomatch, bivideoattach, NULL, NULL); 131 132 struct hpcfb_accessops bivideo_ha = { 133 bivideo_ioctl, bivideo_mmap 134 }; 135 136 static int console_flag = 0; 137 static int attach_flag = 0; 138 139 /* 140 * function bodies 141 */ 142 int 143 bivideomatch(struct device *parent, struct cfdata *match, void *aux) 144 { 145 struct mainbus_attach_args *ma = aux; 146 147 if (bivideo_dont_attach || 148 strcmp(ma->ma_name, match->cf_name)) 149 return 0; 150 151 return (1); 152 } 153 154 void 155 bivideoattach(struct device *parent, struct device *self, void *aux) 156 { 157 struct bivideo_softc *sc = device_private(self); 158 struct hpcfb_attach_args ha; 159 160 if (attach_flag) { 161 panic("%s(%d): bivideo attached twice", __FILE__, __LINE__); 162 } 163 attach_flag = 1; 164 165 printf(": "); 166 if (bivideo_init(&sc->sc_fbconf) != 0) { 167 /* just return so that hpcfb will not be attached */ 168 return; 169 } 170 171 printf("pseudo video controller"); 172 if (console_flag) { 173 printf(", console"); 174 } 175 printf("\n"); 176 printf("%s: framebuffer address: 0x%08lx\n", 177 sc->sc_dev.dv_xname, (u_long)bootinfo->fb_addr); 178 179 /* Add a suspend hook to power saving */ 180 sc->sc_powerstate = 0; 181 sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, 182 bivideo_power, sc); 183 if (sc->sc_powerhook == NULL) 184 printf("%s: WARNING: unable to establish power hook\n", 185 sc->sc_dev.dv_xname); 186 187 /* initialize backlight brightness and lcd contrast */ 188 sc->sc_lcd_inited = 0; 189 bivideo_init_brightness(sc, 1); 190 bivideo_init_contrast(sc, 1); 191 bivideo_init_backlight(sc, 1); 192 193 ha.ha_console = console_flag; 194 ha.ha_accessops = &bivideo_ha; 195 ha.ha_accessctx = sc; 196 ha.ha_curfbconf = 0; 197 ha.ha_nfbconf = 1; 198 ha.ha_fbconflist = &sc->sc_fbconf; 199 ha.ha_curdspconf = 0; 200 ha.ha_ndspconf = 1; 201 ha.ha_dspconflist = &sc->sc_dspconf; 202 203 config_found(self, &ha, hpcfbprint); 204 } 205 206 int 207 bivideo_getcnfb(struct hpcfb_fbconf *fb) 208 { 209 console_flag = 1; 210 211 return bivideo_init(fb); 212 } 213 214 static int 215 bivideo_init(struct hpcfb_fbconf *fb) 216 { 217 /* 218 * get fb settings from bootinfo 219 */ 220 if (bootinfo == NULL || 221 bootinfo->fb_addr == 0 || 222 bootinfo->fb_line_bytes == 0 || 223 bootinfo->fb_width == 0 || 224 bootinfo->fb_height == 0) { 225 printf("no frame buffer information.\n"); 226 return (-1); 227 } 228 229 /* zero fill */ 230 memset(fb, 0, sizeof(*fb)); 231 232 fb->hf_conf_index = 0; /* configuration index */ 233 fb->hf_nconfs = 1; /* how many configurations */ 234 strcpy(fb->hf_name, "built-in video"); 235 /* frame buffer name */ 236 strcpy(fb->hf_conf_name, "default"); 237 /* configuration name */ 238 fb->hf_height = bootinfo->fb_height; 239 fb->hf_width = bootinfo->fb_width; 240 fb->hf_baseaddr = (u_long)bootinfo->fb_addr; 241 fb->hf_offset = (u_long)bootinfo->fb_addr - 242 __PTOB(__BTOP(bootinfo->fb_addr)); 243 /* frame buffer start offset */ 244 fb->hf_bytes_per_line = bootinfo->fb_line_bytes; 245 fb->hf_nplanes = 1; 246 fb->hf_bytes_per_plane = bootinfo->fb_height * 247 bootinfo->fb_line_bytes; 248 249 fb->hf_access_flags |= HPCFB_ACCESS_BYTE; 250 fb->hf_access_flags |= HPCFB_ACCESS_WORD; 251 fb->hf_access_flags |= HPCFB_ACCESS_DWORD; 252 253 switch (bootinfo->fb_type) { 254 /* 255 * gray scale 256 */ 257 case BIFB_D2_M2L_3: 258 case BIFB_D2_M2L_3x2: 259 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 260 /* fall through */ 261 case BIFB_D2_M2L_0: 262 case BIFB_D2_M2L_0x2: 263 fb->hf_class = HPCFB_CLASS_GRAYSCALE; 264 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 265 fb->hf_pack_width = 8; 266 fb->hf_pixels_per_pack = 4; 267 fb->hf_pixel_width = 2; 268 fb->hf_class_data_length = sizeof(struct hf_gray_tag); 269 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */ 270 break; 271 272 case BIFB_D4_M2L_F: 273 case BIFB_D4_M2L_Fx2: 274 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 275 /* fall through */ 276 case BIFB_D4_M2L_0: 277 case BIFB_D4_M2L_0x2: 278 fb->hf_class = HPCFB_CLASS_GRAYSCALE; 279 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 280 fb->hf_pack_width = 8; 281 fb->hf_pixels_per_pack = 2; 282 fb->hf_pixel_width = 4; 283 fb->hf_class_data_length = sizeof(struct hf_gray_tag); 284 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */ 285 break; 286 287 /* 288 * indexed color 289 */ 290 case BIFB_D8_FF: 291 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 292 /* fall through */ 293 case BIFB_D8_00: 294 fb->hf_class = HPCFB_CLASS_INDEXCOLOR; 295 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 296 fb->hf_pack_width = 8; 297 fb->hf_pixels_per_pack = 1; 298 fb->hf_pixel_width = 8; 299 fb->hf_class_data_length = sizeof(struct hf_indexed_tag); 300 fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */ 301 break; 302 303 /* 304 * RGB color 305 */ 306 case BIFB_D16_FFFF: 307 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 308 /* fall through */ 309 case BIFB_D16_0000: 310 fb->hf_class = HPCFB_CLASS_RGBCOLOR; 311 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 312 #if BYTE_ORDER == LITTLE_ENDIAN 313 fb->hf_order_flags = HPCFB_REVORDER_BYTE; 314 #endif 315 fb->hf_pack_width = 16; 316 fb->hf_pixels_per_pack = 1; 317 fb->hf_pixel_width = 16; 318 319 fb->hf_class_data_length = sizeof(struct hf_rgb_tag); 320 fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */ 321 322 fb->hf_u.hf_rgb.hf_red_width = 5; 323 fb->hf_u.hf_rgb.hf_red_shift = 11; 324 fb->hf_u.hf_rgb.hf_green_width = 6; 325 fb->hf_u.hf_rgb.hf_green_shift = 5; 326 fb->hf_u.hf_rgb.hf_blue_width = 5; 327 fb->hf_u.hf_rgb.hf_blue_shift = 0; 328 fb->hf_u.hf_rgb.hf_alpha_width = 0; 329 fb->hf_u.hf_rgb.hf_alpha_shift = 0; 330 break; 331 332 default: 333 printf("unsupported type %d.\n", bootinfo->fb_type); 334 return (-1); 335 break; 336 } 337 338 return (0); /* no error */ 339 } 340 341 static void 342 bivideo_power(int why, void *arg) 343 { 344 struct bivideo_softc *sc = arg; 345 346 switch (why) { 347 case PWR_SUSPEND: 348 case PWR_STANDBY: 349 sc->sc_powerstate |= PWRSTAT_SUSPEND; 350 bivideo_update_powerstate(sc, PWRSTAT_ALL); 351 break; 352 case PWR_RESUME: 353 sc->sc_powerstate &= ~PWRSTAT_SUSPEND; 354 bivideo_update_powerstate(sc, PWRSTAT_ALL); 355 break; 356 } 357 } 358 359 static void 360 bivideo_update_powerstate(struct bivideo_softc *sc, int updates) 361 { 362 if (updates & PWRSTAT_LCD) 363 config_hook_call(CONFIG_HOOK_POWERCONTROL, 364 CONFIG_HOOK_POWERCONTROL_LCD, 365 (void*)!(sc->sc_powerstate & 366 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND))); 367 368 if (updates & PWRSTAT_BACKLIGHT) 369 config_hook_call(CONFIG_HOOK_POWERCONTROL, 370 CONFIG_HOOK_POWERCONTROL_LCDLIGHT, 371 (void*)(!(sc->sc_powerstate & 372 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) && 373 (sc->sc_powerstate & PWRSTAT_BACKLIGHT))); 374 } 375 376 int 377 bivideo_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 378 { 379 struct bivideo_softc *sc = (struct bivideo_softc *)v; 380 struct hpcfb_fbconf *fbconf; 381 struct hpcfb_dspconf *dspconf; 382 struct wsdisplay_cmap *cmap; 383 struct wsdisplay_param *dispparam; 384 int error; 385 386 switch (cmd) { 387 case WSDISPLAYIO_GETCMAP: 388 cmap = (struct wsdisplay_cmap *)data; 389 390 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR || 391 sc->sc_fbconf.hf_pack_width != 8 || 392 256 <= cmap->index || 393 256 < (cmap->index + cmap->count)) 394 return (EINVAL); 395 396 error = copyout(&bivideo_cmap_r[cmap->index], cmap->red, 397 cmap->count); 398 if (error) 399 return error; 400 error = copyout(&bivideo_cmap_g[cmap->index], cmap->green, 401 cmap->count); 402 if (error) 403 return error; 404 error = copyout(&bivideo_cmap_b[cmap->index], cmap->blue, 405 cmap->count); 406 return error; 407 408 case WSDISPLAYIO_PUTCMAP: 409 /* 410 * This driver can't set color map. 411 */ 412 return (EINVAL); 413 414 case WSDISPLAYIO_SVIDEO: 415 if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) 416 sc->sc_powerstate |= PWRSTAT_VIDEOOFF; 417 else 418 sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF; 419 bivideo_update_powerstate(sc, PWRSTAT_ALL); 420 return 0; 421 422 case WSDISPLAYIO_GVIDEO: 423 *(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ? 424 WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON; 425 return 0; 426 427 428 case WSDISPLAYIO_GETPARAM: 429 dispparam = (struct wsdisplay_param*)data; 430 switch (dispparam->param) { 431 case WSDISPLAYIO_PARAM_BACKLIGHT: 432 VPRINTF(("bivideo_ioctl: GET:BACKLIGHT\n")); 433 bivideo_init_brightness(sc, 0); 434 bivideo_init_backlight(sc, 0); 435 VPRINTF(("bivideo_ioctl: GET:(real)BACKLIGHT %d\n", 436 (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0)); 437 dispparam->min = 0; 438 dispparam->max = 1; 439 if (sc->sc_max_brightness > 0) 440 dispparam->curval = sc->sc_brightness > 0? 1: 0; 441 else 442 dispparam->curval = 443 (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1: 0; 444 VPRINTF(("bivideo_ioctl: GET:BACKLIGHT:%d(%s)\n", 445 dispparam->curval, 446 sc->sc_max_brightness > 0? "brightness": "light")); 447 return 0; 448 break; 449 case WSDISPLAYIO_PARAM_CONTRAST: 450 VPRINTF(("bivideo_ioctl: GET:CONTRAST\n")); 451 bivideo_init_contrast(sc, 0); 452 if (sc->sc_max_contrast > 0) { 453 dispparam->min = 0; 454 dispparam->max = sc->sc_max_contrast; 455 dispparam->curval = sc->sc_contrast; 456 VPRINTF(("bivideo_ioctl: GET:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast)); 457 return 0; 458 } else { 459 VPRINTF(("bivideo_ioctl: GET:CONTRAST EINVAL\n")); 460 return (EINVAL); 461 } 462 break; 463 case WSDISPLAYIO_PARAM_BRIGHTNESS: 464 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS\n")); 465 bivideo_init_brightness(sc, 0); 466 if (sc->sc_max_brightness > 0) { 467 dispparam->min = 0; 468 dispparam->max = sc->sc_max_brightness; 469 dispparam->curval = sc->sc_brightness; 470 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness)); 471 return 0; 472 } else { 473 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS EINVAL\n")); 474 return (EINVAL); 475 } 476 return (EINVAL); 477 default: 478 return (EINVAL); 479 } 480 return (0); 481 482 case WSDISPLAYIO_SETPARAM: 483 dispparam = (struct wsdisplay_param*)data; 484 switch (dispparam->param) { 485 case WSDISPLAYIO_PARAM_BACKLIGHT: 486 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT\n")); 487 if (dispparam->curval < 0 || 488 1 < dispparam->curval) 489 return (EINVAL); 490 bivideo_init_brightness(sc, 0); 491 VPRINTF(("bivideo_ioctl: SET:max brightness=%d\n", sc->sc_max_brightness)); 492 if (sc->sc_max_brightness > 0) { /* dimmer */ 493 if (dispparam->curval == 0){ 494 sc->sc_brightness_save = sc->sc_brightness; 495 bivideo_set_brightness(sc, 0); /* min */ 496 } else { 497 if (sc->sc_brightness_save == 0) 498 sc->sc_brightness_save = sc->sc_max_brightness; 499 bivideo_set_brightness(sc, sc->sc_brightness_save); 500 } 501 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:brightness=%d\n", sc->sc_brightness)); 502 } else { /* off */ 503 if (dispparam->curval == 0) 504 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 505 else 506 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 507 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:powerstate %d\n", 508 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); 509 bivideo_update_powerstate(sc, PWRSTAT_BACKLIGHT); 510 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:%d\n", 511 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); 512 } 513 return 0; 514 break; 515 case WSDISPLAYIO_PARAM_CONTRAST: 516 VPRINTF(("bivideo_ioctl: SET:CONTRAST\n")); 517 bivideo_init_contrast(sc, 0); 518 if (dispparam->curval < 0 || 519 sc->sc_max_contrast < dispparam->curval) 520 return (EINVAL); 521 if (sc->sc_max_contrast > 0) { 522 #ifdef FBDEBUG 523 int org = sc->sc_contrast; 524 #endif 525 bivideo_set_contrast(sc, dispparam->curval); 526 VPRINTF(("bivideo_ioctl: SET:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast)); 527 return 0; 528 } else { 529 VPRINTF(("bivideo_ioctl: SET:CONTRAST EINVAL\n")); 530 return (EINVAL); 531 } 532 break; 533 case WSDISPLAYIO_PARAM_BRIGHTNESS: 534 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS\n")); 535 bivideo_init_brightness(sc, 0); 536 if (dispparam->curval < 0 || 537 sc->sc_max_brightness < dispparam->curval) 538 return (EINVAL); 539 if (sc->sc_max_brightness > 0) { 540 #ifdef FBDEBUG 541 int org = sc->sc_brightness; 542 #endif 543 bivideo_set_brightness(sc, dispparam->curval); 544 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness)); 545 return 0; 546 } else { 547 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS EINVAL\n")); 548 return (EINVAL); 549 } 550 break; 551 default: 552 return (EINVAL); 553 } 554 return (0); 555 556 case HPCFBIO_GCONF: 557 fbconf = (struct hpcfb_fbconf *)data; 558 if (fbconf->hf_conf_index != 0 && 559 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 560 return (EINVAL); 561 } 562 *fbconf = sc->sc_fbconf; /* structure assignment */ 563 return (0); 564 case HPCFBIO_SCONF: 565 fbconf = (struct hpcfb_fbconf *)data; 566 if (fbconf->hf_conf_index != 0 && 567 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 568 return (EINVAL); 569 } 570 /* 571 * nothing to do because we have only one configuration 572 */ 573 return (0); 574 case HPCFBIO_GDSPCONF: 575 dspconf = (struct hpcfb_dspconf *)data; 576 if ((dspconf->hd_unit_index != 0 && 577 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 578 (dspconf->hd_conf_index != 0 && 579 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 580 return (EINVAL); 581 } 582 *dspconf = sc->sc_dspconf; /* structure assignment */ 583 return (0); 584 case HPCFBIO_SDSPCONF: 585 dspconf = (struct hpcfb_dspconf *)data; 586 if ((dspconf->hd_unit_index != 0 && 587 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 588 (dspconf->hd_conf_index != 0 && 589 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 590 return (EINVAL); 591 } 592 /* 593 * nothing to do 594 * because we have only one unit and one configuration 595 */ 596 return (0); 597 case HPCFBIO_GOP: 598 case HPCFBIO_SOP: 599 /* 600 * curently not implemented... 601 */ 602 return (EINVAL); 603 } 604 605 return (EPASSTHROUGH); 606 } 607 608 paddr_t 609 bivideo_mmap(void *ctx, off_t offset, int prot) 610 { 611 struct bivideo_softc *sc = (struct bivideo_softc *)ctx; 612 613 if (offset < 0 || 614 (sc->sc_fbconf.hf_bytes_per_plane + 615 sc->sc_fbconf.hf_offset) < offset) 616 return -1; 617 618 return __BTOP((u_long)bootinfo->fb_addr + offset); 619 } 620 621 622 void 623 bivideo_init_backlight(struct bivideo_softc *sc, int inattach) 624 { 625 int val = -1; 626 627 if (sc->sc_lcd_inited&BACKLIGHT_INITED) 628 return; 629 630 if (config_hook_call(CONFIG_HOOK_GET, 631 CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) { 632 /* we can get real light state */ 633 VPRINTF(("bivideo_init_backlight: real backlight=%d\n", val)); 634 if (val == 0) 635 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 636 else 637 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 638 sc->sc_lcd_inited |= BACKLIGHT_INITED; 639 } else if (inattach) { 640 /* 641 we cannot get real light state in attach time 642 because light device not yet attached. 643 we will retry in !inattach. 644 temporary assume light is on. 645 */ 646 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 647 } else { 648 /* we cannot get real light state, so work by myself state */ 649 sc->sc_lcd_inited |= BACKLIGHT_INITED; 650 } 651 } 652 653 void 654 bivideo_init_brightness(struct bivideo_softc *sc, int inattach) 655 { 656 int val = -1; 657 658 if (sc->sc_lcd_inited&BRIGHTNESS_INITED) 659 return; 660 661 VPRINTF(("bivideo_init_brightness\n")); 662 if (config_hook_call(CONFIG_HOOK_GET, 663 CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) { 664 /* we can get real brightness max */ 665 VPRINTF(("bivideo_init_brightness: real brightness max=%d\n", val)); 666 sc->sc_max_brightness = val; 667 val = -1; 668 if (config_hook_call(CONFIG_HOOK_GET, 669 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 670 /* we can get real brightness */ 671 VPRINTF(("bivideo_init_brightness: real brightness=%d\n", val)); 672 sc->sc_brightness_save = sc->sc_brightness = val; 673 } else { 674 sc->sc_brightness_save = 675 sc->sc_brightness = sc->sc_max_brightness; 676 } 677 sc->sc_lcd_inited |= BRIGHTNESS_INITED; 678 } else if (inattach) { 679 /* 680 we cannot get real brightness in attach time 681 because brightness device not yet attached. 682 we will retry in !inattach. 683 */ 684 sc->sc_max_brightness = -1; 685 sc->sc_brightness = -1; 686 sc->sc_brightness_save = -1; 687 } else { 688 /* we cannot get real brightness */ 689 sc->sc_lcd_inited |= BRIGHTNESS_INITED; 690 } 691 692 return; 693 } 694 695 void 696 bivideo_init_contrast(struct bivideo_softc *sc, int inattach) 697 { 698 int val = -1; 699 700 if (sc->sc_lcd_inited&CONTRAST_INITED) 701 return; 702 703 VPRINTF(("bivideo_init_contrast\n")); 704 if (config_hook_call(CONFIG_HOOK_GET, 705 CONFIG_HOOK_CONTRAST_MAX, &val) != -1) { 706 /* we can get real contrast max */ 707 VPRINTF(("bivideo_init_contrast: real contrast max=%d\n", val)); 708 sc->sc_max_contrast = val; 709 val = -1; 710 if (config_hook_call(CONFIG_HOOK_GET, 711 CONFIG_HOOK_CONTRAST, &val) != -1) { 712 /* we can get real contrast */ 713 VPRINTF(("bivideo_init_contrast: real contrast=%d\n", val)); 714 sc->sc_contrast = val; 715 } else { 716 sc->sc_contrast = sc->sc_max_contrast; 717 } 718 sc->sc_lcd_inited |= CONTRAST_INITED; 719 } else if (inattach) { 720 /* 721 we cannot get real contrast in attach time 722 because contrast device not yet attached. 723 we will retry in !inattach. 724 */ 725 sc->sc_max_contrast = -1; 726 sc->sc_contrast = -1; 727 } else { 728 /* we cannot get real contrast */ 729 sc->sc_lcd_inited |= CONTRAST_INITED; 730 } 731 732 return; 733 } 734 735 void 736 bivideo_set_brightness(struct bivideo_softc *sc, int val) 737 { 738 sc->sc_brightness = val; 739 740 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 741 if (config_hook_call(CONFIG_HOOK_GET, 742 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 743 sc->sc_brightness = val; 744 } 745 } 746 747 void 748 bivideo_set_contrast(struct bivideo_softc *sc, int val) 749 { 750 sc->sc_contrast = val; 751 752 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 753 if (config_hook_call(CONFIG_HOOK_GET, 754 CONFIG_HOOK_CONTRAST, &val) != -1) { 755 sc->sc_contrast = val; 756 } 757 } 758