diff mbox series

[3/3] drm/i915: Fix frame start delay programming

Message ID 20191024122138.25065-3-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series [1/3] drm/i915: Use _PICK() for CHICKEN_TRANS() | expand

Commit Message

Ville Syrjala Oct. 24, 2019, 12:21 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently we're blindly poking at the frame start delay bits
in PIPECONF when trying to sanitize the hardware state. Those
bits decided to move elsewhere on HSW, so on many platforms
we're not doing anything at all here. Also we're forgetting
about the PCH transcoder entirely.

Add all the bit definitions for the various homes these bits
have had throughout the years, and reset them all to zero.

However I'm not entirely sure this is a safe thing to do. If
not I guess we'd want full readout+statecheck for this stuff.
For now let's stick to the current logic and hope for the
best.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 101 ++++++++++++++++---
 drivers/gpu/drm/i915/i915_reg.h              |  12 ++-
 drivers/gpu/drm/i915/intel_pm.c              |   1 -
 3 files changed, 95 insertions(+), 19 deletions(-)

Comments

Uma Shankar Nov. 15, 2019, 4:08 p.m. UTC | #1
>-----Original Message-----
>From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf Of Ville Syrjala
>Sent: Thursday, October 24, 2019 5:52 PM
>To: intel-gfx@lists.freedesktop.org
>Subject: [Intel-gfx] [PATCH 3/3] drm/i915: Fix frame start delay programming
>
>From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
>Currently we're blindly poking at the frame start delay bits in PIPECONF when trying to
>sanitize the hardware state. Those bits decided to move elsewhere on HSW, so on
>many platforms we're not doing anything at all here. Also we're forgetting about the
>PCH transcoder entirely.
>
>Add all the bit definitions for the various homes these bits have had throughout the
>years, and reset them all to zero.
>
>However I'm not entirely sure this is a safe thing to do. If not I guess we'd want full
>readout+statecheck for this stuff.
>For now let's stick to the current logic and hope for the best.
>
>Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>---
> drivers/gpu/drm/i915/display/intel_display.c | 101 ++++++++++++++++---
> drivers/gpu/drm/i915/i915_reg.h              |  12 ++-
> drivers/gpu/drm/i915/intel_pm.c              |   1 -
> 3 files changed, 95 insertions(+), 19 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/display/intel_display.c
>b/drivers/gpu/drm/i915/display/intel_display.c
>index 579655675b08..2896cf864f61 100644
>--- a/drivers/gpu/drm/i915/display/intel_display.c
>+++ b/drivers/gpu/drm/i915/display/intel_display.c
>@@ -1645,11 +1645,16 @@ static void ironlake_enable_pch_transcoder(const struct
>intel_crtc_state *crtc_s
> 	assert_fdi_rx_enabled(dev_priv, pipe);
>
> 	if (HAS_PCH_CPT(dev_priv)) {
>-		/* Workaround: Set the timing override bit before enabling the
>-		 * pch transcoder. */
> 		reg = TRANS_CHICKEN2(pipe);
> 		val = I915_READ(reg);
>+		/*
>+		 * Workaround: Set the timing override bit
>+		 * before enabling the pch transcoder.
>+		 */
> 		val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
>+		/* Configure frame start delay to match the CPU */
>+		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
>+		val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
> 		I915_WRITE(reg, val);
> 	}
>
>@@ -1658,6 +1663,10 @@ static void ironlake_enable_pch_transcoder(const struct
>intel_crtc_state *crtc_s
> 	pipeconf_val = I915_READ(PIPECONF(pipe));
>
> 	if (HAS_PCH_IBX(dev_priv)) {
>+		/* Configure frame start delay to match the CPU */
>+		val &= ~TRANS_FRAME_START_DELAY_MASK;
>+		val |= TRANS_FRAME_START_DELAY(0);
>+
> 		/*
> 		 * Make the BPC in transcoder be consistent with
> 		 * that in pipeconf reg. For HDMI we must use 8bpc @@ -1695,9
>+1704,12 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private
>*dev_priv,
> 	assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
> 	assert_fdi_rx_enabled(dev_priv, PIPE_A);
>
>+	val = I915_READ(TRANS_CHICKEN2(PIPE_A));
> 	/* Workaround: set timing override bit. */
>-	val = I915_READ(TRANS_CHICKEN2(PIPE_A));
> 	val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
>+	/* Configure frame start delay to match the CPU */
>+	val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
>+	val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
> 	I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
>
> 	val = TRANS_ENABLE;
>@@ -6452,6 +6464,19 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
> 	I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val);  }
>
>+static void hsw_set_frame_start_delay(const struct intel_crtc_state
>+*crtc_state) {
>+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
>+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>+	i915_reg_t reg = CHICKEN_TRANS(crtc_state->cpu_transcoder);
>+	u32 val;
>+
>+	val = I915_READ(reg);
>+	val &= ~HSW_FRAME_START_DELAY_MASK;
>+	val |= HSW_FRAME_START_DELAY(0);
>+	I915_WRITE(reg, val);
>+}
>+
> static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
> 				struct intel_atomic_state *state)
> {
>@@ -6494,8 +6519,10 @@ static void haswell_crtc_enable(struct intel_crtc_state
>*pipe_config,
> 					     &pipe_config->fdi_m_n, NULL);
> 	}
>
>-	if (!transcoder_is_dsi(cpu_transcoder))
>+	if (!transcoder_is_dsi(cpu_transcoder)) {
>+		hsw_set_frame_start_delay(pipe_config);
> 		haswell_set_pipeconf(pipe_config);
>+	}
>
> 	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
> 		bdw_set_pipemisc(pipe_config);
>@@ -8394,6 +8421,8 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state
>*crtc_state)
>
> 	pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
>
>+	pipeconf |= PIPECONF_FRAME_START_DELAY(0);
>+
> 	I915_WRITE(PIPECONF(crtc->pipe), pipeconf);
> 	POSTING_READ(PIPECONF(crtc->pipe));
> }
>@@ -9474,6 +9503,8 @@ static void ironlake_set_pipeconf(const struct
>intel_crtc_state *crtc_state)
>
> 	val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
>
>+	val |= PIPECONF_FRAME_START_DELAY(0);
>+
> 	I915_WRITE(PIPECONF(pipe), val);
> 	POSTING_READ(PIPECONF(pipe));
> }
>@@ -16919,25 +16950,69 @@ static bool has_pch_trancoder(struct
>drm_i915_private *dev_priv,
> 		(HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A);  }
>
>+static void intel_sanitize_frame_start_delay(const struct
>+intel_crtc_state *crtc_state) {
>+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
>+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>+	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
>+
>+	if (INTEL_GEN(dev_priv) >= 9 ||
>+	    IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
>+		i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
>+		u32 val;
>+
>+		if (transcoder_is_dsi(cpu_transcoder))
>+			return;
>+
>+		val = I915_READ(reg);
>+		val &= ~HSW_FRAME_START_DELAY_MASK;
>+		val |= HSW_FRAME_START_DELAY(0);
>+		I915_WRITE(reg, val);
>+	} else {
>+		i915_reg_t reg = PIPECONF(cpu_transcoder);
>+		u32 val;
>+
>+		val = I915_READ(reg);
>+		val &= ~PIPECONF_FRAME_START_DELAY_MASK;
>+		val |= PIPECONF_FRAME_START_DELAY(0);
>+		I915_WRITE(reg, val);
>+	}
>+
>+	if (!crtc_state->has_pch_encoder)
>+		return;
>+
>+	if (HAS_PCH_IBX(dev_priv)) {
>+		i915_reg_t reg = PCH_TRANSCONF(crtc->pipe);
>+		u32 val;
>+
>+		val = I915_READ(reg);
>+		val &= ~TRANS_FRAME_START_DELAY_MASK;
>+		val |= TRANS_FRAME_START_DELAY(0);
>+		I915_WRITE(reg, val);
>+	} else {
>+		i915_reg_t reg = TRANS_CHICKEN2(crtc->pipe);
>+		u32 val;
>+
>+		val = I915_READ(reg);
>+		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
>+		val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
>+		I915_WRITE(reg, val);
>+	}
>+}
>+
> static void intel_sanitize_crtc(struct intel_crtc *crtc,
> 				struct drm_modeset_acquire_ctx *ctx)  {
> 	struct drm_device *dev = crtc->base.dev;
> 	struct drm_i915_private *dev_priv = to_i915(dev);
> 	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
>-	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
>-
>-	/* Clear any frame start delays used for debugging left by the BIOS */
>-	if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) {
>-		i915_reg_t reg = PIPECONF(cpu_transcoder);
>-
>-		I915_WRITE(reg,
>-			   I915_READ(reg) &
>~PIPECONF_FRAME_START_DELAY_MASK);
>-	}
>
> 	if (crtc_state->base.active) {
> 		struct intel_plane *plane;
>
>+		/* Clear any frame start delays used for debugging left by the BIOS */
>+		intel_sanitize_frame_start_delay(crtc_state);
>+
> 		/* Disable everything but the primary plane */
> 		for_each_intel_plane_on_crtc(dev, crtc, plane) {
> 			const struct intel_plane_state *plane_state = diff --git
>a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index
>50c2fa0f2cab..cb2e0f4679c4 100644
>--- a/drivers/gpu/drm/i915/i915_reg.h
>+++ b/drivers/gpu/drm/i915/i915_reg.h
>@@ -5671,7 +5671,8 @@ enum {
> #define   PIPECONF_DOUBLE_WIDE	(1 << 30)
> #define   I965_PIPECONF_ACTIVE	(1 << 30)
> #define   PIPECONF_DSI_PLL_LOCKED	(1 << 29) /* vlv & pipe A only */
>-#define   PIPECONF_FRAME_START_DELAY_MASK (3 << 27)
>+#define   PIPECONF_FRAME_START_DELAY_MASK	(3 << 27) /* pre-hsw */
>+#define   PIPECONF_FRAME_START_DELAY(x)		((x) << 27) /* pre-hsw: 0-3
>*/
> #define   PIPECONF_SINGLE_WIDE	0
> #define   PIPECONF_PIPE_UNLOCKED 0
> #define   PIPECONF_PIPE_LOCKED	(1 << 25)
>@@ -7627,6 +7628,8 @@ enum {
> 					    [TRANSCODER_B] = _CHICKEN_TRANS_B,
>\
> 					    [TRANSCODER_C] = _CHICKEN_TRANS_C,
>\
> 					    [TRANSCODER_D] =
>_CHICKEN_TRANS_D))
>+#define  HSW_FRAME_START_DELAY_MASK	(3 << 27)
>+#define  HSW_FRAME_START_DELAY(x)	((x) << 27) /* 0-3 */
> #define  VSC_DATA_SEL_SOFTWARE_CONTROL	(1 << 25) /* GLK and CNL+ */
> #define  DDI_TRAINING_OVERRIDE_ENABLE	(1 << 19)
> #define  DDI_TRAINING_OVERRIDE_VALUE	(1 << 18)
>@@ -8341,10 +8344,8 @@ enum {
> #define  TRANS_STATE_MASK       (1 << 30)
> #define  TRANS_STATE_DISABLE    (0 << 30)
> #define  TRANS_STATE_ENABLE     (1 << 30)
>-#define  TRANS_FSYNC_DELAY_HB1  (0 << 27) -#define  TRANS_FSYNC_DELAY_HB2
>(1 << 27) -#define  TRANS_FSYNC_DELAY_HB3  (2 << 27) -#define
>TRANS_FSYNC_DELAY_HB4  (3 << 27)
>+#define  TRANS_FRAME_START_DELAY_MASK	(3 << 27) /* ibx */
>+#define  TRANS_FRAME_START_DELAY(x)	((x) << 27) /* ibx: 0-3 */
> #define  TRANS_INTERLACE_MASK   (7 << 21)
> #define  TRANS_PROGRESSIVE      (0 << 21)
> #define  TRANS_INTERLACED       (3 << 21)
>@@ -8365,6 +8366,7 @@ enum {
> #define  TRANS_CHICKEN2_TIMING_OVERRIDE			(1 << 31)
> #define  TRANS_CHICKEN2_FDI_POLARITY_REVERSED		(1 << 29)
> #define  TRANS_CHICKEN2_FRAME_START_DELAY_MASK		(3 << 27)
>+#define  TRANS_CHICKEN2_FRAME_START_DELAY(x)		((x) << 27) /* 0-3 */
> #define  TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER	(1 << 26)
> #define  TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH	(1 << 25)
>
>diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index
>362234449087..8b1fbdb36537 100644
>--- a/drivers/gpu/drm/i915/intel_pm.c
>+++ b/drivers/gpu/drm/i915/intel_pm.c
>@@ -8079,7 +8079,6 @@ static void cpt_init_clock_gating(struct drm_i915_private
>*dev_priv)
> 		val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
> 		if (dev_priv->vbt.fdi_rx_polarity_inverted)
> 			val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
>-		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;

Is there any reason not to let it be set at 0.

Overall, I looked at the register and bit definitions for various platforms and this looks
a very reasonable change rectifying the frame start delay programming.

However I am not sure if for all platforms 0 will be the preferred value. If the default values
of these bits are 0 in hardware register (or the BIOS set them at 0 itself), this should
work seamlessly. Only caveat will be if the defaults are not 0 on all platforms, we may have
issues. 

Good way to figure this out I guess is our CI results. So if the CI passes, this is
Reviewed-by: Uma Shankar <uma.shankar@intel.com>

> 		val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
> 		val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH;
> 		I915_WRITE(TRANS_CHICKEN2(pipe), val);
>--
>2.21.0
>
>_______________________________________________
>Intel-gfx mailing list
>Intel-gfx@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ville Syrjala Nov. 15, 2019, 5:19 p.m. UTC | #2
On Fri, Nov 15, 2019 at 04:08:45PM +0000, Shankar, Uma wrote:
> 
> 
> >-----Original Message-----
> >From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf Of Ville Syrjala
> >Sent: Thursday, October 24, 2019 5:52 PM
> >To: intel-gfx@lists.freedesktop.org
> >Subject: [Intel-gfx] [PATCH 3/3] drm/i915: Fix frame start delay programming
> >
> >From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> >Currently we're blindly poking at the frame start delay bits in PIPECONF when trying to
> >sanitize the hardware state. Those bits decided to move elsewhere on HSW, so on
> >many platforms we're not doing anything at all here. Also we're forgetting about the
> >PCH transcoder entirely.
> >
> >Add all the bit definitions for the various homes these bits have had throughout the
> >years, and reset them all to zero.
> >
> >However I'm not entirely sure this is a safe thing to do. If not I guess we'd want full
> >readout+statecheck for this stuff.
> >For now let's stick to the current logic and hope for the best.
> >
> >Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >---
> > drivers/gpu/drm/i915/display/intel_display.c | 101 ++++++++++++++++---
> > drivers/gpu/drm/i915/i915_reg.h              |  12 ++-
> > drivers/gpu/drm/i915/intel_pm.c              |   1 -
> > 3 files changed, 95 insertions(+), 19 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> >b/drivers/gpu/drm/i915/display/intel_display.c
> >index 579655675b08..2896cf864f61 100644
> >--- a/drivers/gpu/drm/i915/display/intel_display.c
> >+++ b/drivers/gpu/drm/i915/display/intel_display.c
> >@@ -1645,11 +1645,16 @@ static void ironlake_enable_pch_transcoder(const struct
> >intel_crtc_state *crtc_s
> > 	assert_fdi_rx_enabled(dev_priv, pipe);
> >
> > 	if (HAS_PCH_CPT(dev_priv)) {
> >-		/* Workaround: Set the timing override bit before enabling the
> >-		 * pch transcoder. */
> > 		reg = TRANS_CHICKEN2(pipe);
> > 		val = I915_READ(reg);
> >+		/*
> >+		 * Workaround: Set the timing override bit
> >+		 * before enabling the pch transcoder.
> >+		 */
> > 		val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
> >+		/* Configure frame start delay to match the CPU */
> >+		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
> >+		val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
> > 		I915_WRITE(reg, val);
> > 	}
> >
> >@@ -1658,6 +1663,10 @@ static void ironlake_enable_pch_transcoder(const struct
> >intel_crtc_state *crtc_s
> > 	pipeconf_val = I915_READ(PIPECONF(pipe));
> >
> > 	if (HAS_PCH_IBX(dev_priv)) {
> >+		/* Configure frame start delay to match the CPU */
> >+		val &= ~TRANS_FRAME_START_DELAY_MASK;
> >+		val |= TRANS_FRAME_START_DELAY(0);
> >+
> > 		/*
> > 		 * Make the BPC in transcoder be consistent with
> > 		 * that in pipeconf reg. For HDMI we must use 8bpc @@ -1695,9
> >+1704,12 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private
> >*dev_priv,
> > 	assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
> > 	assert_fdi_rx_enabled(dev_priv, PIPE_A);
> >
> >+	val = I915_READ(TRANS_CHICKEN2(PIPE_A));
> > 	/* Workaround: set timing override bit. */
> >-	val = I915_READ(TRANS_CHICKEN2(PIPE_A));
> > 	val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
> >+	/* Configure frame start delay to match the CPU */
> >+	val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
> >+	val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
> > 	I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
> >
> > 	val = TRANS_ENABLE;
> >@@ -6452,6 +6464,19 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
> > 	I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val);  }
> >
> >+static void hsw_set_frame_start_delay(const struct intel_crtc_state
> >+*crtc_state) {
> >+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> >+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> >+	i915_reg_t reg = CHICKEN_TRANS(crtc_state->cpu_transcoder);
> >+	u32 val;
> >+
> >+	val = I915_READ(reg);
> >+	val &= ~HSW_FRAME_START_DELAY_MASK;
> >+	val |= HSW_FRAME_START_DELAY(0);
> >+	I915_WRITE(reg, val);
> >+}
> >+
> > static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
> > 				struct intel_atomic_state *state)
> > {
> >@@ -6494,8 +6519,10 @@ static void haswell_crtc_enable(struct intel_crtc_state
> >*pipe_config,
> > 					     &pipe_config->fdi_m_n, NULL);
> > 	}
> >
> >-	if (!transcoder_is_dsi(cpu_transcoder))
> >+	if (!transcoder_is_dsi(cpu_transcoder)) {
> >+		hsw_set_frame_start_delay(pipe_config);
> > 		haswell_set_pipeconf(pipe_config);
> >+	}
> >
> > 	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
> > 		bdw_set_pipemisc(pipe_config);
> >@@ -8394,6 +8421,8 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state
> >*crtc_state)
> >
> > 	pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
> >
> >+	pipeconf |= PIPECONF_FRAME_START_DELAY(0);
> >+
> > 	I915_WRITE(PIPECONF(crtc->pipe), pipeconf);
> > 	POSTING_READ(PIPECONF(crtc->pipe));
> > }
> >@@ -9474,6 +9503,8 @@ static void ironlake_set_pipeconf(const struct
> >intel_crtc_state *crtc_state)
> >
> > 	val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
> >
> >+	val |= PIPECONF_FRAME_START_DELAY(0);
> >+
> > 	I915_WRITE(PIPECONF(pipe), val);
> > 	POSTING_READ(PIPECONF(pipe));
> > }
> >@@ -16919,25 +16950,69 @@ static bool has_pch_trancoder(struct
> >drm_i915_private *dev_priv,
> > 		(HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A);  }
> >
> >+static void intel_sanitize_frame_start_delay(const struct
> >+intel_crtc_state *crtc_state) {
> >+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> >+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> >+	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> >+
> >+	if (INTEL_GEN(dev_priv) >= 9 ||
> >+	    IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
> >+		i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
> >+		u32 val;
> >+
> >+		if (transcoder_is_dsi(cpu_transcoder))
> >+			return;
> >+
> >+		val = I915_READ(reg);
> >+		val &= ~HSW_FRAME_START_DELAY_MASK;
> >+		val |= HSW_FRAME_START_DELAY(0);
> >+		I915_WRITE(reg, val);
> >+	} else {
> >+		i915_reg_t reg = PIPECONF(cpu_transcoder);
> >+		u32 val;
> >+
> >+		val = I915_READ(reg);
> >+		val &= ~PIPECONF_FRAME_START_DELAY_MASK;
> >+		val |= PIPECONF_FRAME_START_DELAY(0);
> >+		I915_WRITE(reg, val);
> >+	}
> >+
> >+	if (!crtc_state->has_pch_encoder)
> >+		return;
> >+
> >+	if (HAS_PCH_IBX(dev_priv)) {
> >+		i915_reg_t reg = PCH_TRANSCONF(crtc->pipe);
> >+		u32 val;
> >+
> >+		val = I915_READ(reg);
> >+		val &= ~TRANS_FRAME_START_DELAY_MASK;
> >+		val |= TRANS_FRAME_START_DELAY(0);
> >+		I915_WRITE(reg, val);
> >+	} else {
> >+		i915_reg_t reg = TRANS_CHICKEN2(crtc->pipe);
> >+		u32 val;
> >+
> >+		val = I915_READ(reg);
> >+		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
> >+		val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
> >+		I915_WRITE(reg, val);
> >+	}
> >+}
> >+
> > static void intel_sanitize_crtc(struct intel_crtc *crtc,
> > 				struct drm_modeset_acquire_ctx *ctx)  {
> > 	struct drm_device *dev = crtc->base.dev;
> > 	struct drm_i915_private *dev_priv = to_i915(dev);
> > 	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
> >-	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> >-
> >-	/* Clear any frame start delays used for debugging left by the BIOS */
> >-	if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) {
> >-		i915_reg_t reg = PIPECONF(cpu_transcoder);
> >-
> >-		I915_WRITE(reg,
> >-			   I915_READ(reg) &
> >~PIPECONF_FRAME_START_DELAY_MASK);
> >-	}
> >
> > 	if (crtc_state->base.active) {
> > 		struct intel_plane *plane;
> >
> >+		/* Clear any frame start delays used for debugging left by the BIOS */
> >+		intel_sanitize_frame_start_delay(crtc_state);
> >+
> > 		/* Disable everything but the primary plane */
> > 		for_each_intel_plane_on_crtc(dev, crtc, plane) {
> > 			const struct intel_plane_state *plane_state = diff --git
> >a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index
> >50c2fa0f2cab..cb2e0f4679c4 100644
> >--- a/drivers/gpu/drm/i915/i915_reg.h
> >+++ b/drivers/gpu/drm/i915/i915_reg.h
> >@@ -5671,7 +5671,8 @@ enum {
> > #define   PIPECONF_DOUBLE_WIDE	(1 << 30)
> > #define   I965_PIPECONF_ACTIVE	(1 << 30)
> > #define   PIPECONF_DSI_PLL_LOCKED	(1 << 29) /* vlv & pipe A only */
> >-#define   PIPECONF_FRAME_START_DELAY_MASK (3 << 27)
> >+#define   PIPECONF_FRAME_START_DELAY_MASK	(3 << 27) /* pre-hsw */
> >+#define   PIPECONF_FRAME_START_DELAY(x)		((x) << 27) /* pre-hsw: 0-3
> >*/
> > #define   PIPECONF_SINGLE_WIDE	0
> > #define   PIPECONF_PIPE_UNLOCKED 0
> > #define   PIPECONF_PIPE_LOCKED	(1 << 25)
> >@@ -7627,6 +7628,8 @@ enum {
> > 					    [TRANSCODER_B] = _CHICKEN_TRANS_B,
> >\
> > 					    [TRANSCODER_C] = _CHICKEN_TRANS_C,
> >\
> > 					    [TRANSCODER_D] =
> >_CHICKEN_TRANS_D))
> >+#define  HSW_FRAME_START_DELAY_MASK	(3 << 27)
> >+#define  HSW_FRAME_START_DELAY(x)	((x) << 27) /* 0-3 */
> > #define  VSC_DATA_SEL_SOFTWARE_CONTROL	(1 << 25) /* GLK and CNL+ */
> > #define  DDI_TRAINING_OVERRIDE_ENABLE	(1 << 19)
> > #define  DDI_TRAINING_OVERRIDE_VALUE	(1 << 18)
> >@@ -8341,10 +8344,8 @@ enum {
> > #define  TRANS_STATE_MASK       (1 << 30)
> > #define  TRANS_STATE_DISABLE    (0 << 30)
> > #define  TRANS_STATE_ENABLE     (1 << 30)
> >-#define  TRANS_FSYNC_DELAY_HB1  (0 << 27) -#define  TRANS_FSYNC_DELAY_HB2
> >(1 << 27) -#define  TRANS_FSYNC_DELAY_HB3  (2 << 27) -#define
> >TRANS_FSYNC_DELAY_HB4  (3 << 27)
> >+#define  TRANS_FRAME_START_DELAY_MASK	(3 << 27) /* ibx */
> >+#define  TRANS_FRAME_START_DELAY(x)	((x) << 27) /* ibx: 0-3 */
> > #define  TRANS_INTERLACE_MASK   (7 << 21)
> > #define  TRANS_PROGRESSIVE      (0 << 21)
> > #define  TRANS_INTERLACED       (3 << 21)
> >@@ -8365,6 +8366,7 @@ enum {
> > #define  TRANS_CHICKEN2_TIMING_OVERRIDE			(1 << 31)
> > #define  TRANS_CHICKEN2_FDI_POLARITY_REVERSED		(1 << 29)
> > #define  TRANS_CHICKEN2_FRAME_START_DELAY_MASK		(3 << 27)
> >+#define  TRANS_CHICKEN2_FRAME_START_DELAY(x)		((x) << 27) /* 0-3 */
> > #define  TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER	(1 << 26)
> > #define  TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH	(1 << 25)
> >
> >diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index
> >362234449087..8b1fbdb36537 100644
> >--- a/drivers/gpu/drm/i915/intel_pm.c
> >+++ b/drivers/gpu/drm/i915/intel_pm.c
> >@@ -8079,7 +8079,6 @@ static void cpt_init_clock_gating(struct drm_i915_private
> >*dev_priv)
> > 		val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
> > 		if (dev_priv->vbt.fdi_rx_polarity_inverted)
> > 			val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
> >-		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
> 
> Is there any reason not to let it be set at 0.
> 
> Overall, I looked at the register and bit definitions for various platforms and this looks
> a very reasonable change rectifying the frame start delay programming.
> 
> However I am not sure if for all platforms 0 will be the preferred value. If the default values
> of these bits are 0 in hardware register (or the BIOS set them at 0 itself), this should
> work seamlessly. Only caveat will be if the defaults are not 0 on all platforms, we may have
> issues. 

Default is 0, but supposedly some VBIOSen have left other values
in there for whatever reason. Or else we probably wouldn't have this
code to sanitize things.

I *may* want to try bumping this to 3 across the board to give
gamma programming more breathing room during the vblank, but I'm
not sure that's entirely safe to do. Hence I started with just
cleaning up the current mess.

IIRC there was also some obnoxious workaround on LVDS+IBX (or maybe
it was CPT) that would require some extra handling if we were to
program this to some non-zero value.

> 
> Good way to figure this out I guess is our CI results. So if the CI passes, this is
> Reviewed-by: Uma Shankar <uma.shankar@intel.com>

Ta.

> 
> > 		val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
> > 		val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH;
> > 		I915_WRITE(TRANS_CHICKEN2(pipe), val);
> >--
> >2.21.0
> >
> >_______________________________________________
> >Intel-gfx mailing list
> >Intel-gfx@lists.freedesktop.org
> >https://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 579655675b08..2896cf864f61 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1645,11 +1645,16 @@  static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s
 	assert_fdi_rx_enabled(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev_priv)) {
-		/* Workaround: Set the timing override bit before enabling the
-		 * pch transcoder. */
 		reg = TRANS_CHICKEN2(pipe);
 		val = I915_READ(reg);
+		/*
+		 * Workaround: Set the timing override bit
+		 * before enabling the pch transcoder.
+		 */
 		val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
+		/* Configure frame start delay to match the CPU */
+		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
+		val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
 		I915_WRITE(reg, val);
 	}
 
@@ -1658,6 +1663,10 @@  static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s
 	pipeconf_val = I915_READ(PIPECONF(pipe));
 
 	if (HAS_PCH_IBX(dev_priv)) {
+		/* Configure frame start delay to match the CPU */
+		val &= ~TRANS_FRAME_START_DELAY_MASK;
+		val |= TRANS_FRAME_START_DELAY(0);
+
 		/*
 		 * Make the BPC in transcoder be consistent with
 		 * that in pipeconf reg. For HDMI we must use 8bpc
@@ -1695,9 +1704,12 @@  static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
 	assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
 	assert_fdi_rx_enabled(dev_priv, PIPE_A);
 
+	val = I915_READ(TRANS_CHICKEN2(PIPE_A));
 	/* Workaround: set timing override bit. */
-	val = I915_READ(TRANS_CHICKEN2(PIPE_A));
 	val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
+	/* Configure frame start delay to match the CPU */
+	val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
+	val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
 	I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
 
 	val = TRANS_ENABLE;
@@ -6452,6 +6464,19 @@  static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
 	I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val);
 }
 
+static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	i915_reg_t reg = CHICKEN_TRANS(crtc_state->cpu_transcoder);
+	u32 val;
+
+	val = I915_READ(reg);
+	val &= ~HSW_FRAME_START_DELAY_MASK;
+	val |= HSW_FRAME_START_DELAY(0);
+	I915_WRITE(reg, val);
+}
+
 static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 				struct intel_atomic_state *state)
 {
@@ -6494,8 +6519,10 @@  static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 					     &pipe_config->fdi_m_n, NULL);
 	}
 
