blob: 6a65325a3bffb60b369d170014f33112e4aa0802 [file] [log] [blame]
From ce094de5b4d0ce7a33f290b33f504c3ef92c575f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Tue, 24 Sep 2013 21:26:20 +0300
Subject: drm/i915: Make vlv_find_best_dpll() ppm calculation safe
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use div_u64() to make the ppm calculation in vlv_find_best_dpll() safe
against interger overflows.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
(cherry picked from commit 69e4f900be175fd80fe69221a329c8993b16925b)
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1759e4c469e6..5b95e2a42caa 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -672,13 +672,11 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2;
u32 m, n, fastclk;
u32 updrate, minupdate, p;
- unsigned long bestppm, ppm, absppm;
+ unsigned int bestppm = 1000000;
int dotclk, flag;
flag = 0;
dotclk = target * 1000;
- bestppm = 1000000;
- ppm = absppm = 0;
fastclk = dotclk / (2*100);
updrate = 0;
minupdate = 19200;
@@ -695,6 +693,8 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
p = p1 * p2;
/* based on hardware requirement, prefer bigger m1,m2 values */
for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) {
+ unsigned int ppm, diff;
+
m2 = DIV_ROUND_CLOSEST(fastclk * p * n, refclk * m1);
m = m1 * m2;
vco = updrate * m;
@@ -702,14 +702,14 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
if (vco < limit->vco.min || vco >= limit->vco.max)
continue;
- ppm = 1000000 * ((vco / p) - fastclk) / fastclk;
- absppm = (ppm > 0) ? ppm : (-ppm);
- if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) {
+ diff = abs(vco / p - fastclk);
+ ppm = div_u64(1000000ULL * diff, fastclk);
+ if (ppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) {
bestppm = 0;
flag = 1;
}
- if (absppm < bestppm - 10) {
- bestppm = absppm;
+ if (ppm < bestppm - 10) {
+ bestppm = ppm;
flag = 1;
}
if (flag) {
--
1.8.5.rc3