diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2009-06-10 18:49:32 -0700 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2009-06-10 22:32:45 -0700 |
commit | 36eb96854b34bee6b65a2b2d4df25f53b47194e4 (patch) | |
tree | 16c8d7b38d443307e6278a1d8acd2ea2aec8f626 | |
parent | 23ca1b0d4324ae65a0c2a39cc877d318063988b1 (diff) |
New chip support.
Part of the G80DispPreInit change suggested by <shenyn321@hotmail.com>.
-rw-r--r-- | src/g80_display.c | 93 | ||||
-rw-r--r-- | src/g80_output.c | 23 | ||||
-rw-r--r-- | src/g80_type.h | 2 | ||||
-rw-r--r-- | src/nv_driver.c | 2 |
4 files changed, 105 insertions, 15 deletions
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; } |