xref: /netbsd-src/sys/arch/newsmips/dev/fb.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
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