xref: /openbsd-src/sys/arch/luna88k/dev/lunafb.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
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