aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLyude Paul <lyude@redhat.com>2018-04-06 21:10:53 -0400
committerLyude Paul <lyude@redhat.com>2018-04-07 18:26:15 -0400
commitbe1c63c8017bb00a4041abace6cc1e9f0bf26aa9 (patch)
tree86c28fec4e2c157ee88a79947ed27e2e1246b1d5
parentd0667e9ce52eb2d5d32db4f16976226e78f88784 (diff)
drm/i915/dp: Send DPCD ON for MST before phy_up
When doing a modeset where the sink is transitioning from D3 to D0 , it would sometimes be possible for the initial power_up_phy() to start timing out. This would only be observed in the last action before the sink went into D3 mode was intel_dp_sink_dpms(DRM_MODE_DPMS_OFF). We originally thought this might be an issue with us accidentally shutting off the aux block when putting the sink into D3, but since the DP spec mandates that sinks must wake up within 1ms while we have 100ms to respond to an ESI irq, this didn't really add up. Turns out that the problem is more subtle then that: It turns out that the timeout is from us not enabling DPMS on the MST hub before actually trying to initiate sideband communications. This would cause the first sideband communication (power_up_phy()), to start timing out because the sink wasn't ready to respond. Afterwards, we would call intel_dp_sink_dpms(DRM_MODE_DPMS_ON) in intel_ddi_pre_enable_dp(), which would actually result in waking up the sink so that sideband requests would work again. Since DPMS is what lets us actually bring the hub up into a state where sideband communications become functional again, we just need to make sure to enable DPMS on the display before attempting to perform sideband communications. Changes since v1: - Remove comment above if (!intel_dp->is_mst) - vsryjala - Move intel_dp_sink_dpms() for MST into intel_dp_post_disable_mst() to keep enable/disable paths symmetrical - Improve commit message - dhnkrn Changes since v2: - Only send DPMS off when we're disabling the last sink, and only send DPMS on when we're enabling the first sink - dhnkrn Changes since v3: - Check against is_mst, not intel_dp->is_mst - dhnkrn/vsyrjala Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Tested-by: Laura Abbott <labbott@redhat.com> Cc: stable@vger.kernel.org Fixes: ad260ab32a4d9 ("drm/i915/dp: Write to SET_POWER dpcd to enable MST hub.") Link: https://patchwork.freedesktop.org/patch/msgid/20180407011053.22437-1-lyude@redhat.com
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c8
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c8
2 files changed, 13 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index a6672a9abd85..92cb26b18a9b 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2324,7 +2324,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
2324 intel_prepare_dp_ddi_buffers(encoder, crtc_state); 2324 intel_prepare_dp_ddi_buffers(encoder, crtc_state);
2325 2325
2326 intel_ddi_init_dp_buf_reg(encoder); 2326 intel_ddi_init_dp_buf_reg(encoder);
2327 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); 2327 if (!is_mst)
2328 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
2328 intel_dp_start_link_train(intel_dp); 2329 intel_dp_start_link_train(intel_dp);
2329 if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) 2330 if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
2330 intel_dp_stop_link_train(intel_dp); 2331 intel_dp_stop_link_train(intel_dp);
@@ -2422,12 +2423,15 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
2422 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2423 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2423 struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); 2424 struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
2424 struct intel_dp *intel_dp = &dig_port->dp; 2425 struct intel_dp *intel_dp = &dig_port->dp;
2426 bool is_mst = intel_crtc_has_type(old_crtc_state,
2427 INTEL_OUTPUT_DP_MST);
2425 2428
2426 /* 2429 /*
2427 * Power down sink before disabling the port, otherwise we end 2430 * Power down sink before disabling the port, otherwise we end
2428 * up getting interrupts from the sink on detecting link loss. 2431 * up getting interrupts from the sink on detecting link loss.
2429 */ 2432 */
2430 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); 2433 if (!is_mst)
2434 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
2431 2435
2432 intel_disable_ddi_buf(encoder); 2436 intel_disable_ddi_buf(encoder);
2433 2437
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index c3de0918ee13..9e6956c08688 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -180,9 +180,11 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
180 intel_dp->active_mst_links--; 180 intel_dp->active_mst_links--;
181 181
182 intel_mst->connector = NULL; 182 intel_mst->connector = NULL;
183 if (intel_dp->active_mst_links == 0) 183 if (intel_dp->active_mst_links == 0) {
184 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
184 intel_dig_port->base.post_disable(&intel_dig_port->base, 185 intel_dig_port->base.post_disable(&intel_dig_port->base,
185 old_crtc_state, NULL); 186 old_crtc_state, NULL);
187 }
186 188
187 DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); 189 DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links);
188} 190}
@@ -223,7 +225,11 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
223 225
224 DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); 226 DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links);
225 227
228 if (intel_dp->active_mst_links == 0)
229 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
230
226 drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true); 231 drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true);
232
227 if (intel_dp->active_mst_links == 0) 233 if (intel_dp->active_mst_links == 0)
228 intel_dig_port->base.pre_enable(&intel_dig_port->base, 234 intel_dig_port->base.pre_enable(&intel_dig_port->base,
229 pipe_config, NULL); 235 pipe_config, NULL);