diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c index f9698f3..c200a9b 100644 --- a/src/atombios_crtc.c +++ b/src/atombios_crtc.c @@ -324,6 +324,12 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode) else pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; + /* some duallink monitors seem to prefer dividers calculated with a wider + * pll range + */ + if (mode->Clock > 200000) + pll_flags |= RADEON_PLL_USE_DEFAULT_OUT_MIN; + for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) { diff --git a/src/radeon.h b/src/radeon.h index 182e946..a077ccc 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -276,6 +276,7 @@ typedef struct { #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) +#define RADEON_PLL_USE_DEFAULT_OUT_MIN (1 << 12) typedef struct { uint16_t reference_freq; diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c index 72fbe21..91aa562 100644 --- a/src/radeon_atombios.c +++ b/src/radeon_atombios.c @@ -2201,17 +2201,12 @@ RADEONGetATOMClockInfo(ScrnInfoPtr pScrn) break; } pll->reference_div = 0; - if (pll->pll_out_min == 0) - pll->pll_out_min = 64800; - - /* limiting the range is a good thing in most cases - * as it limits the number of matching pll combinations, - * however, some duallink DVI monitors seem to prefer combinations that - * would be limited by this. This may need to be revisited - * per chip family. - */ - if (pll->pll_out_min > 64800) - pll->pll_out_min = 64800; + if (pll->pll_out_min == 0) { + if (IS_AVIVO_VARIANT) + pll->pll_out_min = 64800; + else + pll->pll_out_min = 20000; + } return TRUE; } diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c index 3899064..9b353f3 100644 --- a/src/radeon_crtc.c +++ b/src/radeon_crtc.c @@ -144,6 +144,8 @@ RADEONComputePLL(RADEONPLLPtr pll, { uint32_t min_ref_div = pll->min_ref_div; uint32_t max_ref_div = pll->max_ref_div; + uint32_t pll_out_min = pll->pll_out_min; + uint32_t pll_out_max = pll->pll_out_max; uint32_t min_fractional_feed_div = 0; uint32_t max_fractional_feed_div = 0; uint32_t best_vco = pll->best_vco; @@ -179,6 +181,13 @@ RADEONComputePLL(RADEONPLLPtr pll, max_fractional_feed_div = pll->max_frac_feedback_div; } + if (flags & RADEON_PLL_USE_DEFAULT_OUT_MIN) { + if (flags & RADEON_PLL_LEGACY) + pll_out_min = 20000; + else + pll_out_min = 64800; + } + for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) { uint32_t ref_div; @@ -216,10 +225,10 @@ RADEONComputePLL(RADEONPLLPtr pll, tmp = (CARD64)pll->reference_freq * feedback_div; vco = RADEONDiv(tmp, ref_div); - if (vco < pll->pll_out_min) { + if (vco < pll_out_min) { min_feed_div = feedback_div+1; continue; - } else if(vco > pll->pll_out_max) { + } else if(vco > pll_out_max) { max_feed_div = feedback_div; continue; }