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