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