summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/radeon/radeon_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 386cfa4c194d..063d4255137f 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -865,7 +865,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
unsigned post_div_min, post_div_max, post_div;
unsigned ref_div_min, ref_div_max, ref_div;
unsigned post_div_best, diff_best;
- unsigned nom, den, tmp;
+ unsigned nom, den;
/* determine allowed feedback divider range */
fb_div_min = pll->min_feedback_div;
@@ -937,23 +937,27 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
}
post_div = post_div_best;
+ /* limit reference * post divider to a maximum */
+ ref_div_max = min(210 / post_div, ref_div_max);
+
/* get matching reference and feedback divider */
- ref_div = max(den / post_div, 1u);
- fb_div = nom;
+ ref_div = max(DIV_ROUND_CLOSEST(den, post_div), 1u);
+ fb_div = DIV_ROUND_CLOSEST(nom * ref_div * post_div, den);
/* we're almost done, but reference and feedback
divider might be to large now */
- tmp = ref_div;
+ nom = fb_div;
+ den = ref_div;
if (fb_div > fb_div_max) {
- ref_div = ref_div * fb_div_max / fb_div;
+ ref_div = DIV_ROUND_CLOSEST(den * fb_div_max, nom);
fb_div = fb_div_max;
}
if (ref_div > ref_div_max) {
ref_div = ref_div_max;
- fb_div = nom * ref_div_max / tmp;
+ fb_div = DIV_ROUND_CLOSEST(nom * ref_div_max, den);
}
/* reduce the numbers to a simpler ratio once more */