From: Paul A. Clarke There has been a longstanding problem with the Matrox G450 and perhaps other similar cards, with modes "above" 1280x1024-60 on ppc/ppc64 boxes running Linux. Higher resolutions and/or higher refresh rates resulted in a very noticably "jittery" display, and sometimes no display, depending on the physical monitor. This patch fixes that problem on the systems I have easy access to... I've tested with SLES9SP3 (2.6.5+ kernel) and 2.6.16-rc6 custom kernels on an IBM eServer p5 520 w/G450 (a.k.a GXT135P on IBM's ppc64 systems), and a colleague of mine (Ian Romanick) tested it successfully on an Apple ppc32 box (w/GXT135P). I also tested it on IA32 box I have with a GXT135P to verify that it didn't obviously break anything. In my testing, I covered single-card, single and dual-head setups using both HD15 and DVI-D signals, on both the IA32 and ppc64 boxes. While everything appeared fine on both boxes, I did encounter one problem: I can't get any signal on the DVI-D output on the ppc64 box. However, this is also the case without my patch. I just noticed that screen-blanking only occurs on the primary display as well. Signed-off-by: Paul A. Clarke Signed-off-by: Ian Romanick Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton --- drivers/video/matrox/g450_pll.c | 23 ++++++++++++++++++++-- drivers/video/matrox/matroxfb_DAC1064.h | 2 + drivers/video/matrox/matroxfb_base.h | 2 + 3 files changed, 25 insertions(+), 2 deletions(-) diff -puN drivers/video/matrox/g450_pll.c~matroxfb-fix-dvi-setup-to-be-more-compatible drivers/video/matrox/g450_pll.c --- devel/drivers/video/matrox/g450_pll.c~matroxfb-fix-dvi-setup-to-be-more-compatible 2006-04-23 22:29:02.000000000 -0700 +++ devel-akpm/drivers/video/matrox/g450_pll.c 2006-04-23 22:29:02.000000000 -0700 @@ -316,14 +316,24 @@ static int __g450_setclk(WPMINFO unsigne case M_PIXEL_PLL_B: case M_PIXEL_PLL_C: { - u_int8_t tmp; + u_int8_t tmp, xpwrctrl; unsigned long flags; matroxfb_DAC_lock_irqsave(flags); + + xpwrctrl = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL); + matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN); + mga_outb(M_SEQ_INDEX, M_SEQ1); + mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF); tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL); + tmp |= M1064_XPIXCLKCTRL_DIS; if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) { - matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp | M1064_XPIXCLKCTRL_PLL_UP); + tmp |= M1064_XPIXCLKCTRL_PLL_UP; } + matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp); + matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0); + matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl); + matroxfb_DAC_unlock_irqrestore(flags); } { @@ -418,6 +428,15 @@ static int __g450_setclk(WPMINFO unsigne frequency to higher - with <= lowest wins, while with < highest one wins */ if (delta <= deltaarray[idx-1]) { + /* all else being equal except VCO, + * choose VCO not near (within 1/16th or so) VCOmin + * (freqs near VCOmin aren't as stable) + */ + if (delta == deltaarray[idx-1] + && vco != g450_mnp2vco(PMINFO mnparray[idx-1]) + && vco < (pi->vcomin * 17 / 16)) { + break; + } mnparray[idx] = mnparray[idx-1]; deltaarray[idx] = deltaarray[idx-1]; } else { diff -puN drivers/video/matrox/matroxfb_base.h~matroxfb-fix-dvi-setup-to-be-more-compatible drivers/video/matrox/matroxfb_base.h --- devel/drivers/video/matrox/matroxfb_base.h~matroxfb-fix-dvi-setup-to-be-more-compatible 2006-04-23 22:29:02.000000000 -0700 +++ devel-akpm/drivers/video/matrox/matroxfb_base.h 2006-04-23 22:29:02.000000000 -0700 @@ -672,6 +672,8 @@ void matroxfb_unregister_driver(struct m #define M_SEQ_INDEX 0x1FC4 #define M_SEQ_DATA 0x1FC5 +#define M_SEQ1 0x01 +#define M_SEQ1_SCROFF 0x20 #define M_MISC_REG_READ 0x1FCC diff -puN drivers/video/matrox/matroxfb_DAC1064.h~matroxfb-fix-dvi-setup-to-be-more-compatible drivers/video/matrox/matroxfb_DAC1064.h --- devel/drivers/video/matrox/matroxfb_DAC1064.h~matroxfb-fix-dvi-setup-to-be-more-compatible 2006-04-23 22:29:02.000000000 -0700 +++ devel-akpm/drivers/video/matrox/matroxfb_DAC1064.h 2006-04-23 22:29:02.000000000 -0700 @@ -40,6 +40,7 @@ void DAC1064_global_restore(WPMINFO2); #define M1064_XCURCOL1RED 0x0C #define M1064_XCURCOL1GREEN 0x0D #define M1064_XCURCOL1BLUE 0x0E +#define M1064_XDVICLKCTRL 0x0F #define M1064_XCURCOL2RED 0x10 #define M1064_XCURCOL2GREEN 0x11 #define M1064_XCURCOL2BLUE 0x12 @@ -144,6 +145,7 @@ void DAC1064_global_restore(WPMINFO2); #define M1064_XVIDPLLN 0x8F #define M1064_XPWRCTRL 0xA0 +#define M1064_XPWRCTRL_PANELPDN 0x04 #define M1064_XPANMODE 0xA2 _