]> git.hungrycats.org Git - linux/commitdiff
[PATCH] (1/3) matroxfb for 2.5.3
authorPetr Vandrovec <vandrove@vc.cvut.cz>
Tue, 19 Feb 2002 05:56:37 +0000 (21:56 -0800)
committerPetr Vandrovec <vandrove@vc.cvut.cz>
Tue, 19 Feb 2002 05:56:37 +0000 (21:56 -0800)
(1) Updates documentation.
(2) Remove 'current' and 'previous' hardware fields. X just do not play fair,
    and one cannot assume anything about current hardware state.
(3) Changes algorithm for computing PLL parameters to one used by Matrox. On
    recent chips (G550) there are no limits for PLL, you just have to try
    couple of possible combinations to find which one works on this
    particualr hardware.
(4) Add code which can intialize G450/G550 when BIOS did not initalize it
    (non-ia32 hardware, secondary devices on ia32 hardware).

Petr Vandrovec

16 files changed:
Documentation/fb/matroxfb.txt
drivers/video/Config.help
drivers/video/Config.in
drivers/video/matrox/Makefile
drivers/video/matrox/g450_pll.c [new file with mode: 0644]
drivers/video/matrox/g450_pll.h [new file with mode: 0644]
drivers/video/matrox/matroxfb_DAC1064.c
drivers/video/matrox/matroxfb_DAC1064.h
drivers/video/matrox/matroxfb_Ti3026.c
drivers/video/matrox/matroxfb_base.c
drivers/video/matrox/matroxfb_base.h
drivers/video/matrox/matroxfb_crtc2.c
drivers/video/matrox/matroxfb_g450.c
drivers/video/matrox/matroxfb_maven.c
drivers/video/matrox/matroxfb_misc.c
drivers/video/matrox/matroxfb_misc.h

index 508aaa1878ef290a0189b84ba42a01434d3aaa1a..1d0dd81dccde3eaf828cb90067c4f89915966231 100644 (file)
@@ -10,7 +10,7 @@ Advantages:
 
  * It provides a nice large console (128 cols + 48 lines with 1024x768)
    without using tiny, unreadable fonts.
- * You can run XF68_FBDev on top of /dev/fb0
+ * You can run XF{68,86}_FBDev or XFree86 fbdev driver on top of /dev/fb0
  * Most important: boot logo :-)
 
 Disadvantages:
@@ -27,9 +27,6 @@ or using `fbset' program.
 
 If you want, for example, enable a resolution of 1280x1024x24bpp you should
 pass to the kernel this command line: "video=matrox:vesa:0x1BB".
-Note that the same line, if 'appended' as a lilo parameter in lilo.conf will
-read "video=matrox:vesa:443" because lilo pass integer parameters as decimal
-numbers to the kernel.
 
 You should compile in both vgacon (to boot if you remove you Matrox from
 box) and matroxfb (for graphics mode). You should not compile-in vesafb
@@ -82,13 +79,16 @@ example 1600x1200x32bpp can be specified by `video=matrox:vesa:0x11C,depth:32'.
 X11
 ===
 
-XF68_FBDev should work just fine, but it is non-accelerated. On non-intel
+XF{68,86}_FBDev should work just fine, but it is non-accelerated. On non-intel
 architectures there are some glitches for 24bpp videomodes. 8, 16 and 32bpp
 works fine.
 
 Running another (accelerated) X-Server like XF86_SVGA works too. But (at least)
 XFree servers have big troubles in multihead configurations (even on first
-head, not even talking about second).
+head, not even talking about second). Running XFree86 4.x accelerated mga 
+driver is possible, but you must not enable DRI - if you do, resolution and
+color depth of your X desktop must match resolution and color depths of your
+virtual consoles, otherwise X will corrupt accelerator settings.
 
 
 SVGALib
index 1dcfd5b473acc3566ceb7a29f8ca754ac78f0ed8..a3598e051049b6db2a01a76e8eaefd2f0e962140 100644 (file)
@@ -381,8 +381,8 @@ CONFIG_FB_MATROX
   Say Y here if you have a Matrox Millennium, Matrox Millennium II,
   Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
   Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video,
-  Matrox G400 or G450 card in your box. At this time, support for the
-  G100 is untested and support for G450 is highly experimental.
+  Matrox G400, G450 or G550 card in your box. At this time, support for 
+  the G-series digital output is almost non-existant.
 
   This driver is also available as a module ( = code which can be
   inserted and removed from the running kernel whenever you want).
@@ -408,7 +408,7 @@ CONFIG_FB_MATROX_MYSTIQUE
   different from 8.
 
 CONFIG_FB_MATROX_G100
-  Say Y here if you have a Matrox G100, G200, G400 or G450 based
+  Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based
   video card. If you select "Advanced lowlevel driver options", you
   should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
   pixel and 32 bpp packed pixel. You can also use font widths
@@ -418,6 +418,10 @@ CONFIG_FB_MATROX_G100
   "I2C support" and "I2C bit-banging support" in the character devices
   section, and then to "Matrox I2C support" and "G400 second head
   support" here in the framebuffer section.
+  
+  If you have G550, you must also compile support for G450/G550 secondary
+  head into kernel, otherwise picture will be shown only on output you
+  are probably not using...
 
 CONFIG_FB_MATROX_I2C
   This drivers creates I2C buses which are needed for accessing the
@@ -462,7 +466,8 @@ CONFIG_FB_MATROX_MAVEN
 
 CONFIG_FB_MATROX_G450
   Say Y or M here if you want to use a secondary head (meaning two
-  monitors in parallel) on G450.
+  monitors in parallel) on G450, or if you are using analog output
+  of G550.
 
   If you compile it as module, two modules are created,
   matroxfb_crtc2.o and matroxfb_g450.o. Both modules are needed if you
index 1d92c99c25052c0b582f5e6d7d2c0d7f4d217db5..f5ce38ed128fd77d3b4f7721bd770075101c3eae 100644 (file)
@@ -121,14 +121,14 @@ if [ "$CONFIG_FB" = "y" ]; then
         if [ "$CONFIG_FB_MATROX" != "n" ]; then
            bool '    Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM
            bool '    Mystique support' CONFIG_FB_MATROX_MYSTIQUE
-           bool '    G100/G200/G400/G450 support' CONFIG_FB_MATROX_G100
+           bool '    G100/G200/G400/G450/G550 support' CONFIG_FB_MATROX_G100
             if [ "$CONFIG_I2C" != "n" ]; then
               dep_tristate '      Matrox I2C support' CONFIG_FB_MATROX_I2C $CONFIG_FB_MATROX $CONFIG_I2C_ALGOBIT
               if [ "$CONFIG_FB_MATROX_G100" = "y" ]; then
                  dep_tristate '      G400 second head support' CONFIG_FB_MATROX_MAVEN $CONFIG_FB_MATROX_I2C
               fi
             fi
-            dep_tristate '      G450 second head support' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100
+            dep_tristate '      G450/G550 second head support (mandatory for G550)' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100
            bool '    Multihead support' CONFIG_FB_MATROX_MULTIHEAD
         fi
         tristate '  ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY
