Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci implement WSDISPLAYIO_{GET|PUT}CMAP ioctl()s



details:   https://anonhg.NetBSD.org/src/rev/0e732f434248
branches:  trunk
changeset: 326218:0e732f434248
user:      macallan <macallan%NetBSD.org@localhost>
date:      Wed Jan 22 07:57:33 2014 +0000

description:
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 ;) )

diffstat:

 sys/dev/pci/radeonfb.c    |  233 ++++++++++++++++++++++++++++++++-------------
 sys/dev/pci/radeonfbvar.h |    4 +-
 2 files changed, 167 insertions(+), 70 deletions(-)

diffs (truncated from 346 to 300 lines):

diff -r bae577549c6e -r 0e732f434248 sys/dev/pci/radeonfb.c
--- a/sys/dev/pci/radeonfb.c    Wed Jan 22 06:18:17 2014 +0000
+++ b/sys/dev/pci/radeonfb.c    Wed Jan 22 07:57:33 2014 +0000
@@ -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 @@
     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 @@
        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 @@
                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 @@
        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_rectfill(dp, 0, 0, dp->rd_virtx,
                                    dp->rd_virty, dp->rd_bg);
                                vcons_redraw_screen(dp->rd_vd.active);
-                       } else {
+                       }
+                       if (dp->rd_wsmode == WSDISPLAYIO_MODE_MAPPED)
                                radeonfb_unmap(sc);
-                       }
                }
                return 0;
 
@@ -2549,20 +2566,12 @@
        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 @@
                else
                        CLR32(sc, RADEON_DAC_CNTL2, RADEON_DAC2_PALETTE_ACC_CTL);
 
-               PUT32(sc, RADEON_PALETTE_INDEX, 0);
-
-               if (dp->rd_bpp == 8) {
-
-                       /* R3G3B2 palette */
-                       int j = 0;
-                       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;
-
-                               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)));
-                       }
+               PUT32(sc, RADEON_PALETTE_INDEX, idx);
+               PUT32(sc, RADEON_PALETTE_30_DATA,
+                   (r << 22) | (g << 12) | (b << 2));
+       }
+
+       PUTPLL(sc, RADEON_VCLK_ECP_CNTL, vclk);
+}
+
+/*
+ * This loads a linear color map for true color.
+ */
+void
+radeonfb_init_palette(struct radeonfb_display *dp)
+{
+       int             i;
+
+#define        DAC_WIDTH ((1 << 10) - 1)
+#define        CLUT_WIDTH ((1 << 8) - 1)
+#define        CLUT_COLOR(i)      ((i * DAC_WIDTH * 2 / CLUT_WIDTH + 1) / 2)
+
+       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);
-
-       PUTPLL(sc, RADEON_VCLK_ECP_CNTL, vclk);
+}
+
+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];
+
+#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 @@
        return 0;
 }
 
+static uint8_t
+radeonfb_backwards(uint8_t d)
+{
+       uint8_t l;
+
+       l = d << 7;



Home | Main Index | Thread Index | Old Index