]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
drm/i915/display: Disable audio, DRRS and PSR before planes
authorJosé Roberto de Souza <jose.souza@intel.com>
Mon, 26 Jul 2021 18:15:59 +0000 (11:15 -0700)
committerJosé Roberto de Souza <jose.souza@intel.com>
Tue, 27 Jul 2021 20:35:02 +0000 (13:35 -0700)
HDMI and DisplayPort sequences states that audio and PSR should be
disabled before planes are disabled.
Not following it did not caused any problems up to Alderlake-P but
for this platform it causes underruns during the PSR2 disable
sequence.

Specification don't mention that DRRS should be disabled before planes
but it looks safer to switch back to the default refresh rate before
following with the rest of the pipe disable sequence.

BSpec: 49191
BSpec: 49190
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210726181559.80855-1-jose.souza@intel.com
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_dp_mst.c

index 26a3aa73fcc434628826cd3ce134ae6b82de2515..061a663f43b8429c57a165a5fc9a0e1377b554ee 100644 (file)
@@ -3204,12 +3204,6 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state,
 
        intel_dp->link_trained = false;
 
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
-
-       intel_edp_drrs_disable(intel_dp, old_crtc_state);
-       intel_psr_disable(intel_dp, old_crtc_state);
        intel_edp_backlight_off(old_conn_state);
        /* Disable the decompression in DP Sink */
        intel_dp_sink_set_decompression_state(intel_dp, old_crtc_state,
@@ -3227,10 +3221,6 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
        struct drm_i915_private *i915 = to_i915(encoder->base.dev);
        struct drm_connector *connector = old_conn_state->connector;
 
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
-
        if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
                                               false, false))
                drm_dbg_kms(&i915->drm,
@@ -3238,6 +3228,25 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
                            connector->base.id, connector->name);
 }
 
+static void intel_pre_disable_ddi(struct intel_atomic_state *state,
+                                 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;
+
+       if (old_crtc_state->has_audio)
+               intel_audio_codec_disable(encoder, old_crtc_state,
+                                         old_conn_state);
+
+       if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
+               return;
+
+       intel_dp = enc_to_intel_dp(encoder);
+       intel_edp_drrs_disable(intel_dp, old_crtc_state);
+       intel_psr_disable(intel_dp, old_crtc_state);
+}
+
 static void intel_disable_ddi(struct intel_atomic_state *state,
                              struct intel_encoder *encoder,
                              const struct intel_crtc_state *old_crtc_state,
@@ -4590,6 +4599,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
        encoder->enable = intel_enable_ddi;
        encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
        encoder->pre_enable = intel_ddi_pre_enable;
+       encoder->pre_disable = intel_pre_disable_ddi;
        encoder->disable = intel_disable_ddi;
        encoder->post_disable = intel_ddi_post_disable;
        encoder->update_pipe = intel_ddi_update_pipe;
index ba45aca1b30c7b3669bcee2fe46bcbb6a11f21cc..34a961143efcf1cdb903de0e9ab0b72ca962146e 100644 (file)
@@ -3192,6 +3192,28 @@ static void intel_encoders_enable(struct intel_atomic_state *state,
        }
 }
 
+static void intel_encoders_pre_disable(struct intel_atomic_state *state,
+                                      struct intel_crtc *crtc)
+{
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct drm_connector_state *old_conn_state;
+       struct drm_connector *conn;
+       int i;
+
+       for_each_old_connector_in_state(&state->base, conn, old_conn_state, i) {
+               struct intel_encoder *encoder =
+                       to_intel_encoder(old_conn_state->best_encoder);
+
+               if (old_conn_state->crtc != &crtc->base)
+                       continue;
+
+               if (encoder->pre_disable)
+                       encoder->pre_disable(state, encoder, old_crtc_state,
+                                            old_conn_state);
+       }
+}
+
 static void intel_encoders_disable(struct intel_atomic_state *state,
                                   struct intel_crtc *crtc)
 {
@@ -10324,6 +10346,8 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
 
        drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave);
 
+       intel_encoders_pre_disable(state, crtc);
+
        intel_crtc_disable_planes(state, crtc);
 
        /*
index e7300ce211ab3eedd44f3d76b7fc452797b7d246..0a0aad0faf627ccbbfc2249157584e295d82aae1 100644 (file)
@@ -196,6 +196,10 @@ struct intel_encoder {
        void (*update_complete)(struct intel_atomic_state *,
                                struct intel_encoder *,
                                struct intel_crtc *);
+       void (*pre_disable)(struct intel_atomic_state *,
+                           struct intel_encoder *,
+                           const struct intel_crtc_state *,
+                           const struct drm_connector_state *);
        void (*disable)(struct intel_atomic_state *,
                        struct intel_encoder *,
                        const struct intel_crtc_state *,
index e2eb46337369e5c8b0612e76a5ecbc638d000b55..8d13d7b26a25b2623408d86161468ade848c9bf3 100644 (file)
@@ -348,6 +348,16 @@ static void wait_for_act_sent(struct intel_encoder *encoder,
        drm_dp_check_act_status(&intel_dp->mst_mgr);
 }
 
+static void intel_mst_pre_disable_dp(struct intel_atomic_state *state,
+                                    struct intel_encoder *encoder,
+                                    const struct intel_crtc_state *old_crtc_state,
+                                    const struct drm_connector_state *old_conn_state)
+{
+       if (old_crtc_state->has_audio)
+               intel_audio_codec_disable(encoder, old_crtc_state,
+                                         old_conn_state);
+}
+
 static void intel_mst_disable_dp(struct intel_atomic_state *state,
                                 struct intel_encoder *encoder,
                                 const struct intel_crtc_state *old_crtc_state,
@@ -372,9 +382,6 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
        if (ret) {
                drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret);
        }
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
 }
 
 static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
@@ -903,6 +910,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *dig_port, enum pipe
 
        intel_encoder->compute_config = intel_dp_mst_compute_config;
        intel_encoder->compute_config_late = intel_dp_mst_compute_config_late;
+       intel_encoder->pre_disable = intel_mst_pre_disable_dp;
        intel_encoder->disable = intel_mst_disable_dp;
        intel_encoder->post_disable = intel_mst_post_disable_dp;
        intel_encoder->update_pipe = intel_ddi_update_pipe;