index 2b7945150cbe59c8c2fdbc021836e4b7cfb9bfae..b34afde318ded726dcbde87255ebbfd06effdcfb 100644 (file)
@@ -7,11 +7,13 @@ O_TARGET := matrox.o
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
-export-objs    :=  matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o
+export-objs    :=  matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o g450_pll.o
 
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_FB_MATROX)           += matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o
+my-obj-$(CONFIG_FB_MATROX_G100)          := g450_pll.o
+
+obj-$(CONFIG_FB_MATROX)           += matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o $(my-obj-y)
 obj-$(CONFIG_FB_MATROX_I2C)       += i2c-matroxfb.o
 obj-$(CONFIG_FB_MATROX_MAVEN)     += matroxfb_maven.o matroxfb_crtc2.o
 obj-$(CONFIG_FB_MATROX_G450)     += matroxfb_g450.o matroxfb_crtc2.o
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
new file mode 100644 (file)
index 0000000..2b7e81b
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ *
+ * Hardware accelerated Matrox PCI cards - G450/G550 PLL control.
+ *
+ * (c) 2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.62 2001/11/29
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ */
+
+#include "g450_pll.h"
+#include "matroxfb_DAC1064.h"
+
+static inline unsigned int g450_vco2f(unsigned char p, unsigned int fvco) {
+       return (p & 0x40) ? fvco : fvco >> ((p & 3) + 1);
+}
+
+static inline unsigned int g450_f2vco(unsigned char p, unsigned int fin) {
+       return (p & 0x40) ? fin : fin << ((p & 3) + 1);
+}
+
+static unsigned int g450_mnp2vco(CPMINFO unsigned int mnp) {
+       unsigned int m, n;
+
+       m = ((mnp >> 16) & 0x0FF) + 1;
+       n = ((mnp >>  7) & 0x1FE) + 4;
+       return (ACCESS_FBINFO(features).pll.ref_freq * n + (m >> 1)) / m;
+}
+
+static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) {
+       if (f2 < f1) {
+               f2 = f1 - f2;
+       } else {
+               f2 = f2 - f1;
+       }
+       return f2;
+}
+
+#define NO_MORE_MNP    0x01FFFFFF
+#define G450_MNP_FREQBITS      (0xFFFFFF43)    /* do not mask high byte so we'll catch NO_MORE_MNP */
+
+static unsigned int g450_nextpll(CPMINFO const struct matrox_pll_limits* pi, unsigned int* fvco, unsigned int mnp) {
+       unsigned int m, n, p;
+       unsigned int tvco = *fvco;
+
+       m = (mnp >> 16) & 0xFF;
+       p = mnp & 0xFF;
+
+       if (m == 0 || m == 0xFF) {
+               if (m == 0) {
+                       if (p & 0x40) {
+                               return NO_MORE_MNP;
+                       }
+                       if (p & 3) {
+                               p--;
+                       } else {
+                               p = 0x40;
+                       }
+                       tvco >>= 1;
+                       if (tvco < pi->vcomin) {
+                               return NO_MORE_MNP;
+                       }
+                       *fvco = tvco;
+               }
+
+               p &= 0x43;
+               if (tvco < 550000) {
+/*                     p |= 0x00; */
+               } else if (tvco < 700000) {
+                       p |= 0x08;
+               } else if (tvco < 1000000) {
+                       p |= 0x10;
+               } else if (tvco < 1150000) {
+                       p |= 0x18;
+               } else {
+                       p |= 0x20;
+               }
+               m = 9;
+       } else {
+               m--;
+       }
+        n = ((tvco * (m+1) + ACCESS_FBINFO(features).pll.ref_freq) / (ACCESS_FBINFO(features).pll.ref_freq * 2)) - 2;
+       return (m << 16) | (n << 8) | p;
+}
+
+static unsigned int g450_firstpll(CPMINFO const struct matrox_pll_limits* pi, unsigned int* vco, unsigned int fout) {
+       unsigned int p;
+       unsigned int vcomax;
+
+       vcomax = pi->vcomax;
+       if (fout > (vcomax / 2)) {
+               if (fout > vcomax) {
+                       *vco = vcomax;
+               } else {
+                       *vco = fout;
+               }
+               p = 0x40;
+       } else {
+               unsigned int tvco;
+
+               p = 3;
+               tvco = g450_f2vco(p, fout);
+               while (p && (tvco > vcomax)) {
+                       p--;
+                       tvco >>= 1;
+               }
+               if (tvco < pi->vcomin) {
+                       tvco = pi->vcomin;
+               }
+               *vco = tvco;
+       }
+       return g450_nextpll(PMINFO pi, vco, 0xFF0000 | p);
+}
+
+static inline unsigned int g450_setpll(CPMINFO unsigned int mnp, unsigned int pll) {
+       switch (pll) {
+               case M_PIXEL_PLL_A:
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLAM, mnp >> 16);
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLAN, mnp >> 8);
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLAP, mnp);
+                       return M1064_XPIXPLLSTAT;
+
+               case M_PIXEL_PLL_B:
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLBM, mnp >> 16);
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLBN, mnp >> 8);
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLBP, mnp);
+                       return M1064_XPIXPLLSTAT;
+
+               case M_PIXEL_PLL_C:
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLCM, mnp >> 16);
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLCN, mnp >> 8);
+                       matroxfb_DAC_out(PMINFO M1064_XPIXPLLCP, mnp);
+                       return M1064_XPIXPLLSTAT;
+
+               case M_SYSTEM_PLL:
+                       matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLM, mnp >> 16);
+                       matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLN, mnp >> 8);
+                       matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLP, mnp);
+                       return DAC1064_XSYSPLLSTAT;
+
+               case M_VIDEO_PLL:
+                       matroxfb_DAC_out(PMINFO M1064_XVIDPLLM, mnp >> 16);
+                       matroxfb_DAC_out(PMINFO M1064_XVIDPLLN, mnp >> 8);
+                       matroxfb_DAC_out(PMINFO M1064_XVIDPLLP, mnp);
+                       return M1064_XVIDPLLSTAT;
+       }
+       return 0;
+}
+
+static inline unsigned int g450_cmppll(CPMINFO unsigned int mnp, unsigned int pll) {
+       unsigned char m = mnp >> 16;
+       unsigned char n = mnp >> 8;
+       unsigned char p = mnp;
+
+       switch (pll) {
+               case M_PIXEL_PLL_A:
+                       return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLAM) != m ||
+                               matroxfb_DAC_in(PMINFO M1064_XPIXPLLAN) != n ||
+                               matroxfb_DAC_in(PMINFO M1064_XPIXPLLAP) != p);
+
+               case M_PIXEL_PLL_B:
+                       return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLBM) != m ||
+                               matroxfb_DAC_in(PMINFO M1064_XPIXPLLBN) != n ||
+                               matroxfb_DAC_in(PMINFO M1064_XPIXPLLBP) != p);
+
+               case M_PIXEL_PLL_C:
+                       return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLCM) != m ||
+                               matroxfb_DAC_in(PMINFO M1064_XPIXPLLCN) != n ||
+                               matroxfb_DAC_in(PMINFO M1064_XPIXPLLCP) != p);
+
+               case M_SYSTEM_PLL:
+                       return (matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLM) != m ||
+                               matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLN) != n ||
+                               matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLP) != p);
+
+               case M_VIDEO_PLL:
+                       return (matroxfb_DAC_in(PMINFO M1064_XVIDPLLM) != m ||
+                               matroxfb_DAC_in(PMINFO M1064_XVIDPLLN) != n ||
+                               matroxfb_DAC_in(PMINFO M1064_XVIDPLLP) != p);
+       }
+       return 1;
+}
+
+static inline int g450_isplllocked(CPMINFO unsigned int regidx) {
+       unsigned int j;
+
+       for (j = 0; j < 1000; j++) {
+               if (matroxfb_DAC_in(PMINFO regidx) & 0x40) {
+                       unsigned int r = 0;
+                       int i;
+
+                       for (i = 0; i < 100; i++) {
+                               r += matroxfb_DAC_in(PMINFO regidx) & 0x40;
+                       }
+                       return r >= (90 * 0x40);
+               }
+               /* udelay(1)... but DAC_in is much slower... */
+       }
+       return 0;
+}
+
+static int g450_testpll(CPMINFO unsigned int mnp, unsigned int pll) {
+       return g450_isplllocked(PMINFO g450_setpll(PMINFO mnp, pll));
+}
+
+static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsigned int pll) {
+       switch (pll) {
+               case M_SYSTEM_PLL:
+                       hw->DACclk[3] = mnp >> 16;
+                       hw->DACclk[4] = mnp >> 8;
+                       hw->DACclk[5] = mnp;
+                       break;
+       }
+}
+
+static inline void g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll) {
+       if (g450_cmppll(PMINFO mnp, pll)) {
+               g450_setpll(PMINFO mnp, pll);
+       }
+}
+
+static inline unsigned int g450_findworkingpll(WPMINFO unsigned int pll, unsigned int* mnparray, unsigned int mnpcount) {
+       unsigned int found = 0;
+       unsigned int idx;
+       unsigned int mnpfound = mnparray[0];
+               
+       for (idx = 0; idx < mnpcount; idx++) {
+               unsigned int sarray[3];
+               unsigned int *sptr;
+               {
+                       unsigned int mnp;
+               
+                       sptr = sarray;
+                       mnp = mnparray[idx];
+                       if (mnp & 0x38) {
+                               *sptr++ = mnp - 8;
+                       }
+                       if ((mnp & 0x38) != 0x38) {
+                               *sptr++ = mnp + 8;
+                       }
+                       *sptr = mnp;
+               }
+               while (sptr >= sarray) {
+                       unsigned int mnp = *sptr--;
+               
+                       if (g450_testpll(PMINFO mnp - 0x0300, pll) &&
+                           g450_testpll(PMINFO mnp + 0x0300, pll) &&
+                           g450_testpll(PMINFO mnp - 0x0200, pll) &&
+                           g450_testpll(PMINFO mnp + 0x0200, pll) &&
+                           g450_testpll(PMINFO mnp - 0x0100, pll) &&
+                           g450_testpll(PMINFO mnp + 0x0100, pll)) {
+                               if (g450_testpll(PMINFO mnp, pll)) {
+                                       return mnp;
+                               }
+                       } else if (!found && g450_testpll(PMINFO mnp, pll)) {
+                               mnpfound = mnp;
+                               found = 1;
+                       }
+               }
+       }
+       g450_setpll(PMINFO mnpfound, pll);
+       return mnpfound;
+}
+
+static void g450_addcache(struct matrox_pll_cache* ci, unsigned int mnp_key, unsigned int mnp_value) {
+       if (++ci->valid > ARRAY_SIZE(ci->data)) {
+               ci->valid = ARRAY_SIZE(ci->data);
+       }
+       memmove(ci->data + 1, ci->data, (ci->valid - 1) * sizeof(*ci->data));
+       ci->data[0].mnp_key = mnp_key & G450_MNP_FREQBITS;
+       ci->data[0].mnp_value = mnp_value;
+}
+
+static int g450_checkcache(WPMINFO struct matrox_pll_cache* ci, unsigned int mnp_key) {
+       unsigned int i;
+       
+       mnp_key &= G450_MNP_FREQBITS;
+       for (i = 0; i < ci->valid; i++) {
+               if (ci->data[i].mnp_key == mnp_key) {
+                       unsigned int mnp;
+                       
+                       mnp = ci->data[i].mnp_value;
+                       if (i) {
+                               memmove(ci->data + 1, ci->data, i * sizeof(*ci->data));
+                               ci->data[0].mnp_key = mnp_key;
+                               ci->data[0].mnp_value = mnp;
+                       }
+                       return mnp;
+               }
+       }
+       return NO_MORE_MNP;
+}
+
+static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, 
+               unsigned int* mnparray, unsigned int* deltaarray) {
+       unsigned int mnpcount;
+       unsigned int pixel_vco;
+       const struct matrox_pll_limits* pi;
+       struct matrox_pll_cache* ci;
+
+       pixel_vco = 0;
+       switch (pll) {
+               case M_PIXEL_PLL_A:
+               case M_PIXEL_PLL_B:
+               case M_PIXEL_PLL_C:
+                       {
+                               u_int8_t tmp;
+                               unsigned long flags;
+                               
+                               matroxfb_DAC_lock_irqsave(flags);
+                               tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL);
+                               if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) {
+                                       matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp | M1064_XPIXCLKCTRL_PLL_UP);
+                               }
+                               matroxfb_DAC_unlock_irqrestore(flags);
+                       }
+                       {
+                               u_int8_t misc;
+               
+                               misc = mga_inb(M_MISC_REG_READ) & ~0x0C;
+                               switch (pll) {
+                                       case M_PIXEL_PLL_A:
+                                               break;
+                                       case M_PIXEL_PLL_B:
+                                               misc |=  0x04;
+                                               break;
+                                       default:
+                                               misc |=  0x0C;
+                                               break;
+                               }
+                               mga_outb(M_MISC_REG, misc);
+                       }
+                       pi = &ACCESS_FBINFO(limits.pixel);
+                       ci = &ACCESS_FBINFO(cache.pixel);
+                       break;
+               case M_SYSTEM_PLL:
+                       {
+                               u_int32_t opt;
+
+                               pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &opt);
+                               if (!(opt & 0x20)) {
+                                       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, opt | 0x20);
+                               }
+                       }
+                       pi = &ACCESS_FBINFO(limits.system);
+                       ci = &ACCESS_FBINFO(cache.system);
+                       break;
+               case M_VIDEO_PLL:
+                       {
+                               u_int8_t tmp;
+                               unsigned int mnp;
+                               unsigned long flags;
+                               
+                               matroxfb_DAC_lock_irqsave(flags);
+                               tmp = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL);
+                               if (!(tmp & 2)) {
+                                       matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, tmp | 2);
+                               }
+                               
+                               mnp = matroxfb_DAC_in(PMINFO M1064_XPIXPLLCM) << 16;
+                               mnp |= matroxfb_DAC_in(PMINFO M1064_XPIXPLLCN) << 8;
+                               pixel_vco = g450_mnp2vco(PMINFO mnp);
+                               matroxfb_DAC_unlock_irqrestore(flags);
+                       }
+                       pi = &ACCESS_FBINFO(limits.video);
+                       ci = &ACCESS_FBINFO(cache.video);
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       mnpcount = 0;
+       {
+               unsigned int mnp;
+               unsigned int xvco;
+
+               for(mnp = g450_firstpll(PMINFO pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(PMINFO pi, &xvco, mnp)) {
+                       unsigned int idx;
+                       unsigned int vco;
+                       unsigned int delta;
+
+                       if ((mnp & 0xFF00) < 0x0300 || (mnp & 0xFF00) > 0x7A00) {
+                               continue;
+                       }
+                       vco = g450_mnp2vco(PMINFO mnp);
+                       if (pll == M_VIDEO_PLL) {
+                               unsigned int big, small;
+
+                               if (vco < pixel_vco) {
+                                       small = vco;
+                                       big = pixel_vco;
+                               } else {
+                                       small = pixel_vco;
+                                       big = vco;
+                               }
+                               while (big > small) {
+                                       big >>= 1;
+                               }
+                               if (big == small) {
+                                       continue;
+                               }
+                       }
+                       delta = pll_freq_delta(fout, g450_vco2f(mnp, vco));
+                       for (idx = mnpcount; idx > 0; idx--) {
+                               /* == is important; due to nextpll algorithm we get
+                                  sorted equally good frequencies from lower VCO 
+                                  frequency to higher - with <= lowest wins, while
+                                  with < highest one wins */
+                               if (delta <= deltaarray[idx-1]) {
+                                       mnparray[idx] = mnparray[idx-1];
+                                       deltaarray[idx] = deltaarray[idx-1];
+                               } else {
+                                       break;
+                               }
+                       }
+                       mnparray[idx] = mnp;
+                       deltaarray[idx] = delta;
+                       mnpcount++;
+               }
+       }
+       /* VideoPLL and PixelPLL matched: do nothing... In all other cases we should get at least one frequency */
+       if (!mnpcount) {
+               return 1;
+       }
+       {
+               unsigned long flags;
+               unsigned int mnp;
+               
+               matroxfb_DAC_lock_irqsave(flags);
+               mnp = g450_checkcache(PMINFO ci, mnparray[0]);
+               if (mnp != NO_MORE_MNP) {
+                       g450_setpll_cond(PMINFO mnp, pll);
+               } else {
+                       mnp = g450_findworkingpll(PMINFO pll, mnparray, mnpcount);
+                       g450_addcache(ci, mnparray[0], mnp);
+               }
+               updatehwstate_clk(&ACCESS_FBINFO(hw), mnp, pll);
+               matroxfb_DAC_unlock_irqrestore(flags);
+       }
+       return 0;
+}
+
+/* It must be greater than number of possible PLL values.
+ * Currently there is 5(p) * 10(m) = 50 possible values. */
+#define MNP_TABLE_SIZE  64
+
+int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll) {
+       unsigned int* arr;
+       
+       arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL);
+       if (arr) {
+               int r;
+
+               r = __g450_setclk(PMINFO fout, pll, arr, arr + MNP_TABLE_SIZE);
+               kfree(arr);
+               return r;
+       }
+       return -ENOMEM;
+}
+
+EXPORT_SYMBOL(matroxfb_g450_setclk);
+
+MODULE_AUTHOR("(c) 2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Matrox G450/G550 PLL driver");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/g450_pll.h b/drivers/video/matrox/g450_pll.h
new file mode 100644 (file)
index 0000000..58a80ef
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __G450_PLL_H__
+#define __G450_PLL_H__
+
+#include "matroxfb_base.h"
+
+int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll);
+
+#endif /* __G450_PLL_H__ */
index b0a12c07e1eb0dbca825ceede0836bf7b91f3f01..ad5dfb1a10740e7f4bef5a02800d756ec795956b 100644 (file)
@@ -4,7 +4,9 @@
  *
  * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.54 2001/09/09
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.62 2001/11/29
  *
  * See matroxfb_base.c for contributors.
  *
@@ -16,6 +18,7 @@
 #include "matroxfb_DAC1064.h"
 #include "matroxfb_misc.h"
 #include "matroxfb_accel.h"
+#include "g450_pll.h"
 #include <linux/matroxfb.h>
 
 #ifdef NEED_DAC1064
@@ -217,19 +220,20 @@ static const unsigned char MGA1064_DAC[] = {
                0x00,
                0x00, 0x00, 0xFF, 0xFF};
 
-static void DAC1064_setpclk(CPMINFO struct matrox_hw_state* hw, unsigned long fout) {
+static void DAC1064_setpclk(WPMINFO unsigned long fout) {
        unsigned int m, n, p;
 
        DBG("DAC1064_setpclk")
 
        DAC1064_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
-       hw->DACclk[0] = m;
-       hw->DACclk[1] = n;
-       hw->DACclk[2] = p;
+       ACCESS_FBINFO(hw).DACclk[0] = m;
+       ACCESS_FBINFO(hw).DACclk[1] = n;
+       ACCESS_FBINFO(hw).DACclk[2] = p;
 }
 
-static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem){
+static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) {
        u_int32_t mx;
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 
        DBG("DAC1064_setmclk")
 
@@ -289,7 +293,9 @@ static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, uns
        hw->MXoptionReg = mx;
 }
 
