1 /* $NetBSD: bivideo.c,v 1.21 2005/12/11 12:21:22 christos 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.21 2005/12/11 12:21:22 christos 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 lwp *); 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 CFATTACH_DECL(bivideo, sizeof(struct bivideo_softc), 126 bivideomatch, bivideoattach, NULL, NULL); 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_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 lwp *l) 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 int error; 380 381 switch (cmd) { 382 case WSDISPLAYIO_GETCMAP: 383 cmap = (struct wsdisplay_cmap *)data; 384 385 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR || 386 sc->sc_fbconf.hf_pack_width != 8 || 387 256 <= cmap->index || 388 256 < (cmap->index + cmap->count)) 389 return (EINVAL); 390 391 error = copyout(&bivideo_cmap_r[cmap->index], cmap->red, 392 cmap->count); 393 if (error) 394 return error; 395 error = copyout(&bivideo_cmap_g[cmap->index], cmap->green, 396 cmap->count); 397 if (error) 398 return error; 399 error = copyout(&bivideo_cmap_b[cmap->index], cmap->blue, 400 cmap->count); 401 return error; 402 403 case WSDISPLAYIO_PUTCMAP: 404 /* 405 * This driver can't set color map. 406 */ 407 return (EINVAL); 408 409 case WSDISPLAYIO_SVIDEO: 410 if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) 411 sc->sc_powerstate |= PWRSTAT_VIDEOOFF; 412 else 413 sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF; 414 bivideo_update_powerstate(sc, PWRSTAT_ALL); 415 return 0; 416 417 case WSDISPLAYIO_GVIDEO: 418 *(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ? 419 WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON; 420 return 0; 421 422 423 case WSDISPLAYIO_GETPARAM: 424 dispparam = (struct wsdisplay_param*)data; 425 switch (dispparam->param) { 426 case WSDISPLAYIO_PARAM_BACKLIGHT: 427 VPRINTF(("bivideo_ioctl: GET:BACKLIGHT\n")); 428 bivideo_init_brightness(sc, 0); 429 bivideo_init_backlight(sc, 0); 430 VPRINTF(("bivideo_ioctl: GET:(real)BACKLIGHT %d\n", 431 (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0)); 432 dispparam->min = 0; 433 dispparam->max = 1; 434 if (sc->sc_max_brightness > 0) 435 dispparam->curval = sc->sc_brightness > 0? 1: 0; 436 else 437 dispparam->curval = 438 (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1: 0; 439 VPRINTF(("bivideo_ioctl: GET:BACKLIGHT:%d(%s)\n", 440 dispparam->curval, 441 sc->sc_max_brightness > 0? "brightness": "light")); 442 return 0; 443 break; 444 case WSDISPLAYIO_PARAM_CONTRAST: 445 VPRINTF(("bivideo_ioctl: GET:CONTRAST\n")); 446 bivideo_init_contrast(sc, 0); 447 if (sc->sc_max_contrast > 0) { 448 dispparam->min = 0; 449 dispparam->max = sc->sc_max_contrast; 450 dispparam->curval = sc->sc_contrast; 451 VPRINTF(("bivideo_ioctl: GET:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast)); 452 return 0; 453 } else { 454 VPRINTF(("bivideo_ioctl: GET:CONTRAST EINVAL\n")); 455 return (EINVAL); 456 } 457 break; 458 case WSDISPLAYIO_PARAM_BRIGHTNESS: 459 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS\n")); 460 bivideo_init_brightness(sc, 0); 461 if (sc->sc_max_brightness > 0) { 462 dispparam->min = 0; 463 dispparam->max = sc->sc_max_brightness; 464 dispparam->curval = sc->sc_brightness; 465 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness)); 466 return 0; 467 } else { 468 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS EINVAL\n")); 469 return (EINVAL); 470 } 471 return (EINVAL); 472 default: 473 return (EINVAL); 474 } 475 return (0); 476 477 case WSDISPLAYIO_SETPARAM: 478 dispparam = (struct wsdisplay_param*)data; 479 switch (dispparam->param) { 480 case WSDISPLAYIO_PARAM_BACKLIGHT: 481 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT\n")); 482 if (dispparam->curval < 0 || 483 1 < dispparam->curval) 484 return (EINVAL); 485 bivideo_init_brightness(sc, 0); 486 VPRINTF(("bivideo_ioctl: SET:max brightness=%d\n", sc->sc_max_brightness)); 487 if (sc->sc_max_brightness > 0) { /* dimmer */ 488 if (dispparam->curval == 0){ 489 sc->sc_brightness_save = sc->sc_brightness; 490 bivideo_set_brightness(sc, 0); /* min */ 491 } else { 492 if (sc->sc_brightness_save == 0) 493 sc->sc_brightness_save = sc->sc_max_brightness; 494 bivideo_set_brightness(sc, sc->sc_brightness_save); 495 } 496 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:brightness=%d\n", sc->sc_brightness)); 497 } else { /* off */ 498 if (dispparam->curval == 0) 499 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 500 else 501 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 502 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:powerstate %d\n", 503 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); 504 bivideo_update_powerstate(sc, PWRSTAT_BACKLIGHT); 505 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:%d\n", 506 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); 507 } 508 return 0; 509 break; 510 case WSDISPLAYIO_PARAM_CONTRAST: 511 VPRINTF(("bivideo_ioctl: SET:CONTRAST\n")); 512 bivideo_init_contrast(sc, 0); 513 if (dispparam->curval < 0 || 514 sc->sc_max_contrast < dispparam->curval) 515 return (EINVAL); 516 if (sc->sc_max_contrast > 0) { 517 int org = sc->sc_contrast; 518 bivideo_set_contrast(sc, dispparam->curval); 519 VPRINTF(("bivideo_ioctl: SET:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast)); 520 return 0; 521 } else { 522 VPRINTF(("bivideo_ioctl: SET:CONTRAST EINVAL\n")); 523 return (EINVAL); 524 } 525 break; 526 case WSDISPLAYIO_PARAM_BRIGHTNESS: 527 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS\n")); 528 bivideo_init_brightness(sc, 0); 529 if (dispparam->curval < 0 || 530 sc->sc_max_brightness < dispparam->curval) 531 return (EINVAL); 532 if (sc->sc_max_brightness > 0) { 533 int org = sc->sc_brightness; 534 bivideo_set_brightness(sc, dispparam->curval); 535 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness)); 536 return 0; 537 } else { 538 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS EINVAL\n")); 539 return (EINVAL); 540 } 541 break; 542 default: 543 return (EINVAL); 544 } 545 return (0); 546 547 case HPCFBIO_GCONF: 548 fbconf = (struct hpcfb_fbconf *)data; 549 if (fbconf->hf_conf_index != 0 && 550 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 551 return (EINVAL); 552 } 553 *fbconf = sc->sc_fbconf; /* structure assignment */ 554 return (0); 555 case HPCFBIO_SCONF: 556 fbconf = (struct hpcfb_fbconf *)data; 557 if (fbconf->hf_conf_index != 0 && 558 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 559 return (EINVAL); 560 } 561 /* 562 * nothing to do because we have only one configuration 563 */ 564 return (0); 565 case HPCFBIO_GDSPCONF: 566 dspconf = (struct hpcfb_dspconf *)data; 567 if ((dspconf->hd_unit_index != 0 && 568 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 569 (dspconf->hd_conf_index != 0 && 570 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 571 return (EINVAL); 572 } 573 *dspconf = sc->sc_dspconf; /* structure assignment */ 574 return (0); 575 case HPCFBIO_SDSPCONF: 576 dspconf = (struct hpcfb_dspconf *)data; 577 if ((dspconf->hd_unit_index != 0 && 578 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 579 (dspconf->hd_conf_index != 0 && 580 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 581 return (EINVAL); 582 } 583 /* 584 * nothing to do 585 * because we have only one unit and one configuration 586 */ 587 return (0); 588 case HPCFBIO_GOP: 589 case HPCFBIO_SOP: 590 /* 591 * curently not implemented... 592 */ 593 return (EINVAL); 594 } 595 596 return (EPASSTHROUGH); 597 } 598 599 paddr_t 600 bivideo_mmap(void *ctx, off_t offset, int prot) 601 { 602 struct bivideo_softc *sc = (struct bivideo_softc *)ctx; 603 604 if (offset < 0 || 605 (sc->sc_fbconf.hf_bytes_per_plane + 606 sc->sc_fbconf.hf_offset) < offset) 607 return -1; 608 609 return __BTOP((u_long)bootinfo->fb_addr + offset); 610 } 611 612 613 void 614 bivideo_init_backlight(struct bivideo_softc *sc, int inattach) 615 { 616 int val = -1; 617 618 if (sc->sc_lcd_inited&BACKLIGHT_INITED) 619 return; 620 621 if (config_hook_call(CONFIG_HOOK_GET, 622 CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) { 623 /* we can get real light state */ 624 VPRINTF(("bivideo_init_backlight: real backlight=%d\n", val)); 625 if (val == 0) 626 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 627 else 628 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 629 sc->sc_lcd_inited |= BACKLIGHT_INITED; 630 } else if (inattach) { 631 /* 632 we cannot get real light state in attach time 633 because light device not yet attached. 634 we will retry in !inattach. 635 temporary assume light is on. 636 */ 637 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 638 } else { 639 /* we cannot get real light state, so work by myself state */ 640 sc->sc_lcd_inited |= BACKLIGHT_INITED; 641 } 642 } 643 644 void 645 bivideo_init_brightness(struct bivideo_softc *sc, int inattach) 646 { 647 int val = -1; 648 649 if (sc->sc_lcd_inited&BRIGHTNESS_INITED) 650 return; 651 652 VPRINTF(("bivideo_init_brightness\n")); 653 if (config_hook_call(CONFIG_HOOK_GET, 654 CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) { 655 /* we can get real brightness max */ 656 VPRINTF(("bivideo_init_brightness: real brightness max=%d\n", val)); 657 sc->sc_max_brightness = val; 658 val = -1; 659 if (config_hook_call(CONFIG_HOOK_GET, 660 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 661 /* we can get real brightness */ 662 VPRINTF(("bivideo_init_brightness: real brightness=%d\n", val)); 663 sc->sc_brightness_save = sc->sc_brightness = val; 664 } else { 665 sc->sc_brightness_save = 666 sc->sc_brightness = sc->sc_max_brightness; 667 } 668 sc->sc_lcd_inited |= BRIGHTNESS_INITED; 669 } else if (inattach) { 670 /* 671 we cannot get real brightness in attach time 672 because brightness device not yet attached. 673 we will retry in !inattach. 674 */ 675 sc->sc_max_brightness = -1; 676 sc->sc_brightness = -1; 677 sc->sc_brightness_save = -1; 678 } else { 679 /* we cannot get real brightness */ 680 sc->sc_lcd_inited |= BRIGHTNESS_INITED; 681 } 682 683 return; 684 } 685 686 void 687 bivideo_init_contrast(struct bivideo_softc *sc, int inattach) 688 { 689 int val = -1; 690 691 if (sc->sc_lcd_inited&CONTRAST_INITED) 692 return; 693 694 VPRINTF(("bivideo_init_contrast\n")); 695 if (config_hook_call(CONFIG_HOOK_GET, 696 CONFIG_HOOK_CONTRAST_MAX, &val) != -1) { 697 /* we can get real contrast max */ 698 VPRINTF(("bivideo_init_contrast: real contrast max=%d\n", val)); 699 sc->sc_max_contrast = val; 700 val = -1; 701 if (config_hook_call(CONFIG_HOOK_GET, 702 CONFIG_HOOK_CONTRAST, &val) != -1) { 703 /* we can get real contrast */ 704 VPRINTF(("bivideo_init_contrast: real contrast=%d\n", val)); 705 sc->sc_contrast = val; 706 } else { 707 sc->sc_contrast = sc->sc_max_contrast; 708 } 709 sc->sc_lcd_inited |= CONTRAST_INITED; 710 } else if (inattach) { 711 /* 712 we cannot get real contrast in attach time 713 because contrast device not yet attached. 714 we will retry in !inattach. 715 */ 716 sc->sc_max_contrast = -1; 717 sc->sc_contrast = -1; 718 } else { 719 /* we cannot get real contrast */ 720 sc->sc_lcd_inited |= CONTRAST_INITED; 721 } 722 723 return; 724 } 725 726 void 727 bivideo_set_brightness(struct bivideo_softc *sc, int val) 728 { 729 sc->sc_brightness = val; 730 731 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 732 if (config_hook_call(CONFIG_HOOK_GET, 733 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 734 sc->sc_brightness = val; 735 } 736 } 737 738 void 739 bivideo_set_contrast(struct bivideo_softc *sc, int val) 740 { 741 sc->sc_contrast = val; 742 743 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 744 if (config_hook_call(CONFIG_HOOK_GET, 745 CONFIG_HOOK_CONTRAST, &val) != -1) { 746 sc->sc_contrast = val; 747 } 748 } 749