diff options
Diffstat (limited to 'src/radeon_crtc.c')
-rw-r--r-- | src/radeon_crtc.c | 73 |
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; } |