Module Name: src
Committed By: macallan
Date: Wed Feb 28 10:25:36 UTC 2024
Modified Files:
src/sys/arch/hppa/dev: gftfb.c
Log Message:
add hardware cursor support, mostly for X
To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/hppa/dev/gftfb.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/hppa/dev/gftfb.c
diff -u src/sys/arch/hppa/dev/gftfb.c:1.6 src/sys/arch/hppa/dev/gftfb.c:1.7
--- src/sys/arch/hppa/dev/gftfb.c:1.6 Wed Feb 21 13:24:40 2024
+++ src/sys/arch/hppa/dev/gftfb.c Wed Feb 28 10:25:36 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: gftfb.c,v 1.6 2024/02/21 13:24:40 macallan Exp $ */
+/* $NetBSD: gftfb.c,v 1.7 2024/02/28 10:25:36 macallan Exp $ */
/* $OpenBSD: sti_pci.c,v 1.7 2009/02/06 22:51:04 miod Exp $ */
@@ -29,6 +29,7 @@
#include <sys/systm.h>
#include <sys/kmem.h>
#include <sys/device.h>
+#include <sys/mutex.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -82,10 +83,15 @@ struct gftfb_softc {
u_char sc_cmap_red[256];
u_char sc_cmap_green[256];
u_char sc_cmap_blue[256];
+ kmutex_t sc_hwlock;
uint32_t sc_hwmode;
#define HW_FB 0
#define HW_FILL 1
#define HW_BLIT 2
+ /* cursor stuff */
+ int sc_cursor_x, sc_cursor_y;
+ int sc_hot_x, sc_hot_y, sc_enabled;
+ uint32_t sc_pos;
glyphcache sc_gc;
};
@@ -139,6 +145,9 @@ static void gftfb_erasecols(void *, int,
static void gftfb_copyrows(void *, int, int, int);
static void gftfb_eraserows(void *, int, int, long);
+static void gftfb_move_cursor(struct gftfb_softc *, int, int);
+static int gftfb_do_cursor(struct gftfb_softc *, struct wsdisplay_cursor *);
+
struct wsdisplay_accessops gftfb_accessops = {
gftfb_ioctl,
gftfb_mmap,
@@ -175,6 +184,8 @@ struct wsdisplay_accessops gftfb_accesso
#define MaskDynamic 1 /* Mask register reloaded by direct access */
#define MaskOtc 0 /* Mask contains Object Count valid bits */
+static inline void gftfb_wait_fifo(struct gftfb_softc *, uint32_t);
+
int
gftfb_match(device_t parent, cfdata_t cf, void *aux)
{
@@ -209,6 +220,9 @@ gftfb_attach(device_t parent, device_t s
sc->sc_base.sc_enable_rom = gftfb_enable_rom;
sc->sc_base.sc_disable_rom = gftfb_disable_rom;
+ /* we can *not* be interrupted when doing colour map accesses */
+ mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH);
+
aprint_normal("\n");
if (gftfb_check_rom(sc, paa) != 0)
@@ -663,8 +677,12 @@ gftfb_setup(struct gftfb_softc *sc)
struct sti_rom *rom = sc->sc_base.sc_rom;
bus_space_tag_t memt = rom->memt;
bus_space_handle_t memh = rom->regh[2];
+ int i;
sc->sc_hwmode = HW_FB;
+ sc->sc_hot_x = 0;
+ sc->sc_hot_y = 0;
+ sc->sc_enabled = 0;
/* set Bt458 read mask register to all planes */
gftfb_wait(sc);
@@ -702,6 +720,50 @@ gftfb_setup(struct gftfb_softc *sc)
bus_space_read_stream_4(memt, memh, NGLE_REG_21) | 0x0a000000);
bus_space_write_stream_4(memt, memh, NGLE_REG_27,
bus_space_read_stream_4(memt, memh, NGLE_REG_27) | 0x00800000);
+
+ /* initialize cursor sprite */
+ gftfb_wait(sc);
+
+ /* cursor mask */
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x300);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x28A07000);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+ for (i = 0; i < 64; i++) {
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0xffffffff);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_5, 0xffffffff);
+ }
+
+ /* cursor image */
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x300);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x28A06000);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+ for (i = 0; i < 64; i++) {
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0xff00ff00);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_5, 0xff00ff00);
+ }
+
+ /* colour map */
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xBBE0F000);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0x000000ff); /* BG */
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0x00ff0000); /* FG */
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_26, 0x80008004);
+ gftfb_setup_fb(sc);
+
+ gftfb_move_cursor(sc, 100, 100);
+
}
static int
@@ -773,7 +835,41 @@ gftfb_ioctl(void *v, void *vs, u_long cm
return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
}
+
+ case WSDISPLAYIO_GCURPOS:
+ {
+ struct wsdisplay_curpos *cp = (void *)data;
+
+ cp->x = sc->sc_cursor_x;
+ cp->y = sc->sc_cursor_y;
+ }
+ return 0;
+
+ case WSDISPLAYIO_SCURPOS:
+ {
+ struct wsdisplay_curpos *cp = (void *)data;
+
+ gftfb_move_cursor(sc, cp->x, cp->y);
+ }
+ return 0;
+
+ case WSDISPLAYIO_GCURMAX:
+ {
+ struct wsdisplay_curpos *cp = (void *)data;
+
+ cp->x = 64;
+ cp->y = 64;
+ }
+ return 0;
+
+ case WSDISPLAYIO_SCURSOR:
+ {
+ struct wsdisplay_cursor *cursor = (void *)data;
+
+ return gftfb_do_cursor(sc, cursor);
+ }
}
+
return EPASSTHROUGH;
}
@@ -909,6 +1005,7 @@ gftfb_putpalreg(struct gftfb_softc *sc,
bus_space_tag_t memt = rom->memt;
bus_space_handle_t memh = rom->regh[2];
+ mutex_enter(&sc->sc_hwlock);
gftfb_wait(sc);
bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
@@ -923,6 +1020,7 @@ gftfb_putpalreg(struct gftfb_softc *sc,
bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400);
bus_space_write_stream_4(memt, memh, NGLE_REG_26, 0x80000100);
gftfb_setup_fb(sc);
+ mutex_exit(&sc->sc_hwlock);
return 0;
}
@@ -1187,3 +1285,182 @@ gftfb_eraserows(void *cookie, int row, i
ri->ri_flg &= ~RI_CURSOR;
}
}
+
+/*
+ * cursor sprite handling
+ * like most hw info, xf86 3.3 -> nglehdw.h was used as documentation
+ * problem is, the PCI EG doesn't quite behave like an S9000_ID_ARTIST
+ * the cursor position register bahaves like the one on HCRX while using
+ * the same address as Artist, incuding the enable bit and weird handling
+ * of negative coordinates. The rest of it, colour map, sprite image etc.,
+ * behave like Artist.
+ */
+
+static void
+gftfb_move_cursor(struct gftfb_softc *sc, int x, int y)
+{
+ struct sti_rom *rom = sc->sc_base.sc_rom;
+ bus_space_tag_t memt = rom->memt;
+ bus_space_handle_t memh = rom->regh[2];
+ uint32_t pos;
+
+ sc->sc_cursor_x = x;
+ x -= sc->sc_hot_x;
+ sc->sc_cursor_y = y;
+ y -= sc->sc_hot_y;
+
+ if (x < 0) x = 0x1000 - x;
+ if (y < 0) y = 0x1000 - y;
+ pos = (x << 16) | y;
+ if (sc->sc_enabled) pos |= 0x80000000;
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_17, pos);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_18, 0x80);
+}
+
+static int
+gftfb_do_cursor(struct gftfb_softc *sc, struct wsdisplay_cursor *cur)
+{
+ struct sti_rom *rom = sc->sc_base.sc_rom;
+ bus_space_tag_t memt = rom->memt;
+ bus_space_handle_t memh = rom->regh[2];
+
+ if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
+
+ sc->sc_enabled = cur->enable;
+ cur->which |= WSDISPLAY_CURSOR_DOPOS;
+ }
+ if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
+
+ sc->sc_hot_x = cur->hot.x;
+ sc->sc_hot_y = cur->hot.y;
+ cur->which |= WSDISPLAY_CURSOR_DOPOS;
+ }
+ if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
+
+ gftfb_move_cursor(sc, cur->pos.x, cur->pos.y);
+ }
+ if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
+ uint32_t rgb;
+ uint8_t r[2], g[2], b[2];
+
+ copyin(cur->cmap.blue, b, 2);
+ copyin(cur->cmap.green, g, 2);
+ copyin(cur->cmap.red, r, 2);
+ mutex_enter(&sc->sc_hwlock);
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xBBE0F000);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0);
+ rgb = (r[0] << 16) | (g[0] << 8) | b[0];
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, rgb); /* BG */
+ rgb = (r[1] << 16) | (g[1] << 8) | b[1];
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, rgb); /* FG */
+ bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_26, 0x80008004);
+ gftfb_setup_fb(sc);
+ mutex_exit(&sc->sc_hwlock);
+
+ }
+ if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
+ uint32_t buffer[128], latch, tmp;
+ int i;
+
+ copyin(cur->mask, buffer, 512);
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x300);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x28A07000);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+ for (i = 0; i < 128; i += 2) {
+ latch = 0;
+ tmp = buffer[i] & 0x80808080;
+ latch |= tmp >> 7;
+ tmp = buffer[i] & 0x40404040;
+ latch |= tmp >> 5;
+ tmp = buffer[i] & 0x20202020;
+ latch |= tmp >> 3;
+ tmp = buffer[i] & 0x10101010;
+ latch |= tmp >> 1;
+ tmp = buffer[i] & 0x08080808;
+ latch |= tmp << 1;
+ tmp = buffer[i] & 0x04040404;
+ latch |= tmp << 3;
+ tmp = buffer[i] & 0x02020202;
+ latch |= tmp << 5;
+ tmp = buffer[i] & 0x01010101;
+ latch |= tmp << 7;
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, latch);
+ latch = 0;
+ tmp = buffer[i + 1] & 0x80808080;
+ latch |= tmp >> 7;
+ tmp = buffer[i + 1] & 0x40404040;
+ latch |= tmp >> 5;
+ tmp = buffer[i + 1] & 0x20202020;
+ latch |= tmp >> 3;
+ tmp = buffer[i + 1] & 0x10101010;
+ latch |= tmp >> 1;
+ tmp = buffer[i + 1] & 0x08080808;
+ latch |= tmp << 1;
+ tmp = buffer[i + 1] & 0x04040404;
+ latch |= tmp << 3;
+ tmp = buffer[i + 1] & 0x02020202;
+ latch |= tmp << 5;
+ tmp = buffer[i + 1] & 0x01010101;
+ latch |= tmp << 7;
+ bus_space_write_stream_4(memt, memh, NGLE_REG_5, latch);
+ }
+
+ copyin(cur->image, buffer, 512);
+ gftfb_wait(sc);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x300);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x28A06000);
+ bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+ for (i = 0; i < 128; i += 2) {
+ latch = 0;
+ tmp = buffer[i] & 0x80808080;
+ latch |= tmp >> 7;
+ tmp = buffer[i] & 0x40404040;
+ latch |= tmp >> 5;
+ tmp = buffer[i] & 0x20202020;
+ latch |= tmp >> 3;
+ tmp = buffer[i] & 0x10101010;
+ latch |= tmp >> 1;
+ tmp = buffer[i] & 0x08080808;
+ latch |= tmp << 1;
+ tmp = buffer[i] & 0x04040404;
+ latch |= tmp << 3;
+ tmp = buffer[i] & 0x02020202;
+ latch |= tmp << 5;
+ tmp = buffer[i] & 0x01010101;
+ latch |= tmp << 7;
+ bus_space_write_stream_4(memt, memh, NGLE_REG_4, latch);
+ latch = 0;
+ tmp = buffer[i + 1] & 0x80808080;
+ latch |= tmp >> 7;
+ tmp = buffer[i + 1] & 0x40404040;
+ latch |= tmp >> 5;
+ tmp = buffer[i + 1] & 0x20202020;
+ latch |= tmp >> 3;
+ tmp = buffer[i + 1] & 0x10101010;
+ latch |= tmp >> 1;
+ tmp = buffer[i + 1] & 0x08080808;
+ latch |= tmp << 1;
+ tmp = buffer[i + 1] & 0x04040404;
+ latch |= tmp << 3;
+ tmp = buffer[i + 1] & 0x02020202;
+ latch |= tmp << 5;
+ tmp = buffer[i + 1] & 0x01010101;
+ latch |= tmp << 7;
+ bus_space_write_stream_4(memt, memh, NGLE_REG_5, latch);
+ }
+ gftfb_setup_fb(sc);
+ }
+
+ return 0;
+}