Module Name:    src
Committed By:   macallan
Date:           Wed Sep 28 02:36:37 UTC 2011

Modified Files:
        src/sys/dev/pci/voyager: voyagerfb.c

Log Message:
support a hardware cursor - now X with wsfb on gdium is a little less annoying


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/pci/voyager/voyagerfb.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/dev/pci/voyager/voyagerfb.c
diff -u src/sys/dev/pci/voyager/voyagerfb.c:1.5 src/sys/dev/pci/voyager/voyagerfb.c:1.6
--- src/sys/dev/pci/voyager/voyagerfb.c:1.5	Thu Sep 22 06:16:13 2011
+++ src/sys/dev/pci/voyager/voyagerfb.c	Wed Sep 28 02:36:37 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: voyagerfb.c,v 1.5 2011/09/22 06:16:13 macallan Exp $	*/
+/*	$NetBSD: voyagerfb.c,v 1.6 2011/09/28 02:36:37 macallan Exp $	*/
 
 /*
  * Copyright (c) 2009 Michael Lorenz
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: voyagerfb.c,v 1.5 2011/09/22 06:16:13 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: voyagerfb.c,v 1.6 2011/09/28 02:36:37 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -59,6 +59,12 @@ __KERNEL_RCSID(0, "$NetBSD: voyagerfb.c,
 #include <dev/i2c/i2cvar.h>
 #include <dev/pci/voyagervar.h>
 
+#ifdef VOYAGERFB_DEBUG
+#define DPRINTF aprint_error
+#else
+#define DPRINTF while (0) printf
+#endif
+
 /* there are probably gdium-specific */
 #define GPIO_BACKLIGHT	0x20000000
 
@@ -86,6 +92,16 @@ struct voyagerfb_softc {
 	int sc_mode;
 	int sc_bl_on, sc_bl_level;
 	void *sc_gpio_cookie;
+
+	/* cursor stuff */
+	int sc_cur_x;
+	int sc_cur_y;
+	int sc_hot_x;
+	int sc_hot_y;
+	uint32_t sc_cursor_addr;
+	uint32_t *sc_cursor;
+ 
+	/* colour map */
 	u_char sc_cmap_red[256];
 	u_char sc_cmap_green[256];
 	u_char sc_cmap_blue[256];
@@ -127,6 +143,10 @@ static void	voyagerfb_erasecols(void *, 
 static void	voyagerfb_copyrows(void *, int, int, int);
 static void	voyagerfb_eraserows(void *, int, int, long);
 
+static int	voyagerfb_set_curpos(struct voyagerfb_softc *, int, int);
+static int	voyagerfb_gcursor(struct voyagerfb_softc *, struct wsdisplay_cursor *);
+static int	voyagerfb_scursor(struct voyagerfb_softc *, struct wsdisplay_cursor *);
+
 struct wsdisplay_accessops voyagerfb_accessops = {
 	voyagerfb_ioctl,
 	voyagerfb_mmap,
@@ -410,6 +430,51 @@ voyagerfb_ioctl(void *v, void *vs, u_lon
 			return 0;
 		}
 		return EPASSTHROUGH;
+
+	case WSDISPLAYIO_GCURPOS:
+		{
+			struct wsdisplay_curpos *pos;
+
+			pos = (struct wsdisplay_curpos *)data;
+			pos->x = sc->sc_cur_x;
+			pos->y = sc->sc_cur_y;
+		}
+		return 0;
+
+	case WSDISPLAYIO_SCURPOS:
+		{
+			struct wsdisplay_curpos *pos;
+
+			pos = (struct wsdisplay_curpos *)data;
+			voyagerfb_set_curpos(sc, pos->x, pos->y);
+		}
+		return 0;
+
+	case WSDISPLAYIO_GCURMAX:
+		{
+			struct wsdisplay_curpos *pos;
+
+			pos = (struct wsdisplay_curpos *)data;
+			pos->x = 64;
+			pos->y = 64;
+		}
+		return 0;
+
+	case WSDISPLAYIO_GCURSOR:
+		{
+			struct wsdisplay_cursor *cu;
+
+			cu = (struct wsdisplay_cursor *)data;
+			return voyagerfb_gcursor(sc, cu);
+		}
+
+	case WSDISPLAYIO_SCURSOR:
+		{
+			struct wsdisplay_cursor *cu;
+
+			cu = (struct wsdisplay_cursor *)data;
+			return voyagerfb_scursor(sc, cu);
+		}
 	}
 	return EPASSTHROUGH;
 }
@@ -612,6 +677,29 @@ voyagerfb_init(struct voyagerfb_softc *s
 			    SM502_STRETCH, SM502_STRETCH_32BIT);
 			break;
 	}
