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