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