Module Name:    src
Committed By:   macallan
Date:           Wed Jan 22 07:57:33 UTC 2014

Modified Files:
        src/sys/dev/pci: radeonfb.c radeonfbvar.h

Log Message:
implement WSDISPLAYIO_{GET|PUT}CMAP ioctl()s
while there:
- unmap registers and vram only in WSDISPLAYIO_MODE_MAPPED ( so DRM can map
  them ) but not in WSDISPLAYIO_MODE_DUMBFB ( so wsfb can do things that
  require hardware access, like palette and cursor ioctl()s )
- reject ioctl()s that need hardware access if registers are unmapped ( so we
  don't crash instead )
- use the same bit order in cursor sprite images as the other drivers do
with all this, Xorg with wsfb works properly on top of radeonfb

tested on i386 and macppc ( fingers crossed for alpha ;) )


To generate a diff of this commit:
cvs rdiff -u -r1.81 -r1.82 src/sys/dev/pci/radeonfb.c
cvs rdiff -u -r1.18 -r1.19 src/sys/dev/pci/radeonfbvar.h

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/radeonfb.c
diff -u src/sys/dev/pci/radeonfb.c:1.81 src/sys/dev/pci/radeonfb.c:1.82
--- src/sys/dev/pci/radeonfb.c:1.81	Tue Jan 14 09:46:42 2014
+++ src/sys/dev/pci/radeonfb.c	Wed Jan 22 07:57:33 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: radeonfb.c,v 1.81 2014/01/14 09:46:42 macallan Exp $ */
+/*	$NetBSD: radeonfb.c,v 1.82 2014/01/22 07:57:33 macallan Exp $ */
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.81 2014/01/14 09:46:42 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.82 2014/01/22 07:57:33 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -140,6 +140,9 @@ static int radeonfb_set_cursor(struct ra
     struct wsdisplay_cursor *);
 static int radeonfb_set_curpos(struct radeonfb_display *,
     struct wsdisplay_curpos *);
