1 /* $NetBSD: ite8181.c,v 1.25 2007/03/04 05:59:52 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2000,2001 SATO Kazumi 5 * 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: ite8181.c,v 1.25 2007/03/04 05:59:52 christos Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/kernel.h> 35 #include <sys/device.h> 36 #include <sys/systm.h> 37 #include <sys/boot_flag.h> 38 #include <sys/buf.h> 39 40 #include <uvm/uvm_extern.h> 41 42 #include <dev/wscons/wsconsio.h> 43 44 #include <machine/bootinfo.h> 45 #include <machine/bus.h> 46 #include <machine/autoconf.h> 47 #include <machine/config_hook.h> 48 #include <machine/platid.h> 49 #include <machine/platid_mask.h> 50 51 #include <hpcmips/dev/ite8181reg.h> 52 #include <hpcmips/dev/ite8181var.h> 53 #include "bivideo.h" 54 #if NBIVIDEO > 0 55 #include <dev/hpc/bivideovar.h> 56 #endif 57 #include <dev/hpc/hpccmapvar.h> 58 59 #define ITE8181DEBUG 60 #ifdef ITE8181DEBUG 61 #ifndef ITE8181DEBUG_CONF 62 #define ITE8181DEBUG_CONF 0 63 #endif 64 int ite8181_debug = ITE8181DEBUG_CONF; 65 #define DPRINTF(arg) if (ite8181_debug) printf arg 66 #define DPRINTFN(n, arg) if (ite8181_debug > (n)) printf arg 67 #define VPRINTF(arg) if (bootverbose || ite8181_debug) printf arg 68 #define VPRINTFN(n, arg) if (bootverbose || ite8181_debug > (n)) printf arg 69 #else 70 #define DPRINTF(arg) 71 #define DPRINTFN(n, arg) 72 #define VPRINTF(arg) if (bootverbose) printf arg 73 #define VPRINTFN(n, arg) if (bootverbose) printf arg 74 #endif 75 76 #ifndef ITE8181_LCD_CONTROL_ENABLE 77 int ite8181_lcd_control_disable = 1; 78 #else /* ITE8181_LCD_CONTROL_ENABLE */ 79 int ite8181_lcd_control_disable = 0; 80 #endif /* ITE8181_LCD_CONTROL_ENABLE */ 81 82 #define ITE8181_WINCE_CMAP 83 84 /* 85 * XXX: 86 * IBM WorkPad z50 power unit has too weak power. 87 * So we must wait too many times to access some device 88 * after LCD panel and BackLight on. 89 * Currently delay is not enough ??? FIXME 90 */ 91 #ifndef ITE8181_LCD_ON_SELF_DELAY 92 #define ITE8181_LCD_ON_SELF_DELAY 1000 93 #endif /* ITE8181_LCD_ON__SELF_DELAY */ 94 #ifndef ITE8181_LCD_ON_DELAY 95 #define ITE8181_LCD_ON_DELAY 2000 96 #endif /* ITE8181_LCD_ON_DELAY */ 97 int ite8181_lcd_on_self_delay = ITE8181_LCD_ON_SELF_DELAY; /* msec */ 98 int ite8181_lcd_on_delay = ITE8181_LCD_ON_DELAY; /* msec */ 99 100 #define MSEC 1000 101 /* 102 * function prototypes 103 */ 104 static void ite8181_config_write_4(bus_space_tag_t, bus_space_handle_t, 105 int, int); 106 static int ite8181_config_read_4(bus_space_tag_t, bus_space_handle_t, 107 int); 108 static void ite8181_gui_write_4(struct ite8181_softc *, int, int); 109 static int ite8181_gui_read_4(struct ite8181_softc *, int); 110 111 static void ite8181_gui_write_1(struct ite8181_softc *, int, int); 112 static int ite8181_gui_read_1(struct ite8181_softc *, int); 113 114 static void ite8181_graphics_write_1(struct ite8181_softc *, int, int); 115 static int ite8181_graphics_read_1(struct ite8181_softc *, int); 116 117 static void ite8181_ema_write_1(struct ite8181_softc *, int, int); 118 static int ite8181_ema_read_1(struct ite8181_softc *, int); 119 120 static void ite8181_power(int, void *); 121 static int ite8181_hardpower(void *, int, long, void *); 122 static int ite8181_fbinit(struct hpcfb_fbconf *); 123 static int ite8181_ioctl(void *, u_long, void *, int, struct lwp *); 124 static paddr_t ite8181_mmap(void *, off_t offset, int); 125 static void ite8181_erase_cursor(struct ite8181_softc *); 126 static int ite8181_lcd_power(struct ite8181_softc *, int); 127 128 static void ite8181_update_powerstate(struct ite8181_softc *, int); 129 void ite8181_init_backlight(struct ite8181_softc *, int); 130 void ite8181_init_brightness(struct ite8181_softc *, int); 131 void ite8181_init_contrast(struct ite8181_softc *, int); 132 void ite8181_set_brightness(struct ite8181_softc *, int); 133 void ite8181_set_contrast(struct ite8181_softc *, int); 134 135 /* 136 * static variables 137 */ 138 struct hpcfb_accessops ite8181_ha = { 139 ite8181_ioctl, ite8181_mmap 140 }; 141 142 inline int 143 ite8181_config_read_4(bus_space_tag_t iot, bus_space_handle_t ioh, 144 int byteoffset) 145 { 146 147 return (bus_space_read_4(iot, ioh, ITE8181_CONF_OFFSET + byteoffset)); 148 } 149 150 inline void 151 ite8181_config_write_4(bus_space_tag_t iot, bus_space_handle_t ioh, 152 int byteoffset, int data) 153 { 154 155 bus_space_write_4(iot, ioh, ITE8181_CONF_OFFSET + byteoffset, data); 156 } 157 158 inline int 159 ite8181_gui_read_4(struct ite8181_softc *sc, int byteoffset) 160 { 161 162 return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 163 sc->sc_gba + byteoffset)); 164 } 165 166 inline void 167 ite8181_gui_write_4(struct ite8181_softc *sc, int byteoffset, int data) 168 { 169 170 bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_gba + byteoffset, 171 data); 172 } 173 174 inline int 175 ite8181_gui_read_1(struct ite8181_softc *sc, int byteoffset) 176 { 177 178 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, 179 sc->sc_gba + byteoffset)); 180 } 181 182 inline void 183 ite8181_gui_write_1(struct ite8181_softc *sc, int byteoffset, int data) 184 { 185 186 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_gba + byteoffset, 187 data); 188 } 189 190 inline int 191 ite8181_graphics_read_1(struct ite8181_softc *sc, int byteoffset) 192 { 193 194 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, 195 sc->sc_sba + byteoffset)); 196 } 197 198 inline void 199 ite8181_graphics_write_1(struct ite8181_softc *sc, int byteoffset, int data) 200 { 201 202 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_sba + byteoffset, 203 data); 204 } 205 206 inline int 207 ite8181_ema_read_1(struct ite8181_softc *sc, int byteoffset) 208 { 209 210 ite8181_graphics_write_1(sc, ITE8181_EMA_EXAX, byteoffset); 211 return (ite8181_graphics_read_1(sc, ITE8181_EMA_EXADATA)); 212 } 213 214 inline void 215 ite8181_ema_write_1(struct ite8181_softc *sc, int byteoffset, int data) 216 { 217 218 ite8181_graphics_write_1(sc, ITE8181_EMA_EXAX, byteoffset); 219 ite8181_graphics_write_1(sc, ITE8181_EMA_EXADATA, data); 220 } 221 222 int 223 ite8181_probe(bus_space_tag_t iot, bus_space_handle_t ioh) 224 { 225 unsigned long regval; 226 227 #if NBIVIDEO > 0 228 if (bivideo_dont_attach) /* some video driver already attached */ 229 return (0); 230 #endif /* NBIVIDEO > 0 */ 231 232 regval = ite8181_config_read_4(iot, ioh, ITE8181_ID); 233 VPRINTF(("ite8181_probe: vendor id=%04lx product id=%04lx\n", 234 regval & 0xffff, (regval >> 16) & 0xffff)); 235 if (regval != ((ITE8181_PRODUCT_ID << 16) | ITE8181_VENDER_ID)) 236 return (0); 237 238 return (1); 239 } 240 241 void 242 ite8181_attach(struct ite8181_softc *sc) 243 { 244 unsigned long regval; 245 struct hpcfb_attach_args ha; 246 int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1; 247 248 printf(": "); 249 if (ite8181_fbinit(&sc->sc_fbconf) != 0) { 250 /* just return so that hpcfb will not be attached */ 251 return; 252 } 253 254 regval = ite8181_config_read_4(sc->sc_iot, sc->sc_ioh, ITE8181_CLASS); 255 printf("ITE8181 Rev.%02lx", regval & ITE8181_REV_MASK); 256 if (console) { 257 printf(", console"); 258 } 259 printf("\n"); 260 printf("%s: framebuffer address: 0x%08lx\n", 261 sc->sc_dev.dv_xname, (u_long)bootinfo->fb_addr); 262 if (ite8181_lcd_control_disable) 263 printf("%s: ite8181 lcd control is DISABLED.\n", 264 sc->sc_dev.dv_xname); 265 266 /* set base offsets */ 267 sc->sc_mba = ite8181_config_read_4(sc->sc_iot, sc->sc_ioh, ITE8181_MBA); 268 DPRINTFN(1, ("ite8181: Memory base offset %08x\n", sc->sc_mba)); 269 sc->sc_gba = ite8181_config_read_4(sc->sc_iot, sc->sc_ioh, ITE8181_GBA); 270 DPRINTFN(1, ("ite8181: GUI base offset %08x\n", sc->sc_gba)); 271 sc->sc_sba = ite8181_config_read_4(sc->sc_iot, sc->sc_ioh, ITE8181_SBA); 272 DPRINTFN(1, ("ite8181: Graphics base offset %08x\n", sc->sc_sba)); 273 274 /* assume lcd is on */ 275 sc->sc_lcd = 1; 276 /* erase wince cursor */ 277 ite8181_erase_cursor(sc); 278 279 /* Add a power hook to power saving */ 280 sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, 281 ite8181_power, sc); 282 if (sc->sc_powerhook == NULL) 283 printf("%s: WARNING: unable to establish power hook\n", 284 sc->sc_dev.dv_xname); 285 286 /* Add a hard power hook to power saving */ 287 sc->sc_hardpowerhook = config_hook(CONFIG_HOOK_PMEVENT, 288 CONFIG_HOOK_PMEVENT_HARDPOWER, 289 CONFIG_HOOK_SHARE, 290 ite8181_hardpower, sc); 291 if (sc->sc_hardpowerhook == NULL) 292 printf("%s: WARNING: unable to establish hard power hook\n", 293 sc->sc_dev.dv_xname); 294 295 /* initialize backlight brightness and lcd contrast */ 296 sc->sc_lcd_inited = 0; 297 ite8181_init_brightness(sc, 1); 298 ite8181_init_contrast(sc, 1); 299 ite8181_init_backlight(sc, 1); 300 301 if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) { 302 panic("ite8181_attach: can't init fb console"); 303 } 304 305 ha.ha_console = console; 306 ha.ha_accessops = &ite8181_ha; 307 ha.ha_accessctx = sc; 308 ha.ha_curfbconf = 0; 309 ha.ha_nfbconf = 1; 310 ha.ha_fbconflist = &sc->sc_fbconf; 311 ha.ha_curdspconf = 0; 312 ha.ha_ndspconf = 1; 313 ha.ha_dspconflist = &sc->sc_dspconf; 314 315 config_found(&sc->sc_dev, &ha, hpcfbprint); 316 317 #if NBIVIDEO > 0 318 /* 319 * bivideo is no longer need 320 */ 321 bivideo_dont_attach = 1; 322 #endif /* NBIVIDEO > 0 */ 323 } 324 325 int 326 ite8181_lcd_power(struct ite8181_softc *sc, int on) 327 { 328 int lcd_p; 329 int lcd_s; 330 int lcd_seq; 331 int loop = 10; 332 333 if (ite8181_lcd_control_disable) { 334 VPRINTF(("ite8171_lcd_control_disable!: %s\n", on?"on":"off")); 335 return 0; 336 } 337 338 if (sc->sc_lcd != on) { 339 ite8181_ema_write_1(sc, ITE8181_EMA_ENABLEEMA, 340 ITE8181_EMA_ENABLEPASS); 341 lcd_p = ite8181_ema_read_1(sc, ITE8181_EMA_LCDPOWER); 342 lcd_s = ite8181_ema_read_1(sc, ITE8181_EMA_LCDPOWERSTAT); 343 lcd_seq = ite8181_ema_read_1(sc, ITE8181_EMA_LCDPOWERSEQ); 344 DPRINTFN(1,("ite8181_lcd_power(%d)< p=%x, s=%x, seq=%x\n", 345 on, 346 lcd_p, lcd_s, lcd_seq)); 347 if (on) { 348 sc->sc_lcd = 1; 349 lcd_seq |= (ITE8181_PUP0|ITE8181_PUP1|ITE8181_PUP2); 350 ite8181_ema_write_1(sc, ITE8181_EMA_LCDPOWERSEQ, 351 lcd_seq); 352 lcd_p &= ~ITE8181_LCDSTANDBY; 353 ite8181_ema_write_1(sc, ITE8181_EMA_LCDPOWER, lcd_p); 354 /* 355 * XXX: 356 * IBM WorkPad z50 power unit has too weak power. 357 * So we must wait too many times to access self device 358 * after LCD panel and BackLight on. 359 * Currently delay is not enough ??? FIXME 360 */ 361 delay(ite8181_lcd_on_self_delay*MSEC); 362 while (loop--) { 363 lcd_p = ite8181_ema_read_1(sc, 364 ITE8181_EMA_LCDPOWER); 365 lcd_s = ite8181_ema_read_1(sc, 366 ITE8181_EMA_LCDPOWERSTAT); 367 lcd_seq = ite8181_ema_read_1(sc, 368 ITE8181_EMA_LCDPOWERSEQ); 369 DPRINTFN(1,("ite8181_lcd_power(%d)%d| p=%x," 370 " s=%x, seq=%x\n", on, loop, lcd_p, lcd_s, 371 lcd_seq)); 372 /* 373 * XXX the states which are not described 374 * XXX in manual. 375 */ 376 if (!(lcd_s&ITE8181_LCDPSTANDBY) && 377 !(lcd_s&ITE8181_LCDPUP) && 378 (lcd_s&ITE8181_LCDPON)) 379 break; 380 delay(100); 381 } 382 lcd_s |= ITE8181_PPTOBEON; 383 ite8181_ema_write_1(sc, ITE8181_EMA_LCDPOWERSTAT, 384 lcd_s); 385 } else { 386 sc->sc_lcd = 0; 387 lcd_p |= ITE8181_LCDSTANDBY; 388 ite8181_ema_write_1(sc, ITE8181_EMA_LCDPOWER, lcd_p); 389 while (loop--) { 390 lcd_p = ite8181_ema_read_1(sc, 391 ITE8181_EMA_LCDPOWER); 392 lcd_s = ite8181_ema_read_1(sc, 393 ITE8181_EMA_LCDPOWERSTAT); 394 lcd_seq = ite8181_ema_read_1(sc, 395 ITE8181_EMA_LCDPOWERSEQ); 396 DPRINTFN(1,("ite8181_lcd_power(%d)%d| p=%x," 397 " s=%x, seq=%x\n", on, loop, lcd_p, lcd_s, 398 lcd_seq)); 399 /* 400 * XXX the states which are not described 401 * XXX in manual. 402 */ 403 if ((lcd_s&ITE8181_LCDPSTANDBY) && 404 !(lcd_s&ITE8181_LCDPDOWN) && 405 !(lcd_s&ITE8181_LCDPON)) 406 break; 407 delay(100); 408 } 409 lcd_s &= ~ITE8181_PPTOBEON; 410 ite8181_ema_write_1(sc, ITE8181_EMA_LCDPOWERSTAT, 411 lcd_s); 412 } 413 DPRINTFN(1,("ite8181_lcd_power(%d)> p=%x, s=%x, seq=%x\n", 414 on, 415 ite8181_ema_read_1(sc, ITE8181_EMA_LCDPOWER), 416 ite8181_ema_read_1(sc, ITE8181_EMA_LCDPOWERSTAT), 417 ite8181_ema_read_1(sc, ITE8181_EMA_LCDPOWERSEQ))); 418 ite8181_ema_write_1(sc, ITE8181_EMA_ENABLEEMA, 419 ITE8181_EMA_DISABLEPASS); 420 } 421 return 0; 422 } 423 424 static void 425 ite8181_erase_cursor(struct ite8181_softc *sc) 426 { 427 ite8181_gui_write_1(sc, ITE8181_GUI_C1C, 0); /* Cursor 1 Control Reg. */ 428 /* other ? */ 429 } 430 431 static void 432 ite8181_update_powerstate(struct ite8181_softc *sc, int updates) 433 { 434 if (updates & PWRSTAT_LCD) 435 config_hook_call(CONFIG_HOOK_POWERCONTROL, 436 CONFIG_HOOK_POWERCONTROL_LCD, 437 (void*)!(sc->sc_powerstate & 438 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND))); 439 440 if (updates & PWRSTAT_BACKLIGHT) 441 config_hook_call(CONFIG_HOOK_POWERCONTROL, 442 CONFIG_HOOK_POWERCONTROL_LCDLIGHT, 443 (void*)(!(sc->sc_powerstate & 444 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) && 445 (sc->sc_powerstate & PWRSTAT_BACKLIGHT))); 446 } 447 448 static void 449 ite8181_power(int why, void *arg) 450 { 451 struct ite8181_softc *sc = arg; 452 453 switch (why) { 454 case PWR_STANDBY: 455 sc->sc_powerstate |= PWRSTAT_SUSPEND; 456 ite8181_update_powerstate(sc, PWRSTAT_ALL); 457 break; 458 case PWR_SUSPEND: 459 sc->sc_powerstate |= PWRSTAT_SUSPEND; 460 ite8181_update_powerstate(sc, PWRSTAT_ALL); 461 break; 462 case PWR_RESUME: 463 sc->sc_powerstate &= ~PWRSTAT_SUSPEND; 464 ite8181_update_powerstate(sc, PWRSTAT_ALL); 465 break; 466 } 467 } 468 469 static int 470 ite8181_hardpower(void *ctx, int type, long id, void *msg) 471 { 472 struct ite8181_softc *sc = ctx; 473 int why = (int)msg; 474 475 switch (why) { 476 case PWR_STANDBY: 477 /* ite8181_lcd_power(sc, 0); */ 478 delay(MSEC); 479 break; 480 case PWR_SUSPEND: 481 ite8181_lcd_power(sc, 0); 482 delay(MSEC); 483 break; 484 case PWR_RESUME: 485 delay(MSEC); 486 ite8181_lcd_power(sc, 1); 487 /* 488 * XXX: 489 * IBM WorkPad z50 power unit has too weak power. 490 * So we must wait too many times to access other devices 491 * after LCD panel and BackLight on. 492 */ 493 delay(ite8181_lcd_on_delay*MSEC); 494 break; 495 } 496 497 /* 498 * you should wait until the 499 * power state transit sequence will end. 500 */ 501 502 return (0); 503 } 504 505 static int 506 ite8181_fbinit(struct hpcfb_fbconf *fb) 507 { 508 509 /* 510 * get fb settings from bootinfo 511 */ 512 if (bootinfo == NULL || 513 bootinfo->fb_addr == 0 || 514 bootinfo->fb_line_bytes == 0 || 515 bootinfo->fb_width == 0 || 516 bootinfo->fb_height == 0) { 517 printf("no frame buffer information.\n"); 518 return (-1); 519 } 520 521 /* zero fill */ 522 bzero(fb, sizeof(*fb)); 523 524 fb->hf_conf_index = 0; /* configuration index */ 525 fb->hf_nconfs = 1; /* how many configurations */ 526 strcpy(fb->hf_name, "built-in video"); 527 /* frame buffer name */ 528 strcpy(fb->hf_conf_name, "default"); 529 /* configuration name */ 530 fb->hf_height = bootinfo->fb_height; 531 fb->hf_width = bootinfo->fb_width; 532 fb->hf_baseaddr = (u_long)bootinfo->fb_addr; 533 fb->hf_offset = (u_long)bootinfo->fb_addr - 534 mips_ptob(mips_btop(bootinfo->fb_addr)); 535 /* frame buffer start offset */ 536 fb->hf_bytes_per_line = bootinfo->fb_line_bytes; 537 fb->hf_nplanes = 1; 538 fb->hf_bytes_per_plane = bootinfo->fb_height * 539 bootinfo->fb_line_bytes; 540 541 fb->hf_access_flags |= HPCFB_ACCESS_BYTE; 542 fb->hf_access_flags |= HPCFB_ACCESS_WORD; 543 fb->hf_access_flags |= HPCFB_ACCESS_DWORD; 544 545 switch (bootinfo->fb_type) { 546 /* 547 * gray scale 548 */ 549 case BIFB_D2_M2L_3: 550 case BIFB_D2_M2L_3x2: 551 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 552 /* fall through */ 553 case BIFB_D2_M2L_0: 554 case BIFB_D2_M2L_0x2: 555 fb->hf_class = HPCFB_CLASS_GRAYSCALE; 556 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 557 fb->hf_pack_width = 8; 558 fb->hf_pixels_per_pack = 4; 559 fb->hf_pixel_width = 2; 560 fb->hf_class_data_length = sizeof(struct hf_gray_tag); 561 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */ 562 break; 563 564 case BIFB_D4_M2L_F: 565 case BIFB_D4_M2L_Fx2: 566 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 567 /* fall through */ 568 case BIFB_D4_M2L_0: 569 case BIFB_D4_M2L_0x2: 570 fb->hf_class = HPCFB_CLASS_GRAYSCALE; 571 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 572 fb->hf_pack_width = 8; 573 fb->hf_pixels_per_pack = 2; 574 fb->hf_pixel_width = 4; 575 fb->hf_class_data_length = sizeof(struct hf_gray_tag); 576 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */ 577 break; 578 579 /* 580 * indexed color 581 */ 582 case BIFB_D8_FF: 583 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 584 /* fall through */ 585 case BIFB_D8_00: 586 fb->hf_class = HPCFB_CLASS_INDEXCOLOR; 587 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 588 fb->hf_pack_width = 8; 589 fb->hf_pixels_per_pack = 1; 590 fb->hf_pixel_width = 8; 591 fb->hf_class_data_length = sizeof(struct hf_indexed_tag); 592 fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */ 593 break; 594 595 /* 596 * RGB color 597 */ 598 case BIFB_D16_FFFF: 599 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 600 /* fall through */ 601 case BIFB_D16_0000: 602 fb->hf_class = HPCFB_CLASS_RGBCOLOR; 603 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 604 fb->hf_order_flags = HPCFB_REVORDER_BYTE; 605 fb->hf_pack_width = 16; 606 fb->hf_pixels_per_pack = 1; 607 fb->hf_pixel_width = 16; 608 609 fb->hf_class_data_length = sizeof(struct hf_rgb_tag); 610 fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */ 611 612 fb->hf_u.hf_rgb.hf_red_width = 5; 613 fb->hf_u.hf_rgb.hf_red_shift = 11; 614 fb->hf_u.hf_rgb.hf_green_width = 6; 615 fb->hf_u.hf_rgb.hf_green_shift = 5; 616 fb->hf_u.hf_rgb.hf_blue_width = 5; 617 fb->hf_u.hf_rgb.hf_blue_shift = 0; 618 fb->hf_u.hf_rgb.hf_alpha_width = 0; 619 fb->hf_u.hf_rgb.hf_alpha_shift = 0; 620 break; 621 622 default: 623 printf("unknown type (=%d).\n", bootinfo->fb_type); 624 return (-1); 625 break; 626 } 627 628 return (0); /* no error */ 629 } 630 631 int 632 ite8181_ioctl(v, cmd, data, flag, l) 633 void *v; 634 u_long cmd; 635 void *data; 636 int flag; 637 struct lwp *l; 638 { 639 struct ite8181_softc *sc = (struct ite8181_softc *)v; 640 struct hpcfb_fbconf *fbconf; 641 struct hpcfb_dspconf *dspconf; 642 struct wsdisplay_cmap *cmap; 643 struct wsdisplay_param *dispparam; 644 int error; 645 646 switch (cmd) { 647 case WSDISPLAYIO_GETCMAP: 648 cmap = (struct wsdisplay_cmap *)data; 649 650 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR || 651 sc->sc_fbconf.hf_pack_width != 8 || 652 256 <= cmap->index || 653 256 - cmap->index < cmap->count) 654 return (EINVAL); 655 656 #ifdef ITE8181_WINCE_CMAP 657 error = copyout(&bivideo_cmap_r[cmap->index], cmap->red, 658 cmap->count); 659 if (error) 660 return error; 661 error = copyout(&bivideo_cmap_g[cmap->index], cmap->green, 662 cmap->count); 663 if (error) 664 return error; 665 error = copyout(&bivideo_cmap_b[cmap->index], cmap->blue, 666 cmap->count); 667 return error; 668 #else /* ITE8181_WINCE_CMAP */ 669 return EINVAL; 670 #endif /* ITE8181_WINCE_CMAP */ 671 672 case WSDISPLAYIO_PUTCMAP: 673 /* 674 * This driver can't set color map. 675 */ 676 return (EINVAL); 677 678 case WSDISPLAYIO_SVIDEO: 679 if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) 680 sc->sc_powerstate |= PWRSTAT_VIDEOOFF; 681 else 682 sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF; 683 ite8181_update_powerstate(sc, PWRSTAT_ALL); 684 return 0; 685 686 case WSDISPLAYIO_GVIDEO: 687 *(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ? 688 WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON; 689 return 0; 690 691 692 case WSDISPLAYIO_GETPARAM: 693 dispparam = (struct wsdisplay_param*)data; 694 switch (dispparam->param) { 695 case WSDISPLAYIO_PARAM_BACKLIGHT: 696 VPRINTF(("ite8181_ioctl: GET:BACKLIGHT\n")); 697 ite8181_init_brightness(sc, 0); 698 ite8181_init_backlight(sc, 0); 699 VPRINTF(("ite8181_ioctl: GET:(real)BACKLIGHT %d\n", 700 (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0)); 701 dispparam->min = 0; 702 dispparam->max = 1; 703 if (sc->sc_max_brightness > 0) 704 dispparam->curval = 705 sc->sc_brightness > 0 ? 1: 0; 706 else 707 dispparam->curval = 708 (sc->sc_powerstate & PWRSTAT_BACKLIGHT) 709 ? 1: 0; 710 VPRINTF(("ite8181_ioctl: GET:BACKLIGHT:%d(%s)\n", 711 dispparam->curval, 712 sc->sc_max_brightness > 0? "brightness": "light")); 713 return 0; 714 break; 715 case WSDISPLAYIO_PARAM_CONTRAST: 716 VPRINTF(("ite8181_ioctl: GET:CONTRAST\n")); 717 ite8181_init_contrast(sc, 0); 718 if (sc->sc_max_contrast > 0) { 719 dispparam->min = 0; 720 dispparam->max = sc->sc_max_contrast; 721 dispparam->curval = sc->sc_contrast; 722 VPRINTF(("ite8181_ioctl: GET:CONTRAST max=%d," 723 " current=%d\n", sc->sc_max_contrast, 724 sc->sc_contrast)); 725 return 0; 726 } else { 727 VPRINTF(("ite8181_ioctl: " 728 "GET:CONTRAST EINVAL\n")); 729 return (EINVAL); 730 } 731 break; 732 case WSDISPLAYIO_PARAM_BRIGHTNESS: 733 VPRINTF(("ite8181_ioctl: GET:BRIGHTNESS\n")); 734 ite8181_init_brightness(sc, 0); 735 if (sc->sc_max_brightness > 0) { 736 dispparam->min = 0; 737 dispparam->max = sc->sc_max_brightness; 738 dispparam->curval = sc->sc_brightness; 739 VPRINTF(("ite8181_ioctl: GET:BRIGHTNESS" 740 " max=%d, current=%d\n", 741 sc->sc_max_brightness, sc->sc_brightness)); 742 return 0; 743 } else { 744 VPRINTF(("ite8181_ioctl: GET:BRIGHTNESS" 745 " EINVAL\n")); 746 return (EINVAL); 747 } 748 return (EINVAL); 749 default: 750 return (EINVAL); 751 } 752 return (0); 753 754 case WSDISPLAYIO_SETPARAM: 755 dispparam = (struct wsdisplay_param*)data; 756 switch (dispparam->param) { 757 case WSDISPLAYIO_PARAM_BACKLIGHT: 758 VPRINTF(("ite8181_ioctl: SET:BACKLIGHT\n")); 759 if (dispparam->curval < 0 || 760 1 < dispparam->curval) 761 return (EINVAL); 762 ite8181_init_brightness(sc, 0); 763 VPRINTF(("ite8181_ioctl: SET:max brightness=%d\n", 764 sc->sc_max_brightness)); 765 if (sc->sc_max_brightness > 0) { /* dimmer */ 766 if (dispparam->curval == 0){ 767 sc->sc_brightness_save = 768 sc->sc_brightness; 769 ite8181_set_brightness(sc, 0);/* min */ 770 } else { 771 if (sc->sc_brightness_save == 0) 772 sc->sc_brightness_save = 773 sc->sc_max_brightness; 774 ite8181_set_brightness(sc, 775 sc->sc_brightness_save); 776 } 777 VPRINTF(("ite8181_ioctl: SET:BACKLIGHT:" 778 "brightness=%d\n", sc->sc_brightness)); 779 } else { /* off */ 780 if (dispparam->curval == 0) 781 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 782 else 783 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 784 VPRINTF(("ite8181_ioctl: SET:BACKLIGHT:" 785 "powerstate %d\n", 786 (sc->sc_powerstate & PWRSTAT_BACKLIGHT) 787 ? 1 : 0)); 788 ite8181_update_powerstate(sc, 789 PWRSTAT_BACKLIGHT); 790 VPRINTF(("ite8181_ioctl: SET:BACKLIGHT:%d\n", 791 (sc->sc_powerstate & PWRSTAT_BACKLIGHT) 792 ? 1 : 0)); 793 } 794 return 0; 795 break; 796 case WSDISPLAYIO_PARAM_CONTRAST: 797 VPRINTF(("ite8181_ioctl: SET:CONTRAST\n")); 798 ite8181_init_contrast(sc, 0); 799 if (dispparam->curval < 0 || 800 sc->sc_max_contrast < dispparam->curval) 801 return (EINVAL); 802 if (sc->sc_max_contrast > 0) { 803 int org = sc->sc_contrast; 804 ite8181_set_contrast(sc, dispparam->curval); 805 VPRINTF(("ite8181_ioctl: SET:CONTRAST" 806 " org=%d, current=%d\n", org, 807 sc->sc_contrast)); 808 return 0; 809 } else { 810 VPRINTF(("ite8181_ioctl: SET:CONTRAST" 811 " EINVAL\n")); 812 return (EINVAL); 813 } 814 break; 815 case WSDISPLAYIO_PARAM_BRIGHTNESS: 816 VPRINTF(("ite8181_ioctl: SET:BRIGHTNESS\n")); 817 ite8181_init_brightness(sc, 0); 818 if (dispparam->curval < 0 || 819 sc->sc_max_brightness < dispparam->curval) 820 return (EINVAL); 821 if (sc->sc_max_brightness > 0) { 822 int org = sc->sc_brightness; 823 ite8181_set_brightness(sc, dispparam->curval); 824 VPRINTF(("ite8181_ioctl: SET:BRIGHTNESS" 825 " org=%d, current=%d\n", org, 826 sc->sc_brightness)); 827 return 0; 828 } else { 829 VPRINTF(("ite8181_ioctl: SET:BRIGHTNESS" 830 " EINVAL\n")); 831 return (EINVAL); 832 } 833 break; 834 default: 835 return (EINVAL); 836 } 837 return (0); 838 839 case HPCFBIO_GCONF: 840 fbconf = (struct hpcfb_fbconf *)data; 841 if (fbconf->hf_conf_index != 0 && 842 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 843 return (EINVAL); 844 } 845 *fbconf = sc->sc_fbconf; /* structure assignment */ 846 return (0); 847 case HPCFBIO_SCONF: 848 fbconf = (struct hpcfb_fbconf *)data; 849 if (fbconf->hf_conf_index != 0 && 850 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 851 return (EINVAL); 852 } 853 /* 854 * nothing to do because we have only one configuration 855 */ 856 return (0); 857 case HPCFBIO_GDSPCONF: 858 dspconf = (struct hpcfb_dspconf *)data; 859 if ((dspconf->hd_unit_index != 0 && 860 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 861 (dspconf->hd_conf_index != 0 && 862 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 863 return (EINVAL); 864 } 865 *dspconf = sc->sc_dspconf; /* structure assignment */ 866 return (0); 867 case HPCFBIO_SDSPCONF: 868 dspconf = (struct hpcfb_dspconf *)data; 869 if ((dspconf->hd_unit_index != 0 && 870 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 871 (dspconf->hd_conf_index != 0 && 872 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 873 return (EINVAL); 874 } 875 /* 876 * nothing to do 877 * because we have only one unit and one configuration 878 */ 879 return (0); 880 case HPCFBIO_GOP: 881 case HPCFBIO_SOP: 882 /* 883 * curently not implemented... 884 */ 885 return (EINVAL); 886 } 887 888 return (EPASSTHROUGH); 889 } 890 891 paddr_t 892 ite8181_mmap(void *ctx, off_t offset, int prot) 893 { 894 struct ite8181_softc *sc = (struct ite8181_softc *)ctx; 895 896 if (offset < 0 || 897 (sc->sc_fbconf.hf_bytes_per_plane + 898 sc->sc_fbconf.hf_offset) < offset) 899 return -1; 900 901 return mips_btop((u_long)bootinfo->fb_addr + offset); 902 } 903 904 905 void 906 ite8181_init_backlight(struct ite8181_softc *sc, int inattach) 907 { 908 int val = -1; 909 910 if (sc->sc_lcd_inited&BACKLIGHT_INITED) 911 return; 912 913 if (config_hook_call(CONFIG_HOOK_GET, 914 CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) { 915 /* we can get real light state */ 916 VPRINTF(("ite8181_init_backlight: real backlight=%d\n", val)); 917 if (val == 0) 918 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 919 else 920 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 921 sc->sc_lcd_inited |= BACKLIGHT_INITED; 922 } else if (inattach) { 923 /* 924 we cannot get real light state in attach time 925 because light device not yet attached. 926 we will retry in !inattach. 927 temporary assume light is on. 928 */ 929 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 930 } else { 931 /* we cannot get real light state, so work by myself state */ 932 sc->sc_lcd_inited |= BACKLIGHT_INITED; 933 } 934 } 935 936 void 937 ite8181_init_brightness(struct ite8181_softc *sc, int inattach) 938 { 939 int val = -1; 940 941 if (sc->sc_lcd_inited&BRIGHTNESS_INITED) 942 return; 943 944 VPRINTF(("ite8181_init_brightness\n")); 945 if (config_hook_call(CONFIG_HOOK_GET, 946 CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) { 947 /* we can get real brightness max */ 948 VPRINTF(("ite8181_init_brightness: real brightness max=%d\n", 949 val)); 950 sc->sc_max_brightness = val; 951 val = -1; 952 if (config_hook_call(CONFIG_HOOK_GET, 953 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 954 /* we can get real brightness */ 955 VPRINTF(("ite8181_init_brightness:" 956 " real brightness=%d\n", val)); 957 sc->sc_brightness_save = sc->sc_brightness = val; 958 } else { 959 sc->sc_brightness_save = 960 sc->sc_brightness = sc->sc_max_brightness; 961 } 962 sc->sc_lcd_inited |= BRIGHTNESS_INITED; 963 } else if (inattach) { 964 /* 965 we cannot get real brightness in attach time 966 because brightness device not yet attached. 967 we will retry in !inattach. 968 */ 969 sc->sc_max_brightness = -1; 970 sc->sc_brightness = -1; 971 sc->sc_brightness_save = -1; 972 } else { 973 /* we cannot get real brightness */ 974 sc->sc_lcd_inited |= BRIGHTNESS_INITED; 975 } 976 977 return; 978 } 979 980 void 981 ite8181_init_contrast(struct ite8181_softc *sc, int inattach) 982 { 983 int val = -1; 984 985 if (sc->sc_lcd_inited&CONTRAST_INITED) 986 return; 987 988 VPRINTF(("ite8181_init_contrast\n")); 989 if (config_hook_call(CONFIG_HOOK_GET, 990 CONFIG_HOOK_CONTRAST_MAX, &val) != -1) { 991 /* we can get real contrast max */ 992 VPRINTF(("ite8181_init_contrast: real contrast max=%d\n", val)); 993 sc->sc_max_contrast = val; 994 val = -1; 995 if (config_hook_call(CONFIG_HOOK_GET, 996 CONFIG_HOOK_CONTRAST, &val) != -1) { 997 /* we can get real contrast */ 998 VPRINTF(("ite8181_init_contrast: real contrast=%d\n", 999 val)); 1000 sc->sc_contrast = val; 1001 } else { 1002 sc->sc_contrast = sc->sc_max_contrast; 1003 } 1004 sc->sc_lcd_inited |= CONTRAST_INITED; 1005 } else if (inattach) { 1006 /* 1007 we cannot get real contrast in attach time 1008 because contrast device not yet attached. 1009 we will retry in !inattach. 1010 */ 1011 sc->sc_max_contrast = -1; 1012 sc->sc_contrast = -1; 1013 } else { 1014 /* we cannot get real contrast */ 1015 sc->sc_lcd_inited |= CONTRAST_INITED; 1016 } 1017 1018 return; 1019 } 1020 1021 1022 void 1023 ite8181_set_brightness(struct ite8181_softc *sc, int val) 1024 { 1025 1026 sc->sc_brightness = val; 1027 1028 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 1029 if (config_hook_call(CONFIG_HOOK_GET, 1030 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 1031 sc->sc_brightness = val; 1032 } 1033 } 1034 1035 void 1036 ite8181_set_contrast(struct ite8181_softc *sc, int val) 1037 { 1038 1039 sc->sc_contrast = val; 1040 1041 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 1042 if (config_hook_call(CONFIG_HOOK_GET, 1043 CONFIG_HOOK_CONTRAST, &val) != -1) { 1044 sc->sc_contrast = val; 1045 } 1046 } 1047