Blob Blame History Raw
From e7a278a329dd8aa2c70c564849f164cb5673689c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Mon, 29 Oct 2018 20:18:20 +0200
Subject: drm/i915: Account for scale factor when calculating initial phase
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git-commit: e7a278a329dd8aa2c70c564849f164cb5673689c
Patch-mainline: v5.0-rc1
References: bsc#1113956

To get the initial phase correct we need to account for the scale
factor as well. I forgot this initially and was mostly looking at
heavily upscaled content where the minor difference between -0.5
and the proper initial phase was not readily apparent.

And let's toss in a comment that tries to explain the formula
a little bit.

v2: The initial phase upper limit is 1.5, not 24.0!

Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Fixes: 0a59952b24e2 ("drm/i915: Configure SKL+ scaler initial phase correctly")
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181029181820.21956-1-ville.syrjala@linux.intel.com
Tested-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Tested-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> #irc
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> #irc
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/i915/intel_display.c |   45 ++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_drv.h     |    2 -
 drivers/gpu/drm/i915/intel_sprite.c  |   20 ++++++++++-----
 3 files changed, 57 insertions(+), 10 deletions(-)

--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4795,8 +4795,31 @@ static void cpt_verify_modeset(struct dr
  * chroma samples for both of the luma samples, and thus we don't
  * actually get the expected MPEG2 chroma siting convention :(
  * The same behaviour is observed on pre-SKL platforms as well.
+ *
+ * Theory behind the formula (note that we ignore sub-pixel
+ * source coordinates):
+ * s = source sample position
+ * d = destination sample position
+ *
+ * Downscaling 4:1:
+ * -0.5
+ * | 0.0
+ * | |     1.5 (initial phase)
+ * | |     |
+ * v v     v
+ * | s | s | s | s |
+ * |       d       |
+ *
+ * Upscaling 1:4:
+ * -0.5
+ * | -0.375 (initial phase)
+ * | |     0.0
+ * | |     |
+ * v v     v
+ * |       s       |
+ * | d | d | d | d |
  */
-u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
+u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)
 {
 	int phase = -0x8000;
 	u16 trip = 0;
@@ -4804,6 +4827,15 @@ u16 skl_scaler_calc_phase(int sub, bool
 	if (chroma_cosited)
 		phase += (sub - 1) * 0x8000 / sub;
 
+	phase += scale / (2 * sub);
+
+	/*
+	 * Hardware initial phase limited to [-0.5:1.5].
+	 * Since the max hardware scale factor is 3.0, we
+	 * should never actually excdeed 1.0 here.
+	 */
+	WARN_ON(phase < -0x8000 || phase > 0x18000);
+
 	if (phase < 0)
 		phase = 0x10000 + phase;
 	else
@@ -5012,13 +5044,20 @@ static void skylake_pfit_enable(struct i
 
 	if (crtc->config->pch_pfit.enabled) {
 		u16 uv_rgb_hphase, uv_rgb_vphase;
+		int pfit_w, pfit_h, hscale, vscale;
 		int id;
 
 		if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))
 			return;
 
-		uv_rgb_hphase = skl_scaler_calc_phase(1, false);
-		uv_rgb_vphase = skl_scaler_calc_phase(1, false);
+		pfit_w = (crtc->config->pch_pfit.size >> 16) & 0xFFFF;
+		pfit_h = crtc->config->pch_pfit.size & 0xFFFF;
+
+		hscale = (crtc->config->pipe_src_w << 16) / pfit_w;
+		vscale = (crtc->config->pipe_src_h << 16) / pfit_h;
+
+		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
+		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
 
 		id = scaler_state->scaler_id;
 		I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1643,7 +1643,7 @@ void intel_mode_from_pipe_config(struct
 void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
 				  struct intel_crtc_state *crtc_state);
 
-u16 skl_scaler_calc_phase(int sub, bool chroma_center);
+u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
 		  uint32_t pixel_format);
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -286,22 +286,30 @@ skl_update_plane(struct intel_plane *pla
 			&crtc_state->scaler_state.scalers[scaler_id];
 		u16 y_hphase, uv_rgb_hphase;
 		u16 y_vphase, uv_rgb_vphase;
+		int hscale, vscale;
+
+		hscale = drm_rect_calc_hscale(&plane_state->base.src,
+					      &plane_state->base.dst,
+					      0, INT_MAX);
+		vscale = drm_rect_calc_vscale(&plane_state->base.src,
+					      &plane_state->base.dst,
+					      0, INT_MAX);
 
 		/* TODO: handle sub-pixel coordinates */
 		if (fb->format->format == DRM_FORMAT_NV12) {
-			y_hphase = skl_scaler_calc_phase(1, false);
-			y_vphase = skl_scaler_calc_phase(1, false);
+			y_hphase = skl_scaler_calc_phase(1, hscale, false);
+			y_vphase = skl_scaler_calc_phase(1, vscale, false);
 
 			/* MPEG2 chroma siting convention */
-			uv_rgb_hphase = skl_scaler_calc_phase(2, true);
-			uv_rgb_vphase = skl_scaler_calc_phase(2, false);
+			uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
+			uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
 		} else {
 			/* not used */
 			y_hphase = 0;
 			y_vphase = 0;
 
-			uv_rgb_hphase = skl_scaler_calc_phase(1, false);
-			uv_rgb_vphase = skl_scaler_calc_phase(1, false);
+			uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
+			uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
 		}
 
 		I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),