|
@@ -99,6 +99,7 @@ struct dp_display_private {
|
|
struct mutex session_lock;
|
|
struct mutex session_lock;
|
|
bool suspended;
|
|
bool suspended;
|
|
bool hdcp_delayed_off;
|
|
bool hdcp_delayed_off;
|
|
|
|
+ bool hdcp_abort;
|
|
|
|
|
|
u32 active_stream_cnt;
|
|
u32 active_stream_cnt;
|
|
struct dp_mst mst;
|
|
struct dp_mst mst;
|
|
@@ -306,7 +307,8 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
|
|
|
|
|
|
dp = container_of(dw, struct dp_display_private, hdcp_cb_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;
|
|
return;
|
|
|
|
|
|
if (dp->suspended) {
|
|
if (dp->suspended) {
|
|
@@ -1660,13 +1662,16 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
|
|
goto end;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ dp->hdcp_abort = true;
|
|
|
|
+ cancel_delayed_work_sync(&dp->hdcp_cb_work);
|
|
if (dp_display_is_hdcp_enabled(dp) &&
|
|
if (dp_display_is_hdcp_enabled(dp) &&
|
|
status->hdcp_state != HDCP_STATE_INACTIVE) {
|
|
status->hdcp_state != HDCP_STATE_INACTIVE) {
|
|
|
|
+ bool off = true;
|
|
|
|
|
|
if (dp->suspended) {
|
|
if (dp->suspended) {
|
|
pr_debug("Can't perform HDCP cleanup while suspended. Defer\n");
|
|
pr_debug("Can't perform HDCP cleanup while suspended. Defer\n");
|
|
dp->hdcp_delayed_off = true;
|
|
dp->hdcp_delayed_off = true;
|
|
- goto stream;
|
|
|
|
|
|
+ goto clean;
|
|
}
|
|
}
|
|
|
|
|
|
flush_delayed_work(&dp->hdcp_cb_work);
|
|
flush_delayed_work(&dp->hdcp_cb_work);
|
|
@@ -1677,18 +1682,19 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
|
|
if (i != dp_panel->stream_id &&
|
|
if (i != dp_panel->stream_id &&
|
|
dp->active_panels[i]) {
|
|
dp->active_panels[i]) {
|
|
pr_debug("Streams are still active. Skip disabling HDCP\n");
|
|
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)
|
|
if (dp_panel->audio_supported)
|
|
dp_panel->audio->off(dp_panel->audio);
|
|
dp_panel->audio->off(dp_panel->audio);
|
|
|
|
|
|
@@ -1701,8 +1707,10 @@ end:
|
|
|
|
|
|
static int dp_display_disable(struct dp_display *dp_display, void *panel)
|
|
static int dp_display_disable(struct dp_display *dp_display, void *panel)
|
|
{
|
|
{
|
|
|
|
+ int i;
|
|
struct dp_display_private *dp = NULL;
|
|
struct dp_display_private *dp = NULL;
|
|
struct dp_panel *dp_panel = NULL;
|
|
struct dp_panel *dp_panel = NULL;
|
|
|
|
+ struct dp_link_hdcp_status *status;
|
|
|
|
|
|
if (!dp_display || !panel) {
|
|
if (!dp_display || !panel) {
|
|
pr_err("invalid input\n");
|
|
pr_err("invalid input\n");
|
|
@@ -1711,6 +1719,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 = container_of(dp_display, struct dp_display_private, dp_display);
|
|
dp_panel = panel;
|
|
dp_panel = panel;
|
|
|
|
+ status = &dp->link->hdcp_status;
|
|
|
|
|
|
mutex_lock(&dp->session_lock);
|
|
mutex_lock(&dp->session_lock);
|
|
|
|
|
|
@@ -1721,6 +1730,16 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel)
|
|
|
|
|
|
dp_display_stream_disable(dp, dp_panel);
|
|
dp_display_stream_disable(dp, dp_panel);
|
|
dp_display_update_dsc_resources(dp, dp_panel, false);
|
|
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:
|
|
end:
|
|
mutex_unlock(&dp->session_lock);
|
|
mutex_unlock(&dp->session_lock);
|
|
return 0;
|
|
return 0;
|