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