xref: /netbsd-src/sys/arch/newsmips/dev/fb.c (revision 666894a5f86743977297b3f28b6e30b1a78da7cb)
1 /*	$NetBSD: fb.c,v 1.34 2023/11/04 15:30:52 tsutsui Exp $	*/
2 
3 /*-
4  * Copyright (c) 2000 Tsubai Masanari.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 /*-
29  * Copyright (c) 2023 Izumi Tsutsui.  All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  * 1. Redistributions of source code must retain the above copyright
35  *    notice, this list of conditions and the following disclaimer.
36  * 2. Redistributions in binary form must reproduce the above copyright
37  *    notice, this list of conditions and the following disclaimer in the
38  *    documentation and/or other materials provided with the distribution.
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
41  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
44  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
46  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
47  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
48  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
49  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50  */
51 
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: fb.c,v 1.34 2023/11/04 15:30:52 tsutsui Exp $");
54 
55 #include <sys/param.h>
56 #include <sys/device.h>
57 #include <sys/ioctl.h>
58 #include <sys/kmem.h>
59 #include <sys/systm.h>
60 
61 #include <uvm/uvm_extern.h>
62 
63 #include <machine/adrsmap.h>
64 
65 #include <newsmips/dev/hbvar.h>
66 
67 #include <dev/wscons/wsconsio.h>
68 #include <dev/wscons/wsdisplayvar.h>
69 #include <dev/rasops/rasops.h>
70 
71 struct fb_devconfig {
72 	uint8_t *dc_fbbase;		/* VRAM base address */
73 	struct rasops_info dc_ri;
74 	int dc_model;
75 #define NWB253	0
76 #define LCDM	1
77 	int dc_displayid;
78 #define NWP512	0
79 #define NWP518	1
80 #define NWE501	2
81 	int dc_size;
82 };
83 
84 struct fb_softc {
85 	device_t sc_dev;
86 	struct fb_devconfig *sc_dc;
87 	int sc_nscreens;
88 };
89 
90 static int fb_match(device_t, cfdata_t, void *);
91 static void fb_attach(device_t, device_t, void *);
92 
93 static int fb_common_init(struct fb_devconfig *);
94 static int fb_is_console(void);
95 
96 static int fb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
97 static paddr_t fb_mmap(void *, void *, off_t, int);
98 static int fb_alloc_screen(void *, const struct wsscreen_descr *, void **,
99     int *, int *, long *);
100 static void fb_free_screen(void *, void *);
101 static int fb_show_screen(void *, void *, int, void (*)(void *, int, int),
102     void *);
103 
104 void fb_cnattach(void);
105 
106 static int fb_set_state(struct fb_softc *, int);
107 
108 static bool fb253_probe(void);
109 static bool fblcdm_probe(void);
110 static bool fb_probe_model(struct fb_devconfig *);
111 static void fb_init(struct fb_devconfig *);
112 static void fb253_init(void);
113 static void fblcdm_init(void);
114 
115 CFATTACH_DECL_NEW(fb, sizeof(struct fb_softc),
116     fb_match, fb_attach, NULL, NULL);
117 
118 static struct fb_devconfig fb_console_dc;
119 
120 static struct wsdisplay_accessops fb_accessops = {
121 	.ioctl        = fb_ioctl,
122 	.mmap         = fb_mmap,
123 	.alloc_screen = fb_alloc_screen,
124 	.free_screen  = fb_free_screen,
125 	.show_screen  = fb_show_screen,
126 	.load_font    = NULL
127 };
128 
129 static struct wsscreen_descr fb_stdscreen = {
130 	.name = "std",
131 	.ncols = 0,
132 	.nrows = 0,
133 	.textops = NULL,
134 	.fontwidth = 0,
135 	.fontheight = 0,
136 	.capabilities = WSSCREEN_REVERSE
137 };
138 
139 static const struct wsscreen_descr *fb_scrlist[] = {
140 	&fb_stdscreen
141 };
142 
143 static struct wsscreen_list fb_screenlist = {
144 	.nscreens = __arraycount(fb_scrlist),
145 	.screens  = fb_scrlist
146 };
147 
148 #define NWB253_VRAM   0x88000000
149 #define NWB253_CTLREG ((uint16_t *)0xb8ff0000)
150 #define NWB253_CRTREG ((uint16_t *)0xb8fe0000)
151 
152 static const char *nwb253dispname[8] = {
153 	[NWP512] = "NWB-512",
154 	[NWP518] = "NWB-518",
155 	[NWE501] = "NWE-501"
156 }; /* XXX ? */
157 
158 #define LCDM_VRAM	0x90200000
159 #define LCDM_PORT	((uint32_t *)0xb0000000)
160 #define LCDM_DIMMER	((uint32_t *)0xb0100000)
161 #define LCDM_DIMMER_ON	0xf0
162 #define LCDM_DIMMER_OFF	0xf1
163 #define LCDM_CTRL	((uint8_t *)0xbff50000)	/* XXX no macro in 4.4BSD */
164 #define LCDM_CRTC	((uint8_t *)0xbff60000)
165 
166 static int
fb_match(device_t parent,cfdata_t cf,void * aux)167 fb_match(device_t parent, cfdata_t cf, void *aux)
168 {
169 	struct hb_attach_args *ha = aux;
170 
171 	if (strcmp(ha->ha_name, "fb") != 0)
172 		return 0;
173 
174 	if (fb253_probe() && ha->ha_addr == NWB253_VRAM)
175 		return 1;
176 	if (fblcdm_probe() && ha->ha_addr == LCDM_VRAM)
177 		return 1;
178 
179 	return 0;
180 }
181 
182 static void
fb_attach(device_t parent,device_t self,void * aux)183 fb_attach(device_t parent, device_t self, void *aux)
184 {
185 	struct fb_softc *sc = device_private(self);
186 	struct wsemuldisplaydev_attach_args waa;
187 	struct fb_devconfig *dc;
188 	struct rasops_info *ri;
189 	int console;
190 	const char *devname;
191 
192 	sc->sc_dev = self;
193 
194 	console = fb_is_console();
195 
196 	if (console) {
197 		dc = &fb_console_dc;
198 		ri = &dc->dc_ri;
199 		ri->ri_flg &= ~RI_NO_AUTO;
200 		sc->sc_nscreens = 1;
201 	} else {
202 		dc = kmem_zalloc(sizeof(struct fb_devconfig), KM_SLEEP);
203 
204 		fb_probe_model(dc);
205 		fb_common_init(dc);
206 		ri = &dc->dc_ri;
207 
208 		/* clear screen */
209 		(*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, 0);
210 
211 		fb_init(dc);
212 	}
213 	sc->sc_dc = dc;
214 
215 	switch (dc->dc_model) {
216 	case NWB253:
217 		devname = nwb253dispname[dc->dc_displayid];
218 		break;
219 	case LCDM:
220 		devname = "LCD-MONO";
221 		break;
222 	default:
223 		/* should not be here */
224 		devname = "unknown";
225 		break;
226 	}
227 	aprint_normal(": %s, %d x %d, %dbpp\n", devname,
228 	    ri->ri_width, ri->ri_height, ri->ri_depth);
229 
230 	waa.console = console;
231 	waa.scrdata = &fb_screenlist;
232 	waa.accessops = &fb_accessops;
233 	waa.accesscookie = sc;
234 
235 	config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
236 }
237 
238 static bool
fb253_probe(void)239 fb253_probe(void)
240 {
241 
242 	if (hb_badaddr(NWB253_CTLREG, 2) || hb_badaddr(NWB253_CRTREG, 2))
243 		return false;
244 	if ((*(volatile uint16_t *)NWB253_CTLREG & 7) != 4)
245 		return false;
246 
247 	return true;
248 }
249 
250 static bool
fblcdm_probe(void)251 fblcdm_probe(void)
252 {
253 
254 	if (hb_badaddr(LCDM_CTRL, 1))
255 		return false;
256 	if (*(volatile uint8_t *)LCDM_CTRL != 0xff)
257 		return false;
258 
259 	return true;
260 }
261 
262 static bool
fb_probe_model(struct fb_devconfig * dc)263 fb_probe_model(struct fb_devconfig *dc)
264 {
265 
266 	if (fb253_probe()) {
267 		volatile uint16_t *ctlreg = NWB253_CTLREG;
268 
269 		dc->dc_model = NWB253;
270 		dc->dc_displayid = (*ctlreg >> 8) & 0xf;
271 		return true;
272 	}
273 	if (fblcdm_probe()) {
274 		dc->dc_model = LCDM;
275 		dc->dc_displayid = 0;	/* no variant */
276 		return true;
277 	}
278 
279 	return false;
280 }
281 
282 static int
fb_common_init(struct fb_devconfig * dc)283 fb_common_init(struct fb_devconfig *dc)
284 {
285 	struct rasops_info *ri = &dc->dc_ri;
286 	int width, height, stride, xoff, yoff, cols, rows;
287 
288 	switch (dc->dc_model) {
289 	case NWB253:
290 		dc->dc_fbbase = (uint8_t *)NWB253_VRAM;
291 
292 		switch (dc->dc_displayid) {
293 		case NWP512:
294 			width = 816;
295 			height = 1024;
296 			break;
297 		case NWP518:
298 		case NWE501:
299 		default:
300 			width = 1024;
301 			height = 768;
302 			break;
303 		}
304 		stride = 2048 / 8;
305 		dc->dc_size = stride * 2048;
306 		break;
307 
308 	case LCDM:
309 		dc->dc_fbbase = (uint8_t *)LCDM_VRAM;
310 		width = 1120;
311 		height = 780;
312 		stride = width / 8;
313 		dc->dc_size = stride * height;
314 		break;
315 
316 	default:
317 		panic("fb: no valid framebuffer");
318 	}
319 
320 	/* initialize rasops */
321 
322 	ri->ri_width = width;
323 	ri->ri_height = height;
324 	ri->ri_depth = 1;
325 	ri->ri_stride = stride;
326 	ri->ri_bits = dc->dc_fbbase;
327 	ri->ri_flg = RI_FULLCLEAR;
328 	if (dc == &fb_console_dc)
329 		ri->ri_flg |= RI_NO_AUTO;
330 
331 	rasops_init(ri, 24, 80);
332 	rows = (height - 2) / ri->ri_font->fontheight;
333 	cols = ((width - 2) / ri->ri_font->fontwidth) & ~7;
334 	xoff = ((width - cols * ri->ri_font->fontwidth) / 2 / 8) & ~3;
335 	yoff = (height - rows * ri->ri_font->fontheight) / 2;
336 	rasops_reconfig(ri, rows, cols);
337 
338 	ri->ri_xorigin = xoff;
339 	ri->ri_yorigin = yoff;
340 	ri->ri_bits = dc->dc_fbbase + xoff + ri->ri_stride * yoff;
341 
342 	fb_stdscreen.nrows = ri->ri_rows;
343 	fb_stdscreen.ncols = ri->ri_cols;
344 	fb_stdscreen.textops = &ri->ri_ops;
345 	fb_stdscreen.capabilities = ri->ri_caps;
346 
347 	return 0;
348 }
349 
350 static int
fb_is_console(void)351 fb_is_console(void)
352 {
353 	volatile u_int *dipsw = (void *)DIP_SWITCH;
354 
355 	if (*dipsw & 7)					/* XXX right? */
356 		return 1;
357 
358 	return 0;
359 }
360 
361 static int
fb_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct lwp * l)362 fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
363 {
364 	struct fb_softc *sc = v;
365 	struct fb_devconfig *dc = sc->sc_dc;
366 	struct wsdisplay_fbinfo *wdf;
367 
368 	switch (cmd) {
369 	case WSDISPLAYIO_GTYPE:
370 		*(int *)data = WSDISPLAY_TYPE_UNKNOWN;	/* XXX */
371 		return 0;
372 
373 	case WSDISPLAYIO_GINFO:
374 		wdf = (void *)data;
375 		wdf->height = dc->dc_ri.ri_height;
376 		wdf->width = dc->dc_ri.ri_width;
377 		wdf->depth = dc->dc_ri.ri_depth;
378 		wdf->cmsize = 0;
379 		return 0;
380 
381 	case WSDISPLAYIO_LINEBYTES:
382 		*(u_int *)data = dc->dc_ri.ri_stride;
383 		return 0;
384 
385 	case WSDISPLAYIO_SVIDEO:
386 		return fb_set_state(sc, *(int *)data);
387 
388 	case WSDISPLAYIO_GETCMAP:
389 	case WSDISPLAYIO_PUTCMAP:
390 		break;
391 	}
392 	return EPASSTHROUGH;
393 }
394 
395 static int
fb_set_state(struct fb_softc * sc,int state)396 fb_set_state(struct fb_softc *sc, int state)
397 {
398 	struct fb_devconfig *dc = sc->sc_dc;
399 	volatile uint16_t *ctlreg;
400 	volatile uint32_t *dimmerreg;
401 
402 	if (state != WSDISPLAYIO_VIDEO_OFF && state != WSDISPLAYIO_VIDEO_ON)
403 		return EINVAL;
404 
405 	switch (dc->dc_model) {
406 	case NWB253:
407 		if (state == WSDISPLAYIO_VIDEO_OFF) {
408 			ctlreg = NWB253_CTLREG;
409 			*ctlreg = 0;			/* stop crtc */
410 		} else {
411 			fb253_init();
412 		}
413 		break;
414 	case LCDM:
415 		dimmerreg = LCDM_DIMMER;
416 		if (state == WSDISPLAYIO_VIDEO_OFF) {
417 			*dimmerreg = LCDM_DIMMER_OFF;
418 		} else {
419 			*dimmerreg = LCDM_DIMMER_ON;
420 		}
421 		break;
422 	default:
423 		/* should not be here */
424 		break;
425 	}
426 	return 0;
427 }
428 
429 static paddr_t
fb_mmap(void * v,void * vs,off_t offset,int prot)430 fb_mmap(void *v, void *vs, off_t offset, int prot)
431 {
432 	struct fb_softc *sc = v;
433 	struct fb_devconfig *dc = sc->sc_dc;
434 
435 	if (offset >= dc->dc_size || offset < 0)
436 		return -1;
437 
438 	return mips_btop((int)dc->dc_fbbase + offset);
439 }
440 
441 static int
fb_alloc_screen(void * v,const struct wsscreen_descr * scrdesc,void ** cookiep,int * ccolp,int * crowp,long * attrp)442 fb_alloc_screen(void *v, const struct wsscreen_descr *scrdesc, void **cookiep,
443     int *ccolp, int *crowp, long *attrp)
444 {
445 	struct fb_softc *sc = v;
446 	struct rasops_info *ri = &sc->sc_dc->dc_ri;
447 	long defattr;
448 
449 	if (sc->sc_nscreens > 0)
450 		return ENOMEM;
451 
452 	*cookiep = ri;
453 	*ccolp = *crowp = 0;
454 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
455 	*attrp = defattr;
456 	sc->sc_nscreens++;
457 
458 	return 0;
459 }
460 
461 static void
fb_free_screen(void * v,void * cookie)462 fb_free_screen(void *v, void *cookie)
463 {
464 	struct fb_softc *sc = v;
465 
466 	if (sc->sc_dc == &fb_console_dc)
467 		panic("%s: console", __func__);
468 
469 	sc->sc_nscreens--;
470 }
471 
472 static int
fb_show_screen(void * v,void * cookie,int waitok,void (* cb)(void *,int,int),void * cbarg)473 fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
474     void *cbarg)
475 {
476 
477 	return 0;
478 }
479 
480 void
fb_cnattach(void)481 fb_cnattach(void)
482 {
483 	struct fb_devconfig *dc = &fb_console_dc;
484 	struct rasops_info *ri = &dc->dc_ri;
485 	long defattr;
486 
487 	if (!fb_is_console())
488 		return;
489 
490 	if (!fb_probe_model(dc))
491 		return;
492 
493 	fb_common_init(dc);
494 	fb_init(dc);
495 
496 	/*
497 	 * Wait CRTC output or LCD backlight become settled
498 	 * before starting to print kernel greeting messages.
499 	 */
500 	delay(500 * 1000);
501 
502 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
503 	wsdisplay_cnattach(&fb_stdscreen, ri, 0, ri->ri_rows - 1, defattr);
504 }
505 
506 static void
fb_init(struct fb_devconfig * dc)507 fb_init(struct fb_devconfig *dc)
508 {
509 
510 	switch (dc->dc_model) {
511 	case NWB253:
512 		fb253_init();
513 		break;
514 	case LCDM:
515 		fblcdm_init();
516 		break;
517 	default:
518 		/* should not be here */
519 		break;
520 	}
521 }
522 
523 static const uint8_t
524 nwp512_data1[] = {
525 	0x00, 0x44,
526 	0x01, 0x33,
527 	0x02, 0x3c,
528 	0x03, 0x38,
529 	0x04, 0x84,
530 	0x05, 0x03,
531 	0x06, 0x80,
532 	0x07, 0x80,
533 	0x08, 0x10,
534 	0x09, 0x07,
535 	0x0a, 0x20,
536 	0x0c, 0x00,
537 	0x0d, 0x00,
538 	0x1b, 0x03
539 };
540 
541 static const uint8_t
542 nwp512_data2[] = {
543 	0x1e, 0x08,
544 	0x20, 0x08,
545 	0x21, 0x0d
546 };
547 
548 static const uint8_t
549 nwp518_data1[] = {
550 	0x00, 0x52,
551 	0x01, 0x40,
552 	0x02, 0x4a,
553 	0x03, 0x49,
554 	0x04, 0x63,
555 	0x05, 0x02,
556 	0x06, 0x60,
557 	0x07, 0x60,
558 	0x08, 0x10,
559 	0x09, 0x07,
560 	0x0a, 0x20,
561 	0x0c, 0x00,
562 	0x0d, 0x00,
563 	0x1b, 0x04
564 };
565 
566 static const uint8_t
567 nwp518_data2[] = {
568 	0x1e, 0x08,
569 	0x20, 0x00,
570 	0x21, 0x00
571 };
572 
573 static const uint8_t
574 nwe501_data1[] = {
575 	0x00, 0x4b,
576 	0x01, 0x40,
577 	0x02, 0x4a,
578 	0x03, 0x43,
579 	0x04, 0x64,
580 	0x05, 0x02,
581 	0x06, 0x60,
582 	0x07, 0x60,
583 	0x08, 0x10,
584 	0x09, 0x07,
585 	0x0a, 0x20,
586 	0x0c, 0x00,
587 	0x0d, 0x00,
588 	0x1b, 0x04
589 };
590 
591 static const uint8_t
592 nwe501_data2[] = {
593 	0x1e, 0x08,
594 	0x20, 0x00,
595 	0x21, 0x00
596 };
597 
598 static const uint8_t
599 *crtc_data[3][2] = {
600 	{ nwp512_data1, nwp512_data2 },
601 	{ nwp518_data1, nwp518_data2 },
602 	{ nwe501_data1, nwe501_data2 }
603 };
604 
605 static void
fb253_init(void)606 fb253_init(void)
607 {
608 	volatile uint16_t *ctlreg = NWB253_CTLREG;
609 	volatile uint16_t *crtreg = NWB253_CRTREG;
610 	int id = (*ctlreg >> 8) & 0xf;
611 	const uint8_t *p;
612 	int i;
613 
614 	*ctlreg = 0;			/* stop crtc */
615 	delay(10);
616 
617 	/* initialize crtc without R3{0,1,2} */
618 	p = crtc_data[id][0];
619 	for (i = 0; i < 28; i++) {
620 		*crtreg++ = *p++;
621 		delay(10);
622 	}
623 
624 	*ctlreg = 0x02;			/* start crtc */
625 	delay(10);
626 
627 	/* set crtc control reg */
628 	p = crtc_data[id][1];
629 	for (i = 0; i < 6; i++) {
630 		*crtreg++ = *p++;
631 		delay(10);
632 	}
633 }
634 
635 static const uint8_t lcdcrtc_data[] = {
636 	 0, 47,
637 	 1, 35,
638 	 9,  0,
639 	10,  0,
640 	11,  0,
641 	12,  0,
642 	13,  0,
643 	14,  0,
644 	15,  0,
645 	18, 35,
646 	19, 0x01,
647 	20, 0x85,
648 	21,  0,
649 	22, 0x10
650 };
651 
652 static void
fblcdm_init(void)653 fblcdm_init(void)
654 {
655 	volatile uint8_t *crtcreg = LCDM_CRTC;
656 	volatile uint32_t *portreg = LCDM_PORT;
657 	volatile uint32_t *dimmerreg = LCDM_DIMMER;
658 	int i;
659 
660 	/* initialize crtc */
661 	for (i = 0; i < 28; i++) {
662 		*crtcreg++ = lcdcrtc_data[i];
663 		delay(10);
664 	}
665 
666 	delay(1000);
667 	*portreg = 1;
668 	*dimmerreg = LCDM_DIMMER_ON;
669 }
670 
671 #if 0
672 static struct wsdisplay_font newsrom8x16;
673 static struct wsdisplay_font newsrom12x24;
674 static uint8_t fontarea16[96][32];
675 static uint8_t fontarea24[96][96];
676 
677 void
678 initfont(struct rasops_info *ri)
679 {
680 	int c, x;
681 
682 	for (c = 0; c < 96; c++) {
683 		x = ((c & 0x1f) | ((c & 0xe0) << 2)) << 7;
684 		memcpy(fontarea16 + c, (uint8_t *)0xb8e00000 + x + 96, 32);
685 		memcpy(fontarea24 + c, (uint8_t *)0xb8e00000 + x, 96);
686 	}
687 
688 	newsrom8x16.name = "rom8x16";
689 	newsrom8x16.firstchar = 32;
690 	newsrom8x16.numchars = 96;
691 	newsrom8x16.encoding = WSDISPLAY_FONTENC_ISO;
692 	newsrom8x16.fontwidth = 8;
693 	newsrom8x16.fontheight = 16;
694 	newsrom8x16.stride = 2;
695 	newsrom8x16.bitorder = WSDISPLAY_FONTORDER_L2R;
696 	newsrom8x16.byteorder = WSDISPLAY_FONTORDER_L2R;
697 	newsrom8x16.data = fontarea16;
698 
699 	newsrom12x24.name = "rom12x24";
700 	newsrom12x24.firstchar = 32;
701 	newsrom12x24.numchars = 96;
702 	newsrom12x24.encoding = WSDISPLAY_FONTENC_ISO;
703 	newsrom12x24.fontwidth = 12;
704 	newsrom12x24.fontheight = 24;
705 	newsrom12x24.stride = 4;
706 	newsrom12x24.bitorder = WSDISPLAY_FONTORDER_L2R;
707 	newsrom12x24.byteorder = WSDISPLAY_FONTORDER_L2R;
708 	newsrom12x24.data = fontarea24;
709 
710 	ri->ri_font = &newsrom8x16;
711 	ri->ri_font = &newsrom12x24;
712 	ri->ri_wsfcookie = -1;		/* not using wsfont */
713 }
714 #endif
715