+	/* put the cursor at the end of video memory */
+	sc->sc_cursor_addr = 16 * 1024 * 1024 - 16 * 64;	/* XXX */
+	DPRINTF("%s: %08x\n", __func__, sc->sc_cursor_addr); 
+	sc->sc_cursor = (uint32_t *)((uint8_t *)bus_space_vaddr(sc->sc_memt, sc->sc_fbh)
+			 + sc->sc_cursor_addr);
+#ifdef VOYAGERFB_DEBUG
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PANEL_CRSR_XY, 0x00100010);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PANEL_CRSR_COL12, 0x0000ffff);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PANEL_CRSR_COL3, 0x0000f800);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PANEL_CRSR_ADDR,
+	    SM502_CRSR_ENABLE | sc->sc_cursor_addr);
+	sc->sc_cursor[0] = 0x00000000;
+	sc->sc_cursor[1] = 0x00000000;
+	sc->sc_cursor[2] = 0xffffffff;
+	sc->sc_cursor[3] = 0xffffffff;
+	sc->sc_cursor[4] = 0xaaaaaaaa;
+	sc->sc_cursor[5] = 0xaaaaaaaa;
+	sc->sc_cursor[6] = 0xffffffff;
+	sc->sc_cursor[7] = 0x00000000;
+#else
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PANEL_CRSR_ADDR,
+	    sc->sc_cursor_addr);
+#endif
 }
 
 static void
@@ -930,3 +1018,115 @@ voyagerfb_brightness_down(device_t dev)
 
 	voyagerfb_set_backlight(sc, sc->sc_bl_level - 8);
 }
+
+static int
+voyagerfb_set_curpos(struct voyagerfb_softc *sc, int x, int y)
+{
+	uint32_t val;
+	int xx, yy;
+
+	sc->sc_cur_x = x;
+	sc->sc_cur_y = y;
+
+	xx = x - sc->sc_hot_x;
+	yy = y - sc->sc_hot_y;
+	
+	if (xx < 0) xx = abs(xx) | 0x800;
+	if (yy < 0) yy = abs(yy) | 0x800;
+	
+	val = (xx & 0xffff) | (yy << 16);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PANEL_CRSR_XY, val);
+
+	return 0;
+}
+
+static int
+voyagerfb_gcursor(struct voyagerfb_softc *sc, struct wsdisplay_cursor *cur)
+{
+	/* do nothing for now */
+	return 0;
+}
+
+static int
+voyagerfb_scursor(struct voyagerfb_softc *sc, struct wsdisplay_cursor *cur)
+{
+	if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
+
+		bus_space_write_4(sc->sc_memt, sc->sc_regh,
+		    SM502_PANEL_CRSR_ADDR,
+		    sc->sc_cursor_addr | (cur->enable ? SM502_CRSR_ENABLE : 0));
+		DPRINTF("%s: %08x\n", __func__, sc->sc_cursor_addr);
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
+
+		sc->sc_hot_x = cur->hot.x;
+		sc->sc_hot_y = cur->hot.y;
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
+
+		voyagerfb_set_curpos(sc, cur->pos.x, cur->pos.y);
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
+		int i, idx;
+		uint32_t val;
+	
+		for (i = 0; i < cur->cmap.count; i++) {
+			val = ((cur->cmap.red[i] & 0xf8) << 8) |
+			      ((cur->cmap.green[i] & 0xfc) << 3) |
+			      ((cur->cmap.blue[i] & 0xf8) >> 3);
+			idx = i + cur->cmap.index;
+			bus_space_write_2(sc->sc_memt, sc->sc_regh,
+			    SM502_PANEL_CRSR_COL12 + (idx << 1),
+			    val);
+			/*
+			 * if userland doesn't try to set the 3rd colour we
+			 * assume it expects an X11-style 2 colour cursor
+			 * X should be our main user anyway
+			 */
+			if ((idx == 1) && 
+			   ((cur->cmap.count + cur->cmap.index) < 3)) {
+				bus_space_write_2(sc->sc_memt, sc->sc_regh,
+				    SM502_PANEL_CRSR_COL3,
+				    val);
+			}
+			DPRINTF("%s: %d %04x\n", __func__, i + cur->cmap.index, val);
+		}
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
+
+		int i, j, cnt = 0;
+		uint32_t latch = 0, omask;
+		uint8_t imask;
+		DPRINTF("%s: %d %d\n", __func__, cur->size.x, cur->size.y);
+		for (i = 0; i < 256; i++) {
+			omask = 0x00000001;
+			imask = 0x01;
+			cur->image[cnt] &= cur->mask[cnt];
+			for (j = 0; j < 8; j++) {
+				if (cur->mask[cnt] & imask)
+					latch |= omask;
+				omask <<= 1;
+				if (cur->image[cnt] & imask)
+					latch |= omask;
+				omask <<= 1;
+				imask <<= 1;
+			}
+			cnt++;
+			imask = 0x01;
+			cur->image[cnt] &= cur->mask[cnt];
+			for (j = 0; j < 8; j++) {
+				if (cur->mask[cnt] & imask)
+					latch |= omask;
+				omask <<= 1;
+				if (cur->image[cnt] & imask)
+					latch |= omask;
+				omask <<= 1;
+				imask <<= 1;
+			}
+			cnt++;
+			sc->sc_cursor[i] = latch;
+			latch = 0;
+		}				
+	}
+	return 0;
+}

Reply via email to