summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sparc/dev')
-rw-r--r--sys/arch/sparc/dev/tvtwo.c119
1 files changed, 83 insertions, 36 deletions
diff --git a/sys/arch/sparc/dev/tvtwo.c b/sys/arch/sparc/dev/tvtwo.c
index 1b9b628507a..a46eb9c44cb 100644
--- a/sys/arch/sparc/dev/tvtwo.c
+++ b/sys/arch/sparc/dev/tvtwo.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: tvtwo.c,v 1.9 2006/02/12 00:04:21 miod Exp $ */
+/* $OpenBSD: tvtwo.c,v 1.10 2006/02/12 12:02:29 miod Exp $ */
/*
- * Copyright (c) 2003, Miodrag Vallat.
+ * Copyright (c) 2003, 2006, Miodrag Vallat.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,8 +39,8 @@
*/
/*
- * Currently, this driver can only handle the 24-bit plane of the frame
- * buffer, in an unaccelerated mode.
+ * Currently, this driver can only handle the 8-bit and 24-bit planes of the
+ * frame buffer, in an unaccelerated mode.
*
* TODO:
* - nvram handling
@@ -90,13 +90,10 @@
* We currently refuse to attach to the old version because mapping
* things requires us to play with the sbus register ranges, and I
* don't want to play this game without the hardware at hand -- miod
- *
- * At PROM initialization, the board will be in 24-bit mode,
- * so no specific initialization is necessary.
*/
#define PX_PROM0_OFFSET 0x000000
-#define PX_OVERAY_OFFSET 0x010000
+#define PX_OVERLAY_OFFSET 0x010000
#define PX_REG_OFFSET 0x040000
#define PX_CCUBE_OFFSET 0x050000
#define PX_PLANE8_OFFSET 0x080000
@@ -125,6 +122,8 @@ struct tvtwo_softc {
struct sbusdev sc_sd; /* sbus device */
struct rom_reg sc_phys;
+ volatile u_int8_t *sc_m8;
+ volatile u_int8_t *sc_m24;
volatile u_int8_t *sc_regs;
};
@@ -132,10 +131,6 @@ int tvtwo_ioctl(void *, u_long, caddr_t, int, struct proc *);
paddr_t tvtwo_mmap(void *, off_t, int);
void tvtwo_burner(void *, u_int, u_int);
-static __inline__ void tvtwo_ramdac_wraddr(struct tvtwo_softc *sc,
- u_int32_t addr);
-void tvtwo_initcmap(struct tvtwo_softc *);
-
struct wsdisplay_accessops tvtwo_accessops = {
tvtwo_ioctl,
tvtwo_mmap,
@@ -149,6 +144,12 @@ struct wsdisplay_accessops tvtwo_accessops = {
NULL /* pollc */
};
+void tvtwo_directcmap(struct tvtwo_softc *);
+static __inline__
+void tvtwo_ramdac_wraddr(struct tvtwo_softc *, u_int32_t);
+void tvtwo_reset(struct tvtwo_softc *, u_int);
+void tvtwo_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
+
int tvtwomatch(struct device *, void *, void *);
void tvtwoattach(struct device *, struct device *, void *);
@@ -227,27 +228,36 @@ tvtwoattach(struct device *parent, struct device *self, void *args)
width = getpropint(node, "hres", width);
height = getpropint(node, "vres", height);
- fb_setsize(&sc->sc_sunfb, 32, width, height, node, ca->ca_bustype);
+
+ /*
+ * Since the depth property is usually missing, we could do
+ * fb_setsize(&sc->sc_sunfb, 8, width, height, node, ca->ca_bustype);
+ * but for safety in case it would exist and be set to 32, do it
+ * manually...
+ */
+ sc->sc_sunfb.sf_depth = 8;
+ sc->sc_sunfb.sf_width = width;
+ sc->sc_sunfb.sf_height = height;
+ sc->sc_sunfb.sf_linebytes = width;
+ sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_linebytes * height;
/* Map the frame buffer memory area we're interested in. */
sc->sc_phys = ca->ca_ra.ra_reg[0];
- sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg,
- PX_PLANE24_OFFSET, round_page(sc->sc_sunfb.sf_fbsize));
+ sc->sc_m8 = mapiodev(ca->ca_ra.ra_reg,
+ PX_PLANE8_OFFSET, round_page(sc->sc_sunfb.sf_fbsize));
+ sc->sc_m24 = mapiodev(ca->ca_ra.ra_reg,
+ PX_PLANE24_OFFSET, round_page(4 * sc->sc_sunfb.sf_fbsize));
- /* Initialize a direct color map. */
- tvtwo_initcmap(sc);
-
- /*
- * Clear display. We can't pass RI_CLEAR to fbwscons_init
- * below and have rasops do it for us as we want a white background.
- */
- memset(sc->sc_sunfb.sf_ro.ri_bits, 0xff, sc->sc_sunfb.sf_fbsize);
+ /* Enable video. */
+ tvtwo_burner(sc, 1, 0);
sc->sc_sunfb.sf_ro.ri_hw = sc;
- fbwscons_init(&sc->sc_sunfb, 0);
+ sc->sc_sunfb.sf_ro.ri_bits = (u_char *)sc->sc_m8;
+ fbwscons_init(&sc->sc_sunfb, isconsole ? RI_CLEARMARGINS : RI_CLEAR);
+ fbwscons_setcolormap(&sc->sc_sunfb, tvtwo_setcolor);
if (isconsole) {
- fbwscons_console_init(&sc->sc_sunfb, 0);
+ fbwscons_console_init(&sc->sc_sunfb, -1);
}
sbus_establish(&sc->sc_sd, &sc->sc_sunfb.sf_dev);
@@ -264,6 +274,10 @@ tvtwo_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
struct tvtwo_softc *sc = dev;
struct wsdisplay_fbinfo *wdf;
+ /*
+ * Note that, although the emulation (text) mode is running in a
+ * 8-bit plane, we advertize the frame buffer as 32-bit.
+ */
switch (cmd) {
case WSDISPLAYIO_GTYPE:
*(u_int *)data = WSDISPLAY_TYPE_SUN24;
@@ -272,17 +286,27 @@ tvtwo_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
wdf = (struct wsdisplay_fbinfo *)data;
wdf->height = sc->sc_sunfb.sf_height;
wdf->width = sc->sc_sunfb.sf_width;
- wdf->depth = sc->sc_sunfb.sf_depth;
+ wdf->depth = 32;
wdf->cmsize = 0;
break;
case WSDISPLAYIO_LINEBYTES:
- *(u_int *)data = sc->sc_sunfb.sf_linebytes;
+ *(u_int *)data = sc->sc_sunfb.sf_linebytes * 4;
break;
case WSDISPLAYIO_GETCMAP:
case WSDISPLAYIO_PUTCMAP:
break;
+ case WSDISPLAYIO_SMODE:
+ if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
+ /* Back from X11 to text mode */
+ tvtwo_reset(sc, 8);
+ } else {
+ /* Starting X11, initialize 32-bit mode */
+ tvtwo_reset(sc, 32);
+ }
+ break;
+
case WSDISPLAYIO_SVIDEO:
case WSDISPLAYIO_GVIDEO:
break;
@@ -308,7 +332,7 @@ tvtwo_mmap(void *v, off_t offset, int prot)
return (-1);
/* Allow mapping as a dumb framebuffer from offset 0 */
- if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
+ if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize * 4) {
return (REG2PHYS(&sc->sc_phys,
PX_PLANE24_OFFSET + offset) | PMAP_NC);
}
@@ -316,6 +340,30 @@ tvtwo_mmap(void *v, off_t offset, int prot)
return (-1);
}
+void
+tvtwo_burner(void *v, u_int on, u_int flags)
+{
+ struct tvtwo_softc *sc = v;
+ volatile u_int32_t *dispkludge =
+ (u_int32_t *)(sc->sc_regs + PX_REG_DISPKLUDGE);
+
+ if (on)
+ *dispkludge = DISPKLUDGE_DEFAULT & ~DISPKLUDGE_BLANK;
+ else
+ *dispkludge = DISPKLUDGE_DEFAULT | DISPKLUDGE_BLANK;
+}
+
+void
+tvtwo_reset(struct tvtwo_softc *sc, u_int depth)
+{
+ if (depth == 32) {
+ /* Initialize a direct color map. */
+ tvtwo_directcmap(sc);
+ } else {
+ fbwscons_setcolormap(&sc->sc_sunfb, tvtwo_setcolor);
+ }
+}
+
/*
* Simple Bt463 programming routines.
*/
@@ -330,7 +378,7 @@ tvtwo_ramdac_wraddr(struct tvtwo_softc *sc, u_int32_t addr)
}
void
-tvtwo_initcmap(struct tvtwo_softc *sc)
+tvtwo_directcmap(struct tvtwo_softc *sc)
{
volatile u_int32_t *dac = (u_int32_t *)(sc->sc_regs + PX_REG_BT463_RED);
u_int32_t c;
@@ -344,14 +392,13 @@ tvtwo_initcmap(struct tvtwo_softc *sc)
}
void
-tvtwo_burner(void *v, u_int on, u_int flags)
+tvtwo_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
{
struct tvtwo_softc *sc = v;
- volatile u_int32_t *dispkludge =
- (u_int32_t *)(sc->sc_regs + PX_REG_DISPKLUDGE);
+ volatile u_int32_t *dac = (u_int32_t *)(sc->sc_regs + PX_REG_BT463_RED);
- if (on)
- *dispkludge = DISPKLUDGE_DEFAULT & ~DISPKLUDGE_BLANK;
- else
- *dispkludge = DISPKLUDGE_DEFAULT | DISPKLUDGE_BLANK;
+ tvtwo_ramdac_wraddr(sc, index);
+ dac[3] = r;
+ dac[3] = g;
+ dac[3] = b;
}