[PATCH] xf86-video-mga: set the pan_ctl register

Mikulas Patocka mpatocka at redhat.com
Fri Jan 17 13:04:26 PST 2014


Hi

Here I'm sending a patch for Matrox driver in Xorg. It sets the pan_ctl 
register just like Linux framebuffer driver.


Other unrelated problems with the driver:

* most videomodes (such as 640x480) are double-scan if no modeline is 
  provided. This looks really bad on DVI - the monitor doesn't know that 
  it's doublescan, so the image is twice higher. Is there any way to tell 
  the Xorg to prefer single-scan videomodes?


* The Matrox G450 and G550 cards have analog output with up to 360MHz 
  pixel clock, it supports resolutions up to 2048x1536. However, the 
  digital output pixel clock is limited to about 132MHz. According to 
  official specification, the digital resolution is limited to 1280x1024; 
  it can do 1920x1080, but only with a custom modeline that minimizes 
  blank times to keep the pixel clock down.


  The problem is that when the user connects 1920x1080 monitor using the 
  DVI cable, Xorg selects the resolution 1920x1080 with some built-in 
  modeline and the result is blank screen because the dot clock is above 
  132MHz. It can be overriden in xorg.conf, but most users don't have 
  knowledge how to edit xorg.conf.


  Is it possible to somehow detect that the digital output is being used 
  (possibly with DDC) and restrict the dot clock for the driver?

  Alternative solution - as modes bigger than 1280x1024 may work (if 
  the user uses VGA cable) or may not work (if the user uses DVI cable) - 
  they shouldn't be selected by default. Does Xorg have some facility 
  where the driver could allow modes up to 2048x1536, but restrict that 
  the default mode is not bigger than 1280x1024?


Mikulas

-

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.

---
 src/mga.h      |    1 +
 src/mga_dacG.c |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

Index: xf86-video-mga-1.6.3/src/mga.h
===================================================================
--- xf86-video-mga-1.6.3.orig/src/mga.h	2013-12-05 02:16:12.000000000 +0100
+++ xf86-video-mga-1.6.3/src/mga.h	2014-01-10 20:20:37.836840650 +0100
@@ -218,6 +218,7 @@ typedef struct {
     CARD32		Option2;
     CARD32		Option3;
     long                Clock;
+    unsigned char	Pan_Ctl;
     Bool                PIXPLLCSaved;
     unsigned char       PllM;
     unsigned char       PllN;
Index: xf86-video-mga-1.6.3/src/mga_dacG.c
===================================================================
--- xf86-video-mga-1.6.3.orig/src/mga_dacG.c	2012-07-02 13:07:53.000000000 +0200
+++ xf86-video-mga-1.6.3/src/mga_dacG.c	2014-01-10 20:20:37.843506354 +0100
@@ -849,6 +849,43 @@ MGAGSetPCLK( ScrnInfoPtr pScrn, long f_o
 
 	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 vg
 	 * VESA modes (s.o.). MATROX: hint, hint.
 	 */
 	if (MGAISGx50(pMga)) {
+	    mgaReg->Pan_Ctl = inMGAdac(MGA1064_PAN_CTL);
 	    mgaReg->Clock = MGAG450SavePLLFreq(pScrn);
 	}
 


More information about the xorg-devel mailing list