-void DAC1064_global_init(CPMINFO struct matrox_hw_state* hw) {
+void DAC1064_global_init(WPMINFO2) {
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
        hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK;
        hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
        hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
@@ -314,7 +320,9 @@ void DAC1064_global_init(CPMINFO struct matrox_hw_state* hw) {
                hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
 }
 
-void DAC1064_global_restore(CPMINFO const struct matrox_hw_state* hw) {
+void DAC1064_global_restore(WPMINFO2) {
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
        outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
        outDAC1064(PMINFO M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]);
        if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) {
@@ -328,7 +336,9 @@ void DAC1064_global_restore(CPMINFO const struct matrox_hw_state* hw) {
        }
 }
 
-static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display *p) {
+static int DAC1064_init_1(WPMINFO struct my_timming* m, struct display *p) {
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
        DBG("DAC1064_init_1")
 
        memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
@@ -359,7 +369,7 @@ static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming*
                }
        }
 
-       DAC1064_global_init(PMINFO hw);
+       DAC1064_global_init(PMINFO2);
        hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl);
        hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
        hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
@@ -368,7 +378,8 @@ static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming*
        return 0;
 }
 
-static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
+static int DAC1064_init_2(WPMINFO struct my_timming* m, struct display* p) {
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 
        DBG("DAC1064_init_2")
 
@@ -409,21 +420,22 @@ static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming*
        return 0;
 }
 
-static void DAC1064_restore_1(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw) {
+static void DAC1064_restore_1(WPMINFO2) {
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
        CRITFLAGS
 
        DBG("DAC1064_restore_1")
 
        CRITBEGIN
 
-       outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]);
-       outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]);
-       outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]);
-       /*
-        * We must ALWAYS reprogram hardware due to broken XF4 matrox drivers...
-        *
-        * if (!oldhw || memcmp(hw->DACreg, oldhw->DACreg, sizeof(MGA1064_DAC_regs))) 
-        */
+       if ((inDAC1064(PMINFO DAC1064_XSYSPLLM) != hw->DACclk[3]) ||
+           (inDAC1064(PMINFO DAC1064_XSYSPLLN) != hw->DACclk[4]) ||
+           (inDAC1064(PMINFO DAC1064_XSYSPLLP) != hw->DACclk[5])) {
+               outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]);
+               outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]);
+               outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]);
+       }
        {
                unsigned int i;
 
@@ -433,12 +445,12 @@ static void DAC1064_restore_1(WPMINFO const struct matrox_hw_state* hw, const st
                }
        }
 
-       DAC1064_global_restore(PMINFO hw);
+       DAC1064_global_restore(PMINFO2);
 
        CRITEND
 };
 
-static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) {
+static void DAC1064_restore_2(WPMINFO struct display* p) {
 #ifdef DEBUG
        unsigned int i;
 #endif
@@ -449,48 +461,51 @@ static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const st
 #ifdef DEBUG
        dprintk(KERN_DEBUG "DAC1064regs ");
        for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
-               dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], hw->DACreg[i]);
+               dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]);
                if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... ");
        }
        dprintk("\n" KERN_DEBUG "DAC1064clk ");
        for (i = 0; i < 6; i++)
-               dprintk("C%02X=%02X ", i, hw->DACclk[i]);
+               dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]);
        dprintk("\n");
 #endif
 }
 
-static int m1064_compute(void* outdev, struct my_timming* m, struct matrox_hw_state* hw) {
-#define minfo ((struct matrox_fb_info*)outdev)
-       DAC1064_setpclk(PMINFO hw, m->pixclock);
-#undef minfo
-       return 0;
-}
-
-static int m1064_program(void* outdev, const struct matrox_hw_state* hw) {
+static int m1064_compute(void* outdev, struct my_timming* m) {
 #define minfo ((struct matrox_fb_info*)outdev)
-       int i;
-       int tmout;
-       CRITFLAGS
+       if (ACCESS_FBINFO(devflags.g450dac)) {
+               matroxfb_g450_setclk(PMINFO m->pixclock, M_PIXEL_PLL_C);
+       } else {
+               int i;
+               int tmout;
+               CRITFLAGS
 
-       CRITBEGIN
+               DAC1064_setpclk(PMINFO m->pixclock);
 
-       for (i = 0; i < 3; i++)
-               outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]);
-       for (tmout = 500000; tmout; tmout--) {
-               if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
-                       break;
-               udelay(10);
-       };
+               CRITBEGIN
 
-       CRITEND
+               for (i = 0; i < 3; i++)
+                       outDAC1064(PMINFO M1064_XPIXPLLCM + i, ACCESS_FBINFO(hw).DACclk[i]);
+               for (tmout = 500000; tmout; tmout--) {
+                       if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
+                               break;
+                       udelay(10);
+               };
 
-       if (!tmout)
-               printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+               CRITEND
 
+               if (!tmout)
+                       printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+       }
 #undef minfo
        return 0;
 }
 
+static int m1064_program(void* outdev) {
+       /* nothing, hardware is set in m1064_compute */
+       return 0;
+}
+
 static int m1064_start(void* outdev) {
        /* nothing */
        return 0;
@@ -522,12 +537,13 @@ static struct matrox_altout m1064 = {
 #endif /* NEED_DAC1064 */
 
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
-static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
+static int MGA1064_init(WPMINFO struct my_timming* m, struct display* p) {
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 
        DBG("MGA1064_init")
 
-       if (DAC1064_init_1(PMINFO hw, m, p)) return 1;
-       if (matroxfb_vgaHWinit(PMINFO hw, m, p)) return 1;
+       if (DAC1064_init_1(PMINFO m, p)) return 1;
+       if (matroxfb_vgaHWinit(PMINFO m, p)) return 1;
 
        hw->MiscOutReg = 0xCB;
        if (m->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -537,19 +553,20 @@ static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m
        if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
                hw->CRTCEXT[3] |= 0x40;
 
-       if (DAC1064_init_2(PMINFO hw, m, p)) return 1;
+       if (DAC1064_init_2(PMINFO m, p)) return 1;
        return 0;
 }
 #endif
 
 #ifdef CONFIG_FB_MATROX_G100
-static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
+static int MGAG100_init(WPMINFO struct my_timming* m, struct display* p) {
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 
        DBG("MGAG100_init")
 
-       if (DAC1064_init_1(PMINFO hw, m, p)) return 1;
+       if (DAC1064_init_1(PMINFO m, p)) return 1;
        hw->MXoptionReg &= ~0x2000;
-       if (matroxfb_vgaHWinit(PMINFO hw, m, p)) return 1;
+       if (matroxfb_vgaHWinit(PMINFO m, p)) return 1;
 
        hw->MiscOutReg = 0xEF;
        if (m->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -559,13 +576,13 @@ static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m
        if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
                hw->CRTCEXT[3] |= 0x40;
 
-       if (DAC1064_init_2(PMINFO hw, m, p)) return 1;
+       if (DAC1064_init_2(PMINFO m, p)) return 1;
        return 0;
 }
 #endif /* G100 */
 
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
-static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw){
+static void MGA1064_ramdac_init(WPMINFO2) {
 
        DBG("MGA1064_ramdac_init");
 
@@ -579,7 +596,7 @@ static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw){
        ACCESS_FBINFO(features.pll.post_shift_max) = 3;
        ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_EXTERNAL;
        /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
-       DAC1064_setmclk(PMINFO hw, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
+       DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
 }
 #endif
 
@@ -591,7 +608,7 @@ static int x7AF4 = 0x10;    /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
 static int def50 = 0;  /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
 #endif
 
-static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p){
+static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) {
        int reg;
        int selClk;
        int clk;
@@ -635,7 +652,7 @@ static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p){
        outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
 }
 
-static void MGAG100_setPixClock(CPMINFO int flags, int freq){
+static void MGAG100_setPixClock(CPMINFO int flags, int freq) {
        unsigned int m, n, p;
 
        DBG("MGAG100_setPixClock")
@@ -646,10 +663,12 @@ static void MGAG100_setPixClock(CPMINFO int flags, int freq){
 #endif
 
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
-static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw){
+static int MGA1064_preinit(WPMINFO2) {
        static const int vxres_mystique[] = { 512,        640, 768,  800,  832,  960,
                                             1024, 1152, 1280,      1600, 1664, 1920,
                                             2048,    0};
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
        DBG("MGA1064_preinit")
 
        /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
@@ -680,7 +699,7 @@ static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw){
        return 0;
 }
 
-static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw){
+static void MGA1064_reset(WPMINFO2) {
 
        DBG("MGA1064_reset");
 
@@ -688,15 +707,130 @@ static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw){
        if (ACCESS_FBINFO(devflags.hwcursor))
                ACCESS_FBINFO(video.len_usable) -= 1024;
        matroxfb_fastfont_init(MINFO);
-       MGA1064_ramdac_init(PMINFO hw);
+       MGA1064_ramdac_init(PMINFO2);
 }
 #endif
 
 #ifdef CONFIG_FB_MATROX_G100
-static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){
+static void g450_mclk_init(WPMINFO2) {
+       /* switch all clocks to PCI source */
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4);
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3 & ~0x00300C03);
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
+       
+       if (((ACCESS_FBINFO(values).reg.opt3 & 0x000003) == 0x000003) ||
+           ((ACCESS_FBINFO(values).reg.opt3 & 0x000C00) == 0x000C00) ||
+           ((ACCESS_FBINFO(values).reg.opt3 & 0x300000) == 0x300000)) {
+               matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.video), M_VIDEO_PLL);
+       } else {
+               /* slow down video clocks... */
+               matroxfb_g450_setclk(PMINFO 0, M_VIDEO_PLL);
+       }
+       matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.system), M_SYSTEM_PLL);
+       
+       /* switch clocks to their real PLL source(s) */
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4);
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3);
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
+
+}
+
+static void g450_memory_init(WPMINFO2) {
+       /* disable memory refresh */
+       ACCESS_FBINFO(hw).MXoptionReg &= ~0x001F8000;
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
+       
+       /* set memory interface parameters */
+       ACCESS_FBINFO(hw).MXoptionReg &= ~0x00207E00;
+       ACCESS_FBINFO(hw).MXoptionReg |= 0x00207E00 & ACCESS_FBINFO(values).reg.opt;
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ACCESS_FBINFO(values).reg.opt2);
+       
+       mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
+       
+       /* first set up memory interface with disabled memory interface clocks */
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc & ~0x80000000U);
+       mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
+       mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess);
+       /* start memory clocks */
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc | 0x80000000U);
+
+       udelay(200);
+       
+       if (ACCESS_FBINFO(values).memory.ddr && (!ACCESS_FBINFO(values).memory.emrswen || !ACCESS_FBINFO(values).memory.dll)) {
+               mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk & ~0x1000);
+       }
+       mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess | 0x8000);
+       
+       udelay(200);
+       
+       ACCESS_FBINFO(hw).MXoptionReg |= 0x001F8000 & ACCESS_FBINFO(values).reg.opt;
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
+       
+       /* value is written to memory chips only if old != new */
+       mga_outl(M_PLNWT, 0);
+       mga_outl(M_PLNWT, ~0);
+       
+       if (ACCESS_FBINFO(values).reg.mctlwtst != ACCESS_FBINFO(values).reg.mctlwtst_core) {
+               mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst_core);
+       }
+       
+}
+
+static void g450_preinit(WPMINFO2) {
+       u_int32_t c2ctl;
+       u_int8_t curctl;
+       u_int8_t c1ctl;
+       
+       /* ACCESS_FBINFO(hw).MXoptionReg = minfo->values.reg.opt; */
+       ACCESS_FBINFO(hw).MXoptionReg &= 0xC0000100;
+       ACCESS_FBINFO(hw).MXoptionReg |= 0x00000020;
+       if (ACCESS_FBINFO(devflags.novga))
+               ACCESS_FBINFO(hw).MXoptionReg &= ~0x00000100;
+       if (ACCESS_FBINFO(devflags.nobios))
+               ACCESS_FBINFO(hw).MXoptionReg &= ~0x40000000;
+       if (ACCESS_FBINFO(devflags.nopciretry))
+               ACCESS_FBINFO(hw).MXoptionReg |=  0x20000000;
+       ACCESS_FBINFO(hw).MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x03400040;
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
+
+       /* Init system clocks */
+               
+       /* stop crtc2 */
+       c2ctl = mga_inl(M_C2CTL);
+       mga_outl(M_C2CTL, c2ctl & ~1);
+       /* stop cursor */
+       curctl = inDAC1064(PMINFO M1064_XCURCTRL);
+       outDAC1064(PMINFO M1064_XCURCTRL, 0);
+       /* stop crtc1 */
+       c1ctl = mga_readr(M_SEQ_INDEX, 1);
+       mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20);
+
+       g450_mclk_init(PMINFO2);
+       g450_memory_init(PMINFO2);
+       
+       /* set legacy VGA clock sources for DOSEmu or VMware... */
+       matroxfb_g450_setclk(PMINFO 25175, M_PIXEL_PLL_A);
+       matroxfb_g450_setclk(PMINFO 28322, M_PIXEL_PLL_B);
+
+       /* restore crtc1 */
+       mga_setr(M_SEQ_INDEX, 1, c1ctl);
+       
+       /* restore cursor */
+       outDAC1064(PMINFO M1064_XCURCTRL, curctl);
+
+       /* restore crtc2 */
+       mga_outl(M_C2CTL, c2ctl);
+       
+       return;
+}
+
+static int MGAG100_preinit(WPMINFO2) {
        static const int vxres_g100[] = {  512,        640, 768,  800,  832,  960,
                                           1024, 1152, 1280,      1600, 1664, 1920,
                                           2048, 0};
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
         u_int32_t reg50;
 #if 0
        u_int32_t q;
@@ -710,7 +844,9 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){
        } else {
                ACCESS_FBINFO(features.pll.vco_freq_min) = 62000;
        }
