summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2014-01-17 16:04:26 -0500
committerDave Airlie <airlied@redhat.com>2014-03-14 10:36:04 +1000
commit62ba63f687d7b99aff7c88ffd2774f15a2471ce0 (patch)
tree230f5d0ce7fbbd8d2e70366983e1f3a7d608d4c9
parentf647727a2c1d4c2a9261c411cd3df71c3c9f0c06 (diff)
xf86-video-mga: set the pan_ctl register
On my Matrox G550 most videomodes in Xorg didn't work. I found out that it works if Xorg pixel clock is similar to the pixel clock set on framebuffer console. Further analysis showed that the Linux framebuffer driver sets the pan_ctl register (the register 0xa2) according to the pixel clock, the Xorg driver doesn't set it. I copied the code to set the pan_ctl register from the Linux kernel to the Xorg driver, and most videomodes in Xorg work. The pan_ctl register is required for both analog and digital output. The pan_ctl register is saved and restored, this is required so that we restore text-mode screen or Linux framebuffer correctly. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/mga.h1
-rw-r--r--src/mga_dacG.c39
2 files changed, 40 insertions, 0 deletions
diff --git a/src/mga.h b/src/mga.h
index 988ba93..5f75d37 100644
--- a/src/mga.h
+++ b/src/mga.h
@@ -218,6 +218,7 @@ typedef struct {
CARD32 Option2;
CARD32 Option3;
long Clock;
+ unsigned char Pan_Ctl;
Bool PIXPLLCSaved;
unsigned char PllM;
unsigned char PllN;
diff --git a/src/mga_dacG.c b/src/mga_dacG.c
index 9a80193..f307488 100644
--- a/src/mga_dacG.c
+++ b/src/mga_dacG.c
@@ -849,6 +849,43 @@ MGAGSetPCLK( ScrnInfoPtr pScrn, long f_out )
if(MGAISGx50(pMga)) {
pReg->Clock = f_out;
+ if (pMga->Chipset == PCI_CHIP_MGAG550) {
+ if (f_out < 45000) {
+ pReg->Pan_Ctl = 0x00;
+ } else if (f_out < 55000) {
+ pReg->Pan_Ctl = 0x08;
+ } else if (f_out < 70000) {
+ pReg->Pan_Ctl = 0x10;
+ } else if (f_out < 85000) {
+ pReg->Pan_Ctl = 0x18;
+ } else if (f_out < 100000) {
+ pReg->Pan_Ctl = 0x20;
+ } else if (f_out < 115000) {
+ pReg->Pan_Ctl = 0x28;
+ } else if (f_out < 125000) {
+ pReg->Pan_Ctl = 0x30;
+ } else {
+ pReg->Pan_Ctl = 0x38;
+ }
+ } else {
+ if (f_out < 45000) {
+ pReg->Pan_Ctl = 0x00;
+ } else if (f_out < 65000) {
+ pReg->Pan_Ctl = 0x08;
+ } else if (f_out < 85000) {
+ pReg->Pan_Ctl = 0x10;
+ } else if (f_out < 105000) {
+ pReg->Pan_Ctl = 0x18;
+ } else if (f_out < 135000) {
+ pReg->Pan_Ctl = 0x20;
+ } else if (f_out < 160000) {
+ pReg->Pan_Ctl = 0x28;
+ } else if (f_out < 175000) {
+ pReg->Pan_Ctl = 0x30;
+ } else {
+ pReg->Pan_Ctl = 0x38;
+ }
+ }
return;
}
@@ -1395,6 +1432,7 @@ MGA_NOT_HAL(
* To test this we check for Clock == 0.
*/
MGAG450SetPLLFreq(pScrn, mgaReg->Clock);
+ outMGAdac(MGA1064_PAN_CTL, mgaReg->Pan_Ctl);
mgaReg->PIXPLLCSaved = FALSE;
}
@@ -1583,6 +1621,7 @@ MGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
* VESA modes (s.o.). MATROX: hint, hint.
*/
if (MGAISGx50(pMga)) {
+ mgaReg->Pan_Ctl = inMGAdac(MGA1064_PAN_CTL);
mgaReg->Clock = MGAG450SavePLLFreq(pScrn);
}