summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/fb/matroxfb.txt12
-rw-r--r--drivers/video/Config.help13
-rw-r--r--drivers/video/Config.in4
-rw-r--r--drivers/video/matrox/Makefile6
-rw-r--r--drivers/video/matrox/g450_pll.c472
-rw-r--r--drivers/video/matrox/g450_pll.h8
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.c346
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.h12
-rw-r--r--drivers/video/matrox/matroxfb_Ti3026.c67
-rw-r--r--drivers/video/matrox/matroxfb_base.c127
-rw-r--r--drivers/video/matrox/matroxfb_base.h94
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c26
-rw-r--r--drivers/video/matrox/matroxfb_g450.c128
-rw-r--r--drivers/video/matrox/matroxfb_maven.c16
-rw-r--r--drivers/video/matrox/matroxfb_misc.c361
-rw-r--r--drivers/video/matrox/matroxfb_misc.h5
16 files changed, 1329 insertions, 368 deletions
diff --git a/Documentation/fb/matroxfb.txt b/Documentation/fb/matroxfb.txt
index 508aaa1878ef..1d0dd81dccde 100644
--- a/Documentation/fb/matroxfb.txt
+++ b/Documentation/fb/matroxfb.txt
@@ -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
diff --git a/drivers/video/Config.help b/drivers/video/Config.help
index 1dcfd5b473ac..a3598e051049 100644
--- a/drivers/video/Config.help
+++ b/drivers/video/Config.help
@@ -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
diff --git a/drivers/video/Config.in b/drivers/video/Config.in
index 1d92c99c2505..f5ce38ed128f 100644
--- a/drivers/video/Config.in
+++ b/drivers/video/Config.in
@@ -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
diff --git a/drivers/video/matrox/Makefile b/drivers/video/matrox/Makefile
index 2b7945150cbe..b34afde318de 100644
--- a/drivers/video/matrox/Makefile
+++ b/drivers/video/matrox/Makefile
@@ -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
index 000000000000..2b7e81b08931
--- /dev/null
+++ b/drivers/video/matrox/g450_pll.c
@@ -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
index 000000000000..58a80ef2fd76
--- /dev/null
+++ b/drivers/video/matrox/g450_pll.h
@@ -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__ */
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
index b0a12c07e1eb..ad5dfb1a1074 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ b/drivers/video/matrox/matroxfb_DAC1064.c
@@ -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
diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h
index 62cde7919e9d..6136fd33a14b 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.h
+++ b/drivers/video/matrox/matroxfb_DAC1064.h
@@ -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
diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c
index 16f1e7653a82..57b37600a3cb 100644
--- a/drivers/video/matrox/matroxfb_Ti3026.c
+++ b/drivers/video/matrox/matroxfb_Ti3026.c
@@ -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")
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 0902bee80076..07d881b1c5fa 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -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;
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index d4d2df71fd3f..be8074117fec 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -162,7 +162,7 @@
#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);
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index ac17dbb5d226..f6f6552d5fa6 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -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;
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index f3705bf6fca2..d57a8845bbcc 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -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.
*
@@ -13,119 +15,28 @@
#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");
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index cfee9249decc..e6a904dde2b8 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -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) {
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index 1c46f42157d7..49a00835203f 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -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");
diff --git a/drivers/video/matrox/matroxfb_misc.h b/drivers/video/matrox/matroxfb_misc.h
index b88ccd8caa1e..58eddccbfa8d 100644
--- a/drivers/video/matrox/matroxfb_misc.h
+++ b/drivers/video/matrox/matroxfb_misc.h
@@ -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__ */