diff options
author | Dave Airlie <airlied@linux.ie> | 2006-03-31 17:26:59 +1000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-06-02 10:01:50 +1000 |
commit | 31bdcd0f48bfdc023f58917c68612923738302b1 (patch) | |
tree | 10dc803459fbb2e8a13fd96cf0c7a5320851435e | |
parent | adf7d15da6201955f838f053635fc60219372371 (diff) |
i830: add better pll calculations..
Got some better info on the p1/p2 stuff, so I fixed up the clocks,
all the modes seem to work..
-rw-r--r-- | src/i810_reg.h | 55 | ||||
-rw-r--r-- | src/i830_driver.c | 35 | ||||
-rw-r--r-- | src/i830_i2c.c | 76 | ||||
-rw-r--r-- | src/i830_raw.c | 262 |
4 files changed, 256 insertions, 172 deletions
diff --git a/src/i810_reg.h b/src/i810_reg.h index 74790c00..ef4e360b 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -270,12 +270,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define GPIOE 0x5020 // this is DVO i2C #define GPIOF 0x5024 -#define GMBUS_CLK_PORT_SEL 0x5100 -#define GMBUS_CMD 0x5104 -#define GMBUS_SLAVE_REG_SHIFT 8 -#define GMBUS_DATA_COUNT_SHIFT 16 -#define GMBUS_STATUS 0x5108 -#define GMBUS_DATA 0x510C +#define GMBUS_CLK_PORT_SEL 0x5100 +#define GMBUS_CMD 0x5104 +#define GMBUS_SLAVE_REG_SHIFT 8 +#define GMBUS_DATA_COUNT_SHIFT 16 +#define GMBUS_CYCLE_END_WAIT 1 // 0x42 +#define GMBUS_CYCLE_INDEX_END_WAIT 3 // 0x46 +#define GMBUS_CYCLE_STOP_IF_WAIT 4 // 0x48 +#define GMBUS_CYCLE_STOP 5 // 0x4a +#define GMBUS_CYCLE_INDEX_STOP 7 // 0x4e +#define GMBUS_CYCLE_SEL_SHIFT 25 +#define GMBUS_STATUS 0x5108 +#define GMBUS_DATA 0x510C /* p317, 319 */ @@ -684,6 +690,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DPLL_DIVISOR_SELECT (1 << 24) #define DPLL_P2_MASK 1 #define DPLL_P2_SHIFT 23 +#define DPLL_I9XX_P2_SHIFT 24 #define DPLL_P1_FORCE_DIV2 (1 << 21) #define DPLL_P1_MASK 0x1f #define DPLL_P1_SHIFT 16 @@ -703,42 +710,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FP_M1_DIVISOR_SHIFT 8 #define FP_M2_DIVISOR_SHIFT 0 - -struct pll_min_max { - int min_m, max_m; - int min_m1, max_m1; - int min_m2, max_m2; - int min_n, max_n; - int min_p, max_p; - int min_p1, max_p1; -}; - -/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */ -/* Clock values are in units of kHz */ -#define PLL_REFCLK 48000 - -#define MIN_VCO_FREQ 930000 -#define MAX_VCO_FREQ 1400000 -#define MIN_CLOCK 25000 -#define MAX_CLOCK 350000 -#define P_TRANSITION_CLOCK 165000 - - -#define I9XX_MIN_VCO_FREQ 930000 -#define I9XX_MAX_VCO_FREQ 2800000 -#define I9XX_P_TRANSITION_CLOCK 200000 - -#define CALC_VCLOCK_i8xx(m1, m2, n, p1, p2) \ - ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \ - (((p1) + 2) * (1 << (p2 + 1)))) - -#define CALC_VCLOCK_i9xx(m1, m2, n, p1, p2) \ - ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \ - (((p1)) * (p2 ? 10: 5))) - -#define CALC_VCLOCK3(m, n, p) ((PLL_REFCLK * (m) / (n)) / (p)) - - #define I830_HTOTAL_MASK 0xfff0000 #define I830_HACTIVE_MASK 0x7ff diff --git a/src/i830_driver.c b/src/i830_driver.c index aca8c281..7775f873 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -319,7 +319,6 @@ I830DumpModeDebugInfo(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); CARD32 temp, planeA, planeB; - int p1, p2, m1, m2, n, p, m, clock; planeA = INREG(DSPACNTR); planeB = INREG(DSPBCNTR); #if 1 @@ -373,36 +372,8 @@ I830DumpModeDebugInfo(ScrnInfoPtr pScrn) DR(DSPASIZE); #if 1 - temp = INREG(DPLL_A); - p2 = (temp >> DPLL_P2_SHIFT) & DPLL_P2_MASK; - p1 = (temp >> DPLL_P1_SHIFT) & DPLL_P1_MASK; - - if (IS_I9XX(pI830)) - p = ((p1) * (p2 ? 10 : 5)); - else - p = (p1+2) * ( 1<< (p2 + 1)); - ErrorF("DPLL A is %08X: p1 is %d p2 is %d\n", temp, p1, p2); - temp = INREG(FPA0); - n = (temp >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; - m1 = (temp >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; - m2 = (temp >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; - m = (5 * ((m1) + 2) + ((m2) + 2)); - n += 2; - clock = (((PLL_REFCLK * m) / n) / p); - - ErrorF("FPA0 is %08X N is %d m1 is %d m2 is %d\n", temp, n, m1, m2); - ErrorF("m %d n %d p %d clock %d\n", m, n, p, clock); - - temp = INREG(FPA1); - n = (temp >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; - m1 = (temp >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; - m2 = (temp >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; - m = (5 * ((m1) + 2) + ((m2) + 2)); - n += 2; - clock = ((PLL_REFCLK * m / n) / p); - - ErrorF("FPA1 is %08X N is %d m1 is %d m2 is %d\n", temp, n, m1, m2); - ErrorF("m %d n %d p %d clock %d\n", m, n, p, clock); + I830DumpPLLRegisters(pScrn); +#endif /* Print out some CRTC/display information. */ temp = INREG(HTOTAL_A); ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff, @@ -468,8 +439,6 @@ I830DumpModeDebugInfo(ScrnInfoPtr pScrn) ErrorF("Plane B position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); temp = INREG(DSPBSIZE); ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); - -#endif DR(DPLL_B); DR(FPB0); diff --git a/src/i830_i2c.c b/src/i830_i2c.c index b13e3d4b..1740fd8a 100644 --- a/src/i830_i2c.c +++ b/src/i830_i2c.c @@ -324,10 +324,11 @@ Bool I830I2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite, I2CBusPtr b = d->pI2CBus; ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); - + unsigned int temp; + unsigned int count; /* use the GMBUS protocol. */ - if ((d->pI2CBus->DriverPrivate.uval != 0x5020) || (nWrite > 2)) + if ((d->pI2CBus->DriverPrivate.uval != 0x5020) || (nWrite > 2) || (nRead > 1)) return I2CWriteRead(d, WriteBuffer, nWrite, ReadBuffer, nRead); /* okay use the GMBUS protocol - */ @@ -337,13 +338,13 @@ Bool I830I2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite, if (nWrite==2) { OUTREG(GMBUS_DATA, WriteBuffer[1]); - - gmbus_cmd = 0x4e << 24; + gmbus_cmd = 0x4 << 28; + gmbus_cmd |= GMBUS_CYCLE_INDEX_STOP << GMBUS_CYCLE_SEL_SHIFT; gmbus_cmd |= (d->SlaveAddr & ~1); gmbus_cmd |= (nWrite-1) << GMBUS_DATA_COUNT_SHIFT; gmbus_cmd |= WriteBuffer[0] << GMBUS_SLAVE_REG_SHIFT; - ErrorF("OUTREG(%08X,%08X)\n", GMBUS_CMD, gmbus_cmd); + // ErrorF("OUTREG(%08X,%08X)\n", GMBUS_CMD, gmbus_cmd); OUTREG(GMBUS_CMD, gmbus_cmd); status[0] = status[1] = status[2] = 0; @@ -351,40 +352,63 @@ Bool I830I2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite, i=0; do { status[i%3] = INREG(GMBUS_STATUS); - if ((status[0] == status[1]) && (status[1] == status[2])) + ErrorF("INREG(%08X,%08X)\n", GMBUS_STATUS, status[i%3]); + if ((status[0] & 0x800) && (status[0] == status[1]) && (status[1] == status[2])) break; i++; - } while(1); + // usleep(1); + } while(i<1000); - gmbus_cmd = 0x48 << 24; + gmbus_cmd = 0x4 << 28; + gmbus_cmd |= (GMBUS_CYCLE_STOP_IF_WAIT << GMBUS_CYCLE_SEL_SHIFT); gmbus_cmd |= (d->SlaveAddr & ~1); - ErrorF("OUTREG(%08X,%08X)\n", GMBUS_CMD, gmbus_cmd); + // ErrorF("OUTREG(%08X,%08X)\n", GMBUS_CMD, gmbus_cmd); OUTREG(GMBUS_CMD, gmbus_cmd); } - if (nRead==1) + count = 0; + if (nRead) { - gmbus_cmd = 0x4E << 24; + gmbus_cmd = 0x4 << 28; + if (nRead > 1) + gmbus_cmd |= (GMBUS_CYCLE_STOP << GMBUS_CYCLE_SEL_SHIFT); + else + gmbus_cmd |= (GMBUS_CYCLE_INDEX_STOP << GMBUS_CYCLE_SEL_SHIFT); + gmbus_cmd |= (d->SlaveAddr | 1); gmbus_cmd |= (nRead) << GMBUS_DATA_COUNT_SHIFT; gmbus_cmd |= WriteBuffer[0] << GMBUS_SLAVE_REG_SHIFT; - ErrorF("OUTREG(%08X,%08X)\n", GMBUS_CMD, gmbus_cmd); + // ErrorF("OUTREG(%08X,%08X)\n", GMBUS_CMD, gmbus_cmd); OUTREG(GMBUS_CMD, gmbus_cmd); - status[0] = status[1] = status[2] = 0; - i=0; - do { - status[i%3] = INREG(GMBUS_STATUS); - if ((status[0] == status[1]) && (status[1] == status[2])) - break; - i++; - } while(1); - ReadBuffer[0] = INREG(GMBUS_DATA) & 0xff; - gmbus_cmd = 0x48 << 24; - gmbus_cmd |= (d->SlaveAddr & ~1); - ErrorF("OUTREG(%08X,%08X)\n", GMBUS_CMD, gmbus_cmd); - OUTREG(GMBUS_CMD, gmbus_cmd); + while (count < nRead) { + + // GET STATUS REG + status[0] = status[1] = status[2] = 0; + i=0; + do { + status[i%3] = INREG(GMBUS_STATUS); + if ((status[0] == status[1]) && (status[1] == status[2])) + break; + i++; + } while(i<1000); + + if ((status & 0x800) && !((status & 0xFF) % 4)) + { + temp = INREG(GMBUS_DATA); + ReadBuffer[count] = temp & 0xff; + ReadBuffer[count+1] = (temp >> 0x8) & 0xff; + ReadBuffer[count+2] = (temp >> 0x16) & 0xff; + ReadBuffer[count+3] = (temp >> 0x24) & 0xff; + + // ErrorF("INREG(%08X) = %08X\n", GMBUS_DATA, temp); + + gmbus_cmd = 0x4 << 28; + gmbus_cmd |= (GMBUS_CYCLE_STOP_IF_WAIT << GMBUS_CYCLE_SEL_SHIFT); + gmbus_cmd |= (d->SlaveAddr & ~1); + // ErrorF("OUTREG(%08X,%08X)\n", GMBUS_CMD, gmbus_cmd); + OUTREG(GMBUS_CMD, gmbus_cmd); } return TRUE; } @@ -410,7 +434,7 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) pI2CBus->I2CStop = I830I2CStop; pI2CBus->I2CAddress = I830I2CAddress; pI2CBus->DriverPrivate.uval = i2c_reg; - // pI2CBus->I2CWriteRead = I830I2CWriteRead; + //pI2CBus->I2CWriteRead = I830I2CWriteRead; if (!xf86I2CBusInit(pI2CBus)) return FALSE; *bus_ptr = pI2CBus; diff --git a/src/i830_raw.c b/src/i830_raw.c index f108a572..90d35014 100644 --- a/src/i830_raw.c +++ b/src/i830_raw.c @@ -64,21 +64,83 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define PLLS_I9xx 1 #define PLLS_MAX 2 -struct pll_min_max plls[PLLS_MAX] = { - { 108, 140, 18, 26, 6, 16, 3, 16, 4, 128, 0, 31 }, //I8xx - { 75, 120, 10, 20, 5, 9, 4, 7, 5, 80, 1, 8 } //I9xx +struct pll_min_max { + int min_m, max_m; + int min_m1, max_m1; + int min_m2, max_m2; + int min_n, max_n; + int min_p, max_p; + int min_p1, max_p1; + int min_vco, max_vco; + int min_clk, max_clk; + int p_transition_clk, ref_clk; }; +/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */ +/* Clock values are in units of kHz */ + +static struct pll_min_max plls[PLLS_MAX] = { + { 108, 140, + 18, 26, + 6, 16, + 3, 16, + 4, 128, + 0, 31, + 930000, 1400000, + 25000, 350000, + 165000, 48000 + }, //I8xx + + { 75, 120, + 10, 20, + 5, 9, + 4, 7, + 5, 80, + 1, 8, + 930000, 2800000, + 25000, 350000, + 200000, 96000 + } //I9xx +}; + +static CARD32 calc_vclock(CARD32 index, CARD32 m1, CARD32 m2, CARD32 n, CARD32 p1, CARD32 p2) +{ + struct pll_min_max *pll = &plls[index]; + CARD32 m; + CARD32 vco; + CARD32 p; + + m = ( 5 * (m1 + 2) ) + ( m2 + 2 ); + n += 2; + vco = pll->ref_clk * m / n; + + if (index == PLLS_I8xx) { + p = ((p1 + 2) * (1 << (p2 + 1))); + } else { + p = ((p1) * (p2 ? 5 : 10)); + } + return vco / p; +} + +static CARD32 calc_vclock3(CARD32 index, CARD32 m, CARD32 n, CARD32 p) +{ + struct pll_min_max *pll = &plls[index]; + + return pll->ref_clk * m / n / p; +} + /* Split the M parameter into M1 and M2. */ static int splitm(int index, unsigned int m, CARD32 *retm1, CARD32 *retm2) { int m1, m2; int testm; + struct pll_min_max *pll = &plls[index]; + /* no point optimising too much - brute force m */ - for (m1 = plls[index].min_m1; m1 < plls[index].max_m1+1; m1++) + for (m1 = pll->min_m1; m1 < pll->max_m1+1; m1++) { - for (m2 = plls[index].min_m2; m2 < plls[index].max_m2+1; m2++) + for (m2 = pll->min_m2; m2 < pll->max_m2+1; m2++) { testm = ( 5 * ( m1 + 2 )) + (m2 + 2); if (testm == m) @@ -98,28 +160,17 @@ static int splitp(int index, unsigned int p, CARD32 *retp1, CARD32 *retp2) { int p1, p2; - + struct pll_min_max *pll = &plls[index]; /* deal with i9xx plls first - incomplete but mostly working */ if (index == PLLS_I9xx) { - switch (p) { - case 10: - p1 = 2; - p2 = 0; - break; - case 20: - p1 = 1; - p2 = 0; - break; - default: - p1 = (p / 10) + 1; - p2 = 0; - break; - } - - *retp1 = (unsigned int)p1; - *retp2 = (unsigned int)p2; - return 0; + p2 = 0; // for now + + p1 = p / (p2 ? 5 : 10); + + *retp1 = (unsigned int)p1; + *retp2 = (unsigned int)p2; + return 0; } if (p % 4 == 0) @@ -127,11 +178,11 @@ splitp(int index, unsigned int p, CARD32 *retp1, CARD32 *retp2) else p2 = 0; p1 = (p / (1 << (p2 + 1))) - 2; - if (p % 4 == 0 && p1 < plls[index].min_p1) { + if (p % 4 == 0 && p1 < pll->min_p1) { p2 = 0; p1 = (p / (1 << (p2 + 1))) - 2; } - if (p1 < plls[index].min_p1 || p1 > plls[index].max_p1 || (p1 + 2) * (1 << (p2 + 1)) != p) { + if (p1 < pll->min_p1 || p1 > pll->max_p1 || (p1 + 2) * (1 << (p2 + 1)) != p) { return 1; } else { *retp1 = (unsigned int)p1; @@ -152,6 +203,7 @@ i9xx_calc_pll_params(int index, int clock, CARD32 n_best = 0, m_best = 0, f_best, f_err; CARD32 p_min, p_max, p_inc, div_min, div_max; int ret; + struct pll_min_max *pll = &plls[index]; /* Accept 0.5% difference, but aim for 0.1% */ err_max = 5 * clock / 1000; @@ -159,29 +211,23 @@ i9xx_calc_pll_params(int index, int clock, DPRINTF(PFX, "Clock is %d\n", clock); - div_max = I9XX_MAX_VCO_FREQ / clock; + div_max = pll->max_vco / clock; // div_min = ROUND_UP_TO(I9XX_MIN_VCO_FREQ, clock) / clock; div_min = 5; - if (clock <= I9XX_P_TRANSITION_CLOCK) + if (clock <= pll->p_transition_clk) p_inc = 10; else p_inc = 5; p_min = ROUND_UP_TO(div_min, p_inc); p_max = ROUND_DOWN_TO(div_max, p_inc); - if (p_min < plls[index].min_p) - p_min = plls[index].min_p; - if (p_max > plls[index].max_p) - p_max = plls[index].max_p; + if (p_min < pll->min_p) + p_min = pll->min_p; + if (p_max > pll->max_p) + p_max = pll->max_p; - if (clock < PLL_REFCLK) + if (clock < pll->ref_clk) { - p_min = 10; - p_max = 20; *flags |= I830_MFLAG_DOUBLE; - /* this makes 640x480 work it really shouldn't - - SOMEONE WITHOUT DOCS WOZ HERE */ - if (clock < 30000) - clock *= 4; } DPRINTF(PFX, "p range is %d-%d (%d)\n", p_min, p_max, p_inc); @@ -195,18 +241,18 @@ i9xx_calc_pll_params(int index, int clock, p += p_inc; continue; } - n = plls[index].min_n; + n = pll->min_n; f_vco = clock * p; do { - m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK; + m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk; fprintf(stderr,"trying m %d n %d\n", m, n); - if (m < plls[index].min_m) - m = plls[index].min_m + 1; - if (m > plls[index].max_m) - m = plls[index].max_m - 1; + if (m < pll->min_m) + m = pll->min_m + 1; + if (m > pll->max_m) + m = pll->max_m - 1; for (testm = m - 1; testm <= m; testm++) { - f_out = CALC_VCLOCK3(testm, n, p); + f_out = calc_vclock3(index, testm, n, p); if (splitm(index, testm, &m1, &m2)) { DPRINTF(PFX, "cannot split m = %d\n", testm); n++; @@ -226,7 +272,7 @@ i9xx_calc_pll_params(int index, int clock, } } n++; - } while ((n <= plls[index].max_n));//(f_out >= clock)); + } while ((n <= pll->max_n));//(f_out >= clock)); p += p_inc; } while (p <= p_max); @@ -244,14 +290,14 @@ i9xx_calc_pll_params(int index, int clock, DPRINTF(PFX, "m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " "f: %d (%d), VCO: %d\n", m, m1, m2, n, n1, p, p1, p2, - CALC_VCLOCK3(m, n, p), CALC_VCLOCK_i9xx(m1, m2, n1, p1, p2), - CALC_VCLOCK3(m, n, p) * p); + calc_vclock3(index, m, n, p), calc_vclock(index, m1, m2, n1, p1, p2), + calc_vclock3(index, m, n, p) * p); *retm1 = m1; *retm2 = m2; *retn = n1; *retp1 = p1; *retp2 = p2; - *retclock = CALC_VCLOCK_i9xx(m1, m2, n1, p1, p2); + *retclock = calc_vclock(index, m1, m2, n1, p1, p2); return 0; } @@ -266,6 +312,7 @@ calc_pll_params(int index, int clock, CARD32 *retm1, CARD32 *retm2, CARD32 *retn CARD32 n_best = 0, m_best = 0, f_best, f_err; CARD32 p_min, p_max, p_inc, div_min, div_max; int ret; + struct pll_min_max *pll = &plls[index]; /* Accept 0.5% difference, but aim for 0.1% */ err_max = 5 * clock / 1000; @@ -273,19 +320,19 @@ calc_pll_params(int index, int clock, CARD32 *retm1, CARD32 *retm2, CARD32 *retn DPRINTF(PFX, "Clock is %d\n", clock); - div_max = MAX_VCO_FREQ / clock; - div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock; + div_max = pll->max_vco / clock; + div_min = ROUND_UP_TO(pll->min_vco, clock) / clock; - if (clock <= P_TRANSITION_CLOCK) + if (clock <= pll->p_transition_clk) p_inc = 4; else p_inc = 2; p_min = ROUND_UP_TO(div_min, p_inc); p_max = ROUND_DOWN_TO(div_max, p_inc); - if (p_min < plls[index].min_p) - p_min = plls[index].min_p; - if (p_max > plls[index].max_p) - p_max = plls[index].max_p; + if (p_min < pll->min_p) + p_min = pll->min_p; + if (p_max > pll->max_p) + p_max = pll->max_p; DPRINTF(PFX, "p range is %d-%d (%d)\n", p_min, p_max, p_inc); @@ -297,16 +344,16 @@ calc_pll_params(int index, int clock, CARD32 *retm1, CARD32 *retm2, CARD32 *retn p += p_inc; continue; } - n = plls[index].min_n; + n = pll->min_n; f_vco = clock * p; do { - m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK; - if (m < plls[index].min_m) - m = plls[index].min_m; - if (m > plls[index].max_m) - m = plls[index].max_m; - f_out = CALC_VCLOCK3(m, n, p); + m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk; + if (m < pll->min_m) + m = pll->min_m; + if (m > pll->max_m) + m = pll->max_m; + f_out = calc_vclock3(index, m, n, p); if (splitm(index, m, &m1, &m2)) { DPRINTF(PFX, "cannot split m = %d\n", m); n++; @@ -325,7 +372,7 @@ calc_pll_params(int index, int clock, CARD32 *retm1, CARD32 *retm2, CARD32 *retn err_best = f_err; } n++; - } while ((n <= plls[index].max_n) && (f_out >= clock)); + } while ((n <= pll->max_n) && (f_out >= clock)); p += p_inc; } while ((p <= p_max)); @@ -343,14 +390,14 @@ calc_pll_params(int index, int clock, CARD32 *retm1, CARD32 *retm2, CARD32 *retn DPRINTF(PFX, "m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " "f: %d (%d), VCO: %d\n", m, m1, m2, n, n1, p, p1, p2, - CALC_VCLOCK3(m, n, p), CALC_VCLOCK_i8xx(m1, m2, n1, p1, p2), - CALC_VCLOCK3(m, n, p) * p); + calc_vclock3(index, m, n, p), calc_vclock(index, m1, m2, n1, p1, p2), + calc_vclock3(index, m, n, p) * p); *retm1 = m1; *retm2 = m2; *retn = n1; *retp1 = p1; *retp2 = p2; - *retclock = CALC_VCLOCK_i8xx(m1, m2, n1, p1, p2); + *retclock = calc_vclock(index, m1, m2, n1, p1, p2); return 0; } @@ -472,11 +519,21 @@ I830RawSetHw(ScrnInfoPtr pScrn, DisplayModePtr pMode) *dpll &= ~DPLL_P1_FORCE_DIV2; *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) | (DPLL_P1_MASK << DPLL_P1_SHIFT)); - *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); + if (IS_I9XX(pI830)) { - *dpll |= 0x4000000; + CARD32 tmpp1; + + *dpll |= 0x4000000; + *dpll |= p2 << DPLL_I9XX_P2_SHIFT; + + tmpp1 = (1 << (p1 - 1)); + *dpll |= tmpp1 << 16; + } + else + { + *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); } *fp0 = (n << FP_N_DIVISOR_SHIFT) | @@ -933,11 +990,13 @@ I830RawSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) { ret = I830SDVOPostSetMode(pI830->output[i].sdvo_drv, mode); /* if it didn't enable the DFP on the output */ - if (ret==FALSE && (pI830->MonType1 & PIPE_DFP) && retry_count<3) + if ((ret==FALSE) && ((pI830->MonType1 & PIPE_DFP) == PIPE_DFP) && (retry_count<3)) { retry_count++; goto retry; } + else + ret = TRUE; } } if (didLock) @@ -950,3 +1009,64 @@ I830RawSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) } +void I830DumpPLLRegisters(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct pll_min_max *pll; + int p1, p2, m1, m2, n, p, m, clock; + CARD32 temp; + + if (IS_I9XX(pI830)) + pll = &plls[PLLS_I9xx]; + else + pll = &plls[PLLS_I8xx]; + + temp = INREG(DPLL_A); + + if (IS_I9XX(pI830)) { + int tmpp1; + + tmpp1 = (temp >> DPLL_P1_SHIFT) & 0xff; + + switch (tmpp1) + { + case 0x1: p1 = 1; break; + case 0x2: p1 = 2; break; + case 0x4: p1 = 3; break; + case 0x8: p1 = 4; break; + case 0x10: p1 = 5; break; + case 0x20: p1 = 6; break; + case 0x40: p1 = 7; break; + case 0x80: p1 = 8; break; + default: break; + } + p2 = (temp >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK; + p = ((p1) * (p2 ? 5 : 10)); + } else { + p1 = (temp >> DPLL_P1_SHIFT) & DPLL_P1_MASK; + p2 = (temp >> DPLL_P2_SHIFT) & DPLL_P2_MASK; + p = (p1+2) * ( 1<< (p2 + 1)); + } + + ErrorF("DPLL A is %08X: p1 is %d p2 is %d p is %d\n", temp, p1, p2, p); + temp = INREG(FPA0); + n = (temp >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; + m1 = (temp >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; + m2 = (temp >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; + m = (5 * ((m1) + 2) + ((m2) + 2)); + n += 2; + clock = (((pll->ref_clk * m) / n) / p); + + ErrorF("FPA0 is %08X N is %d m1 is %d m2 is %d\n", temp, n, m1, m2); + ErrorF("m %d n %d p %d clock %d\n", m, n, p, clock); + + temp = INREG(FPA1); + n = (temp >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; + m1 = (temp >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; + m2 = (temp >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; + m = (5 * ((m1) + 2) + ((m2) + 2)); + n += 2; + clock = ((pll->ref_clk * m / n) / p); + + return; +} |