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