Blob Blame History Raw
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Wed, 13 Jun 2018 19:05:53 +0300
Subject: drm/i915: Turn off g4x DP port in .post_disable()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git-commit: 4dccc4d517481282e84335c7acbfd7a1481004b8
Patch-mainline: v4.18-rc2
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

While Bspec doesn't list a specific sequence for turning off the DP port
on g4x we are getting an underrun if the port is disabled in the
.disable() hook. Looks like the pipe stops when the port stops, and by
that time the plane disable may not have completed yet. Also the plane(s)
seem to end up in some wonky state when this happens as they also signal
another underrun immediately after we turn them back on during the next
enable sequence.

We could add a vblank wait in .disable() to avoid wedging the planes,
but I assume we're still tripping up the pipe in some way. So it seems
better to me to just follow the ILK+ sequence and turn off the DP port
in .post_disable() instead. This sequence doesn't seem to suffer from
this problem. Could be it was always the intended sequence for DP and
the gen4 bspec was just never updated to include it.

Originally we used the bad sequence even on ilk+, but I changed that
in commit 08aff3fe26ae ("drm/i915: Move DP port disable to post_disable
for pch platforms") as it was causing issues on those platforms as well.
I left out g4x then only because I didn't have the hardware to test it.
Now that I do it's fairly clear that the ilk+ sequence is also the
right choice for g4x.

v2: Fix whitespace fail (Jani)
    Mention the ilk+ commit (Jani)

Cc: stable@vger.kernel.org
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180613160553.11664-2-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
(cherry picked from commit 51a9f6dfc00d35f927ecfaf6f0ae8ebaba39b3fe)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/i915/intel_dp.c |   24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2790,16 +2790,6 @@ static void g4x_disable_dp(struct intel_
 			   const struct drm_connector_state *old_conn_state)
 {
 	intel_disable_dp(encoder, old_crtc_state, old_conn_state);
-
-	/* disable the port before the pipe on g4x */
-	intel_dp_link_down(encoder, old_crtc_state);
-}
-
-static void ilk_disable_dp(struct intel_encoder *encoder,
-			   const struct intel_crtc_state *old_crtc_state,
-			   const struct drm_connector_state *old_conn_state)
-{
-	intel_disable_dp(encoder, old_crtc_state, old_conn_state);
 }
 
 static void vlv_disable_dp(struct intel_encoder *encoder,
@@ -2813,13 +2803,19 @@ static void vlv_disable_dp(struct intel_
 	intel_disable_dp(encoder, old_crtc_state, old_conn_state);
 }
 
-static void ilk_post_disable_dp(struct intel_encoder *encoder,
+static void g4x_post_disable_dp(struct intel_encoder *encoder,
 				const struct intel_crtc_state *old_crtc_state,
 				const struct drm_connector_state *old_conn_state)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	enum port port = encoder->port;
 
+	/*
+	 * Bspec does not list a specific disable sequence for g4x DP.
+	 * Follow the ilk+ sequence (disable pipe before the port) for
+	 * g4x DP as it does not suffer from underruns like the normal
+	 * g4x modeset sequence (disable pipe after the port).
+	 */
 	intel_dp_link_down(encoder, old_crtc_state);
 
 	/* Only ilk+ has port A */
@@ -6442,15 +6438,11 @@ bool intel_dp_init(struct drm_i915_priva
 		intel_encoder->enable = vlv_enable_dp;
 		intel_encoder->disable = vlv_disable_dp;
 		intel_encoder->post_disable = vlv_post_disable_dp;
-	} else if (INTEL_GEN(dev_priv) >= 5) {
-		intel_encoder->pre_enable = g4x_pre_enable_dp;
-		intel_encoder->enable = g4x_enable_dp;
-		intel_encoder->disable = ilk_disable_dp;
-		intel_encoder->post_disable = ilk_post_disable_dp;
 	} else {
 		intel_encoder->pre_enable = g4x_pre_enable_dp;
 		intel_encoder->enable = g4x_enable_dp;
 		intel_encoder->disable = g4x_disable_dp;
+		intel_encoder->post_disable = g4x_post_disable_dp;
 	}
 
 	intel_dig_port->dp.output_reg = output_reg;