-       ACCESS_FBINFO(features.pll.ref_freq)     = 27000;
+       if (!ACCESS_FBINFO(features.pll.ref_freq)) {
+               ACCESS_FBINFO(features.pll.ref_freq)     = 27000;
+       }
        ACCESS_FBINFO(features.pll.feed_div_min) = 7;
        ACCESS_FBINFO(features.pll.feed_div_max) = 127;
        ACCESS_FBINFO(features.pll.in_div_min)   = 1;
@@ -734,6 +870,10 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){
        }
        if (ACCESS_FBINFO(devflags.noinit))
                return 0;
+       if (ACCESS_FBINFO(devflags.g450dac)) {
+               g450_preinit(PMINFO2);
+               return 0;
+       }
        hw->MXoptionReg &= 0xC0000100;
        hw->MXoptionReg |= 0x00000020;
        if (ACCESS_FBINFO(devflags.novga))
@@ -743,12 +883,12 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){
        if (ACCESS_FBINFO(devflags.nopciretry))
                hw->MXoptionReg |=  0x20000000;
        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
-       DAC1064_setmclk(PMINFO hw, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
+       DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
 
        if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) {
-               pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, &reg50);
+               pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
                reg50 &= ~0x3000;
-               pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
+               pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
 
                hw->MXoptionReg |= 0x1080;
                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
@@ -763,7 +903,7 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){
                udelay(100);
                reg50 &= ~0xFF;
                reg50 |=  0x07;
-               pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
+               pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
                /* it should help with G100 */
                mga_outb(M_GRAPHICS_INDEX, 6);
                mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
@@ -778,29 +918,30 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){
                }
 #endif
                hw->MXoptionReg |= 0x00078020;
-       } else  if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) {
-               pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, &reg50);
+       } else if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) {
+               pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
                reg50 &= ~0x3000;
-               pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
+               pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
 
                if (ACCESS_FBINFO(devflags.memtype) == -1)
-                       ACCESS_FBINFO(devflags.memtype) = 3;
-               hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10;
+                       hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00;
+               else
+                       hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10;
                if (ACCESS_FBINFO(devflags.sgram))
                        hw->MXoptionReg |= 0x4000;
-               mga_outl(M_CTLWTST, 0x042450A1);
-               mga_outl(M_MEMRDBK, 0x00000108);
+               mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
+               mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
                udelay(200);
                mga_outl(M_MACCESS, 0x00000000);
                mga_outl(M_MACCESS, 0x00008000);
                udelay(100);
-               mga_outw(M_MEMRDBK, 0x00000108);
+               mga_outw(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
                hw->MXoptionReg |= 0x00078020;
        } else {
-               pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, &reg50);
+               pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
                reg50 &= ~0x00000100;
                reg50 |=  0x00000000;
-               pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
+               pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
 
                if (ACCESS_FBINFO(devflags.memtype) == -1)
                        ACCESS_FBINFO(devflags.memtype) = 0;
@@ -820,8 +961,9 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){
        return 0;
 }
 
-static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw){
+static void MGAG100_reset(WPMINFO2) {
        u_int8_t b;
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 
        DBG("MGAG100_reset")
 
@@ -845,13 +987,20 @@ static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw){
 #endif
                if (!ACCESS_FBINFO(devflags.noinit)) {
                        if (x7AF4 & 8) {
-                               hw->MXoptionReg |= 0x40;
+                               hw->MXoptionReg |= 0x40;        /* FIXME... */
                                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
                        }
                        mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
                }
        }
-       DAC1064_setmclk(PMINFO hw, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
+       if (ACCESS_FBINFO(devflags.g450dac)) {
+               /* either leave MCLK as is... or they were set in preinit */
+               hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM);
+               hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN);
+               hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP);
+       } else {
+               DAC1064_setmclk(PMINFO DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
+       }
        if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) {
                if (ACCESS_FBINFO(devflags.dfp_type) == -1) {
                        ACCESS_FBINFO(devflags.dfp_type) = inDAC1064(PMINFO 0x1F);
@@ -859,20 +1008,25 @@ static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw){
        }
        if (ACCESS_FBINFO(devflags.noinit))
                return;
-       MGAG100_setPixClock(PMINFO 4, 25175);
-       MGAG100_setPixClock(PMINFO 5, 28322);
-       if (x7AF4 & 0x10) {
-               b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1;
-               outDAC1064(PMINFO M1064_XGENIODATA, b);
-               b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1;
-               outDAC1064(PMINFO M1064_XGENIOCTRL, b);
+       if (ACCESS_FBINFO(devflags.g450dac)) {
+       } else {
+               MGAG100_setPixClock(PMINFO 4, 25175);
+               MGAG100_setPixClock(PMINFO 5, 28322);
+               if (x7AF4 & 0x10) {
+                       b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1;
+                       outDAC1064(PMINFO M1064_XGENIODATA, b);
+                       b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1;
+                       outDAC1064(PMINFO M1064_XGENIOCTRL, b);
+               }
        }
 }
 #endif
 
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
-static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
+static void MGA1064_restore(WPMINFO struct display* p) {
        int i;
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
        CRITFLAGS
 
        DBG("MGA1064_restore")
@@ -885,17 +1039,19 @@ static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw
 
        CRITEND
 
-       DAC1064_restore_1(PMINFO hw, oldhw);
-       matroxfb_vgaHWrestore(PMINFO hw, oldhw);
+       DAC1064_restore_1(PMINFO2);
+       matroxfb_vgaHWrestore(PMINFO2);
        for (i = 0; i < 6; i++)
                mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
-       DAC1064_restore_2(PMINFO hw, oldhw, p);
+       DAC1064_restore_2(PMINFO p);
 }
 #endif
 
 #ifdef CONFIG_FB_MATROX_G100
-static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
+static void MGAG100_restore(WPMINFO struct display* p) {
        int i;
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+
        CRITFLAGS
 
        DBG("MGAG100_restore")
@@ -905,15 +1061,15 @@ static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw
        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
        CRITEND
 
-       DAC1064_restore_1(PMINFO hw, oldhw);
-       matroxfb_vgaHWrestore(PMINFO hw, oldhw);
+       DAC1064_restore_1(PMINFO2);
+       matroxfb_vgaHWrestore(PMINFO2);
 #ifdef CONFIG_FB_MATROX_32MB
        if (ACCESS_FBINFO(devflags.support32MB))
                mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
 #endif
        for (i = 0; i < 6; i++)
                mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
-       DAC1064_restore_2(PMINFO hw, oldhw, p);
+       DAC1064_restore_2(PMINFO p);
 }
 #endif
 
index 62cde7919e9d0d9f9c330ab06f61f4a87358d507..6136fd33a14b5ac416220bb54cb6e8e582def818 100644 (file)
@@ -13,8 +13,8 @@ extern struct matrox_switch matrox_mystique;
 extern struct matrox_switch matrox_G100;
 #endif
 #ifdef NEED_DAC1064
-void DAC1064_global_init(CPMINFO struct matrox_hw_state*);
-void DAC1064_global_restore(CPMINFO const struct matrox_hw_state*);
+void DAC1064_global_init(WPMINFO2);
+void DAC1064_global_restore(WPMINFO2);
 #endif
 
 #define M1064_INDEX    0x00
@@ -139,10 +139,10 @@ void DAC1064_global_restore(CPMINFO const struct matrox_hw_state*);
 
 #define M1064_XOUTPUTCONN      0x8A
 #define M1064_XSYNCCTRL                0x8B
-#define M1064_XPIXPLL2STAT     0x8C
-#define M1064_XPIXPLL2P                0x8D
-#define M1064_XPIXPLL2N                0x8E
-#define M1064_XPIXPLL2M                0x8F
+#define M1064_XVIDPLLSTAT      0x8C
+#define M1064_XVIDPLLP         0x8D
+#define M1064_XVIDPLLM         0x8E
+#define M1064_XVIDPLLN         0x8F
 
 #define M1064_XPWRCTRL         0xA0
 
index 16f1e7653a8254b95d024782cd4f1d89650e387b..57b37600a3cb5d5c4a50d36a131805ffbeec3c3a 100644 (file)
@@ -4,7 +4,9 @@
  *
  * (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.50 2000/08/10
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.62 2000/11/29
  *
  * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
  *
@@ -357,7 +359,7 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) {
                        del_timer_sync(&ACCESS_FBINFO(cursor.timer));
                        matroxfb_DAC_lock_irqsave(flags);
                        ACCESS_FBINFO(cursor.state) = CM_ERASE;
-                       outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]));
+                       outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(hw.DACreg[POS3026_XCURCTRL]));
                        matroxfb_DAC_unlock_irqrestore(flags);
                }
                return;
@@ -377,7 +379,7 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) {
                ACCESS_FBINFO(cursor.y) = y;
                x += 64;
                y += 64;
-               outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]));
+               outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(hw.DACreg[POS3026_XCURCTRL]));
                mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSXL, x);
                mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSXH, x >> 8);
                mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSYL, y);
@@ -386,7 +388,7 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) {
        ACCESS_FBINFO(cursor.state) = CM_DRAW;
        if (ACCESS_FBINFO(devflags.blink))
                mod_timer(&ACCESS_FBINFO(cursor.timer), jiffies + HZ/2);
-       outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]) | TVP3026_XCURCTRL_XGA);
+       outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(hw.DACreg[POS3026_XCURCTRL]) | TVP3026_XCURCTRL_XGA);
        matroxfb_DAC_unlock_irqrestore(flags);
 }
 
@@ -418,9 +420,10 @@ static int Ti3026_calcclock(CPMINFO unsigned int freq, unsigned int fmax, int* i
        return fvco;
 }
 
-static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, struct display* p) {
+static int Ti3026_setpclk(WPMINFO int clk, struct display* p) {
        unsigned int f_pll;
        unsigned int pixfeed, pixin, pixpost;
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 
        DBG("Ti3026_setpclk")
 
@@ -491,8 +494,9 @@ static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, struct di
        return 0;
 }
 
-static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
+static int Ti3026_init(WPMINFO struct my_timming* m, struct display* p) {
        u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 
        DBG("Ti3026_init")
 
@@ -538,7 +542,7 @@ static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m,
                        return 1;       /* TODO: failed */
                }
        }
-       if (matroxfb_vgaHWinit(PMINFO hw, m, p)) return 1;
+       if (matroxfb_vgaHWinit(PMINFO m, p)) return 1;
 
        /* set SYNC */
        hw->MiscOutReg = 0xCB;
@@ -567,11 +571,11 @@ static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m,
        if ((p->type != FB_TYPE_TEXT) && isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000;
 
        /* set DAC */
-       Ti3026_setpclk(PMINFO hw, m->pixclock, p);
+       Ti3026_setpclk(PMINFO m->pixclock, p);
        return 0;
 }
 
