summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@FreeBSD.org>2006-04-24 17:23:06 -0700
committerEric Anholt <anholt@FreeBSD.org>2006-04-24 17:23:06 -0700
commit7c5495d0903a50af7eb9908aec2af0ed6f83340a (patch)
treeed5966f02532907537937c8e0795be563336687e
parenta555e28e5afc81969ef7b28482e654cc26b3a446 (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.c28
-rw-r--r--src/i830_sdvo.c20
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;
}