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