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