Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci add mode setting support



details:   https://anonhg.NetBSD.org/src/rev/a6552a1d4a6c
branches:  trunk
changeset: 781530:a6552a1d4a6c
user:      macallan <macallan%NetBSD.org@localhost>
date:      Thu Sep 13 02:09:00 2012 +0000

description:
add mode setting support
While there, don't pretend to support the Permedia2 non-V - I don't have the
hardware and it has never been tested in the first place. The only hardware
this has been tested on is a TechSource Raptor GFX 8P / Sun PGX32 which
happens to be a Permedia2V with Sun firmware.

diffstat:

 sys/dev/pci/pm2fb.c |  224 ++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 166 insertions(+), 58 deletions(-)

diffs (truncated from 398 to 300 lines):

diff -r f85a9b86e99c -r a6552a1d4a6c sys/dev/pci/pm2fb.c
--- a/sys/dev/pci/pm2fb.c       Thu Sep 13 00:36:12 2012 +0000
+++ b/sys/dev/pci/pm2fb.c       Thu Sep 13 02:09:00 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pm2fb.c,v 1.17 2012/09/12 12:07:04 macallan Exp $      */
+/*     $NetBSD: pm2fb.c,v 1.18 2012/09/13 02:09:00 macallan Exp $      */
 
 /*
  * Copyright (c) 2009 Michael Lorenz
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pm2fb.c,v 1.17 2012/09/12 12:07:04 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pm2fb.c,v 1.18 2012/09/13 02:09:00 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -104,7 +104,7 @@
        struct i2c_controller sc_i2c;
        uint8_t sc_edid_data[128];
        struct edid_info sc_ei;
-       struct videomode *sc_videomode;
+       const struct videomode *sc_videomode;
        glyphcache sc_gc;
 };
 
@@ -180,12 +180,49 @@
        }
 };
 
-#if 0
 /* mode setting stuff */
 static int pm2fb_set_pll(struct pm2fb_softc *, int);
 static uint8_t pm2fb_read_dac(struct pm2fb_softc *, int);
 static void pm2fb_write_dac(struct pm2fb_softc *, int, uint8_t);
-#endif
+static void pm2fb_set_mode(struct pm2fb_softc *, const struct videomode *);
+
+/* this table is from xf86-video-glint */
+#define PARTPROD(a,b,c) (((a)<<6) | ((b)<<3) | (c))
+int partprodPermedia[] = {
+       -1,
+       PARTPROD(0,0,1), PARTPROD(0,1,1), PARTPROD(1,1,1), PARTPROD(1,1,2),
+       PARTPROD(1,2,2), PARTPROD(2,2,2), PARTPROD(1,2,3), PARTPROD(2,2,3),
+       PARTPROD(1,3,3), PARTPROD(2,3,3), PARTPROD(1,2,4), PARTPROD(3,3,3),
+       PARTPROD(1,3,4), PARTPROD(2,3,4),              -1, PARTPROD(3,3,4), 
+       PARTPROD(1,4,4), PARTPROD(2,4,4),              -1, PARTPROD(3,4,4), 
+                    -1, PARTPROD(2,3,5),              -1, PARTPROD(4,4,4), 
+       PARTPROD(1,4,5), PARTPROD(2,4,5), PARTPROD(3,4,5),              -1,
+                    -1,              -1,              -1, PARTPROD(4,4,5), 
+       PARTPROD(1,5,5), PARTPROD(2,5,5),              -1, PARTPROD(3,5,5), 
+                    -1,              -1,              -1, PARTPROD(4,5,5), 
+                    -1,              -1,              -1, PARTPROD(3,4,6),
+                    -1,              -1,              -1, PARTPROD(5,5,5), 
+       PARTPROD(1,5,6), PARTPROD(2,5,6),              -1, PARTPROD(3,5,6),
+                    -1,              -1,              -1, PARTPROD(4,5,6),
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1, PARTPROD(5,5,6),
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    -1,              -1,              -1,              -1,
+                    0};
 
 static inline void
 pm2fb_wait(struct pm2fb_softc *sc, int slots)
