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