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