xf86-video-nv: src/g80_display.c src/g80_output.c src/g80_type.h src/nv_driver.c

Aaron Plattner aplattner at kemper.freedesktop.org
Thu Jun 11 15:35:00 PDT 2009


 src/g80_display.c |   93 +++++++++++++++++++++++++++++++++++++++++++++++-------
 src/g80_output.c  |   23 +++++++++++--
 src/g80_type.h    |    2 -
 src/nv_driver.c   |    2 +
 4 files changed, 105 insertions(+), 15 deletions(-)

New commits:
commit 36eb96854b34bee6b65a2b2d4df25f53b47194e4
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Wed Jun 10 18:49:32 2009 -0700

    New chip support.
    
    Part of the G80DispPreInit change suggested by <shenyn321 at hotmail.com>.

diff --git a/src/g80_display.c b/src/g80_display.c
index cf4631d..1b1efe9 100644
--- a/src/g80_display.c
+++ b/src/g80_display.c
@@ -146,26 +146,95 @@ G80CalcPLL(float pclk, int *pNA, int *pMA, int *pNB, int *pMB, int *pP)
 }
 
 static void
+G80CalcPLL2(float pclk, int *pN, int *pM, int *pPL)
+{
+    const float refclk = 27000.0f;
+    const int minN = 8, maxN = 255;
+    const int minM = 1, maxM = 255;
+    const int minPL = 1, maxPL = 63;
+    const int minU = 25000, maxU = 50000;
+    const int minVco = 500000;
+    int maxVco = 1000000;
+    int lowPL, highPL, pl;
+    float vco, bestError = FLT_MAX;
+
+    vco = pclk + pclk / 50;
+
+    if(maxVco < vco) maxVco = vco;
+
+    highPL = (maxVco + vco - 1) / pclk;
+    if(highPL > maxPL) highPL = maxPL;
+    if(highPL < minPL) highPL = minPL;
+
+    lowPL = minVco / vco;
+    if(lowPL > maxPL) lowPL = maxPL;
+    if(lowPL < minPL) lowPL = minPL;
+
+    for(pl = highPL; pl >= lowPL; pl--) {
+        int m;
+
+        for(m = minM; m <= maxM; m++) {
+            int n;
+            float freq, error;
+
+            if(refclk / m < minU) break;
+            if(refclk / m > maxU) continue;
+
+            n = rint(pclk * pl * m / refclk);
+            if(n > maxN) break;
+            if(n < minN) continue;
+
+            freq = refclk * (n / (float)m) / pl;
+            error = fabsf(pclk - freq);
+            if(error < bestError) {
+                *pN = n;
+                *pM = m;
+                *pPL = pl;
+                bestError = error;
+            }
+        }
+    }
+}
+
+static void
 G80CrtcSetPClk(xf86CrtcPtr crtc)
 {
     G80Ptr pNv = G80PTR(crtc->scrn);
     G80CrtcPrivPtr pPriv = crtc->driver_private;
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
     const int headOff = 0x800 * pPriv->head;
-    int lo_n, lo_m, hi_n, hi_m, p, i;
-    CARD32 lo = pNv->reg[(0x00614104+headOff)/4];
-    CARD32 hi = pNv->reg[(0x00614108+headOff)/4];
+    int i;
+
+    if(pPriv->pclk == 0)
+        return;
+
+    if(pNv->architecture < 0xa0) {
+        int lo_n, lo_m, hi_n, hi_m, p, i;
+        CARD32 lo = pNv->reg[(0x00614104+headOff)/4];
+        CARD32 hi = pNv->reg[(0x00614108+headOff)/4];
+
+        pNv->reg[(0x00614100+headOff)/4] = 0x10000610;
+        lo &= 0xff00ff00;
+        hi &= 0x8000ff00;
 
-    pNv->reg[(0x00614100+headOff)/4] = 0x10000610;
-    lo &= 0xff00ff00;
-    hi &= 0x8000ff00;
+        G80CalcPLL(pPriv->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p);
 
-    G80CalcPLL(pPriv->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p);
+        lo |= (lo_m << 16) | lo_n;
+        hi |= (p << 28) | (hi_m << 16) | hi_n;
+        pNv->reg[(0x00614104+headOff)/4] = lo;
+        pNv->reg[(0x00614108+headOff)/4] = hi;
+    } else {
+        int n, m, pl;
+        CARD32 r = pNv->reg[(0x00614104+headOff)/4];
+
+        pNv->reg[(0x00614100+headOff)/4] = 0x50000610;
+        r &= 0xffc00000;
 
-    lo |= (lo_m << 16) | lo_n;
-    hi |= (p << 28) | (hi_m << 16) | hi_n;
-    pNv->reg[(0x00614104+headOff)/4] = lo;
-    pNv->reg[(0x00614108+headOff)/4] = hi;
+        G80CalcPLL2(pPriv->pclk, &n, &m, &pl);
+        r |= pl << 16 | m << 8 | n;
+
+        pNv->reg[(0x00614104+headOff)/4] = r;
+    }
     pNv->reg[(0x00614200+headOff)/4] = 0;
 
     for(i = 0; i < xf86_config->num_output; i++) {
@@ -235,6 +304,8 @@ G80DispPreInit(ScrnInfoPtr pScrn)
     pNv->reg[0x006101D8/4] = pNv->reg[0x0061B000/4];
     pNv->reg[0x006101E0/4] = pNv->reg[0x0061C000/4];
     pNv->reg[0x006101E4/4] = pNv->reg[0x0061C800/4];
+    pNv->reg[0x006101E8/4] = pNv->reg[0x0061D000/4];
+    pNv->reg[0x006101EC/4] = pNv->reg[0x0061D800/4];
     pNv->reg[0x0061A004/4] = 0x80550000;
     pNv->reg[0x0061A010/4] = 0x00000001;
     pNv->reg[0x0061A804/4] = 0x80550000;
diff --git a/src/g80_output.c b/src/g80_output.c
index 75bf7ba..b2d8b07 100644
--- a/src/g80_output.c
+++ b/src/g80_output.c
@@ -127,6 +127,11 @@ static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv)
                                "VGA%d: invalid port type %d\n", or, portType);
                     break;
                 }
