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