Loading drivers/gpu/drm/msm/dp/dp_display.c +32 −2 Original line number Diff line number Diff line Loading @@ -105,6 +105,8 @@ struct dp_display_private { struct work_struct connect_work; struct work_struct attention_work; struct mutex session_lock; bool suspended; bool hdcp_delayed_off; u32 active_stream_cnt; struct dp_mst mst; Loading Loading @@ -315,6 +317,19 @@ static void dp_display_hdcp_cb_work(struct work_struct *work) if (!dp->power_on || !dp->is_connected || atomic_read(&dp->aborted)) 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) { Loading Loading @@ -936,9 +951,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) Loading Loading @@ -1694,6 +1707,13 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) if (dp_display_is_hdcp_enabled(dp) && status->hdcp_state != HDCP_STATE_INACTIVE) { if (dp->suspended) { pr_debug("Can't perform HDCP cleanup while suspended. Defer\n"); dp->hdcp_delayed_off = true; goto stream; } flush_delayed_work(&dp->hdcp_cb_work); if (dp->mst.mst_active) { dp_display_hdcp_deregister_stream(dp, Loading Loading @@ -2627,14 +2647,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 = { Loading drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +12 −13 Original line number Diff line number Diff line Loading @@ -277,19 +277,22 @@ static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl) static int dp_hdcp2p2_register(void *input, bool mst_enabled) { int rc; enum sde_hdcp_2x_device_type device_type; struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; struct dp_hdcp2p2_ctrl *ctrl = input; struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_ENABLE}; rc = dp_hdcp2p2_valid_handle(ctrl); if (rc) return rc; if (mst_enabled) device_type = HDCP_TXMTR_DP_MST; cdata.device_type = HDCP_TXMTR_DP_MST; else device_type = HDCP_TXMTR_DP; cdata.device_type = HDCP_TXMTR_DP; cdata.context = ctrl->lib_ctx; rc = ctrl->lib->wakeup(&cdata); return sde_hdcp_2x_enable(ctrl->lib_ctx, device_type); return rc; } static int dp_hdcp2p2_on(void *input) Loading @@ -315,25 +318,21 @@ static void dp_hdcp2p2_off(void *input) { int rc; struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_DISABLE}; rc = dp_hdcp2p2_valid_handle(ctrl); if (rc) return; if (atomic_read(&ctrl->auth_state) != HDCP_STATE_AUTH_FAIL) { cdata.cmd = HDCP_2X_CMD_STOP; cdata.context = ctrl->lib_ctx; dp_hdcp2p2_wakeup_lib(ctrl, &cdata); } dp_hdcp2p2_set_interrupts(ctrl, false); dp_hdcp2p2_reset(ctrl); kthread_flush_worker(&ctrl->worker); sde_hdcp_2x_disable(ctrl->lib_ctx); cdata.context = ctrl->lib_ctx; ctrl->lib->wakeup(&cdata); } static int dp_hdcp2p2_authenticate(void *input) Loading drivers/gpu/drm/msm/sde_hdcp.h +1 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ struct sde_hdcp_stream { u8 stream_id; u8 virtual_channel; u32 stream_handle; bool active; }; struct sde_hdcp_init_data { Loading drivers/gpu/drm/msm/sde_hdcp_2x.c +154 −168 Original line number Diff line number Diff line Loading @@ -76,13 +76,13 @@ struct sde_hdcp_2x_ctrl { u8 min_enc_level; struct list_head stream_handles; u8 stream_count; struct stream_info *streams; u8 num_streams; struct task_struct *thread; struct completion response_completion; struct kthread_worker worker; struct kthread_work wk_enable; struct kthread_work wk_disable; struct kthread_work wk_init; struct kthread_work wk_start_auth; struct kthread_work wk_msg_sent; Loading @@ -92,8 +92,7 @@ struct sde_hdcp_2x_ctrl { struct kthread_work wk_stream; struct kthread_work wk_wait; struct kthread_work wk_send_type; struct kthread_work wk_open_stream; struct kthread_work wk_close_stream; struct kthread_work wk_manage_stream; }; static const char *sde_hdcp_2x_message_name(int msg_id) Loading Loading @@ -343,6 +342,8 @@ static bool sde_hdcp_2x_client_feature_supported(void *data) { struct sde_hdcp_2x_ctrl *hdcp = data; kthread_flush_work(&hdcp->wk_enable); return hdcp2_feature_supported(hdcp->hdcp2_ctx); } Loading @@ -361,24 +362,20 @@ static void sde_hdcp_2x_force_encryption(void *data, bool enable) static int sde_hdcp_2x_check_valid_state(struct sde_hdcp_2x_ctrl *hdcp) { int rc = 0; if (!list_empty(&hdcp->worker.work_list)) sde_hdcp_2x_check_worker_status(hdcp); if (hdcp->wakeup_cmd == HDCP_2X_CMD_START) { if (!list_empty(&hdcp->worker.work_list)) { rc = -EBUSY; goto exit; } } else { if (atomic_read(&hdcp->hdcp_off)) { if (!hdcp->hdcp2_ctx) kthread_flush_work(&hdcp->wk_enable); if (hdcp->wakeup_cmd != HDCP_2X_CMD_ENABLE && !hdcp->hdcp2_ctx) { pr_err("HDCP enable must be called\n"); return -EINVAL; } else if (atomic_read(&hdcp->hdcp_off)) { pr_debug("hdcp2.2 session tearing down\n"); goto exit; } } exit: return rc; return 0; } static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp) Loading Loading @@ -852,61 +849,37 @@ static struct list_head *sde_hdcp_2x_stream_present( return entry; } static void sde_hdcp_2x_open_stream(struct sde_hdcp_2x_ctrl *hdcp) static void sde_hdcp_2x_manage_stream_work(struct kthread_work *work) { int rc; size_t i, iterations; u8 stream_id; u8 virtual_channel; u32 stream_handle = 0; struct list_head *entry; struct list_head *element; struct sde_hdcp_stream *stream_entry; struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_manage_stream); bool query_streams = false; if (!hdcp->streams) { pr_err("Array of streams to register is NULL\n"); return; } iterations = min(hdcp->num_streams, (u8)(MAX_STREAM_COUNT)); for (i = 0; i < iterations; i++) { if (hdcp->stream_count == MAX_STREAM_COUNT) { pr_debug("Registered the maximum amount of streams\n"); break; } stream_id = hdcp->streams[i].stream_id; virtual_channel = hdcp->streams[i].virtual_channel; pr_debug("Opening stream %d, virtual channel %d\n", stream_id, virtual_channel); entry = hdcp->stream_handles.next; while (entry != &hdcp->stream_handles) { stream_entry = list_entry(entry, struct sde_hdcp_stream, list); element = entry; entry = entry->next; if (sde_hdcp_2x_stream_present(hdcp, stream_id, virtual_channel)) { pr_debug("Stream %d, virtual channel %d already open\n", stream_id, virtual_channel); continue; } rc = hdcp2_open_stream(hdcp->hdcp2_ctx, virtual_channel, stream_id, &stream_handle); if (rc) { if (!stream_entry->active) { hdcp2_close_stream(hdcp->hdcp2_ctx, stream_entry->stream_handle); hdcp->stream_count--; list_del(element); kzfree(stream_entry); query_streams = true; } else if (!stream_entry->stream_handle) { if (hdcp2_open_stream(hdcp->hdcp2_ctx, stream_entry->virtual_channel, stream_entry->stream_id, &stream_entry->stream_handle)) pr_err("Unable to open stream %d, virtual channel %d\n", stream_id, virtual_channel); } else { struct sde_hdcp_stream *stream = kzalloc(sizeof(struct sde_hdcp_stream), GFP_KERNEL); if (!stream) break; INIT_LIST_HEAD(&stream->list); stream->stream_handle = stream_handle; stream->stream_id = stream_id; stream->virtual_channel = virtual_channel; list_add(&stream->list, &hdcp->stream_handles); hdcp->stream_count++; stream_entry->stream_id, stream_entry->virtual_channel); else query_streams = true; } } Loading @@ -915,75 +888,74 @@ static void sde_hdcp_2x_open_stream(struct sde_hdcp_2x_ctrl *hdcp) HDCP_2X_EXECUTE(stream); } static void sde_hdcp_2x_open_stream_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_open_stream); sde_hdcp_2x_open_stream(hdcp); } static void sde_hdcp_2x_close_stream(struct sde_hdcp_2x_ctrl *hdcp) static bool sde_remove_streams(struct sde_hdcp_2x_ctrl *hdcp, struct stream_info *streams, u8 num_streams) { int rc; size_t i, iterations; u8 i; u8 stream_id; u8 virtual_channel; struct list_head *entry; struct sde_hdcp_stream *stream_entry; bool query_streams = false; if (!hdcp->streams) { pr_err("Array of streams to register is NULL\n"); return; } iterations = min(hdcp->num_streams, (u8)(MAX_STREAM_COUNT)); for (i = 0; i < iterations; i++) { if (hdcp->stream_count == 0) { pr_debug("No streams are currently registered\n"); return; } stream_id = hdcp->streams[i].stream_id; virtual_channel = hdcp->streams[i].virtual_channel; pr_debug("Closing stream %d, virtual channel %d\n", stream_id, virtual_channel); bool changed = false; for (i = 0 ; i < num_streams; i++) { stream_id = streams[i].stream_id; virtual_channel = streams[i].virtual_channel; entry = sde_hdcp_2x_stream_present(hdcp, stream_id, virtual_channel); if (!entry) { pr_err("Unable to find stream %d, virtual channel %d\n" , stream_id, virtual_channel); if (!entry) continue; } stream_entry = list_entry(entry, struct sde_hdcp_stream, list); rc = hdcp2_close_stream(hdcp->hdcp2_ctx, stream_entry->stream_handle); if (rc) pr_err("Unable to close stream %d, virtual channel %d\n" , stream_id, virtual_channel); if (!stream_entry->stream_handle) { /* Stream wasn't fully initialized so remove it */ hdcp->stream_count--; list_del(entry); kzfree(stream_entry); query_streams = true; } else { stream_entry->active = false; } changed = true; } if (query_streams && hdcp->authenticated) HDCP_2X_EXECUTE(stream); return changed; } static void sde_hdcp_2x_close_stream_work(struct kthread_work *work) static bool sde_add_streams(struct sde_hdcp_2x_ctrl *hdcp, struct stream_info *streams, u8 num_streams) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_close_stream); sde_hdcp_2x_close_stream(hdcp); u8 i; u8 stream_id; u8 virtual_channel; struct sde_hdcp_stream *stream; bool changed = false; for (i = 0 ; i < num_streams; i++) { stream_id = streams[i].stream_id; virtual_channel = streams[i].virtual_channel; if (sde_hdcp_2x_stream_present(hdcp, stream_id, virtual_channel)) continue; stream = kzalloc(sizeof(struct sde_hdcp_stream), GFP_KERNEL); if (!stream) continue; INIT_LIST_HEAD(&stream->list); stream->stream_handle = 0; stream->stream_id = stream_id; stream->virtual_channel = virtual_channel; stream->active = true; list_add(&stream->list, &hdcp->stream_handles); hdcp->stream_count++; changed = true; } return changed; } static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) Loading Loading @@ -1017,7 +989,18 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) complete_all(&hdcp->response_completion); switch (hdcp->wakeup_cmd) { case HDCP_2X_CMD_ENABLE: kthread_cancel_work_sync(&hdcp->wk_enable); hdcp->device_type = data->device_type; HDCP_2X_EXECUTE(enable); break; case HDCP_2X_CMD_DISABLE: if (!atomic_xchg(&hdcp->hdcp_off, 1)) HDCP_2X_EXECUTE(clean); HDCP_2X_EXECUTE(disable); break; case HDCP_2X_CMD_START: kthread_cancel_work_sync(&hdcp->wk_init); hdcp->no_stored_km = 0; hdcp->repeater_flag = false; hdcp->update_stream = false; Loading @@ -1028,6 +1011,7 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) HDCP_2X_EXECUTE(init); break; case HDCP_2X_CMD_START_AUTH: kthread_cancel_work_sync(&hdcp->wk_start_auth); HDCP_2X_EXECUTE(start_auth); break; case HDCP_2X_CMD_STOP: Loading @@ -1035,6 +1019,7 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) HDCP_2X_EXECUTE(clean); break; case HDCP_2X_CMD_MSG_SEND_SUCCESS: kthread_cancel_work_sync(&hdcp->wk_msg_sent); HDCP_2X_EXECUTE(msg_sent); break; case HDCP_2X_CMD_MSG_SEND_FAILED: Loading @@ -1043,34 +1028,37 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) HDCP_2X_EXECUTE(clean); break; case HDCP_2X_CMD_MSG_RECV_SUCCESS: kthread_cancel_work_sync(&hdcp->wk_msg_recvd); HDCP_2X_EXECUTE(msg_recvd); break; case HDCP_2X_CMD_MSG_RECV_TIMEOUT: kthread_cancel_work_sync(&hdcp->wk_timeout); HDCP_2X_EXECUTE(timeout); break; case HDCP_2X_CMD_QUERY_STREAM_TYPE: kthread_cancel_work_sync(&hdcp->wk_stream); HDCP_2X_EXECUTE(stream); break; case HDCP_2X_CMD_MIN_ENC_LEVEL: kthread_cancel_work_sync(&hdcp->wk_send_type); hdcp->min_enc_level = data->min_enc_level; if (!hdcp->repeater_flag) { HDCP_2X_EXECUTE(send_type); break; } kthread_cancel_work_sync(&hdcp->wk_stream); HDCP_2X_EXECUTE(stream); break; case HDCP_2X_CMD_OPEN_STREAMS: hdcp->streams = data->streams; hdcp->num_streams = data->num_streams; HDCP_2X_EXECUTE(open_stream); kthread_flush_work(&hdcp->wk_open_stream); kthread_cancel_work_sync(&hdcp->wk_manage_stream); if (sde_add_streams(hdcp, data->streams, data->num_streams)) HDCP_2X_EXECUTE(manage_stream); break; case HDCP_2X_CMD_CLOSE_STREAMS: hdcp->streams = data->streams; hdcp->num_streams = data->num_streams; HDCP_2X_EXECUTE(close_stream); kthread_flush_work(&hdcp->wk_close_stream); kthread_cancel_work_sync(&hdcp->wk_manage_stream); if (sde_remove_streams(hdcp, data->streams, data->num_streams)) HDCP_2X_EXECUTE(manage_stream); break; default: pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd); Loading @@ -1081,6 +1069,37 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) return rc; } static void sde_hdcp_2x_enable_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_enable); if (!hdcp) return; if (hdcp->hdcp2_ctx) { pr_debug("HDCP library context already acquired\n"); return; } hdcp->hdcp2_ctx = hdcp2_init(hdcp->device_type); if (!hdcp->hdcp2_ctx) pr_err("Unable to acquire HDCP library handle\n"); } static void sde_hdcp_2x_disable_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_disable); if (!hdcp->hdcp2_ctx) return; hdcp2_deinit(hdcp->hdcp2_ctx); hdcp->hdcp2_ctx = NULL; } int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) { int rc = 0; Loading Loading @@ -1127,6 +1146,8 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) kthread_init_worker(&hdcp->worker); kthread_init_work(&hdcp->wk_enable, sde_hdcp_2x_enable_work); kthread_init_work(&hdcp->wk_disable, sde_hdcp_2x_disable_work); kthread_init_work(&hdcp->wk_init, sde_hdcp_2x_init_work); kthread_init_work(&hdcp->wk_start_auth, sde_hdcp_2x_start_auth_work); kthread_init_work(&hdcp->wk_msg_sent, sde_hdcp_2x_msg_sent_work); Loading @@ -1136,9 +1157,8 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) kthread_init_work(&hdcp->wk_stream, sde_hdcp_2x_query_stream_work); kthread_init_work(&hdcp->wk_wait, sde_hdcp_2x_wait_for_response_work); kthread_init_work(&hdcp->wk_send_type, sde_hdcp_2x_send_type_work); kthread_init_work(&hdcp->wk_open_stream, sde_hdcp_2x_open_stream_work); kthread_init_work(&hdcp->wk_close_stream, sde_hdcp_2x_close_stream_work); kthread_init_work(&hdcp->wk_manage_stream, sde_hdcp_2x_manage_stream_work); init_completion(&hdcp->response_completion); Loading @@ -1164,41 +1184,6 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) return rc; } int sde_hdcp_2x_enable(void *data, enum sde_hdcp_2x_device_type device_type) { int rc = 0; struct sde_hdcp_2x_ctrl *hdcp = data; if (!hdcp) return -EINVAL; if (hdcp->hdcp2_ctx) { pr_debug("HDCP library context already acquired\n"); return 0; } hdcp->device_type = device_type; hdcp->hdcp2_ctx = hdcp2_init(hdcp->device_type); if (!hdcp->hdcp2_ctx) { pr_err("Unable to acquire HDCP library handle\n"); return -ENOMEM; } return rc; } void sde_hdcp_2x_disable(void *data) { struct sde_hdcp_2x_ctrl *hdcp = data; if (!hdcp->hdcp2_ctx) return; kthread_flush_worker(&hdcp->worker); hdcp2_deinit(hdcp->hdcp2_ctx); hdcp->hdcp2_ctx = NULL; } void sde_hdcp_2x_deregister(void *data) { struct sde_hdcp_2x_ctrl *hdcp = data; Loading @@ -1206,8 +1191,9 @@ void sde_hdcp_2x_deregister(void *data) if (!hdcp) return; sde_hdcp_2x_disable(data); kthread_stop(hdcp->thread); hdcp2_deinit(hdcp->hdcp2_ctx); hdcp->hdcp2_ctx = NULL; mutex_destroy(&hdcp->wakeup_mutex); kzfree(hdcp); } drivers/gpu/drm/msm/sde_hdcp_2x.h +3 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ */ enum sde_hdcp_2x_wakeup_cmd { HDCP_2X_CMD_INVALID, HDCP_2X_CMD_ENABLE, HDCP_2X_CMD_DISABLE, HDCP_2X_CMD_START, HDCP_2X_CMD_START_AUTH, HDCP_2X_CMD_STOP, Loading Loading @@ -93,6 +95,7 @@ enum sde_hdcp_2x_device_type { */ struct sde_hdcp_2x_wakeup_data { enum sde_hdcp_2x_wakeup_cmd cmd; enum sde_hdcp_2x_device_type device_type; void *context; uint32_t total_message_length; uint32_t timeout; Loading Loading
drivers/gpu/drm/msm/dp/dp_display.c +32 −2 Original line number Diff line number Diff line Loading @@ -105,6 +105,8 @@ struct dp_display_private { struct work_struct connect_work; struct work_struct attention_work; struct mutex session_lock; bool suspended; bool hdcp_delayed_off; u32 active_stream_cnt; struct dp_mst mst; Loading Loading @@ -315,6 +317,19 @@ static void dp_display_hdcp_cb_work(struct work_struct *work) if (!dp->power_on || !dp->is_connected || atomic_read(&dp->aborted)) 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) { Loading Loading @@ -936,9 +951,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) Loading Loading @@ -1694,6 +1707,13 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) if (dp_display_is_hdcp_enabled(dp) && status->hdcp_state != HDCP_STATE_INACTIVE) { if (dp->suspended) { pr_debug("Can't perform HDCP cleanup while suspended. Defer\n"); dp->hdcp_delayed_off = true; goto stream; } flush_delayed_work(&dp->hdcp_cb_work); if (dp->mst.mst_active) { dp_display_hdcp_deregister_stream(dp, Loading Loading @@ -2627,14 +2647,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 = { Loading
drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +12 −13 Original line number Diff line number Diff line Loading @@ -277,19 +277,22 @@ static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl) static int dp_hdcp2p2_register(void *input, bool mst_enabled) { int rc; enum sde_hdcp_2x_device_type device_type; struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; struct dp_hdcp2p2_ctrl *ctrl = input; struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_ENABLE}; rc = dp_hdcp2p2_valid_handle(ctrl); if (rc) return rc; if (mst_enabled) device_type = HDCP_TXMTR_DP_MST; cdata.device_type = HDCP_TXMTR_DP_MST; else device_type = HDCP_TXMTR_DP; cdata.device_type = HDCP_TXMTR_DP; cdata.context = ctrl->lib_ctx; rc = ctrl->lib->wakeup(&cdata); return sde_hdcp_2x_enable(ctrl->lib_ctx, device_type); return rc; } static int dp_hdcp2p2_on(void *input) Loading @@ -315,25 +318,21 @@ static void dp_hdcp2p2_off(void *input) { int rc; struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_DISABLE}; rc = dp_hdcp2p2_valid_handle(ctrl); if (rc) return; if (atomic_read(&ctrl->auth_state) != HDCP_STATE_AUTH_FAIL) { cdata.cmd = HDCP_2X_CMD_STOP; cdata.context = ctrl->lib_ctx; dp_hdcp2p2_wakeup_lib(ctrl, &cdata); } dp_hdcp2p2_set_interrupts(ctrl, false); dp_hdcp2p2_reset(ctrl); kthread_flush_worker(&ctrl->worker); sde_hdcp_2x_disable(ctrl->lib_ctx); cdata.context = ctrl->lib_ctx; ctrl->lib->wakeup(&cdata); } static int dp_hdcp2p2_authenticate(void *input) Loading
drivers/gpu/drm/msm/sde_hdcp.h +1 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ struct sde_hdcp_stream { u8 stream_id; u8 virtual_channel; u32 stream_handle; bool active; }; struct sde_hdcp_init_data { Loading
drivers/gpu/drm/msm/sde_hdcp_2x.c +154 −168 Original line number Diff line number Diff line Loading @@ -76,13 +76,13 @@ struct sde_hdcp_2x_ctrl { u8 min_enc_level; struct list_head stream_handles; u8 stream_count; struct stream_info *streams; u8 num_streams; struct task_struct *thread; struct completion response_completion; struct kthread_worker worker; struct kthread_work wk_enable; struct kthread_work wk_disable; struct kthread_work wk_init; struct kthread_work wk_start_auth; struct kthread_work wk_msg_sent; Loading @@ -92,8 +92,7 @@ struct sde_hdcp_2x_ctrl { struct kthread_work wk_stream; struct kthread_work wk_wait; struct kthread_work wk_send_type; struct kthread_work wk_open_stream; struct kthread_work wk_close_stream; struct kthread_work wk_manage_stream; }; static const char *sde_hdcp_2x_message_name(int msg_id) Loading Loading @@ -343,6 +342,8 @@ static bool sde_hdcp_2x_client_feature_supported(void *data) { struct sde_hdcp_2x_ctrl *hdcp = data; kthread_flush_work(&hdcp->wk_enable); return hdcp2_feature_supported(hdcp->hdcp2_ctx); } Loading @@ -361,24 +362,20 @@ static void sde_hdcp_2x_force_encryption(void *data, bool enable) static int sde_hdcp_2x_check_valid_state(struct sde_hdcp_2x_ctrl *hdcp) { int rc = 0; if (!list_empty(&hdcp->worker.work_list)) sde_hdcp_2x_check_worker_status(hdcp); if (hdcp->wakeup_cmd == HDCP_2X_CMD_START) { if (!list_empty(&hdcp->worker.work_list)) { rc = -EBUSY; goto exit; } } else { if (atomic_read(&hdcp->hdcp_off)) { if (!hdcp->hdcp2_ctx) kthread_flush_work(&hdcp->wk_enable); if (hdcp->wakeup_cmd != HDCP_2X_CMD_ENABLE && !hdcp->hdcp2_ctx) { pr_err("HDCP enable must be called\n"); return -EINVAL; } else if (atomic_read(&hdcp->hdcp_off)) { pr_debug("hdcp2.2 session tearing down\n"); goto exit; } } exit: return rc; return 0; } static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp) Loading Loading @@ -852,61 +849,37 @@ static struct list_head *sde_hdcp_2x_stream_present( return entry; } static void sde_hdcp_2x_open_stream(struct sde_hdcp_2x_ctrl *hdcp) static void sde_hdcp_2x_manage_stream_work(struct kthread_work *work) { int rc; size_t i, iterations; u8 stream_id; u8 virtual_channel; u32 stream_handle = 0; struct list_head *entry; struct list_head *element; struct sde_hdcp_stream *stream_entry; struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_manage_stream); bool query_streams = false; if (!hdcp->streams) { pr_err("Array of streams to register is NULL\n"); return; } iterations = min(hdcp->num_streams, (u8)(MAX_STREAM_COUNT)); for (i = 0; i < iterations; i++) { if (hdcp->stream_count == MAX_STREAM_COUNT) { pr_debug("Registered the maximum amount of streams\n"); break; } stream_id = hdcp->streams[i].stream_id; virtual_channel = hdcp->streams[i].virtual_channel; pr_debug("Opening stream %d, virtual channel %d\n", stream_id, virtual_channel); entry = hdcp->stream_handles.next; while (entry != &hdcp->stream_handles) { stream_entry = list_entry(entry, struct sde_hdcp_stream, list); element = entry; entry = entry->next; if (sde_hdcp_2x_stream_present(hdcp, stream_id, virtual_channel)) { pr_debug("Stream %d, virtual channel %d already open\n", stream_id, virtual_channel); continue; } rc = hdcp2_open_stream(hdcp->hdcp2_ctx, virtual_channel, stream_id, &stream_handle); if (rc) { if (!stream_entry->active) { hdcp2_close_stream(hdcp->hdcp2_ctx, stream_entry->stream_handle); hdcp->stream_count--; list_del(element); kzfree(stream_entry); query_streams = true; } else if (!stream_entry->stream_handle) { if (hdcp2_open_stream(hdcp->hdcp2_ctx, stream_entry->virtual_channel, stream_entry->stream_id, &stream_entry->stream_handle)) pr_err("Unable to open stream %d, virtual channel %d\n", stream_id, virtual_channel); } else { struct sde_hdcp_stream *stream = kzalloc(sizeof(struct sde_hdcp_stream), GFP_KERNEL); if (!stream) break; INIT_LIST_HEAD(&stream->list); stream->stream_handle = stream_handle; stream->stream_id = stream_id; stream->virtual_channel = virtual_channel; list_add(&stream->list, &hdcp->stream_handles); hdcp->stream_count++; stream_entry->stream_id, stream_entry->virtual_channel); else query_streams = true; } } Loading @@ -915,75 +888,74 @@ static void sde_hdcp_2x_open_stream(struct sde_hdcp_2x_ctrl *hdcp) HDCP_2X_EXECUTE(stream); } static void sde_hdcp_2x_open_stream_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_open_stream); sde_hdcp_2x_open_stream(hdcp); } static void sde_hdcp_2x_close_stream(struct sde_hdcp_2x_ctrl *hdcp) static bool sde_remove_streams(struct sde_hdcp_2x_ctrl *hdcp, struct stream_info *streams, u8 num_streams) { int rc; size_t i, iterations; u8 i; u8 stream_id; u8 virtual_channel; struct list_head *entry; struct sde_hdcp_stream *stream_entry; bool query_streams = false; if (!hdcp->streams) { pr_err("Array of streams to register is NULL\n"); return; } iterations = min(hdcp->num_streams, (u8)(MAX_STREAM_COUNT)); for (i = 0; i < iterations; i++) { if (hdcp->stream_count == 0) { pr_debug("No streams are currently registered\n"); return; } stream_id = hdcp->streams[i].stream_id; virtual_channel = hdcp->streams[i].virtual_channel; pr_debug("Closing stream %d, virtual channel %d\n", stream_id, virtual_channel); bool changed = false; for (i = 0 ; i < num_streams; i++) { stream_id = streams[i].stream_id; virtual_channel = streams[i].virtual_channel; entry = sde_hdcp_2x_stream_present(hdcp, stream_id, virtual_channel); if (!entry) { pr_err("Unable to find stream %d, virtual channel %d\n" , stream_id, virtual_channel); if (!entry) continue; } stream_entry = list_entry(entry, struct sde_hdcp_stream, list); rc = hdcp2_close_stream(hdcp->hdcp2_ctx, stream_entry->stream_handle); if (rc) pr_err("Unable to close stream %d, virtual channel %d\n" , stream_id, virtual_channel); if (!stream_entry->stream_handle) { /* Stream wasn't fully initialized so remove it */ hdcp->stream_count--; list_del(entry); kzfree(stream_entry); query_streams = true; } else { stream_entry->active = false; } changed = true; } if (query_streams && hdcp->authenticated) HDCP_2X_EXECUTE(stream); return changed; } static void sde_hdcp_2x_close_stream_work(struct kthread_work *work) static bool sde_add_streams(struct sde_hdcp_2x_ctrl *hdcp, struct stream_info *streams, u8 num_streams) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_close_stream); sde_hdcp_2x_close_stream(hdcp); u8 i; u8 stream_id; u8 virtual_channel; struct sde_hdcp_stream *stream; bool changed = false; for (i = 0 ; i < num_streams; i++) { stream_id = streams[i].stream_id; virtual_channel = streams[i].virtual_channel; if (sde_hdcp_2x_stream_present(hdcp, stream_id, virtual_channel)) continue; stream = kzalloc(sizeof(struct sde_hdcp_stream), GFP_KERNEL); if (!stream) continue; INIT_LIST_HEAD(&stream->list); stream->stream_handle = 0; stream->stream_id = stream_id; stream->virtual_channel = virtual_channel; stream->active = true; list_add(&stream->list, &hdcp->stream_handles); hdcp->stream_count++; changed = true; } return changed; } static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) Loading Loading @@ -1017,7 +989,18 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) complete_all(&hdcp->response_completion); switch (hdcp->wakeup_cmd) { case HDCP_2X_CMD_ENABLE: kthread_cancel_work_sync(&hdcp->wk_enable); hdcp->device_type = data->device_type; HDCP_2X_EXECUTE(enable); break; case HDCP_2X_CMD_DISABLE: if (!atomic_xchg(&hdcp->hdcp_off, 1)) HDCP_2X_EXECUTE(clean); HDCP_2X_EXECUTE(disable); break; case HDCP_2X_CMD_START: kthread_cancel_work_sync(&hdcp->wk_init); hdcp->no_stored_km = 0; hdcp->repeater_flag = false; hdcp->update_stream = false; Loading @@ -1028,6 +1011,7 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) HDCP_2X_EXECUTE(init); break; case HDCP_2X_CMD_START_AUTH: kthread_cancel_work_sync(&hdcp->wk_start_auth); HDCP_2X_EXECUTE(start_auth); break; case HDCP_2X_CMD_STOP: Loading @@ -1035,6 +1019,7 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) HDCP_2X_EXECUTE(clean); break; case HDCP_2X_CMD_MSG_SEND_SUCCESS: kthread_cancel_work_sync(&hdcp->wk_msg_sent); HDCP_2X_EXECUTE(msg_sent); break; case HDCP_2X_CMD_MSG_SEND_FAILED: Loading @@ -1043,34 +1028,37 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) HDCP_2X_EXECUTE(clean); break; case HDCP_2X_CMD_MSG_RECV_SUCCESS: kthread_cancel_work_sync(&hdcp->wk_msg_recvd); HDCP_2X_EXECUTE(msg_recvd); break; case HDCP_2X_CMD_MSG_RECV_TIMEOUT: kthread_cancel_work_sync(&hdcp->wk_timeout); HDCP_2X_EXECUTE(timeout); break; case HDCP_2X_CMD_QUERY_STREAM_TYPE: kthread_cancel_work_sync(&hdcp->wk_stream); HDCP_2X_EXECUTE(stream); break; case HDCP_2X_CMD_MIN_ENC_LEVEL: kthread_cancel_work_sync(&hdcp->wk_send_type); hdcp->min_enc_level = data->min_enc_level; if (!hdcp->repeater_flag) { HDCP_2X_EXECUTE(send_type); break; } kthread_cancel_work_sync(&hdcp->wk_stream); HDCP_2X_EXECUTE(stream); break; case HDCP_2X_CMD_OPEN_STREAMS: hdcp->streams = data->streams; hdcp->num_streams = data->num_streams; HDCP_2X_EXECUTE(open_stream); kthread_flush_work(&hdcp->wk_open_stream); kthread_cancel_work_sync(&hdcp->wk_manage_stream); if (sde_add_streams(hdcp, data->streams, data->num_streams)) HDCP_2X_EXECUTE(manage_stream); break; case HDCP_2X_CMD_CLOSE_STREAMS: hdcp->streams = data->streams; hdcp->num_streams = data->num_streams; HDCP_2X_EXECUTE(close_stream); kthread_flush_work(&hdcp->wk_close_stream); kthread_cancel_work_sync(&hdcp->wk_manage_stream); if (sde_remove_streams(hdcp, data->streams, data->num_streams)) HDCP_2X_EXECUTE(manage_stream); break; default: pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd); Loading @@ -1081,6 +1069,37 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) return rc; } static void sde_hdcp_2x_enable_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_enable); if (!hdcp) return; if (hdcp->hdcp2_ctx) { pr_debug("HDCP library context already acquired\n"); return; } hdcp->hdcp2_ctx = hdcp2_init(hdcp->device_type); if (!hdcp->hdcp2_ctx) pr_err("Unable to acquire HDCP library handle\n"); } static void sde_hdcp_2x_disable_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_disable); if (!hdcp->hdcp2_ctx) return; hdcp2_deinit(hdcp->hdcp2_ctx); hdcp->hdcp2_ctx = NULL; } int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) { int rc = 0; Loading Loading @@ -1127,6 +1146,8 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) kthread_init_worker(&hdcp->worker); kthread_init_work(&hdcp->wk_enable, sde_hdcp_2x_enable_work); kthread_init_work(&hdcp->wk_disable, sde_hdcp_2x_disable_work); kthread_init_work(&hdcp->wk_init, sde_hdcp_2x_init_work); kthread_init_work(&hdcp->wk_start_auth, sde_hdcp_2x_start_auth_work); kthread_init_work(&hdcp->wk_msg_sent, sde_hdcp_2x_msg_sent_work); Loading @@ -1136,9 +1157,8 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) kthread_init_work(&hdcp->wk_stream, sde_hdcp_2x_query_stream_work); kthread_init_work(&hdcp->wk_wait, sde_hdcp_2x_wait_for_response_work); kthread_init_work(&hdcp->wk_send_type, sde_hdcp_2x_send_type_work); kthread_init_work(&hdcp->wk_open_stream, sde_hdcp_2x_open_stream_work); kthread_init_work(&hdcp->wk_close_stream, sde_hdcp_2x_close_stream_work); kthread_init_work(&hdcp->wk_manage_stream, sde_hdcp_2x_manage_stream_work); init_completion(&hdcp->response_completion); Loading @@ -1164,41 +1184,6 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) return rc; } int sde_hdcp_2x_enable(void *data, enum sde_hdcp_2x_device_type device_type) { int rc = 0; struct sde_hdcp_2x_ctrl *hdcp = data; if (!hdcp) return -EINVAL; if (hdcp->hdcp2_ctx) { pr_debug("HDCP library context already acquired\n"); return 0; } hdcp->device_type = device_type; hdcp->hdcp2_ctx = hdcp2_init(hdcp->device_type); if (!hdcp->hdcp2_ctx) { pr_err("Unable to acquire HDCP library handle\n"); return -ENOMEM; } return rc; } void sde_hdcp_2x_disable(void *data) { struct sde_hdcp_2x_ctrl *hdcp = data; if (!hdcp->hdcp2_ctx) return; kthread_flush_worker(&hdcp->worker); hdcp2_deinit(hdcp->hdcp2_ctx); hdcp->hdcp2_ctx = NULL; } void sde_hdcp_2x_deregister(void *data) { struct sde_hdcp_2x_ctrl *hdcp = data; Loading @@ -1206,8 +1191,9 @@ void sde_hdcp_2x_deregister(void *data) if (!hdcp) return; sde_hdcp_2x_disable(data); kthread_stop(hdcp->thread); hdcp2_deinit(hdcp->hdcp2_ctx); hdcp->hdcp2_ctx = NULL; mutex_destroy(&hdcp->wakeup_mutex); kzfree(hdcp); }
drivers/gpu/drm/msm/sde_hdcp_2x.h +3 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ */ enum sde_hdcp_2x_wakeup_cmd { HDCP_2X_CMD_INVALID, HDCP_2X_CMD_ENABLE, HDCP_2X_CMD_DISABLE, HDCP_2X_CMD_START, HDCP_2X_CMD_START_AUTH, HDCP_2X_CMD_STOP, Loading Loading @@ -93,6 +95,7 @@ enum sde_hdcp_2x_device_type { */ struct sde_hdcp_2x_wakeup_data { enum sde_hdcp_2x_wakeup_cmd cmd; enum sde_hdcp_2x_device_type device_type; void *context; uint32_t total_message_length; uint32_t timeout; Loading