Module Name:    src
Committed By:   macallan
Date:           Tue Feb 12 21:17:38 UTC 2013

Modified Files:
        src/sys/arch/arm/omap: omapfb.c

Log Message:
support a hardware cursor


To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/arm/omap/omapfb.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/arm/omap/omapfb.c
diff -u src/sys/arch/arm/omap/omapfb.c:1.21 src/sys/arch/arm/omap/omapfb.c:1.22
--- src/sys/arch/arm/omap/omapfb.c:1.21	Sat Feb  9 13:28:59 2013
+++ src/sys/arch/arm/omap/omapfb.c	Tue Feb 12 21:17:37 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: omapfb.c,v 1.21 2013/02/09 13:28:59 jmcneill Exp $	*/
+/*	$NetBSD: omapfb.c,v 1.22 2013/02/12 21:17:37 macallan Exp $	*/
 
 /*
  * Copyright (c) 2010 Michael Lorenz
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: omapfb.c,v 1.21 2013/02/09 13:28:59 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: omapfb.c,v 1.22 2013/02/12 21:17:37 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -75,6 +75,15 @@ struct omapfb_softc {
 	int sc_width, sc_height, sc_depth, sc_stride;
 	int sc_locked;
 	void *sc_fbaddr, *sc_vramaddr;
+
+	int sc_cursor_offset;
+	uint32_t *sc_cursor_img;
+	int sc_cursor_x, sc_cursor_y;
+	int sc_hot_x, sc_hot_y;
+	uint8_t sc_cursor_bitmap[8 * 64];
+	uint8_t sc_cursor_mask[8 * 64];
+	uint32_t sc_cursor_cmap[4];
+
 	bus_addr_t sc_fbhwaddr;
 	uint32_t *sc_clut;
 	uint32_t sc_dispc_config;
@@ -112,6 +121,10 @@ static void 	omapfb_putpalreg(struct oma
 static int	omapfb_set_depth(struct omapfb_softc *, int);
 static void	omapfb_set_video(struct omapfb_softc *, int);
 
+static void 	omapfb_move_cursor(struct omapfb_softc *, int, int);
+static int	omapfb_do_cursor(struct omapfb_softc *,
+		    struct wsdisplay_cursor *);
+
 #if NOMAPDMA > 0
 static void	omapfb_init(struct omapfb_softc *);
 static void	omapfb_wait_idle(struct omapfb_softc *);
@@ -300,24 +313,53 @@ omapfb_attach(device_t parent, device_t 
 
 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_SYSCONFIG, 
 	    OMAP_SYSCONF_AUTOIDLE);
-	reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG);
-	reg = OMAP_DISPC_CTRL_ACTIVE_MTRX;
+
+	reg = OMAP_DISPC_CFG_TV_ALPHA_EN | OMAP_DISPC_CFG_LCD_ALPHA_EN;
 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG, reg);
 	sc->sc_dispc_config = reg;
 
+	/* we use overlay 1 for the console and X */
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GLOBAL_ALPHA, 0x00ff00ff);
 	sc->sc_fbhwaddr = sc->sc_dmamem->ds_addr + 0x1000;
-	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0, 
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_BASE_0, 
 	    sc->sc_fbhwaddr);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_POSITION, 
+	    0);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_SIZE, 
+	    ((sc->sc_height - 1) << 16) | (sc->sc_width - 1));
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_PICTURE_SIZE, 
+	    ((sc->sc_height - 1) << 16) | (sc->sc_width - 1));
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_ROW_INC, 1);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_PIXEL_INC, 1);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_PRELOAD, 0x60);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_ATTRIBUTES, 
+	    OMAP_VID_ATTR_ENABLE |
+	    OMAP_VID_ATTR_BURST_16x32 |
+	    OMAP_VID_ATTR_RGB16 |
+	    OMAP_VID_ATTR_REPLICATION);
+
+	/* turn off overlay 2 */
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID2_ATTRIBUTES, 0); 
+
+	/* initialize the gfx layer for use as hardware cursor */
+	sc->sc_cursor_cmap[0] = 0;
+	sc->sc_cursor_offset = (12 << 20) - (64 * 64 * 4);
+	sc->sc_cursor_img = (uint32_t *)((uint8_t *)sc->sc_fbaddr + sc->sc_cursor_offset);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0, 
+	    sc->sc_fbhwaddr + sc->sc_cursor_offset);
 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_TABLE_BASE, 
 	    sc->sc_dmamem->ds_addr);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE, 
+	    0x003f003f);
 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION, 
-	    0);
+	    0x00100010);
 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_PRELOAD, 0x60);
 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ATTRIBUTES, 
-	    OMAP_DISPC_ATTR_ENABLE |
+	    /*OMAP_DISPC_ATTR_ENABLE |*/
 	    OMAP_DISPC_ATTR_BURST_16x32 |
-	    /*OMAP_DISPC_ATTR_8BIT*/OMAP_DISPC_ATTR_RGB16
-	    | OMAP_DISPC_ATTR_REPLICATION);
+	    OMAP_DISPC_ATTR_ARGB32 |
+	    OMAP_DISPC_ATTR_REPLICATION);
+
 #if 0
 	printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
 	    OMAPFB_DSS_CONTROL));
@@ -532,6 +574,36 @@ omapfb_ioctl(void *v, void *vs, u_long c
 				omapfb_set_video(sc, *on);
 			}
 			return 0;
