drm/i915/dp: Fix MST disable sequence

The disable sequence after wait for transcoder off was not correctly
implemented.
The MST disable sequence is basically the same for HSW, SKL, ICL and
TGL, with just minor changes for TGL.

With this last patch we finally fixed the hotplugs triggered by MST
sinks during the disable/enable sequence, those were causing source
to try to do a link training while it was not ready causing CPU pipe
FIFO underrrus on TGL.

v2: Only unsetting TGL_TRANS_DDI_PORT_MASK for TGL on the post
disable sequence

v4: Rebased, moved MST sequences to intel_mst_post_disable_dp()

BSpec: 4231
BSpec: 4163
BSpec: 22243
BSpec: 49190
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarJosé Roberto de Souza <jose.souza@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191223010654.67037-4-jose.souza@intel.com
parent 659f1415
......@@ -34,6 +34,7 @@
#include "intel_ddi.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_mst.h"
#include "intel_dp_link_training.h"
#include "intel_dpio_phy.h"
#include "intel_dsi.h"
......@@ -1949,17 +1950,18 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
u32 val = I915_READ(reg);
u32 val;
val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
val &= ~TRANS_DDI_FUNC_ENABLE;
if (INTEL_GEN(dev_priv) >= 12) {
val &= ~(TRANS_DDI_FUNC_ENABLE | TGL_TRANS_DDI_PORT_MASK |
TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
if (!intel_dp_mst_is_master_trans(crtc_state))
val &= ~TGL_TRANS_DDI_PORT_MASK;
} else {
val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK |
TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
val &= ~TRANS_DDI_PORT_MASK;
}
I915_WRITE(reg, val);
I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), val);
if (dev_priv->quirks & QUIRK_INCREASE_DDI_DISABLED_TIME &&
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
......@@ -3813,8 +3815,19 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
*/
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
if (INTEL_GEN(dev_priv) < 12 && !is_mst)
intel_ddi_disable_pipe_clock(old_crtc_state);
if (INTEL_GEN(dev_priv) >= 12) {
if (is_mst) {
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
u32 val;
val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
val &= ~TGL_TRANS_DDI_PORT_MASK;
I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), val);
}
} else {
if (!is_mst)
intel_ddi_disable_pipe_clock(old_crtc_state);
}
intel_disable_ddi_buf(encoder, old_crtc_state);
......
......@@ -347,6 +347,7 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
to_intel_connector(old_conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
bool last_mst_stream;
u32 val;
intel_dp->active_mst_links--;
last_mst_stream = intel_dp->active_mst_links == 0;
......@@ -357,6 +358,19 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
intel_disable_pipe(old_crtc_state);
drm_dp_update_payload_part2(&intel_dp->mst_mgr);
val = I915_READ(TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder));
val &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
I915_WRITE(TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder), val);
if (intel_de_wait_for_set(dev_priv, intel_dp->regs.dp_tp_status,
DP_TP_STATUS_ACT_SENT, 1))
DRM_ERROR("Timed out waiting for ACT sent when disabling\n");
drm_dp_check_act_status(&intel_dp->mst_mgr);
drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port);
intel_ddi_disable_transcoder_func(old_crtc_state);
if (INTEL_GEN(dev_priv) >= 9)
......@@ -364,6 +378,12 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
else
ironlake_pfit_disable(old_crtc_state);
/*
* 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);
/*
* From TGL spec: "If multi-stream slave transcoder: Configure
* Transcoder Clock Select to direct no clock to the transcoder"
......@@ -374,19 +394,6 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
if (INTEL_GEN(dev_priv) < 12 || !last_mst_stream)
intel_ddi_disable_pipe_clock(old_crtc_state);
/* this can fail */
drm_dp_check_act_status(&intel_dp->mst_mgr);
/* and this can also fail */
drm_dp_update_payload_part2(&intel_dp->mst_mgr);
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_mst->connector = NULL;
if (last_mst_stream)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment