fb.c revision 1.9 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