Here's my matroxfb G400 clock patch if someone want's to try it. It's
against 2.4.22.
The setup values are read from the EEPROM so it should work on a normal
G400 and a G400 MAX. MAX should have faster clocks. I'd really like to see
df_dok results for a MAX.
You need to boot with "video=matrox:init" to initialize the primary card.
I also tried the patch with another PCI card as the primary one and the
G400 woke up fine and the clocks were correct.
--
Ville Syrj�l�
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
diff -urN linux-2.4.22-orig/drivers/video/matrox/matroxfb_DAC1064.c
linux-2.4.22/drivers/video/matrox/matroxfb_DAC1064.c
--- linux-2.4.22-orig/drivers/video/matrox/matroxfb_DAC1064.c 2003-10-01
11:51:02.000000000 +0300
+++ linux-2.4.22/drivers/video/matrox/matroxfb_DAC1064.c 2003-10-01
12:19:35.000000000 +0300
@@ -951,6 +951,96 @@
}
#endif
+static void g400_preinit(WPMINFO2) {
+ unsigned int m, n, p, rfhcnt, mclk, clk;
+ u_int32_t opt, opt2;
+
+ pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &opt);
+ opt &= 0xE0000100;
+ opt |= ACCESS_FBINFO(values).reg.opt;
+ if (ACCESS_FBINFO(devflags.novga))
+ opt &= ~0x00000100;
+ if (ACCESS_FBINFO(devflags.nobios))
+ opt &= ~0x40000000;
+ if (ACCESS_FBINFO(devflags.nopciretry))
+ opt |= 0x20000000;
+ opt |= 0x20;
+
+ pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &opt2);
+ opt2 &= ~0x0F3F0100;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, opt2);
+
+ /* switch all clocks to PCI source */
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG,
+ opt | 0x4);
+ 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, opt);
+
+ DAC1064_calcclock(ACCESS_FBINFO(values.pll.system),
+ ACCESS_FBINFO(limits.system.vcomax),
+ &m, &n, &p );
+ ACCESS_FBINFO(hw).DACclk[0] = m;
+ ACCESS_FBINFO(hw).DACclk[1] = n;
+ ACCESS_FBINFO(hw).DACclk[2] = p;
+
+ outDAC1064(PMINFO DAC1064_XSYSPLLM, m );
+ outDAC1064(PMINFO DAC1064_XSYSPLLN, n );
+ outDAC1064(PMINFO DAC1064_XSYSPLLP, p );
+ for (clk = 65536; clk; --clk) {
+ if (inDAC1064(PMINFO DAC1064_XSYSPLLSTAT) & 0x40)
+ break;
+ }
+ if (!clk)
+ printk(KERN_ERR "matroxfb: aiee, SYSPLL not locked\n");
+
+ /* switch clocks to their real PLL source(s) */
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG,
+ opt | 0x4);
+ 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, opt);
+
+ mclk = ACCESS_FBINFO(values.pll.system) * 1000;
+ switch ((ACCESS_FBINFO(values).reg.opt3 >> 13) & 0x7) {
+ case 0:
+ mclk = mclk * 1 / 3;
+ break;
+ case 1:
+ mclk = mclk * 2 / 5;
+ break;
+ case 2:
+ mclk = mclk * 4 / 9;
+ break;
+ case 3:
+ mclk = mclk * 1 / 2;
+ break;
+ case 4:
+ mclk = mclk * 2 / 3;
+ break;
+ default:
+ mclk = mclk * 1 / 1;
+ break;
+ }
+
+ /* 15 ns? */
+ rfhcnt = (mclk - 66667) / (64 * 66667);
+ if (rfhcnt > 63)
+ rfhcnt = 63;
+ rfhcnt <<= 15;
+
+ 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_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
+ opt |= rfhcnt;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, opt);
+ ACCESS_FBINFO(hw).MXoptionReg = opt;
+}
+
static int MGAG100_preinit(WPMINFO2) {
static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960,
1024, 1152, 1280, 1600, 1664, 1920,
@@ -1010,6 +1100,10 @@
g450_preinit(PMINFO2);
return 0;
}
+ if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) {
+ g400_preinit(PMINFO2);
+ return 0;
+ }
hw->MXoptionReg &= 0xC0000100;
hw->MXoptionReg |= 0x00000020;
if (ACCESS_FBINFO(devflags.novga))
@@ -1072,26 +1166,6 @@
udelay(100);
mga_outw(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
hw->MXoptionReg |= 0x00078020;
- } else {
- pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50);
- reg50 &= ~0x00000100;
- reg50 |= 0x00000000;
- pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
-
- if (ACCESS_FBINFO(devflags.memtype) == -1)
- 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, 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_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
- hw->MXoptionReg |= 0x00040020;
}
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
return 0;
@@ -1129,7 +1203,7 @@
mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
}
}
- if (ACCESS_FBINFO(devflags.g450dac)) {
+ if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) {
/* 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);
diff -urN linux-2.4.22-orig/drivers/video/matrox/matroxfb_misc.c
linux-2.4.22/drivers/video/matrox/matroxfb_misc.c
--- linux-2.4.22-orig/drivers/video/matrox/matroxfb_misc.c 2003-10-01
11:51:02.000000000 +0300
+++ linux-2.4.22/drivers/video/matrox/matroxfb_misc.c 2003-10-01 12:13:00.000000000
+0300
@@ -845,16 +845,17 @@
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.mctlwtst = get_u32(bd->pins + 81);
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] << 7) & 0x00001C00);
- MINFO->values.reg.opt3 = get_u32(bd->pins + 67);
- MINFO->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000
: bd->pins[ 65] * 4000;
+ ((bd->pins[53] << 7) & 0x00001C00) |
+ (((bd->pins[92] << 10) ^ 0x00004000) &
0x00004000);
+ MINFO->values.reg.opt3 = get_u32(bd->pins + 77);
+ MINFO->values.pll.system = (bd->pins[ 76] == 0xFF) ? 200000
: bd->pins[ 76] * 4000;
MINFO->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000;
return 0;
}