Home | History | Annotate | Line # | Download | only in dev
fb.c revision 1.24
      1 /*	$NetBSD: fb.c,v 1.24 2008/04/09 15:40:30 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 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: fb.c,v 1.24 2008/04/09 15:40:30 tsutsui Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/device.h>
     34 #include <sys/ioctl.h>
     35 #include <sys/malloc.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 		sc->sc_nscreens = 1;
    147 	} else {
    148 		dc = malloc(sizeof(struct fb_devconfig), M_DEVBUF,
    149 		    M_WAITOK|M_ZERO);
    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);
    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 
    205 	rasops_init(ri, 24, 80);
    206 	rows = (height - 2) / ri->ri_font->fontheight;
    207 	cols = ((width - 2) / ri->ri_font->fontwidth) & ~7;
    208 	xoff = ((width - cols * ri->ri_font->fontwidth) / 2 / 8) & ~3;
    209 	yoff = (height - rows * ri->ri_font->fontheight) / 2;
    210 	rasops_reconfig(ri, rows, cols);
    211 
    212 	ri->ri_xorigin = xoff;
    213 	ri->ri_yorigin = yoff;
    214 	ri->ri_bits = dc->dc_fbbase + xoff + ri->ri_stride * yoff;
    215 
    216 	fb_stdscreen.nrows = ri->ri_rows;
    217 	fb_stdscreen.ncols = ri->ri_cols;
    218 	fb_stdscreen.textops = &ri->ri_ops;
    219 	fb_stdscreen.capabilities = ri->ri_caps;
    220 
    221 	return 0;
    222 }
    223 
    224 int
    225 fb_is_console(void)
    226 {
    227 	volatile u_int *dipsw = (void *)DIP_SWITCH;
    228 
    229 	if (*dipsw & 7)					/* XXX right? */
    230 		return 1;
    231 
    232 	return 0;
    233 }
    234 
    235 int
    236 fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
    237 {
    238 	struct fb_softc *sc = v;
    239 	struct fb_devconfig *dc = sc->sc_dc;
    240 	struct wsdisplay_fbinfo *wdf;
    241 
    242 	switch (cmd) {
    243 	case WSDISPLAYIO_GTYPE:
    244 		*(int *)data = WSDISPLAY_TYPE_UNKNOWN;	/* XXX */
    245 		return 0;
    246 
    247 	case WSDISPLAYIO_GINFO:
    248 		wdf = (void *)data;
    249 		wdf->height = dc->dc_ri.ri_height;
    250 		wdf->width = dc->dc_ri.ri_width;
    251 		wdf->depth = dc->dc_ri.ri_depth;
    252 		wdf->cmsize = 2;
    253 		return 0;
    254 
    255 	case WSDISPLAYIO_SVIDEO:
    256 		if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) {
    257 			volatile u_short *ctlreg = NWB253_CTLREG;
    258 			*ctlreg = 0;			/* stop crtc */
    259 		} else
    260 			fb253_init();
    261 		return 0;
    262 
    263 	case WSDISPLAYIO_GETCMAP:
    264 	case WSDISPLAYIO_PUTCMAP:
    265 		break;
    266 	}
    267 	return EPASSTHROUGH;
    268 }
    269 
    270 paddr_t
    271 fb_mmap(void *v, void *vs, off_t offset, int prot)
    272 {
    273 	struct fb_softc *sc = v;
    274 	struct fb_devconfig *dc = sc->sc_dc;
    275 
    276 	if (offset >= 2048 * 2048 / 8 || offset < 0)
    277 		return -1;
    278 
    279 	return mips_btop((int)dc->dc_fbbase + offset);
    280 }
    281 
    282 int
    283 fb_alloc_screen(void *v, const struct wsscreen_descr *scrdesc, void **cookiep,
    284     int *ccolp, int *crowp, long *attrp)
    285 {
    286 	struct fb_softc *sc = v;
    287 	struct rasops_info *ri = &sc->sc_dc->dc_ri;
    288 	long defattr;
    289 
    290 	if (sc->sc_nscreens > 0)
    291 		return ENOMEM;
    292 
    293 	*cookiep = ri;
    294 	*ccolp = *crowp = 0;
    295 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    296 	*attrp = defattr;
    297 	sc->sc_nscreens++;
    298 
    299 	return 0;
    300 }
    301 
    302 void
    303 fb_free_screen(void *v, void *cookie)
    304 {
    305 	struct fb_softc *sc = v;
    306 
    307 	if (sc->sc_dc == &fb_console_dc)
    308 		panic("%s: console", __func__);
    309 
    310 	sc->sc_nscreens--;
    311 }
    312 
    313 int
    314 fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
    315     void *cbarg)
    316 {
    317 
    318 	return 0;
    319 }
    320 
    321 void
    322 fb_cnattach(void)
    323 {
    324 	struct fb_devconfig *dc = &fb_console_dc;
    325 	struct rasops_info *ri = &dc->dc_ri;
    326 	long defattr;
    327 
    328 	if (!fb_is_console())
    329 		return;
    330 
    331 	dc->dc_fbbase = NWB253_VRAM;
    332 	fb_common_init(dc);
    333 
    334 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    335 	wsdisplay_cnattach(&fb_stdscreen, ri, 0, ri->ri_rows - 1, defattr);
    336 }
    337 
    338 static const uint8_t
    339 nwp512_data1[] = {
    340 	0x00, 0x44,
    341 	0x01, 0x33,
    342 	0x02, 0x3c,
    343 	0x03, 0x38,
    344 	0x04, 0x84,
    345 	0x05, 0x03,
    346 	0x06, 0x80,
    347 	0x07, 0x80,
    348 	0x08, 0x10,
    349 	0x09, 0x07,
    350 	0x0a, 0x20,
    351 	0x0c, 0x00,
    352 	0x0d, 0x00,
    353 	0x1b, 0x03
    354 };
    355 
    356 static const uint8_t
    357 nwp512_data2[] = {
    358 	0x1e, 0x08,
    359 	0x20, 0x08,
    360 	0x21, 0x0d
    361 };
    362 
    363 static const uint8_t
    364 nwp518_data1[] = {
    365 	0x00, 0x52,
    366 	0x01, 0x40,
    367 	0x02, 0x4a,
    368 	0x03, 0x49,
    369 	0x04, 0x63,
    370 	0x05, 0x02,
    371 	0x06, 0x60,
    372 	0x07, 0x60,
    373 	0x08, 0x10,
    374 	0x09, 0x07,
    375 	0x0a, 0x20,
    376 	0x0c, 0x00,
    377 	0x0d, 0x00,
    378 	0x1b, 0x04
    379 };
    380 
    381 static const uint8_t
    382 nwp518_data2[] = {
    383 	0x1e, 0x08,
    384 	0x20, 0x00,
    385 	0x21, 0x00
    386 };
    387 
    388 static const uint8_t
    389 nwe501_data1[] = {
    390 	0x00, 0x4b,
    391 	0x01, 0x40,
    392 	0x02, 0x4a,
    393 	0x03, 0x43,
    394 	0x04, 0x64,
    395 	0x05, 0x02,
    396 	0x06, 0x60,
    397 	0x07, 0x60,
    398 	0x08, 0x10,
    399 	0x09, 0x07,
    400 	0x0a, 0x20,
    401 	0x0c, 0x00,
    402 	0x0d, 0x00,
    403 	0x1b, 0x04
    404 };
    405 
    406 static const uint8_t
    407 nwe501_data2[] = {
    408 	0x1e, 0x08,
    409 	0x20, 0x00,
    410 	0x21, 0x00
    411 };
    412 
    413 static const uint8_t
    414 *crtc_data[3][2] = {
    415 	{ nwp512_data1, nwp512_data2 },
    416 	{ nwp518_data1, nwp518_data2 },
    417 	{ nwe501_data1, nwe501_data2 }
    418 };
    419 
    420 static void
    421 fb253_init(void)
    422 {
    423 	volatile uint16_t *ctlreg = NWB253_CTLREG;
    424 	volatile uint16_t *crtreg = NWB253_CRTREG;
    425 	int id = (*ctlreg >> 8) & 0xf;
    426 	const uint8_t *p;
    427 	int i;
    428 
    429 	*ctlreg = 0;			/* stop crtc */
    430 	delay(10);
    431 
    432 	/* initialize crtc without R3{0,1,2} */
    433 	p = crtc_data[id][0];
    434 	for (i = 0; i < 28; i++) {
    435 		*crtreg++ = *p++;
    436 		delay(10);
    437 	}
    438 
    439 	*ctlreg = 0x02;			/* start crtc */
    440 	delay(10);
    441 
    442 	/* set crtc control reg */
    443 	p = crtc_data[id][1];
    444 	for (i = 0; i < 6; i++) {
    445 		*crtreg++ = *p++;
    446 		delay(10);
    447 	}
    448 }
    449 
    450 #if 0
    451 static struct wsdisplay_font newsrom8x16;
    452 static struct wsdisplay_font newsrom12x24;
    453 static char fontarea16[96][32];
    454 static char fontarea24[96][96];
    455 
    456 void
    457 initfont(struct rasops_info *ri)
    458 {
    459 	int c, x;
    460 
    461 	for (c = 0; c < 96; c++) {
    462 		x = ((c & 0x1f) | ((c & 0xe0) << 2)) << 7;
    463 		memcpy(fontarea16 + c, (char *)0xb8e00000 + x + 96, 32);
    464 		memcpy(fontarea24 + c, (char *)0xb8e00000 + x, 96);
    465 	}
    466 
    467 	newsrom8x16.name = "rom8x16";
    468 	newsrom8x16.firstchar = 32;
    469 	newsrom8x16.numchars = 96;
    470 	newsrom8x16.encoding = WSDISPLAY_FONTENC_ISO;
    471 	newsrom8x16.fontwidth = 8;
    472 	newsrom8x16.fontheight = 16;
    473 	newsrom8x16.stride = 2;
    474 	newsrom8x16.bitorder = WSDISPLAY_FONTORDER_L2R;
    475 	newsrom8x16.byteorder = WSDISPLAY_FONTORDER_L2R;
    476 	newsrom8x16.data = fontarea16;
    477 
    478 	newsrom12x24.name = "rom12x24";
    479 	newsrom12x24.firstchar = 32;
    480 	newsrom12x24.numchars = 96;
    481 	newsrom12x24.encoding = WSDISPLAY_FONTENC_ISO;
    482 	newsrom12x24.fontwidth = 12;
    483 	newsrom12x24.fontheight = 24;
    484 	newsrom12x24.stride = 4;
    485 	newsrom12x24.bitorder = WSDISPLAY_FONTORDER_L2R;
    486 	newsrom12x24.byteorder = WSDISPLAY_FONTORDER_L2R;
    487 	newsrom12x24.data = fontarea24;
    488 
    489 	ri->ri_font = &newsrom8x16;
    490 	ri->ri_font = &newsrom12x24;
    491 	ri->ri_wsfcookie = -1;		/* not using wsfont */
    492 }
    493 #endif
    494