-	if (!transcoder_is_dsi(cpu_transcoder))
+	if (!transcoder_is_dsi(cpu_transcoder)) {
+		hsw_set_frame_start_delay(pipe_config);
 		haswell_set_pipeconf(pipe_config);
+	}
 
 	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
 		bdw_set_pipemisc(pipe_config);
@@ -8394,6 +8421,8 @@  static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
 
 	pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
 
+	pipeconf |= PIPECONF_FRAME_START_DELAY(0);
+
 	I915_WRITE(PIPECONF(crtc->pipe), pipeconf);
 	POSTING_READ(PIPECONF(crtc->pipe));
 }
@@ -9474,6 +9503,8 @@  static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state)
 
 	val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
 
+	val |= PIPECONF_FRAME_START_DELAY(0);
+
 	I915_WRITE(PIPECONF(pipe), val);
 	POSTING_READ(PIPECONF(pipe));
 }
@@ -16919,25 +16950,69 @@  static bool has_pch_trancoder(struct drm_i915_private *dev_priv,
 		(HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A);
 }
 
+static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+
+	if (INTEL_GEN(dev_priv) >= 9 ||
+	    IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
+		i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
+		u32 val;
+
+		if (transcoder_is_dsi(cpu_transcoder))
+			return;
+
+		val = I915_READ(reg);
+		val &= ~HSW_FRAME_START_DELAY_MASK;
+		val |= HSW_FRAME_START_DELAY(0);
+		I915_WRITE(reg, val);
+	} else {
+		i915_reg_t reg = PIPECONF(cpu_transcoder);
+		u32 val;
+
+		val = I915_READ(reg);
+		val &= ~PIPECONF_FRAME_START_DELAY_MASK;
+		val |= PIPECONF_FRAME_START_DELAY(0);
+		I915_WRITE(reg, val);
+	}
+
+	if (!crtc_state->has_pch_encoder)
+		return;
+
+	if (HAS_PCH_IBX(dev_priv)) {
+		i915_reg_t reg = PCH_TRANSCONF(crtc->pipe);
+		u32 val;
+
+		val = I915_READ(reg);
+		val &= ~TRANS_FRAME_START_DELAY_MASK;
+		val |= TRANS_FRAME_START_DELAY(0);
+		I915_WRITE(reg, val);
+	} else {
+		i915_reg_t reg = TRANS_CHICKEN2(crtc->pipe);
+		u32 val;
+
+		val = I915_READ(reg);
+		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
+		val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
+		I915_WRITE(reg, val);
+	}
+}
+
 static void intel_sanitize_crtc(struct intel_crtc *crtc,
 				struct drm_modeset_acquire_ctx *ctx)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
