Merge "disp: msm: dp: Prevent disconnect from stopping HDCP"

Цей коміт міститься в:
qctecmdr
2019-05-03 02:04:49 -07:00
зафіксовано Gerrit - the friendly Code Review server
джерело 4be499df4b 9b4453096a
коміт c0035372e5
5 змінених файлів з 243 додано та 168 видалено

Переглянути файл

@@ -97,6 +97,9 @@ struct dp_display_private {
struct work_struct connect_work;
struct work_struct attention_work;
struct mutex session_lock;
bool suspended;
bool hdcp_delayed_off;
bool hdcp_abort;
u32 active_stream_cnt;
struct dp_mst mst;
@@ -304,9 +307,23 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
dp = container_of(dw, struct dp_display_private, hdcp_cb_work);
if (!dp->power_on || !dp->is_connected || atomic_read(&dp->aborted))
if (!dp->power_on || !dp->is_connected || atomic_read(&dp->aborted) ||
dp->hdcp_abort)
return;
if (dp->suspended) {
pr_debug("System suspending. Delay HDCP operations\n");
queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ);
return;
}
if (dp->hdcp_delayed_off) {
if (dp->hdcp.ops && dp->hdcp.ops->off)
dp->hdcp.ops->off(dp->hdcp.data);
dp_display_update_hdcp_status(dp, true);
dp->hdcp_delayed_off = false;
}
drm_dp_dpcd_readb(dp->aux->drm_aux, DP_SINK_STATUS, &sink_status);
sink_status &= (DP_RECEIVE_PORT_0_STATUS | DP_RECEIVE_PORT_1_STATUS);
if (sink_status < 1) {
@@ -891,9 +908,7 @@ static void dp_display_clean(struct dp_display_private *dp)
dp->power_on = false;
mutex_lock(&dp->session_lock);
dp->ctrl->off(dp->ctrl);
mutex_unlock(&dp->session_lock);
}
static int dp_display_handle_disconnect(struct dp_display_private *dp)
@@ -1649,8 +1664,18 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
goto end;
}
dp->hdcp_abort = true;
cancel_delayed_work_sync(&dp->hdcp_cb_work);
if (dp_display_is_hdcp_enabled(dp) &&
status->hdcp_state != HDCP_STATE_INACTIVE) {
bool off = true;
if (dp->suspended) {
pr_debug("Can't perform HDCP cleanup while suspended. Defer\n");
dp->hdcp_delayed_off = true;
goto clean;
}
flush_delayed_work(&dp->hdcp_cb_work);
if (dp->mst.mst_active) {
dp_display_hdcp_deregister_stream(dp,
@@ -1659,18 +1684,19 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
if (i != dp_panel->stream_id &&
dp->active_panels[i]) {
pr_debug("Streams are still active. Skip disabling HDCP\n");
goto stream;
off = false;
}
}
}
if (dp->hdcp.ops->off)
dp->hdcp.ops->off(dp->hdcp.data);
dp_display_update_hdcp_status(dp, true);
if (off) {
if (dp->hdcp.ops->off)
dp->hdcp.ops->off(dp->hdcp.data);
dp_display_update_hdcp_status(dp, true);
}
}
stream:
clean:
if (dp_panel->audio_supported)
dp_panel->audio->off(dp_panel->audio);
@@ -1683,8 +1709,10 @@ end:
static int dp_display_disable(struct dp_display *dp_display, void *panel)
{
int i;
struct dp_display_private *dp = NULL;
struct dp_panel *dp_panel = NULL;
struct dp_link_hdcp_status *status;
if (!dp_display || !panel) {
pr_err("invalid input\n");
@@ -1693,6 +1721,7 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel)
dp = container_of(dp_display, struct dp_display_private, dp_display);
dp_panel = panel;
status = &dp->link->hdcp_status;
mutex_lock(&dp->session_lock);
@@ -1703,6 +1732,16 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel)
dp_display_stream_disable(dp, dp_panel);
dp_display_update_dsc_resources(dp, dp_panel, false);
dp->hdcp_abort = false;
for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) {
if (dp->active_panels[i]) {
if (status->hdcp_state != HDCP_STATE_AUTHENTICATED)
queue_delayed_work(dp->wq, &dp->hdcp_cb_work,
HZ/4);
break;
}
}
end:
mutex_unlock(&dp->session_lock);
return 0;
@@ -2590,14 +2629,24 @@ static int dp_display_remove(struct platform_device *pdev)
static int dp_pm_prepare(struct device *dev)
{
struct dp_display_private *dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
dp_display_set_mst_state(g_dp_display, PM_SUSPEND);
dp->suspended = true;
return 0;
}
static void dp_pm_complete(struct device *dev)
{
struct dp_display_private *dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
dp_display_set_mst_state(g_dp_display, PM_DEFAULT);
dp->suspended = false;
}
static const struct dev_pm_ops dp_pm_ops = {