1 /* $NetBSD: cg4.c,v 1.38 2008/06/08 17:30:08 tsutsui Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
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.
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
40 * from: @(#)cgthree.c 8.2 (Berkeley) 10/30/93
44 * color display (cg4) driver.
47 * Gordon Ross created this driver based on the cg3 driver from
48 * the sparc port as distributed in BSD 4.4 Lite, but included
49 * support for only the "type B" adapter (Brooktree DACs).
50 * Ezra Story added support for the "type A" (AMD DACs).
53 * Make this driver handle video interrupts.
54 * Defer colormap updates to vertical retrace interrupts.
57 #include <sys/cdefs.h>
58 __KERNEL_RCSID(0, "$NetBSD: cg4.c,v 1.38 2008/06/08 17:30:08 tsutsui Exp $");
60 #include <sys/param.h>
61 #include <sys/systm.h>
63 #include <sys/device.h>
64 #include <sys/ioctl.h>
65 #include <sys/malloc.h>
70 #include <uvm/uvm_extern.h>
72 #include <machine/autoconf.h>
73 #include <machine/cpu.h>
74 #include <dev/sun/fbio.h>
75 #include <machine/idprom.h>
76 #include <machine/pmap.h>
78 #include <sun3/dev/fbvar.h>
79 #include <sun3/dev/btreg.h>
80 #include <sun3/dev/cg4reg.h>
81 #include <sun3/dev/p4reg.h>
86 uint8_t btcm_char
[256 * 3]; /* raw data */
87 uint8_t btcm_rgb
[256][3]; /* 256 R/G/B entries */
88 u_int btcm_int
[256 * 3 / 4]; /* the way the chip gets loaded */
91 #define CG4_TYPE_A 0 /* AMD DACs */
92 #define CG4_TYPE_B 1 /* Brooktree DACs */
94 #define CG4_MMAP_SIZE (CG4_OVERLAY_SIZE + CG4_ENABLE_SIZE + CG4_PIXMAP_SIZE)
100 uint8_t b
[CMAP_SIZE
];
103 /* per-display variables */
105 device_t sc_dev
; /* base device */
106 struct fbdevice sc_fb
; /* frame buffer device */
107 int sc_cg4type
; /* A or B */
108 int sc_pa_overlay
; /* phys. addr. of overlay plane */
109 int sc_pa_enable
; /* phys. addr. of enable plane */
110 int sc_pa_pixmap
; /* phys. addr. of color plane */
111 int sc_video_on
; /* zero if blanked */
112 void *sc_va_cmap
; /* Colormap h/w (mapped KVA) */
113 void *sc_btcm
; /* Soft cmap, Brooktree format */
114 void (*sc_ldcmap
)(struct cg4_softc
*);
115 struct soft_cmap sc_cmap
; /* Soft cmap, user format */
118 /* autoconfiguration driver */
119 static int cg4match(device_t
, cfdata_t
, void *);
120 static void cg4attach(device_t
, device_t
, void *);
122 CFATTACH_DECL_NEW(cgfour
, sizeof(struct cg4_softc
),
123 cg4match
, cg4attach
, NULL
, NULL
);
125 dev_type_open(cg4open
);
126 dev_type_ioctl(cg4ioctl
);
127 dev_type_mmap(cg4mmap
);
129 const struct cdevsw cgfour_cdevsw
= {
130 cg4open
, nullclose
, noread
, nowrite
, cg4ioctl
,
131 nostop
, notty
, nopoll
, cg4mmap
, nokqfilter
,
134 static int cg4gattr (struct fbdevice
*, void *);
135 static int cg4gvideo (struct fbdevice
*, void *);
136 static int cg4svideo (struct fbdevice
*, void *);
137 static int cg4getcmap(struct fbdevice
*, void *);
138 static int cg4putcmap(struct fbdevice
*, void *);
141 static void cg4a_init (struct cg4_softc
*);
142 static void cg4a_ldcmap(struct cg4_softc
*);
145 static void cg4b_init (struct cg4_softc
*);
146 static void cg4b_ldcmap(struct cg4_softc
*);
148 static struct fbdriver cg4_fbdriver
= {
149 cg4open
, nullclose
, cg4mmap
, nokqfilter
, cg4gattr
,
150 cg4gvideo
, cg4svideo
,
151 cg4getcmap
, cg4putcmap
};
157 cg4match(device_t parent
, cfdata_t cf
, void *args
)
159 struct confargs
*ca
= args
;
160 int mid
, p4id
, peekval
, tmp
;
163 /* No default address support. */
164 if (ca
->ca_paddr
== -1)
168 * Slight hack here: The low four bits of the
169 * config flags, if set, restrict the match to
170 * that machine "implementation" only.
172 mid
= cf
->cf_flags
& IDM_IMPL_MASK
;
173 if (mid
&& (mid
!= (cpu_machine_id
& IDM_IMPL_MASK
)))
177 * The config flag 0x10 if set means we are
178 * looking for a Type A board (3/110).
180 if (cf
->cf_flags
& 0x10) {
182 /* Type A: Check for AMD RAMDACs in control space. */
183 if (bus_peek(BUS_OBIO
, CG4A_OBIO_CMAP
, 1) == -1)
185 /* Check for the overlay plane. */
186 tmp
= ca
->ca_paddr
+ CG4A_OFF_OVERLAY
;
187 if (bus_peek(ca
->ca_bustype
, tmp
, 1) == -1)
189 /* OK, it looks like a Type A. */
192 /* Only the Sun3/110 ever has a type A. */
198 * From here on, it is a type B or nothing.
199 * The config flag 0x20 if set means there
200 * is no P4 register. (bus error)
202 if ((cf
->cf_flags
& 0x20) == 0) {
203 p4reg
= bus_tmapin(ca
->ca_bustype
, ca
->ca_paddr
);
204 peekval
= peek_long(p4reg
);
205 p4id
= (peekval
== -1) ?
206 P4_NOTFOUND
: fb_pfour_id(p4reg
);
210 if (p4id
!= P4_ID_COLOR8P1
) {
212 aprint_debug("cgfour at 0x%lx match p4id=0x%x fails\n",
213 ca
->ca_paddr
, p4id
& 0xFF);
220 * Check for CMAP hardware and overlay plane.
222 tmp
= ca
->ca_paddr
+ CG4B_OFF_CMAP
;
223 if (bus_peek(ca
->ca_bustype
, tmp
, 4) == -1)
225 tmp
= ca
->ca_paddr
+ CG4B_OFF_OVERLAY
;
226 if (bus_peek(ca
->ca_bustype
, tmp
, 1) == -1)
233 * Attach a display. We need to notice if it is the console, too.
236 cg4attach(device_t parent
, device_t self
, void *args
)
238 struct cg4_softc
*sc
= device_private(self
);
239 struct fbdevice
*fb
= &sc
->sc_fb
;
240 struct confargs
*ca
= args
;
246 fbt
= &fb
->fb_fbtype
;
247 fbt
->fb_type
= FBTYPE_SUN4COLOR
;
248 fbt
->fb_width
= 1152; /* default - see below */
249 fbt
->fb_height
= 900; /* default - see below */
251 fbt
->fb_cmsize
= 256;
252 fbt
->fb_size
= CG4_MMAP_SIZE
;
253 fb
->fb_driver
= &cg4_fbdriver
;
255 fb
->fb_name
= device_xname(self
);
256 fb
->fb_flags
= device_cfdata(self
)->cf_flags
;
259 * The config flag 0x10 if set means we are
260 * attaching a Type A (3/110) which has the
261 * AMD RAMDACs in control space, and no P4.
263 if (fb
->fb_flags
& 0x10) {
265 sc
->sc_cg4type
= CG4_TYPE_A
;
266 sc
->sc_ldcmap
= cg4a_ldcmap
;
267 sc
->sc_pa_overlay
= ca
->ca_paddr
+ CG4A_OFF_OVERLAY
;
268 sc
->sc_pa_enable
= ca
->ca_paddr
+ CG4A_OFF_ENABLE
;
269 sc
->sc_pa_pixmap
= ca
->ca_paddr
+ CG4A_OFF_PIXMAP
;
270 sc
->sc_va_cmap
= bus_mapin(BUS_OBIO
, CG4A_OBIO_CMAP
,
271 sizeof(struct amd_regs
));
274 panic("cgfour flags 0x10");
277 sc
->sc_cg4type
= CG4_TYPE_B
;
278 sc
->sc_ldcmap
= cg4b_ldcmap
;
279 sc
->sc_pa_overlay
= ca
->ca_paddr
+ CG4B_OFF_OVERLAY
;
280 sc
->sc_pa_enable
= ca
->ca_paddr
+ CG4B_OFF_ENABLE
;
281 sc
->sc_pa_pixmap
= ca
->ca_paddr
+ CG4B_OFF_PIXMAP
;
282 tmp
= ca
->ca_paddr
+ CG4B_OFF_CMAP
;
283 sc
->sc_va_cmap
= bus_mapin(ca
->ca_bustype
, tmp
,
284 sizeof(struct bt_regs
));
288 if ((fb
->fb_flags
& 0x20) == 0) {
289 /* It is supposed to have a P4 register. */
290 fb
->fb_pfour
= bus_mapin(ca
->ca_bustype
, ca
->ca_paddr
, 4);
294 * Determine width and height as follows:
295 * If it has a P4 register, use that;
296 * else if unit==0, use the EEPROM size,
297 * else make our best guess.
300 fb_pfour_setsize(fb
);
301 /* XXX device_unit() abuse */
302 else if (device_unit(self
) == 0)
303 fb_eeprom_setsize(fb
);
305 /* Guess based on machine ID. */
306 switch (cpu_machine_id
) {
308 /* Leave the defaults set above. */
312 aprint_normal(" (%dx%d)\n", fbt
->fb_width
, fbt
->fb_height
);
315 * Make sure video is on. This driver uses a
316 * black colormap to blank the screen, so if
317 * there is any global enable, set it here.
322 fb_pfour_set_video(fb
, 1);
326 /* Let /dev/fb know we are here. */
331 cg4open(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
333 struct cg4_softc
*sc
;
334 int unit
= minor(dev
);
336 sc
= device_lookup_private(&cgfour_cd
, unit
);
343 cg4ioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
345 struct cg4_softc
*sc
= device_lookup_private(&cgfour_cd
, minor(dev
));
347 return fbioctlfb(&sc
->sc_fb
, cmd
, data
);
351 * Return the address that would map the given device at the given
352 * offset, allowing for the given protection, or return -1 for error.
354 * X11 expects its mmap'd region to look like this:
355 * 128k overlay data memory
356 * 128k overlay enable bitmap
359 * The hardware looks completely different.
362 cg4mmap(dev_t dev
, off_t off
, int prot
)
364 struct cg4_softc
*sc
= device_lookup_private(&cgfour_cd
, minor(dev
));
368 panic("%s: bad offset", __func__
);
370 if ((off
< 0) || (off
>= CG4_MMAP_SIZE
))
375 physbase
= sc
->sc_pa_overlay
;
379 physbase
= sc
->sc_pa_enable
;
384 physbase
= sc
->sc_pa_pixmap
;
388 * I turned on PMAP_NC here to disable the cache as I was
389 * getting horribly broken behaviour without it.
391 return (physbase
+ off
) | PMAP_NC
;
395 * Internal ioctl functions.
400 cg4gattr(struct fbdevice
*fb
, void *data
)
402 struct fbgattr
*fba
= data
;
404 fba
->real_type
= fb
->fb_fbtype
.fb_type
;
405 fba
->owner
= 0; /* XXX - TIOCCONS stuff? */
406 fba
->fbtype
= fb
->fb_fbtype
;
407 fba
->sattr
.flags
= 0;
408 fba
->sattr
.emu_type
= fb
->fb_fbtype
.fb_type
;
409 fba
->sattr
.dev_specific
[0] = -1;
410 fba
->emu_types
[0] = fb
->fb_fbtype
.fb_type
;
411 fba
->emu_types
[1] = -1;
417 cg4gvideo(struct fbdevice
*fb
, void *data
)
419 struct cg4_softc
*sc
= fb
->fb_private
;
422 *on
= sc
->sc_video_on
;
428 cg4svideo(struct fbdevice
*fb
, void *data
)
430 struct cg4_softc
*sc
= fb
->fb_private
;
433 if (sc
->sc_video_on
== *on
)
435 sc
->sc_video_on
= *on
;
437 (*sc
->sc_ldcmap
)(sc
);
443 * Copy current colormap out to user space.
446 cg4getcmap(struct fbdevice
*fb
, void *data
)
448 struct cg4_softc
*sc
= fb
->fb_private
;
449 struct soft_cmap
*cm
= &sc
->sc_cmap
;
450 struct fbcmap
*fbcm
= data
;
456 if (start
>= CMAP_SIZE
|| count
> CMAP_SIZE
- start
)
459 if ((error
= copyout(&cm
->r
[start
], fbcm
->red
, count
)) != 0)
462 if ((error
= copyout(&cm
->g
[start
], fbcm
->green
, count
)) != 0)
465 if ((error
= copyout(&cm
->b
[start
], fbcm
->blue
, count
)) != 0)
473 * Copy new colormap from user space and load.
476 cg4putcmap(struct fbdevice
*fb
, void *data
)
478 struct cg4_softc
*sc
= fb
->fb_private
;
479 struct soft_cmap
*cm
= &sc
->sc_cmap
;
480 struct fbcmap
*fbcm
= data
;
486 if (start
>= CMAP_SIZE
|| count
> CMAP_SIZE
- start
)
489 if ((error
= copyin(fbcm
->red
, &cm
->r
[start
], count
)) != 0)
492 if ((error
= copyin(fbcm
->green
, &cm
->g
[start
], count
)) != 0)
495 if ((error
= copyin(fbcm
->blue
, &cm
->b
[start
], count
)) != 0)
498 (*sc
->sc_ldcmap
)(sc
);
502 /****************************************************************
503 * Routines for the "Type A" hardware
504 ****************************************************************/
508 cg4a_init(struct cg4_softc
*sc
)
510 volatile struct amd_regs
*ar
= sc
->sc_va_cmap
;
511 struct soft_cmap
*cm
= &sc
->sc_cmap
;
514 /* Grab initial (current) color map. */
515 for(i
= 0; i
< 256; i
++) {
523 cg4a_ldcmap(struct cg4_softc
*sc
)
525 volatile struct amd_regs
*ar
= sc
->sc_va_cmap
;
526 struct soft_cmap
*cm
= &sc
->sc_cmap
;
530 * Now blast them into the chip!
531 * XXX Should use retrace interrupt!
532 * Just set a "need load" bit and let the
533 * retrace interrupt handler do the work.
535 if (sc
->sc_video_on
) {
536 /* Update H/W colormap. */
537 for (i
= 0; i
< 256; i
++) {
543 /* Clear H/W colormap. */
544 for (i
= 0; i
< 256; i
++) {
553 /****************************************************************
554 * Routines for the "Type B" hardware
555 ****************************************************************/
558 cg4b_init(struct cg4_softc
*sc
)
560 volatile struct bt_regs
*bt
= sc
->sc_va_cmap
;
561 struct soft_cmap
*cm
= &sc
->sc_cmap
;
562 union bt_cmap_u
*btcm
;
565 /* Need a buffer for colormap format translation. */
566 btcm
= malloc(sizeof(*btcm
), M_DEVBUF
, M_WAITOK
);
570 * BT458 chip initialization as described in Brooktree's
571 * 1993 Graphics and Imaging Product Databook (DB004-1/93).
573 * It appears that the 3/60 uses the low byte, and the 3/80
574 * uses the high byte, while both ignore the other bytes.
575 * Writing same value to all bytes works on both.
577 bt
->bt_addr
= 0x04040404; /* select read mask register */
578 bt
->bt_ctrl
= ~0; /* all planes on */
579 bt
->bt_addr
= 0x05050505; /* select blink mask register */
580 bt
->bt_ctrl
= 0; /* all planes non-blinking */
581 bt
->bt_addr
= 0x06060606; /* select command register */
582 bt
->bt_ctrl
= 0x43434343; /* palette enabled, overlay planes enabled */
583 bt
->bt_addr
= 0x07070707; /* select test register */
584 bt
->bt_ctrl
= 0; /* not test mode */
586 /* grab initial (current) color map */
589 /* Sun3/60 wants 32-bit access, packed. */
590 for (i
= 0; i
< (256 * 3 / 4); i
++)
591 btcm
->btcm_int
[i
] = bt
->bt_cmap
;
593 /* Sun3/80 wants 8-bits in the high byte. */
594 for (i
= 0; i
< (256 * 3); i
++)
595 btcm
->btcm_char
[i
] = bt
->bt_cmap
>> 24;
598 /* Transpose into H/W cmap into S/W form. */
599 for (i
= 0; i
< 256; i
++) {
600 cm
->r
[i
] = btcm
->btcm_rgb
[i
][0];
601 cm
->g
[i
] = btcm
->btcm_rgb
[i
][1];
602 cm
->b
[i
] = btcm
->btcm_rgb
[i
][2];
607 cg4b_ldcmap(struct cg4_softc
*sc
)
609 volatile struct bt_regs
*bt
= sc
->sc_va_cmap
;
610 struct soft_cmap
*cm
= &sc
->sc_cmap
;
611 union bt_cmap_u
*btcm
= sc
->sc_btcm
;
614 /* Transpose S/W cmap into H/W form. */
615 for (i
= 0; i
< 256; i
++) {
616 btcm
->btcm_rgb
[i
][0] = cm
->r
[i
];
617 btcm
->btcm_rgb
[i
][1] = cm
->g
[i
];
618 btcm
->btcm_rgb
[i
][2] = cm
->b
[i
];
622 * Now blast them into the chip!
623 * XXX Should use retrace interrupt!
624 * Just set a "need load" bit and let the
625 * retrace interrupt handler do the work.
630 /* Sun3/60 wants 32-bit access, packed. */
631 if (sc
->sc_video_on
) {
632 /* Update H/W colormap. */
633 for (i
= 0; i
< (256 * 3 / 4); i
++)
634 bt
->bt_cmap
= btcm
->btcm_int
[i
];
636 /* Clear H/W colormap. */
637 for (i
= 0; i
< (256 * 3 / 4); i
++)
641 /* Sun3/80 wants 8-bits in the high byte. */
642 if (sc
->sc_video_on
) {
643 /* Update H/W colormap. */
644 for (i
= 0; i
< (256 * 3); i
++)
645 bt
->bt_cmap
= btcm
->btcm_char
[i
] << 24;
647 /* Clear H/W colormap. */
648 for (i
= 0; i
< (256 * 3); i
++)