xref: /netbsd/sys/arch/sun3/dev/fb.c (revision c4a72b64)
1 /*	$NetBSD: fb.c,v 1.9 2002/10/23 09:12:25 jdolecek Exp $ */
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This software was developed by the Computer Systems Engineering group
8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9  * contributed to Berkeley.
10  *
11  * All advertising materials mentioning features or use of this software
12  * must display the following acknowledgement:
13  *	This product includes software developed by the University of
14  *	California, Lawrence Berkeley Laboratory.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. All advertising materials mentioning features or use of this software
25  *    must display the following acknowledgement:
26  *	This product includes software developed by the University of
27  *	California, Berkeley and its contributors.
28  * 4. Neither the name of the University nor the names of its contributors
29  *    may be used to endorse or promote products derived from this software
30  *    without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42  * SUCH DAMAGE.
43  *
44  *	@(#)fb.c	8.1 (Berkeley) 6/11/93
45  */
46 
47 /*
48  * /dev/fb (indirect frame buffer driver).
49  */
50 
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/conf.h>
54 #include <sys/device.h>
55 #include <sys/ioctl.h>
56 #include <sys/proc.h>
57 
58 #include <machine/eeprom.h>
59 #include <dev/sun/fbio.h>
60 
61 #include <sun3/dev/fbvar.h>
62 #include <sun3/dev/p4reg.h>
63 
64 dev_type_open(fbopen);
65 dev_type_close(fbclose);
66 dev_type_ioctl(fbioctl);
67 dev_type_mmap(fbmmap);
68 
69 const struct cdevsw fb_cdevsw = {
70 	fbopen, fbclose, noread, nowrite, fbioctl,
71 	nostop, notty, nopoll, fbmmap, nokqfilter,
72 };
73 
74 static struct fbdevice *devfb;
75 static int fbpriority;
76 
77 /*
78  * This is called by the real driver (i.e. bw2, cg3, ...)
79  * to declare itself as a potential default frame buffer.
80  */
81 void
82 fb_attach(fb, newpri)
83 	struct fbdevice *fb;
84 	int newpri;
85 {
86 	if (fbpriority < newpri) {
87 		fbpriority = newpri;
88 		devfb = fb;
89 	}
90 }
91 
92 int
93 fbopen(dev, flags, mode, p)
94 	dev_t dev;
95 	int flags, mode;
96 	struct proc *p;
97 {
98 
99 	if (devfb == NULL)
100 		return (ENXIO);
101 	return ((*devfb->fb_driver->fbd_open)(dev, flags, mode, p));
102 }
103 
104 int
105 fbclose(dev, flags, mode, p)
106 	dev_t dev;
107 	int flags, mode;
108 	struct proc *p;
109 {
110 
111 	return ((*devfb->fb_driver->fbd_close)(dev, flags, mode, p));
112 }
113 
114 int
115 fbioctl(dev, cmd, data, flags, p)
116 	dev_t dev;
117 	u_long cmd;
118 	caddr_t data;
119 	int flags;
120 	struct proc *p;
121 {
122 	return (fbioctlfb(devfb, cmd, data));
123 }
124 
125 paddr_t
126 fbmmap(dev, off, prot)
127 	dev_t dev;
128 	off_t off;
129 	int prot;
130 {
131 	return ((*devfb->fb_driver->fbd_mmap)(dev, off, prot));
132 }
133 
134 /*
135  * Common fb ioctl function
136  */
137 int
138 fbioctlfb(fb, cmd, data)
139 	struct fbdevice *fb;
140 	u_long cmd;
141 	caddr_t data;
142 {
143 	struct fbdriver *fbd = fb->fb_driver;
144 	void *vp = (void *)data;
145 	int error;
146 
147 	switch (cmd) {
148 
149 	case FBIOGTYPE:
150 		*(struct fbtype *)vp = fb->fb_fbtype;
151 		error = 0;
152 		break;
153 
154 	case FBIOGATTR:
155 		error = (*fbd->fbd_gattr)(fb, vp);
156 		break;
157 
158 	case FBIOGVIDEO:
159 		error = (*fbd->fbd_gvideo)(fb, vp);
160 		break;
161 
162 	case FBIOSVIDEO:
163 		error = (*fbd->fbd_svideo)(fb, vp);
164 		break;
165 
166 	case FBIOGETCMAP:
167 		error = (*fbd->fbd_getcmap)(fb, vp);
168 		break;
169 
170 	case FBIOPUTCMAP:
171 		error = (*fbd->fbd_putcmap)(fb, vp);
172 		break;
173 
174 	default:
175 		error = ENOTTY;
176 	}
177 	return (error);
178 }
179 
180 void
181 fb_unblank()
182 {
183 	int on = 1;
184 
185 	if (devfb == NULL)
186 		return;
187 
188 	(*devfb->fb_driver->fbd_svideo)(devfb, (void *)&on);
189 }
190 
191 /*
192  * Default ioctl function to put in struct fbdriver
193  * for functions that are not supported.
194  */
195 int
196 fb_noioctl(fbd, vp)
197 	struct fbdevice *fbd;
198 	void *vp;
199 {
200 	return ENOTTY;
201 }
202 
203 /****************************************************************
204  * Misc. helpers...
205  */
206 
207 /* Set FB size based on EEPROM screen shape code. */
208 void
209 fb_eeprom_setsize(fb)
210 	struct fbdevice *fb;
211 {
212 	int szcode;
213 	int w, h;
214 
215 	/* Go get the EEPROM screen size byte. */
216 	szcode = eeprom_copy->eeScreenSize;
217 
218 	w = h = 0;
219 	switch (szcode) {
220 	case EE_SCR_1152X900:
221 		w = 1152;
222 		h = 900;
223 		break;
224 	case EE_SCR_1024X1024:
225 		w = 1024;
226 		h = 1024;
227 		break;
228 	case EE_SCR_1600X1280:
229 		w = 1600;
230 		h = 1280;
231 		break;
232 	case EE_SCR_1440X1440:
233 		w = 1440;
234 		h = 1440;
235 		break;
236 	default:
237 		break;
238 	}
239 
240 	if (w && h) {
241 		fb->fb_fbtype.fb_width  = w;
242 		fb->fb_fbtype.fb_height = h;
243 	} else {
244 		printf("%s: EE size code %d unknown\n",
245 			   fb->fb_name, szcode);
246 	}
247 }
248 
249 /*
250  * Probe for a P4 register at the passed virtual address.
251  * Returns P4 ID value, or -1 if no P4 register.
252  */
253 int
254 fb_pfour_id(va)
255 	void *va;
256 {
257 	volatile u_int32_t val, save, *pfour = va;
258 
259 	/* Read the P4 register. */
260 	save = *pfour;
261 
262 	/*
263 	 * Try to modify the type code.  If it changes, put the
264 	 * original value back, and tell the caller that the
265 	 * framebuffer does not have a P4 register.
266 	 */
267 	val = save & ~P4_REG_RESET;
268 	*pfour = (val ^ P4_FBTYPE_MASK);
269 	if ((*pfour ^ val) & P4_FBTYPE_MASK) {
270 		*pfour = save;
271 		return (-1);
272 	}
273 
274 	return (P4_ID(val));
275 }
276 
277 /*
278  * Return the status of the video enable.
279  */
280 int
281 fb_pfour_get_video(fb)
282 	struct fbdevice *fb;
283 {
284 
285 	return ((*fb->fb_pfour & P4_REG_VIDEO) != 0);
286 }
287 
288 /*
289  * Turn video on or off using the P4 register.
290  */
291 void
292 fb_pfour_set_video(fb, on)
293 	struct fbdevice *fb;
294 	int on;
295 {
296 	int pfour;
297 
298 	pfour = *fb->fb_pfour & ~(P4_REG_INTCLR|P4_REG_VIDEO);
299 	*fb->fb_pfour = pfour | (on ? P4_REG_VIDEO : 0);
300 }
301 
302 static const struct {
303 	int w, h;
304 } fb_p4sizedecode[P4_SIZE_MASK+1] = {
305 	{ 1600, 1280 },
306 	{ 1152,  900 },
307 	{ 1024, 1024 },
308 	{ 1280, 1024 },
309 	{ 1440, 1440 },
310 	{  640,  480 },
311 };
312 
313 /*
314  * Use the P4 register to determine the screen size.
315  */
316 void
317 fb_pfour_setsize(fb)
318 	struct fbdevice *fb;
319 {
320 	int p4, p4type, p4size;
321 	int h, w;
322 
323 	if (fb->fb_pfour == 0)
324 		return;
325 
326 	p4 = *fb->fb_pfour;
327 	p4type = P4_FBTYPE(p4);
328 
329 	/* These do not encode the screen size. */
330 	if (p4type == P4_ID_COLOR24)
331 		return;
332 	if ((p4type & P4_ID_MASK) == P4_ID_FASTCOLOR)
333 		return;
334 
335 	p4size = p4type & P4_SIZE_MASK;
336 	w = fb_p4sizedecode[p4size].w;
337 	h = fb_p4sizedecode[p4size].h;
338 	if (w && h) {
339 		fb->fb_fbtype.fb_width  = w;
340 		fb->fb_fbtype.fb_height = h;
341 	} else {
342 		printf("%s: P4 size code %d unknown\n",
343 			   fb->fb_name, p4size);
344 	}
345 }
346