summaryrefslogtreecommitdiff
path: root/src/radeon_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/radeon_crtc.c')
-rw-r--r--src/radeon_crtc.c73
1 files changed, 44 insertions, 29 deletions
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index 611c9abe..d2271b05 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -620,25 +620,22 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
}
-/* Compute n/d with rounding */
static int RADEONDiv(int n, int d)
{
return (n + (d / 2)) / d;
}
-static CARD32 RADEONDiv64(CARD64 n, CARD32 d)
-{
- return (n + (d / 2)) / d;
-}
-
-void
+static void
RADEONComputePLL(RADEONPLLPtr pll,
unsigned long freq,
CARD32 *chosen_dot_clock_freq,
CARD32 *chosen_feedback_div,
CARD32 *chosen_reference_div,
- CARD32 *chosen_post_div)
+ CARD32 *chosen_post_div,
+ int flags)
{
+ 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;
@@ -648,37 +645,45 @@ RADEONComputePLL(RADEONPLLPtr pll,
CARD32 best_vco_diff = 1;
CARD32 post_div;
+ 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 (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
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->pll_out_min || vco > pll->pll_out_max)
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;
@@ -705,7 +710,8 @@ RADEONComputePLL(RADEONPLLPtr pll,
/* Define PLL registers for requested video mode */
static void
RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
- RADEONPLLPtr pll, DisplayModePtr mode)
+ RADEONPLLPtr pll, DisplayModePtr mode,
+ int flags)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
CARD32 feedback_div = 0;
@@ -733,16 +739,15 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
{ 0, 0 }
};
- RADEONComputePLL(pll, mode->Clock * 1000, &freq, &feedback_div, &reference_div, &post_divider);
-#if 0
- if (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;
}
-#endif
+
+ 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)
@@ -754,7 +759,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;
@@ -786,7 +791,8 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
/* Define PLL2 registers for requested video mode */
static void
RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
- RADEONPLLPtr pll, DisplayModePtr mode)
+ RADEONPLLPtr pll, DisplayModePtr mode,
+ int flags)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
CARD32 feedback_div = 0;
@@ -813,7 +819,14 @@ RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
{ 0, 0 }
};
- RADEONComputePLL(pll, mode->Clock * 1000, &freq, &feedback_div, &reference_div, &post_divider);
+ 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, &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)
@@ -825,7 +838,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;
@@ -879,8 +892,8 @@ legacy_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;
+ double dot_clock = 0;
+ int pll_flags = 0;
Bool update_tv_routing = FALSE;
@@ -905,7 +918,9 @@ legacy_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)
+ pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV);
}
}
@@ -927,7 +942,7 @@ legacy_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);
+ 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;
@@ -941,7 +956,7 @@ legacy_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);
+ RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, adjusted_mode, pll_flags);
}
break;
}