Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f0e9d80 authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

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: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180313150759.27620-2-ville.syrjala@linux.intel.com


Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent df550548
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
@@ -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;
}