@@ -225,10 +262,10 @@
                return 0;
 
        /*
-        * only card tested on so far is a TechSource Raptor GFX 8P 
+        * only card tested on so far is a TechSource Raptor GFX 8P /
         * Sun PGX32, which happens to be a Permedia 2v
         */
-       if ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DLABS_PERMEDIA2) ||
+       if (/*(PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DLABS_PERMEDIA2) ||*/
            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DLABS_PERMEDIA2V))
                return 100;
        return (0);
@@ -257,28 +294,31 @@
            PCI_PRODUCT_3DLABS_PERMEDIA2);
        pci_aprint_devinfo(pa, NULL);
 
-       /* fill in parameters from properties */
+       /*
+        * fill in parameters from properties
+        * if we can't get a usable mode via DDC2 we'll use this to pick one,
+        * which is why we fill them in with some conservative values that 
+        * hopefully work as a last resort
+        */
        dict = device_properties(self);
        if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) {
                aprint_error("%s: no width property\n", device_xname(self));
-               return;
+               sc->sc_width = 1024;
        }
        if (!prop_dictionary_get_uint32(dict, "height", &sc->sc_height)) {
                aprint_error("%s: no height property\n", device_xname(self));
-               return;
+               sc->sc_height = 768;
        }
        if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) {
                aprint_error("%s: no depth property\n", device_xname(self));
-               return;
+               sc->sc_depth = 8;
        }
+
        /*
         * don't look at the linebytes property - The Raptor firmware lies
         * about it. Get it from width * depth >> 3 instead.
         */
 
-#if 0
-       sc->sc_depth = 8;
-#endif
        sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3);
 
        prop_dictionary_get_bool(dict, "is_console", &is_console);
@@ -317,12 +357,7 @@
        vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
            &pm2fb_accessops);
        sc->vd.init_screen = pm2fb_init_screen;
-
-#if 0
-       pm2fb_write_dac(sc, PM2V_DAC_PIXEL_SIZE, PM2V_PS_8BIT);
-       pm2fb_write_dac(sc, PM2V_DAC_COLOR_FORMAT, PM2V_DAC_PALETTE);
-#endif
-
+       
        /* init engine here */
        pm2fb_init(sc);
 
@@ -353,11 +388,11 @@
                sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
                /* XXX use actual memory size instead of assuming 8MB */
                glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
-                               (0x800000 / sc->sc_stride) - sc->sc_height - 5,
-                               sc->sc_width,
-                               ri->ri_font->fontwidth,
-                               ri->ri_font->fontheight,
-                               defattr);
+                       (sc->sc_fbsize / sc->sc_stride) - sc->sc_height - 5,
+                       sc->sc_width,
+                       ri->ri_font->fontwidth,
+                       ri->ri_font->fontheight,
+                       defattr);
                wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
                    defattr);
                vcons_replay_msgbuf(&sc->sc_console_screen);
@@ -365,11 +400,11 @@
                if (sc->sc_console_screen.scr_ri.ri_rows == 0) {
                        /* do some minimal setup to avoid weirdnesses later */
                        glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
-                               (0x800000 / sc->sc_stride) - sc->sc_height - 5,
-                               sc->sc_width,
-                               ri->ri_font->fontwidth,
-                               ri->ri_font->fontheight,
-                               defattr);
+                          (sc->sc_fbsize / sc->sc_stride) - sc->sc_height - 5,
+                          sc->sc_width,
+                          ri->ri_font->fontwidth,
+                          ri->ri_font->fontheight,
+                          defattr);
                        vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 
                           &defattr);
                }
@@ -653,7 +688,6 @@
        return 0;
 }
 
-#if 0
 static uint8_t
 pm2fb_read_dac(struct pm2fb_softc *sc, int reg)
 {
@@ -675,6 +709,7 @@
 static void
 pm2fb_write_dac(struct pm2fb_softc *sc, int reg, uint8_t data)
 {
+       pm2fb_wait(sc, 3);
        if (sc->sc_is_pm2) {
                bus_space_write_1(sc->sc_memt, sc->sc_regh,
                    PM2_DAC_PAL_WRITE_IDX, reg);
@@ -689,7 +724,6 @@
                    PM2V_DAC_INDEX_DATA, data);
        }       
 }
