xref: /openbsd/sys/arch/luna88k/dev/lunafb.c (revision ff5ac685)
1 /* $OpenBSD: lunafb.c,v 1.32 2023/08/05 00:34:19 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
omfbmatch(struct device * parent,void * cf,void * aux)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
omfbattach(struct device * parent,struct device * self,void * args)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
omfb_cnattach(void)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
omfbioctl(void * v,u_long cmd,caddr_t data,int flag,struct proc * p)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->stride = dc->dc_rowbytes;
247 		wsd_fbip->offset = 8;
248 		wsd_fbip->cmsize = dc->dc_cmsize;
249 #undef wsd_fbip
250 		break;
251 
252 	case WSDISPLAYIO_LINEBYTES:
253 		*(u_int *)data = dc->dc_rowbytes;
254 		break;
255 
256 	case WSDISPLAYIO_GETCMAP:
257 		return omgetcmap(sc, (struct wsdisplay_cmap *)data);
258 
259 	case WSDISPLAYIO_PUTCMAP:
260 		return omsetcmap(sc, (struct wsdisplay_cmap *)data);
261 
262 	case WSDISPLAYIO_GETSUPPORTEDDEPTH:
263 		if (dc->dc_depth == 8)
264 			*(u_int *)data =
265 			    WSDISPLAYIO_DEPTH_8 | WSDISPLAYIO_DEPTH_1;
266 		else
267 			*(u_int *)data = WSDISPLAYIO_DEPTH_1;
268 		break;
269 
270 	case WSDISPLAYIO_SETGFXMODE:
271 		return omfb_set_gfxmode(sc, (struct wsdisplay_gfx_mode *)data);
272 
273 	case WSDISPLAYIO_SVIDEO:
274 	case WSDISPLAYIO_GVIDEO:
275 		break;
276 
277 	case WSDISPLAYIO_GCURPOS:
278 	case WSDISPLAYIO_SCURPOS:
279 	case WSDISPLAYIO_GCURMAX:
280 	case WSDISPLAYIO_GCURSOR:
281 	case WSDISPLAYIO_SCURSOR:
282 	default:
283 		return (-1);
284 	}
285 
286 	return (0);
287 }
288 
289 /*
290  * Return the address that would map the given device at the given
291  * offset, allowing for the given protection, or return -1 for error.
292  */
293 
294 paddr_t
omfbmmap(void * v,off_t offset,int prot)295 omfbmmap(void *v, off_t offset, int prot)
296 {
297 	struct omfb_softc *sc = v;
298 	struct om_hwdevconfig *dc = sc->sc_dc;
299 	paddr_t cookie = -1;
300 
301 	if ((offset & PAGE_MASK) != 0)
302 		return (-1);
303 
304 #if 0	/* Workaround for making Xorg mono server work */
305 	if (offset >= 0 && offset < OMFB_SIZE)
306 		cookie = (paddr_t)(trunc_page(dc->dc_videobase) + offset);
307 #else
308 	if (offset >= 0 &&
309 	    offset < dc->dc_rowbytes * dc->dc_ht * hwplanebits + PAGE_SIZE)
310 		cookie = (paddr_t)(trunc_page(OMFB_FB_RADDR) + offset);
311 #endif
312 	return cookie;
313 }
314 
315 int
omgetcmap(struct omfb_softc * sc,struct wsdisplay_cmap * p)316 omgetcmap(struct omfb_softc *sc, struct wsdisplay_cmap *p)
317 {
318 	u_int index = p->index, count = p->count;
319 	unsigned int cmsize;
320 	int error;
321 
322 	cmsize = sc->sc_dc->dc_cmsize;
323 
324 	/* Don't touch colormap when we use 1bpp */
325 	if (cmsize == 0)
326 		return (0);
327 
328 	if (index >= cmsize || count > cmsize - index)
329 		return (EINVAL);
330 
331 	error = copyout(&sc->sc_dc->dc_cmap.r[index], p->red, count);
332 	if (error != 0)
333 		return (error);
334 	error = copyout(&sc->sc_dc->dc_cmap.g[index], p->green, count);
335 	if (error != 0)
336 		return (error);
337 	error = copyout(&sc->sc_dc->dc_cmap.b[index], p->blue, count);
338 	if (error != 0)
339 		return (error);
340 
341 	return (0);
342 }
343 
344 int
omsetcmap(struct omfb_softc * sc,struct wsdisplay_cmap * p)345 omsetcmap(struct omfb_softc *sc, struct wsdisplay_cmap *p)
346 {
347 	struct hwcmap cmap;
348 	u_int index = p->index, count = p->count;
349 	unsigned int cmsize, i;
350 	int error;
351 
352 	cmsize = sc->sc_dc->dc_cmsize;
353 
354 	/* Don't touch colormap when we use 1bpp */
355 	if (cmsize == 0)
356 		return (0);
357 
358 	if (index >= cmsize || count > cmsize - index)
359 		return (EINVAL);
360 
361 	error = copyin(p->red, &cmap.r[index], count);
362 	if (error != 0)
363 		return (error);
364 	error = copyin(p->green, &cmap.g[index], count);
365 	if (error != 0)
366 		return (error);
367 	error = copyin(p->blue, &cmap.b[index], count);
368 	if (error != 0)
369 		return (error);
370 
371 	memcpy(&sc->sc_dc->dc_cmap.r[index], &cmap.r[index], count);
372 	memcpy(&sc->sc_dc->dc_cmap.g[index], &cmap.g[index], count);
373 	memcpy(&sc->sc_dc->dc_cmap.b[index], &cmap.b[index], count);
374 
375 	if (hwplanebits == 4) {
376 		struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
377 		odac->bt_addr = (u_int8_t)index;
378 		for (i = index; i < index + count; i++) {
379 			odac->bt_cmap = sc->sc_dc->dc_cmap.r[i];
380 			odac->bt_cmap = sc->sc_dc->dc_cmap.g[i];
381 			odac->bt_cmap = sc->sc_dc->dc_cmap.b[i];
382 		}
383 	}
384 	else if (hwplanebits == 8) {
385 		struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
386 		ndac->bt_addr = (u_int8_t)index;
387 		for (i = index; i < index + count; i++) {
388 			ndac->bt_cmap = sc->sc_dc->dc_cmap.r[i];
389 			ndac->bt_cmap = sc->sc_dc->dc_cmap.g[i];
390 			ndac->bt_cmap = sc->sc_dc->dc_cmap.b[i];
391 		}
392 	}
393 	return (0);
394 }
395 
396 void
omfb_getdevconfig(paddr_t paddr,struct om_hwdevconfig * dc)397 omfb_getdevconfig(paddr_t paddr, struct om_hwdevconfig *dc)
398 {
399 	struct rasops_info *ri;
400 	union {
401 		struct { short h, v; } p;
402 		u_int32_t u;
403 	} rfcnt;
404 
405 	/*
406 	 * If this is the first time call, check how many planes we really
407 	 * have.  This method is for 1, 4, and 8 bpp boards, must be checked
408 	 * different way for 24 bpp board...
409 	 */
410 	if ((hwplanebits > 0) && (dc->dc_depth_checked == 0)) {
411 		int i;
412 		u_int32_t *max, save;
413 
414 		for (i = 0; i < 8; i++) {
415 			max = (u_int32_t *)trunc_page(OMFB_FB_RADDR
416 			    + OMFB_FB_PLANESIZE * i);
417 			save = *max;
418 			*(volatile uint32_t *)max = 0x5a5a5a5a;
419 			if (*max != 0x5a5a5a5a)
420 				break;
421 			*max = save;
422 		}
423 		hwplanebits = i;	/* should be 1, 4, or 8 */
424 
425 		dc->dc_depth_checked = 1;
426 	}
427 
428 	dc->dc_wid = 1280;
429 	dc->dc_ht = 1024;
430 	dc->dc_depth = hwplanebits;
431 	dc->dc_rowbytes = 2048 / 8;
432 	dc->dc_cmsize = (hwplanebits == 1) ? 0 : 1 << hwplanebits;
433 	dc->dc_videobase = paddr;
434 
435 	/* set default colormap */
436 	omfb_set_default_cmap(dc);
437 
438 	/* adjust h/v origin on screen */
439 	rfcnt.p.h = 7;
440 	rfcnt.p.v = -27;
441 	/* single write of 0x007ffe6 */
442 	*(volatile u_int32_t *)OMFB_RFCNT = rfcnt.u;
443 
444 	/* clear the screen */
445 	omfb_clear_framebuffer(dc);
446 
447 	/* initialize the raster */
448 	ri = &dc->dc_ri;
449 	ri->ri_width = dc->dc_wid;
450 	ri->ri_height = dc->dc_ht;
451 	ri->ri_depth = 1;	/* since planes are independently addressed */
452 	ri->ri_stride = dc->dc_rowbytes;
453 	ri->ri_bits = (void *)dc->dc_videobase;
454 	ri->ri_flg = RI_CENTER;
455 	ri->ri_hw = dc;
456 
457 	rasops_init(ri, 35, 80);
458 
459 	ri->ri_ops.copycols = om_copycols;
460 	ri->ri_ops.erasecols = om_erasecols;
461 	ri->ri_ops.copyrows = om_copyrows;
462 	ri->ri_ops.eraserows = om_eraserows;
463 	omfb_stdscreen.ncols = ri->ri_cols;
464 	omfb_stdscreen.nrows = ri->ri_rows;
465 	omfb_stdscreen.textops = &ri->ri_ops;
466 	omfb_stdscreen.fontwidth = ri->ri_font->fontwidth;
467 	omfb_stdscreen.fontheight = ri->ri_font->fontheight;
468 
469 	/* set up depth-depend functions and so on */
470 	if ((hwplanebits == 4) || (hwplanebits == 8)) {
471 		setup_omrasops4(ri);
472 	} else {
473 		setup_omrasops1(ri);
474 	}
475 }
476 
477 int
omfb_alloc_screen(void * v,const struct wsscreen_descr * type,void ** cookiep,int * curxp,int * curyp,uint32_t * attrp)478 omfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
479     int *curxp, int *curyp, uint32_t *attrp)
480 {
481 	struct omfb_softc *sc = v;
482 	struct rasops_info *ri = &sc->sc_dc->dc_ri;
483 
484 	if (sc->nscreens > 0)
485 		return (ENOMEM);
486 
487 	*cookiep = ri;
488 	*curxp = 0;
489 	*curyp = 0;
490 	ri->ri_ops.pack_attr(ri, 0, 0, 0, attrp);
491 	sc->nscreens++;
492 	return (0);
493 }
494 
495 void
omfb_free_screen(void * v,void * cookie)496 omfb_free_screen(void *v, void *cookie)
497 {
498 	struct omfb_softc *sc = v;
499 
500 	sc->nscreens--;
501 }
502 
503 int
omfb_show_screen(void * v,void * cookie,int waitok,void (* cb)(void *,int,int),void * cbarg)504 omfb_show_screen(void *v, void *cookie, int waitok,
505     void (*cb)(void *, int, int), void *cbarg)
506 {
507 	return 0;
508 }
509 
510 int
omfb_load_font(void * v,void * emulcookie,struct wsdisplay_font * font)511 omfb_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
512 {
513 	struct omfb_softc *sc = v;
514 	struct rasops_info *ri = &sc->sc_dc->dc_ri;
515 
516 	return rasops_load_font(ri, emulcookie, font);
517 }
518 
519 int
omfb_list_font(void * v,struct wsdisplay_font * font)520 omfb_list_font(void *v, struct wsdisplay_font *font)
521 {
522 	struct omfb_softc *sc = v;
523 	struct rasops_info *ri = &sc->sc_dc->dc_ri;
524 
525 	return rasops_list_font(ri, font);
526 }
527 
528 /*
529  * Change `pseudo' depth, set the default colormap, and clear frame buffer.
530  * Note: when called with depth == 0, change to the original hardware depth.
531  */
532 int
omfb_set_gfxmode(struct omfb_softc * sc,struct wsdisplay_gfx_mode * wsd_gfxmode)533 omfb_set_gfxmode(struct omfb_softc *sc, struct wsdisplay_gfx_mode *wsd_gfxmode)
534 {
535 	/* LUNA's fb is fixed size */
536 	if ((wsd_gfxmode->width != sc->sc_dc->dc_wid)
537 	    || (wsd_gfxmode->height != sc->sc_dc->dc_ht))
538 		return -1;
539 
540 	/* if depth == 0, set the original hardware depth */
541 	if (wsd_gfxmode->depth == 0)
542 		wsd_gfxmode->depth = hwplanebits;
543 
544 	switch (wsd_gfxmode->depth) {
545 	case 1:
546 		/* all frame buffer support this */
547 		sc->sc_dc->dc_depth = 1;
548 		sc->sc_dc->dc_cmsize = 0;
549 		setup_omrasops1(&sc->sc_dc->dc_ri);
550 		break;
551 	case 4:
552 		if ((hwplanebits == 4) || (hwplanebits == 8)) {
553 			sc->sc_dc->dc_depth = 4;
554 			sc->sc_dc->dc_cmsize = 16;
555 			setup_omrasops4(&sc->sc_dc->dc_ri);
556 			break;
557 		} else
558 			return -1;
559 	case 8:
560 		if (hwplanebits == 8) {
561 			sc->sc_dc->dc_depth = 8;
562 			sc->sc_dc->dc_cmsize = 256;
563 			setup_omrasops4(&sc->sc_dc->dc_ri);
564 			break;
565 		} else
566 			return -1;
567 	default:
568 		return -1;
569 	}
570 
571 	omfb_set_default_cmap(sc->sc_dc);
572 	omfb_clear_framebuffer(sc->sc_dc);
573 
574 	return 0;
575 }
576 
577 /*
578  * Clear all planes of frame buffer
579  */
580 void
omfb_clear_framebuffer(struct om_hwdevconfig * dc)581 omfb_clear_framebuffer(struct om_hwdevconfig *dc)
582 {
583 	int i;
584 
585 	*(volatile u_int32_t *)OMFB_PLANEMASK = 0xff;	/* all planes */
586 	((volatile u_int32_t *)OMFB_ROPFUNC)[5] = ~0;	/* ROP copy */
587 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes / sizeof(u_int32_t); i++)
588 		*((volatile u_int32_t *)dc->dc_videobase + i) = 0;
589 	*(volatile u_int32_t *)OMFB_PLANEMASK = 0x01;	/* plane #0 only */
590 }
591 
592 /*
593  * Set default colormap; white on black for 1bpp, ANSI 16 colors for 4/8 bpp.
594  *
595  * Note about workaround for 8bpp frame buffer:
596  *
597  * Current LUNA wscons touches only first 4 planes (plane #0-#3), but
598  * other program (e.g. mlterm-fb) can use all 8 planes on an 8bpp
599  * frame buffer.  When such program exits, it may not clear all planes,
600  * so there may be some visible garbage data on the other 4 planes
601  * (plane #4-#7) when we use default 256 rasops_cmap directly.
602  *
603  * We should manage all 8 planes on LUNA, but that will be too much
604  * overhead for 16 colors wscons.  So, by repeating 16 colors in 256
605  * colormap, we can ignore the values on the other 4 planes.
606  */
607 void
omfb_set_default_cmap(struct om_hwdevconfig * dc)608 omfb_set_default_cmap(struct om_hwdevconfig *dc)
609 {
610 	int i;
611 
612 	if (hwplanebits == 1) {
613 		struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
614 		/*
615 		 * On 1bpp framebuffer, only plane P0 has framebuffer memory
616 		 * and other planes seems pulled up, i.e. always 1.
617 		 * Set white only for a palette (P0,P1,P2,P3) = (1,1,1,1).
618 		 */
619 		odac->bt_addr = 0;
620 		for (i = 0; i < 15; i++) {
621 			odac->bt_cmap = dc->dc_cmap.r[i] = 0;
622 			odac->bt_cmap = dc->dc_cmap.g[i] = 0;
623 			odac->bt_cmap = dc->dc_cmap.b[i] = 0;
624 		}
625 		/*
626 		 * The B/W video connector is connected to IOG of Bt454,
627 		 * and IOR and IOB are unused.
628 		 */
629 		odac->bt_cmap = dc->dc_cmap.r[15] = 0;
630 		odac->bt_cmap = dc->dc_cmap.g[15] = 255;
631 		odac->bt_cmap = dc->dc_cmap.b[15] = 0;
632 	} else if (hwplanebits == 4) {
633 		struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
634 
635 		odac->bt_addr = 0;
636 		if (dc->dc_depth == 1) {
637 			/* white on black */
638 			for (i = 0; i < 16; i++) {
639 				u_int8_t val = i % 2 ? 255 : 0;
640 
641 				odac->bt_cmap = dc->dc_cmap.r[i] = val;
642 				odac->bt_cmap = dc->dc_cmap.g[i] = val;
643 				odac->bt_cmap = dc->dc_cmap.b[i] = val;
644 			}
645 		} else {
646 			for (i = 0; i < 16; i++) {
647 			/* Set ANSI 16 colors */
648 				odac->bt_cmap = dc->dc_cmap.r[i]
649 				    = rasops_cmap[i * 3];
650 				odac->bt_cmap = dc->dc_cmap.g[i]
651 				    = rasops_cmap[i * 3 + 1];
652 				odac->bt_cmap = dc->dc_cmap.b[i]
653 				    = rasops_cmap[i * 3 + 2];
654 			}
655 		}
656 	} else if (hwplanebits == 8) {
657 		struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
658 
659 		/*
660 		 * Initialize the Bt458.  When we write to control registers,
661 		 * the address is not incremented automatically. So we specify
662 		 * it ourselves for each control register.
663 		 */
664 		ndac->bt_addr = 0x04;
665 		ndac->bt_ctrl = 0xff; /* all planes will be read */
666 		ndac->bt_addr = 0x05;
667 		ndac->bt_ctrl = 0x00; /* all planes have non-blink */
668 		ndac->bt_addr = 0x06;
669 		ndac->bt_ctrl = 0x40; /* palette enabled, ovly plane disabled */
670 		ndac->bt_addr = 0x07;
671 		ndac->bt_ctrl = 0x00; /* no test mode */
672 
673 		ndac->bt_addr = 0;
674 		if (dc->dc_depth == 1) {
675 			/* white on black */
676 			for (i = 0; i < 256; i++) {
677 				u_int8_t val = i % 2 ? 255 : 0;
678 
679 				ndac->bt_cmap = dc->dc_cmap.r[i] = val;
680 				ndac->bt_cmap = dc->dc_cmap.g[i] = val;
681 				ndac->bt_cmap = dc->dc_cmap.b[i] = val;
682 			}
683 		} else {
684 			/*
685 			 * Set ANSI 16 colors.  On 8bpp frame buffer, repeat
686 			 * 16 colors in 256 colormap as described above.
687 			 */
688 			for (i = 0; i < 256; i++) {
689 				int index = i % 16;
690 				ndac->bt_cmap = dc->dc_cmap.r[i]
691 				    = rasops_cmap[index * 3];
692 				ndac->bt_cmap = dc->dc_cmap.g[i]
693 				    = rasops_cmap[index * 3 + 1];
694 				ndac->bt_cmap = dc->dc_cmap.b[i]
695 				    = rasops_cmap[index * 3 + 2];
696 			}
697 		}
698 	}
699 }
700