1 /* $NetBSD: mq200.c,v 1.11 2001/03/09 08:54:18 sato Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Takemura Shin 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 #include <sys/param.h> 33 #include <sys/kernel.h> 34 #include <sys/device.h> 35 #include <sys/systm.h> 36 #include <sys/reboot.h> 37 38 #include <uvm/uvm_extern.h> 39 40 #include <dev/wscons/wsconsio.h> 41 42 #include <machine/bootinfo.h> 43 #include <machine/bus.h> 44 #include <machine/autoconf.h> 45 #include <machine/config_hook.h> 46 #include <machine/platid.h> 47 #include <machine/platid_mask.h> 48 49 #include <hpcmips/dev/mq200reg.h> 50 #include <hpcmips/dev/mq200var.h> 51 #include "bivideo.h" 52 #if NBIVIDEO > 0 53 #include <dev/hpc/bivideovar.h> 54 #endif 55 56 #define MQ200DEBUG 57 #ifdef MQ200DEBUG 58 #ifndef MQ200DEBUG_CONF 59 #define MQ200DEBUG_CONF 0 60 #endif 61 int mq200_debug = MQ200DEBUG_CONF; 62 #define DPRINTF(arg) do { if (mq200_debug) printf arg; } while(0); 63 #define DPRINTFN(n, arg) do { if (mq200_debug > (n)) printf arg; } while (0); 64 #define VPRINTF(arg) do { if (bootverbose || mq200_debug) printf arg; } while(0); 65 #define VPRINTFN(n, arg) do { if (bootverbose || mq200_debug > (n)) printf arg; } while (0); 66 #else 67 #define DPRINTF(arg) do { } while (0); 68 #define DPRINTFN(n, arg) do { } while (0); 69 #define VPRINTF(arg) do { if (bootverbose) printf arg; } while(0); 70 #define VPRINTFN(n, arg) do { if (bootverbose) printf arg; } while (0); 71 #endif 72 73 /* 74 * function prototypes 75 */ 76 static void mq200_power __P((int, void *)); 77 static int mq200_hardpower __P((void *, int, long, void *)); 78 static int mq200_fbinit __P((struct hpcfb_fbconf *)); 79 static int mq200_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 80 static paddr_t mq200_mmap __P((void *, off_t offset, int)); 81 static void mq200_update_powerstate __P((struct mq200_softc *, int)); 82 void mq200_get_backlight __P((struct mq200_softc *)); 83 void mq200_init_brightness __P((struct mq200_softc *)); 84 void mq200_init_contrast __P((struct mq200_softc *)); 85 void mq200_set_brightness __P((struct mq200_softc *, int)); 86 void mq200_set_contrast __P((struct mq200_softc *, int)); 87 88 /* 89 * static variables 90 */ 91 struct hpcfb_accessops mq200_ha = { 92 mq200_ioctl, mq200_mmap 93 }; 94 95 int 96 mq200_probe(iot, ioh) 97 bus_space_tag_t iot; 98 bus_space_handle_t ioh; 99 { 100 unsigned long regval; 101 102 #if NBIVIDEO > 0 103 if (bivideo_dont_attach) /* some video driver already attached */ 104 return (0); 105 #endif /* NBIVIDEO > 0 */ 106 107 regval = bus_space_read_4(iot, ioh, MQ200_PC00R); 108 VPRINTF(("mq200 probe: vendor id=%04lx product id=%04lx\n", 109 regval & 0xffff, (regval >> 16) & 0xffff)); 110 if (regval != ((MQ200_PRODUCT_ID << 16) | MQ200_VENDOR_ID)) 111 return (0); 112 113 return (1); 114 } 115 116 void 117 mq200_attach(sc) 118 struct mq200_softc *sc; 119 { 120 unsigned long regval; 121 struct hpcfb_attach_args ha; 122 int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1; 123 124 printf(": "); 125 if (mq200_fbinit(&sc->sc_fbconf) != 0) { 126 /* just return so that hpcfb will not be attached */ 127 return; 128 } 129 130 sc->sc_fbconf.hf_baseaddr = (u_long)bootinfo->fb_addr; 131 sc->sc_fbconf.hf_offset = (u_long)sc->sc_fbconf.hf_baseaddr - 132 MIPS_PHYS_TO_KSEG1(mips_ptob(mips_btop(sc->sc_baseaddr))); 133 DPRINTF(("hf_baseaddr=%lx\n", sc->sc_fbconf.hf_baseaddr)); 134 DPRINTF(("hf_offset=%lx\n", sc->sc_fbconf.hf_offset)); 135 136 regval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MQ200_PC08R); 137 printf("MQ200 Rev.%02lx video controller", regval & 0xff); 138 if (console) { 139 printf(", console"); 140 } 141 printf("\n"); 142 printf("%s: framebuffer address: 0x%08lx\n", 143 sc->sc_dev.dv_xname, (u_long)bootinfo->fb_addr); 144 145 /* Add a power hook to power saving */ 146 sc->sc_mq200pwstate = MQ200_POWERSTATE_D0; 147 sc->sc_powerhook = powerhook_establish(mq200_power, sc); 148 if (sc->sc_powerhook == NULL) 149 printf("%s: WARNING: unable to establish power hook\n", 150 sc->sc_dev.dv_xname); 151 152 /* Add a hard power hook to power saving */ 153 sc->sc_hardpowerhook = config_hook(CONFIG_HOOK_PMEVENT, 154 CONFIG_HOOK_PMEVENT_HARDPOWER, 155 CONFIG_HOOK_SHARE, 156 mq200_hardpower, sc); 157 if (sc->sc_hardpowerhook == NULL) 158 printf("%s: WARNING: unable to establish hard power hook\n", 159 sc->sc_dev.dv_xname); 160 161 /* initialize backlight brightness and lcd contrast */ 162 sc->sc_brightness = sc->sc_contrast = 163 sc->sc_max_brightness = sc->sc_max_contrast = -1; 164 mq200_init_brightness(sc); 165 mq200_init_contrast(sc); 166 mq200_get_backlight(sc); 167 168 if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) { 169 panic("mq200_attach: can't init fb console"); 170 } 171 172 ha.ha_console = console; 173 ha.ha_accessops = &mq200_ha; 174 ha.ha_accessctx = sc; 175 ha.ha_curfbconf = 0; 176 ha.ha_nfbconf = 1; 177 ha.ha_fbconflist = &sc->sc_fbconf; 178 ha.ha_curdspconf = 0; 179 ha.ha_ndspconf = 1; 180 ha.ha_dspconflist = &sc->sc_dspconf; 181 182 config_found(&sc->sc_dev, &ha, hpcfbprint); 183 184 #if NBIVIDEO > 0 185 /* 186 * bivideo is no longer need 187 */ 188 bivideo_dont_attach = 1; 189 #endif /* NBIVIDEO > 0 */ 190 } 191 192 static void 193 mq200_update_powerstate(sc, updates) 194 struct mq200_softc *sc; 195 int updates; 196 { 197 if (updates & PWRSTAT_LCD) 198 config_hook_call(CONFIG_HOOK_POWERCONTROL, 199 CONFIG_HOOK_POWERCONTROL_LCD, 200 (void*)!(sc->sc_powerstate & 201 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND))); 202 203 if (updates & PWRSTAT_BACKLIGHT) 204 config_hook_call(CONFIG_HOOK_POWERCONTROL, 205 CONFIG_HOOK_POWERCONTROL_LCDLIGHT, 206 (void*)(!(sc->sc_powerstate & 207 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) && 208 (sc->sc_powerstate & PWRSTAT_BACKLIGHT))); 209 } 210 211 static void 212 mq200_power(why, arg) 213 int why; 214 void *arg; 215 { 216 #if 0 217 struct mq200_softc *sc = arg; 218 219 switch (why) { 220 case PWR_SUSPEND: 221 sc->sc_powerstate |= PWRSTAT_SUSPEND; 222 mq200_update_powerstate(sc, PWRSTAT_ALL); 223 sc->sc_mq200pwstate = MQ200_POWERSTATE_D2; 224 break; 225 case PWR_STANDBY: 226 sc->sc_powerstate |= PWRSTAT_SUSPEND; 227 mq200_update_powerstate(sc, PWRSTAT_ALL); 228 sc->sc_mq200pwstate = MQ200_POWERSTATE_D3; 229 break; 230 case PWR_RESUME: 231 sc->sc_powerstate &= ~PWRSTAT_SUSPEND; 232 mq200_update_powerstate(sc, PWRSTAT_ALL); 233 sc->sc_mq200pwstate = MQ200_POWERSTATE_D0; 234 break; 235 } 236 237 printf("MQ200_PMCSR=%08x\n", sc->sc_mq200pwstate); 238 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 239 MQ200_PMCSR, sc->sc_mq200pwstate); 240 #endif 241 } 242 243 static int 244 mq200_hardpower(ctx, type, id, msg) 245 void *ctx; 246 int type; 247 long id; 248 void *msg; 249 { 250 struct mq200_softc *sc = ctx; 251 int why = (int)msg; 252 253 switch (why) { 254 case PWR_SUSPEND: 255 sc->sc_powerstate |= PWRSTAT_SUSPEND; 256 mq200_update_powerstate(sc, PWRSTAT_ALL); 257 sc->sc_mq200pwstate = MQ200_POWERSTATE_D2; 258 break; 259 case PWR_STANDBY: 260 sc->sc_powerstate |= PWRSTAT_SUSPEND; 261 mq200_update_powerstate(sc, PWRSTAT_ALL); 262 sc->sc_mq200pwstate = MQ200_POWERSTATE_D3; 263 break; 264 case PWR_RESUME: 265 sc->sc_powerstate &= ~PWRSTAT_SUSPEND; 266 mq200_update_powerstate(sc, PWRSTAT_ALL); 267 sc->sc_mq200pwstate = MQ200_POWERSTATE_D0; 268 break; 269 } 270 271 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 272 MQ200_PMCSR, sc->sc_mq200pwstate); 273 274 /* 275 * you should wait until the 276 * power state transit sequence will end. 277 */ 278 { 279 unsigned long tmp; 280 do { 281 tmp = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 282 MQ200_PMCSR); 283 } while ((tmp & 0x3) != (sc->sc_mq200pwstate & 0x3)); 284 delay(100000); /* XXX */ 285 } 286 287 return (0); 288 } 289 290 291 static int 292 mq200_fbinit(fb) 293 struct hpcfb_fbconf *fb; 294 { 295 296 /* 297 * get fb settings from bootinfo 298 */ 299 if (bootinfo == NULL || 300 bootinfo->fb_addr == 0 || 301 bootinfo->fb_line_bytes == 0 || 302 bootinfo->fb_width == 0 || 303 bootinfo->fb_height == 0) { 304 printf("no frame buffer infomation.\n"); 305 return (-1); 306 } 307 308 /* zero fill */ 309 bzero(fb, sizeof(*fb)); 310 311 fb->hf_conf_index = 0; /* configuration index */ 312 fb->hf_nconfs = 1; /* how many configurations */ 313 strcpy(fb->hf_name, "built-in video"); 314 /* frame buffer name */ 315 strcpy(fb->hf_conf_name, "default"); 316 /* configuration name */ 317 fb->hf_height = bootinfo->fb_height; 318 fb->hf_width = bootinfo->fb_width; 319 fb->hf_baseaddr = mips_ptob(mips_btop(bootinfo->fb_addr)); 320 fb->hf_offset = (u_long)bootinfo->fb_addr - fb->hf_baseaddr; 321 /* frame buffer start offset */ 322 fb->hf_bytes_per_line = bootinfo->fb_line_bytes; 323 fb->hf_nplanes = 1; 324 fb->hf_bytes_per_plane = bootinfo->fb_height * 325 bootinfo->fb_line_bytes; 326 327 fb->hf_access_flags |= HPCFB_ACCESS_BYTE; 328 fb->hf_access_flags |= HPCFB_ACCESS_WORD; 329 fb->hf_access_flags |= HPCFB_ACCESS_DWORD; 330 331 switch (bootinfo->fb_type) { 332 /* 333 * gray scale 334 */ 335 case BIFB_D2_M2L_3: 336 case BIFB_D2_M2L_3x2: 337 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 338 /* fall through */ 339 case BIFB_D2_M2L_0: 340 case BIFB_D2_M2L_0x2: 341 fb->hf_class = HPCFB_CLASS_GRAYSCALE; 342 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 343 fb->hf_pack_width = 8; 344 fb->hf_pixels_per_pack = 4; 345 fb->hf_pixel_width = 2; 346 fb->hf_class_data_length = sizeof(struct hf_gray_tag); 347 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */ 348 break; 349 350 case BIFB_D4_M2L_F: 351 case BIFB_D4_M2L_Fx2: 352 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 353 /* fall through */ 354 case BIFB_D4_M2L_0: 355 case BIFB_D4_M2L_0x2: 356 fb->hf_class = HPCFB_CLASS_GRAYSCALE; 357 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 358 fb->hf_pack_width = 8; 359 fb->hf_pixels_per_pack = 2; 360 fb->hf_pixel_width = 4; 361 fb->hf_class_data_length = sizeof(struct hf_gray_tag); 362 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */ 363 break; 364 365 /* 366 * indexed color 367 */ 368 case BIFB_D8_FF: 369 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 370 /* fall through */ 371 case BIFB_D8_00: 372 fb->hf_class = HPCFB_CLASS_INDEXCOLOR; 373 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 374 fb->hf_pack_width = 8; 375 fb->hf_pixels_per_pack = 1; 376 fb->hf_pixel_width = 8; 377 fb->hf_class_data_length = sizeof(struct hf_indexed_tag); 378 fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */ 379 break; 380 381 /* 382 * RGB color 383 */ 384 case BIFB_D16_FFFF: 385 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 386 /* fall through */ 387 case BIFB_D16_0000: 388 fb->hf_class = HPCFB_CLASS_RGBCOLOR; 389 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 390 #if BYTE_ORDER == LITTLE_ENDIAN 391 fb->hf_swap_flags = HPCFB_SWAP_BYTE; 392 #endif 393 fb->hf_pack_width = 16; 394 fb->hf_pixels_per_pack = 1; 395 fb->hf_pixel_width = 16; 396 397 fb->hf_class_data_length = sizeof(struct hf_rgb_tag); 398 fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */ 399 400 fb->hf_u.hf_rgb.hf_red_width = 5; 401 fb->hf_u.hf_rgb.hf_red_shift = 11; 402 fb->hf_u.hf_rgb.hf_green_width = 6; 403 fb->hf_u.hf_rgb.hf_green_shift = 5; 404 fb->hf_u.hf_rgb.hf_blue_width = 5; 405 fb->hf_u.hf_rgb.hf_blue_shift = 0; 406 fb->hf_u.hf_rgb.hf_alpha_width = 0; 407 fb->hf_u.hf_rgb.hf_alpha_shift = 0; 408 break; 409 410 default: 411 printf("unknown type (=%d).\n", bootinfo->fb_type); 412 return (-1); 413 break; 414 } 415 416 return (0); /* no error */ 417 } 418 419 int 420 mq200_ioctl(v, cmd, data, flag, p) 421 void *v; 422 u_long cmd; 423 caddr_t data; 424 int flag; 425 struct proc *p; 426 { 427 struct mq200_softc *sc = (struct mq200_softc *)v; 428 struct hpcfb_fbconf *fbconf; 429 struct hpcfb_dspconf *dspconf; 430 struct wsdisplay_cmap *cmap; 431 struct wsdisplay_param *dispparam; 432 433 switch (cmd) { 434 case WSDISPLAYIO_GETCMAP: 435 cmap = (struct wsdisplay_cmap*)data; 436 437 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR || 438 sc->sc_fbconf.hf_pack_width != 8 || 439 256 <= cmap->index || 440 256 < (cmap->index + cmap->count)) 441 return (EINVAL); 442 443 #if 0 444 if (!uvm_useracc(cmap->red, cmap->count, B_WRITE) || 445 !uvm_useracc(cmap->green, cmap->count, B_WRITE) || 446 !uvm_useracc(cmap->blue, cmap->count, B_WRITE)) 447 return (EFAULT); 448 449 copyout(&bivideo_cmap_r[cmap->index], cmap->red, cmap->count); 450 copyout(&bivideo_cmap_g[cmap->index], cmap->green,cmap->count); 451 copyout(&bivideo_cmap_b[cmap->index], cmap->blue, cmap->count); 452 #endif 453 454 return (0); 455 456 case WSDISPLAYIO_PUTCMAP: 457 /* 458 * This driver can't set color map. 459 */ 460 return (EINVAL); 461 462 case WSDISPLAYIO_SVIDEO: 463 if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) 464 sc->sc_powerstate |= PWRSTAT_VIDEOOFF; 465 else 466 sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF; 467 mq200_update_powerstate(sc, PWRSTAT_ALL); 468 return 0; 469 470 case WSDISPLAYIO_GVIDEO: 471 *(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ? 472 WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON; 473 return 0; 474 475 case WSDISPLAYIO_GETPARAM: 476 dispparam = (struct wsdisplay_param*)data; 477 switch (dispparam->param) { 478 case WSDISPLAYIO_PARAM_BACKLIGHT: 479 VPRINTF(("mq200_ioctl: GETPARAM:BACKLIGHT call\n")); 480 if (sc->sc_max_brightness == -1) 481 mq200_init_brightness(sc); 482 mq200_get_backlight(sc); 483 dispparam->min = 0; 484 dispparam->max = 1; 485 if (sc->sc_max_brightness > 0) 486 dispparam->curval = sc->sc_brightness > 0? 1: 0; 487 else 488 dispparam->curval = 489 (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1 : 0; 490 VPRINTF(("mq200_ioctl: GETPARAM:BACKLIGHT:%d\n", 491 dispparam->curval)); 492 return 0; 493 break; 494 case WSDISPLAYIO_PARAM_CONTRAST: 495 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST call\n")); 496 if (sc->sc_max_contrast == -1) 497 mq200_init_contrast(sc); 498 if (sc->sc_max_contrast > 0) { 499 dispparam->min = 0; 500 dispparam->max = sc->sc_max_contrast; 501 dispparam->curval = sc->sc_contrast; 502 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast)); 503 return 0; 504 } else { 505 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST ret\n")); 506 return (EINVAL); 507 } 508 break; 509 case WSDISPLAYIO_PARAM_BRIGHTNESS: 510 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS call\n")); 511 if (sc->sc_max_brightness == -1) 512 mq200_init_brightness(sc); 513 if (sc->sc_max_brightness > 0) { 514 dispparam->min = 0; 515 dispparam->max = sc->sc_max_brightness; 516 dispparam->curval = sc->sc_brightness; 517 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness)); 518 return 0; 519 } else { 520 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS ret\n")); 521 return (EINVAL); 522 } 523 return (EINVAL); 524 default: 525 return (EINVAL); 526 } 527 return (0); 528 529 case WSDISPLAYIO_SETPARAM: 530 dispparam = (struct wsdisplay_param*)data; 531 switch (dispparam->param) { 532 case WSDISPLAYIO_PARAM_BACKLIGHT: 533 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT call\n")); 534 if (dispparam->curval < 0 || 535 1 < dispparam->curval) 536 return (EINVAL); 537 if (sc->sc_max_brightness == -1) 538 mq200_init_brightness(sc); 539 VPRINTF(("mq200_ioctl: SETPARAM:max brightness=%d\n", sc->sc_max_brightness)); 540 if (sc->sc_max_brightness > 0) { /* dimmer */ 541 if (dispparam->curval == 0){ 542 sc->sc_brightness_save = sc->sc_brightness; 543 mq200_set_brightness(sc, 0); /* min */ 544 } else { 545 if (sc->sc_brightness_save == 0) 546 sc->sc_brightness_save = sc->sc_max_brightness; 547 mq200_set_brightness(sc, sc->sc_brightness_save); 548 } 549 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT: brightness=%d\n", sc->sc_brightness)); 550 } else { /* off */ 551 if (dispparam->curval == 0) 552 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 553 else 554 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 555 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT: powerstate %d\n", 556 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); 557 mq200_update_powerstate(sc, PWRSTAT_BACKLIGHT); 558 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT:%d\n", 559 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); 560 } 561 return 0; 562 break; 563 case WSDISPLAYIO_PARAM_CONTRAST: 564 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST call\n")); 565 if (sc->sc_max_contrast == -1) 566 mq200_init_contrast(sc); 567 if (dispparam->curval < 0 || 568 sc->sc_max_contrast < dispparam->curval) 569 return (EINVAL); 570 if (sc->sc_max_contrast > 0) { 571 int org = sc->sc_contrast; 572 mq200_set_contrast(sc, dispparam->curval); 573 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast)); 574 return 0; 575 } else { 576 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST ret\n")); 577 return (EINVAL); 578 } 579 break; 580 case WSDISPLAYIO_PARAM_BRIGHTNESS: 581 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS call\n")); 582 if (sc->sc_max_brightness == -1) 583 mq200_init_brightness(sc); 584 if (dispparam->curval < 0 || 585 sc->sc_max_brightness < dispparam->curval) 586 return (EINVAL); 587 if (sc->sc_max_brightness > 0) { 588 int org = sc->sc_brightness; 589 mq200_set_brightness(sc, dispparam->curval); 590 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness)); 591 return 0; 592 } else { 593 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS ret\n")); 594 return (EINVAL); 595 } 596 break; 597 default: 598 return (EINVAL); 599 } 600 return (0); 601 602 case HPCFBIO_GCONF: 603 fbconf = (struct hpcfb_fbconf *)data; 604 if (fbconf->hf_conf_index != 0 && 605 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 606 return (EINVAL); 607 } 608 *fbconf = sc->sc_fbconf; /* structure assignment */ 609 return (0); 610 case HPCFBIO_SCONF: 611 fbconf = (struct hpcfb_fbconf *)data; 612 if (fbconf->hf_conf_index != 0 && 613 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 614 return (EINVAL); 615 } 616 /* 617 * nothing to do because we have only one configration 618 */ 619 return (0); 620 case HPCFBIO_GDSPCONF: 621 dspconf = (struct hpcfb_dspconf *)data; 622 if ((dspconf->hd_unit_index != 0 && 623 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 624 (dspconf->hd_conf_index != 0 && 625 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 626 return (EINVAL); 627 } 628 *dspconf = sc->sc_dspconf; /* structure assignment */ 629 return (0); 630 case HPCFBIO_SDSPCONF: 631 dspconf = (struct hpcfb_dspconf *)data; 632 if ((dspconf->hd_unit_index != 0 && 633 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 634 (dspconf->hd_conf_index != 0 && 635 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 636 return (EINVAL); 637 } 638 /* 639 * nothing to do 640 * because we have only one unit and one configration 641 */ 642 return (0); 643 case HPCFBIO_GOP: 644 case HPCFBIO_SOP: 645 /* 646 * curently not implemented... 647 */ 648 return (EINVAL); 649 } 650 651 return (ENOTTY); 652 } 653 654 paddr_t 655 mq200_mmap(ctx, offset, prot) 656 void *ctx; 657 off_t offset; 658 int prot; 659 { 660 struct mq200_softc *sc = (struct mq200_softc *)ctx; 661 662 if (offset < 0 || MQ200_MAPSIZE <= offset) 663 return -1; 664 665 return mips_btop(sc->sc_baseaddr + offset); 666 } 667 668 669 void 670 mq200_get_backlight(sc) 671 struct mq200_softc *sc; 672 { 673 int val = -1; 674 675 if (sc->sc_max_brightness < 0) { 676 if (config_hook_call(CONFIG_HOOK_GET, 677 CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) { 678 if (val == 0) 679 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; 680 else 681 sc->sc_powerstate |= PWRSTAT_BACKLIGHT; 682 } 683 } 684 } 685 686 void 687 mq200_init_brightness(sc) 688 struct mq200_softc *sc; 689 { 690 int val = -1; 691 692 VPRINTF(("mq200_init_brightness\n")); 693 if (config_hook_call(CONFIG_HOOK_GET, 694 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 695 sc->sc_brightness_save = sc->sc_brightness = val; 696 } 697 val = -1; 698 if (config_hook_call(CONFIG_HOOK_GET, 699 CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) { 700 sc->sc_max_brightness = val; 701 } 702 return; 703 } 704 705 706 void 707 mq200_init_contrast(sc) 708 struct mq200_softc *sc; 709 { 710 int val = -1; 711 712 VPRINTF(("mq200_init_contrast\n")); 713 if (config_hook_call(CONFIG_HOOK_GET, 714 CONFIG_HOOK_CONTRAST, &val) != -1) { 715 sc->sc_contrast = val; 716 } 717 val = -1; 718 if (config_hook_call(CONFIG_HOOK_GET, 719 CONFIG_HOOK_CONTRAST_MAX, &val) != -1) { 720 sc->sc_max_contrast = val; 721 } 722 return; 723 } 724 725 void 726 mq200_set_brightness(sc, val) 727 struct mq200_softc *sc; 728 int val; 729 { 730 sc->sc_brightness = val; 731 732 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 733 if (config_hook_call(CONFIG_HOOK_GET, 734 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 735 sc->sc_brightness = val; 736 } 737 } 738 739 void 740 mq200_set_contrast(sc, val) 741 struct mq200_softc *sc; 742 int val; 743 { 744 sc->sc_contrast = val; 745 746 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 747 if (config_hook_call(CONFIG_HOOK_GET, 748 CONFIG_HOOK_CONTRAST, &val) != -1) { 749 sc->sc_contrast = val; 750 } 751 } 752