Home | History | Annotate | Line # | Download | only in dev
fb.c revision 1.29
      1 /*	$NetBSD: fb.c,v 1.29 2021/08/07 16:19:01 thorpej 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 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: fb.c,v 1.29 2021/08/07 16:19:01 thorpej Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/device.h>
     34 #include <sys/ioctl.h>
     35 #include <sys/kmem.h>
     36 #include <sys/systm.h>
     37 
     38 #include <uvm/uvm_extern.h>
     39 
     40 #include <machine/adrsmap.h>
     41 
     42 #include <newsmips/dev/hbvar.h>
     43 
     44 #include <dev/wscons/wsconsio.h>
     45 #include <dev/wscons/wsdisplayvar.h>
     46 #include <dev/rasops/rasops.h>
     47 
     48 struct fb_devconfig {
     49 	u_char *dc_fbbase;		/* VRAM base address */
     50 	struct rasops_info dc_ri;
     51 };
     52 
     53 struct fb_softc {
     54 	device_t sc_dev;
     55 	struct fb_devconfig *sc_dc;
     56 	int sc_nscreens;
     57 };
     58 
     59 int fb_match(device_t, cfdata_t, void *);
     60 void fb_attach(device_t, device_t, void *);
     61 
     62 int fb_common_init(struct fb_devconfig *);
     63 int fb_is_console(void);
     64 
     65 int fb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
     66 paddr_t fb_mmap(void *, void *, off_t, int);
     67 int fb_alloc_screen(void *, const struct wsscreen_descr *, void **, int *,
     68     int *, long *);
     69 void fb_free_screen(void *, void *);
     70 int fb_show_screen(void *, void *, int, void (*)(void *, int, int), void *);
     71 
     72 void fb_cnattach(void);
     73 
     74 static void fb253_init(void);
     75 
     76 CFATTACH_DECL_NEW(fb, sizeof(struct fb_softc),
     77     fb_match, fb_attach, NULL, NULL);
     78 
     79 struct fb_devconfig fb_console_dc;
     80 
     81 struct wsdisplay_accessops fb_accessops = {
     82 	fb_ioctl,
     83 	fb_mmap,
     84 	fb_alloc_screen,
     85 	fb_free_screen,
     86 	fb_show_screen,
     87 	NULL	/* load_font */
     88 };
     89 
     90 struct wsscreen_descr fb_stdscreen = {
     91 	"std",
     92 	0, 0,
     93 	0,
     94 	0, 0,
     95 	WSSCREEN_REVERSE
     96 };
     97 
     98 const struct wsscreen_descr *fb_scrlist[] = {
     99 	&fb_stdscreen
    100 };
    101 
    102 struct wsscreen_list fb_screenlist = {
    103 	__arraycount(fb_scrlist), fb_scrlist
    104 };
    105 
    106 #define NWB253_VRAM   ((uint8_t *) 0x88000000)
    107 #define NWB253_CTLREG ((uint16_t *)0xb8ff0000)
    108 #define NWB253_CRTREG ((uint16_t *)0xb8fe0000)
    109 
    110 static const char *devname[8] = { "NWB-512", "NWB-518", "NWE-501" }; /* XXX ? */
    111 
    112 int
    113 fb_match(device_t parent, cfdata_t cf, void *aux)
    114 {
    115 	struct hb_attach_args *ha = aux;
    116 
    117 	if (strcmp(ha->ha_name, "fb") != 0)
    118 		return 0;
    119 
    120 	if (hb_badaddr(NWB253_CTLREG, 2) || hb_badaddr(NWB253_CRTREG, 2))
    121 		return 0;
    122 	if ((*(volatile uint16_t *)NWB253_CTLREG & 7) != 4)
    123 		return 0;
    124 
    125 	return 1;
    126 }
    127 
    128 void
    129 fb_attach(device_t parent, device_t self, void *aux)
    130 {
    131 	struct fb_softc *sc = device_private(self);
    132 	struct wsemuldisplaydev_attach_args waa;
    133 	struct fb_devconfig *dc;
    134 	struct rasops_info *ri;
    135 	int console;
    136 	volatile u_short *ctlreg = NWB253_CTLREG;
    137 	int id;
    138 
    139 	sc->sc_dev = self;
    140 
    141 	console = fb_is_console();
    142 
    143 	if (console) {
    144 		dc = &fb_console_dc;
    145 		ri = &dc->dc_ri;
    146 		ri->ri_flg &= ~RI_NO_AUTO;
    147 		sc->sc_nscreens = 1;
    148 	} else {
    149 		dc = kmem_zalloc(sizeof(struct fb_devconfig), KM_SLEEP);
    150 
    151 		dc->dc_fbbase = NWB253_VRAM;
    152 		fb_common_init(dc);
    153 		ri = &dc->dc_ri;
    154 
    155 		/* clear screen */
    156 		(*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, 0);
    157 
    158 		fb253_init();
    159 	}
    160 	sc->sc_dc = dc;
    161 
    162 	id = (*ctlreg >> 8) & 0xf;
    163 	aprint_normal(": %s, %d x %d, %dbpp\n", devname[id],
    164 	    ri->ri_width, ri->ri_height, ri->ri_depth);
    165 
    166 	waa.console = console;
    167 	waa.scrdata = &fb_screenlist;
    168 	waa.accessops = &fb_accessops;
    169 	waa.accesscookie = sc;
    170 
    171 	config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
    172 }
    173 
    174 int
    175 fb_common_init(struct fb_devconfig *dc)
    176 {
    177 	struct rasops_info *ri = &dc->dc_ri;
    178 	volatile uint16_t *ctlreg = NWB253_CTLREG;
    179 	int id;
    180 	int width, height, xoff, yoff, cols, rows;
    181 
    182 	id = (*ctlreg >> 8) & 0xf;
    183 
    184 	/* initialize rasops */
    185 	switch (id) {
    186 	case 0:
    187 		width = 816;
    188 		height = 1024;
    189 		break;
    190 	case 1:
    191 	case 2:
    192 	default:
    193 		width = 1024;
    194 		height = 768;
    195 		break;
    196 	}
    197 
    198 	ri->ri_width = width;
    199 	ri->ri_height = height;
    200 	ri->ri_depth = 1;
    201 	ri->ri_stride = 2048 / 8;
    202 	ri->ri_bits = dc->dc_fbbase;
    203 	ri->ri_flg = RI_FULLCLEAR;
    204 	if (dc == &fb_console_dc)
    205 		ri->ri_flg |= RI_NO_AUTO;
    206 
    207 	rasops_init(ri, 24, 80);
    208 	rows = (height - 2) / ri->ri_font->fontheight;
    209 	cols = ((width - 2) / ri->ri_font->fontwidth) & ~7;
    210 	xoff = ((width - cols * ri->ri_font->fontwidth) / 2 / 8) & ~3;
    211 	yoff = (height - rows * ri->ri_font->fontheight) / 2;
    212 	rasops_reconfig(ri, rows, cols);
    213 
    214 	ri->ri_xorigin = xoff;
    215 	ri->ri_yorigin = yoff;
    216 	ri->ri_bits = dc->dc_fbbase + xoff + ri->ri_stride * yoff;
    217 
    218 	fb_stdscreen.nrows = ri->ri_rows;
    219 	fb_stdscreen.ncols = ri->ri_cols;
    220 	fb_stdscreen.textops = &ri->ri_ops;
    221 	fb_stdscreen.capabilities = ri->ri_caps;
    222 
    223 	return 0;
    224 }
    225 
    226 int
    227 fb_is_console(void)
    228 {
    229 	volatile u_int *dipsw = (void *)DIP_SWITCH;
    230 
    231 	if (*dipsw & 7)					/* XXX right? */
    232 		return 1;
    233 
    234 	return 0;
    235 }
    236 
    237 int
    238 fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
    239 {
    240 	struct fb_softc *sc = v;
    241 	struct fb_devconfig *dc = sc->sc_dc;
    242 	struct wsdisplay_fbinfo *wdf;
    243 
    244 	switch (cmd) {
    245 	case WSDISPLAYIO_GTYPE:
    246 		*(int *)data = WSDISPLAY_TYPE_UNKNOWN;	/* XXX */
    247 		return 0;
    248 
    249 	case WSDISPLAYIO_GINFO:
    250 		wdf = (void *)data;
    251 		wdf->height = dc->dc_ri.ri_height;
    252 		wdf->width = dc->dc_ri.ri_width;
    253 		wdf->depth = dc->dc_ri.ri_depth;
    254 		wdf->cmsize = 2;
    255 		return 0;
    256 
    257 	case WSDISPLAYIO_LINEBYTES:
    258 		*(u_int *)data = dc->dc_ri.ri_stride;
    259 		return 0;
    260 
    261 	case WSDISPLAYIO_SVIDEO:
    262 		if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) {
    263 			volatile u_short *ctlreg = NWB253_CTLREG;
    264 			*ctlreg = 0;			/* stop crtc */
    265 		} else
    266 			fb253_init();
    267 		return 0;
    268 
    269 	case WSDISPLAYIO_GETCMAP:
    270 	case WSDISPLAYIO_PUTCMAP:
    271 		break;
    272 	}
    273 	return EPASSTHROUGH;
    274 }
    275 
    276 paddr_t
    277 fb_mmap(void *v, void *vs, off_t offset, int prot)
    278 {
    279 	struct fb_softc *sc = v;
    280 	struct fb_devconfig *dc = sc->sc_dc;
    281 
    282 	if (offset >= 2048 * 2048 / 8 || offset < 0)
    283 		return -1;
    284 
    285 	return mips_btop((int)dc->dc_fbbase + offset);
    286 }
    287 
    288 int
    289 fb_alloc_screen(void *v, const struct wsscreen_descr *scrdesc, void **cookiep,
    290     int *ccolp, int *crowp, long *attrp)
    291 {
    292 	struct fb_softc *sc = v;
    293 	struct rasops_info *ri = &sc->sc_dc->dc_ri;
    294 	long defattr;
    295 
    296 	if (sc->sc_nscreens > 0)
    297 		return ENOMEM;
    298 
    299 	*cookiep = ri;
    300 	*ccolp = *crowp = 0;
    301 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    302 	*attrp = defattr;
    303 	sc->sc_nscreens++;
    304 
    305 	return 0;
    306 }
    307 
    308 void
    309 fb_free_screen(void *v, void *cookie)
    310 {
    311 	struct fb_softc *sc = v;
    312 
    313 	if (sc->sc_dc == &fb_console_dc)
    314 		panic("%s: console", __func__);
    315 
    316 	sc->sc_nscreens--;
    317 }
    318 
    319 int
    320 fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
    321     void *cbarg)
    322 {
    323 
    324 	return 0;
    325 }
    326 
    327 void
    328 fb_cnattach(void)
    329 {
    330 	struct fb_devconfig *dc = &fb_console_dc;
    331 	struct rasops_info *ri = &dc->dc_ri;
    332 	long defattr;
    333 
    334 	if (!fb_is_console())
    335 		return;
    336 
    337 	dc->dc_fbbase = NWB253_VRAM;
    338 	fb_common_init(dc);
    339 
    340 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    341 	wsdisplay_cnattach(&fb_stdscreen, ri, 0, ri->ri_rows - 1, defattr);
    342 }
    343 
    344 static const uint8_t
    345 nwp512_data1[] = {
    346 	0x00, 0x44,
    347 	0x01, 0x33,
    348 	0x02, 0x3c,
    349 	0x03, 0x38,
    350 	0x04, 0x84,
    351 	0x05, 0x03,
    352 	0x06, 0x80,
    353 	0x07, 0x80,
    354 	0x08, 0x10,
    355 	0x09, 0x07,
    356 	0x0a, 0x20,
    357 	0x0c, 0x00,
    358 	0x0d, 0x00,
    359 	0x1b, 0x03
    360 };
    361 
    362 static const uint8_t
    363 nwp512_data2[] = {
    364 	0x1e, 0x08,
    365 	0x20, 0x08,
    366 	0x21, 0x0d
    367 };
    368 
    369 static const uint8_t
    370 nwp518_data1[] = {
    371 	0x00, 0x52,
    372 	0x01, 0x40,
    373 	0x02, 0x4a,
    374 	0x03, 0x49,
    375 	0x04, 0x63,
    376 	0x05, 0x02,
    377 	0x06, 0x60,
    378 	0x07, 0x60,
    379 	0x08, 0x10,
    380 	0x09, 0x07,
    381 	0x0a, 0x20,
    382 	0x0c, 0x00,
    383 	0x0d, 0x00,
    384 	0x1b, 0x04
    385 };
    386 
    387 static const uint8_t
    388 nwp518_data2[] = {
    389 	0x1e, 0x08,
    390 	0x20, 0x00,
    391 	0x21, 0x00
    392 };
    393 
    394 static const uint8_t
    395 nwe501_data1[] = {
    396 	0x00, 0x4b,
    397 	0x01, 0x40,
    398 	0x02, 0x4a,
    399 	0x03, 0x43,
    400 	0x04, 0x64,
    401 	0x05, 0x02,
    402 	0x06, 0x60,
    403 	0x07, 0x60,
    404 	0x08, 0x10,
    405 	0x09, 0x07,
    406 	0x0a, 0x20,
    407 	0x0c, 0x00,
    408 	0x0d, 0x00,
    409 	0x1b, 0x04
    410 };
    411 
    412 static const uint8_t
    413 nwe501_data2[] = {
    414 	0x1e, 0x08,
    415 	0x20, 0x00,
    416 	0x21, 0x00
    417 };
    418 
    419 static const uint8_t
    420 *crtc_data[3][2] = {
    421 	{ nwp512_data1, nwp512_data2 },
    422 	{ nwp518_data1, nwp518_data2 },
    423 	{ nwe501_data1, nwe501_data2 }
    424 };
    425 
    426 static void
    427 fb253_init(void)
    428 {
    429 	volatile uint16_t *ctlreg = NWB253_CTLREG;
    430 	volatile uint16_t *crtreg = NWB253_CRTREG;
    431 	int id = (*ctlreg >> 8) & 0xf;
    432 	const uint8_t *p;
    433 	int i;
    434 
    435 	*ctlreg = 0;			/* stop crtc */
    436 	delay(10);
    437 
    438 	/* initialize crtc without R3{0,1,2} */
    439 	p = crtc_data[id][0];
    440 	for (i = 0; i < 28; i++) {
    441 		*crtreg++ = *p++;
    442 		delay(10);
    443 	}
    444 
    445 	*ctlreg = 0x02;			/* start crtc */
    446 	delay(10);
    447 
    448 	/* set crtc control reg */
    449 	p = crtc_data[id][1];
    450 	for (i = 0; i < 6; i++) {
    451 		*crtreg++ = *p++;
    452 		delay(10);
    453 	}
    454 }
    455 
    456 #if 0
    457 static struct wsdisplay_font newsrom8x16;
    458 static struct wsdisplay_font newsrom12x24;
    459 static char fontarea16[96][32];
    460 static char fontarea24[96][96];
    461 
    462 void
    463 initfont(struct rasops_info *ri)
    464 {
    465 	int c, x;
    466 
    467 	for (c = 0; c < 96; c++) {
    468 		x = ((c & 0x1f) | ((c & 0xe0) << 2)) << 7;
    469 		memcpy(fontarea16 + c, (char *)0xb8e00000 + x + 96, 32);
    470 		memcpy(fontarea24 + c, (char *)0xb8e00000 + x, 96);
    471 	}
    472 
    473 	newsrom8x16.name = "rom8x16";
    474 	newsrom8x16.firstchar = 32;
    475 	newsrom8x16.numchars = 96;
    476 	newsrom8x16.encoding = WSDISPLAY_FONTENC_ISO;
    477 	newsrom8x16.fontwidth = 8;
    478 	newsrom8x16.fontheight = 16;
    479 	newsrom8x16.stride = 2;
    480 	newsrom8x16.bitorder = WSDISPLAY_FONTORDER_L2R;
    481 	newsrom8x16.byteorder = WSDISPLAY_FONTORDER_L2R;
    482 	newsrom8x16.data = fontarea16;
    483 
    484 	newsrom12x24.name = "rom12x24";
    485 	newsrom12x24.firstchar = 32;
    486 	newsrom12x24.numchars = 96;
    487 	newsrom12x24.encoding = WSDISPLAY_FONTENC_ISO;
    488 	newsrom12x24.fontwidth = 12;
    489 	newsrom12x24.fontheight = 24;
    490 	newsrom12x24.stride = 4;
    491 	newsrom12x24.bitorder = WSDISPLAY_FONTORDER_L2R;
    492 	newsrom12x24.byteorder = WSDISPLAY_FONTORDER_L2R;
    493 	newsrom12x24.data = fontarea24;
    494 
    495 	ri->ri_font = &newsrom8x16;
    496 	ri->ri_font = &newsrom12x24;
    497 	ri->ri_wsfcookie = -1;		/* not using wsfont */
    498 }
    499 #endif
    500