+static void radeonfb_putpal(struct radeonfb_display *, int, int, int, int);
+static int radeonfb_putcmap(struct radeonfb_display *, struct wsdisplay_cmap *);
+static int radeonfb_getcmap(struct radeonfb_display *, struct wsdisplay_cmap *);
 
 /* acceleration support */
 static void  radeonfb_rectfill(struct radeonfb_display *, int dstx, int dsty,
@@ -1075,6 +1078,21 @@ radeonfb_ioctl(void *v, void *vs,
 	dp = (struct radeonfb_display *)vd->cookie;
 	sc = dp->rd_softc;
 
+	/* can't do these without registers being mapped */
+	if (!sc->sc_mapped) {
+		switch (cmd) {
+			case WSDISPLAYIO_GVIDEO:
+			case WSDISPLAYIO_SVIDEO:
+			case WSDISPLAYIO_GETCMAP:
+			case WSDISPLAYIO_PUTCMAP:
+			case WSDISPLAYIO_SCURSOR:
+			case WSDISPLAYIO_GCURPOS:
+			case WSDISPLAYIO_SCURPOS:
+			case WSDISPLAYIO_SETPARAM:
+				return EINVAL;
+		}
+	}
+
 	switch (cmd) {
 	case WSDISPLAYIO_GTYPE:
 		*(unsigned *)d = WSDISPLAY_TYPE_PCIMISC;
@@ -1104,19 +1122,15 @@ radeonfb_ioctl(void *v, void *vs,
 		return 0;
 
 	case WSDISPLAYIO_GETCMAP:
-#if 0
 		if (dp->rd_bpp == 8)
-			return radeonfb_getcmap(sc,
+			return radeonfb_getcmap(dp,
 			    (struct wsdisplay_cmap *)d);
-#endif
 		return EINVAL;
 		
 	case WSDISPLAYIO_PUTCMAP:
-#if 0
 		if (dp->rd_bpp == 8)
-			return radeonfb_putcmap(sc,
+			return radeonfb_putcmap(dp,
 			    (struct wsdisplay_cmap *)d);
-#endif
 		return EINVAL;
 		
 	case WSDISPLAYIO_LINEBYTES:
@@ -1126,9 +1140,12 @@ radeonfb_ioctl(void *v, void *vs,
 	case WSDISPLAYIO_SMODE:
 		if (*(int *)d != dp->rd_wsmode) {
 			dp->rd_wsmode = *(int *)d;
+			if ((dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) ||
+			    (dp->rd_wsmode == WSDISPLAYIO_MODE_DUMBFB))
+				radeonfb_map(sc);
+			
 			if ((dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) &&
 			    (dp->rd_vd.active)) {
-			    	radeonfb_map(sc);
 				radeonfb_engine_init(dp);
 				glyphcache_wipe(&dp->rd_gc);
 				radeonfb_init_palette(dp);
@@ -1136,9 +1153,9 @@ radeonfb_ioctl(void *v, void *vs,
 				radeonfb_rectfill(dp, 0, 0, dp->rd_virtx,
 				    dp->rd_virty, dp->rd_bg);
 				vcons_redraw_screen(dp->rd_vd.active);
-			} else {
-				radeonfb_unmap(sc);
 			}
+			if (dp->rd_wsmode == WSDISPLAYIO_MODE_MAPPED)
+				radeonfb_unmap(sc);
 		}
 		return 0;
 
@@ -2549,20 +2566,12 @@ radeonfb_init_misc(struct radeonfb_softc
 	PUT32(sc, RADEON_GEN_INT_STATUS, GET32(sc, RADEON_GEN_INT_STATUS));
 }
 
-/*
- * This loads a linear color map for true color.
- */
-void
-radeonfb_init_palette(struct radeonfb_display *dp)
+static void
+radeonfb_putpal(struct radeonfb_display *dp, int idx, int r, int g, int b)
 {
 	struct radeonfb_softc *sc = dp->rd_softc;
-	int		i, cc;
+	int		crtc, cc;
 	uint32_t	vclk;
-	int		crtc;
-
-#define	DAC_WIDTH ((1 << 10) - 1)
-#define	CLUT_WIDTH ((1 << 8) - 1)
-#define	CLUT_COLOR(i)      ((i * DAC_WIDTH * 2 / CLUT_WIDTH + 1) / 2)
 
 	vclk = GETPLL(sc, RADEON_VCLK_ECP_CNTL);
 	PUTPLL(sc, RADEON_VCLK_ECP_CNTL, vclk & ~RADEON_PIXCLK_DAC_ALWAYS_ONb);
@@ -2577,53 +2586,122 @@ radeonfb_init_palette(struct radeonfb_di
 		else
 			CLR32(sc, RADEON_DAC_CNTL2, RADEON_DAC2_PALETTE_ACC_CTL);
 
-		PUT32(sc, RADEON_PALETTE_INDEX, 0);
+		PUT32(sc, RADEON_PALETTE_INDEX, idx);
+            	PUT32(sc, RADEON_PALETTE_30_DATA,
+            	    (r << 22) | (g << 12) | (b << 2));
+	}
 
-		if (dp->rd_bpp == 8) {
+	PUTPLL(sc, RADEON_VCLK_ECP_CNTL, vclk);
+}
 
-			/* R3G3B2 palette */
-			int j = 0;
-			uint32_t tmp, r, g, b;
+/*
+ * This loads a linear color map for true color.
+ */
+void
+radeonfb_init_palette(struct radeonfb_display *dp)
+{
+	int		i;
 
-        	        for (i = 0; i <= CLUT_WIDTH; ++i) {
-    				tmp = i & 0xe0;
-				/*
-				 * replicate bits so 0xe0 maps to a red value of 0xff
-				 * in order to make white look actually white
-				 */
-				tmp |= (tmp >> 3) | (tmp >> 6);
-				r = tmp;
+#define	DAC_WIDTH ((1 << 10) - 1)
+#define	CLUT_WIDTH ((1 << 8) - 1)
+#define	CLUT_COLOR(i)      ((i * DAC_WIDTH * 2 / CLUT_WIDTH + 1) / 2)
 
-				tmp = (i & 0x1c) << 3;
-				tmp |= (tmp >> 3) | (tmp >> 6);
-				g = tmp;
-
-				tmp = (i & 0x03) << 6;
-				tmp |= tmp >> 2;
-				tmp |= tmp >> 4;
-				b = tmp;
-
-		            	PUT32(sc, RADEON_PALETTE_30_DATA,
-					(r << 22) |
-					(g << 12) |
-					(b << 2));
-				j += 3;
-			}
-		} else {
-			/* linear ramp */
-			for (i = 0; i <= CLUT_WIDTH; ++i) {
-				PUT32(sc, RADEON_PALETTE_30_DATA,
-				    (CLUT_COLOR(i) << 10) |
-				    (CLUT_COLOR(i) << 20) |
-				    (CLUT_COLOR(i)));
-			}
+	if (dp->rd_bpp == 8) {
+
+		/* R3G3B2 palette */
+		uint32_t tmp, r, g, b;
+ 
+	        for (i = 0; i <= CLUT_WIDTH; ++i) {
+			tmp = i & 0xe0;
+
+			/*
+			 * replicate bits so 0xe0 maps to a red value of 0xff
+			 * in order to make white look actually white
+			 */
+			tmp |= (tmp >> 3) | (tmp >> 6);
+			r = tmp;
+
+			tmp = (i & 0x1c) << 3;
+			tmp |= (tmp >> 3) | (tmp >> 6);
+			g = tmp;
+
+			tmp = (i & 0x03) << 6;
+			tmp |= tmp >> 2;
+			tmp |= tmp >> 4;
+			b = tmp;
+
+			radeonfb_putpal(dp, i, r, g, b);
+		}
+	} else {
+		/* linear ramp */
+		for (i = 0; i <= CLUT_WIDTH; ++i) {
+			radeonfb_putpal(dp, i, i, i, i);
 		}
 	}
+}
 
-	CLR32(sc, RADEON_DAC_CNTL2, RADEON_DAC2_PALETTE_ACC_CTL);
-	PRINTREG(RADEON_DAC_CNTL2);
+static int
+radeonfb_putcmap(struct radeonfb_display *dp, struct wsdisplay_cmap *cm)
+{
+	u_char *r, *g, *b;
+	u_int index = cm->index;
+	u_int count = cm->count;
+	int i, error;
+	u_char rbuf[256], gbuf[256], bbuf[256];
 
-	PUTPLL(sc, RADEON_VCLK_ECP_CNTL, vclk);
+#ifdef GENFB_DEBUG
+	aprint_debug("putcmap: %d %d\n",index, count);
+#endif
+	if (cm->index >= 256 || cm->count > 256 ||
+	    (cm->index + cm->count) > 256)
+		return EINVAL;
+	error = copyin(cm->red, &rbuf[index], count);
+	if (error)
+		return error;
+	error = copyin(cm->green, &gbuf[index], count);
+	if (error)
+		return error;
+	error = copyin(cm->blue, &bbuf[index], count);
+	if (error)
+		return error;
+
+	memcpy(&dp->rd_cmap_red[index], &rbuf[index], count);
+	memcpy(&dp->rd_cmap_green[index], &gbuf[index], count);
+	memcpy(&dp->rd_cmap_blue[index], &bbuf[index], count);
+
+	r = &dp->rd_cmap_red[index];
+	g = &dp->rd_cmap_green[index];
+	b = &dp->rd_cmap_blue[index];
+
+	for (i = 0; i < count; i++) {
+		radeonfb_putpal(dp, index, *r, *g, *b);
+		index++;
+		r++, g++, b++;
+	}
+	return 0;
+}
+
+static int
+radeonfb_getcmap(struct radeonfb_display *dp, struct wsdisplay_cmap *cm)
+{
+	u_int index = cm->index;
+	u_int count = cm->count;
+	int error;
+
+	if (index >= 255 || count > 256 || index + count > 256)
+		return EINVAL;
+
+	error = copyout(&dp->rd_cmap_red[index],   cm->red,   count);
+	if (error)
+		return error;
+	error = copyout(&dp->rd_cmap_green[index], cm->green, count);
+	if (error)
+		return error;
+	error = copyout(&dp->rd_cmap_blue[index],  cm->blue,  count);
+	if (error)
+		return error;
+
+	return 0;
 }
 
 /*
@@ -3498,6 +3576,22 @@ radeonfb_set_cursor(struct radeonfb_disp
 	return 0;
 }
 
+static uint8_t
+radeonfb_backwards(uint8_t d)
+{
+	uint8_t l;
+
+	l = d << 7;
+	l |= ((d & 0x02) << 5); 
+	l |= ((d & 0x04) << 3); 
+	l |= ((d & 0x08) << 1);
+	l |= ((d & 0x10) >> 1); 
+	l |= ((d & 0x20) >> 3); 
+	l |= ((d & 0x40) >> 5); 
+	l |= ((d & 0x80) >> 7);
+	return l;
+} 
+ 
 /*
  * Change the cursor shape.  Call this with the cursor locked to avoid
  * flickering/tearing.
@@ -3563,6 +3657,11 @@ radeonfb_cursor_shape(struct radeonfb_di
 		}
 	}
 
+	for (i = 0; i < 512; i++) {
+		and[i] = radeonfb_backwards(and[i]);
+		xor[i] = radeonfb_backwards(xor[i]);
+	}
+
 	/* copy the image into place */
 	for (i = 0; i < 64; i++) {
 		memcpy((uint8_t *)dp->rd_curptr + (i * 16),

Index: src/sys/dev/pci/radeonfbvar.h
diff -u src/sys/dev/pci/radeonfbvar.h:1.18 src/sys/dev/pci/radeonfbvar.h:1.19
--- src/sys/dev/pci/radeonfbvar.h:1.18	Thu Mar 28 17:25:10 2013
+++ src/sys/dev/pci/radeonfbvar.h	Wed Jan 22 07:57:33 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: radeonfbvar.h,v 1.18 2013/03/28 17:25:10 macallan Exp $ */
+/* $NetBSD: radeonfbvar.h,v 1.19 2014/01/22 07:57:33 macallan Exp $ */
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -196,11 +196,9 @@ struct radeonfb_display {
 	void (*rd_putchar)(void *, int, int, u_int, long);
 	glyphcache		rd_gc;
 
-#if 0
 	uint8_t			rd_cmap_red[256];
 	uint8_t			rd_cmap_green[256];
 	uint8_t			rd_cmap_blue[256];
-#endif
 
 #ifdef SPLASHSCREEN
 	struct splash_info	rd_splash;

Reply via email to