Home | History | Annotate | Line # | Download | only in dev
fb.c revision 1.5
      1 /*	$NetBSD: fb.c,v 1.5 2000/11/13 16:48:42 tsubai 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/param.h>
     30 #include <sys/device.h>
     31 #include <sys/ioctl.h>
     32 #include <sys/malloc.h>
     33 #include <sys/systm.h>
     34 
     35 #include <uvm/uvm_extern.h>
     36 
     37 #include <machine/adrsmap.h>
     38 #include <machine/autoconf.h>
     39 
     40 #include <dev/wscons/wsconsio.h>
     41 #include <dev/wscons/wsdisplayvar.h>
     42 #include <dev/rasops/rasops.h>
     43 
     44 struct fb_devconfig {
     45 	u_char *dc_fbbase;		/* VRAM base address */
     46 	struct rasops_info dc_ri;
     47 };
     48 
     49 struct fb_softc {
     50 	struct device sc_dev;
     51 	struct fb_devconfig *sc_dc;
     52 	int sc_nscreens;
     53 };
     54 
     55 int fb_match(struct device *, struct cfdata *, void *);
     56 void fb_attach(struct device *, struct device *, void *);
     57 
     58 int fb_common_init(struct fb_devconfig *);
     59 int fb_is_console(void);
     60 
     61 int fb_ioctl(void *, u_long, caddr_t, int, struct proc *);
     62 paddr_t fb_mmap(void *, off_t, int);
     63 int fb_alloc_screen(void *, const struct wsscreen_descr *, void **, int *,
     64 		    int *, long *);
     65 void fb_free_screen(void *, void *);
     66 int fb_show_screen(void *, void *, int, void (*)(void *, int, int), void *);
     67 
     68 void fb_cnattach(void);
     69 
     70 static void fb253_init(int);
     71 
     72 struct cfattach fb_ca = {
     73 	sizeof(struct fb_softc), fb_match, fb_attach,
     74 };
     75 
     76 struct fb_devconfig fb_console_dc;
     77 
     78 struct wsdisplay_accessops fb_accessops = {
     79 	fb_ioctl,
     80 	fb_mmap,
     81 	fb_alloc_screen,
     82 	fb_free_screen,
     83 	fb_show_screen,
     84 	NULL	/* load_font */
     85 };
     86 
     87 struct wsscreen_descr fb_stdscreen = {
     88 	"std",
     89 	0, 0,
     90 	0,
     91 	0, 0,
     92 	WSSCREEN_REVERSE
     93 };
     94 
     95 const struct wsscreen_descr *fb_scrlist[] = {
     96 	&fb_stdscreen
     97 };
     98 
     99 struct wsscreen_list fb_screenlist = {
    100 	sizeof(fb_scrlist) / sizeof(fb_scrlist[0]), fb_scrlist
    101 };
    102 
    103 #define NWB253_VRAM   ((u_char *) 0x88000000)
    104 #define NWB253_CTLREG ((u_short *)0xb8ff0000)
    105 #define NWB253_CRTREG ((u_short *)0xb8fe0000)
    106 
    107 static char *devname[8] = { "NWB-512", "NWB-518", "NWE-501" };	/* XXX ? */
    108 
    109 int
    110 fb_match(parent, match, aux)
    111 	struct device *parent;
    112 	struct cfdata *match;
    113 	void *aux;
    114 {
    115 	struct confargs *ca = aux;
    116 
    117 	if (strcmp(ca->ca_name, "fb") != 0)
    118 		return 0;
    119 
    120 	if (badaddr(NWB253_CTLREG, 2) || 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(parent, self, aux)
    130 	struct device *parent, *self;
    131 	void *aux;
    132 {
    133 	struct fb_softc *sc = (void *)self;
    134 	struct wsemuldisplaydev_attach_args waa;
    135 	struct fb_devconfig *dc;
    136 	struct rasops_info *ri;
    137 	int console;
    138 	volatile u_short *ctlreg = NWB253_CTLREG;
    139 	int id;
    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, M_WAITOK);
    149 		bzero(dc, sizeof(struct fb_devconfig));
    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(id);
    159 	}
    160 	sc->sc_dc = dc;
    161 
    162 	id = (*ctlreg >> 8) & 0xf;
    163 	printf(": %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(dc)
    176 	struct fb_devconfig *dc;
    177 {
    178 	struct rasops_info *ri = &dc->dc_ri;
    179 	volatile u_short *ctlreg = NWB253_CTLREG;
    180 	int id;
    181 	int width, height, xoff, yoff, cols, rows;
    182 
    183 	id = (*ctlreg >> 8) & 0xf;
    184 
    185 	/* initialize rasops */
    186 	switch (id) {
    187 	case 0:
    188 		width = 816;
    189 		height = 1024;
    190 		break;
    191 	case 1:
    192 	case 2:
    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()
    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(v, cmd, data, flag, p)
    237 	void *v;
    238 	u_long cmd;
    239 	caddr_t data;
    240 	int flag;
    241 	struct proc *p;
    242 {
    243 	struct fb_softc *sc = v;
    244 	struct fb_devconfig *dc = sc->sc_dc;
    245 	struct wsdisplay_fbinfo *wdf;
    246 
    247 	switch (cmd) {
    248 	case WSDISPLAYIO_GTYPE:
    249 		*(int *)data = WSDISPLAY_TYPE_UNKNOWN;	/* XXX */
    250 		return 0;
    251 
    252 	case WSDISPLAYIO_GINFO:
    253 		wdf = (void *)data;
    254 		wdf->height = dc->dc_ri.ri_height;
    255 		wdf->width = dc->dc_ri.ri_width;
    256 		wdf->depth = dc->dc_ri.ri_depth;
    257 		wdf->cmsize = 2;
    258 		return 0;
    259 
    260 	case WSDISPLAYIO_SVIDEO:
    261 		if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) {
    262 			volatile u_short *ctlreg = NWB253_CTLREG;
    263 			*ctlreg = 0;			/* stop crtc */
    264 		} else {
    265 			volatile u_short *ctlreg = NWB253_CTLREG;
    266 			int id = (*ctlreg >> 8) & 0xf;
    267 			fb253_init(id);
    268 		}
    269 		return 0;
    270 
    271 	case WSDISPLAYIO_GETCMAP:
    272 	case WSDISPLAYIO_PUTCMAP:
    273 	}
    274 	return -1;
    275 }
    276 
    277 paddr_t
    278 fb_mmap(v, offset, prot)
    279 	void *v;
    280 	off_t offset;
    281 	int prot;
    282 {
    283 	struct fb_softc *sc = v;
    284 	struct fb_devconfig *dc = sc->sc_dc;
    285 	struct rasops_info *ri = &dc->dc_ri;
    286 
    287 	if (offset >= (ri->ri_stride * ri->ri_height) || 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.alloc_attr)(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.alloc_attr)(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(id)
    442 	int id;
    443 {
    444 	volatile u_short *ctlreg = NWB253_CTLREG;
    445 	volatile u_short *crtreg = NWB253_CRTREG;
    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