xref: /netbsd/sys/arch/newsmips/dev/fb.c (revision bf9ec67e)
1 /*	$NetBSD: fb.c,v 1.10 2002/03/17 19:40:46 atatat 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 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();
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 	}
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.alloc_attr)(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.alloc_attr)(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