+
+		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;
+
+				omapfb_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 omapfb_do_cursor(sc, cursor);
+			}
 	}
 	return EPASSTHROUGH;
 }
@@ -685,15 +757,15 @@ omapfb_set_depth(struct omapfb_softc *sc
 {
 	uint32_t reg;
 
-	reg = OMAP_DISPC_ATTR_ENABLE |
-	      OMAP_DISPC_ATTR_BURST_16x32 |
-	      OMAP_DISPC_ATTR_REPLICATION;
+	reg = OMAP_VID_ATTR_ENABLE |
+	      OMAP_VID_ATTR_BURST_16x32 |
+	      OMAP_VID_ATTR_REPLICATION;
 	switch (d) {
 		case 16:
-			reg |= OMAP_DISPC_ATTR_RGB16;
+			reg |= OMAP_VID_ATTR_RGB16;
 			break;
 		case 32:
-			reg |= OMAP_DISPC_ATTR_RGB24;
+			reg |= OMAP_VID_ATTR_RGB24;
 			break;
 		default:
 			aprint_error_dev(sc->sc_dev, "unsupported depth (%d)\n", d);
@@ -701,7 +773,7 @@ omapfb_set_depth(struct omapfb_softc *sc
 	}
 
 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
-	    OMAPFB_DISPC_GFX_ATTRIBUTES, reg); 
+	    OMAPFB_DISPC_VID1_ATTRIBUTES, reg); 
 
 	/*
 	 * now tell the video controller that we're done mucking around and 
@@ -1025,3 +1097,127 @@ omapfb_eraserows(void *cookie, int row, 
 	}
 }
 #endif /* NOMAPDMA > 0 */
+
+static void
+omapfb_move_cursor(struct omapfb_softc *sc, int x, int y)
+{
+	uint32_t pos, reg, addr;
+	int xx, yy, wi = 64, he = 64;
+
+	/*
+	 * we need to special case anything and everything where the cursor
+	 * may be partially off screen
+	 */
+
+	addr = sc->sc_fbhwaddr + sc->sc_cursor_offset;
+	xx = x - sc->sc_hot_x;
+	yy = y - sc->sc_hot_y;
+
+	/*
+	 * if we're off to the top or left we need to shif the start address
+	 * and shrink the gfx layer size
+	 */
+	if (xx < 0) {
+		wi += xx;
+		addr -= xx * 4;
+		xx = 0;
+	}
+	if (yy < 0) {
+		he += yy;
+		addr -= yy * 64 * 4;
+		yy = 0;
+	}
+	if (xx > (sc->sc_width - 64)) {
+		wi -= (xx + 64 - sc->sc_width);
+	}
+	if (yy > (sc->sc_height - 64)) {
+		he -= (yy + 64 - sc->sc_height);
+	}
+	pos = (yy << 16) | xx;
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0,
+	    addr);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION, 
+	    pos);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE,
+	    ((he - 1) << 16) | (wi - 1));
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ROW_INC,
+	    (64 - wi) * 4 + 1);
+	/*
+	 * now tell the video controller that we're done mucking around and 
+	 * actually update its settings
+	 */
+	reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
+	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
+	    reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
+}
+
+static int
+omapfb_do_cursor(struct omapfb_softc * sc,
+                           struct wsdisplay_cursor *cur)
+{
+	int whack = 0;
+	int shape = 0;
+
+	if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
+		uint32_t attr = OMAP_DISPC_ATTR_BURST_16x32 |
+				OMAP_DISPC_ATTR_ARGB32 |
+				OMAP_DISPC_ATTR_REPLICATION;
+
+		if (cur->enable) attr |= OMAP_DISPC_ATTR_ENABLE;
+		bus_space_write_4(sc->sc_iot, sc->sc_regh,
+		    OMAPFB_DISPC_GFX_ATTRIBUTES, attr);
+		whack = 1;
+	}
+	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) {
+
+		omapfb_move_cursor(sc, cur->pos.x, cur->pos.y);
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
+		int i;
+		uint32_t val;
+	
+		for (i = 0; i < min(cur->cmap.count, 3); i++) {
+			val = (cur->cmap.red[i] << 16 ) |
+			      (cur->cmap.green[i] << 8) |
+			      (cur->cmap.blue[i] ) |
+			      0xff000000;
+			sc->sc_cursor_cmap[i + cur->cmap.index + 2] = val;
+		}
+		shape = 1;
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
+
+		copyin(cur->mask, sc->sc_cursor_mask, 64 * 8);
+		copyin(cur->image, sc->sc_cursor_bitmap, 64 * 8);
+		shape = 1;
+	}
+	if (shape) {
+		int i, j, idx;
+		uint8_t mask;
+
+		for (i = 0; i < 64 * 8; i++) {
+			mask = 0x01;
+			for (j = 0; j < 8; j++) {
+				idx = ((sc->sc_cursor_mask[i] & mask) ? 2 : 0) |
+				      ((sc->sc_cursor_bitmap[i] & mask) ? 1 : 0);
+				sc->sc_cursor_img[i * 8 + j] = sc->sc_cursor_cmap[idx];
+				mask = mask << 1;
+			} 
+		}
+	}
+	if (whack) {
+		uint32_t reg;
+
+		reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
+		bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
+		    reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
+	}		
+	return 0;
+
+}

Reply via email to