-#endif
 
 static void
 pm2fb_init(struct pm2fb_softc *sc)
@@ -730,9 +764,13 @@
        bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_STIPPLE_MODE, 0);
        bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_ROP_MODE, 0);
        bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_WINDOW_ORIGIN, 0);
+#if 0
        sc->sc_pprod = bus_space_read_4(sc->sc_memt, sc->sc_regh, 
            PM2_FB_READMODE) &
            (PM2FB_PP0_MASK | PM2FB_PP1_MASK | PM2FB_PP2_MASK);
+#endif
+       sc->sc_pprod = partprodPermedia[sc->sc_stride >> 5];
+
        bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_FB_READMODE, 
            sc->sc_pprod);
        bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_TEXMAP_FORMAT, 
@@ -1039,7 +1077,6 @@
        /*
         * TODO:
         * - use packed mode here as well, instead of writing each pixel separately
-        * - support 32bit colour
         * - see if we can trick the chip into doing the alpha blending for us
         */
        x = x >> 2;
@@ -1204,7 +1241,16 @@
        }
 }
 
-#define MODE_IS_VALID(m) (((m)->hdisplay < 2048) && ((m)->dot_clock < 230000))
+/*
+ * Permedia2 requires a stride that's a multiple of 32 pixels.
+ * For now reject modes with odd widths, although at some point we may want
+ * to just pick the next bigger stride and waste a few kB of video memory
+ */
+
+#define MODE_IS_VALID(m) (((m)->hdisplay < 2048) && \
+       ((m)->dot_clock < 230000) && \
+       (((m)->hdisplay & 32) == 0))
+
 static void
 pm2_setup_i2c(struct pm2fb_softc *sc)
 {
@@ -1236,7 +1282,6 @@
        i = 0;
        while (sc->sc_edid_data[1] == 0 && i < 10) {
                ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, 128);
-               printf("\n");
                i++;
        }
 #ifdef PM2FB_DEBUG
@@ -1248,7 +1293,7 @@
                printf("\n");
        }
 #endif
-#if 0
+
        if (edid_parse(&sc->sc_edid_data[0], &sc->sc_ei) != -1) {
 #ifdef PM2FB_DEBUG
                edid_print(&sc->sc_ei);
@@ -1286,17 +1331,14 @@
                        }
                }
        }
+       if (sc->sc_videomode == NULL) {
+               /* no EDID data? */
+               sc->sc_videomode = pick_mode_by_ref(sc->sc_width, 
+                   sc->sc_height, 60);
+       }
        if (sc->sc_videomode != NULL) {
-               pm2fb_set_pll(sc, sc->sc_videomode->dot_clock);
-               if (sc->sc_is_pm2) {
-                       printf("DAC: %02x\n",
-                           pm2fb_read_dac(sc, PM2_DAC_COLOR_MODE));
-               } else
-                       printf("DAC: %02x\n",
-                           pm2fb_read_dac(sc, PM2V_DAC_COLOR_FORMAT));
-               if (0) pm2fb_write_dac(sc, PM2_DAC_COLOR_MODE, CM_PALETTE);
+               pm2fb_set_mode(sc, sc->sc_videomode);
        }
-#endif
 }
 
 /* I2C bitbanging */
@@ -1372,25 +1414,22 @@
        return (i2c_bitbang_write_byte(cookie, val, flags, &pm2fb_i2cbb_ops));
 }
 
-#if 0
-
 #define RefClk 14318   /* all frequencies are in kHz */
 static int
 pm2fb_set_pll(struct pm2fb_softc *sc, int freq)
 {
        int m, n, p, diff, out_freq, bm, bn, bp, bdiff = 1000000, bfreq;
        int fi;
+       uint8_t temp;
 
        /*
-        * this should work on both PM2 and PM2V 



Home | Main Index | Thread Index | Old Index