Home | History | Annotate | Line # | Download | only in dev
fb.c revision 1.16
      1 /*	$NetBSD: fb.c,v 1.16 2003/05/09 13:36:39 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/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 
     39 #include <newsmips/dev/hbvar.h>
     40 
     41 #include <dev/wscons/wsconsio.h>
     42 #include <dev/wscons/wsdisplayvar.h>
     43 #include <dev/rasops/rasops.h>
     44 
     45 struct fb_devconfig {
     46 	u_char *dc_fbbase;		/* VRAM base address */
     47 	struct rasops_info dc_ri;
     48 };
     49 
     50 struct fb_softc {
     51 	struct device sc_dev;
     52 	struct fb_devconfig *sc_dc;
     53 	int sc_nscreens;
     54 };
     55 
     56 int fb_match(struct device *, struct cfdata *, void *);
     57 void fb_attach(struct device *, struct device *, void *);
     58 
     59 int fb_common_init(struct fb_devconfig *);
     60 int fb_is_console(void);
     61 
     62 int fb_ioctl(void *, u_long, caddr_t, int, struct proc *);
     63 paddr_t fb_mmap(void *, off_t, int);
     64 int fb_alloc_screen(void *, const struct wsscreen_descr *, void **, int *,
     65 		    int *, long *);
     66 void fb_free_screen(void *, void *);
     67 int fb_show_screen(void *, void *, int, void (*)(void *, int, int), void *);
     68 
     69 void fb_cnattach(void);
     70 
     71 static void fb253_init(void);
     72 
     73 CFATTACH_DECL(fb, sizeof(struct fb_softc),
     74     fb_match, fb_attach, NULL, NULL);
     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 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(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();
    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 			fb253_init();
    266 		return 0;
    267 
    268 	case WSDISPLAYIO_GETCMAP:
    269 	case WSDISPLAYIO_PUTCMAP:
    270 		break;
    271 	}
    272 	return EPASSTHROUGH;
    273 }
    274 
    275 paddr_t
    276 fb_mmap(v, offset, prot)
    277 	void *v;
    278 	off_t offset;
    279 	int prot;
    280 {
    281 	struct fb_softc *sc = v;
    282 	struct fb_devconfig *dc = sc->sc_dc;
    283 
    284 	if (offset >= 2048 * 2048 / 8 || offset < 0)
    285 		return -1;
    286 
    287 	return mips_btop((int)dc->dc_fbbase + offset);
    288 }
    289 
    290 int
    291 fb_alloc_screen(v, scrdesc, cookiep, ccolp, crowp, attrp)
    292 	void *v;
    293 	const struct wsscreen_descr *scrdesc;
    294 	void **cookiep;
    295 	int *ccolp, *crowp;
    296 	long *attrp;
    297 {
    298 	struct fb_softc *sc = v;
    299 	struct rasops_info *ri = &sc->sc_dc->dc_ri;
    300 	long defattr;
    301 
    302 	if (sc->sc_nscreens > 0)
    303 		return ENOMEM;
    304 
    305 	*cookiep = ri;
    306 	*ccolp = *crowp = 0;
    307 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    308 	*attrp = defattr;
    309 	sc->sc_nscreens++;
    310 
    311 	return 0;
    312 }
    313 
    314 void
    315 fb_free_screen(v, cookie)
    316 	void *v;
    317 	void *cookie;
    318 {
    319 	struct fb_softc *sc = v;
    320 
    321 	if (sc->sc_dc == &fb_console_dc)
    322 		panic("fb_free_screen: console");
    323 
    324 	sc->sc_nscreens--;
    325 }
    326 
    327 int
    328 fb_show_screen(v, cookie, waitok, cb, cbarg)
    329 	void *v;
    330 	void *cookie;
    331 	int waitok;
    332 	void (*cb)(void *, int, int);
    333 	void *cbarg;
    334 {
    335 	return 0;
    336 }
    337 
    338 void
    339 fb_cnattach()
    340 {
    341 	struct fb_devconfig *dc = &fb_console_dc;
    342 	struct rasops_info *ri = &dc->dc_ri;
    343 	long defattr;
    344 
    345 	if (!fb_is_console())
    346 		return;
    347 
    348 	dc->dc_fbbase = NWB253_VRAM;
    349 	fb_common_init(dc);
    350 
    351 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    352 	wsdisplay_cnattach(&fb_stdscreen, ri, 0, ri->ri_rows - 1, defattr);
    353 }
    354 
    355 static u_char
    356 nwp512_data1[] = {
    357 	0x00, 0x44,
    358 	0x01, 0x33,
    359 	0x02, 0x3c,
    360 	0x03, 0x38,
    361 	0x04, 0x84,
    362 	0x05, 0x03,
    363 	0x06, 0x80,
    364 	0x07, 0x80,
    365 	0x08, 0x10,
    366 	0x09, 0x07,
    367 	0x0a, 0x20,
    368 	0x0c, 0x00,
    369 	0x0d, 0x00,
    370 	0x1b, 0x03
    371 };
    372 
    373 static u_char
    374 nwp512_data2[] = {
    375 	0x1e, 0x08,
    376 	0x20, 0x08,
    377 	0x21, 0x0d
    378 };
    379 
    380 static u_char
    381 nwp518_data1[] = {
    382 	0x00, 0x52,
    383 	0x01, 0x40,
    384 	0x02, 0x4a,
    385 	0x03, 0x49,
    386 	0x04, 0x63,
    387 	0x05, 0x02,
    388 	0x06, 0x60,
    389 	0x07, 0x60,
    390 	0x08, 0x10,
    391 	0x09, 0x07,
    392 	0x0a, 0x20,
    393 	0x0c, 0x00,
    394 	0x0d, 0x00,
    395 	0x1b, 0x04
    396 };
    397 
    398 static u_char
    399 nwp518_data2[] = {
    400 	0x1e, 0x08,
    401 	0x20, 0x00,
    402 	0x21, 0x00
    403 };
    404 
    405 static u_char
    406 nwe501_data1[] = {
    407 	0x00, 0x4b,
    408 	0x01, 0x40,
    409 	0x02, 0x4a,
    410 	0x03, 0x43,
    411 	0x04, 0x64,
    412 	0x05, 0x02,
    413 	0x06, 0x60,
    414 	0x07, 0x60,
    415 	0x08, 0x10,
    416 	0x09, 0x07,
    417 	0x0a, 0x20,
    418 	0x0c, 0x00,
    419 	0x0d, 0x00,
    420 	0x1b, 0x04
    421 };
    422 
    423 static u_char
    424 nwe501_data2[] = {
    425 	0x1e, 0x08,
    426 	0x20, 0x00,
    427 	0x21, 0x00
    428 };
    429 
    430 static u_char
    431 *crtc_data[3][2] = {
    432 	{ nwp512_data1, nwp512_data2 },
    433 	{ nwp518_data1, nwp518_data2 },
    434 	{ nwe501_data1, nwe501_data2 }
    435 };
    436 
    437 static void
    438 fb253_init(void)
    439 {
    440 	volatile u_short *ctlreg = NWB253_CTLREG;
    441 	volatile u_short *crtreg = NWB253_CRTREG;
    442 	int id = (*ctlreg >> 8) & 0xf;
    443 	u_char *p;
    444 	int i;
    445 
    446 	*ctlreg = 0;			/* stop crtc */
    447 	delay(10);
    448 
    449 	/* initialize crtc without R3{0,1,2} */
    450 	p = crtc_data[id][0];
    451 	for (i = 0; i < 28; i++) {
    452 		*crtreg++ = *p++;
    453 		delay(10);
    454 	}
    455 
    456 	*ctlreg = 0x02;			/* start crtc */
    457 	delay(10);
    458 
    459 	/* set crtc control reg */
    460 	p = crtc_data[id][1];
    461 	for (i = 0; i < 6; i++) {
    462 		*crtreg++ = *p++;
    463 		delay(10);
    464 	}
    465 }
    466 
    467 #if 0
    468 static struct wsdisplay_font newsrom8x16;
    469 static struct wsdisplay_font newsrom12x24;
    470 static char fontarea16[96][32];
    471 static char fontarea24[96][96];
    472 
    473 void
    474 initfont(ri)
    475 	struct rasops_info *ri;
    476 {
    477 	int c, x;
    478 
    479 	for (c = 0; c < 96; c++) {
    480 		x = ((c & 0x1f) | ((c & 0xe0) << 2)) << 7;
    481 		bcopy((char *)0xb8e00000 + x + 96, fontarea16 + c, 32);
    482 		bcopy((char *)0xb8e00000 + x, fontarea24 + c, 96);
    483 	}
    484 
    485 	newsrom8x16.name = "rom8x16";
    486 	newsrom8x16.firstchar = 32;
    487 	newsrom8x16.numchars = 96;
    488 	newsrom8x16.encoding = WSDISPLAY_FONTENC_ISO;
    489 	newsrom8x16.fontwidth = 8;
    490 	newsrom8x16.fontheight = 16;
    491 	newsrom8x16.stride = 2;
    492 	newsrom8x16.bitorder = WSDISPLAY_FONTORDER_L2R;
    493 	newsrom8x16.byteorder = WSDISPLAY_FONTORDER_L2R;
    494 	newsrom8x16.data = fontarea16;
    495 
    496 	newsrom12x24.name = "rom12x24";
    497 	newsrom12x24.firstchar = 32;
    498 	newsrom12x24.numchars = 96;
    499 	newsrom12x24.encoding = WSDISPLAY_FONTENC_ISO;
    500 	newsrom12x24.fontwidth = 12;
    501 	newsrom12x24.fontheight = 24;
    502 	newsrom12x24.stride = 4;
    503 	newsrom12x24.bitorder = WSDISPLAY_FONTORDER_L2R;
    504 	newsrom12x24.byteorder = WSDISPLAY_FONTORDER_L2R;
    505 	newsrom12x24.data = fontarea24;
    506 
    507 	ri->ri_font = &newsrom8x16;
    508 	ri->ri_font = &newsrom12x24;
    509 	ri->ri_wsfcookie = -1;		/* not using wsfont */
    510 }
    511 #endif
    512