Home | History | Annotate | Line # | Download | only in dev
fb.c revision 1.13
      1 /*	$NetBSD: fb.c,v 1.13 2005/12/11 12:19:20 christos 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.13 2005/12/11 12:19:20 christos 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(struct fbdevice *fb, int newpri)
     82 {
     83 	if (fbpriority < newpri) {
     84 		fbpriority = newpri;
     85 		devfb = fb;
     86 	}
     87 }
     88 
     89 int
     90 fbopen(dev_t dev, int flags, int mode, struct lwp *l)
     91 {
     92 
     93 	if (devfb == NULL)
     94 		return (ENXIO);
     95 	return ((*devfb->fb_driver->fbd_open)(dev, flags, mode, l));
     96 }
     97 
     98 int
     99 fbclose(dev_t dev, int flags, int mode, struct lwp *l)
    100 {
    101 
    102 	return ((*devfb->fb_driver->fbd_close)(dev, flags, mode, l));
    103 }
    104 
    105 int
    106 fbioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l)
    107 {
    108 	return (fbioctlfb(devfb, cmd, data));
    109 }
    110 
    111 paddr_t
    112 fbmmap(dev_t dev, off_t off, int prot)
    113 {
    114 	return ((*devfb->fb_driver->fbd_mmap)(dev, off, prot));
    115 }
    116 
    117 /*
    118  * Common fb ioctl function
    119  */
    120 int
    121 fbioctlfb(struct fbdevice *fb, u_long cmd, caddr_t data)
    122 {
    123 	struct fbdriver *fbd = fb->fb_driver;
    124 	void *vp = (void *)data;
    125 	int error;
    126 
    127 	switch (cmd) {
    128 
    129 	case FBIOGTYPE:
    130 		*(struct fbtype *)vp = fb->fb_fbtype;
    131 		error = 0;
    132 		break;
    133 
    134 	case FBIOGATTR:
    135 		error = (*fbd->fbd_gattr)(fb, vp);
    136 		break;
    137 
    138 	case FBIOGVIDEO:
    139 		error = (*fbd->fbd_gvideo)(fb, vp);
    140 		break;
    141 
    142 	case FBIOSVIDEO:
    143 		error = (*fbd->fbd_svideo)(fb, vp);
    144 		break;
    145 
    146 	case FBIOGETCMAP:
    147 		error = (*fbd->fbd_getcmap)(fb, vp);
    148 		break;
    149 
    150 	case FBIOPUTCMAP:
    151 		error = (*fbd->fbd_putcmap)(fb, vp);
    152 		break;
    153 
    154 	default:
    155 		error = ENOTTY;
    156 	}
    157 	return (error);
    158 }
    159 
    160 void
    161 fb_unblank(void)
    162 {
    163 	int on = 1;
    164 
    165 	if (devfb == NULL)
    166 		return;
    167 
    168 	(*devfb->fb_driver->fbd_svideo)(devfb, (void *)&on);
    169 }
    170 
    171 /*
    172  * Default ioctl function to put in struct fbdriver
    173  * for functions that are not supported.
    174  */
    175 int
    176 fb_noioctl(struct fbdevice *fbd, void *vp)
    177 {
    178 	return ENOTTY;
    179 }
    180 
    181 /****************************************************************
    182  * Misc. helpers...
    183  */
    184 
    185 /* Set FB size based on EEPROM screen shape code. */
    186 void
    187 fb_eeprom_setsize(struct fbdevice *fb)
    188 {
    189 	int szcode;
    190 	int w, h;
    191 
    192 	/* Go get the EEPROM screen size byte. */
    193 	szcode = eeprom_copy->eeScreenSize;
    194 
    195 	w = h = 0;
    196 	switch (szcode) {
    197 	case EE_SCR_1152X900:
    198 		w = 1152;
    199 		h = 900;
    200 		break;
    201 	case EE_SCR_1024X1024:
    202 		w = 1024;
    203 		h = 1024;
    204 		break;
    205 	case EE_SCR_1600X1280:
    206 		w = 1600;
    207 		h = 1280;
    208 		break;
    209 	case EE_SCR_1440X1440:
    210 		w = 1440;
    211 		h = 1440;
    212 		break;
    213 	default:
    214 		break;
    215 	}
    216 
    217 	if (w && h) {
    218 		fb->fb_fbtype.fb_width  = w;
    219 		fb->fb_fbtype.fb_height = h;
    220 	} else {
    221 		printf("%s: EE size code %d unknown\n",
    222 			   fb->fb_name, szcode);
    223 	}
    224 }
    225 
    226 /*
    227  * Probe for a P4 register at the passed virtual address.
    228  * Returns P4 ID value, or -1 if no P4 register.
    229  */
    230 int
    231 fb_pfour_id(void *va)
    232 {
    233 	volatile uint32_t val, save, *pfour = va;
    234 
    235 	/* Read the P4 register. */
    236 	save = *pfour;
    237 
    238 	/*
    239 	 * Try to modify the type code.  If it changes, put the
    240 	 * original value back, and tell the caller that the
    241 	 * framebuffer does not have a P4 register.
    242 	 */
    243 	val = save & ~P4_REG_RESET;
    244 	*pfour = (val ^ P4_FBTYPE_MASK);
    245 	if ((*pfour ^ val) & P4_FBTYPE_MASK) {
    246 		*pfour = save;
    247 		return (-1);
    248 	}
    249 
    250 	return (P4_ID(val));
    251 }
    252 
    253 /*
    254  * Return the status of the video enable.
    255  */
    256 int
    257 fb_pfour_get_video(struct fbdevice *fb)
    258 {
    259 
    260 	return ((*fb->fb_pfour & P4_REG_VIDEO) != 0);
    261 }
    262 
    263 /*
    264  * Turn video on or off using the P4 register.
    265  */
    266 void
    267 fb_pfour_set_video(struct fbdevice *fb, int on)
    268 {
    269 	int pfour;
    270 
    271 	pfour = *fb->fb_pfour & ~(P4_REG_INTCLR|P4_REG_VIDEO);
    272 	*fb->fb_pfour = pfour | (on ? P4_REG_VIDEO : 0);
    273 }
    274 
    275 static const struct {
    276 	int w, h;
    277 } fb_p4sizedecode[P4_SIZE_MASK+1] = {
    278 	{ 1600, 1280 },
    279 	{ 1152,  900 },
    280 	{ 1024, 1024 },
    281 	{ 1280, 1024 },
    282 	{ 1440, 1440 },
    283 	{  640,  480 },
    284 };
    285 
    286 /*
    287  * Use the P4 register to determine the screen size.
    288  */
    289 void
    290 fb_pfour_setsize(struct fbdevice *fb)
    291 {
    292 	int p4, p4type, p4size;
    293 	int h, w;
    294 
    295 	if (fb->fb_pfour == 0)
    296 		return;
    297 
    298 	p4 = *fb->fb_pfour;
    299 	p4type = P4_FBTYPE(p4);
    300 
    301 	/* These do not encode the screen size. */
    302 	if (p4type == P4_ID_COLOR24)
    303 		return;
    304 	if ((p4type & P4_ID_MASK) == P4_ID_FASTCOLOR)
    305 		return;
    306 
    307 	p4size = p4type & P4_SIZE_MASK;
    308 	w = fb_p4sizedecode[p4size].w;
    309 	h = fb_p4sizedecode[p4size].h;
    310 	if (w && h) {
    311 		fb->fb_fbtype.fb_width  = w;
    312 		fb->fb_fbtype.fb_height = h;
    313 	} else {
    314 		printf("%s: P4 size code %d unknown\n",
    315 			   fb->fb_name, p4size);
    316 	}
    317 }
    318