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