diff options
author | Eric Anholt <anholt@FreeBSD.org> | 2006-04-24 17:23:06 -0700 |
---|---|---|
committer | Eric Anholt <anholt@FreeBSD.org> | 2006-04-24 17:23:06 -0700 |
commit | 7c5495d0903a50af7eb9908aec2af0ed6f83340a (patch) | |
tree | ed5966f02532907537937c8e0795be563336687e | |
parent | a555e28e5afc81969ef7b28482e654cc26b3a446 (diff) |
Try to choose the right SDVO clock rate multiplier for the mode, so we staymodesetting-sdvo-stuffing
within the appropriate bus limits. This currently causes me to fail to sync
with my DVI output.
-rw-r--r-- | src/i830_display.c | 28 | ||||
-rw-r--r-- | src/i830_sdvo.c | 20 |
2 files changed, 42 insertions, 6 deletions
diff --git a/src/i830_display.c b/src/i830_display.c index 95fa936d..72866510 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -257,7 +257,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; CARD32 pipesrc, dspsize, adpa, sdvoc = 0; Bool ok, is_sdvo; - int refclk, pixel_clock; + int refclk, pixel_clock, sdvo_mult; int outputs; ErrorF("Requested pix clock: %d\n", pMode->Clock); @@ -353,6 +353,24 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) return FALSE; } + /* Find the multiplier for SDVO to keep the bus's clock rate (10 times the + * pixel rate) between 1.0Ghz and 2.0Ghz. One doc says the multiplier is + * 1 <= mult <= 5, the other says 1, 2, or 4. Be conservative. + */ + for (sdvo_mult = 1; sdvo_mult <= 4; sdvo_mult *= 2) { + if (pixel_clock * sdvo_mult >= 100000 && + pixel_clock * sdvo_mult <= 200000) + { + break; + } + } + if (sdvo_mult > 4 && is_sdvo) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't find port multiplier for SDVO with clock %d\n", + pixel_clock); + } + ErrorF("mult %d\n", sdvo_mult); + dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; if (IS_I9XX(pI830)) { if (outputs & PIPE_LCD_ACTIVE) @@ -384,7 +402,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= PLL_REF_INPUT_TVCLKINBC; else dpll |= PLL_REF_INPUT_DREFCLK; - dpll |= SDVO_DEFAULT_MULTIPLIER; if (is_sdvo) { dpll |= DPLL_DVO_HIGH_SPEED; @@ -397,6 +414,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) sdvoc |= SDVO_PIPE_B_SELECT; // sdvoc |= SDVO_PHASE_SELECT_DEFAULT; sdvoc |= SDVO_BORDER_ENABLE; + + if (IS_I915G(pI830) || IS_I915GM(pI830)) { + sdvoc |= 1 << (23 + sdvo_mult - 1); + } else { + dpll |= 1 << (4 + sdvo_mult - 1); + } + OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE); } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 99cdc6ac..5f2d37e3 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -477,6 +477,7 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) CARD8 c17a[8]; CARD16 out_timings[6]; CARD16 clock_min, clock_max; + int mult; /* do some mode translations */ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; @@ -536,10 +537,21 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4], out_timings[5]); - /*if (mode->PrivFlags & I830_MFLAG_DOUBLE) - I830SDVOSetClockRateMult(s, 0x02); - else */ - I830SDVOSetClockRateMult(s, 0x01); + for (mult = 1; mult <= 4; mult *= 2) { + if (mode->Clock * mult >= 100000 && mode->Clock * mult <= 200000) + break; + } + switch (mult) { + case 1: + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_1X); + break; + case 2: + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_2X); + break; + case 4: + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_4X); + break; + } return TRUE; } |