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