Loading drivers/gpu/drm/msm/dp/dp_display.c +1 −19 Original line number Diff line number Diff line Loading @@ -712,28 +712,10 @@ static void dp_display_process_mst_hpd_low(struct dp_display_private *dp) static int dp_display_process_hpd_low(struct dp_display_private *dp) { int rc = 0, idx; struct dp_panel *dp_panel; mutex_lock(&dp->session_lock); int rc = 0; dp->is_connected = false; if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->off) dp->hdcp.ops->off(dp->hdcp.data); for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) { if (!dp->active_panels[idx]) continue; dp_panel = dp->active_panels[idx]; if (dp_panel->audio_supported) dp_panel->audio->off(dp_panel->audio); } mutex_unlock(&dp->session_lock); dp_display_process_mst_hpd_low(dp); rc = dp_display_send_hpd_notification(dp); Loading drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +86 −72 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #include <linux/types.h> #include <linux/kthread.h> #include <linux/msm_hdcp.h> #include <linux/kfifo.h> #include <drm/drm_dp_helper.h> #include "sde_hdcp_2x.h" Loading @@ -28,24 +29,19 @@ enum dp_hdcp2p2_sink_status { }; struct dp_hdcp2p2_ctrl { DECLARE_KFIFO(cmd_q, enum hdcp_transport_wakeup_cmd, 8); wait_queue_head_t wait_q; atomic_t auth_state; enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */ struct dp_hdcp2p2_interrupts *intr; struct sde_hdcp_init_data init_data; struct mutex mutex; /* mutex to protect access to ctrl */ struct mutex msg_lock; /* mutex to protect access to msg buffer */ struct mutex wakeup_mutex; /* mutex to protect access to wakeup call*/ struct sde_hdcp_ops *ops; void *lib_ctx; /* Handle to HDCP 2.2 Trustzone library */ struct sde_hdcp_2x_ops *lib; /* Ops for driver to call into TZ */ enum hdcp_transport_wakeup_cmd wakeup_cmd; struct task_struct *thread; struct kthread_worker worker; struct kthread_work auth; struct kthread_work send_msg; struct kthread_work recv_msg; struct kthread_work link; struct hdcp2_buffer response; struct hdcp2_buffer request; uint32_t total_message_length; Loading @@ -72,7 +68,10 @@ struct dp_hdcp2p2_interrupts { static inline bool dp_hdcp2p2_is_valid_state(struct dp_hdcp2p2_ctrl *ctrl) { if (ctrl->wakeup_cmd == HDCP_TRANSPORT_CMD_AUTHENTICATE) enum hdcp_transport_wakeup_cmd cmd; if (kfifo_peek(&ctrl->cmd_q, &cmd) && cmd == HDCP_TRANSPORT_CMD_AUTHENTICATE) return true; if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) Loading Loading @@ -167,58 +166,28 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) return -EINVAL; } mutex_lock(&ctrl->wakeup_mutex); ctrl->wakeup_cmd = data->cmd; if (data->timeout) ctrl->timeout = (data->timeout) * 2; else ctrl->timeout = default_timeout_us; if (!dp_hdcp2p2_is_valid_state(ctrl)) { pr_err("invalid state\n"); goto exit; } if (dp_hdcp2p2_copy_buf(ctrl, data)) goto exit; pr_debug("%s\n", hdcp_transport_cmd_to_str(ctrl->wakeup_cmd)); switch (ctrl->wakeup_cmd) { case HDCP_TRANSPORT_CMD_SEND_MESSAGE: kthread_queue_work(&ctrl->worker, &ctrl->send_msg); break; case HDCP_TRANSPORT_CMD_RECV_MESSAGE: kthread_queue_work(&ctrl->worker, &ctrl->recv_msg); break; switch (data->cmd) { case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATED); dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_STATUS_FAILED: atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); kthread_cancel_work_sync(&ctrl->link); kthread_cancel_work_sync(&ctrl->recv_msg); dp_hdcp2p2_set_interrupts(ctrl, false); dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_LINK_POLL: if (ctrl->cp_irq_done) kthread_queue_work(&ctrl->worker, &ctrl->recv_msg); else ctrl->polling = true; break; case HDCP_TRANSPORT_CMD_AUTHENTICATE: kthread_queue_work(&ctrl->worker, &ctrl->auth); break; default: pr_err("invalid wakeup command %d\n", ctrl->wakeup_cmd); break; } exit: mutex_unlock(&ctrl->wakeup_mutex); kfifo_put(&ctrl->cmd_q, data->cmd); wake_up(&ctrl->wait_q); exit: return 0; } Loading Loading @@ -267,10 +236,10 @@ static void dp_hdcp2p2_off(void *input) dp_hdcp2p2_reset(ctrl); kthread_flush_worker(&ctrl->worker); cdata.context = input; dp_hdcp2p2_wakeup(&cdata); kthread_park(ctrl->thread); } static int dp_hdcp2p2_authenticate(void *input) Loading @@ -280,13 +249,13 @@ static int dp_hdcp2p2_authenticate(void *input) HDCP_TRANSPORT_CMD_AUTHENTICATE}; int rc = 0; kthread_flush_worker(&ctrl->worker); dp_hdcp2p2_set_interrupts(ctrl, true); ctrl->sink_status = SINK_CONNECTED; atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING); kthread_unpark(ctrl->thread); cdata.context = input; dp_hdcp2p2_wakeup(&cdata); Loading Loading @@ -348,7 +317,7 @@ static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl) goto exit; } pr_debug("request: offset(0x%x), size(%d)\n", offset, size); pr_debug("offset(0x%x), size(%d)\n", offset, size); do { read_size = min(size, max_size); Loading Loading @@ -377,6 +346,8 @@ static int dp_hdcp2p2_aux_write_message(struct dp_hdcp2p2_ctrl *ctrl, int const max_size = 16; int rc = 0, write_size = 0, bytes_written = 0; pr_debug("offset(0x%x), size(%d)\n", offset, size); do { write_size = min(size, max_size); Loading Loading @@ -441,11 +412,9 @@ static void dp_hdcp2p2_force_encryption(void *data, bool enable) lib->force_encryption(ctrl->lib_ctx, enable); } static void dp_hdcp2p2_send_msg_work(struct kthread_work *work) static void dp_hdcp2p2_send_msg(struct dp_hdcp2p2_ctrl *ctrl) { int rc = 0; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, send_msg); struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; if (!ctrl) { Loading Loading @@ -513,11 +482,9 @@ static int dp_hdcp2p2_get_msg_from_sink(struct dp_hdcp2p2_ctrl *ctrl) return rc; } static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work) static void dp_hdcp2p2_recv_msg(struct dp_hdcp2p2_ctrl *ctrl) { struct sde_hdcp_2x_wakeup_data cdata = { HDCP_2X_CMD_INVALID }; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, recv_msg); cdata.context = ctrl->lib_ctx; Loading @@ -543,11 +510,9 @@ static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work) dp_hdcp2p2_get_msg_from_sink(ctrl); } static void dp_hdcp2p2_link_work(struct kthread_work *work) static void dp_hdcp2p2_link_check(struct dp_hdcp2p2_ctrl *ctrl) { int rc = 0; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, link); struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; if (!ctrl) { Loading Loading @@ -595,11 +560,9 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work) dp_hdcp2p2_wakeup_lib(ctrl, &cdata); } static void dp_hdcp2p2_auth_work(struct kthread_work *work) static void dp_hdcp2p2_manage_session(struct dp_hdcp2p2_ctrl *ctrl) { struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, auth); cdata.context = ctrl->lib_ctx; Loading Loading @@ -684,7 +647,9 @@ static int dp_hdcp2p2_cp_irq(void *input) goto error; } kthread_queue_work(&ctrl->worker, &ctrl->link); kfifo_put(&ctrl->cmd_q, HDCP_TRANSPORT_CMD_LINK_CHECK); wake_up(&ctrl->wait_q); return 0; error: Loading Loading @@ -774,10 +739,65 @@ void sde_dp_hdcp2p2_deinit(void *input) mutex_destroy(&ctrl->mutex); mutex_destroy(&ctrl->msg_lock); mutex_destroy(&ctrl->wakeup_mutex); kfree(ctrl); } static int dp_hdcp2p2_main(void *data) { struct dp_hdcp2p2_ctrl *ctrl = data; enum hdcp_transport_wakeup_cmd cmd; while (1) { wait_event(ctrl->wait_q, !kfifo_is_empty(&ctrl->cmd_q) || kthread_should_stop() || kthread_should_park()); if (kthread_should_stop()) break; if (kfifo_is_empty(&ctrl->cmd_q) && kthread_should_park()) { kthread_parkme(); continue; } if (!kfifo_get(&ctrl->cmd_q, &cmd)) continue; switch (cmd) { case HDCP_TRANSPORT_CMD_SEND_MESSAGE: dp_hdcp2p2_send_msg(ctrl); break; case HDCP_TRANSPORT_CMD_RECV_MESSAGE: dp_hdcp2p2_recv_msg(ctrl); break; case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_STATUS_FAILED: dp_hdcp2p2_set_interrupts(ctrl, false); dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_LINK_POLL: if (ctrl->cp_irq_done) dp_hdcp2p2_recv_msg(ctrl); else ctrl->polling = true; break; case HDCP_TRANSPORT_CMD_LINK_CHECK: dp_hdcp2p2_link_check(ctrl); break; case HDCP_TRANSPORT_CMD_AUTHENTICATE: dp_hdcp2p2_manage_session(ctrl); break; default: break; } } return 0; } void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) { int rc; Loading Loading @@ -833,12 +853,14 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) ctrl->sink_status = SINK_DISCONNECTED; ctrl->intr = intr; INIT_KFIFO(ctrl->cmd_q); init_waitqueue_head(&ctrl->wait_q); atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE); ctrl->ops = &ops; mutex_init(&ctrl->mutex); mutex_init(&ctrl->msg_lock); mutex_init(&ctrl->wakeup_mutex); register_data.hdcp_data = &ctrl->lib_ctx; register_data.client_ops = &client_ops; Loading @@ -856,15 +878,7 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) msm_hdcp_register_cb(init_data->msm_hdcp_dev, ctrl, dp_hdcp2p2_min_level_change); kthread_init_worker(&ctrl->worker); kthread_init_work(&ctrl->auth, dp_hdcp2p2_auth_work); kthread_init_work(&ctrl->send_msg, dp_hdcp2p2_send_msg_work); kthread_init_work(&ctrl->recv_msg, dp_hdcp2p2_recv_msg_work); kthread_init_work(&ctrl->link, dp_hdcp2p2_link_work); ctrl->thread = kthread_run(kthread_worker_fn, &ctrl->worker, "dp_hdcp2p2"); ctrl->thread = kthread_run(dp_hdcp2p2_main, ctrl, "dp_hdcp2p2"); if (IS_ERR(ctrl->thread)) { pr_err("unable to start DP hdcp2p2 thread\n"); Loading drivers/gpu/drm/msm/sde_hdcp_2x.c +132 −269 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/kthread.h> #include <linux/kfifo.h> #include "sde_hdcp_2x.h" Loading @@ -41,11 +42,9 @@ #define REAUTH_REQ BIT(3) #define LINK_INTEGRITY_FAILURE BIT(4) #define HDCP_2X_EXECUTE(x) { \ kthread_queue_work(&hdcp->worker, &hdcp->wk_##x); \ } struct sde_hdcp_2x_ctrl { DECLARE_KFIFO(cmd_q, enum sde_hdcp_2x_wakeup_cmd, 8); wait_queue_head_t wait_q; struct hdcp2_app_data app_data; u32 timeout_left; u32 wait_timeout_ms; Loading @@ -59,8 +58,6 @@ struct sde_hdcp_2x_ctrl { void *client_data; void *hdcp2_ctx; struct hdcp_transport_ops *client_ops; struct mutex wakeup_mutex; enum sde_hdcp_2x_wakeup_cmd wakeup_cmd; bool repeater_flag; bool update_stream; int last_msg; Loading @@ -70,18 +67,10 @@ struct sde_hdcp_2x_ctrl { struct task_struct *thread; struct completion response_completion; struct kthread_worker worker; struct kthread_work wk_init; struct kthread_work wk_msg_sent; struct kthread_work wk_msg_recvd; struct kthread_work wk_timeout; struct kthread_work wk_clean; struct kthread_work wk_stream; struct kthread_work wk_wait; struct kthread_work wk_send_type; }; static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp); static const char *sde_hdcp_2x_message_name(int msg_id) { switch (msg_id) { Loading @@ -99,7 +88,8 @@ static const char *sde_hdcp_2x_message_name(int msg_id) case REP_STREAM_MANAGE: return TO_STR(REP_STREAM_MANAGE); case REP_STREAM_READY: return TO_STR(REP_STREAM_READY); case SKE_SEND_TYPE_ID: return TO_STR(SKE_SEND_TYPE_ID); default: return "UNKNOWN"; default: return "UNKNOWN"; } } Loading Loading @@ -152,45 +142,6 @@ static const struct sde_hdcp_2x_msg_data 0 }, }; static void sde_hdcp_2x_check_worker_status(struct sde_hdcp_2x_ctrl *hdcp) { if (!list_empty(&hdcp->wk_init.node)) pr_debug("init work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_init) pr_debug("init work executing\n"); if (!list_empty(&hdcp->wk_msg_sent.node)) pr_debug("msg_sent work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_msg_sent) pr_debug("msg_sent work executing\n"); if (!list_empty(&hdcp->wk_msg_recvd.node)) pr_debug("msg_recvd work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_msg_recvd) pr_debug("msg_recvd work executing\n"); if (!list_empty(&hdcp->wk_timeout.node)) pr_debug("timeout work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_timeout) pr_debug("timeout work executing\n"); if (!list_empty(&hdcp->wk_clean.node)) pr_debug("clean work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_clean) pr_debug("clean work executing\n"); if (!list_empty(&hdcp->wk_stream.node)) pr_debug("stream work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_stream) pr_debug("stream work executing\n"); } static int sde_hdcp_2x_get_next_message(struct sde_hdcp_2x_ctrl *hdcp, struct hdcp_transport_wakeup_data *data) { Loading Loading @@ -251,6 +202,8 @@ static int sde_hdcp_2x_get_next_message(struct sde_hdcp_2x_ctrl *hdcp, static void sde_hdcp_2x_wait_for_response(struct sde_hdcp_2x_ctrl *hdcp) { u32 timeout; switch (hdcp->last_msg) { case AKE_SEND_H_PRIME: if (hdcp->no_stored_km) Loading @@ -271,8 +224,26 @@ static void sde_hdcp_2x_wait_for_response(struct sde_hdcp_2x_ctrl *hdcp) hdcp->wait_timeout_ms = 0; } if (hdcp->wait_timeout_ms) HDCP_2X_EXECUTE(wait); if (!hdcp->wait_timeout_ms) return; if (atomic_read(&hdcp->hdcp_off)) { pr_debug("invalid state: hdcp off\n"); return; } reinit_completion(&hdcp->response_completion); timeout = wait_for_completion_timeout(&hdcp->response_completion, hdcp->wait_timeout_ms); if (!timeout) { pr_err("completion expired, last message = %s\n", sde_hdcp_2x_message_name(hdcp->last_msg)); if (!atomic_read(&hdcp->hdcp_off)) sde_hdcp_2x_clean(hdcp); } hdcp->wait_timeout_ms = 0; } static void sde_hdcp_2x_wakeup_client(struct sde_hdcp_2x_ctrl *hdcp, Loading Loading @@ -319,9 +290,6 @@ static inline void sde_hdcp_2x_send_message(struct sde_hdcp_2x_ctrl *hdcp) /* ignore the first byte as it contains the message id */ cdata.buf = hdcp->app_data.response.data + 1; pr_debug("%s\n", sde_hdcp_2x_message_name(hdcp->app_data.response.data[0])); sde_hdcp_2x_wakeup_client(hdcp, &cdata); } Loading @@ -345,32 +313,9 @@ static void sde_hdcp_2x_force_encryption(void *data, bool enable) pr_info("force_encryption=%d\n", hdcp->force_encryption); } 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)) { pr_debug("hdcp2.2 session tearing down\n"); goto exit; } } exit: return rc; } static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp) { struct hdcp_transport_wakeup_data cdata = { HDCP_TRANSPORT_CMD_INVALID }; struct hdcp_transport_wakeup_data cdata = {HDCP_TRANSPORT_CMD_INVALID}; hdcp->authenticated = false; Loading @@ -385,15 +330,6 @@ static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp) hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_STOP, &hdcp->app_data); } static void sde_hdcp_2x_cleanup_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_clean); sde_hdcp_2x_clean(hdcp); } static u8 sde_hdcp_2x_stream_type(u8 min_enc_level) { u8 stream_type = 0; Loading Loading @@ -441,15 +377,7 @@ static void sde_hdcp_2x_send_type(struct sde_hdcp_2x_ctrl *hdcp) sde_hdcp_2x_send_message(hdcp); } static void sde_hdcp_2x_send_type_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_send_type); sde_hdcp_2x_send_type(hdcp); } static void sde_hdcp_2x_stream(struct sde_hdcp_2x_ctrl *hdcp) static void sde_hdcp_2x_query_stream(struct sde_hdcp_2x_ctrl *hdcp) { int rc = 0; Loading @@ -474,21 +402,13 @@ static void sde_hdcp_2x_stream(struct sde_hdcp_2x_ctrl *hdcp) goto exit; } pr_debug("message received from TZ: %s\n", sde_hdcp_2x_message_name(hdcp->app_data.response.data[0])); pr_debug("[tz]: %s\n", sde_hdcp_2x_message_name( hdcp->app_data.response.data[0])); exit: if (!rc && !atomic_read(&hdcp->hdcp_off)) sde_hdcp_2x_send_message(hdcp); } static void sde_hdcp_2x_query_stream_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_stream); sde_hdcp_2x_stream(hdcp); } static void sde_hdcp_2x_initialize_command(struct sde_hdcp_2x_ctrl *hdcp, enum hdcp_transport_wakeup_cmd cmd, struct hdcp_transport_wakeup_data *cdata) Loading @@ -501,8 +421,8 @@ static void sde_hdcp_2x_initialize_command(struct sde_hdcp_2x_ctrl *hdcp, static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp) { struct hdcp_transport_wakeup_data cdata = { HDCP_TRANSPORT_CMD_INVALID }; cdata.context = hdcp->client_data; HDCP_TRANSPORT_CMD_INVALID, hdcp->client_data}; switch (hdcp->app_data.response.data[0]) { case SKE_SEND_TYPE_ID: Loading Loading @@ -541,7 +461,7 @@ static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp) hdcp->update_stream); if (hdcp->update_stream) { HDCP_2X_EXECUTE(stream); sde_hdcp_2x_query_stream(hdcp); hdcp->update_stream = false; } else { sde_hdcp_2x_initialize_command(hdcp, Loading @@ -557,48 +477,22 @@ static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp) sde_hdcp_2x_wakeup_client(hdcp, &cdata); } static void sde_hdcp_2x_msg_sent_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_msg_sent); if (hdcp->wakeup_cmd != HDCP_2X_CMD_MSG_SEND_SUCCESS) { pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd); return; } sde_hdcp_2x_msg_sent(hdcp); } static void sde_hdcp_2x_init(struct sde_hdcp_2x_ctrl *hdcp) { int rc = 0; if (hdcp->wakeup_cmd != HDCP_2X_CMD_START) { pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd); return; } int rc; rc = hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_START, &hdcp->app_data); if (rc) goto exit; pr_debug("message received from TZ: %s\n", sde_hdcp_2x_message_name(hdcp->app_data.response.data[0])); pr_debug("[tz]: %s\n", sde_hdcp_2x_message_name( hdcp->app_data.response.data[0])); sde_hdcp_2x_send_message(hdcp); return; exit: HDCP_2X_EXECUTE(clean); } static void sde_hdcp_2x_init_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_init); sde_hdcp_2x_init(hdcp); sde_hdcp_2x_clean(hdcp); } static void sde_hdcp_2x_timeout(struct sde_hdcp_2x_ctrl *hdcp) Loading @@ -622,15 +516,7 @@ static void sde_hdcp_2x_timeout(struct sde_hdcp_2x_ctrl *hdcp) return; error: if (!atomic_read(&hdcp->hdcp_off)) HDCP_2X_EXECUTE(clean); } static void sde_hdcp_2x_timeout_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_timeout); sde_hdcp_2x_timeout(hdcp); sde_hdcp_2x_clean(hdcp); } static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) Loading @@ -639,8 +525,7 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) char *msg = NULL; u32 message_id_bytes = 0; u32 request_length, out_msg; struct hdcp_transport_wakeup_data cdata = { HDCP_TRANSPORT_CMD_INVALID }; struct hdcp_transport_wakeup_data cdata = {HDCP_TRANSPORT_CMD_INVALID}; if (atomic_read(&hdcp->hdcp_off)) { pr_debug("invalid state, hdcp off\n"); Loading @@ -664,8 +549,7 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) request_length += message_id_bytes; pr_debug("message received from SINK: %s\n", sde_hdcp_2x_message_name(msg[0])); pr_debug("[sink]: %s\n", sde_hdcp_2x_message_name(msg[0])); hdcp->app_data.request.length = request_length; rc = hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_PROCESS_MSG, Loading @@ -686,8 +570,7 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) out_msg = (u32)hdcp->app_data.response.data[0]; pr_debug("message received from TZ: %s\n", sde_hdcp_2x_message_name(out_msg)); pr_debug("[tz]: %s\n", sde_hdcp_2x_message_name(out_msg)); if (msg[0] == REP_STREAM_READY && out_msg != REP_STREAM_MANAGE) { if (!hdcp->authenticated) { Loading Loading @@ -715,16 +598,12 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) } hdcp->resend_lc_init = false; if (msg[0] == LC_SEND_L_PRIME && out_msg == LC_INIT) { pr_debug("resend %s\n", sde_hdcp_2x_message_name(out_msg)); if (msg[0] == LC_SEND_L_PRIME && out_msg == LC_INIT) hdcp->resend_lc_init = true; } hdcp->resend_stream_manage = false; if (msg[0] == REP_STREAM_READY && out_msg == REP_STREAM_MANAGE) { pr_debug("resend %s\n", sde_hdcp_2x_message_name(out_msg)); if (msg[0] == REP_STREAM_READY && out_msg == REP_STREAM_MANAGE) hdcp->resend_stream_manage = true; } if (out_msg == AKE_NO_STORED_KM) hdcp->no_stored_km = true; Loading @@ -737,8 +616,6 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) } if (!atomic_read(&hdcp->hdcp_off)) { pr_debug("creating client data for: %s\n", sde_hdcp_2x_message_name(out_msg)); cdata.cmd = HDCP_TRANSPORT_CMD_SEND_MESSAGE; cdata.buf = hdcp->app_data.response.data + 1; cdata.buf_len = hdcp->app_data.response.length; Loading @@ -748,47 +625,17 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) sde_hdcp_2x_wakeup_client(hdcp, &cdata); if (rc && !atomic_read(&hdcp->hdcp_off)) HDCP_2X_EXECUTE(clean); } static void sde_hdcp_2x_msg_recvd_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_msg_recvd); sde_hdcp_2x_msg_recvd(hdcp); } static void sde_hdcp_2x_wait_for_response_work(struct kthread_work *work) { u32 timeout; struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_wait); if (!hdcp) { pr_err("invalid input\n"); return; } if (atomic_read(&hdcp->hdcp_off)) { pr_debug("invalid state: hdcp off\n"); return; } reinit_completion(&hdcp->response_completion); timeout = wait_for_completion_timeout(&hdcp->response_completion, hdcp->wait_timeout_ms); if (!timeout) { pr_err("completion expired, last message = %s\n", sde_hdcp_2x_message_name(hdcp->last_msg)); if (!atomic_read(&hdcp->hdcp_off)) HDCP_2X_EXECUTE(clean); } hdcp->wait_timeout_ms = 0; sde_hdcp_2x_clean(hdcp); } /** sde_hdcp_2x_wakeup() - wakeup the module to execute a requested command * @data: data required for executing corresponding command. * * This function is executed on caller's thread. Update the local data * and wakeup the local thread to execute the command. Once the local * thread is activated, caller's thread is returned and this function * is ready to receive next command. */ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) { struct sde_hdcp_2x_ctrl *hdcp; Loading @@ -801,72 +648,100 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) if (!hdcp) return -EINVAL; mutex_lock(&hdcp->wakeup_mutex); hdcp->wakeup_cmd = data->cmd; hdcp->timeout_left = data->timeout; hdcp->total_message_length = data->total_message_length; pr_debug("%s\n", sde_hdcp_2x_cmd_to_str(hdcp->wakeup_cmd)); rc = sde_hdcp_2x_check_valid_state(hdcp); if (rc) { pr_err("invalid state for command=%s\n", sde_hdcp_2x_cmd_to_str(hdcp->wakeup_cmd)); goto exit; } hdcp->min_enc_level = data->min_enc_level; if (!completion_done(&hdcp->response_completion)) complete_all(&hdcp->response_completion); switch (hdcp->wakeup_cmd) { kfifo_put(&hdcp->cmd_q, data->cmd); switch (data->cmd) { case HDCP_2X_CMD_STOP: atomic_set(&hdcp->hdcp_off, 1); kthread_park(hdcp->thread); break; case HDCP_2X_CMD_START: hdcp->no_stored_km = false; hdcp->repeater_flag = false; hdcp->update_stream = false; hdcp->authenticated = false; hdcp->last_msg = INVALID_MESSAGE; hdcp->timeout_left = 0; atomic_set(&hdcp->hdcp_off, 0); HDCP_2X_EXECUTE(init); kthread_unpark(hdcp->thread); wake_up(&hdcp->wait_q); break; default: wake_up(&hdcp->wait_q); break; } return rc; } static int sde_hdcp_2x_main(void *data) { struct sde_hdcp_2x_ctrl *hdcp = data; enum sde_hdcp_2x_wakeup_cmd cmd; while (1) { wait_event(hdcp->wait_q, !kfifo_is_empty(&hdcp->cmd_q) || kthread_should_stop() || kthread_should_park()); if (kthread_should_stop()) break; if (kfifo_is_empty(&hdcp->cmd_q) && kthread_should_park()) { kthread_parkme(); continue; } if (!kfifo_get(&hdcp->cmd_q, &cmd)) continue; switch (cmd) { case HDCP_2X_CMD_START: sde_hdcp_2x_init(hdcp); break; case HDCP_2X_CMD_STOP: atomic_set(&hdcp->hdcp_off, 1); HDCP_2X_EXECUTE(clean); sde_hdcp_2x_clean(hdcp); break; case HDCP_2X_CMD_MSG_SEND_SUCCESS: HDCP_2X_EXECUTE(msg_sent); sde_hdcp_2x_msg_sent(hdcp); break; case HDCP_2X_CMD_MSG_SEND_FAILED: case HDCP_2X_CMD_MSG_RECV_FAILED: case HDCP_2X_CMD_LINK_FAILED: HDCP_2X_EXECUTE(clean); sde_hdcp_2x_clean(hdcp); break; case HDCP_2X_CMD_MSG_RECV_SUCCESS: HDCP_2X_EXECUTE(msg_recvd); sde_hdcp_2x_msg_recvd(hdcp); break; case HDCP_2X_CMD_MSG_RECV_TIMEOUT: HDCP_2X_EXECUTE(timeout); sde_hdcp_2x_timeout(hdcp); break; case HDCP_2X_CMD_QUERY_STREAM_TYPE: HDCP_2X_EXECUTE(stream); sde_hdcp_2x_query_stream(hdcp); break; case HDCP_2X_CMD_MIN_ENC_LEVEL: hdcp->min_enc_level = data->min_enc_level; if (!hdcp->repeater_flag) { HDCP_2X_EXECUTE(send_type); sde_hdcp_2x_send_type(hdcp); break; } HDCP_2X_EXECUTE(stream); sde_hdcp_2x_query_stream(hdcp); break; default: pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd); break; } } exit: mutex_unlock(&hdcp->wakeup_mutex); return rc; return 0; } int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) Loading Loading @@ -911,27 +786,16 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) hdcp->hdcp2_ctx = hdcp2_init(hdcp->device_type); atomic_set(&hdcp->hdcp_off, 0); mutex_init(&hdcp->wakeup_mutex); INIT_KFIFO(hdcp->cmd_q); kthread_init_worker(&hdcp->worker); kthread_init_work(&hdcp->wk_init, sde_hdcp_2x_init_work); kthread_init_work(&hdcp->wk_msg_sent, sde_hdcp_2x_msg_sent_work); kthread_init_work(&hdcp->wk_msg_recvd, sde_hdcp_2x_msg_recvd_work); kthread_init_work(&hdcp->wk_timeout, sde_hdcp_2x_timeout_work); kthread_init_work(&hdcp->wk_clean, sde_hdcp_2x_cleanup_work); 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); init_waitqueue_head(&hdcp->wait_q); atomic_set(&hdcp->hdcp_off, 0); init_completion(&hdcp->response_completion); *data->hdcp_data = hdcp; hdcp->thread = kthread_run(kthread_worker_fn, &hdcp->worker, "hdcp_tz_lib"); hdcp->thread = kthread_run(sde_hdcp_2x_main, hdcp, "hdcp_2x"); if (IS_ERR(hdcp->thread)) { pr_err("unable to start lib thread\n"); Loading @@ -958,7 +822,6 @@ void sde_hdcp_2x_deregister(void *data) return; kthread_stop(hdcp->thread); mutex_destroy(&hdcp->wakeup_mutex); hdcp2_deinit(hdcp->hdcp2_ctx); kzfree(hdcp); } drivers/gpu/drm/msm/sde_hdcp_2x.h +3 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ enum sde_hdcp_2x_wakeup_cmd { * @HDCP_TRANSPORT_CMD_STATUS_SUCCESS: successfully communicated with TrustZone * @HDCP_TRANSPORT_CMD_STATUS_FAILED: failed to communicate with TrustZone * @HDCP_TRANSPORT_CMD_LINK_POLL: poll the HDCP link * @HDCP_TRANSPORT_CMD_LINK_CHECK: check link status in response to cp_irq * @HDCP_TRANSPORT_CMD_AUTHENTICATE: start authentication */ enum hdcp_transport_wakeup_cmd { Loading @@ -59,7 +60,8 @@ enum hdcp_transport_wakeup_cmd { HDCP_TRANSPORT_CMD_STATUS_SUCCESS, HDCP_TRANSPORT_CMD_STATUS_FAILED, HDCP_TRANSPORT_CMD_LINK_POLL, HDCP_TRANSPORT_CMD_AUTHENTICATE HDCP_TRANSPORT_CMD_LINK_CHECK, HDCP_TRANSPORT_CMD_AUTHENTICATE, }; enum sde_hdcp_2x_device_type { Loading Loading
drivers/gpu/drm/msm/dp/dp_display.c +1 −19 Original line number Diff line number Diff line Loading @@ -712,28 +712,10 @@ static void dp_display_process_mst_hpd_low(struct dp_display_private *dp) static int dp_display_process_hpd_low(struct dp_display_private *dp) { int rc = 0, idx; struct dp_panel *dp_panel; mutex_lock(&dp->session_lock); int rc = 0; dp->is_connected = false; if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->off) dp->hdcp.ops->off(dp->hdcp.data); for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) { if (!dp->active_panels[idx]) continue; dp_panel = dp->active_panels[idx]; if (dp_panel->audio_supported) dp_panel->audio->off(dp_panel->audio); } mutex_unlock(&dp->session_lock); dp_display_process_mst_hpd_low(dp); rc = dp_display_send_hpd_notification(dp); Loading
drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +86 −72 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #include <linux/types.h> #include <linux/kthread.h> #include <linux/msm_hdcp.h> #include <linux/kfifo.h> #include <drm/drm_dp_helper.h> #include "sde_hdcp_2x.h" Loading @@ -28,24 +29,19 @@ enum dp_hdcp2p2_sink_status { }; struct dp_hdcp2p2_ctrl { DECLARE_KFIFO(cmd_q, enum hdcp_transport_wakeup_cmd, 8); wait_queue_head_t wait_q; atomic_t auth_state; enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */ struct dp_hdcp2p2_interrupts *intr; struct sde_hdcp_init_data init_data; struct mutex mutex; /* mutex to protect access to ctrl */ struct mutex msg_lock; /* mutex to protect access to msg buffer */ struct mutex wakeup_mutex; /* mutex to protect access to wakeup call*/ struct sde_hdcp_ops *ops; void *lib_ctx; /* Handle to HDCP 2.2 Trustzone library */ struct sde_hdcp_2x_ops *lib; /* Ops for driver to call into TZ */ enum hdcp_transport_wakeup_cmd wakeup_cmd; struct task_struct *thread; struct kthread_worker worker; struct kthread_work auth; struct kthread_work send_msg; struct kthread_work recv_msg; struct kthread_work link; struct hdcp2_buffer response; struct hdcp2_buffer request; uint32_t total_message_length; Loading @@ -72,7 +68,10 @@ struct dp_hdcp2p2_interrupts { static inline bool dp_hdcp2p2_is_valid_state(struct dp_hdcp2p2_ctrl *ctrl) { if (ctrl->wakeup_cmd == HDCP_TRANSPORT_CMD_AUTHENTICATE) enum hdcp_transport_wakeup_cmd cmd; if (kfifo_peek(&ctrl->cmd_q, &cmd) && cmd == HDCP_TRANSPORT_CMD_AUTHENTICATE) return true; if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) Loading Loading @@ -167,58 +166,28 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) return -EINVAL; } mutex_lock(&ctrl->wakeup_mutex); ctrl->wakeup_cmd = data->cmd; if (data->timeout) ctrl->timeout = (data->timeout) * 2; else ctrl->timeout = default_timeout_us; if (!dp_hdcp2p2_is_valid_state(ctrl)) { pr_err("invalid state\n"); goto exit; } if (dp_hdcp2p2_copy_buf(ctrl, data)) goto exit; pr_debug("%s\n", hdcp_transport_cmd_to_str(ctrl->wakeup_cmd)); switch (ctrl->wakeup_cmd) { case HDCP_TRANSPORT_CMD_SEND_MESSAGE: kthread_queue_work(&ctrl->worker, &ctrl->send_msg); break; case HDCP_TRANSPORT_CMD_RECV_MESSAGE: kthread_queue_work(&ctrl->worker, &ctrl->recv_msg); break; switch (data->cmd) { case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATED); dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_STATUS_FAILED: atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); kthread_cancel_work_sync(&ctrl->link); kthread_cancel_work_sync(&ctrl->recv_msg); dp_hdcp2p2_set_interrupts(ctrl, false); dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_LINK_POLL: if (ctrl->cp_irq_done) kthread_queue_work(&ctrl->worker, &ctrl->recv_msg); else ctrl->polling = true; break; case HDCP_TRANSPORT_CMD_AUTHENTICATE: kthread_queue_work(&ctrl->worker, &ctrl->auth); break; default: pr_err("invalid wakeup command %d\n", ctrl->wakeup_cmd); break; } exit: mutex_unlock(&ctrl->wakeup_mutex); kfifo_put(&ctrl->cmd_q, data->cmd); wake_up(&ctrl->wait_q); exit: return 0; } Loading Loading @@ -267,10 +236,10 @@ static void dp_hdcp2p2_off(void *input) dp_hdcp2p2_reset(ctrl); kthread_flush_worker(&ctrl->worker); cdata.context = input; dp_hdcp2p2_wakeup(&cdata); kthread_park(ctrl->thread); } static int dp_hdcp2p2_authenticate(void *input) Loading @@ -280,13 +249,13 @@ static int dp_hdcp2p2_authenticate(void *input) HDCP_TRANSPORT_CMD_AUTHENTICATE}; int rc = 0; kthread_flush_worker(&ctrl->worker); dp_hdcp2p2_set_interrupts(ctrl, true); ctrl->sink_status = SINK_CONNECTED; atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING); kthread_unpark(ctrl->thread); cdata.context = input; dp_hdcp2p2_wakeup(&cdata); Loading Loading @@ -348,7 +317,7 @@ static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl) goto exit; } pr_debug("request: offset(0x%x), size(%d)\n", offset, size); pr_debug("offset(0x%x), size(%d)\n", offset, size); do { read_size = min(size, max_size); Loading Loading @@ -377,6 +346,8 @@ static int dp_hdcp2p2_aux_write_message(struct dp_hdcp2p2_ctrl *ctrl, int const max_size = 16; int rc = 0, write_size = 0, bytes_written = 0; pr_debug("offset(0x%x), size(%d)\n", offset, size); do { write_size = min(size, max_size); Loading Loading @@ -441,11 +412,9 @@ static void dp_hdcp2p2_force_encryption(void *data, bool enable) lib->force_encryption(ctrl->lib_ctx, enable); } static void dp_hdcp2p2_send_msg_work(struct kthread_work *work) static void dp_hdcp2p2_send_msg(struct dp_hdcp2p2_ctrl *ctrl) { int rc = 0; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, send_msg); struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; if (!ctrl) { Loading Loading @@ -513,11 +482,9 @@ static int dp_hdcp2p2_get_msg_from_sink(struct dp_hdcp2p2_ctrl *ctrl) return rc; } static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work) static void dp_hdcp2p2_recv_msg(struct dp_hdcp2p2_ctrl *ctrl) { struct sde_hdcp_2x_wakeup_data cdata = { HDCP_2X_CMD_INVALID }; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, recv_msg); cdata.context = ctrl->lib_ctx; Loading @@ -543,11 +510,9 @@ static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work) dp_hdcp2p2_get_msg_from_sink(ctrl); } static void dp_hdcp2p2_link_work(struct kthread_work *work) static void dp_hdcp2p2_link_check(struct dp_hdcp2p2_ctrl *ctrl) { int rc = 0; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, link); struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; if (!ctrl) { Loading Loading @@ -595,11 +560,9 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work) dp_hdcp2p2_wakeup_lib(ctrl, &cdata); } static void dp_hdcp2p2_auth_work(struct kthread_work *work) static void dp_hdcp2p2_manage_session(struct dp_hdcp2p2_ctrl *ctrl) { struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, auth); cdata.context = ctrl->lib_ctx; Loading Loading @@ -684,7 +647,9 @@ static int dp_hdcp2p2_cp_irq(void *input) goto error; } kthread_queue_work(&ctrl->worker, &ctrl->link); kfifo_put(&ctrl->cmd_q, HDCP_TRANSPORT_CMD_LINK_CHECK); wake_up(&ctrl->wait_q); return 0; error: Loading Loading @@ -774,10 +739,65 @@ void sde_dp_hdcp2p2_deinit(void *input) mutex_destroy(&ctrl->mutex); mutex_destroy(&ctrl->msg_lock); mutex_destroy(&ctrl->wakeup_mutex); kfree(ctrl); } static int dp_hdcp2p2_main(void *data) { struct dp_hdcp2p2_ctrl *ctrl = data; enum hdcp_transport_wakeup_cmd cmd; while (1) { wait_event(ctrl->wait_q, !kfifo_is_empty(&ctrl->cmd_q) || kthread_should_stop() || kthread_should_park()); if (kthread_should_stop()) break; if (kfifo_is_empty(&ctrl->cmd_q) && kthread_should_park()) { kthread_parkme(); continue; } if (!kfifo_get(&ctrl->cmd_q, &cmd)) continue; switch (cmd) { case HDCP_TRANSPORT_CMD_SEND_MESSAGE: dp_hdcp2p2_send_msg(ctrl); break; case HDCP_TRANSPORT_CMD_RECV_MESSAGE: dp_hdcp2p2_recv_msg(ctrl); break; case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_STATUS_FAILED: dp_hdcp2p2_set_interrupts(ctrl, false); dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_LINK_POLL: if (ctrl->cp_irq_done) dp_hdcp2p2_recv_msg(ctrl); else ctrl->polling = true; break; case HDCP_TRANSPORT_CMD_LINK_CHECK: dp_hdcp2p2_link_check(ctrl); break; case HDCP_TRANSPORT_CMD_AUTHENTICATE: dp_hdcp2p2_manage_session(ctrl); break; default: break; } } return 0; } void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) { int rc; Loading Loading @@ -833,12 +853,14 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) ctrl->sink_status = SINK_DISCONNECTED; ctrl->intr = intr; INIT_KFIFO(ctrl->cmd_q); init_waitqueue_head(&ctrl->wait_q); atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE); ctrl->ops = &ops; mutex_init(&ctrl->mutex); mutex_init(&ctrl->msg_lock); mutex_init(&ctrl->wakeup_mutex); register_data.hdcp_data = &ctrl->lib_ctx; register_data.client_ops = &client_ops; Loading @@ -856,15 +878,7 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) msm_hdcp_register_cb(init_data->msm_hdcp_dev, ctrl, dp_hdcp2p2_min_level_change); kthread_init_worker(&ctrl->worker); kthread_init_work(&ctrl->auth, dp_hdcp2p2_auth_work); kthread_init_work(&ctrl->send_msg, dp_hdcp2p2_send_msg_work); kthread_init_work(&ctrl->recv_msg, dp_hdcp2p2_recv_msg_work); kthread_init_work(&ctrl->link, dp_hdcp2p2_link_work); ctrl->thread = kthread_run(kthread_worker_fn, &ctrl->worker, "dp_hdcp2p2"); ctrl->thread = kthread_run(dp_hdcp2p2_main, ctrl, "dp_hdcp2p2"); if (IS_ERR(ctrl->thread)) { pr_err("unable to start DP hdcp2p2 thread\n"); Loading
drivers/gpu/drm/msm/sde_hdcp_2x.c +132 −269 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/kthread.h> #include <linux/kfifo.h> #include "sde_hdcp_2x.h" Loading @@ -41,11 +42,9 @@ #define REAUTH_REQ BIT(3) #define LINK_INTEGRITY_FAILURE BIT(4) #define HDCP_2X_EXECUTE(x) { \ kthread_queue_work(&hdcp->worker, &hdcp->wk_##x); \ } struct sde_hdcp_2x_ctrl { DECLARE_KFIFO(cmd_q, enum sde_hdcp_2x_wakeup_cmd, 8); wait_queue_head_t wait_q; struct hdcp2_app_data app_data; u32 timeout_left; u32 wait_timeout_ms; Loading @@ -59,8 +58,6 @@ struct sde_hdcp_2x_ctrl { void *client_data; void *hdcp2_ctx; struct hdcp_transport_ops *client_ops; struct mutex wakeup_mutex; enum sde_hdcp_2x_wakeup_cmd wakeup_cmd; bool repeater_flag; bool update_stream; int last_msg; Loading @@ -70,18 +67,10 @@ struct sde_hdcp_2x_ctrl { struct task_struct *thread; struct completion response_completion; struct kthread_worker worker; struct kthread_work wk_init; struct kthread_work wk_msg_sent; struct kthread_work wk_msg_recvd; struct kthread_work wk_timeout; struct kthread_work wk_clean; struct kthread_work wk_stream; struct kthread_work wk_wait; struct kthread_work wk_send_type; }; static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp); static const char *sde_hdcp_2x_message_name(int msg_id) { switch (msg_id) { Loading @@ -99,7 +88,8 @@ static const char *sde_hdcp_2x_message_name(int msg_id) case REP_STREAM_MANAGE: return TO_STR(REP_STREAM_MANAGE); case REP_STREAM_READY: return TO_STR(REP_STREAM_READY); case SKE_SEND_TYPE_ID: return TO_STR(SKE_SEND_TYPE_ID); default: return "UNKNOWN"; default: return "UNKNOWN"; } } Loading Loading @@ -152,45 +142,6 @@ static const struct sde_hdcp_2x_msg_data 0 }, }; static void sde_hdcp_2x_check_worker_status(struct sde_hdcp_2x_ctrl *hdcp) { if (!list_empty(&hdcp->wk_init.node)) pr_debug("init work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_init) pr_debug("init work executing\n"); if (!list_empty(&hdcp->wk_msg_sent.node)) pr_debug("msg_sent work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_msg_sent) pr_debug("msg_sent work executing\n"); if (!list_empty(&hdcp->wk_msg_recvd.node)) pr_debug("msg_recvd work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_msg_recvd) pr_debug("msg_recvd work executing\n"); if (!list_empty(&hdcp->wk_timeout.node)) pr_debug("timeout work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_timeout) pr_debug("timeout work executing\n"); if (!list_empty(&hdcp->wk_clean.node)) pr_debug("clean work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_clean) pr_debug("clean work executing\n"); if (!list_empty(&hdcp->wk_stream.node)) pr_debug("stream work queued\n"); if (hdcp->worker.current_work == &hdcp->wk_stream) pr_debug("stream work executing\n"); } static int sde_hdcp_2x_get_next_message(struct sde_hdcp_2x_ctrl *hdcp, struct hdcp_transport_wakeup_data *data) { Loading Loading @@ -251,6 +202,8 @@ static int sde_hdcp_2x_get_next_message(struct sde_hdcp_2x_ctrl *hdcp, static void sde_hdcp_2x_wait_for_response(struct sde_hdcp_2x_ctrl *hdcp) { u32 timeout; switch (hdcp->last_msg) { case AKE_SEND_H_PRIME: if (hdcp->no_stored_km) Loading @@ -271,8 +224,26 @@ static void sde_hdcp_2x_wait_for_response(struct sde_hdcp_2x_ctrl *hdcp) hdcp->wait_timeout_ms = 0; } if (hdcp->wait_timeout_ms) HDCP_2X_EXECUTE(wait); if (!hdcp->wait_timeout_ms) return; if (atomic_read(&hdcp->hdcp_off)) { pr_debug("invalid state: hdcp off\n"); return; } reinit_completion(&hdcp->response_completion); timeout = wait_for_completion_timeout(&hdcp->response_completion, hdcp->wait_timeout_ms); if (!timeout) { pr_err("completion expired, last message = %s\n", sde_hdcp_2x_message_name(hdcp->last_msg)); if (!atomic_read(&hdcp->hdcp_off)) sde_hdcp_2x_clean(hdcp); } hdcp->wait_timeout_ms = 0; } static void sde_hdcp_2x_wakeup_client(struct sde_hdcp_2x_ctrl *hdcp, Loading Loading @@ -319,9 +290,6 @@ static inline void sde_hdcp_2x_send_message(struct sde_hdcp_2x_ctrl *hdcp) /* ignore the first byte as it contains the message id */ cdata.buf = hdcp->app_data.response.data + 1; pr_debug("%s\n", sde_hdcp_2x_message_name(hdcp->app_data.response.data[0])); sde_hdcp_2x_wakeup_client(hdcp, &cdata); } Loading @@ -345,32 +313,9 @@ static void sde_hdcp_2x_force_encryption(void *data, bool enable) pr_info("force_encryption=%d\n", hdcp->force_encryption); } 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)) { pr_debug("hdcp2.2 session tearing down\n"); goto exit; } } exit: return rc; } static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp) { struct hdcp_transport_wakeup_data cdata = { HDCP_TRANSPORT_CMD_INVALID }; struct hdcp_transport_wakeup_data cdata = {HDCP_TRANSPORT_CMD_INVALID}; hdcp->authenticated = false; Loading @@ -385,15 +330,6 @@ static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp) hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_STOP, &hdcp->app_data); } static void sde_hdcp_2x_cleanup_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_clean); sde_hdcp_2x_clean(hdcp); } static u8 sde_hdcp_2x_stream_type(u8 min_enc_level) { u8 stream_type = 0; Loading Loading @@ -441,15 +377,7 @@ static void sde_hdcp_2x_send_type(struct sde_hdcp_2x_ctrl *hdcp) sde_hdcp_2x_send_message(hdcp); } static void sde_hdcp_2x_send_type_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_send_type); sde_hdcp_2x_send_type(hdcp); } static void sde_hdcp_2x_stream(struct sde_hdcp_2x_ctrl *hdcp) static void sde_hdcp_2x_query_stream(struct sde_hdcp_2x_ctrl *hdcp) { int rc = 0; Loading @@ -474,21 +402,13 @@ static void sde_hdcp_2x_stream(struct sde_hdcp_2x_ctrl *hdcp) goto exit; } pr_debug("message received from TZ: %s\n", sde_hdcp_2x_message_name(hdcp->app_data.response.data[0])); pr_debug("[tz]: %s\n", sde_hdcp_2x_message_name( hdcp->app_data.response.data[0])); exit: if (!rc && !atomic_read(&hdcp->hdcp_off)) sde_hdcp_2x_send_message(hdcp); } static void sde_hdcp_2x_query_stream_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_stream); sde_hdcp_2x_stream(hdcp); } static void sde_hdcp_2x_initialize_command(struct sde_hdcp_2x_ctrl *hdcp, enum hdcp_transport_wakeup_cmd cmd, struct hdcp_transport_wakeup_data *cdata) Loading @@ -501,8 +421,8 @@ static void sde_hdcp_2x_initialize_command(struct sde_hdcp_2x_ctrl *hdcp, static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp) { struct hdcp_transport_wakeup_data cdata = { HDCP_TRANSPORT_CMD_INVALID }; cdata.context = hdcp->client_data; HDCP_TRANSPORT_CMD_INVALID, hdcp->client_data}; switch (hdcp->app_data.response.data[0]) { case SKE_SEND_TYPE_ID: Loading Loading @@ -541,7 +461,7 @@ static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp) hdcp->update_stream); if (hdcp->update_stream) { HDCP_2X_EXECUTE(stream); sde_hdcp_2x_query_stream(hdcp); hdcp->update_stream = false; } else { sde_hdcp_2x_initialize_command(hdcp, Loading @@ -557,48 +477,22 @@ static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp) sde_hdcp_2x_wakeup_client(hdcp, &cdata); } static void sde_hdcp_2x_msg_sent_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_msg_sent); if (hdcp->wakeup_cmd != HDCP_2X_CMD_MSG_SEND_SUCCESS) { pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd); return; } sde_hdcp_2x_msg_sent(hdcp); } static void sde_hdcp_2x_init(struct sde_hdcp_2x_ctrl *hdcp) { int rc = 0; if (hdcp->wakeup_cmd != HDCP_2X_CMD_START) { pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd); return; } int rc; rc = hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_START, &hdcp->app_data); if (rc) goto exit; pr_debug("message received from TZ: %s\n", sde_hdcp_2x_message_name(hdcp->app_data.response.data[0])); pr_debug("[tz]: %s\n", sde_hdcp_2x_message_name( hdcp->app_data.response.data[0])); sde_hdcp_2x_send_message(hdcp); return; exit: HDCP_2X_EXECUTE(clean); } static void sde_hdcp_2x_init_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_init); sde_hdcp_2x_init(hdcp); sde_hdcp_2x_clean(hdcp); } static void sde_hdcp_2x_timeout(struct sde_hdcp_2x_ctrl *hdcp) Loading @@ -622,15 +516,7 @@ static void sde_hdcp_2x_timeout(struct sde_hdcp_2x_ctrl *hdcp) return; error: if (!atomic_read(&hdcp->hdcp_off)) HDCP_2X_EXECUTE(clean); } static void sde_hdcp_2x_timeout_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_timeout); sde_hdcp_2x_timeout(hdcp); sde_hdcp_2x_clean(hdcp); } static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) Loading @@ -639,8 +525,7 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) char *msg = NULL; u32 message_id_bytes = 0; u32 request_length, out_msg; struct hdcp_transport_wakeup_data cdata = { HDCP_TRANSPORT_CMD_INVALID }; struct hdcp_transport_wakeup_data cdata = {HDCP_TRANSPORT_CMD_INVALID}; if (atomic_read(&hdcp->hdcp_off)) { pr_debug("invalid state, hdcp off\n"); Loading @@ -664,8 +549,7 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) request_length += message_id_bytes; pr_debug("message received from SINK: %s\n", sde_hdcp_2x_message_name(msg[0])); pr_debug("[sink]: %s\n", sde_hdcp_2x_message_name(msg[0])); hdcp->app_data.request.length = request_length; rc = hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_PROCESS_MSG, Loading @@ -686,8 +570,7 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) out_msg = (u32)hdcp->app_data.response.data[0]; pr_debug("message received from TZ: %s\n", sde_hdcp_2x_message_name(out_msg)); pr_debug("[tz]: %s\n", sde_hdcp_2x_message_name(out_msg)); if (msg[0] == REP_STREAM_READY && out_msg != REP_STREAM_MANAGE) { if (!hdcp->authenticated) { Loading Loading @@ -715,16 +598,12 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) } hdcp->resend_lc_init = false; if (msg[0] == LC_SEND_L_PRIME && out_msg == LC_INIT) { pr_debug("resend %s\n", sde_hdcp_2x_message_name(out_msg)); if (msg[0] == LC_SEND_L_PRIME && out_msg == LC_INIT) hdcp->resend_lc_init = true; } hdcp->resend_stream_manage = false; if (msg[0] == REP_STREAM_READY && out_msg == REP_STREAM_MANAGE) { pr_debug("resend %s\n", sde_hdcp_2x_message_name(out_msg)); if (msg[0] == REP_STREAM_READY && out_msg == REP_STREAM_MANAGE) hdcp->resend_stream_manage = true; } if (out_msg == AKE_NO_STORED_KM) hdcp->no_stored_km = true; Loading @@ -737,8 +616,6 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) } if (!atomic_read(&hdcp->hdcp_off)) { pr_debug("creating client data for: %s\n", sde_hdcp_2x_message_name(out_msg)); cdata.cmd = HDCP_TRANSPORT_CMD_SEND_MESSAGE; cdata.buf = hdcp->app_data.response.data + 1; cdata.buf_len = hdcp->app_data.response.length; Loading @@ -748,47 +625,17 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) sde_hdcp_2x_wakeup_client(hdcp, &cdata); if (rc && !atomic_read(&hdcp->hdcp_off)) HDCP_2X_EXECUTE(clean); } static void sde_hdcp_2x_msg_recvd_work(struct kthread_work *work) { struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_msg_recvd); sde_hdcp_2x_msg_recvd(hdcp); } static void sde_hdcp_2x_wait_for_response_work(struct kthread_work *work) { u32 timeout; struct sde_hdcp_2x_ctrl *hdcp = container_of(work, struct sde_hdcp_2x_ctrl, wk_wait); if (!hdcp) { pr_err("invalid input\n"); return; } if (atomic_read(&hdcp->hdcp_off)) { pr_debug("invalid state: hdcp off\n"); return; } reinit_completion(&hdcp->response_completion); timeout = wait_for_completion_timeout(&hdcp->response_completion, hdcp->wait_timeout_ms); if (!timeout) { pr_err("completion expired, last message = %s\n", sde_hdcp_2x_message_name(hdcp->last_msg)); if (!atomic_read(&hdcp->hdcp_off)) HDCP_2X_EXECUTE(clean); } hdcp->wait_timeout_ms = 0; sde_hdcp_2x_clean(hdcp); } /** sde_hdcp_2x_wakeup() - wakeup the module to execute a requested command * @data: data required for executing corresponding command. * * This function is executed on caller's thread. Update the local data * and wakeup the local thread to execute the command. Once the local * thread is activated, caller's thread is returned and this function * is ready to receive next command. */ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) { struct sde_hdcp_2x_ctrl *hdcp; Loading @@ -801,72 +648,100 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) if (!hdcp) return -EINVAL; mutex_lock(&hdcp->wakeup_mutex); hdcp->wakeup_cmd = data->cmd; hdcp->timeout_left = data->timeout; hdcp->total_message_length = data->total_message_length; pr_debug("%s\n", sde_hdcp_2x_cmd_to_str(hdcp->wakeup_cmd)); rc = sde_hdcp_2x_check_valid_state(hdcp); if (rc) { pr_err("invalid state for command=%s\n", sde_hdcp_2x_cmd_to_str(hdcp->wakeup_cmd)); goto exit; } hdcp->min_enc_level = data->min_enc_level; if (!completion_done(&hdcp->response_completion)) complete_all(&hdcp->response_completion); switch (hdcp->wakeup_cmd) { kfifo_put(&hdcp->cmd_q, data->cmd); switch (data->cmd) { case HDCP_2X_CMD_STOP: atomic_set(&hdcp->hdcp_off, 1); kthread_park(hdcp->thread); break; case HDCP_2X_CMD_START: hdcp->no_stored_km = false; hdcp->repeater_flag = false; hdcp->update_stream = false; hdcp->authenticated = false; hdcp->last_msg = INVALID_MESSAGE; hdcp->timeout_left = 0; atomic_set(&hdcp->hdcp_off, 0); HDCP_2X_EXECUTE(init); kthread_unpark(hdcp->thread); wake_up(&hdcp->wait_q); break; default: wake_up(&hdcp->wait_q); break; } return rc; } static int sde_hdcp_2x_main(void *data) { struct sde_hdcp_2x_ctrl *hdcp = data; enum sde_hdcp_2x_wakeup_cmd cmd; while (1) { wait_event(hdcp->wait_q, !kfifo_is_empty(&hdcp->cmd_q) || kthread_should_stop() || kthread_should_park()); if (kthread_should_stop()) break; if (kfifo_is_empty(&hdcp->cmd_q) && kthread_should_park()) { kthread_parkme(); continue; } if (!kfifo_get(&hdcp->cmd_q, &cmd)) continue; switch (cmd) { case HDCP_2X_CMD_START: sde_hdcp_2x_init(hdcp); break; case HDCP_2X_CMD_STOP: atomic_set(&hdcp->hdcp_off, 1); HDCP_2X_EXECUTE(clean); sde_hdcp_2x_clean(hdcp); break; case HDCP_2X_CMD_MSG_SEND_SUCCESS: HDCP_2X_EXECUTE(msg_sent); sde_hdcp_2x_msg_sent(hdcp); break; case HDCP_2X_CMD_MSG_SEND_FAILED: case HDCP_2X_CMD_MSG_RECV_FAILED: case HDCP_2X_CMD_LINK_FAILED: HDCP_2X_EXECUTE(clean); sde_hdcp_2x_clean(hdcp); break; case HDCP_2X_CMD_MSG_RECV_SUCCESS: HDCP_2X_EXECUTE(msg_recvd); sde_hdcp_2x_msg_recvd(hdcp); break; case HDCP_2X_CMD_MSG_RECV_TIMEOUT: HDCP_2X_EXECUTE(timeout); sde_hdcp_2x_timeout(hdcp); break; case HDCP_2X_CMD_QUERY_STREAM_TYPE: HDCP_2X_EXECUTE(stream); sde_hdcp_2x_query_stream(hdcp); break; case HDCP_2X_CMD_MIN_ENC_LEVEL: hdcp->min_enc_level = data->min_enc_level; if (!hdcp->repeater_flag) { HDCP_2X_EXECUTE(send_type); sde_hdcp_2x_send_type(hdcp); break; } HDCP_2X_EXECUTE(stream); sde_hdcp_2x_query_stream(hdcp); break; default: pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd); break; } } exit: mutex_unlock(&hdcp->wakeup_mutex); return rc; return 0; } int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) Loading Loading @@ -911,27 +786,16 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data) hdcp->hdcp2_ctx = hdcp2_init(hdcp->device_type); atomic_set(&hdcp->hdcp_off, 0); mutex_init(&hdcp->wakeup_mutex); INIT_KFIFO(hdcp->cmd_q); kthread_init_worker(&hdcp->worker); kthread_init_work(&hdcp->wk_init, sde_hdcp_2x_init_work); kthread_init_work(&hdcp->wk_msg_sent, sde_hdcp_2x_msg_sent_work); kthread_init_work(&hdcp->wk_msg_recvd, sde_hdcp_2x_msg_recvd_work); kthread_init_work(&hdcp->wk_timeout, sde_hdcp_2x_timeout_work); kthread_init_work(&hdcp->wk_clean, sde_hdcp_2x_cleanup_work); 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); init_waitqueue_head(&hdcp->wait_q); atomic_set(&hdcp->hdcp_off, 0); init_completion(&hdcp->response_completion); *data->hdcp_data = hdcp; hdcp->thread = kthread_run(kthread_worker_fn, &hdcp->worker, "hdcp_tz_lib"); hdcp->thread = kthread_run(sde_hdcp_2x_main, hdcp, "hdcp_2x"); if (IS_ERR(hdcp->thread)) { pr_err("unable to start lib thread\n"); Loading @@ -958,7 +822,6 @@ void sde_hdcp_2x_deregister(void *data) return; kthread_stop(hdcp->thread); mutex_destroy(&hdcp->wakeup_mutex); hdcp2_deinit(hdcp->hdcp2_ctx); kzfree(hdcp); }
drivers/gpu/drm/msm/sde_hdcp_2x.h +3 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ enum sde_hdcp_2x_wakeup_cmd { * @HDCP_TRANSPORT_CMD_STATUS_SUCCESS: successfully communicated with TrustZone * @HDCP_TRANSPORT_CMD_STATUS_FAILED: failed to communicate with TrustZone * @HDCP_TRANSPORT_CMD_LINK_POLL: poll the HDCP link * @HDCP_TRANSPORT_CMD_LINK_CHECK: check link status in response to cp_irq * @HDCP_TRANSPORT_CMD_AUTHENTICATE: start authentication */ enum hdcp_transport_wakeup_cmd { Loading @@ -59,7 +60,8 @@ enum hdcp_transport_wakeup_cmd { HDCP_TRANSPORT_CMD_STATUS_SUCCESS, HDCP_TRANSPORT_CMD_STATUS_FAILED, HDCP_TRANSPORT_CMD_LINK_POLL, HDCP_TRANSPORT_CMD_AUTHENTICATE HDCP_TRANSPORT_CMD_LINK_CHECK, HDCP_TRANSPORT_CMD_AUTHENTICATE, }; enum sde_hdcp_2x_device_type { Loading