Merge drm/drm-next into drm-intel-next-queued
[linux-block.git] / drivers / gpu / drm / i915 / display / intel_dp_mst.c
index d18b406f2a7d2384bf3ed11e909f4d0bf8315c02..8273f2e07427c4d14d3656f0fefd6a67ba407da6 100644 (file)
@@ -33,6 +33,7 @@
 #include "intel_connector.h"
 #include "intel_ddi.h"
 #include "intel_display_types.h"
+#include "intel_hotplug.h"
 #include "intel_dp.h"
 #include "intel_dp_mst.h"
 #include "intel_dpio_phy.h"
@@ -316,6 +317,25 @@ intel_dp_mst_atomic_check(struct drm_connector *connector,
        return ret;
 }
 
+static void clear_act_sent(struct intel_dp *intel_dp)
+{
+       struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+       intel_de_write(i915, intel_dp->regs.dp_tp_status,
+                      DP_TP_STATUS_ACT_SENT);
+}
+
+static void wait_for_act_sent(struct intel_dp *intel_dp)
+{
+       struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+       if (intel_de_wait_for_set(i915, intel_dp->regs.dp_tp_status,
+                                 DP_TP_STATUS_ACT_SENT, 1))
+               drm_err(&i915->drm, "Timed out waiting for ACT sent\n");
+
+       drm_dp_check_act_status(&intel_dp->mst_mgr);
+}
+
 static void intel_mst_disable_dp(struct intel_atomic_state *state,
                                 struct intel_encoder *encoder,
                                 const struct intel_crtc_state *old_crtc_state,
@@ -369,6 +389,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
 
        drm_dp_update_payload_part2(&intel_dp->mst_mgr);
 
+       clear_act_sent(intel_dp);
+
        val = intel_de_read(dev_priv,
                            TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder));
        val &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
@@ -376,11 +398,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
                       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_err(&dev_priv->drm,
-                       "Timed out waiting for ACT sent when disabling\n");
-       drm_dp_check_act_status(&intel_dp->mst_mgr);
+       wait_for_act_sent(intel_dp);
 
        drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port);
 
@@ -397,6 +415,14 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
         */
        drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
                                     false);
+
+       /*
+        * BSpec 4287: disable DIP after the transcoder is disabled and before
+        * the transcoder clock select is set to none.
+        */
+       if (last_mst_stream)
+               intel_dp_set_infoframes(&intel_dig_port->base, false,
+                                       old_crtc_state, NULL);
        /*
         * From TGL spec: "If multi-stream slave transcoder: Configure
         * Transcoder Clock Select to direct no clock to the transcoder"
@@ -443,7 +469,6 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
        struct intel_connector *connector =
                to_intel_connector(conn_state->connector);
        int ret;
-       u32 temp;
        bool first_mst_stream;
 
        /* MST encoders are bound to a crtc, not to a connector,
@@ -476,8 +501,6 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
                drm_err(&dev_priv->drm, "failed to allocate vcpi\n");
 
        intel_dp->active_mst_links++;
-       temp = intel_de_read(dev_priv, intel_dp->regs.dp_tp_status);
-       intel_de_write(dev_priv, intel_dp->regs.dp_tp_status, temp);
 
        ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
 
@@ -505,19 +528,25 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &intel_dig_port->dp;
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       u32 val;
 
        drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder);
 
+       clear_act_sent(intel_dp);
+
        intel_ddi_enable_transcoder_func(encoder, pipe_config);
 
+       val = intel_de_read(dev_priv,
+                           TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
+       val |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
+       intel_de_write(dev_priv,
+                      TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder),
+                      val);
+
        drm_dbg_kms(&dev_priv->drm, "active links %d\n",
                    intel_dp->active_mst_links);
 
-       if (intel_de_wait_for_set(dev_priv, intel_dp->regs.dp_tp_status,
-                                 DP_TP_STATUS_ACT_SENT, 1))
-               drm_err(&dev_priv->drm, "Timed out waiting for ACT sent\n");
-
-       drm_dp_check_act_status(&intel_dp->mst_mgr);
+       wait_for_act_sent(intel_dp);
 
        drm_dp_update_payload_part2(&intel_dp->mst_mgr);
 
@@ -765,8 +794,17 @@ err:
        return NULL;
 }
 
+static void
+intel_dp_mst_poll_hpd_irq(struct drm_dp_mst_topology_mgr *mgr)
+{
+       struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
+
+       intel_hpd_trigger_irq(dp_to_dig_port(intel_dp));
+}
+
 static const struct drm_dp_mst_topology_cbs mst_cbs = {
        .add_connector = intel_dp_add_mst_connector,
+       .poll_hpd_irq = intel_dp_mst_poll_hpd_irq,
 };
 
 static struct intel_dp_mst_encoder *