1 /* $NetBSD: plumvideo.c,v 1.41 2012/10/27 17:17:53 chs Exp $ */ 2 3 /*- 4 * Copyright (c) 1999-2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: plumvideo.c,v 1.41 2012/10/27 17:17:53 chs Exp $"); 34 35 #undef PLUMVIDEODEBUG 36 37 #include "plumohci.h" /* Plum2 OHCI shared memory allocated on V-RAM */ 38 #include "bivideo.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 44 #include <sys/ioctl.h> 45 #include <sys/buf.h> 46 #include <uvm/uvm_extern.h> 47 48 #include <dev/cons.h> /* consdev */ 49 50 #include <mips/cache.h> 51 52 #include <machine/bus.h> 53 #include <machine/intr.h> 54 #include <machine/config_hook.h> 55 56 #include <hpcmips/tx/tx39var.h> 57 #include <hpcmips/dev/plumvar.h> 58 #include <hpcmips/dev/plumicuvar.h> 59 #include <hpcmips/dev/plumpowervar.h> 60 #include <hpcmips/dev/plumvideoreg.h> 61 62 #include <machine/bootinfo.h> 63 64 #include <dev/wscons/wsdisplayvar.h> 65 #include <dev/rasops/rasops.h> 66 #include <dev/hpc/video_subr.h> 67 68 #include <dev/wscons/wsconsio.h> 69 #include <dev/hpc/hpcfbvar.h> 70 #include <dev/hpc/hpcfbio.h> 71 #if NBIVIDEO > 0 72 #include <dev/hpc/bivideovar.h> 73 #endif 74 75 #ifdef PLUMVIDEODEBUG 76 int plumvideo_debug = 1; 77 #define DPRINTF(arg) if (plumvideo_debug) printf arg; 78 #define DPRINTFN(n, arg) if (plumvideo_debug > (n)) printf arg; 79 #else 80 #define DPRINTF(arg) 81 #define DPRINTFN(n, arg) 82 #endif 83 84 struct plumvideo_softc { 85 device_t sc_dev; 86 tx_chipset_tag_t sc_tc; 87 plum_chipset_tag_t sc_pc; 88 89 void *sc_powerhook; /* power management hook */ 90 int sc_console; 91 92 int sc_backlight; 93 int sc_brightness; 94 int sc_max_brightness; 95 96 /* control register */ 97 bus_space_tag_t sc_regt; 98 bus_space_handle_t sc_regh; 99 /* frame buffer */ 100 bus_space_tag_t sc_fbiot; 101 bus_space_handle_t sc_fbioh; 102 /* clut buffer (8bpp only) */ 103 bus_space_tag_t sc_clutiot; 104 bus_space_handle_t sc_clutioh; 105 /* bitblt */ 106 bus_space_tag_t sc_bitbltt; 107 bus_space_handle_t sc_bitblth; 108 109 struct video_chip sc_chip; 110 struct hpcfb_fbconf sc_fbconf; 111 struct hpcfb_dspconf sc_dspconf; 112 }; 113 114 int plumvideo_match(device_t, cfdata_t, void *); 115 void plumvideo_attach(device_t, device_t, void *); 116 117 int plumvideo_ioctl(void *, u_long, void *, int, struct lwp *); 118 paddr_t plumvideo_mmap(void *, off_t, int); 119 120 CFATTACH_DECL_NEW(plumvideo, sizeof(struct plumvideo_softc), 121 plumvideo_match, plumvideo_attach, NULL, NULL); 122 123 struct hpcfb_accessops plumvideo_ha = { 124 plumvideo_ioctl, plumvideo_mmap 125 }; 126 127 int plumvideo_power(void *, int, long, void *); 128 129 int plumvideo_init(struct plumvideo_softc *, int *); 130 void plumvideo_hpcfbinit(struct plumvideo_softc *, int); 131 132 void plumvideo_clut_default(struct plumvideo_softc *); 133 void plumvideo_clut_set(struct plumvideo_softc *, u_int32_t *, int, int); 134 void plumvideo_clut_get(struct plumvideo_softc *, u_int32_t *, int, int); 135 void __plumvideo_clut_access(struct plumvideo_softc *, u_int32_t *, int, int, 136 void (*)(bus_space_tag_t, bus_space_handle_t, u_int32_t *, int, int)); 137 static void _flush_cache(void) __attribute__((__unused__)); /* !!! */ 138 static void plumvideo_init_backlight(struct plumvideo_softc *); 139 static void plumvideo_backlight(struct plumvideo_softc *, int); 140 static void plumvideo_brightness(struct plumvideo_softc *, int); 141 142 #ifdef PLUMVIDEODEBUG 143 void plumvideo_dump(struct plumvideo_softc*); 144 #endif 145 146 #define ON 1 147 #define OFF 0 148 149 int 150 plumvideo_match(device_t parent, cfdata_t cf, void *aux) 151 { 152 /* 153 * VRAM area also uses as UHOSTC shared RAM. 154 */ 155 return (2); /* 1st attach group */ 156 } 157 158 void 159 plumvideo_attach(device_t parent, device_t self, void *aux) 160 { 161 struct plum_attach_args *pa = aux; 162 struct plumvideo_softc *sc = device_private(self); 163 struct hpcfb_attach_args ha; 164 int console, reverse_flag; 165 166 sc->sc_dev = self; 167 sc->sc_console = console = cn_tab ? 0 : 1; 168 sc->sc_pc = pa->pa_pc; 169 sc->sc_regt = pa->pa_regt; 170 sc->sc_fbiot = sc->sc_clutiot = sc->sc_bitbltt = pa->pa_iot; 171 172 printf(": "); 173 174 /* map register area */ 175 if (bus_space_map(sc->sc_regt, PLUM_VIDEO_REGBASE, 176 PLUM_VIDEO_REGSIZE, 0, &sc->sc_regh)) { 177 printf("register map failed\n"); 178 return; 179 } 180 181 /* initialize backlight and brightness values */ 182 plumvideo_init_backlight(sc); 183 184 /* power control */ 185 plumvideo_power(sc, 0, 0, 186 (void *)(console ? PWR_RESUME : PWR_SUSPEND)); 187 /* Add a hard power hook to power saving */ 188 sc->sc_powerhook = config_hook(CONFIG_HOOK_PMEVENT, 189 CONFIG_HOOK_PMEVENT_HARDPOWER, 190 CONFIG_HOOK_SHARE, 191 plumvideo_power, sc); 192 if (sc->sc_powerhook == 0) 193 printf("WARNING unable to establish hard power hook"); 194 195 /* 196 * Initialize LCD controller 197 * map V-RAM area. 198 * reinstall bootinfo structure. 199 * some OHCI shared-buffer hack. XXX 200 */ 201 if (plumvideo_init(sc, &reverse_flag) != 0) 202 return; 203 204 printf("\n"); 205 206 /* Attach frame buffer device */ 207 plumvideo_hpcfbinit(sc, reverse_flag); 208 209 #ifdef PLUMVIDEODEBUG 210 if (plumvideo_debug > 0) 211 plumvideo_dump(sc); 212 /* attach debug draw routine (debugging use) */ 213 video_attach_drawfunc(&sc->sc_chip); 214 tx_conf_register_video(sc->sc_pc->pc_tc, &sc->sc_chip); 215 #endif /* PLUMVIDEODEBUG */ 216 217 if(console && hpcfb_cnattach(&sc->sc_fbconf) != 0) { 218 panic("plumvideo_attach: can't init fb console"); 219 } 220 221 ha.ha_console = console; 222 ha.ha_accessops = &plumvideo_ha; 223 ha.ha_accessctx = sc; 224 ha.ha_curfbconf = 0; 225 ha.ha_nfbconf = 1; 226 ha.ha_fbconflist = &sc->sc_fbconf; 227 ha.ha_curdspconf = 0; 228 ha.ha_ndspconf = 1; 229 ha.ha_dspconflist = &sc->sc_dspconf; 230 231 config_found(self, &ha, hpcfbprint); 232 #if NBIVIDEO > 0 233 /* bivideo is no longer need */ 234 bivideo_dont_attach = 1; 235 #endif /* NBIVIDEO > 0 */ 236 } 237 238 void 239 plumvideo_hpcfbinit(struct plumvideo_softc *sc, int reverse_flag) 240 { 241 struct hpcfb_fbconf *fb = &sc->sc_fbconf; 242 struct video_chip *chip = &sc->sc_chip; 243 vaddr_t fbvaddr = (vaddr_t)sc->sc_fbioh; 244 int height = chip->vc_fbheight; 245 int width = chip->vc_fbwidth; 246 int depth = chip->vc_fbdepth; 247 248 memset(fb, 0, sizeof(struct hpcfb_fbconf)); 249 250 fb->hf_conf_index = 0; /* configuration index */ 251 fb->hf_nconfs = 1; /* how many configurations */ 252 strncpy(fb->hf_name, "PLUM built-in video", HPCFB_MAXNAMELEN); 253 /* frame buffer name */ 254 strncpy(fb->hf_conf_name, "LCD", HPCFB_MAXNAMELEN); 255 /* configuration name */ 256 fb->hf_height = height; 257 fb->hf_width = width; 258 fb->hf_baseaddr = (u_long)fbvaddr; 259 fb->hf_offset = (u_long)fbvaddr - mips_ptob(mips_btop(fbvaddr)); 260 /* frame buffer start offset */ 261 fb->hf_bytes_per_line = (width * depth) / NBBY; 262 fb->hf_nplanes = 1; 263 fb->hf_bytes_per_plane = height * fb->hf_bytes_per_line; 264 265 fb->hf_access_flags |= HPCFB_ACCESS_BYTE; 266 fb->hf_access_flags |= HPCFB_ACCESS_WORD; 267 fb->hf_access_flags |= HPCFB_ACCESS_DWORD; 268 if (reverse_flag) 269 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 270 271 switch (depth) { 272 default: 273 panic("plumvideo_hpcfbinit: not supported color depth"); 274 /* NOTREACHED */ 275 case 16: 276 fb->hf_class = HPCFB_CLASS_RGBCOLOR; 277 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 278 fb->hf_pack_width = 16; 279 fb->hf_pixels_per_pack = 1; 280 fb->hf_pixel_width = 16; 281 282 fb->hf_class_data_length = sizeof(struct hf_rgb_tag); 283 /* reserved for future use */ 284 fb->hf_u.hf_rgb.hf_flags = 0; 285 286 fb->hf_u.hf_rgb.hf_red_width = 5; 287 fb->hf_u.hf_rgb.hf_red_shift = 11; 288 fb->hf_u.hf_rgb.hf_green_width = 6; 289 fb->hf_u.hf_rgb.hf_green_shift = 5; 290 fb->hf_u.hf_rgb.hf_blue_width = 5; 291 fb->hf_u.hf_rgb.hf_blue_shift = 0; 292 fb->hf_u.hf_rgb.hf_alpha_width = 0; 293 fb->hf_u.hf_rgb.hf_alpha_shift = 0; 294 break; 295 296 case 8: 297 fb->hf_class = HPCFB_CLASS_INDEXCOLOR; 298 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 299 fb->hf_pack_width = 8; 300 fb->hf_pixels_per_pack = 1; 301 fb->hf_pixel_width = 8; 302 fb->hf_class_data_length = sizeof(struct hf_indexed_tag); 303 /* reserved for future use */ 304 fb->hf_u.hf_indexed.hf_flags = 0; 305 break; 306 } 307 } 308 309 int 310 plumvideo_init(struct plumvideo_softc *sc, int *reverse) 311 { 312 struct video_chip *chip = &sc->sc_chip; 313 bus_space_tag_t regt = sc->sc_regt; 314 bus_space_handle_t regh = sc->sc_regh; 315 plumreg_t reg; 316 size_t vram_size; 317 int bpp, width, height, vram_pitch; 318 319 *reverse = video_reverse_color(); 320 chip->vc_v = sc->sc_pc->pc_tc; 321 #if notyet 322 /* map BitBlt area */ 323 if (bus_space_map(sc->sc_bitbltt, 324 PLUM_VIDEO_BITBLT_IOBASE, 325 PLUM_VIDEO_BITBLT_IOSIZE, 0, 326 &sc->sc_bitblth)) { 327 printf(": BitBlt map failed\n"); 328 return (1); 329 } 330 #endif 331 reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG); 332 333 switch (reg & PLUM_VIDEO_PLGMD_GMODE_MASK) { 334 case PLUM_VIDEO_PLGMD_16BPP: 335 #if NPLUMOHCI > 0 /* reserve V-RAM area for USB OHCI */ 336 /* FALLTHROUGH */ 337 #else 338 bpp = 16; 339 break; 340 #endif 341 default: 342 bootinfo->fb_type = *reverse ? BIFB_D8_FF : BIFB_D8_00; 343 reg &= ~PLUM_VIDEO_PLGMD_GMODE_MASK; 344 plum_conf_write(regt, regh, PLUM_VIDEO_PLGMD_REG, reg); 345 reg |= PLUM_VIDEO_PLGMD_8BPP; 346 plum_conf_write(regt, regh, PLUM_VIDEO_PLGMD_REG, reg); 347 #if notyet 348 /* change BitBlt color depth */ 349 plum_conf_write(sc->sc_bitbltt, sc->sc_bitblth, 0x8, 0); 350 #endif 351 /* FALLTHROUGH */ 352 case PLUM_VIDEO_PLGMD_8BPP: 353 bpp = 8; 354 break; 355 } 356 chip->vc_fbdepth = bpp; 357 358 /* 359 * Get display size from WindowsCE setted. 360 */ 361 chip->vc_fbwidth = width = bootinfo->fb_width = 362 plum_conf_read(regt, regh, PLUM_VIDEO_PLHPX_REG) + 1; 363 chip->vc_fbheight = height = bootinfo->fb_height = 364 plum_conf_read(regt, regh, PLUM_VIDEO_PLVT_REG) - 365 plum_conf_read(regt, regh, PLUM_VIDEO_PLVDS_REG); 366 367 /* 368 * set line byte length to bootinfo and LCD controller. 369 */ 370 vram_pitch = bootinfo->fb_line_bytes = (width * bpp) / NBBY; 371 plum_conf_write(regt, regh, PLUM_VIDEO_PLPIT1_REG, vram_pitch); 372 plum_conf_write(regt, regh, PLUM_VIDEO_PLPIT2_REG, 373 vram_pitch & PLUM_VIDEO_PLPIT2_MASK); 374 plum_conf_write(regt, regh, PLUM_VIDEO_PLOFS_REG, vram_pitch); 375 376 /* 377 * boot messages and map CLUT(if any). 378 */ 379 printf("display mode: "); 380 switch (bpp) { 381 default: 382 printf("disabled "); 383 break; 384 case 8: 385 printf("8bpp "); 386 /* map CLUT area */ 387 if (bus_space_map(sc->sc_clutiot, 388 PLUM_VIDEO_CLUT_LCD_IOBASE, 389 PLUM_VIDEO_CLUT_LCD_IOSIZE, 0, 390 &sc->sc_clutioh)) { 391 printf(": CLUT map failed\n"); 392 return (1); 393 } 394 /* install default CLUT */ 395 plumvideo_clut_default(sc); 396 break; 397 case 16: 398 printf("16bpp "); 399 break; 400 } 401 402 /* 403 * calcurate frame buffer size. 404 */ 405 reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG); 406 vram_size = (width * height * bpp) / NBBY; 407 vram_size = mips_round_page(vram_size); 408 chip->vc_fbsize = vram_size; 409 410 /* 411 * map V-RAM area. 412 */ 413 if (bus_space_map(sc->sc_fbiot, PLUM_VIDEO_VRAM_IOBASE, 414 vram_size, 0, &sc->sc_fbioh)) { 415 printf(": V-RAM map failed\n"); 416 return (1); 417 } 418 419 bootinfo->fb_addr = (unsigned char *)sc->sc_fbioh; 420 chip->vc_fbvaddr = (vaddr_t)sc->sc_fbioh; 421 chip->vc_fbpaddr = PLUM_VIDEO_VRAM_IOBASE_PHYSICAL; 422 423 return (0); 424 } 425 426 int 427 plumvideo_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 428 { 429 struct plumvideo_softc *sc = v; 430 struct hpcfb_fbconf *fbconf; 431 struct hpcfb_dspconf *dspconf; 432 struct wsdisplay_cmap *cmap; 433 struct wsdisplay_param *dispparam; 434 u_int8_t *r, *g, *b; 435 u_int32_t *rgb; 436 int idx, error; 437 size_t cnt; 438 439 switch (cmd) { 440 case WSDISPLAYIO_GETCMAP: 441 cmap = (struct wsdisplay_cmap *)data; 442 cnt = cmap->count; 443 idx = cmap->index; 444 445 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR || 446 sc->sc_fbconf.hf_pack_width != 8 || 447 !LEGAL_CLUT_INDEX(idx) || 448 !LEGAL_CLUT_INDEX(idx + cnt - 1)) { 449 return (EINVAL); 450 } 451 452 error = cmap_work_alloc(&r, &g, &b, &rgb, cnt); 453 if (error) 454 goto out; 455 plumvideo_clut_get(sc, rgb, idx, cnt); 456 rgb24_decompose(rgb, r, g, b, cnt); 457 458 error = copyout(r, cmap->red, cnt); 459 if (error) 460 goto out; 461 error = copyout(g, cmap->green, cnt); 462 if (error) 463 goto out; 464 error = copyout(b, cmap->blue, cnt); 465 466 out: 467 cmap_work_free(r, g, b, rgb); 468 return error; 469 470 case WSDISPLAYIO_PUTCMAP: 471 cmap = (struct wsdisplay_cmap *)data; 472 cnt = cmap->count; 473 idx = cmap->index; 474 475 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR || 476 sc->sc_fbconf.hf_pack_width != 8 || 477 !LEGAL_CLUT_INDEX(idx) || 478 !LEGAL_CLUT_INDEX(idx + cnt - 1)) { 479 return (EINVAL); 480 } 481 482 error = cmap_work_alloc(&r, &g, &b, &rgb, cnt); 483 if (error) 484 goto out; 485 error = copyin(cmap->red, r, cnt); 486 if (error) 487 goto out; 488 error = copyin(cmap->green, g, cnt); 489 if (error) 490 goto out; 491 error = copyin(cmap->blue, b, cnt); 492 if (error) 493 goto out; 494 rgb24_compose(rgb, r, g, b, cnt); 495 plumvideo_clut_set(sc, rgb, idx, cnt); 496 goto out; 497 498 case WSDISPLAYIO_SVIDEO: 499 if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) 500 plumvideo_backlight(sc, 0); 501 else 502 plumvideo_backlight(sc, 1); 503 return 0; 504 505 case WSDISPLAYIO_GVIDEO: 506 *(int *)data = sc->sc_backlight ? 507 WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 508 return 0; 509 510 case WSDISPLAYIO_GETPARAM: 511 dispparam = (struct wsdisplay_param *)data; 512 switch (dispparam->param) { 513 case WSDISPLAYIO_PARAM_BACKLIGHT: 514 dispparam->min = 0; 515 dispparam->max = 1; 516 dispparam->curval = sc->sc_backlight; 517 break; 518 case WSDISPLAYIO_PARAM_BRIGHTNESS: 519 if (sc->sc_max_brightness <= 0) 520 return EINVAL; 521 dispparam->min = 0; 522 dispparam->max = sc->sc_max_brightness; 523 dispparam->curval = sc->sc_brightness; 524 break; 525 default: 526 return EINVAL; 527 } 528 return 0; 529 530 case WSDISPLAYIO_SETPARAM: 531 dispparam = (struct wsdisplay_param * )data; 532 switch (dispparam->param) { 533 case WSDISPLAYIO_PARAM_BACKLIGHT: 534 if (dispparam->curval < 0 || 1 < dispparam->curval) 535 return EINVAL; 536 plumvideo_backlight(sc, dispparam->curval); 537 break; 538 case WSDISPLAYIO_PARAM_BRIGHTNESS: 539 if (sc->sc_max_brightness <= 0) 540 return EINVAL; 541 if (dispparam->curval < 0 || 542 sc->sc_max_brightness < dispparam->curval) 543 return EINVAL; 544 plumvideo_brightness(sc, dispparam->curval); 545 break; 546 default: 547 return EINVAL; 548 } 549 return 0; 550 551 case HPCFBIO_GCONF: 552 fbconf = (struct hpcfb_fbconf *)data; 553 if (fbconf->hf_conf_index != 0 && 554 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 555 return (EINVAL); 556 } 557 *fbconf = sc->sc_fbconf; /* structure assignment */ 558 return (0); 559 560 case HPCFBIO_SCONF: 561 fbconf = (struct hpcfb_fbconf *)data; 562 if (fbconf->hf_conf_index != 0 && 563 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 564 return (EINVAL); 565 } 566 /* 567 * nothing to do because we have only one configuration 568 */ 569 return (0); 570 571 case HPCFBIO_GDSPCONF: 572 dspconf = (struct hpcfb_dspconf *)data; 573 if ((dspconf->hd_unit_index != 0 && 574 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 575 (dspconf->hd_conf_index != 0 && 576 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 577 return (EINVAL); 578 } 579 *dspconf = sc->sc_dspconf; /* structure assignment */ 580 return (0); 581 582 case HPCFBIO_SDSPCONF: 583 dspconf = (struct hpcfb_dspconf *)data; 584 if ((dspconf->hd_unit_index != 0 && 585 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 586 (dspconf->hd_conf_index != 0 && 587 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 588 return (EINVAL); 589 } 590 /* 591 * nothing to do 592 * because we have only one unit and one configuration 593 */ 594 return (0); 595 596 case HPCFBIO_GOP: 597 case HPCFBIO_SOP: 598 /* XXX not implemented yet */ 599 return (EINVAL); 600 } 601 602 return (EPASSTHROUGH); 603 } 604 605 paddr_t 606 plumvideo_mmap(void *ctx, off_t offset, int prot) 607 { 608 struct plumvideo_softc *sc = ctx; 609 610 if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane + 611 sc->sc_fbconf.hf_offset) < offset) { 612 return (-1); 613 } 614 615 return (mips_btop(PLUM_VIDEO_VRAM_IOBASE_PHYSICAL + offset)); 616 } 617 618 static void __plumvideo_clut_get(bus_space_tag_t, bus_space_handle_t, 619 u_int32_t *, int, int); 620 static void __plumvideo_clut_get(bus_space_tag_t iot, bus_space_handle_t ioh, 621 u_int32_t *rgb, int beg, int cnt) 622 { 623 int i; 624 625 for (i = 0, beg *= 4; i < cnt; i++, beg += 4) { 626 *rgb++ = bus_space_read_4(iot, ioh, beg) & 627 0x00ffffff; 628 } 629 } 630 631 void 632 plumvideo_clut_get(struct plumvideo_softc *sc, u_int32_t *rgb, int beg, 633 int cnt) 634 { 635 KASSERT(rgb); 636 KASSERT(LEGAL_CLUT_INDEX(beg)); 637 KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1)); 638 __plumvideo_clut_access(sc, rgb, beg, cnt, __plumvideo_clut_get); 639 } 640 641 static void __plumvideo_clut_set(bus_space_tag_t, bus_space_handle_t, 642 u_int32_t *, int, int); 643 static void __plumvideo_clut_set(bus_space_tag_t iot, bus_space_handle_t ioh, 644 u_int32_t *rgb, int beg, int cnt) 645 { 646 int i; 647 648 for (i = 0, beg *= 4; i < cnt; i++, beg +=4) { 649 bus_space_write_4(iot, ioh, beg, 650 *rgb++ & 0x00ffffff); 651 } 652 } 653 654 void 655 plumvideo_clut_set(struct plumvideo_softc *sc, u_int32_t *rgb, int beg, 656 int cnt) 657 { 658 KASSERT(rgb); 659 KASSERT(LEGAL_CLUT_INDEX(beg)); 660 KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1)); 661 __plumvideo_clut_access(sc, rgb, beg, cnt, __plumvideo_clut_set); 662 } 663 664 static void __plumvideo_clut_default(bus_space_tag_t, bus_space_handle_t, 665 u_int32_t *, int, int); 666 static void __plumvideo_clut_default(bus_space_tag_t iot, bus_space_handle_t ioh, 667 u_int32_t *rgb, int beg, int cnt) 668 { 669 static const u_int8_t compo6[6] = { 0, 51, 102, 153, 204, 255 }; 670 static const u_int32_t ansi_color[16] = { 671 0x000000, 0xff0000, 0x00ff00, 0xffff00, 672 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff, 673 0x000000, 0x800000, 0x008000, 0x808000, 674 0x000080, 0x800080, 0x008080, 0x808080, 675 }; 676 int i, r, g, b; 677 678 /* ANSI escape sequence */ 679 for (i = 0; i < 16; i++) { 680 bus_space_write_4(iot, ioh, i << 2, ansi_color[i]); 681 } 682 /* 16 - 31, gray scale */ 683 for ( ; i < 32; i++) { 684 int j = (i - 16) * 17; 685 bus_space_write_4(iot, ioh, i << 2, RGB24(j, j, j)); 686 } 687 /* 32 - 247, RGB color */ 688 for (r = 0; r < 6; r++) { 689 for (g = 0; g < 6; g++) { 690 for (b = 0; b < 6; b++) { 691 bus_space_write_4(iot, ioh, i << 2, 692 RGB24(compo6[r], 693 compo6[g], 694 compo6[b])); 695 i++; 696 } 697 } 698 } 699 /* 248 - 245, just white */ 700 for ( ; i < 256; i++) { 701 bus_space_write_4(iot, ioh, i << 2, 0xffffff); 702 } 703 } 704 705 void 706 plumvideo_clut_default(struct plumvideo_softc *sc) 707 { 708 __plumvideo_clut_access(sc, NULL, 0, 256, __plumvideo_clut_default); 709 } 710 711 void 712 __plumvideo_clut_access(struct plumvideo_softc *sc, u_int32_t *rgb, int beg, 713 int cnt, void (*palette_func)(bus_space_tag_t, bus_space_handle_t, 714 u_int32_t *, int, int)) 715 { 716 bus_space_tag_t regt = sc->sc_regt; 717 bus_space_handle_t regh = sc->sc_regh; 718 plumreg_t val, gmode; 719 720 /* display off */ 721 val = bus_space_read_4(regt, regh, PLUM_VIDEO_PLGMD_REG); 722 gmode = val & PLUM_VIDEO_PLGMD_GMODE_MASK; 723 val &= ~PLUM_VIDEO_PLGMD_GMODE_MASK; 724 bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val); 725 726 /* palette access disable */ 727 val &= ~PLUM_VIDEO_PLGMD_PALETTE_ENABLE; 728 bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val); 729 730 /* change palette mode to CPU */ 731 val &= ~PLUM_VIDEO_PLGMD_MODE_DISPLAY; 732 bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val); 733 734 /* palette access */ 735 (*palette_func) (sc->sc_clutiot, sc->sc_clutioh, rgb, beg, cnt); 736 737 /* change palette mode to Display */ 738 val |= PLUM_VIDEO_PLGMD_MODE_DISPLAY; 739 bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val); 740 741 /* palette access enable */ 742 val |= PLUM_VIDEO_PLGMD_PALETTE_ENABLE; 743 bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val); 744 745 /* display on */ 746 val |= gmode; 747 bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val); 748 } 749 750 /* !!! */ 751 static void 752 _flush_cache(void) 753 { 754 mips_dcache_wbinv_all(); 755 mips_icache_sync_all(); 756 } 757 758 int 759 plumvideo_power(void *ctx, int type, long id, void *msg) 760 { 761 struct plumvideo_softc *sc = ctx; 762 int why = (int)msg; 763 764 switch (why) { 765 case PWR_RESUME: 766 if (!sc->sc_console) 767 return (0); /* serial console */ 768 769 DPRINTF(("%s: ON\n", device_xname(sc->sc_dev))); 770 /* power on */ 771 plumvideo_backlight(sc, 1); 772 break; 773 case PWR_SUSPEND: 774 /* FALLTHROUGH */ 775 case PWR_STANDBY: 776 DPRINTF(("%s: OFF\n", device_xname(sc->sc_dev))); 777 /* power off */ 778 plumvideo_backlight(sc, 0); 779 break; 780 } 781 782 return (0); 783 } 784 785 static void 786 plumvideo_init_backlight(struct plumvideo_softc *sc) 787 { 788 int val; 789 790 val = -1; 791 if (config_hook_call(CONFIG_HOOK_GET, 792 CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) { 793 /* we can get real backlight state */ 794 sc->sc_backlight = val; 795 } 796 797 val = -1; 798 if (config_hook_call(CONFIG_HOOK_GET, 799 CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) { 800 /* we can get real brightness max */ 801 sc->sc_max_brightness = val; 802 803 val = -1; 804 if (config_hook_call(CONFIG_HOOK_GET, 805 CONFIG_HOOK_BRIGHTNESS, &val) != -1) { 806 /* we can get real brightness */ 807 sc->sc_brightness = val; 808 } else { 809 sc->sc_brightness = sc->sc_max_brightness; 810 } 811 } 812 } 813 814 static void 815 plumvideo_backlight(struct plumvideo_softc *sc, int on) 816 { 817 plum_chipset_tag_t pc = sc->sc_pc; 818 bus_space_tag_t regt = sc->sc_regt; 819 bus_space_handle_t regh = sc->sc_regh; 820 821 sc->sc_backlight = on; 822 if (on) { 823 /* LCD on */ 824 plum_power_establish(pc, PLUM_PWR_LCD); 825 /* backlight on */ 826 plum_power_establish(pc, PLUM_PWR_BKL); 827 plum_conf_write(regt, regh, PLUM_VIDEO_PLLUM_REG, 828 PLUM_VIDEO_PLLUM_MAX); 829 } else { 830 /* backlight off */ 831 plum_conf_write(regt, regh, PLUM_VIDEO_PLLUM_REG, 832 PLUM_VIDEO_PLLUM_MIN); 833 plum_power_disestablish(pc, PLUM_PWR_BKL); 834 /* LCD off */ 835 plum_power_disestablish(pc, PLUM_PWR_LCD); 836 } 837 /* call machine dependent backlight control */ 838 config_hook_call(CONFIG_HOOK_SET, 839 CONFIG_HOOK_POWER_LCDLIGHT, (void *)on); 840 } 841 842 static void 843 plumvideo_brightness(struct plumvideo_softc *sc, int val) 844 { 845 846 sc->sc_brightness = val; 847 /* call machine dependent brightness control */ 848 if (sc->sc_backlight) 849 config_hook_call(CONFIG_HOOK_SET, 850 CONFIG_HOOK_BRIGHTNESS, &val); 851 } 852 853 #ifdef PLUMVIDEODEBUG 854 void 855 plumvideo_dump(struct plumvideo_softc *sc) 856 { 857 bus_space_tag_t regt = sc->sc_regt; 858 bus_space_handle_t regh = sc->sc_regh; 859 860 plumreg_t reg; 861 int i; 862 863 for (i = 0; i < 0x160; i += 4) { 864 reg = plum_conf_read(regt, regh, i); 865 printf("0x%03x %08x", i, reg); 866 dbg_bit_print(reg); 867 } 868 } 869 #endif /* PLUMVIDEODEBUG */ 870