Home | History | Annotate | Line # | Download | only in dev
      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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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