1 /* $OpenBSD: lunafb.c,v 1.28 2021/09/17 12:02:31 aoyama Exp $ */ 2 /* $NetBSD: lunafb.c,v 1.7.6.1 2002/08/07 01:48:34 lukem Exp $ */ 3 4 /*- 5 * Copyright (c) 2000 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Tohru Nishimura. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/conf.h> 36 #include <sys/device.h> 37 #include <sys/ioctl.h> 38 #include <sys/malloc.h> 39 #include <sys/mman.h> 40 #include <sys/proc.h> 41 #include <sys/tty.h> 42 #include <sys/errno.h> 43 #include <sys/buf.h> 44 45 #include <uvm/uvm_extern.h> 46 47 #include <dev/wscons/wsconsio.h> 48 #include <dev/wscons/wsdisplayvar.h> 49 #include <dev/rasops/rasops.h> 50 51 #include <machine/autoconf.h> 52 #include <machine/board.h> 53 #include <machine/cpu.h> 54 55 struct bt454 { 56 volatile u_int8_t bt_addr; /* map address register */ 57 volatile u_int8_t bt_cmap; /* colormap data register */ 58 }; 59 60 struct bt458 { 61 volatile u_int8_t bt_addr; /* map address register */ 62 unsigned :24; 63 volatile u_int8_t bt_cmap; /* colormap data register */ 64 unsigned :24; 65 volatile u_int8_t bt_ctrl; /* control register */ 66 unsigned :24; 67 volatile u_int8_t bt_omap; /* overlay (cursor) map register */ 68 unsigned :24; 69 }; 70 71 #define OMFB_RFCNT BMAP_RFCNT /* video h-origin/v-origin */ 72 #define OMFB_PLANEMASK BMAP_BMSEL /* planemask register */ 73 #define OMFB_FB_WADDR (BMAP_BMP + 8) /* common plane */ 74 #define OMFB_FB_RADDR (BMAP_BMAP0 + 8)/* plane #0 */ 75 #define OMFB_FB_PLANESIZE 0x40000 /* size of 1 plane, 2048 / 8 * 1024 */ 76 #define OMFB_ROPFUNC BMAP_FN /* ROP function code */ 77 #define OMFB_RAMDAC BMAP_PALLET2 /* Bt454/Bt458 RAMDAC */ 78 #define OMFB_SIZE (BMAP_FN0 - BMAP_BMP + PAGE_SIZE) 79 80 struct hwcmap { 81 #define CMAP_SIZE 256 82 u_int8_t r[CMAP_SIZE]; 83 u_int8_t g[CMAP_SIZE]; 84 u_int8_t b[CMAP_SIZE]; 85 }; 86 87 struct om_hwdevconfig { 88 int dc_wid; /* width of frame buffer */ 89 int dc_ht; /* height of frame buffer */ 90 int dc_depth; /* depth, bits per pixel */ 91 int dc_rowbytes; /* bytes in a FB scan line */ 92 int dc_depth_checked; /* depth is really checked or not */ 93 int dc_cmsize; /* colormap size */ 94 struct hwcmap dc_cmap; /* software copy of colormap */ 95 vaddr_t dc_videobase; /* base of flat frame buffer */ 96 struct rasops_info dc_ri; /* raster blitter variables */ 97 }; 98 99 struct omfb_softc { 100 struct device sc_dev; /* base device */ 101 struct om_hwdevconfig *sc_dc; /* device configuration */ 102 int nscreens; 103 }; 104 105 int omgetcmap(struct omfb_softc *, struct wsdisplay_cmap *); 106 int omsetcmap(struct omfb_softc *, struct wsdisplay_cmap *); 107 108 struct om_hwdevconfig omfb_console_dc; 109 void omfb_getdevconfig(paddr_t, struct om_hwdevconfig *); 110 111 /* in omrasops.c */ 112 int om_copycols(void *, int, int, int, int); 113 int om_copyrows(void *, int, int, int num); 114 int om_erasecols(void *, int, int, int, uint32_t); 115 int om_eraserows(void *, int, int, uint32_t); 116 void setup_omrasops1(struct rasops_info *); 117 void setup_omrasops4(struct rasops_info *); 118 119 struct wsscreen_descr omfb_stdscreen = { 120 "std" 121 }; 122 123 const struct wsscreen_descr *_omfb_scrlist[] = { 124 &omfb_stdscreen, 125 }; 126 127 const struct wsscreen_list omfb_screenlist = { 128 sizeof(_omfb_scrlist) / sizeof(struct wsscreen_descr *), _omfb_scrlist 129 }; 130 131 int omfbioctl(void *, u_long, caddr_t, int, struct proc *); 132 paddr_t omfbmmap(void *, off_t, int); 133 int omfb_alloc_screen(void *, const struct wsscreen_descr *, 134 void **, int *, int *, uint32_t *); 135 void omfb_free_screen(void *, void *); 136 int omfb_show_screen(void *, void *, int, void (*) (void *, int, int), 137 void *); 138 int omfb_load_font(void *, void *, struct wsdisplay_font *); 139 int omfb_list_font(void *, struct wsdisplay_font *); 140 int omfb_set_gfxmode(struct omfb_softc *, struct wsdisplay_gfx_mode *); 141 142 void omfb_set_default_cmap(struct om_hwdevconfig *); 143 void omfb_clear_framebuffer(struct om_hwdevconfig *); 144 145 const struct wsdisplay_accessops omfb_accessops = { 146 .ioctl = omfbioctl, 147 .mmap = omfbmmap, 148 .alloc_screen = omfb_alloc_screen, 149 .free_screen = omfb_free_screen, 150 .show_screen = omfb_show_screen, 151 .load_font = omfb_load_font, 152 .list_font = omfb_list_font 153 }; 154 155 int omfbmatch(struct device *, void *, void *); 156 void omfbattach(struct device *, struct device *, void *); 157 158 const struct cfattach fb_ca = { 159 sizeof(struct omfb_softc), omfbmatch, omfbattach 160 }; 161 162 struct cfdriver fb_cd = { 163 NULL, "fb", DV_DULL 164 }; 165 166 /* hardware plane bits; retrieved at boot, will be updated */ 167 extern int hwplanebits; 168 169 int omfb_console; 170 int omfb_cnattach(void); 171 172 int 173 omfbmatch(struct device *parent, void *cf, void *aux) 174 { 175 struct mainbus_attach_args *ma = aux; 176 177 if (strcmp(ma->ma_name, fb_cd.cd_name)) 178 return (0); 179 #if 0 /* XXX badaddr() bombs if no framebuffer is installed */ 180 if (badaddr((caddr_t)ma->ma_addr, 4)) 181 return (0); 182 #else 183 if (hwplanebits == 0) 184 return (0); 185 #endif 186 return (1); 187 } 188 189 void 190 omfbattach(struct device *parent, struct device *self, void *args) 191 { 192 struct omfb_softc *sc = (struct omfb_softc *)self; 193 struct wsemuldisplaydev_attach_args waa; 194 195 if (omfb_console) { 196 sc->sc_dc = &omfb_console_dc; 197 sc->nscreens = 1; 198 } else { 199 sc->sc_dc = (struct om_hwdevconfig *) 200 malloc(sizeof(struct om_hwdevconfig), M_DEVBUF, 201 M_WAITOK | M_ZERO); 202 omfb_getdevconfig(OMFB_FB_WADDR, sc->sc_dc); 203 } 204 printf(": %dx%d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht, 205 hwplanebits); 206 207 waa.console = omfb_console; 208 waa.scrdata = &omfb_screenlist; 209 waa.accessops = &omfb_accessops; 210 waa.accesscookie = sc; 211 waa.defaultscreens = 0; 212 213 config_found(self, &waa, wsemuldisplaydevprint); 214 } 215 216 /* EXPORT */ int 217 omfb_cnattach(void) 218 { 219 struct om_hwdevconfig *dc = &omfb_console_dc; 220 struct rasops_info *ri = &dc->dc_ri; 221 uint32_t defattr; 222 223 omfb_getdevconfig(OMFB_FB_WADDR, dc); 224 ri->ri_ops.pack_attr(ri, 0, 0, 0, &defattr); 225 wsdisplay_cnattach(&omfb_stdscreen, ri, 0, 0, defattr); 226 omfb_console = 1; 227 return (0); 228 } 229 230 int 231 omfbioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 232 { 233 struct omfb_softc *sc = v; 234 struct om_hwdevconfig *dc = sc->sc_dc; 235 236 switch (cmd) { 237 case WSDISPLAYIO_GTYPE: 238 *(u_int *)data = WSDISPLAY_TYPE_LUNA; 239 break; 240 241 case WSDISPLAYIO_GINFO: 242 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 243 wsd_fbip->height = dc->dc_ht; 244 wsd_fbip->width = dc->dc_wid; 245 wsd_fbip->depth = dc->dc_depth; 246 wsd_fbip->cmsize = dc->dc_cmsize; 247 #undef wsd_fbip 248 break; 249 250 case WSDISPLAYIO_LINEBYTES: 251 *(u_int *)data = dc->dc_rowbytes; 252 break; 253 254 case WSDISPLAYIO_GETCMAP: 255 return omgetcmap(sc, (struct wsdisplay_cmap *)data); 256 257 case WSDISPLAYIO_PUTCMAP: 258 return omsetcmap(sc, (struct wsdisplay_cmap *)data); 259 260 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 261 *(u_int *)data = WSDISPLAYIO_DEPTH_1; 262 break; 263 264 case WSDISPLAYIO_SETGFXMODE: 265 return omfb_set_gfxmode(sc, (struct wsdisplay_gfx_mode *)data); 266 267 case WSDISPLAYIO_SVIDEO: 268 case WSDISPLAYIO_GVIDEO: 269 break; 270 271 case WSDISPLAYIO_GCURPOS: 272 case WSDISPLAYIO_SCURPOS: 273 case WSDISPLAYIO_GCURMAX: 274 case WSDISPLAYIO_GCURSOR: 275 case WSDISPLAYIO_SCURSOR: 276 default: 277 return (-1); 278 } 279 280 return (0); 281 } 282 283 /* 284 * Return the address that would map the given device at the given 285 * offset, allowing for the given protection, or return -1 for error. 286 */ 287 288 paddr_t 289 omfbmmap(void *v, off_t offset, int prot) 290 { 291 struct omfb_softc *sc = v; 292 struct om_hwdevconfig *dc = sc->sc_dc; 293 paddr_t cookie = -1; 294 295 if ((offset & PAGE_MASK) != 0) 296 return (-1); 297 298 #if 0 /* Workaround for making Xorg mono server work */ 299 if (offset >= 0 && offset < OMFB_SIZE) 300 cookie = (paddr_t)(trunc_page(dc->dc_videobase) + offset); 301 #else 302 if (offset >= 0 && offset < dc->dc_rowbytes * dc->dc_ht * hwplanebits) 303 cookie = (paddr_t)(trunc_page(OMFB_FB_RADDR) + offset); 304 #endif 305 return cookie; 306 } 307 308 int 309 omgetcmap(struct omfb_softc *sc, struct wsdisplay_cmap *p) 310 { 311 u_int index = p->index, count = p->count; 312 unsigned int cmsize; 313 int error; 314 315 cmsize = sc->sc_dc->dc_cmsize; 316 317 /* Don't touch colormap when we use 1bpp */ 318 if (cmsize == 0) 319 return (0); 320 321 if (index >= cmsize || count > cmsize - index) 322 return (EINVAL); 323 324 error = copyout(&sc->sc_dc->dc_cmap.r[index], p->red, count); 325 if (error != 0) 326 return (error); 327 error = copyout(&sc->sc_dc->dc_cmap.g[index], p->green, count); 328 if (error != 0) 329 return (error); 330 error = copyout(&sc->sc_dc->dc_cmap.b[index], p->blue, count); 331 if (error != 0) 332 return (error); 333 334 return (0); 335 } 336 337 int 338 omsetcmap(struct omfb_softc *sc, struct wsdisplay_cmap *p) 339 { 340 struct hwcmap cmap; 341 u_int index = p->index, count = p->count; 342 unsigned int cmsize, i; 343 int error; 344 345 cmsize = sc->sc_dc->dc_cmsize; 346 347 /* Don't touch colormap when we use 1bpp */ 348 if (cmsize == 0) 349 return (0); 350 351 if (index >= cmsize || count > cmsize - index) 352 return (EINVAL); 353 354 error = copyin(p->red, &cmap.r[index], count); 355 if (error != 0) 356 return (error); 357 error = copyin(p->green, &cmap.g[index], count); 358 if (error != 0) 359 return (error); 360 error = copyin(p->blue, &cmap.b[index], count); 361 if (error != 0) 362 return (error); 363 364 memcpy(&sc->sc_dc->dc_cmap.r[index], &cmap.r[index], count); 365 memcpy(&sc->sc_dc->dc_cmap.g[index], &cmap.g[index], count); 366 memcpy(&sc->sc_dc->dc_cmap.b[index], &cmap.b[index], count); 367 368 if (hwplanebits == 4) { 369 struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC; 370 odac->bt_addr = (u_int8_t)index; 371 for (i = index; i < index + count; i++) { 372 odac->bt_cmap = sc->sc_dc->dc_cmap.r[i]; 373 odac->bt_cmap = sc->sc_dc->dc_cmap.g[i]; 374 odac->bt_cmap = sc->sc_dc->dc_cmap.b[i]; 375 } 376 } 377 else if (hwplanebits == 8) { 378 struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC; 379 ndac->bt_addr = (u_int8_t)index; 380 for (i = index; i < index + count; i++) { 381 ndac->bt_cmap = sc->sc_dc->dc_cmap.r[i]; 382 ndac->bt_cmap = sc->sc_dc->dc_cmap.g[i]; 383 ndac->bt_cmap = sc->sc_dc->dc_cmap.b[i]; 384 } 385 } 386 return (0); 387 } 388 389 void 390 omfb_getdevconfig(paddr_t paddr, struct om_hwdevconfig *dc) 391 { 392 struct rasops_info *ri; 393 union { 394 struct { short h, v; } p; 395 u_int32_t u; 396 } rfcnt; 397 398 /* 399 * If this is the first time call, check how many planes we really 400 * have. This method is for 1, 4, and 8 bpp boards, must be checked 401 * different way for 24 bpp board... 402 */ 403 if ((hwplanebits > 0) && (dc->dc_depth_checked == 0)) { 404 int i; 405 u_int32_t *max, save; 406 407 for (i = 0; i < 8; i++) { 408 max = (u_int32_t *)trunc_page(OMFB_FB_RADDR 409 + OMFB_FB_PLANESIZE * i); 410 save = *max; 411 *(volatile uint32_t *)max = 0x5a5a5a5a; 412 if (*max != 0x5a5a5a5a) 413 break; 414 *max = save; 415 } 416 hwplanebits = i; /* should be 1, 4, or 8 */ 417 418 dc->dc_depth_checked = 1; 419 } 420 421 dc->dc_wid = 1280; 422 dc->dc_ht = 1024; 423 dc->dc_depth = hwplanebits; 424 dc->dc_rowbytes = 2048 / 8; 425 dc->dc_cmsize = (hwplanebits == 1) ? 0 : 1 << hwplanebits; 426 dc->dc_videobase = paddr; 427 428 /* set default colormap */ 429 omfb_set_default_cmap(dc); 430 431 /* adjust h/v origin on screen */ 432 rfcnt.p.h = 7; 433 rfcnt.p.v = -27; 434 /* single write of 0x007ffe6 */ 435 *(volatile u_int32_t *)OMFB_RFCNT = rfcnt.u; 436 437 /* clear the screen */ 438 omfb_clear_framebuffer(dc); 439 440 /* initialize the raster */ 441 ri = &dc->dc_ri; 442 ri->ri_width = dc->dc_wid; 443 ri->ri_height = dc->dc_ht; 444 ri->ri_depth = 1; /* since planes are independently addressed */ 445 ri->ri_stride = dc->dc_rowbytes; 446 ri->ri_bits = (void *)dc->dc_videobase; 447 ri->ri_flg = RI_CENTER; 448 ri->ri_hw = dc; 449 450 rasops_init(ri, 35, 80); 451 452 ri->ri_ops.copycols = om_copycols; 453 ri->ri_ops.erasecols = om_erasecols; 454 ri->ri_ops.copyrows = om_copyrows; 455 ri->ri_ops.eraserows = om_eraserows; 456 omfb_stdscreen.ncols = ri->ri_cols; 457 omfb_stdscreen.nrows = ri->ri_rows; 458 omfb_stdscreen.textops = &ri->ri_ops; 459 omfb_stdscreen.fontwidth = ri->ri_font->fontwidth; 460 omfb_stdscreen.fontheight = ri->ri_font->fontheight; 461 462 /* set up depth-depend functions and so on */ 463 if ((hwplanebits == 4) || (hwplanebits == 8)) { 464 setup_omrasops4(ri); 465 } else { 466 setup_omrasops1(ri); 467 } 468 } 469 470 int 471 omfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 472 int *curxp, int *curyp, uint32_t *attrp) 473 { 474 struct omfb_softc *sc = v; 475 struct rasops_info *ri = &sc->sc_dc->dc_ri; 476 477 if (sc->nscreens > 0) 478 return (ENOMEM); 479 480 *cookiep = ri; 481 *curxp = 0; 482 *curyp = 0; 483 ri->ri_ops.pack_attr(ri, 0, 0, 0, attrp); 484 sc->nscreens++; 485 return (0); 486 } 487 488 void 489 omfb_free_screen(void *v, void *cookie) 490 { 491 struct omfb_softc *sc = v; 492 493 sc->nscreens--; 494 } 495 496 int 497 omfb_show_screen(void *v, void *cookie, int waitok, 498 void (*cb)(void *, int, int), void *cbarg) 499 { 500 return 0; 501 } 502 503 int 504 omfb_load_font(void *v, void *emulcookie, struct wsdisplay_font *font) 505 { 506 struct omfb_softc *sc = v; 507 struct rasops_info *ri = &sc->sc_dc->dc_ri; 508 509 return rasops_load_font(ri, emulcookie, font); 510 } 511 512 int 513 omfb_list_font(void *v, struct wsdisplay_font *font) 514 { 515 struct omfb_softc *sc = v; 516 struct rasops_info *ri = &sc->sc_dc->dc_ri; 517 518 return rasops_list_font(ri, font); 519 } 520 521 /* 522 * Change `pseudo' depth, set the default colormap, and clear frame buffer. 523 * Note: when called with depth == 0, change to the original hardware depth. 524 */ 525 int 526 omfb_set_gfxmode(struct omfb_softc *sc, struct wsdisplay_gfx_mode *wsd_gfxmode) 527 { 528 /* LUNA's fb is fixed size */ 529 if ((wsd_gfxmode->width != sc->sc_dc->dc_wid) 530 || (wsd_gfxmode->height != sc->sc_dc->dc_ht)) 531 return -1; 532 533 /* if depth == 0, set the original hardware depth */ 534 if (wsd_gfxmode->depth == 0) 535 wsd_gfxmode->depth = hwplanebits; 536 537 switch (wsd_gfxmode->depth) { 538 case 1: 539 /* all frame buffer support this */ 540 sc->sc_dc->dc_depth = 1; 541 sc->sc_dc->dc_cmsize = 0; 542 break; 543 case 4: 544 if ((hwplanebits == 4) || (hwplanebits == 8)) { 545 sc->sc_dc->dc_depth = 4; 546 sc->sc_dc->dc_cmsize = 16; 547 break; 548 } else 549 return -1; 550 case 8: 551 if (hwplanebits == 8) { 552 sc->sc_dc->dc_depth = 8; 553 sc->sc_dc->dc_cmsize = 256; 554 break; 555 } else 556 return -1; 557 default: 558 return -1; 559 } 560 561 omfb_set_default_cmap(sc->sc_dc); 562 omfb_clear_framebuffer(sc->sc_dc); 563 564 return 0; 565 } 566 567 /* 568 * Clear all planes of frame buffer 569 */ 570 void 571 omfb_clear_framebuffer(struct om_hwdevconfig *dc) 572 { 573 int i; 574 575 *(volatile u_int32_t *)OMFB_PLANEMASK = 0xff; /* all planes */ 576 ((volatile u_int32_t *)OMFB_ROPFUNC)[5] = ~0; /* ROP copy */ 577 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes / sizeof(u_int32_t); i++) 578 *((volatile u_int32_t *)dc->dc_videobase + i) = 0; 579 *(volatile u_int32_t *)OMFB_PLANEMASK = 0x01; /* plane #0 only */ 580 } 581 582 /* 583 * Set default colormap; white on black for 1bpp, ANSI 16 colors for 4/8 bpp. 584 * 585 * Note about workaround for 8bpp frame buffer: 586 * 587 * Current LUNA wscons touches only first 4 planes (plane #0-#3), but 588 * other program (e.g. mlterm-fb) can use all 8 planes on an 8bpp 589 * frame buffer. When such program exits, it may not clear all planes, 590 * so there may be some visible garbage data on the other 4 planes 591 * (plane #4-#7) when we use default 256 rasops_cmap directly. 592 * 593 * We should manage all 8 planes on LUNA, but that will be too much 594 * overhead for 16 colors wscons. So, by repeating 16 colors in 256 595 * colormap, we can ignore the values on the other 4 planes. 596 */ 597 void 598 omfb_set_default_cmap(struct om_hwdevconfig *dc) 599 { 600 int i; 601 602 if (hwplanebits == 1) { 603 struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC; 604 /* 605 * On 1bpp framebuffer, only plane P0 has framebuffer memory 606 * and other planes seems pulled up, i.e. always 1. 607 * Set white only for a palette (P0,P1,P2,P3) = (1,1,1,1). 608 */ 609 odac->bt_addr = 0; 610 for (i = 0; i < 15; i++) { 611 odac->bt_cmap = dc->dc_cmap.r[i] = 0; 612 odac->bt_cmap = dc->dc_cmap.g[i] = 0; 613 odac->bt_cmap = dc->dc_cmap.b[i] = 0; 614 } 615 /* 616 * The B/W video connector is connected to IOG of Bt454, 617 * and IOR and IOB are unused. 618 */ 619 odac->bt_cmap = dc->dc_cmap.r[15] = 0; 620 odac->bt_cmap = dc->dc_cmap.g[15] = 255; 621 odac->bt_cmap = dc->dc_cmap.b[15] = 0; 622 } else if (hwplanebits == 4) { 623 struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC; 624 625 odac->bt_addr = 0; 626 if (dc->dc_depth == 1) { 627 /* white on black */ 628 for (i = 0; i < 16; i++) { 629 u_int8_t val = i % 2 ? 255 : 0; 630 631 odac->bt_cmap = dc->dc_cmap.r[i] = val; 632 odac->bt_cmap = dc->dc_cmap.g[i] = val; 633 odac->bt_cmap = dc->dc_cmap.b[i] = val; 634 } 635 } else { 636 for (i = 0; i < 16; i++) { 637 /* Set ANSI 16 colors */ 638 odac->bt_cmap = dc->dc_cmap.r[i] 639 = rasops_cmap[i * 3]; 640 odac->bt_cmap = dc->dc_cmap.g[i] 641 = rasops_cmap[i * 3 + 1]; 642 odac->bt_cmap = dc->dc_cmap.b[i] 643 = rasops_cmap[i * 3 + 2]; 644 } 645 } 646 } else if (hwplanebits == 8) { 647 struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC; 648 649 /* 650 * Initialize the Bt458. When we write to control registers, 651 * the address is not incremented automatically. So we specify 652 * it ourselves for each control register. 653 */ 654 ndac->bt_addr = 0x04; 655 ndac->bt_ctrl = 0xff; /* all planes will be read */ 656 ndac->bt_addr = 0x05; 657 ndac->bt_ctrl = 0x00; /* all planes have non-blink */ 658 ndac->bt_addr = 0x06; 659 ndac->bt_ctrl = 0x40; /* palette enabled, ovly plane disabled */ 660 ndac->bt_addr = 0x07; 661 ndac->bt_ctrl = 0x00; /* no test mode */ 662 663 ndac->bt_addr = 0; 664 if (dc->dc_depth == 1) { 665 /* white on black */ 666 for (i = 0; i < 256; i++) { 667 u_int8_t val = i % 2 ? 255 : 0; 668 669 ndac->bt_cmap = dc->dc_cmap.r[i] = val; 670 ndac->bt_cmap = dc->dc_cmap.g[i] = val; 671 ndac->bt_cmap = dc->dc_cmap.b[i] = val; 672 } 673 } else { 674 /* 675 * Set ANSI 16 colors. On 8bpp frame buffer, repeat 676 * 16 colors in 256 colormap as described above. 677 */ 678 for (i = 0; i < 256; i++) { 679 int index = i % 16; 680 ndac->bt_cmap = dc->dc_cmap.r[i] 681 = rasops_cmap[index * 3]; 682 ndac->bt_cmap = dc->dc_cmap.g[i] 683 = rasops_cmap[index * 3 + 1]; 684 ndac->bt_cmap = dc->dc_cmap.b[i] 685 = rasops_cmap[index * 3 + 2]; 686 } 687 } 688 } 689 } 690