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