summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorjmcneill <jmcneill@NetBSD.org>2006-08-13 14:16:44 +0000
committerjmcneill <jmcneill@NetBSD.org>2006-08-13 14:16:44 +0000
commitef21ee74e6088ed42c819bb5bdcf5290c262c3d8 (patch)
treeddbe2cc9c45b368ddadee9b78373cd93fe76f131 /sys/dev
parentd2cb59a6d27be03f8501c558aa82a8a25620a71e (diff)
Add accelerated putchar and cursor ops. Also fix a bug in copyrows that
caused scrolling down to always fail.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/unichromefb.c156
1 files changed, 136 insertions, 20 deletions
diff --git a/sys/dev/pci/unichromefb.c b/sys/dev/pci/unichromefb.c
index 043cf47165e..c548f471f48 100644
--- a/sys/dev/pci/unichromefb.c
+++ b/sys/dev/pci/unichromefb.c
@@ -1,4 +1,4 @@
-/* $NetBSD: unichromefb.c,v 1.2 2006/08/13 03:37:02 jmcneill Exp $ */
+/* $NetBSD: unichromefb.c,v 1.3 2006/08/13 14:16:44 jmcneill Exp $ */
/*-
* Copyright (c) 2006 Jared D. McNeill <jmcneill@invisible.ca>
@@ -57,7 +57,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: unichromefb.c,v 1.2 2006/08/13 03:37:02 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: unichromefb.c,v 1.3 2006/08/13 14:16:44 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -171,17 +171,24 @@ static void uni_set_accel_depth(struct unichromefb_softc *);
static void uni_wait_idle(struct unichromefb_softc *);
static void uni_fillrect(struct unichromefb_softc *,
int, int, int, int, int);
-static void uni_bitblit(struct unichromefb_softc *, int, int, int, int, int, int);
+static void uni_rectinvert(struct unichromefb_softc *,
+ int, int, int, int);
+static void uni_bitblit(struct unichromefb_softc *, int, int, int, int,
+ int, int);
+static void uni_setup_mono(struct unichromefb_softc *, int, int, int,
+ int, uint32_t, uint32_t);
+#if notyet
+static void uni_cursor_show(struct unichromefb_softc *);
+static void uni_cursor_hide(struct unichromefb_softc *);
+#endif
/* rasops glue */
static void uni_copycols(void *, int, int, int, int);
static void uni_copyrows(void *, int, int, int);
static void uni_erasecols(void *, int, int, int, long);
static void uni_eraserows(void *, int, int, long);
-#if notyet
static void uni_cursor(void *, int, int, int);
static void uni_putchar(void *, int, int, u_int, long);
-#endif
struct wsdisplay_accessops unichromefb_accessops = {
unichromefb_ioctl,
@@ -433,10 +440,8 @@ unichromefb_init_screen(void *c, struct vcons_screen *scr, int existing,
ri->ri_ops.copycols = uni_copycols;
ri->ri_ops.eraserows = uni_eraserows;
ri->ri_ops.erasecols = uni_erasecols;
-#if notyet
ri->ri_ops.cursor = uni_cursor;
ri->ri_ops.putchar = uni_putchar;
-#endif
}
return;
@@ -1168,6 +1173,8 @@ uni_fillrect(struct unichromefb_softc *sc, int x, int y, int width,
int height, int colour)
{
+ uni_wait_idle(sc);
+
MMIO_OUT32(VIA_REG_SRCPOS, 0);
MMIO_OUT32(VIA_REG_SRCBASE, 0);
MMIO_OUT32(VIA_REG_DSTBASE, 0);
@@ -1180,9 +1187,27 @@ uni_fillrect(struct unichromefb_softc *sc, int x, int y, int width,
MMIO_OUT32(VIA_REG_FGCOLOR, colour);
MMIO_OUT32(VIA_REG_GECMD, (0x01 | 0x2000 | 0xf0 << 24));
- /* XXX */
+ return;
+}
+
+static void
+uni_rectinvert(struct unichromefb_softc *sc, int x, int y, int width,
+ int height)
+{
+
uni_wait_idle(sc);
+ MMIO_OUT32(VIA_REG_SRCPOS, 0);
+ MMIO_OUT32(VIA_REG_SRCBASE, 0);
+ MMIO_OUT32(VIA_REG_DSTBASE, 0);
+ MMIO_OUT32(VIA_REG_PITCH, VIA_PITCH_ENABLE |
+ (((sc->sc_width * sc->sc_depth >> 3) >> 3) |
+ (((sc->sc_width * sc->sc_depth >> 3) >> 3) << 16)));
+ MMIO_OUT32(VIA_REG_DSTPOS, ((y << 16) | x));
+ MMIO_OUT32(VIA_REG_DIMENSION,
+ (((height - 1) << 16) | (width - 1)));
+ MMIO_OUT32(VIA_REG_GECMD, (0x01 | 0x2000 | 0x55 << 24));
+
return;
}
@@ -1196,15 +1221,17 @@ uni_bitblit(struct unichromefb_softc *sc, int xs, int ys, int xd, int yd, int wi
if (ys < yd) {
yd += height - 1;
ys += height - 1;
- dir |= 0x8000;
+ dir |= 0x4000;
}
if (xs < xd) {
xd += width - 1;
xs += width - 1;
- dir |= 0x4000;
+ dir |= 0x8000;
}
+ uni_wait_idle(sc);
+
MMIO_OUT32(VIA_REG_SRCBASE, 0);
MMIO_OUT32(VIA_REG_DSTBASE, 0);
MMIO_OUT32(VIA_REG_PITCH, VIA_PITCH_ENABLE |
@@ -1215,11 +1242,56 @@ uni_bitblit(struct unichromefb_softc *sc, int xs, int ys, int xd, int yd, int wi
MMIO_OUT32(VIA_REG_DIMENSION, ((height - 1) << 16) | (width - 1));
MMIO_OUT32(VIA_REG_GECMD, (0x01 | dir | (0xcc << 24)));
- /* XXX */
+ return;
+}
+
+static void
+uni_setup_mono(struct unichromefb_softc *sc, int xd, int yd, int width, int height,
+ uint32_t fg, uint32_t bg)
+{
+
uni_wait_idle(sc);
+ MMIO_OUT32(VIA_REG_SRCBASE, 0);
+ MMIO_OUT32(VIA_REG_DSTBASE, 0);
+ MMIO_OUT32(VIA_REG_PITCH, VIA_PITCH_ENABLE |
+ (((sc->sc_width * sc->sc_depth >> 3) >> 3) |
+ (((sc->sc_width * sc->sc_depth >> 3) >> 3) << 16)));
+ MMIO_OUT32(VIA_REG_SRCPOS, 0);
+ MMIO_OUT32(VIA_REG_DSTPOS, (yd << 16) | xd);
+ MMIO_OUT32(VIA_REG_DIMENSION, ((height - 1) << 16) | (width - 1));
+ MMIO_OUT32(VIA_REG_FGCOLOR, fg);
+ MMIO_OUT32(VIA_REG_BGCOLOR, bg);
+ MMIO_OUT32(VIA_REG_GECMD, 0xcc020142);
+
+ return;
+}
+
+#if notyet
+static void
+uni_cursor_show(struct unichromefb_softc *sc)
+{
+ uint32_t val;
+
+ val = MMIO_IN32(VIA_REG_CURSOR_MODE);
+ val |= 1;
+ MMIO_OUT32(VIA_REG_CURSOR_MODE, val);
+
+ return;
+}
+
+static void
+uni_cursor_hide(struct unichromefb_softc *sc)
+{
+ uint32_t val;
+
+ val = MMIO_IN32(VIA_REG_CURSOR_MODE);
+ val &= 0xfffffffe;
+ MMIO_OUT32(VIA_REG_CURSOR_MODE, val);
+
return;
}
+#endif
/*
* rasops glue
@@ -1327,13 +1399,13 @@ uni_eraserows(void *opaque, int row, int nrows, long fillattr)
return;
}
-#if notyet
static void
uni_cursor(void *opaque, int on, int row, int col)
{
struct rasops_info *ri;
struct vcons_screen *scr;
struct unichromefb_softc *sc;
+ int x, y, wi, he;
ri = (struct rasops_info *)opaque;
scr = (struct vcons_screen *)ri->ri_hw;
@@ -1341,14 +1413,35 @@ uni_cursor(void *opaque, int on, int row, int col)
uni_wait_idle(sc);
- if (sc->sc_cursor)
- sc->sc_cursor(opaque, on, row, col);
+ wi = ri->ri_font->fontwidth;
+ he = ri->ri_font->fontheight;
+
+ if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) {
+ x = ri->ri_ccol * wi + ri->ri_xorigin;
+ y = ri->ri_crow * he + ri->ri_yorigin;
+ if (ri->ri_flg & RI_CURSOR) {
+ uni_rectinvert(sc, x, y, wi, he);
+ ri->ri_flg &= ~RI_CURSOR;
+ }
+ ri->ri_crow = row;
+ ri->ri_ccol = col;
+ if (on) {
+ x = ri->ri_ccol * wi + ri->ri_xorigin;
+ y = ri->ri_crow * he + ri->ri_yorigin;
+ uni_rectinvert(sc, x, y, wi, he);
+ ri->ri_flg |= RI_CURSOR;
+ }
+ } else {
+ ri->ri_flg &= ~RI_CURSOR;
+ ri->ri_crow = row;
+ ri->ri_ccol = col;
+ }
return;
}
static void
-uni_putchar(void *opaque, int row, int col, u_int c, long fillattr)
+uni_putchar(void *opaque, int row, int col, u_int c, long attr)
{
struct rasops_info *ri;
struct vcons_screen *scr;
@@ -1358,14 +1451,37 @@ uni_putchar(void *opaque, int row, int col, u_int c, long fillattr)
scr = (struct vcons_screen *)ri->ri_hw;
sc = (struct unichromefb_softc *)scr->scr_cookie;
- uni_wait_idle(sc);
-
- if (sc->sc_putchar)
- sc->sc_putchar(opaque, row, col, c, fillattr);
+ if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) {
+ uint32_t *data;
+ int fg, bg, ul, uc, i;
+ int x, y, wi, he;
+
+ wi = ri->ri_font->fontwidth;
+ he = ri->ri_font->fontheight;
+
+ if (!CHAR_IN_FONT(c, ri->ri_font))
+ return;
+
+ rasops_unpack_attr(attr, &fg, &bg, &ul);
+ x = ri->ri_xorigin + col * wi;
+ y = ri->ri_yorigin + row * he;
+ if (c == 0x20)
+ uni_fillrect(sc, x, y, wi, he, ri->ri_devcmap[bg]);
+ else {
+ uc = c - ri->ri_font->firstchar;
+ data = (uint32_t *)((uint8_t *)ri->ri_font->data +
+ uc * ri->ri_fontscale);
+ uni_setup_mono(sc, x, y, wi, he,
+ ri->ri_devcmap[fg], ri->ri_devcmap[bg]);
+ for (i = 0; i < (wi * he) / 4; i++) {
+ MMIO_OUT32(VIA_MMIO_BLTBASE, *data);
+ data++;
+ }
+ }
+ }
return;
}
-#endif
/* XXX TODO */
int