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