summaryrefslogtreecommitdiff
path: root/sys/dev/sbus
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2002-01-04 19:39:07 +0000
committerJason Wright <jason@cvs.openbsd.org>2002-01-04 19:39:07 +0000
commit78d368fb2f7077a133807e48e408391e5b74f5c2 (patch)
treee2351ce4512ec3010207e1963a54afa6108fe49b /sys/dev/sbus
parent14b2d2ff826507e45143f4d319acb80e09d5f4da (diff)
Add handling for cmap get/put (mostly from sparc)
Diffstat (limited to 'sys/dev/sbus')
-rw-r--r--sys/dev/sbus/cgsix.c158
1 files changed, 151 insertions, 7 deletions
diff --git a/sys/dev/sbus/cgsix.c b/sys/dev/sbus/cgsix.c
index 6153a596e6a..cb7e5eb9039 100644
--- a/sys/dev/sbus/cgsix.c
+++ b/sys/dev/sbus/cgsix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cgsix.c,v 1.3 2002/01/04 01:13:29 jason Exp $ */
+/* $OpenBSD: cgsix.c,v 1.4 2002/01/04 19:39:06 jason Exp $ */
/*
* Copyright (c) 2001 Jason L. Wright (jason@thought.net)
@@ -50,6 +50,31 @@
#include <dev/wscons/wscons_raster.h>
#include <dev/rcons/raster.h>
+union bt_cmap {
+ u_int8_t cm_map[256][3]; /* 256 r/b/g entries */
+ u_int32_t cm_chip[256 * 3 / 4]; /* the way the chip is loaded */
+};
+
+#define BT_ADDR 0x00 /* map address register */
+#define BT_CMAP 0x04 /* colormap data register */
+#define BT_CTRL 0x08 /* control register */
+#define BT_OMAP 0x0c /* overlay (cursor) map register */
+
+#define BT_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bustag, (sc)->sc_bt_regs, (reg), (val))
+#define BT_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bustag, (sc)->sc_bt_regs, (reg))
+
+#define BT_INIT(sc) do { \
+ BT_WRITE((sc), BT_ADDR, 0x06); /* command reg */ \
+ BT_WRITE((sc), BT_CTRL, 0x73); /* overlay plane */ \
+ BT_WRITE((sc), BT_ADDR, 0x04); /* read mask */ \
+ BT_WRITE((sc), BT_CTRL, 0xff); /* color planes */ \
+} while (0)
+
+#define BT_D4M3(x) ((((x) >> 2) << 1) + ((x) >> 2)) /* (x / 4) * 3 */
+#define BT_D4M4(x) ((x) & ~3) /* (x / 4) * 4 */
+
#define CGSIX_ROM_OFFSET 0x000000
#define CGSIX_BT_OFFSET 0x200000
#define CGSIX_BT_SIZE (sizeof(u_int32_t) * 4)
@@ -78,6 +103,7 @@ struct cgsix_softc {
int sc_width, sc_height, sc_depth, sc_linebytes;
struct rcons sc_rcons;
struct raster sc_raster;
+ union bt_cmap sc_cmap;
};
#define CG6_USER_FBC 0x70000000
@@ -131,6 +157,11 @@ int cgsix_show_screen __P((void *, void *, int,
void (*cb) __P((void *, int, int)), void *));
paddr_t cgsix_mmap __P((void *, off_t, int));
int cgsix_is_console __P((int));
+int cg6_bt_getcmap __P((union bt_cmap *, struct wsdisplay_cmap *));
+int cg6_bt_putcmap __P((union bt_cmap *, struct wsdisplay_cmap *));
+void cgsix_loadcmap __P((struct cgsix_softc *, u_int, u_int));
+void cgsix_setcolor __P((struct cgsix_softc *, u_int,
+ u_int8_t, u_int8_t, u_int8_t));
static int a2int __P((char *, int));
@@ -173,7 +204,7 @@ cgsixattach(parent, self, aux)
struct cgsix_softc *sc = (struct cgsix_softc *)self;
struct sbus_attach_args *sa = aux;
struct wsemuldisplaydev_attach_args waa;
- int console;
+ int console, i;
long defattr;
sc->sc_bustag = sa->sa_bustag;
@@ -218,6 +249,13 @@ cgsixattach(parent, self, aux)
console = cgsix_is_console(sa->sa_node);
+ BT_WRITE(sc, BT_ADDR, 0);
+ for (i = 0; i < 256; i++) {
+ sc->sc_cmap.cm_map[i][0] = BT_READ(sc, BT_CMAP) >> 24;
+ sc->sc_cmap.cm_map[i][1] = BT_READ(sc, BT_CMAP) >> 24;
+ sc->sc_cmap.cm_map[i][2] = BT_READ(sc, BT_CMAP) >> 24;
+ }
+
sc->sc_depth = getpropint(sa->sa_node, "depth", -1);
if (sc->sc_depth == -1)
sc->sc_depth = 8;
@@ -265,9 +303,20 @@ cgsixattach(parent, self, aux)
printf("\n");
- if (console)
+ if (console) {
+ cgsix_setcolor(sc, WSCOL_BLACK, 0, 0, 0);
+ cgsix_setcolor(sc, 255, 255, 255, 255);
+ cgsix_setcolor(sc, WSCOL_RED, 255, 0, 0);
+ cgsix_setcolor(sc, WSCOL_GREEN, 0, 255, 0);
+ cgsix_setcolor(sc, WSCOL_BROWN, 154, 85, 46);
+ cgsix_setcolor(sc, WSCOL_BLUE, 0, 0, 255);
+ cgsix_setcolor(sc, WSCOL_MAGENTA, 255, 255, 0);
+ cgsix_setcolor(sc, WSCOL_CYAN, 0, 255, 255);
+ cgsix_setcolor(sc, WSCOL_WHITE, 255, 255, 255);
+
wsdisplay_cnattach(&cgsix_stdscreen, &sc->sc_rcons,
*sc->sc_rcons.rc_ccolp, *sc->sc_rcons.rc_crowp, defattr);
+ }
waa.console = console;
waa.scrdata = &cgsix_screenlist;
@@ -296,7 +345,9 @@ cgsix_ioctl(v, cmd, data, flags, p)
struct proc *p;
{
struct cgsix_softc *sc = v;
+ struct wsdisplay_cmap *cm;
struct wsdisplay_fbinfo *wdf;
+ int error;
switch (cmd) {
case WSDISPLAYIO_GTYPE:
@@ -313,12 +364,20 @@ cgsix_ioctl(v, cmd, data, flags, p)
*(u_int *)data = sc->sc_linebytes;
break;
-#if 0
case WSDISPLAYIO_GETCMAP:
- return vgafb_getcmap(vc, (struct wsdisplay_cmap *)data);
+ cm = (struct wsdisplay_cmap *)data;
+ error = cg6_bt_getcmap(&sc->sc_cmap, cm);
+ if (error)
+ return (error);
+ break;
+
case WSDISPLAYIO_PUTCMAP:
- return vgafb_putcmap(vc, (struct wsdisplay_cmap *)data);
-#endif
+ cm = (struct wsdisplay_cmap *)data;
+ error = cg6_bt_putcmap(&sc->sc_cmap, cm);
+ if (error)
+ return (error);
+ cgsix_loadcmap(sc, cm->index, cm->count);
+ break;
case WSDISPLAYIO_SVIDEO:
case WSDISPLAYIO_GVIDEO:
@@ -448,3 +507,88 @@ cgsix_is_console(node)
return (fbnode == node);
}
+
+int
+cg6_bt_getcmap(bcm, rcm)
+ union bt_cmap *bcm;
+ struct wsdisplay_cmap *rcm;
+{
+ u_int index = rcm->index, count = rcm->count, i;
+ int error;
+
+ if (index >= 256 || index + count > 256)
+ return (EINVAL);
+ for (i = 0; i < count; i++) {
+ if ((error = copyout(&bcm->cm_map[index + i][0],
+ &rcm->red[i], 1)) != 0)
+ return (error);
+ if ((error = copyout(&bcm->cm_map[index + i][1],
+ &rcm->green[i], 1)) != 0)
+ return (error);
+ if ((error = copyout(&bcm->cm_map[index + i][2],
+ &rcm->blue[i], 1)) != 0)
+ return (error);
+ }
+ return (0);
+}
+
+int
+cg6_bt_putcmap(bcm, rcm)
+ union bt_cmap *bcm;
+ struct wsdisplay_cmap *rcm;
+{
+ u_int index = rcm->index, count = rcm->count, i;
+ int error;
+
+ if (index >= 256 || rcm->count > 256 ||
+ (rcm->index + rcm->count) > 256)
+ return (EINVAL);
+ for (i = 0; i < count; i++) {
+ if ((error = copyin(&rcm->red[i],
+ &bcm->cm_map[index + i][0], 1)) != 0)
+ return (error);
+ if ((error = copyin(&rcm->green[i],
+ &bcm->cm_map[index + i][1], 1)) != 0)
+ return (error);
+ if ((error = copyin(&rcm->blue[i],
+ &bcm->cm_map[index + i][2], 1)) != 0)
+ return (error);
+ }
+ return (0);
+}
+
+void
+cgsix_loadcmap(sc, start, ncolors)
+ struct cgsix_softc *sc;
+ u_int start, ncolors;
+{
+ u_int cstart;
+ u_int32_t v;
+ int count;
+
+ cstart = BT_D4M3(start);
+ count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
+ BT_WRITE(sc, BT_ADDR, BT_D4M4(start) << 24);
+ while (--count >= 0) {
+ v = sc->sc_cmap.cm_chip[cstart];
+ BT_WRITE(sc, BT_CMAP, v << 0);
+ BT_WRITE(sc, BT_CMAP, v << 8);
+ BT_WRITE(sc, BT_CMAP, v << 16);
+ BT_WRITE(sc, BT_CMAP, v << 24);
+ cstart++;
+ }
+}
+
+void
+cgsix_setcolor(sc, index, r, g, b)
+ struct cgsix_softc *sc;
+ u_int index;
+ u_int8_t r, g, b;
+{
+ union bt_cmap *bcm = &sc->sc_cmap;
+
+ bcm->cm_map[index][0] = r;
+ bcm->cm_map[index][1] = g;
+ bcm->cm_map[index][2] = b;
+ cgsix_loadcmap(sc, index, 1);
+}