diff options
Diffstat (limited to 'msm/dp/dp_display.c')
-rw-r--r-- | msm/dp/dp_display.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index d0c3d903..cc702307 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -62,6 +62,7 @@ enum dp_display_states { DP_STATE_SUSPENDED = BIT(7), DP_STATE_ABORTED = BIT(8), DP_STATE_HDCP_ABORTED = BIT(9), + DP_STATE_SRC_PWRDN = BIT(10), }; static char *dp_display_state_name(enum dp_display_states state) @@ -111,6 +112,10 @@ static char *dp_display_state_name(enum dp_display_states state) len += scnprintf(buf + len, sizeof(buf) - len, "|%s|", "HDCP_ABORTED"); + if (state & DP_STATE_SRC_PWRDN) + len += scnprintf(buf + len, sizeof(buf) - len, "|%s|", + "SRC_PWRDN"); + if (!strlen(buf)) return "DISCONNECTED"; @@ -970,6 +975,26 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz, dp->debug->max_pclk_khz); + + /* + * If dp video session is not restored from a previous session teardown + * by userspace, ensure the host_init is executed, in such a scenario, + * so that all the required DP resources are enabled. + * + * Below is one of the sequences of events which describe the above + * scenario: + * a. Source initiated power down resulting in host_deinit. + * b. Sink issues hpd low attention without physical cable disconnect. + * c. Source initiated power up sequence returns early because hpd is + * not high. + * d. Sink issues a hpd high attention event. + */ + if (dp_display_state_is(DP_STATE_SRC_PWRDN) && + dp_display_state_is(DP_STATE_CONFIGURED)) { + dp_display_host_init(dp); + dp_display_state_remove(DP_STATE_SRC_PWRDN); + } + dp_display_host_ready(dp); dp->link->psm_config(dp->link, &dp->panel->link_info, false); @@ -1245,7 +1270,6 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state, dp->debug->psm_enabled); - dp_display_state_remove(DP_STATE_CONFIGURED); if (dp->debug->psm_enabled && dp_display_state_is(DP_STATE_READY)) dp->link->psm_config(dp->link, &dp->panel->link_info, true); @@ -1254,6 +1278,7 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) mutex_lock(&dp->session_lock); dp_display_host_deinit(dp); + dp_display_state_remove(DP_STATE_CONFIGURED); mutex_unlock(&dp->session_lock); if (!dp->debug->sim_mode && !dp->parser->no_aux_switch @@ -1802,6 +1827,20 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel) mutex_lock(&dp->session_lock); /* + * If DP video session is restored by the userspace after display + * disconnect notification from dongle i.e. typeC cable connected to + * source but disconnected at the display side, the DP controller is + * not restored to the desired configured state. So, ensure host_init + * is executed in such a scenario so that all the DP controller + * resources are enabled for the next connection event. + */ + if (dp_display_state_is(DP_STATE_SRC_PWRDN) && + dp_display_state_is(DP_STATE_CONFIGURED)) { + dp_display_host_init(dp); + dp_display_state_remove(DP_STATE_SRC_PWRDN); + } + + /* * If the physical connection to the sink is already lost by the time * we try to set up the connection, we can just skip all the steps * here safely. @@ -1826,7 +1865,6 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel) } /* For supporting DP_PANEL_SRC_INITIATED_POWER_DOWN case */ - dp_display_host_init(dp); dp_display_host_ready(dp); if (dp->debug->psm_enabled) { @@ -2241,6 +2279,7 @@ static int dp_display_unprepare(struct dp_display *dp_display, void *panel) dp->ctrl->off(dp->ctrl); dp_display_host_unready(dp); dp_display_host_deinit(dp); + dp_display_state_add(DP_STATE_SRC_PWRDN); } dp_display_state_remove(DP_STATE_ENABLED); |