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