1 /* $NetBSD: bivideo.c,v 1.28 2008/04/06 20:28:36 cegger 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.28 2008/04/06 20:28:36 cegger 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 device_xname(&sc->sc_dev), (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(device_xname(&sc->sc_dev), 182 bivideo_power, sc); 183 if (sc->sc_powerhook == NULL) 184 aprint_error_dev(&sc->sc_dev, "WARNING: unable to establish power hook\n"); 185 186 /* initialize backlight brightness and lcd contrast */ 187 sc->sc_lcd_inited = 0; 188 bivideo_init_brightness(sc, 1); 189 bivideo_init_contrast(sc, 1); 190 bivideo_init_backlight(sc, 1); 191 192 ha.ha_console = console_flag; 193 ha.ha_accessops = &bivideo_ha; 194 ha.ha_accessctx = sc; 195 ha.ha_curfbconf = 0; 196 ha.ha_nfbconf = 1; 197 ha.ha_fbconflist = &sc->sc_fbconf; 198 ha.ha_curdspconf = 0; 199 ha.ha_ndspconf = 1; 200 ha.ha_dspconflist = &sc->sc_dspconf; 201 202 config_found(self, &ha, hpcfbprint); 203 } 204 205 int 206 bivideo_getcnfb(struct hpcfb_fbconf *fb) 207 { 208 console_flag = 1; 209 210 return bivideo_init(fb); 211 } 212 213 static int 214 bivideo_init(struct hpcfb_fbconf *fb) 215 { 216 /* 217 * get fb settings from bootinfo 218 */ 219 if (bootinfo == NULL || 220 bootinfo->fb_addr == 0 || 221 bootinfo->fb_line_bytes == 0 || 222 bootinfo->fb_width == 0 || 223 bootinfo->fb_height == 0) { 224 printf("no frame buffer information.\n"); 225 return (-1); 226 } 227 228 /* zero fill */ 229 memset(fb, 0, sizeof(*fb)); 230 231 fb->hf_conf_index = 0; /* configuration index */ 232 fb->hf_nconfs = 1; /* how many configurations */ 233 strcpy(fb->hf_name, "built-in video"); 234 /* frame buffer name */ 235 strcpy(fb->hf_conf_name, "default"); 236 /* configuration name */ 237 fb->hf_height = bootinfo->fb_height; 238 fb->hf_width = bootinfo->fb_width; 239 fb->hf_baseaddr = (u_long)bootinfo->fb_addr; 240 fb->hf_offset = (u_long)bootinfo->fb_addr - 241 __PTOB(__BTOP(bootinfo->fb_addr)); 242 /* frame buffer start offset */ 243 fb->hf_bytes_per_line = bootinfo->fb_line_bytes; 244 fb->hf_nplanes = 1; 245 fb->hf_bytes_per_plane = bootinfo->fb_height * 246 bootinfo->fb_line_bytes; 247 248 fb->hf_access_flags |= HPCFB_ACCESS_BYTE; 249 fb->hf_access_flags |= HPCFB_ACCESS_WORD; 250 fb->hf_access_flags |= HPCFB_ACCESS_DWORD; 251 252 switch (bootinfo->fb_type) { 253 /* 254 * gray scale 255 */ 256 case BIFB_D2_M2L_3: 257 case BIFB_D2_M2L_3x2: 258 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 259 /* fall through */ 260 case BIFB_D2_M2L_0: 261 case BIFB_D2_M2L_0x2: 262 fb->hf_class = HPCFB_CLASS_GRAYSCALE; 263 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 264 fb->hf_pack_width = 8; 265 fb->hf_pixels_per_pack = 4; 266 fb->hf_pixel_width = 2; 267 fb->hf_class_data_length = sizeof(struct hf_gray_tag); 268 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */ 269 break; 270 271 case BIFB_D4_M2L_F: 272 case BIFB_D4_M2L_Fx2: 273 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 274 /* fall through */ 275 case BIFB_D4_M2L_0: 276 case BIFB_D4_M2L_0x2: 277 fb->hf_class = HPCFB_CLASS_GRAYSCALE; 278 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 279 fb->hf_pack_width = 8; 280 fb->hf_pixels_per_pack = 2; 281 fb->hf_pixel_width = 4; 282 fb->hf_class_data_length = sizeof(struct hf_gray_tag); 283 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */ 284 break; 285 286 /* 287 * indexed color 288 */ 289 case BIFB_D8_FF: 290 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 291 /* fall through */ 292 case BIFB_D8_00: 293 fb->hf_class = HPCFB_CLASS_INDEXCOLOR; 294 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 295 fb->hf_pack_width = 8; 296 fb->hf_pixels_per_pack = 1; 297 fb->hf_pixel_width = 8; 298 fb->hf_class_data_length = sizeof(struct hf_indexed_tag); 299 fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */ 300 break; 301 302 /* 303 * RGB color 304 */ 305 case BIFB_D16_FFFF: 306 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 307 /* fall through */ 308 case BIFB_D16_0000: 309 fb->hf_class = HPCFB_CLASS_RGBCOLOR; 310 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 311 #if BYTE_ORDER == LITTLE_ENDIAN 312 fb->hf_order_flags = HPCFB_REVORDER_BYTE; 313 #endif 314 fb->hf_pack_width = 16; 315 fb->hf_pixels_per_pack = 1; 316 fb->hf_pixel_width = 16; 317 318 fb->hf_class_data_length = sizeof(struct hf_rgb_tag); 319 fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */ 320 321 fb->hf_u.hf_rgb.hf_red_width = 5; 322 fb->hf_u.hf_rgb.hf_red_shift = 11; 323 fb->hf_u.hf_rgb.hf_green_width = 6; 324 fb->hf_u.hf_rgb.hf_green_shift = 5; 325 fb->hf_u.hf_rgb.hf_blue_width = 5; 326 fb->hf_u.hf_rgb.hf_blue_shift = 0; 327 fb->hf_u.hf_rgb.hf_alpha_width = 0; 328 fb->hf_u.hf_rgb.hf_alpha_shift = 0; 329 break; 330 331 default: 332 printf("unsupported type %d.\n", bootinfo->fb_type); 333 return (-1); 334 break; 335 } 336 337 return (0); /* no error */ 338 } 339 340 static void 341 bivideo_power(int why, void *arg) 342 { 343 struct bivideo_softc *sc = arg; 344 345 switch (why) { 346 case PWR_SUSPEND: 347 case PWR_STANDBY: 348 sc->sc_powerstate |= PWRSTAT_SUSPEND; 349 bivideo_update_powerstate(sc, PWRSTAT_ALL); 350 break; 351 case PWR_RESUME: 352 sc->sc_powerstate &= ~PWRSTAT_SUSPEND; 353 bivideo_update_powerstate(sc, PWRSTAT_ALL); 354 break; 355 } 356 } 357 358 static void 359 bivideo_update_powerstate(struct bivideo_softc *sc, int updates) 360 { 361 if (updates & PWRSTAT_LCD) 362 config_hook_call(CONFIG_HOOK_POWERCONTROL, 363 CONFIG_HOOK_POWERCONTROL_LCD, 364 (void*)!(sc->sc_powerstate & 365 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND))); 366 367 if (updates & PWRSTAT_BACKLIGHT) 368 config_hook_call(CONFIG_HOOK_POWERCONTROL, 369 CONFIG_HOOK_POWERCONTROL_LCDLIGHT, 370 (void*)(!(sc->sc_powerstate & 371 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) && 372 (sc->sc_powerstate & PWRSTAT_BACKLIGHT))); 373 } 374 375 int 376 bivideo_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 377 { 378 struct bivideo_softc *sc = (struct bivideo_softc *)v; 379 struct hpcfb_fbconf *fbconf; 380 struct hpcfb_dspconf *dspconf; 381 struct wsdisplay_cmap *cmap; 382 struct wsdisplay_param *dispparam; 383 int error; 384 385 switch (cmd) { 386 case WSDISPLAYIO_GETCMAP: 387 cmap = (struct wsdisplay_cmap *)data; 388 389 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR || 390 sc->sc_fbconf.hf_pack_width != 8 || 391 256 <= cmap->index || 392 256 < (cmap->index + cmap->count)) 393 return (EINVAL); 394 395 error = copyout(&bivideo_cmap_r[cmap->index], cmap->red, 396 cmap->count); 397 if (error) 398 return error; 399 error = copyout(&bivideo_cmap_g[cmap->index], cmap->green, 400 cmap->count); 401 if (error) 402 return error; 403 error = copyout(&bivideo_cmap_b[cmap->index], cmap->blue, 404 cmap->count); 405 return error; 406 407 case WSDISPLAYIO_PUTCMAP: 408 /* 409 * This driver can't set color map. 410 */ 411 return (EINVAL); 412 413 case WSDISPLAYIO_SVIDEO: 414 if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) 415 sc->sc_powerstate |= PWRSTAT_VIDEOOFF; 416 else 417 sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF; 418 bivideo_update_powerstate(sc, PWRSTAT_ALL); 419 return 0; 420 421 case WSDISPLAYIO_GVIDEO: 422 *(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ? 423 WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON; 424 return 0; 425 426 427 case WSDISPLAYIO_GETPARAM: 428 dispparam = (struct wsdisplay_param*)data; 429 switch (dispparam->param) { 430 case WSDISPLAYIO_PARAM_BACKLIGHT: 431 VPRINTF(("bivideo_ioctl: GET:BACKLIGHT\n")); 432 bivideo_init_brightness(sc, 0); 433 bivideo_init_backlight(sc, 0); 434 VPRINTF(("bivideo_ioctl: GET:(real)BACKLIGHT %d\n", 435 (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0)); 436 dispparam->min = 0; 437 dispparam->max = 1; 438 if (sc->sc_max_brightness > 0) 439 dispparam->curval = sc->sc_brightness > 0? 1: 0; 440 else 441 dispparam->curval = 442 (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1: 0; 443 VPRINTF(("bivideo_ioctl: GET:BACKLIGHT:%d(%s)\n", 444 dispparam->curval, 445 sc->sc_max_brightness > 0? "brightness": "light")); 446 return 0; 447 break; 448 case WSDISPLAYIO_PARAM_CONTRAST: 449 VPRINTF(("bivideo_ioctl: GET:CONTRAST\n")); 450 bivideo_init_contrast(sc, 0); 451 if (sc->sc_max_contrast > 0) { 452 dispparam->min = 0; 453 dispparam->max = sc->sc_max_contrast; 454 dispparam->curval = sc->sc_contrast; 455 VPRINTF(("bivideo_ioctl: GET:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast)); 456 return 0; 457 } else { 458 VPRINTF(("bivideo_ioctl: GET:CONTRAST EINVAL\n")); 459 return (EINVAL); 460 } 461 break; 462 case WSDISPLAYIO_PARAM_BRIGHTNESS: 463 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS\n")); 464 bivideo_init_brightness(sc, 0); 465 if (sc->sc_max_brightness > 0) { 466 dispparam->min = 0; 467 dispparam->max = sc->sc_max_brightness; 468 dispparam->curval = sc->sc_brightness; 469 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness)); 470 return 0; 471 } else { 472 VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS EINVAL\n")); 473 return (EINVAL); 474 } 475 return (EINVAL); 476 default: 477 return (EINVAL); 478 } 479 return (0); 480 481 case WSDISPLAYIO_SETPARAM: 482 dispparam = (struct wsdisplay_param*)data; 483 switch (dispparam->param) { 484 case WSDISPLAYIO_PARAM_BACKLIGHT: 485 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT\n")); 486 if (dispparam->curval < 0 || 487 1 < dispparam->curval) 488 return (EINVAL); 489 bivideo_init_brightness(sc, 0); 490 VPRINTF(("bivideo_ioctl: SET:max brightness=%d\n", sc->sc_max_brightness)); 491 if (sc->sc_max_brightness > 0) { /* dimmer */ 492 if (dispparam->curval == 0){ 493 sc->sc_brightness_save = sc->sc_brightness; 494 bivideo_set_brightness(sc, 0); /* min */ 495 } else { 496 if (sc->sc_brightness_save == 0) 497 sc->sc_brightness_save = sc->sc_max_brightness; 498 bivideo_set_brightness(sc, sc->sc_brightness_save); 499 } 500 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:brightness=%d\n", sc->sc_brightness)); 501 } else { /* off */ 502 if (dispparam->curval == 0) 503 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 504 else 505 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 506 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:powerstate %d\n", 507 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); 508 bivideo_update_powerstate(sc, PWRSTAT_BACKLIGHT); 509 VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:%d\n", 510 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); 511 } 512 return 0; 513 break; 514 case WSDISPLAYIO_PARAM_CONTRAST: 515 VPRINTF(("bivideo_ioctl: SET:CONTRAST\n")); 516 bivideo_init_contrast(sc, 0); 517 if (dispparam->curval < 0 || 518 sc->sc_max_contrast < dispparam->curval) 519 return (EINVAL); 520 if (sc->sc_max_contrast > 0) { 521 #ifdef FBDEBUG 522 int org = sc->sc_contrast; 523 #endif 524 bivideo_set_contrast(sc, dispparam->curval); 525 VPRINTF(("bivideo_ioctl: SET:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast)); 526 return 0; 527 } else { 528 VPRINTF(("bivideo_ioctl: SET:CONTRAST EINVAL\n")); 529 return (EINVAL); 530 } 531 break; 532 case WSDISPLAYIO_PARAM_BRIGHTNESS: 533 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS\n")); 534 bivideo_init_brightness(sc, 0); 535 if (dispparam->curval < 0 || 536 sc->sc_max_brightness < dispparam->curval) 537 return (EINVAL); 538 if (sc->sc_max_brightness > 0) { 539 #ifdef FBDEBUG 540 int org = sc->sc_brightness; 541 #endif 542 bivideo_set_brightness(sc, dispparam->curval); 543 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness)); 544 return 0; 545 } else { 546 VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS EINVAL\n")); 547 return (EINVAL); 548 } 549 break; 550 default: 551 return (EINVAL); 552 } 553 return (0); 554 555 case HPCFBIO_GCONF: 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 *fbconf = sc->sc_fbconf; /* structure assignment */ 562 return (0); 563 case HPCFBIO_SCONF: 564 fbconf = (struct hpcfb_fbconf *)data; 565 if (fbconf->hf_conf_index != 0 && 566 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 567 return (EINVAL); 568 } 569 /* 570 * nothing to do because we have only one configuration 571 */ 572 return (0); 573 case HPCFBIO_GDSPCONF: 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 *dspconf = sc->sc_dspconf; /* structure assignment */ 582 return (0); 583 case HPCFBIO_SDSPCONF: 584 dspconf = (struct hpcfb_dspconf *)data; 585 if ((dspconf->hd_unit_index != 0 && 586 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 587 (dspconf->hd_conf_index != 0 && 588 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 589 return (EINVAL); 590 } 591 /* 592 * nothing to do 593 * because we have only one unit and one configuration 594 */ 595 return (0); 596 case HPCFBIO_GOP: 597 case HPCFBIO_SOP: 598 /* 599 * curently not implemented... 600 */ 601 return (EINVAL); 602 } 603 604 return (EPASSTHROUGH); 605 } 606 607 paddr_t 608 bivideo_mmap(void *ctx, off_t offset, int prot) 609 { 610 struct bivideo_softc *sc = (struct bivideo_softc *)ctx; 611 612 if (offset < 0 || 613 (sc->sc_fbconf.hf_bytes_per_plane + 614 sc->sc_fbconf.hf_offset) < offset) 615 return -1; 616 617 return __BTOP((u_long)bootinfo->fb_addr + offset); 618 } 619 620 621 void 622 bivideo_init_backlight(struct bivideo_softc *sc, int inattach) 623 { 624 int val = -1; 625 626 if (sc->sc_lcd_inited&BACKLIGHT_INITED) 627 return; 628 629 if (config_hook_call(CONFIG_HOOK_GET, 630 CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) { 631 /* we can get real light state */ 632 VPRINTF(("bivideo_init_backlight: real backlight=%d\n", val)); 633 if (val == 0) 634 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 635 else 636 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 637 sc->sc_lcd_inited |= BACKLIGHT_INITED; 638 } else if (inattach) { 639 /* 640 we cannot get real light state in attach time 641 because light device not yet attached. 642 we will retry in !inattach. 643 temporary assume light is on. 644 */ 645 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 646 } else { 647 /* we cannot get real light state, so work by myself state */ 648 sc->sc_lcd_inited |= BACKLIGHT_INITED; 649 } 650 } 651 652 void 653 bivideo_init_brightness(struct bivideo_softc *sc, int inattach) 654 { 655 int val = -1; 656 657 if (sc->sc_lcd_inited&BRIGHTNESS_INITED) 658 return; 659 660 VPRINTF(("bivideo_init_brightness\n")); 661 if (config_hook_call(CONFIG_HOOK_GET, 662 CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) { 663 /* we can get real brightness max */ 664 VPRINTF(("bivideo_init_brightness: real brightness max=%d\n", val)); 665 sc->sc_max_brightness = val; 666 val = -1; 667 if (config_hook_call(CONFIG_HOOK_GET, 668 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 669 /* we can get real brightness */ 670 VPRINTF(("bivideo_init_brightness: real brightness=%d\n", val)); 671 sc->sc_brightness_save = sc->sc_brightness = val; 672 } else { 673 sc->sc_brightness_save = 674 sc->sc_brightness = sc->sc_max_brightness; 675 } 676 sc->sc_lcd_inited |= BRIGHTNESS_INITED; 677 } else if (inattach) { 678 /* 679 we cannot get real brightness in attach time 680 because brightness device not yet attached. 681 we will retry in !inattach. 682 */ 683 sc->sc_max_brightness = -1; 684 sc->sc_brightness = -1; 685 sc->sc_brightness_save = -1; 686 } else { 687 /* we cannot get real brightness */ 688 sc->sc_lcd_inited |= BRIGHTNESS_INITED; 689 } 690 691 return; 692 } 693 694 void 695 bivideo_init_contrast(struct bivideo_softc *sc, int inattach) 696 { 697 int val = -1; 698 699 if (sc->sc_lcd_inited&CONTRAST_INITED) 700 return; 701 702 VPRINTF(("bivideo_init_contrast\n")); 703 if (config_hook_call(CONFIG_HOOK_GET, 704 CONFIG_HOOK_CONTRAST_MAX, &val) != -1) { 705 /* we can get real contrast max */ 706 VPRINTF(("bivideo_init_contrast: real contrast max=%d\n", val)); 707 sc->sc_max_contrast = val; 708 val = -1; 709 if (config_hook_call(CONFIG_HOOK_GET, 710 CONFIG_HOOK_CONTRAST, &val) != -1) { 711 /* we can get real contrast */ 712 VPRINTF(("bivideo_init_contrast: real contrast=%d\n", val)); 713 sc->sc_contrast = val; 714 } else { 715 sc->sc_contrast = sc->sc_max_contrast; 716 } 717 sc->sc_lcd_inited |= CONTRAST_INITED; 718 } else if (inattach) { 719 /* 720 we cannot get real contrast in attach time 721 because contrast device not yet attached. 722 we will retry in !inattach. 723 */ 724 sc->sc_max_contrast = -1; 725 sc->sc_contrast = -1; 726 } else { 727 /* we cannot get real contrast */ 728 sc->sc_lcd_inited |= CONTRAST_INITED; 729 } 730 731 return; 732 } 733 734 void 735 bivideo_set_brightness(struct bivideo_softc *sc, int val) 736 { 737 sc->sc_brightness = val; 738 739 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 740 if (config_hook_call(CONFIG_HOOK_GET, 741 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 742 sc->sc_brightness = val; 743 } 744 } 745 746 void 747 bivideo_set_contrast(struct bivideo_softc *sc, int val) 748 { 749 sc->sc_contrast = val; 750 751 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 752 if (config_hook_call(CONFIG_HOOK_GET, 753 CONFIG_HOOK_CONTRAST, &val) != -1) { 754 sc->sc_contrast = val; 755 } 756 } 757