From c70eb90bc037a7272a98ae7f030f7bcc8fab6315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 28 Mar 2014 18:55:10 +0100 Subject: [PATCH] drm/radeon: try to find better post dividers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_display.c | 58 +++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index fbd8b93..b63188f 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -821,40 +821,50 @@ static void avivo_get_fb_div(struct radeon_pll *pll, static u32 avivo_get_post_div(struct radeon_pll *pll, u32 target_clock) { - u32 vco, post_div, tmp; + unsigned vco_min, vco_max; + unsigned pd_min, pd_max; + unsigned diff_best = ~0; + u32 post_div, post_div_best; if (pll->flags & RADEON_PLL_USE_POST_DIV) return pll->post_div; - if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { - if (pll->flags & RADEON_PLL_IS_LCD) - vco = pll->lcd_pll_out_min; - else - vco = pll->pll_out_min; + if (pll->flags & RADEON_PLL_IS_LCD) { + vco_min = pll->lcd_pll_out_min; + vco_max = pll->lcd_pll_out_max; } else { - if (pll->flags & RADEON_PLL_IS_LCD) - vco = pll->lcd_pll_out_max; - else - vco = pll->pll_out_max; + vco_min = pll->pll_out_min; + vco_max = pll->pll_out_max; } - post_div = vco / target_clock; - tmp = vco % target_clock; + pd_min = vco_min / target_clock; + if ((target_clock * pd_min) < vco_min) + ++pd_min; + if (pd_min < pll->min_post_div) + pd_min = pll->min_post_div; - if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { - if (tmp) - post_div++; - } else { - if (!tmp) - post_div--; - } + pd_max = vco_max / target_clock; + if ((target_clock * pd_max) > vco_max) + ++pd_max; + if (pd_max > pll->max_post_div) + pd_max = pll->max_post_div; - if (post_div > pll->max_post_div) - post_div = pll->max_post_div; - else if (post_div < pll->min_post_div) - post_div = pll->min_post_div; + if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) + post_div_best = pd_min; + else + post_div_best = pd_max; + + for (post_div = pd_min; post_div <= pd_max; ++post_div) { + u32 tmp = target_clock / post_div; + u32 diff = abs(target_clock - tmp * post_div); + if (diff < diff_best || (diff == diff_best && + !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) { + post_div_best = post_div; + diff_best = diff; + } + } - return post_div; + return post_div_best; } #define MAX_TOLERANCE 10 -- 1.9.1