Home | History | Annotate | Line # | Download | only in dev
cg4.c revision 1.12
      1 /*	$NetBSD: cg4.c,v 1.12 1996/12/17 21:10:39 gwr 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. All advertising materials mentioning features or use of this software
     25  *    must display the following acknowledgement:
     26  *	This product includes software developed by the University of
     27  *	California, Berkeley and its contributors.
     28  * 4. Neither the name of the University nor the names of its contributors
     29  *    may be used to endorse or promote products derived from this software
     30  *    without specific prior written permission.
     31  *
     32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     42  * SUCH DAMAGE.
     43  *
     44  *	from: @(#)cgthree.c	8.2 (Berkeley) 10/30/93
     45  */
     46 
     47 /*
     48  * color display (cg4) driver.
     49  *
     50  * Credits, history:
     51  * Gordon Ross created this driver based on the cg3 driver from
     52  * the sparc port as distributed in BSD 4.4 Lite, but included
     53  * support for only the "type B" adapter (Brooktree DACs).
     54  * Ezra Story added support for the "type A" (AMD DACs).
     55  *
     56  * Todo:
     57  * Make this driver handle video interrupts.
     58  * Defer colormap updates to vertical retrace interrupts.
     59  */
     60 
     61 #include <sys/param.h>
     62 #include <sys/systm.h>
     63 #include <sys/conf.h>
     64 #include <sys/device.h>
     65 #include <sys/ioctl.h>
     66 #include <sys/malloc.h>
     67 #include <sys/mman.h>
     68 #include <sys/proc.h>
     69 #include <sys/tty.h>
     70 
     71 #include <vm/vm.h>
     72 
     73 #include <machine/autoconf.h>
     74 #include <machine/cpu.h>
     75 #include <machine/fbio.h>
     76 #include <machine/idprom.h>
     77 #include <machine/pmap.h>
     78 
     79 #include "fbvar.h"
     80 #include "btreg.h"
     81 #include "btvar.h"
     82 #include "cg4reg.h"
     83 
     84 cdev_decl(cg4);
     85 
     86 #define	CG4_MMAP_SIZE (CG4_OVERLAY_SIZE + CG4_ENABLE_SIZE + CG4_PIXMAP_SIZE)
     87 
     88 extern unsigned char cpu_machine_id;
     89 
     90 #define CMAP_SIZE 256
     91 struct soft_cmap {
     92 	u_char r[CMAP_SIZE];
     93 	u_char g[CMAP_SIZE];
     94 	u_char b[CMAP_SIZE];
     95 };
     96 
     97 /* per-display variables */
     98 struct cg4_softc {
     99 	struct	device sc_dev;		/* base device */
    100 	struct	fbdevice sc_fb;		/* frame buffer device */
    101 	int 	sc_cg4type;		/* A or B */
    102 	void	*sc_va_cmap;		/* Colormap h/w (mapped KVA) */
    103 	int 	sc_pa_overlay;		/* phys. addr. of overlay plane */
    104 	int 	sc_pa_enable;		/* phys. addr. of enable plane */
    105 	int 	sc_pa_pixmap;		/* phys. addr. of color plane */
    106 	int 	sc_blanked;		/* true if blanked */
    107 
    108 	union bt_cmap *sc_btcm;		/* Brooktree color map */
    109 	struct soft_cmap sc_cmap;	/* Generic soft colormap. */
    110 };
    111 
    112 /* autoconfiguration driver */
    113 static void	cg4attach __P((struct device *, struct device *, void *));
    114 static int	cg4match __P((struct device *, struct cfdata *, void *));
    115 
    116 struct cfattach cgfour_ca = {
    117 	sizeof(struct cg4_softc), cg4match, cg4attach
    118 };
    119 
    120 struct cfdriver cgfour_cd = {
    121 	NULL, "cgfour", DV_DULL
    122 };
    123 
    124 static int	cg4gattr   __P((struct fbdevice *, void *));
    125 static int	cg4gvideo  __P((struct fbdevice *, void *));
    126 static int	cg4svideo  __P((struct fbdevice *, void *));
    127 static int	cg4getcmap __P((struct fbdevice *, void *));
    128 static int	cg4putcmap __P((struct fbdevice *, void *));
    129 
    130 static void	cg4a_init   __P((struct cg4_softc *));
    131 static void	cg4a_svideo __P((struct cg4_softc *, int));
    132 static void	cg4a_ldcmap __P((struct cg4_softc *));
    133 
    134 static void	cg4b_init   __P((struct cg4_softc *));
    135 static void	cg4b_svideo __P((struct cg4_softc *, int));
    136 static void	cg4b_ldcmap __P((struct cg4_softc *));
    137 
    138 static struct fbdriver cg4_fbdriver = {
    139 	cg4open, cg4close, cg4mmap, cg4gattr,
    140 	cg4gvideo, cg4svideo,
    141 	cg4getcmap, cg4putcmap };
    142 
    143 /*
    144  * Match a cg4.
    145  */
    146 static int
    147 cg4match(parent, cf, args)
    148 	struct device *parent;
    149 	struct cfdata *cf;
    150 	void *args;
    151 {
    152 	struct confargs *ca = args;
    153 	int paddr;
    154 
    155 	/* XXX: Huge hack due to lack of probe info... */
    156 	/* XXX: Machines that might have a cg4 (gag). */
    157 	/* XXX: Need info on the "P4" register... */
    158 	switch (cpu_machine_id) {
    159 
    160 	case SUN3_MACH_110:
    161 		/* XXX: Assume type A. */
    162 		if (ca->ca_paddr == -1)
    163 			ca->ca_paddr = CG4A_DEF_BASE;
    164 		if (bus_peek(ca->ca_bustype, ca->ca_paddr, 1) == -1)
    165 			return (0);
    166 		if (bus_peek(BUS_OBIO, CG4A_OBIO_CMAP, 1) == -1)
    167 			return (0);
    168 		break;
    169 
    170 	case SUN3_MACH_60:
    171 		/* XXX: Assume type A. */
    172 		if (ca->ca_paddr == -1)
    173 			ca->ca_paddr = CG4B_DEF_BASE;
    174 		paddr = ca->ca_paddr;
    175 		if (bus_peek(ca->ca_bustype, paddr, 1) == -1)
    176 			return (0);
    177         /* Make sure we're color */
    178 		paddr += CG4B_OFF_PIXMAP;
    179 		if (bus_peek(ca->ca_bustype, paddr, 1) == -1)
    180 			return (0);
    181 		break;
    182 
    183 	default:
    184 		return (0);
    185 	}
    186 
    187 	return (1);
    188 }
    189 
    190 /*
    191  * Attach a display.  We need to notice if it is the console, too.
    192  */
    193 static void
    194 cg4attach(parent, self, args)
    195 	struct device *parent, *self;
    196 	void *args;
    197 {
    198 	struct cg4_softc *sc = (struct cg4_softc *)self;
    199 	struct fbdevice *fb = &sc->sc_fb;
    200 	struct confargs *ca = args;
    201 	struct fbtype *fbt;
    202 
    203 	/* XXX: should do better than this... */
    204 	switch (cpu_machine_id) {
    205 	case SUN3_MACH_110:
    206 		sc->sc_cg4type = CG4_TYPE_A;
    207 		break;
    208 	case SUN3_MACH_60:
    209 	default:
    210 		sc->sc_cg4type = CG4_TYPE_B;
    211 	}
    212 
    213 	fb->fb_driver = &cg4_fbdriver;
    214 	fb->fb_private = sc;
    215 	fb->fb_name = sc->sc_dev.dv_xname;
    216 
    217 	fbt = &fb->fb_fbtype;
    218 	fbt->fb_type = FBTYPE_SUN4COLOR;
    219 	fbt->fb_depth = 8;
    220 	fbt->fb_cmsize = 256;
    221 
    222 	fbt->fb_width = 1152;
    223 	fbt->fb_height = 900;
    224 	fbt->fb_size = CG4_MMAP_SIZE;
    225 
    226 	switch (sc->sc_cg4type) {
    227 	case CG4_TYPE_A:	/* Sun3/110 */
    228 		sc->sc_va_cmap = bus_mapin(BUS_OBIO, CG4A_OBIO_CMAP,
    229 		                           sizeof(struct amd_regs));
    230 		sc->sc_pa_overlay = ca->ca_paddr + CG4A_OFF_OVERLAY;
    231 		sc->sc_pa_enable  = ca->ca_paddr + CG4A_OFF_ENABLE;
    232 		sc->sc_pa_pixmap  = ca->ca_paddr + CG4A_OFF_PIXMAP;
    233 		sc->sc_btcm = NULL;
    234 		cg4a_init(sc);
    235 		break;
    236 
    237 	case CG4_TYPE_B:	/* Sun3/60 */
    238 	default:
    239 		sc->sc_va_cmap = (struct bt_regs *)
    240 			bus_mapin(ca->ca_bustype, ca->ca_paddr,
    241 					  sizeof(struct bt_regs *));
    242 		sc->sc_pa_overlay = ca->ca_paddr + CG4B_OFF_OVERLAY;
    243 		sc->sc_pa_enable  = ca->ca_paddr + CG4B_OFF_ENABLE;
    244 		sc->sc_pa_pixmap  = ca->ca_paddr + CG4B_OFF_PIXMAP;
    245 		sc->sc_btcm = malloc(sizeof(union bt_cmap), M_DEVBUF, M_WAITOK);
    246 		cg4b_init(sc);
    247 		break;
    248 	}
    249 
    250 	printf(" (%dx%d)\n", fbt->fb_width, fbt->fb_height);
    251 	fb_attach(fb, 4);
    252 }
    253 
    254 int
    255 cg4open(dev, flags, mode, p)
    256 	dev_t dev;
    257 	int flags, mode;
    258 	struct proc *p;
    259 {
    260 	int unit = minor(dev);
    261 
    262 	if (unit >= cgfour_cd.cd_ndevs || cgfour_cd.cd_devs[unit] == NULL)
    263 		return (ENXIO);
    264 	return (0);
    265 }
    266 
    267 int
    268 cg4close(dev, flags, mode, p)
    269 	dev_t dev;
    270 	int flags, mode;
    271 	struct proc *p;
    272 {
    273 
    274 	return (0);
    275 }
    276 
    277 int
    278 cg4ioctl(dev, cmd, data, flags, p)
    279 	dev_t dev;
    280 	u_long cmd;
    281 	caddr_t data;
    282 	int flags;
    283 	struct proc *p;
    284 {
    285 	struct cg4_softc *sc = cgfour_cd.cd_devs[minor(dev)];
    286 
    287 	return (fbioctlfb(&sc->sc_fb, cmd, data));
    288 }
    289 
    290 /*
    291  * Return the address that would map the given device at the given
    292  * offset, allowing for the given protection, or return -1 for error.
    293  *
    294  * X11 expects its mmap'd region to look like this:
    295  * 	128k overlay data memory
    296  * 	128k overlay enable bitmap
    297  * 	1024k color memory
    298  *
    299  * The hardware really looks like this (starting at ca_paddr)
    300  *  4 bytes Brooktree DAC registers
    301  *  2MB-4 gap
    302  * 	128k overlay memory
    303  * 	1920k gap
    304  * 	128k overlay-enable bitmap
    305  * 	1920k gap
    306  * 	1024k color memory
    307  */
    308 int
    309 cg4mmap(dev, off, prot)
    310 	dev_t dev;
    311 	register int off;
    312 	int prot;
    313 {
    314 	struct cg4_softc *sc = cgfour_cd.cd_devs[minor(dev)];
    315 	register int physbase;
    316 
    317 	if (off & PGOFSET)
    318 		panic("cg4mmap");
    319 
    320 	if ((unsigned)off >= CG4_MMAP_SIZE)
    321 		return (-1);
    322 
    323 	if (off < 0x40000) {
    324 		if (off < 0x20000) {
    325 			physbase = sc->sc_pa_overlay;
    326 		} else {
    327 			/* enable plane */
    328 			off -= 0x20000;
    329 			physbase = sc->sc_pa_enable;
    330 		}
    331 	} else {
    332 		/* pixel map */
    333 		off -= 0x40000;
    334 		physbase = sc->sc_pa_pixmap;
    335 	}
    336 
    337 	/*
    338 	 * I turned on PMAP_NC here to disable the cache as I was
    339 	 * getting horribly broken behaviour with it on.
    340 	 */
    341 	return ((physbase + off) | PMAP_NC);
    342 }
    343 
    344 /*
    345  * Internal ioctl functions.
    346  */
    347 
    348 /* FBIOGATTR: */
    349 static int  cg4gattr(fb, data)
    350 	struct fbdevice *fb;
    351 	void *data;
    352 {
    353 	struct fbgattr *fba = data;
    354 
    355 	fba->real_type = fb->fb_fbtype.fb_type;
    356 	fba->owner = 0;		/* XXX - TIOCCONS stuff? */
    357 	fba->fbtype = fb->fb_fbtype;
    358 	fba->sattr.flags = 0;
    359 	fba->sattr.emu_type = fb->fb_fbtype.fb_type;
    360 	fba->sattr.dev_specific[0] = -1;
    361 	fba->emu_types[0] = fb->fb_fbtype.fb_type;
    362 	fba->emu_types[1] = -1;
    363 	return (0);
    364 }
    365 
    366 /* FBIOGVIDEO: */
    367 static int  cg4gvideo(fb, data)
    368 	struct fbdevice *fb;
    369 	void *data;
    370 {
    371 	int *on = data;
    372 	struct cg4_softc *sc = fb->fb_private;
    373 
    374 	*on = !sc->sc_blanked;
    375 	return (0);
    376 }
    377 
    378 /* FBIOSVIDEO: */
    379 static int cg4svideo(fb, data)
    380 	struct fbdevice *fb;
    381 	void *data;
    382 {
    383 	int *on = data;
    384 	struct cg4_softc *sc = fb->fb_private;
    385 	int state;
    386 
    387 	state = *on;
    388 	if (sc->sc_cg4type == CG4_TYPE_A)
    389 		cg4a_svideo(sc, state);
    390 	else
    391 		cg4b_svideo(sc, state);
    392 	return (0);
    393 }
    394 
    395 /*
    396  * FBIOGETCMAP:
    397  * Copy current colormap out to user space.
    398  */
    399 static int cg4getcmap(fb, data)
    400 	struct fbdevice *fb;
    401 	void *data;
    402 {
    403 	struct fbcmap *fbcm = data;
    404 	struct cg4_softc *sc = fb->fb_private;
    405 	struct soft_cmap *cm = &sc->sc_cmap;
    406 	int error, start, count;
    407 
    408 	start = fbcm->index;
    409 	count = fbcm->count;
    410 	if ((start < 0) || (start >= CMAP_SIZE) ||
    411 	    (count < 0) || (start + count > CMAP_SIZE) )
    412 		return (EINVAL);
    413 
    414 	if ((error = copyout(&cm->r[start], fbcm->red, count)) != 0)
    415 		return (error);
    416 
    417 	if ((error = copyout(&cm->g[start], fbcm->green, count)) != 0)
    418 		return (error);
    419 
    420 	if ((error = copyout(&cm->b[start], fbcm->blue, count)) != 0)
    421 		return (error);
    422 
    423 	return (0);
    424 }
    425 
    426 /*
    427  * FBIOPUTCMAP:
    428  * Copy new colormap from user space and load.
    429  */
    430 static int cg4putcmap(fb, data)
    431 	struct fbdevice *fb;
    432 	void *data;
    433 {
    434 	struct fbcmap *fbcm = data;
    435 	struct cg4_softc *sc = fb->fb_private;
    436 	struct soft_cmap *cm = &sc->sc_cmap;
    437 	int error, start, count;
    438 
    439 	start = fbcm->index;
    440 	count = fbcm->count;
    441 	if ((start < 0) || (start >= CMAP_SIZE) ||
    442 	    (count < 0) || (start + count > CMAP_SIZE) )
    443 		return (EINVAL);
    444 
    445 	if ((error = copyin(fbcm->red, &cm->r[start], count)) != 0)
    446 		return (error);
    447 
    448 	if ((error = copyin(fbcm->green, &cm->g[start], count)) != 0)
    449 		return (error);
    450 
    451 	if ((error = copyin(fbcm->blue, &cm->b[start], count)) != 0)
    452 		return (error);
    453 
    454 	if (sc->sc_cg4type == CG4_TYPE_A)
    455 		cg4a_ldcmap(sc);
    456 	else
    457 		cg4b_ldcmap(sc);
    458 
    459 	return (0);
    460 }
    461 
    462 /****************************************************************
    463  * Routines for the "Type A" hardware
    464  ****************************************************************/
    465 
    466 static void
    467 cg4a_init(sc)
    468 	struct cg4_softc *sc;
    469 {
    470 	volatile struct amd_regs *ar = sc->sc_va_cmap;
    471 	struct soft_cmap *cm = &sc->sc_cmap;
    472 	int i;
    473 
    474 	/* grab initial (current) color map */
    475 	for(i = 0; i < 256; i++) {
    476 		cm->r[i] = ar->r[i];
    477 		cm->g[i] = ar->g[i];
    478 		cm->b[i] = ar->b[i];
    479 	}
    480 }
    481 
    482 static void
    483 cg4a_ldcmap(sc)
    484 	struct cg4_softc *sc;
    485 {
    486 	volatile struct amd_regs *ar = sc->sc_va_cmap;
    487 	struct soft_cmap *cm = &sc->sc_cmap;
    488 	int i;
    489 
    490 	/*
    491 	 * Now blast them into the chip!
    492 	 * XXX Should use retrace interrupt!
    493 	 * Just set a "need load" bit and let the
    494 	 * retrace interrupt handler do the work.
    495 	 */
    496 	for(i = 0; i < 256; i++) {
    497 		ar->r[i] = cm->r[i];
    498 		ar->g[i] = cm->g[i];
    499 		ar->b[i] = cm->b[i];
    500 	}
    501 }
    502 
    503 static void
    504 cg4a_svideo(sc, on)
    505 	struct cg4_softc *sc;
    506 	int on;
    507 {
    508 	volatile struct amd_regs *ar = sc->sc_va_cmap;
    509 	int i;
    510 
    511 	if ((on == 0) && (sc->sc_blanked == 0)) {
    512 		/* Turn OFF video (make it blank). */
    513 		sc->sc_blanked = 1;
    514 		/* Load fake "all zero" colormap. */
    515 		for (i = 0; i < 256; i++) {
    516 			ar->r[i] = 0;
    517 			ar->g[i] = 0;
    518 			ar->b[i] = 0;
    519 		}
    520 	}
    521 
    522 	if ((on != 0) && (sc->sc_blanked != 0)) {
    523 		/* Turn video back ON (unblank). */
    524 		sc->sc_blanked = 0;
    525 		/* Restore normal colormap. */
    526 		cg4a_ldcmap(sc);
    527 	}
    528 }
    529 
    530 
    531 /****************************************************************
    532  * Routines for the "Type B" hardware
    533  ****************************************************************/
    534 
    535 static void
    536 cg4b_init(sc)
    537 	struct cg4_softc *sc;
    538 {
    539 	volatile struct bt_regs *bt = sc->sc_va_cmap;
    540 	struct soft_cmap *cm = &sc->sc_cmap;
    541 	union bt_cmap *btcm = sc->sc_btcm;
    542 	int i;
    543 
    544 	/*
    545 	 * BT458 chip initialization as described in Brooktree's
    546 	 * 1993 Graphics and Imaging Product Databook (DB004-1/93).
    547 	 */
    548 	bt->bt_addr = 0x04;	/* select read mask register */
    549 	bt->bt_ctrl = 0xff;	/* all planes on */
    550 	bt->bt_addr = 0x05;	/* select blink mask register */
    551 	bt->bt_ctrl = 0x00;	/* all planes non-blinking */
    552 	bt->bt_addr = 0x06;	/* select command register */
    553 	bt->bt_ctrl = 0x43;	/* palette enabled, overlay planes enabled */
    554 	bt->bt_addr = 0x07;	/* select test register */
    555 	bt->bt_ctrl = 0x00;	/* set test mode */
    556 
    557 	/* grab initial (current) color map */
    558 	bt->bt_addr = 0;
    559 	for (i = 0; i < (256 * 3 / 4); i++) {
    560 		btcm->cm_chip[i] = bt->bt_cmap;
    561 	}
    562 
    563 	/* Transpose into S/W form. */
    564 	for (i = 0; i < 256; i++) {
    565 		cm->r[i] = btcm->cm_map[i][0];
    566 		cm->g[i] = btcm->cm_map[i][1];
    567 		cm->b[i] = btcm->cm_map[i][2];
    568 	}
    569 }
    570 
    571 static void
    572 cg4b_ldcmap(sc)
    573 	struct cg4_softc *sc;
    574 {
    575 	volatile struct bt_regs *bt = sc->sc_va_cmap;
    576 	struct soft_cmap *cm = &sc->sc_cmap;
    577 	union bt_cmap *btcm = sc->sc_btcm;
    578 	int i;
    579 
    580 	/*
    581 	 * Now blast them into the chip!
    582 	 * XXX Should use retrace interrupt!
    583 	 * Just set a "need load" bit and let the
    584 	 * retrace interrupt handler do the work.
    585 	 */
    586 
    587 	/* Transpose into H/W form. */
    588 	for (i = 0; i < 256; i++) {
    589 		btcm->cm_map[i][0] = cm->r[i];
    590 		btcm->cm_map[i][1] = cm->g[i];
    591 		btcm->cm_map[i][2] = cm->b[i];
    592 	}
    593 
    594 	bt->bt_addr = 0;
    595 	for (i = 0; i < (256 * 3 / 4); i++) {
    596 		bt->bt_cmap = btcm->cm_chip[i];
    597 	}
    598 }
    599 
    600 static void
    601 cg4b_svideo(sc, on)
    602 	struct cg4_softc *sc;
    603 	int on;
    604 {
    605 	volatile struct bt_regs *bt = sc->sc_va_cmap;
    606 	int i;
    607 
    608 	if ((on == 0) && (sc->sc_blanked == 0)) {
    609 		/* Turn OFF video (make it blank). */
    610 		sc->sc_blanked = 1;
    611 		/* Load fake "all zero" colormap. */
    612 		bt->bt_addr = 0;
    613 		for (i = 0; i < (256 * 3 / 4); i++)
    614 			bt->bt_cmap = 0;
    615 	}
    616 
    617 	if ((on != 0) && (sc->sc_blanked != 0)) {
    618 		/* Turn video back ON (unblank). */
    619 		sc->sc_blanked = 0;
    620 		/* Restore normal colormap. */
    621 		cg4b_ldcmap(sc);
    622 	}
    623 }
    624 
    625