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