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