Merge tag 'drm-next-2021-02-26' of git://anongit.freedesktop.org/drm/drm
[sfrench/cifs-2.6.git] / drivers / gpu / drm / msm / dp / dp_display.c
index 3bc7ed21de2863823b1800b89bddf8d60cf54e7d..5a39da6e1eaf2779a2944a81490e22f8bc0374d2 100644 (file)
@@ -350,7 +350,7 @@ end:
        return rc;
 }
 
-static void dp_display_host_init(struct dp_display_private *dp)
+static void dp_display_host_init(struct dp_display_private *dp, int reset)
 {
        bool flip = false;
 
@@ -365,7 +365,7 @@ static void dp_display_host_init(struct dp_display_private *dp)
        dp_display_set_encoder_mode(dp);
 
        dp_power_init(dp->power, flip);
-       dp_ctrl_host_init(dp->ctrl, flip);
+       dp_ctrl_host_init(dp->ctrl, flip, reset);
        dp_aux_init(dp->aux);
        dp->core_initialized = true;
 }
@@ -403,7 +403,7 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
                goto end;
        }
 
-       dp_display_host_init(dp);
+       dp_display_host_init(dp, false);
 
        /*
         * set sink to normal operation mode -- D0
@@ -651,8 +651,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
        dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
 
        /* signal the disconnect event early to ensure proper teardown */
-       dp_display_handle_plugged_change(g_dp_display, false);
        reinit_completion(&dp->audio_comp);
+       dp_display_handle_plugged_change(g_dp_display, false);
 
        dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK |
                                        DP_DP_IRQ_HPD_INT_MASK, true);
@@ -700,6 +700,13 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
                return 0;
        }
 
+       if (state == ST_CONNECT_PENDING || state == ST_DISCONNECT_PENDING) {
+               /* wait until ST_CONNECTED */
+               dp_add_event(dp, EV_IRQ_HPD_INT, 0, 1); /* delay = 1 */
+               mutex_unlock(&dp->event_mutex);
+               return 0;
+       }
+
        ret = dp_display_usbpd_attention_cb(&dp->pdev->dev);
        if (ret == -ECONNRESET) { /* cable unplugged */
                dp->core_initialized = false;
@@ -890,6 +897,9 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data)
 
        /* wait only if audio was enabled */
        if (dp_display->audio_enabled) {
+               /* signal the disconnect event */
+               reinit_completion(&dp->audio_comp);
+               dp_display_handle_plugged_change(dp_display, false);
                if (!wait_for_completion_timeout(&dp->audio_comp,
                                HZ * 5))
                        DRM_ERROR("audio comp timeout\n");
@@ -1002,7 +1012,7 @@ int dp_display_get_test_bpp(struct msm_dp *dp)
 static void dp_display_config_hpd(struct dp_display_private *dp)
 {
 
-       dp_display_host_init(dp);
+       dp_display_host_init(dp, true);
        dp_catalog_ctrl_hpd_config(dp->catalog);
 
        /* Enable interrupt first time
@@ -1256,7 +1266,7 @@ static int dp_pm_resume(struct device *dev)
        dp->hpd_state = ST_DISCONNECTED;
 
        /* turn on dp ctrl/phy */
-       dp_display_host_init(dp);
+       dp_display_host_init(dp, true);
 
        dp_catalog_ctrl_hpd_config(dp->catalog);
 
@@ -1439,7 +1449,7 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
        state =  dp_display->hpd_state;
 
        if (state == ST_DISPLAY_OFF)
-               dp_display_host_init(dp_display);
+               dp_display_host_init(dp_display, true);
 
        dp_display_enable(dp_display, 0);