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