-	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
-
-	/* Clear any frame start delays used for debugging left by the BIOS */
-	if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) {
-		i915_reg_t reg = PIPECONF(cpu_transcoder);
-
-		I915_WRITE(reg,
-			   I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
-	}
 
 	if (crtc_state->base.active) {
 		struct intel_plane *plane;
 
+		/* Clear any frame start delays used for debugging left by the BIOS */
+		intel_sanitize_frame_start_delay(crtc_state);
+
 		/* Disable everything but the primary plane */
 		for_each_intel_plane_on_crtc(dev, crtc, plane) {
 			const struct intel_plane_state *plane_state =
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 50c2fa0f2cab..cb2e0f4679c4 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5671,7 +5671,8 @@  enum {
 #define   PIPECONF_DOUBLE_WIDE	(1 << 30)
 #define   I965_PIPECONF_ACTIVE	(1 << 30)
 #define   PIPECONF_DSI_PLL_LOCKED	(1 << 29) /* vlv & pipe A only */
-#define   PIPECONF_FRAME_START_DELAY_MASK (3 << 27)
+#define   PIPECONF_FRAME_START_DELAY_MASK	(3 << 27) /* pre-hsw */
+#define   PIPECONF_FRAME_START_DELAY(x)		((x) << 27) /* pre-hsw: 0-3 */
 #define   PIPECONF_SINGLE_WIDE	0
 #define   PIPECONF_PIPE_UNLOCKED 0
 #define   PIPECONF_PIPE_LOCKED	(1 << 25)
@@ -7627,6 +7628,8 @@  enum {
 					    [TRANSCODER_B] = _CHICKEN_TRANS_B, \
 					    [TRANSCODER_C] = _CHICKEN_TRANS_C, \
 					    [TRANSCODER_D] = _CHICKEN_TRANS_D))
+#define  HSW_FRAME_START_DELAY_MASK	(3 << 27)
+#define  HSW_FRAME_START_DELAY(x)	((x) << 27) /* 0-3 */
 #define  VSC_DATA_SEL_SOFTWARE_CONTROL	(1 << 25) /* GLK and CNL+ */
 #define  DDI_TRAINING_OVERRIDE_ENABLE	(1 << 19)
 #define  DDI_TRAINING_OVERRIDE_VALUE	(1 << 18)
@@ -8341,10 +8344,8 @@  enum {
 #define  TRANS_STATE_MASK       (1 << 30)
 #define  TRANS_STATE_DISABLE    (0 << 30)
 #define  TRANS_STATE_ENABLE     (1 << 30)
-#define  TRANS_FSYNC_DELAY_HB1  (0 << 27)
-#define  TRANS_FSYNC_DELAY_HB2  (1 << 27)
-#define  TRANS_FSYNC_DELAY_HB3  (2 << 27)
-#define  TRANS_FSYNC_DELAY_HB4  (3 << 27)
+#define  TRANS_FRAME_START_DELAY_MASK	(3 << 27) /* ibx */
+#define  TRANS_FRAME_START_DELAY(x)	((x) << 27) /* ibx: 0-3 */
 #define  TRANS_INTERLACE_MASK   (7 << 21)
 #define  TRANS_PROGRESSIVE      (0 << 21)
 #define  TRANS_INTERLACED       (3 << 21)
@@ -8365,6 +8366,7 @@  enum {
 #define  TRANS_CHICKEN2_TIMING_OVERRIDE			(1 << 31)
 #define  TRANS_CHICKEN2_FDI_POLARITY_REVERSED		(1 << 29)
 #define  TRANS_CHICKEN2_FRAME_START_DELAY_MASK		(3 << 27)
+#define  TRANS_CHICKEN2_FRAME_START_DELAY(x)		((x) << 27) /* 0-3 */
 #define  TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER	(1 << 26)
 #define  TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH	(1 << 25)
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 362234449087..8b1fbdb36537 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -8079,7 +8079,6 @@  static void cpt_init_clock_gating(struct drm_i915_private *dev_priv)
 		val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
 		if (dev_priv->vbt.fdi_rx_polarity_inverted)
 			val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
-		val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
 		val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
 		val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH;
 		I915_WRITE(TRANS_CHICKEN2(pipe), val);