-static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout){
+static void ti3026_setMCLK(WPMINFO int fout){
        unsigned int f_pll;
        unsigned int pclk_m, pclk_n, pclk_p;
        unsigned int mclk_m, mclk_n, mclk_p;
@@ -643,8 +647,8 @@ static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout){
                if (rfhcnt > 15)
                        rfhcnt = 0;
        }
-       hw->MXoptionReg = (hw->MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
-       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+       ACCESS_FBINFO(hw).MXoptionReg = (ACCESS_FBINFO(hw).MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
+       pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
 
        /* output MCLK to MCLK pin */
        outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
@@ -670,7 +674,7 @@ static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout){
                printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
 }
 
-static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw){
+static void ti3026_ramdac_init(WPMINFO2) {
 
        DBG("ti3026_ramdac_init")
 
@@ -683,11 +687,13 @@ static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw){
        ACCESS_FBINFO(features.pll.post_shift_max) = 3;
        if (ACCESS_FBINFO(devflags.noinit))
                return;
-       ti3026_setMCLK(PMINFO hw, 60000);
+       ti3026_setMCLK(PMINFO 60000);
 }
 
-static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
+static void Ti3026_restore(WPMINFO struct display* p) {
        int i;
+       unsigned char progdac[6];
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
        CRITFLAGS
 
        DBG("Ti3026_restore")
@@ -705,7 +711,7 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
 
        CRITEND
 
-       matroxfb_vgaHWrestore(PMINFO hw, oldhw);
+       matroxfb_vgaHWrestore(PMINFO2);
 
        CRITBEGIN
 
@@ -715,19 +721,19 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
        for (i = 0; i < 21; i++) {
                outTi3026(PMINFO DACseq[i], hw->DACreg[i]);
        }
-       if (oldhw) {
-               outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
-               oldhw->DACclk[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
-               oldhw->DACclk[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
-               outTi3026(PMINFO TVP3026_XPLLADDR, 0x15);
-               oldhw->DACclk[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
-               oldhw->DACclk[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
-               outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
-               oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
-               oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
-       }
+
+       outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
+       progdac[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+       progdac[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+       outTi3026(PMINFO TVP3026_XPLLADDR, 0x15);
+       progdac[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+       progdac[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+       outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
+       progdac[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+       progdac[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+
        CRITEND
-       if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) {
+       if (memcmp(hw->DACclk, progdac, 6)) {
                /* agrhh... setting up PLL is very slow on Millennium... */
                /* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */
                /* Maybe even we should call schedule() ? */
@@ -796,22 +802,23 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
 #endif
 }
 
-static void Ti3026_reset(WPMINFO struct matrox_hw_state* hw){
+static void Ti3026_reset(WPMINFO2) {
 
        DBG("Ti3026_reset")
 
        matroxfb_fastfont_init(MINFO);
 
-       ti3026_ramdac_init(PMINFO hw);
+       ti3026_ramdac_init(PMINFO2);
 }
 
-static int Ti3026_preinit(WPMINFO struct matrox_hw_state* hw){
+static int Ti3026_preinit(WPMINFO2) {
        static const int vxres_mill2[] = { 512,        640, 768,  800,  832,  960,
                                          1024, 1152, 1280,      1600, 1664, 1920,
                                          2048, 0};
        static const int vxres_mill1[] = {             640, 768,  800,        960,
                                          1024, 1152, 1280,      1600,       1920,
                                          2048, 0};
+       struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 
        DBG("Ti3026_preinit")
 
index 0902bee80076efbcc947228b7f5f0c140f0b2cfc..07d881b1c5fa98f015263d1d24fb6ab7f2e041e6 100644 (file)
@@ -4,7 +4,9 @@
  *
  * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.54 2001/09/09
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.62 2001/11/29
  *
  * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
  *
@@ -161,11 +163,11 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
                pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
                pos += ACCESS_FBINFO(curr.ydstorg.chunks);
        }
-       p0 = ACCESS_FBINFO(currenthw)->CRTC[0x0D] = pos & 0xFF;
-       p1 = ACCESS_FBINFO(currenthw)->CRTC[0x0C] = (pos & 0xFF00) >> 8;
-       p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
+       p0 = ACCESS_FBINFO(hw).CRTC[0x0D] = pos & 0xFF;
+       p1 = ACCESS_FBINFO(hw).CRTC[0x0C] = (pos & 0xFF00) >> 8;
+       p2 = ACCESS_FBINFO(hw).CRTCEXT[0] = (ACCESS_FBINFO(hw).CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
 #ifdef CONFIG_FB_MATROX_32MB
-       p3 = ACCESS_FBINFO(currenthw)->CRTCEXT[8] = pos >> 21;
+       p3 = ACCESS_FBINFO(hw).CRTCEXT[8] = pos >> 21;
 #endif
 
        CRITBEGIN
@@ -814,7 +816,6 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
 
                {       struct my_timming mt;
                        struct matrox_hw_state* hw;
-                       struct matrox_hw_state* ohw;
 
                        matroxfb_var2my(var, &mt);
                        /* CRTC1 delays */
@@ -826,16 +827,12 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
                                default:        mt.delay = 31 + 8; break;
                        }
 
-                       hw = ACCESS_FBINFO(newhw);
-                       ohw = ACCESS_FBINFO(currenthw);
-
-                       /* copy last setting... */
-                       memcpy(hw, ohw, sizeof(*hw));
+                       hw = &ACCESS_FBINFO(hw);
 
                        del_timer_sync(&ACCESS_FBINFO(cursor.timer));
                        ACCESS_FBINFO(cursor.state) = CM_ERASE;
 
-                       ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt, display));
+                       ACCESS_FBINFO(hw_switch->init(PMINFO &mt, display));
                        if (display->type == FB_TYPE_TEXT) {
                                if (fontheight(display))
                                        pos = var->yoffset / fontheight(display) * display->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(display)?fontwidth(display):8);
@@ -852,28 +849,26 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
                        hw->CRTCEXT[8] = pos >> 21;
                        if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) {
                                if (ACCESS_FBINFO(primout))
-                                       ACCESS_FBINFO(primout)->compute(MINFO, &mt, hw);
+                                       ACCESS_FBINFO(primout)->compute(MINFO, &mt);
                        }
                        if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) {
                                down_read(&ACCESS_FBINFO(altout.lock));
                                if (ACCESS_FBINFO(altout.output))
-                                       ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt, hw);
+                                       ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt);
                                up_read(&ACCESS_FBINFO(altout.lock));
                        }
-                       ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display));
+                       ACCESS_FBINFO(hw_switch->restore(PMINFO display));
                        if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) {
                                if (ACCESS_FBINFO(primout))
-                                       ACCESS_FBINFO(primout)->program(MINFO, hw);
+                                       ACCESS_FBINFO(primout)->program(MINFO);
                        }
                        if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) {
                                down_read(&ACCESS_FBINFO(altout.lock));
                                if (ACCESS_FBINFO(altout.output))
-                                       ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device), hw);
+                                       ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device));
                                up_read(&ACCESS_FBINFO(altout.lock));
                        }
                        ACCESS_FBINFO(cursor.redraw) = 1;
-                       ACCESS_FBINFO(currenthw) = hw;
-                       ACCESS_FBINFO(newhw) = ohw;
                        if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) {
                                if (ACCESS_FBINFO(primout))
                                        ACCESS_FBINFO(primout)->start(MINFO);
@@ -1004,7 +999,7 @@ static int matroxfb_get_vblank(CPMINFO struct fb_vblank *vblank)
                vblank->flags |= FB_VBLANK_HBLANKING;
        if (sts1 & 8)
                vblank->flags |= FB_VBLANK_VSYNCING;
-       if (vblank->count >= ACCESS_FBINFO(currcon_display)->var.yres)
+       if (vblank->vcount >= ACCESS_FBINFO(currcon_display)->var.yres)
                vblank->flags |= FB_VBLANK_VBLANKING;
        vblank->hcount = 0;
        vblank->count = 0;
@@ -1416,7 +1411,7 @@ static struct video_board vbG400          = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG4
 #define DEVF_CROSS4MB          0x0010
 #define DEVF_TEXT4B            0x0020
 #define DEVF_DDC_8_2           0x0040
-#define DEVF_G550DAC           0x0080
+/* #define DEVF_recycled       0x0080  */
 #define DEVF_SUPPORT32MB       0x0100
 #define DEVF_ANY_VXRES         0x0200
 #define DEVF_TEXT16B           0x0400
@@ -1432,12 +1427,13 @@ static struct video_board vbG400                = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG4
 #define DEVF_G400      (DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2)
 /* if you'll find how to drive DFP... */
 #define DEVF_G450      (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG)
-#define DEVF_G550      (DEVF_G450 | DEVF_G550DAC | DEVF_BOTHDACS)
+#define DEVF_G550      (DEVF_G450 | DEVF_BOTHDACS)
 
 static struct board {
        unsigned short vendor, device, rev, svid, sid;
        unsigned int flags;
        unsigned int maxclk;
+       enum mga_chip chip;
        struct video_board* base;
        const char* name;
                } dev_list[] = {
@@ -1446,18 +1442,21 @@ static struct board {
                0,                      0,
                DEVF_TEXT4B,
                230000,
+               MGA_2064,
                &vbMillennium,
                "Millennium (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_MIL_2,     0xFF,
                0,                      0,
                DEVF_SWAPS,
                220000,
+               MGA_2164,
                &vbMillennium2,
                "Millennium II (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_MIL_2_AGP, 0xFF,
                0,                      0,
                DEVF_SWAPS,
                250000,
+               MGA_2164,
                &vbMillennium2A,
                "Millennium II (AGP)"},
 #endif
@@ -1466,122 +1465,107 @@ static struct board {
                0,                      0,
                DEVF_VIDEO64BIT | DEVF_CROSS4MB,
                180000,
+               MGA_1064,
                &vbMystique,
                "Mystique (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_MYS,       0xFF,
                0,                      0,
                DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
                220000,
+               MGA_1164,
                &vbMystique,
                "Mystique 220 (PCI)"},
 #endif
 #ifdef CONFIG_FB_MATROX_G100
-       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_MM,   0xFF,
-               PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MGA_G100_PCI,
-               DEVF_G100,
-               230000,
-               &vbG100,
-               "MGA-G100 (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_MM,   0xFF,
                0,                      0,
                DEVF_G100,
                230000,
+               MGA_G100,
                &vbG100,
-               "unknown G100 (PCI)"},
-       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
-               PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_GENERIC,
-               DEVF_G100,
-               230000,
-               &vbG100,
-               "MGA-G100 (AGP)"},
-       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
-               PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MGA_G100_AGP,
-               DEVF_G100,
-               230000,
-               &vbG100,
-               "MGA-G100 (AGP)"},
-       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
-               PCI_SS_VENDOR_ID_SIEMENS_NIXDORF,       PCI_SS_ID_SIEMENS_MGA_G100_AGP,
-               DEVF_G100,
-               230000,
-               &vbG100,
-               "MGA-G100 (AGP)"},
-       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
-               PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP,
-               DEVF_G100,
-               230000,
-               &vbG100,
-               "Productiva G100 (AGP)"},
+               "MGA-G100 (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
                0,                      0,
                DEVF_G100,
                230000,
+               MGA_G100,
                &vbG100,
-               "unknown G100 (AGP)"},
+               "MGA-G100 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_PCI,  0xFF,
                0,                      0,
                DEVF_G200,
                250000,
+               MGA_G200,
                &vbG200,
-               "unknown G200 (PCI)"},
+               "MGA-G200 (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_GENERIC,
                DEVF_G200,
                220000,
+               MGA_G200,
                &vbG200,
                "MGA-G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
                DEVF_G200,
                230000,
+               MGA_G200,
                &vbG200,
                "Mystique G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MILLENIUM_G200_AGP,
                DEVF_G200,
                250000,
+               MGA_G200,
                &vbG200,
                "Millennium G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MARVEL_G200_AGP,
                DEVF_G200,
                230000,
+               MGA_G200,
                &vbG200,
                "Marvel G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_SIEMENS_NIXDORF,       PCI_SS_ID_SIEMENS_MGA_G200_AGP,
                DEVF_G200,
                230000,
+               MGA_G200,
                &vbG200,
                "MGA-G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                0,                      0,
                DEVF_G200,
                230000,
+               MGA_G200,
                &vbG200,
                "G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G400,      0x80,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP,
                DEVF_G400,
                360000,
+               MGA_G400,
                &vbG400,
                "Millennium G400 MAX (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G400,      0x80,
                0,                      0,
                DEVF_G400,
                300000,
+               MGA_G400,
                &vbG400,
                "G400 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G400,      0xFF,
                0,                      0,
                DEVF_G450,
-               500000,         /* ??? vco goes up to 900MHz... */
+               360000,
+               MGA_G450,
                &vbG400,
                "G450"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G550,      0xFF,
                0,                      0,
                DEVF_G550,
-               500000,
+               360000,
+               MGA_G550,
                &vbG400,
                "G550"},
 #endif
@@ -1589,6 +1573,7 @@ static struct board {
                0,                      0,
                0,
                0,
+               0,
                NULL,
                NULL}};
 
@@ -1606,7 +1591,6 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
        unsigned long ctrlptr_phys = 0;
        unsigned long video_base_phys = 0;
        unsigned int memsize;
-       struct matrox_hw_state* hw = ACCESS_FBINFO(currenthw);
        int err;
 
        DBG("initMatrox2")
@@ -1620,6 +1604,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
 
        printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
        ACCESS_FBINFO(capable.plnwt) = 1;
+       ACCESS_FBINFO(chip) = b->chip;
        ACCESS_FBINFO(capable.srcorg) = b->flags & DEVF_SRCORG;
        ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT;
        if (b->flags & DEVF_TEXT4B) {
@@ -1657,7 +1642,6 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
        }
        ACCESS_FBINFO(devflags.dfp_type) = dfp_type;
        ACCESS_FBINFO(devflags.g450dac) = b->flags & DEVF_G450DAC;
-       ACCESS_FBINFO(devflags.g550dac) = b->flags & DEVF_G550DAC;
        ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
        ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
 
