summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alex@t41p.hsd1.va.comcast.net>2007-12-17 18:04:05 -0500
committerAlex Deucher <alex@t41p.hsd1.va.comcast.net>2007-12-17 18:04:05 -0500
commit9f1d8220315c8894a17f2cc328025dc682b0c6e0 (patch)
treee8a443188e022f01aa43d6b9be283dd96be8029d
parent4747c1f3cd4167b6a51d4864a297719ea48b9346 (diff)
RADEON: more PLL fixes
- reduce the calculation accuracy - certain LVDS panels seem to only like certain ref_divs - add pll flags to handle special cases - adjust the pll limits on legacy cards
-rw-r--r--src/radeon.h4
-rw-r--r--src/radeon_crtc.c58
-rw-r--r--src/radeon_driver.c2
3 files changed, 39 insertions, 25 deletions
diff --git a/src/radeon.h b/src/radeon.h
index 960266e..67315a2 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -366,6 +366,10 @@ typedef struct {
} RADEONSaveRec, *RADEONSavePtr;
+#define RADEON_PLL_USE_BIOS_DIVS (1 << 0)
+#define RADEON_PLL_NO_ODD_POST_DIV (1 << 1)
+#define RADEON_PLL_USE_REF_DIV (1 << 2)
+
typedef struct {
CARD16 reference_freq;
CARD16 reference_div;
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index ebb8c52..41375da 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -606,7 +606,7 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
}
-static CARD32 RADEONDiv64(CARD64 n, CARD32 d)
+static int RADEONDiv(int n, int d)
{
return (n + (d / 2)) / d;
}
@@ -617,12 +617,15 @@ RADEONComputePLL(RADEONPLLPtr pll,
CARD32 *chosen_dot_clock_freq,
CARD32 *chosen_feedback_div,
CARD32 *chosen_reference_div,
- CARD32 *chosen_post_div)
+ CARD32 *chosen_post_div,
+ int flags)
{
int post_divs[] = {1, 2, 4, 8, 3, 6, 12, 0};
int i;
+ CARD32 min_ref_div = pll->min_ref_div;
+ CARD32 max_ref_div = pll->max_ref_div;
CARD32 best_vco = pll->best_vco;
CARD32 best_post_div = 1;
CARD32 best_ref_div = 1;
@@ -631,38 +634,46 @@ RADEONComputePLL(RADEONPLLPtr pll,
CARD32 best_error = 0xffffffff;
CARD32 best_vco_diff = 1;
+ freq = freq / 10;
+
ErrorF("freq: %lu\n", freq);
+ if (flags & RADEON_PLL_USE_REF_DIV)
+ min_ref_div = max_ref_div = pll->reference_div;
+
for (i = 0; post_divs[i]; i++) {
int post_div = post_divs[i];
CARD32 ref_div;
- CARD32 vco = (freq / 10000) * post_div;
+ CARD32 vco = freq * post_div;
+
+ if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+ continue;
if (vco < pll->min_pll_freq || vco > pll->max_pll_freq)
continue;
- for (ref_div = pll->min_ref_div; ref_div <= pll->max_ref_div; ++ref_div) {
+ for (ref_div = min_ref_div; ref_div <= max_ref_div; ++ref_div) {
CARD32 feedback_div, current_freq, error, vco_diff;
CARD32 pll_in = pll->reference_freq / ref_div;
if (pll_in < pll->pll_in_min || pll_in > pll->pll_in_max)
continue;
- feedback_div = RADEONDiv64((CARD64)freq * ref_div * post_div,
- pll->reference_freq * 10000);
+ feedback_div = RADEONDiv(freq * ref_div * post_div,
+ pll->reference_freq);
if (feedback_div < pll->min_feedback_div || feedback_div > pll->max_feedback_div)
continue;
- current_freq = RADEONDiv64((CARD64)pll->reference_freq * 10000 * feedback_div,
- ref_div * post_div);
+ current_freq = RADEONDiv(pll->reference_freq * feedback_div,
+ ref_div * post_div);
error = abs(current_freq - freq);
vco_diff = abs(vco - best_vco);
if ((best_vco == 0 && error < best_error) ||
(best_vco != 0 &&
- (error < best_error - 100 ||
+ (error < best_error - 1000 ||
(abs(error - best_error) < 100 && vco_diff < best_vco_diff )))) {
best_post_div = post_div;
best_ref_div = ref_div;
@@ -690,7 +701,7 @@ RADEONComputePLL(RADEONPLLPtr pll,
static void
RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
RADEONPLLPtr pll, DisplayModePtr mode,
- Bool UseBiosDividers)
+ int flags)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
CARD32 feedback_div = 0;
@@ -719,14 +730,14 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
};
- if (UseBiosDividers && info->UseBiosDividers) {
+ if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
save->ppll_ref_div = info->RefDivider;
save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16);
save->htotal_cntl = 0;
return;
}
- RADEONComputePLL(pll, mode->Clock * 1000, &freq, &feedback_div, &reference_div, &post_divider);
+ RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
if (post_div->divider == post_divider)
@@ -738,7 +749,7 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
post_div = &post_divs[0];
}
- save->dot_clock_freq = freq / 10000;
+ save->dot_clock_freq = freq;
save->feedback_div = feedback_div;
save->reference_div = reference_div;
save->post_div = post_divider;
@@ -772,7 +783,7 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
static void
RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
RADEONPLLPtr pll, DisplayModePtr mode,
- Bool UseBiosDividers)
+ int flags)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
CARD32 feedback_div = 0;
@@ -799,14 +810,14 @@ RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
{ 0, 0 }
};
- if (UseBiosDividers && info->UseBiosDividers) {
+ if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
save->p2pll_ref_div = info->RefDivider;
save->p2pll_div_0 = info->FeedbackDivider | (info->PostDivider << 16);
save->htotal_cntl2 = 0;
return;
}
- RADEONComputePLL(pll, mode->Clock * 1000, &freq, &feedback_div, &reference_div, &post_divider);
+ RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
if (post_div->divider == post_divider)
@@ -818,7 +829,7 @@ RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
post_div = &post_divs[0];
}
- save->dot_clock_freq_2 = freq / 10000;
+ save->dot_clock_freq_2 = freq;
save->feedback_div_2 = feedback_div;
save->reference_div_2 = reference_div;
save->post_div_2 = post_divider;
@@ -873,9 +884,8 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
RADEONInfoPtr info = RADEONPTR(pScrn);
Bool tilingOld = info->tilingEnabled;
int i = 0;
- double dot_clock = 0;
- Bool no_odd_post_div = FALSE;
- Bool use_bios_dividers = FALSE;
+ double dot_clock = 0;
+ int pll_flags = 0;
Bool update_tv_routing = FALSE;
@@ -900,9 +910,9 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
if (output->crtc == crtc) {
if (radeon_output->MonType != MT_CRT)
- no_odd_post_div = TRUE;
+ pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
if (radeon_output->MonType == MT_LCD)
- use_bios_dividers = TRUE;
+ pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV);
}
}
@@ -924,7 +934,7 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
dot_clock = adjusted_mode->Clock / 1000.0;
if (dot_clock) {
ErrorF("init pll1\n");
- RADEONInitPLLRegisters(pScrn, &info->ModeReg, &info->pll, adjusted_mode, use_bios_dividers);
+ RADEONInitPLLRegisters(pScrn, &info->ModeReg, &info->pll, adjusted_mode, pll_flags);
} else {
info->ModeReg.ppll_ref_div = info->SavedReg.ppll_ref_div;
info->ModeReg.ppll_div_3 = info->SavedReg.ppll_div_3;
@@ -938,7 +948,7 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
dot_clock = adjusted_mode->Clock / 1000.0;
if (dot_clock) {
ErrorF("init pll2\n");
- RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, adjusted_mode, use_bios_dividers);
+ RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, adjusted_mode, pll_flags);
}
break;
}
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 55752d1..25b2119 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1069,7 +1069,7 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
pll->min_feedback_div = 4;
pll->max_feedback_div = 0x7ff;
pll->pll_in_min = 40;
- pll->pll_in_max = 100;
+ pll->pll_in_max = 500;
pll->best_vco = 0;
xf86DrvMsg (pScrn->scrnIndex, X_INFO,