summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2018-03-13 18:07:58 +0300
committerVille Syrjälä <ville.syrjala@linux.intel.com>2018-03-16 19:31:49 +0300
commit2f0e9d804935970a4ce0f58dd046b41881bfd8f3 (patch)
treee5b12b5b3bb171b37ec79ba10296bf64bbc690aa
parentdf550548c6339e0d032af4a7f9bd7200ab0c827b (diff)
downloadlinux-2f0e9d804935970a4ce0f58dd046b41881bfd8f3.tar.xz
drm: Make drm_mode_vrefresh() a bit more accurate
Do the refresh rate calculation with a single division. This gives us slightly more accurate results, especially for interlaced since we don't just double the final truncated result. We do lose one bit compared to the old way, so with an interlaced mode the new code can only handle ~2GHz instead of the ~4GHz the old code handeled. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180313150759.27620-2-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_modes.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 4157250140b0..f6b7c0e36a1a 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -773,24 +773,23 @@ EXPORT_SYMBOL(drm_mode_hsync);
int drm_mode_vrefresh(const struct drm_display_mode *mode)
{
int refresh = 0;
- unsigned int calc_val;
if (mode->vrefresh > 0)
refresh = mode->vrefresh;
else if (mode->htotal > 0 && mode->vtotal > 0) {
- int vtotal;
- vtotal = mode->vtotal;
- /* work out vrefresh the value will be x1000 */
- calc_val = (mode->clock * 1000);
- calc_val /= mode->htotal;
- refresh = (calc_val + vtotal / 2) / vtotal;
+ unsigned int num, den;
+
+ num = mode->clock * 1000;
+ den = mode->htotal * mode->vtotal;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- refresh *= 2;
+ num *= 2;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- refresh /= 2;
+ den *= 2;
if (mode->vscan > 1)
- refresh /= mode->vscan;
+ den *= mode->vscan;
+
+ refresh = DIV_ROUND_CLOSEST(num, den);
}
return refresh;
}