From 5ea2355a100a3c6304901d058aee06d3a6be69bc Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Tue, 3 Oct 2017 17:22:11 +0300 Subject: [PATCH] drm/i915/mst: Use MST sideband message transactions for dpms control Mime-version: 1.0 Content-type: text/plain; charset=UTF-8 Content-transfer-encoding: 8bit Git-commit: 5ea2355a100a3c6304901d058aee06d3a6be69bc Patch-mainline: v4.15-rc1 References: FATE#322643 bsc#1055900 Use the POWER_DOWN_PHY and POWER_UP_PHY sideband message transactions to set power states for downstream sinks. Apart from giving us the ability to set power state for individual sinks, this fixes the below test for me. $ xrandr --display :0 --output DP-2-2-8 --off $ xrandr --display :0 --output DP-2-2-1 --off $ xrandr --display :0 --output DP-2-2-8 --auto #Black screen $ xrandr --display :0 --output DP-2-2-1 --auto V2: Modify and document the dpms and port disable order (Ville) Add comment explaining is_mst = !crtc_state equivalence(Ville, Maarten) v3 by Jani: rebase References: https://bugs.freedesktop.org/show_bug.cgi?id=90963 References: https://bugs.freedesktop.org/show_bug.cgi?id=88124 Cc: Ville Syrjälä Cc: Lyude Cc: Maarten Lankhorst Reviewed-by: Lyude Paul Acked-by: Maarten Lankhorst Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20171003142211.860-1-jani.nikula@intel.com Acked-by: Takashi Iwai --- drivers/gpu/drm/i915/intel_ddi.c | 18 ++++++++++++++---- drivers/gpu/drm/i915/intel_dp_mst.c | 10 ++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2161,7 +2161,8 @@ static void intel_ddi_pre_enable_dp(stru intel_prepare_dp_ddi_buffers(encoder); intel_ddi_init_dp_buf_reg(encoder); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + if (!link_mst) + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) intel_dp_stop_link_train(intel_dp); @@ -2235,12 +2236,21 @@ static void intel_ddi_post_disable(struc uint32_t val; bool wait = false; - /* old_crtc_state and old_conn_state are NULL when called from DP_MST */ - if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { + /* + * old_crtc_state and old_conn_state are NULL when called from + * DP_MST. The main connector associated with this port is never + * bound to a crtc for MST. + */ + bool is_mst = !old_crtc_state; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); + /* + * Power down sink before disabling the port, otherwise we end + * up getting interrupts from the sink on detecting link loss. + */ + if (!is_mst) + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); } val = I915_READ(DDI_BUF_CTL(port)); --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -162,14 +162,19 @@ static void intel_mst_post_disable_dp(st drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port); + /* + * Power down mst path before disabling the port, otherwise we end + * up getting interrupts from the sink upon detecting link loss. + */ + drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, + false); + intel_dp->active_mst_links--; intel_mst->connector = NULL; if (intel_dp->active_mst_links == 0) { intel_dig_port->base.post_disable(&intel_dig_port->base, NULL, NULL); - - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); } DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); } @@ -196,6 +201,7 @@ static void intel_mst_pre_enable_dp(stru DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); + drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true); if (intel_dp->active_mst_links == 0) intel_dig_port->base.pre_enable(&intel_dig_port->base, pipe_config, NULL);