@@ -1666,9 +1650,11 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
        if (b->flags & DEVF_SWAPS) {
                ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1);
                video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0);
+               ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_0;
        } else {
                ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0);
                video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1);
+               ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_1;
        }
        err = -EINVAL;
        if (!ctrlptr_phys) {
@@ -1725,7 +1711,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
                }
                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, cmd);
                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mga_option);
-               hw->MXoptionReg = mga_option;
+               ACCESS_FBINFO(hw).MXoptionReg = mga_option;
 
                /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
                /* maybe preinit() candidate, but it is same... for all devices... at this time... */
@@ -1733,7 +1719,8 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
        }
 
        err = -ENXIO;
-       if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO hw)) {
+       matroxfb_read_pins(PMINFO2);
+       if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO2)) {
                goto failVideoIO;
        }
 
@@ -1746,13 +1733,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
 
        ACCESS_FBINFO(currcon) = -1;
        ACCESS_FBINFO(currcon_display) = d;
-       mga_iounmap(ACCESS_FBINFO(video.vbase));
        ACCESS_FBINFO(video.base) = video_base_phys;
-       if (mga_ioremap(video_base_phys, ACCESS_FBINFO(video.len), MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) {
-               printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
-                       video_base_phys, ACCESS_FBINFO(video.len));
-               goto failCtrlIO;
-       }
        ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len);
        if (ACCESS_FBINFO(video.len_usable) > b->base->maxdisplayable)
                ACCESS_FBINFO(video.len_usable) = b->base->maxdisplayable;
@@ -1766,7 +1747,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
 
        if (!ACCESS_FBINFO(devflags.novga))
                request_region(0x3C0, 32, "matrox");
-       ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
+       ACCESS_FBINFO(hw_switch->reset(PMINFO2));
 
        ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0;
        ACCESS_FBINFO(fbcon.monspecs.hfmax) = fh;
@@ -1789,7 +1770,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
 
        strcpy(ACCESS_FBINFO(fbcon.modename), "MATROX VGA");
        ACCESS_FBINFO(fbcon.changevar) = NULL;
-       ACCESS_FBINFO(fbcon.node) = -1;
+       ACCESS_FBINFO(fbcon.node) = NODEV;
        ACCESS_FBINFO(fbcon.fbops) = &matroxfb_ops;
        ACCESS_FBINFO(fbcon.disp) = d;
        ACCESS_FBINFO(fbcon.switch_con) = &matroxfb_switch;
@@ -1848,9 +1829,9 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
                                  + vesafb_defined.right_margin + vesafb_defined.hsync_len);
                        if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
                }
-               maxclk = (maxclk + 499) / 500;
-               if (maxclk) {
-                       tmp = (2000000000 + maxclk) / maxclk;
+               tmp = (maxclk + 499) / 500;
+               if (tmp) {
+                       tmp = (2000000000 + tmp) / tmp;
                        if (tmp > pixclock) pixclock = tmp;
                }
        }
@@ -2070,8 +2051,6 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
        memset(MINFO, 0, sizeof(*MINFO));
        memset(d, 0, sizeof(*d));
 
-       ACCESS_FBINFO(currenthw) = &ACCESS_FBINFO(hw1);
-       ACCESS_FBINFO(newhw) = &ACCESS_FBINFO(hw2);
        ACCESS_FBINFO(pcidev) = pdev;
        ACCESS_FBINFO(dead) = 0;
        ACCESS_FBINFO(usecount) = 0;
index d4d2df71fd3fad453086d3dcc0675f93a12fece3..be8074117fecc23dd61c7225e6e397f7779cdeff 100644 (file)
 
 #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
 
-/* G100, G200 and Mystique have (almost) same DAC */
+/* G-series and Mystique have (almost) same DAC */
 #undef NEED_DAC1064
 #if defined(CONFIG_FB_MATROX_MYSTIQUE) || defined(CONFIG_FB_MATROX_G100)
 #define NEED_DAC1064 1
@@ -305,6 +305,21 @@ struct my_timming {
        unsigned int delay;     /* CRTC delay */
 };
 
+enum { M_SYSTEM_PLL, M_PIXEL_PLL_A, M_PIXEL_PLL_B, M_PIXEL_PLL_C, M_VIDEO_PLL };
+
+struct matrox_pll_cache {
+       unsigned int    valid;
+       struct {
+               unsigned int    mnp_key;
+               unsigned int    mnp_value;
+                     } data[4];
+};
+
+struct matrox_pll_limits {
+       unsigned int    vcomin;
+       unsigned int    vcomax;
+};
+
 struct matrox_pll_features {
        unsigned int    vco_freq_min;
        unsigned int    ref_freq;
@@ -371,6 +386,8 @@ struct matrox_hw_state {
 
        /* CRTC2 only */
        /* u_int32_t    TBD */
+
+       unsigned int    vidclk;
 };
 
 struct matrox_accel_data {
@@ -382,8 +399,8 @@ struct matrox_accel_data {
 };
 
 struct matrox_altout {
-       int             (*compute)(void* altout_dev, struct my_timming* input, struct matrox_hw_state* state);
-       int             (*program)(void* altout_dev, const struct matrox_hw_state* state);
+       int             (*compute)(void* altout_dev, struct my_timming* input);
+       int             (*program)(void* altout_dev);
        int             (*start)(void* altout_dev);
        void            (*incuse)(void* altout_dev);
        void            (*decuse)(void* altout_dev);
@@ -391,6 +408,20 @@ struct matrox_altout {
        int             (*getmode)(void* altout_dev, u_int32_t* mode);
 };
 
+enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 };
+
+struct matrox_bios {
+       unsigned int    bios_valid : 1;
+       unsigned int    pins_len;
+       unsigned char   pins[128];
+       struct {
+               unsigned char vMaj, vMin, vRev;
+                     } version;
+       struct {
+               unsigned char state, tvout;
+                     } output;
+};
+
 struct matrox_switch;
 struct matroxfb_driver;
 
@@ -404,10 +435,7 @@ struct matrox_fb_info {
        unsigned int            usecount;
 
        struct matroxfb_par     curr;
-       struct matrox_hw_state  hw1;
-       struct matrox_hw_state  hw2;
-       struct matrox_hw_state* newhw;
-       struct matrox_hw_state* currenthw;
+       struct matrox_hw_state  hw;
 
        struct matrox_accel_data accel;
 
@@ -464,6 +492,8 @@ struct matrox_fb_info {
                spinlock_t      accel;
                              } lock;
 
+       enum mga_chip           chip;
+
        int                     interleave;
        int                     millenium;
        int                     milleniumII;
@@ -514,8 +544,8 @@ struct matrox_fb_info {
                                                /* 0 except for 6MB Millenium */
                int             memtype;
                int             g450dac;
-               int             g550dac;
                int             dfp_type;
+               unsigned int    fbResource;
                              } devflags;
        struct display_switch   dispsw;
        struct {
@@ -529,6 +559,38 @@ struct matrox_fb_info {
                int             redraw;
                struct timer_list timer;
                              } cursor;
+       struct matrox_bios      bios;
+       struct {
+               struct matrox_pll_limits        pixel;
+               struct matrox_pll_limits        system;
+               struct matrox_pll_limits        video;
+                             } limits;
+       struct {
+               struct matrox_pll_cache pixel;
+               struct matrox_pll_cache system;
+               struct matrox_pll_cache video;
+                                     } cache;
+       struct {
+               struct {
+                       unsigned int    video;
+                       unsigned int    system;
+                                     } pll;
+               struct {
+                       u_int32_t       opt;
+                       u_int32_t       opt2;
+                       u_int32_t       opt3;
+                       u_int32_t       mctlwtst;
+                       u_int32_t       mctlwtst_core;
+                       u_int32_t       memmisc;
+                       u_int32_t       memrdbk;
+                       u_int32_t       maccess;
+                                     } reg;
+               struct {
+                       unsigned int    ddr:1,
+                                       emrswen:1,
+                                       dll:1;
+                                     } memory;
+                             } values;
        struct { unsigned red, green, blue, transp; } palette[256];
 #if defined(CONFIG_FB_COMPAT_XPMAC)
        char    matrox_name[32];
@@ -599,10 +661,10 @@ static inline struct matrox_fb_info* mxinfo(const struct display* p) {
 #endif
 
 struct matrox_switch {
-       int     (*preinit)(WPMINFO struct matrox_hw_state*);
-       void    (*reset)(WPMINFO struct matrox_hw_state*);
-       int     (*init)(CPMINFO struct matrox_hw_state*, struct my_timming*, struct display*);
-       void    (*restore)(WPMINFO struct matrox_hw_state*, struct matrox_hw_state*, struct display*);
+       int     (*preinit)(WPMINFO2);
+       void    (*reset)(WPMINFO2);
+       int     (*init)(WPMINFO struct my_timming*, struct display*);
+       void    (*restore)(WPMINFO struct display*);
        int     (*selhwcursor)(WPMINFO struct display*);
 };
 
@@ -617,8 +679,13 @@ int matroxfb_register_driver(struct matroxfb_driver* drv);
 void matroxfb_unregister_driver(struct matroxfb_driver* drv);
 
 #define PCI_OPTION_REG 0x40
+#define   PCI_OPTION_ENABLE_ROM                0x40000000
+
 #define PCI_MGA_INDEX  0x44
 #define PCI_MGA_DATA   0x48
+#define PCI_OPTION2_REG        0x50
+#define PCI_OPTION3_REG        0x54
+#define PCI_MEMMISC_REG        0x58
 
 #define M_DWGCTL       0x1C00
 #define M_MACCESS      0x1C04
@@ -737,6 +804,8 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv);
 #define DAC_XGENIOCTRL         0x2A
 #define DAC_XGENIODATA         0x2B
 
+#define M_C2CTL                0x3E10
+
 #ifdef __LITTLE_ENDIAN
 #define MX_OPTION_BSWAP                0x00000000
 
@@ -794,6 +863,7 @@ extern void matroxfb_DAC_out(CPMINFO int reg, int val);
 extern int matroxfb_DAC_in(CPMINFO int reg);
 extern struct list_head matroxfb_list;
 extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt);
+extern int matroxfb_switch(int con, struct fb_info *);
 
 #ifdef MATROXFB_USE_SPINLOCKS
 #define CRITBEGIN  spin_lock_irqsave(&ACCESS_FBINFO(lock.accel), critflags);
index ac17dbb5d2265ae2b5bf65f4325125e3f811d0d7..f6f6552d5fa628291d4689714122db6ce91338ca 100644 (file)
@@ -4,7 +4,9 @@
  *
  * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.52 2001/05/25
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.62 2001/11/29
  *
  */
 
@@ -402,43 +404,35 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
                info->changevar(con);
        if (con == m2info->currcon) {
                struct my_timming mt;
-               struct matrox_hw_state* hw;
-               struct matrox_hw_state* ohw;
                unsigned int pos;
 
                matroxfb_var2my(var, &mt);
                /* CRTC2 delay */
                mt.delay = 34;
 
-               hw = ACCESS_FBINFO(newhw);
-               ohw = ACCESS_FBINFO(currenthw);
-
-               /* copy last setting... */
-               memcpy(hw, ohw, sizeof(*hw));
-
                pos = (var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel >> 3;
                pos += m2info->video.offbase;
-               DAC1064_global_init(PMINFO hw);
+               DAC1064_global_init(PMINFO2);
                if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
                        if (ACCESS_FBINFO(primout))
-                               ACCESS_FBINFO(primout)->compute(MINFO, &mt, hw);
+                               ACCESS_FBINFO(primout)->compute(MINFO, &mt);
                }
                if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) {
                        down_read(&ACCESS_FBINFO(altout.lock));
                        if (ACCESS_FBINFO(altout.output))
-                               ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt, hw);
+                               ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt);
                        up_read(&ACCESS_FBINFO(altout.lock));
                }
                matroxfb_dh_restore(m2info, &mt, p, mode, pos);
-               DAC1064_global_restore(PMINFO hw);
+               DAC1064_global_restore(PMINFO2);
                if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
                        if (ACCESS_FBINFO(primout))
-                               ACCESS_FBINFO(primout)->program(MINFO, hw);
+                               ACCESS_FBINFO(primout)->program(MINFO);
                }
                if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) {
                        down_read(&ACCESS_FBINFO(altout.lock));
                        if (ACCESS_FBINFO(altout.output))
-                               ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device), hw);
+                               ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device));
                        up_read(&ACCESS_FBINFO(altout.lock));
                }
                if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
@@ -693,7 +687,7 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
 
        strcpy(m2info->fbcon.modename, "MATROX CRTC2");
        m2info->fbcon.changevar = NULL;
-       m2info->fbcon.node = -1;
+       m2info->fbcon.node = NODEV;
        m2info->fbcon.fbops = &matroxfb_dh_ops;
        m2info->fbcon.disp = d;
        m2info->fbcon.switch_con = &matroxfb_dh_switch;