+                if(port >= G80_NUM_I2C_PORTS) {
+                    xf86DrvMsg(scrnIndex, X_WARNING,
+                               "VGA%d: unrecognized port %d\n", or, port);
+                    break;
+                }
                 if(pNv->i2cMap[port].dac != -1) {
                     xf86DrvMsg(scrnIndex, X_WARNING,
                                "DDC routing table corrupt!  DAC %i -> %i for "
@@ -152,6 +157,11 @@ static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv)
                                "DVI%d: invalid port type %d\n", or, portType);
                     break;
                 }
+                if(port >= G80_NUM_I2C_PORTS) {
+                    xf86DrvMsg(scrnIndex, X_WARNING,
+                               "DVI%d: unrecognized port %d\n", or, port);
+                    break;
+                }
                 if(pNv->i2cMap[port].sor != -1)
                     xf86DrvMsg(scrnIndex, X_WARNING,
                                "DDC routing table corrupt!  SOR %i -> %i for "
@@ -181,6 +191,11 @@ static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv)
                                "LVDS: invalid port type %d\n", portType);
                     break;
                 }
+                if(port >= G80_NUM_I2C_PORTS) {
+                    xf86DrvMsg(scrnIndex, X_WARNING,
+                               "LVDS: unrecognized port %d\n", port);
+                    break;
+                }
                 pNv->lvds.i2cPort = port;
 
                 break;
@@ -217,9 +232,11 @@ fail:
 
 static CARD32 i2cAddr(const int port)
 {
-    const CARD32 base = (port > 3) ? 0x0000E1D4 : 0x0000E138;
-    const CARD32 offset = (port > 3) ? 0x20 : 0x18;
-    return base + port * offset;
+    const CARD32 addrs[G80_NUM_I2C_PORTS] = {
+        0xE138, 0xE150, 0xE168, 0xE180, 0xE254, 0xE274, 0xE764, 0xE780, 0xE79C,
+        0xE7B8
+    };
+    return addrs[port];
 }
 
 static void G80_I2CPutBits(I2CBusPtr b, int clock, int data)
diff --git a/src/g80_type.h b/src/g80_type.h
index 0cebae7..9bb07a4 100644
--- a/src/g80_type.h
+++ b/src/g80_type.h
@@ -7,7 +7,7 @@
 #include <xf86Crtc.h>
 #include <xf86int10.h>
 
-#define G80_NUM_I2C_PORTS 6
+#define G80_NUM_I2C_PORTS 10
 
 typedef enum Head {
     HEAD0 = 0,
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 41840dd..d1f4c24 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -727,6 +727,8 @@ NVIsG80(int chipType)
         case 0x0650:
         case 0x06e0:
         case 0x06f0:
+        case 0x0a60:
+        case 0x0a70:
             return TRUE;
     }
 


More information about the xorg-commit mailing list