index f3705bf6fca2caa3328d610d7f669d6969f76691..d57a8845bbccf57bf7054a2196b6139807bc9af9 100644 (file)
@@ -4,7 +4,9 @@
  *
  * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.51 2001/01/19
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.62 2001/11/29
  *
  * See matroxfb_base.c for contributors.
  *
 #include "matroxfb_g450.h"
 #include "matroxfb_misc.h"
 #include "matroxfb_DAC1064.h"
+#include "g450_pll.h"
 #include <linux/matroxfb.h>
 #include <asm/uaccess.h>
 
-static int matroxfb_g450_get_reg(WPMINFO int reg) {
-       int val;
-       unsigned long flags;
-
-       matroxfb_DAC_lock_irqsave(flags);
-       val = matroxfb_DAC_in(PMINFO reg);
-       matroxfb_DAC_unlock_irqrestore(flags);
-       return val;
-}
-
-static int matroxfb_g450_set_reg(WPMINFO int reg, int val) {
-       unsigned long flags;
-
-       matroxfb_DAC_lock_irqsave(flags);
-       matroxfb_DAC_out(PMINFO reg, val);
-       matroxfb_DAC_unlock_irqrestore(flags);
-       return 0;
-}
-
-static const struct matrox_pll_features maven_pll = {
-       110000,
-       27000,
-       4, 127,
-       2, 31,
-       3
-};
-
-static const struct matrox_pll_features g550_pll = {
-       135000,
-       27000,
-       4, 127,
-       0, 9,
-       3
-};
-
-static void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
-               unsigned int* in, unsigned int* feed, unsigned int* post,
-               unsigned int timmings) {
-       unsigned int fvco;
-       unsigned int p;
-
-       switch (timmings) {
-               default:
-                       fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
-                       /* 0 => 100 ... 275 MHz
-                          1 => 243 ... 367 MHz
-                          2 => 320 ... 475 MHz
-                          3 => 453 ... 556 MHz
-                          4 => 540 ... 594 MHz
-                          5 => 588 ... 621 MHz
-                          6 => 626 ... 637 MHz
-                          7 => 631 ... 642 MHz
-
-                          As you can see, never choose frequency > 621 MHz, there is unavailable gap...
-                          Just to be sure, currently driver uses 110 ... 500 MHz range.
-                        */
-                       if (fvco <= 260000)
-                               ;
-                       else if (fvco <= 350000)
-                               p |= 0x08;
-                       else if (fvco <= 460000)
-                               p |= 0x10;
-                       else if (fvco <= 550000)
-                               p |= 0x18;
-                       else if (fvco <= 590000)
-                               p |= 0x20;
-                       else
-                               p |= 0x28;
-                       break;
-               case 1:
-                       fvco = matroxfb_PLL_calcclock(&g550_pll, freq, fmax, in, feed, &p);
-                       /* p |= 0x00; */
-                       break;
-       }
-       *post = p;
-       return;
-}
-
-static inline int matroxfb_g450_compute_timming(struct matroxfb_g450_info* m2info,
-               struct my_timming* mt,
-               struct mavenregs* m) {
-       unsigned int a, b, c;
-
-       DAC1064_calcclock(mt->pixclock, 300000, &a, &b, &c, m2info->timmings);
-       m->regs[0x80] = a;
-       m->regs[0x81] = b;
-       m->regs[0x82] = c;
-       printk(KERN_DEBUG "PLL: %02X %02X %02X\n", a, b, c);
+static int matroxfb_g450_compute(void* md, struct my_timming* mt) {
+#define m2info ((struct matroxfb_g450_info*)md)
+#define minfo (m2info->primary_dev)
+       ACCESS_FBINFO(hw).vidclk = mt->pixclock;
+#undef minfo
+#undef m2info
        return 0;
 }
 
-static inline int matroxfb_g450_program_timming(struct matroxfb_g450_info* m2info, const struct mavenregs* m) {
-       MINFO_FROM(m2info->primary_dev);
-
-       matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2M, m->regs[0x81]);
-       matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2N, m->regs[0x80]);
-       matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2P, m->regs[0x82]);
+static int matroxfb_g450_program(void* md) {
+#define m2info ((struct matroxfb_g450_info*)md)
+#define minfo (m2info->primary_dev)
+       matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(hw).vidclk, M_VIDEO_PLL);
+#undef minfo
+#undef m2info  
        return 0;
 }
 
-/******************************************************/
-
-static int matroxfb_g450_compute(void* md, struct my_timming* mt, struct matrox_hw_state* mr) {
-       return matroxfb_g450_compute_timming(md, mt, &mr->maven);
-}
-
-static int matroxfb_g450_program(void* md, const struct matrox_hw_state* mr) {
-       return matroxfb_g450_program_timming(md, &mr->maven);
-}
-
 static int matroxfb_g450_start(void* md) {
        return 0;
 }
@@ -191,7 +102,7 @@ static void matroxfb_g450_shutdown(struct matroxfb_g450_info* m2info) {
 static void* matroxfb_g450_probe(struct matrox_fb_info* minfo) {
        struct matroxfb_g450_info* m2info;
 
-       /* hardware is not G450 incapable... */
+       /* hardware is not G450... */
        if (!ACCESS_FBINFO(devflags.g450dac))
                return NULL;
        m2info = (struct matroxfb_g450_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
@@ -201,11 +112,6 @@ static void* matroxfb_g450_probe(struct matrox_fb_info* minfo) {
        }
        memset(m2info, 0, sizeof(*m2info));
        m2info->primary_dev = MINFO;
-       if (ACCESS_FBINFO(devflags.g550dac)) {
-               m2info->timmings = 1;
-       } else {
-               m2info->timmings = 0;
-       }
        if (matroxfb_g450_connect(m2info)) {
                kfree(m2info);
                printk(KERN_ERR "matroxfb_g450: G450 DAC failed to initialize\n");
index cfee9249decc09517456c7bdf9c46678a9d41348..e6a904dde2b81d6648bffcc199b30c581be553f9 100644 (file)
@@ -862,12 +862,20 @@ static int maven_get_output_mode(struct maven_data* md, u_int32_t *arg) {
 
 /******************************************************/
 
-static int maven_out_compute(void* md, struct my_timming* mt, struct matrox_hw_state* mr) {
-       return maven_compute_timming(md, mt, &mr->maven);
+static int maven_out_compute(void* md, struct my_timming* mt) {
+#define mdinfo ((struct maven_data*)md)
+#define minfo (mdinfo->primary_head)
+       return maven_compute_timming(md, mt, &ACCESS_FBINFO(hw).maven);
+#undef minfo
+#undef mdinfo
 }
 
-static int maven_out_program(void* md, const struct matrox_hw_state* mr) {
-       return maven_program_timming(md, &mr->maven);
+static int maven_out_program(void* md) {
+#define mdinfo ((struct maven_data*)md)
+#define minfo (mdinfo->primary_head)
+       return maven_program_timming(md, &ACCESS_FBINFO(hw).maven);
+#undef minfo
+#undef mdinfo
 }
 
 static int maven_out_start(void* md) {
index 1c46f42157d7f33f08121c789e8c1fd36ac73917..49a00835203f7e11fcb299f85abea55800cf9339 100644 (file)
@@ -2,9 +2,11 @@
  *
  * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
  *
- * (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998,1999,2000,2001 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.54 2001/09/09
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.62 2001/11/29
  *
  * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
  *
@@ -218,7 +220,7 @@ int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int f
        return bestvco;
 }
 
-int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
+int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p) {
        unsigned int hd, hs, he, hbe, ht;
        unsigned int vd, vs, ve, vt;
        unsigned int wd;
@@ -226,6 +228,7 @@ int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m,
        int i;
        int text = p->type == FB_TYPE_TEXT;
        int fwidth;
+       struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
 
        if (text) {
                fwidth = fontwidth(p);
@@ -416,8 +419,9 @@ int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m,
        return 0;
 };
 
-void matroxfb_vgaHWrestore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw) {
+void matroxfb_vgaHWrestore(WPMINFO2) {
        int i;
+       struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
        CRITFLAGS
 
        DBG("vgaHWrestore")
@@ -643,6 +647,354 @@ int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
        return 1;
 }
 
+static void get_pins(unsigned char* pins, struct matrox_bios* bd) {
+       unsigned int b0 = readb(pins);
+       
+       if (b0 == 0x2E && readb(pins+1) == 0x41) {
+               unsigned int pins_len = readb(pins+2);
+               unsigned int i;
+               unsigned char cksum;
+               unsigned char* dst = bd->pins;
+
+               if (pins_len < 3 || pins_len > 128) {
+                       return;
+               }
+               *dst++ = 0x2E;
+               *dst++ = 0x41;
+               *dst++ = pins_len;
+               cksum = 0x2E + 0x41 + pins_len;
+               for (i = 3; i < pins_len; i++) {
+                       cksum += *dst++ = readb(pins+i);
+               }
+               if (cksum) {
+                       return;
+               }
+               bd->pins_len = pins_len;
+       } else if (b0 == 0x40 && readb(pins+1) == 0x00) {
+               unsigned int i;
+               unsigned char* dst = bd->pins;
+
+               *dst++ = 0x40;
+               *dst++ = 0;
+               for (i = 2; i < 0x40; i++) {
+                       *dst++ = readb(pins+i);
+               }
+               bd->pins_len = 0x40;
+       }
+}
+
+static void get_bios_version(unsigned char* vbios, struct matrox_bios* bd) {
+       unsigned int pcir_offset;
+       
+       pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
+       if (pcir_offset >= 26 && pcir_offset < 0xFFE0 &&
+           readb(vbios + pcir_offset    ) == 'P' &&
+           readb(vbios + pcir_offset + 1) == 'C' &&
+           readb(vbios + pcir_offset + 2) == 'I' &&
+           readb(vbios + pcir_offset + 3) == 'R') {
+               unsigned char h;
+
+               h = readb(vbios + pcir_offset + 0x12);
+               bd->version.vMaj = (h >> 4) & 0xF;
+               bd->version.vMin = h & 0xF;
+               bd->version.vRev = readb(vbios + pcir_offset + 0x13);
+       } else {
+               unsigned char h;
+
+               h = readb(vbios + 5);
+               bd->version.vMaj = (h >> 4) & 0xF;
+               bd->version.vMin = h & 0xF;
+               bd->version.vRev = 0;
+       }
+}
+
+static void get_bios_output(unsigned char* vbios, struct matrox_bios* bd) {
+       unsigned char b;
+       
+       b = readb(vbios + 0x7FF1);
+       if (b == 0xFF) {
+               b = 0;
+       }
+       bd->output.state = b;
+}
+
+static void get_bios_tvout(unsigned char* vbios, struct matrox_bios* bd) {
+       unsigned int i;
+       
+       /* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */
+       bd->output.tvout = 0;
+       if (readb(vbios + 0x1D) != 'I' ||
+           readb(vbios + 0x1E) != 'B' ||
+           readb(vbios + 0x1F) != 'M' ||
+           readb(vbios + 0x20) != ' ') {
+               return;
+       }
+       for (i = 0x2D; i < 0x2D + 128; i++) {
+               unsigned char b = readb(vbios + i);
+               
+               if (b == '(' && readb(vbios + i + 1) == 'V') {
+                       if (readb(vbios + i + 6) == 'T' &&
+                           readb(vbios + i + 7) == 'V' &&
+                           readb(vbios + i + 8) == 'O') {
+                               bd->output.tvout = 1;
+                       }
+                       return;
+               }
+               if (b == 0)
+                       break;
+       }
+}
+
+static void parse_bios(unsigned char* vbios, struct matrox_bios* bd) {
+       unsigned int pins_offset;
+       
+       if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
+               return;
+       }
+       bd->bios_valid = 1;
+       get_bios_version(vbios, bd);
+       get_bios_output(vbios, bd);
+       get_bios_tvout(vbios, bd);
+       pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
+       if (pins_offset <= 0xFF80) {
+               get_pins(vbios + pins_offset, bd);
+       }
+}
+
+#define get_u16(x) (le16_to_cpu(get_unaligned((__u16*)(x))))
+#define get_u32(x) (le32_to_cpu(get_unaligned((__u32*)(x))))
+static int parse_pins1(WPMINFO const struct matrox_bios* bd) {
+       unsigned int maxdac;
+
+       switch (bd->pins[22]) {
+               case 0:         maxdac = 175000; break;
+               case 1:         maxdac = 220000; break;
+               default:        maxdac = 240000; break;
+       }
+       if (get_u16(bd->pins + 24)) {
+               maxdac = get_u16(bd->pins + 24) * 10;
+       }
+       MINFO->limits.pixel.vcomax = maxdac;
+       MINFO->values.pll.system = get_u16(bd->pins + 28) ? get_u16(bd->pins + 28) * 10 : 50000;
+       /* ignore 4MB, 8MB, module clocks */
+       MINFO->features.pll.ref_freq = 14318;
+       MINFO->values.reg.mctlwtst      = 0x00030101;
+       return 0;
+}
+
+static void default_pins1(WPMINFO2) {
+       /* Millennium */
+       MINFO->limits.pixel.vcomax      = 220000;
+       MINFO->values.pll.system        =  50000;
+       MINFO->features.pll.ref_freq    =  14318;
+       MINFO->values.reg.mctlwtst      = 0x00030101;
+}
+
+static int parse_pins2(WPMINFO const struct matrox_bios* bd) {
+       MINFO->limits.pixel.vcomax      =
+       MINFO->limits.system.vcomax     = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000);
+       MINFO->values.reg.mctlwtst      = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) |
+                                         ((bd->pins[51] & 0x02) ? 0x00000100 : 0) |
+                                         ((bd->pins[51] & 0x04) ? 0x00010000 : 0) |
+                                         ((bd->pins[51] & 0x08) ? 0x00020000 : 0);
+       MINFO->values.pll.system        = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000);
+       MINFO->features.pll.ref_freq    = 14318;
+       return 0;
+}
+
+static void default_pins2(WPMINFO2) {
+       /* Millennium II, Mystique */
+       MINFO->limits.pixel.vcomax      =
+       MINFO->limits.system.vcomax     = 230000;
+       MINFO->values.reg.mctlwtst      = 0x00030101;
+       MINFO->values.pll.system        =  50000;
+       MINFO->features.pll.ref_freq    =  14318;
+}
+
+static int parse_pins3(WPMINFO const struct matrox_bios* bd) {
+       MINFO->limits.pixel.vcomax      =
+       MINFO->limits.system.vcomax     = (bd->pins[36] == 0xFF) ? 230000                       : ((bd->pins[36] + 100) * 1000);
+       MINFO->values.reg.mctlwtst      = get_u32(bd->pins + 48) == 0xFFFFFFFF ? 0x01250A21     : get_u32(bd->pins + 48);
+       /* memory config */
+       MINFO->values.reg.memrdbk       = ((bd->pins[57] << 21) & 0x1E000000) |
+                                         ((bd->pins[57] << 22) & 0x00C00000) |
+                                         ((bd->pins[56] <<  1) & 0x000001E0) |
+                                         ( bd->pins[56]        & 0x0000000F);
+       MINFO->values.reg.opt           = (bd->pins[54] & 7) << 10;
+       MINFO->values.reg.opt2          = bd->pins[58] << 12;
+       MINFO->features.pll.ref_freq    = (bd->pins[52] & 0x20) ? 14318 : 27000;
+       return 0;
+}
+
+static void default_pins3(WPMINFO2) {
+       /* G100, G200 */
+       MINFO->limits.pixel.vcomax      =
+       MINFO->limits.system.vcomax     = 230000;
+       MINFO->values.reg.mctlwtst      = 0x01250A21;
+       MINFO->values.reg.memrdbk       = 0x00000000;
+       MINFO->values.reg.opt           = 0x00000C00;
+       MINFO->values.reg.opt2          = 0x00000000;
+       MINFO->features.pll.ref_freq    =  27000;
+}
+
+static int parse_pins4(WPMINFO const struct matrox_bios* bd) {
+       MINFO->limits.pixel.vcomax      = (bd->pins[ 39] == 0xFF) ? 230000                      : bd->pins[ 39] * 4000;
+       MINFO->limits.system.vcomax     = (bd->pins[ 38] == 0xFF) ? MINFO->limits.pixel.vcomax  : bd->pins[ 38] * 4000;
+       MINFO->values.reg.mctlwtst      = get_u32(bd->pins + 71);
+       MINFO->values.reg.memrdbk       = ((bd->pins[87] << 21) & 0x1E000000) |
+                                         ((bd->pins[87] << 22) & 0x00C00000) |
+                                         ((bd->pins[86] <<  1) & 0x000001E0) |
+                                         ( bd->pins[86]        & 0x0000000F);
+       MINFO->values.reg.opt           = ((bd->pins[53] << 15) & 0x00400000) |
+                                         ((bd->pins[53] << 22) & 0x10000000) |
+                                         ((bd->pins[53] << 10) & 0x00001C00);
+       MINFO->values.reg.opt3          = get_u32(bd->pins + 67);
+       MINFO->values.pll.system        = (bd->pins[ 65] == 0xFF) ? 200000                      : bd->pins[ 65] * 4000;
+       MINFO->features.pll.ref_freq    = (bd->pins[ 92] & 0x01) ? 14318 : 27000;
+       return 0;
+}
+
+static void default_pins4(WPMINFO2) {
+       /* G400 */
+       MINFO->limits.pixel.vcomax      =
+       MINFO->limits.system.vcomax     = 252000;
+       MINFO->values.reg.mctlwtst      = 0x04A450A1;
+       MINFO->values.reg.memrdbk       = 0x000000E7;
+       MINFO->values.reg.opt           = 0x10000400;
+       MINFO->values.reg.opt3          = 0x0190A419;
+       MINFO->values.pll.system        = 200000;
+       MINFO->features.pll.ref_freq    = 27000;
+}
+
+static int parse_pins5(WPMINFO const struct matrox_bios* bd) {
+       unsigned int mult;
+       
+       mult = bd->pins[4]?8000:6000;
+       
+       MINFO->limits.pixel.vcomax      = (bd->pins[ 38] == 0xFF) ? 600000                      : bd->pins[ 38] * mult;
+       MINFO->limits.system.vcomax     = (bd->pins[ 36] == 0xFF) ? MINFO->limits.pixel.vcomax  : bd->pins[ 39] * mult;
+       MINFO->limits.video.vcomax      = (bd->pins[ 37] == 0xFF) ? MINFO->limits.system.vcomax : bd->pins[ 37] * mult;
+       MINFO->limits.pixel.vcomin      = (bd->pins[123] == 0xFF) ? 256000                      : bd->pins[123] * mult;
+       MINFO->limits.system.vcomin     = (bd->pins[121] == 0xFF) ? MINFO->limits.pixel.vcomin  : bd->pins[121] * mult;
+       MINFO->limits.video.vcomin      = (bd->pins[122] == 0xFF) ? MINFO->limits.system.vcomin : bd->pins[122] * mult;
+       MINFO->values.pll.system        =
+       MINFO->values.pll.video         = (bd->pins[ 92] == 0xFF) ? 284000                      : bd->pins[ 92] * 4000;
+       MINFO->values.reg.opt           = get_u32(bd->pins+ 48);
+       MINFO->values.reg.opt2          = get_u32(bd->pins+ 52);
+       MINFO->values.reg.opt3          = get_u32(bd->pins+ 94);
+       MINFO->values.reg.mctlwtst      = get_u32(bd->pins+ 98);
+       MINFO->values.reg.memmisc       = get_u32(bd->pins+102);
+       MINFO->values.reg.memrdbk       = get_u32(bd->pins+106);
+       MINFO->features.pll.ref_freq    = (bd->pins[110] & 0x01) ? 14318 : 27000;
+       MINFO->values.memory.ddr        = (bd->pins[114] & 0x60) == 0x20;
+       MINFO->values.memory.dll        = (bd->pins[115] & 0x02) != 0;
+       MINFO->values.memory.emrswen    = (bd->pins[115] & 0x01) != 0;
+       MINFO->values.reg.maccess       = MINFO->values.memory.emrswen ? 0x00004000 : 0x00000000;
+       if (bd->pins[115] & 4) {
+               MINFO->values.reg.mctlwtst_core = MINFO->values.reg.mctlwtst;
+       } else {
+               u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 };
+               MINFO->values.reg.mctlwtst_core = (MINFO->values.reg.mctlwtst & ~7) |
+                                                 wtst_xlat[MINFO->values.reg.mctlwtst & 7];
+       }
+       return 0;
+}
+
+static void default_pins5(WPMINFO2) {
+       /* Mine 16MB G450 with SDRAM DDR */
+       MINFO->limits.pixel.vcomax      =
+       MINFO->limits.system.vcomax     =
+       MINFO->limits.video.vcomax      = 600000;
+       MINFO->limits.pixel.vcomin      =
+       MINFO->limits.system.vcomin     =
+       MINFO->limits.video.vcomin      = 256000;
+       MINFO->values.pll.system        =
+       MINFO->values.pll.video         = 284000;
+       MINFO->values.reg.opt           = 0x404A1160;
+       MINFO->values.reg.opt2          = 0x0000AC00;
+       MINFO->values.reg.opt3          = 0x0090A409;
+       MINFO->values.reg.mctlwtst_core =
+       MINFO->values.reg.mctlwtst      = 0x0C81462B;
+       MINFO->values.reg.memmisc       = 0x80000004;
+       MINFO->values.reg.memrdbk       = 0x01001103;
+       MINFO->features.pll.ref_freq    = 27000;
+       MINFO->values.memory.ddr        = 1;
+       MINFO->values.memory.dll        = 1;
+       MINFO->values.memory.emrswen    = 1;
+       MINFO->values.reg.maccess       = 0x00004000;
+}
+
+static int matroxfb_set_limits(WPMINFO const struct matrox_bios* bd) {
+       unsigned int pins_version;
+       static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 };
+
+       switch (ACCESS_FBINFO(chip)) {
+               case MGA_2064:  default_pins1(PMINFO2); break;
+               case MGA_2164:
+               case MGA_1064:
+               case MGA_1164:  default_pins2(PMINFO2); break;
+               case MGA_G100:
+               case MGA_G200:  default_pins3(PMINFO2); break;
+               case MGA_G400:  default_pins4(PMINFO2); break;
+               case MGA_G450:
+               case MGA_G550:  default_pins5(PMINFO2); break;
+       }
+       if (!bd->bios_valid) {
+               printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n");
+               return -1;
+       }
+       if (bd->pins_len < 64) {
+               printk(KERN_INFO "matroxfb: BIOS on your Matrox device does not contain powerup info\n");
+               return -1;
+       }
+       if (bd->pins[0] == 0x2E && bd->pins[1] == 0x41) {
+               pins_version = bd->pins[5];
+               if (pins_version < 2 || pins_version > 5) {
+                       printk(KERN_INFO "matroxfb: Unknown version (%u) of powerup info\n", pins_version);
+                       return -1;
+               }
+       } else {
+               pins_version = 1;
+       }
+       if (bd->pins_len != pinslen[pins_version - 1]) {
+               printk(KERN_INFO "matroxfb: Invalid powerup info\n");
+               return -1;
+       }
+       switch (pins_version) {
+               case 1:
+                       return parse_pins1(PMINFO bd);
+               case 2:
+                       return parse_pins2(PMINFO bd);
+               case 3:
+                       return parse_pins3(PMINFO bd);
+               case 4:
+                       return parse_pins4(PMINFO bd);
+               case 5:
+                       return parse_pins5(PMINFO bd);
+               default:
+                       printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version);
+                       return -1;
+       }
+}
+
+void matroxfb_read_pins(WPMINFO2) {
+       u32 opt;
+       u32 biosbase;
+       u32 fbbase;
+       struct pci_dev* pdev = ACCESS_FBINFO(pcidev);
+       
+       memset(&ACCESS_FBINFO(bios), 0, sizeof(ACCESS_FBINFO(bios)));
+       pci_read_config_dword(pdev, PCI_OPTION_REG, &opt);
+       pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM);
+       pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase);
+       pci_read_config_dword(pdev, ACCESS_FBINFO(devflags.fbResource), &fbbase);
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+       parse_bios(vaddr_va(ACCESS_FBINFO(video).vbase), &ACCESS_FBINFO(bios));
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase);
+       pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
+       matroxfb_set_limits(PMINFO &ACCESS_FBINFO(bios));
+}
+
 EXPORT_SYMBOL(matroxfb_DAC_in);
 EXPORT_SYMBOL(matroxfb_DAC_out);
 EXPORT_SYMBOL(matroxfb_var2my);
@@ -657,6 +1009,7 @@ EXPORT_SYMBOL(matroxfb_fastfont_tryset);   /* accel */
 EXPORT_SYMBOL(matroxfb_fastfont_init);         /* DAC1064, Ti3026 */
 EXPORT_SYMBOL(matroxfb_vgaHWinit);             /* DAC1064, Ti3026 */
 EXPORT_SYMBOL(matroxfb_vgaHWrestore);          /* DAC1064, Ti3026 */
+EXPORT_SYMBOL(matroxfb_read_pins);
 
 MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
 MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
index b88ccd8caa1e5aea2fbcd71ac83eed0216d699df..58eddccbfa8dba1bc18c3a1b0efa443499b4eba9 100644 (file)
@@ -12,10 +12,11 @@ static inline int PLL_calcclock(CPMINFO unsigned int freq, unsigned int fmax,
 }
 
 void matroxfb_createcursorshape(WPMINFO struct display* p, int vmode);
-int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p);
-void matroxfb_vgaHWrestore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw);
+int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p);
+void matroxfb_vgaHWrestore(WPMINFO2);
 void matroxfb_fastfont_init(struct matrox_fb_info* minfo);
 int matrox_text_loadfont(WPMINFO struct display* p);
 int matroxfb_fastfont_tryset(WPMINFO struct display* p);
+void matroxfb_read_pins(WPMINFO2);
 
 #endif /* __MATROXFB_MISC_H__ */