diff options
| author | Ajay Singh Parmar <aparmar@codeaurora.org> | 2015-10-01 13:24:06 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:46:20 -0700 |
| commit | 38fdd3f630696356da2575fe8f0ea51cecd95b5c (patch) | |
| tree | 8d9eea7c7a9274d0eb9b218df9c6cad5597648e7 | |
| parent | e8591b7730777af87c1ea2b6d7742118c2531bf3 (diff) | |
msm: mdss: hdmi: cleanup wakeup calls
Do not lock in wakeup functions as it may block current thread.
Wakeup can trigger a callback looking to acquire same lock.
Also rename the wakeup command names to properly identify client
and lib commands.
Change-Id: I28411714d2d7f0104364726fc5ce0593e5ccff91
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
| -rw-r--r-- | drivers/misc/hdcp.c | 202 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c | 244 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_tx.c | 2 | ||||
| -rw-r--r-- | include/linux/hdcp_qseecom.h | 97 |
4 files changed, 277 insertions, 268 deletions
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c index 3acfb3e272cf..7319d51114b0 100644 --- a/drivers/misc/hdcp.c +++ b/drivers/misc/hdcp.c @@ -85,7 +85,11 @@ #define MAX_RCVR_IDS_ALLOWED_IN_LIST 31 #define MAX_RCVR_ID_LIST_SIZE \ (RCVR_ID_SIZE*MAX_RCVR_IDS_ALLOWED_IN_LIST) -#define SLEEP_SET_HW_KEY_MS 200 +/* + * minimum wait as per standard is 200 ms. keep it 300 ms + * to be on safe side. + */ +#define SLEEP_SET_HW_KEY_MS 300 #define QSEECOM_ALIGN_SIZE 0x40 @@ -387,60 +391,30 @@ static const char *hdcp_lib_message_name(int msg_id) return "UNKNOWN"; } -static inline int hdcp_lib_report_error(struct hdcp_lib_handle *handle) +static inline void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle, + struct hdmi_hdcp_wakeup_data *data) { - int rc = -EINVAL; + int rc = 0; - if (handle->client_ops->wakeup) { - rc = handle->client_ops->wakeup( - handle->client_ctx, HDMI_HDCP_STATUS_FAIL, - 0, 0, 0); + if (handle && handle->client_ops && handle->client_ops->wakeup && + data && (data->cmd != HDMI_HDCP_WKUP_CMD_INVALID)) { + rc = handle->client_ops->wakeup(data); if (rc) - pr_err("error: report error\n"); - } else { - pr_err("error: client ops wakeup not defined\n"); + pr_err("error sending %s to client\n", + hdmi_hdcp_cmd_to_str(data->cmd)); } - - return rc; } -static inline int hdcp_lib_recv_message(struct hdcp_lib_handle *handle) +static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle) { - int rc = -EINVAL; - - if (handle->client_ops->wakeup) { - rc = handle->client_ops->wakeup( - handle->client_ctx, HDMI_HDCP_RECV_MESSAGE, - 0, 0, handle->hdcp_timeout); - if (rc) - pr_err("error receiving message from client\n"); - } else { - pr_err("error: client ops wakeup not defined\n"); - } - - return rc; -} + struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_SEND_MESSAGE}; -static inline int hdcp_lib_send_message(struct hdcp_lib_handle *handle) -{ - int rc = -EINVAL; - - pr_debug("send msg: %s to sink\n", - hdcp_lib_message_name((int)handle->listener_buf[0])); - - if (handle->client_ops->wakeup) { - rc = handle->client_ops->wakeup( - handle->client_ctx, HDMI_HDCP_SEND_MESSAGE, - handle->listener_buf, handle->msglen, 0); - if (!rc) - handle->last_msg_sent = (int)handle->listener_buf[0]; - else - pr_err("error sending message to client\n"); - } else { - pr_err("error: client ops wakeup not defined\n"); - } + cdata.context = handle->client_ctx; + cdata.send_msg_buf = handle->listener_buf; + cdata.send_msg_len = handle->msglen; + cdata.timeout = handle->hdcp_timeout; - return rc; + hdcp_lib_wakeup_client(handle, &cdata); } static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle) @@ -450,7 +424,7 @@ static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle) struct hdcp_set_hw_key_rsp *rsp_buf; /* - * wait for 200ms before enabling encryption + * wait at least 200ms before enabling encryption * as per hdcp2p2 sepcifications. */ msleep(SLEEP_SET_HW_KEY_MS); @@ -781,43 +755,38 @@ exit: return supported; } -static int hdcp_lib_wakeup(void *phdcpcontext, - enum hdcp_lib_wakeup_cmd cmd, char *msg, uint32_t msglen) +static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) { - struct hdcp_lib_handle *handle = phdcpcontext; + struct hdcp_lib_handle *handle; int rc = 0; - if (!handle) + if (!data) return -EINVAL; - mutex_lock(&handle->hdcp_lock); - handle->wakeup_cmd = cmd; - mutex_unlock(&handle->hdcp_lock); - - if (handle->wakeup_cmd == HDCP_WKUP_CMD_STOP) { - atomic_set(&handle->hdcp_off_pending, 1); - flush_kthread_worker(&handle->worker); - atomic_set(&handle->hdcp_off_pending, 0); - } + handle = data->context; + if (!handle) + return -EINVAL; - mutex_lock(&handle->hdcp_lock); + handle->wakeup_cmd = data->cmd; - pr_debug("wakeup_cmd: %s\n", hdcp_cmd_to_str(handle->wakeup_cmd)); + pr_debug("wakeup_cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd)); - if (msglen) { - handle->last_msg_recvd_len = msglen; + if (data->recvd_msg_len) { + handle->last_msg_recvd_len = data->recvd_msg_len; - handle->last_msg_recvd_buf = kzalloc(msglen, GFP_KERNEL); + handle->last_msg_recvd_buf = kzalloc(data->recvd_msg_len, + GFP_KERNEL); if (!handle->last_msg_recvd_buf) { rc = -ENOMEM; goto exit; } - memcpy(handle->last_msg_recvd_buf, msg, msglen); + memcpy(handle->last_msg_recvd_buf, data->recvd_msg_buf, + data->recvd_msg_len); } switch (handle->wakeup_cmd) { - case HDCP_WKUP_CMD_START: + case HDCP_LIB_WKUP_CMD_START: handle->no_stored_km_flag = 0; handle->repeater_flag = 0; handle->hdcp_state = HDCP_STATE_INIT; @@ -825,24 +794,26 @@ static int hdcp_lib_wakeup(void *phdcpcontext, if (!atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->init); break; - case HDCP_WKUP_CMD_STOP: - /* wait for any work being executed */ + case HDCP_LIB_WKUP_CMD_STOP: + atomic_set(&handle->hdcp_off_pending, 1); queue_kthread_work(&handle->worker, &handle->clean); break; - case HDCP_WKUP_CMD_MSG_SEND_SUCCESS: + case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS: + handle->last_msg_sent = handle->listener_buf[0]; + if (!atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->msg_sent); break; - case HDCP_WKUP_CMD_MSG_SEND_FAILED: - case HDCP_WKUP_CMD_MSG_RECV_FAILED: + case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED: + case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED: if (!atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->clean); break; - case HDCP_WKUP_CMD_MSG_RECV_SUCCESS: + case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS: if (!atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->msg_recvd); break; - case HDCP_WKUP_CMD_MSG_RECV_TIMEOUT: + case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT: if (!atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->timeout); break; @@ -850,7 +821,6 @@ static int hdcp_lib_wakeup(void *phdcpcontext, pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); } exit: - mutex_unlock(&handle->hdcp_lock); return 0; } @@ -858,6 +828,7 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work) { struct hdcp_lib_handle *handle = container_of(work, struct hdcp_lib_handle, msg_sent); + struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID}; if (!handle) { pr_err("invalid handle\n"); @@ -866,15 +837,17 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work) mutex_lock(&handle->hdcp_lock); - if (handle->wakeup_cmd == HDCP_WKUP_CMD_MSG_SEND_SUCCESS) { + cdata.context = handle->client_ctx; + + if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) { if (handle->last_msg_sent == SKE_SEND_EKS_MESSAGE_ID) { if (!hdcp_lib_enable_encryption(handle)) - handle->client_ops->wakeup( - handle->client_ctx, - HDMI_HDCP_STATUS_SUCCESS, - 0, 0, 0); + cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS; + else + cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_FAILED; } else { - hdcp_lib_recv_message(handle); + cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; + cdata.timeout = handle->hdcp_timeout; } } else { pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); @@ -882,12 +855,14 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work) mutex_unlock(&handle->hdcp_lock); + hdcp_lib_wakeup_client(handle, &cdata); return; } static void hdcp_lib_init_work(struct kthread_work *work) { int rc = 0; + bool send_msg = false; struct hdcp_lib_handle *handle = container_of(work, struct hdcp_lib_handle, init); @@ -898,7 +873,7 @@ static void hdcp_lib_init_work(struct kthread_work *work) mutex_lock(&handle->hdcp_lock); - if (handle->wakeup_cmd == HDCP_WKUP_CMD_START) { + if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_START) { rc = hdcp_lib_library_load(handle); if (rc) goto exit; @@ -907,10 +882,8 @@ static void hdcp_lib_init_work(struct kthread_work *work) if (rc) goto exit; - rc = hdcp_lib_send_message(handle); - if (rc) - goto exit; - } else if (handle->wakeup_cmd == HDCP_WKUP_CMD_STOP) { + send_msg = true; + } else if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_STOP) { rc = hdcp_lib_txmtr_deinit(handle); if (rc) goto exit; @@ -922,16 +895,20 @@ static void hdcp_lib_init_work(struct kthread_work *work) pr_err("invalid wakeup cmd: %d\n", handle->wakeup_cmd); } exit: + mutex_unlock(&handle->hdcp_lock); + + if (send_msg) + hdcp_lib_send_message(handle); + if (rc && !atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->clean); - - mutex_unlock(&handle->hdcp_lock); return; } static void hdcp_lib_manage_timeout_work(struct kthread_work *work) { int rc = 0; + bool send_msg = false; struct hdcp_send_timeout_req *req_buf; struct hdcp_send_timeout_rsp *rsp_buf; struct hdcp_lib_handle *handle = container_of(work, @@ -986,20 +963,24 @@ static void hdcp_lib_manage_timeout_work(struct kthread_work *work) handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; - hdcp_lib_send_message(handle); + send_msg = true; } } error: + mutex_unlock(&handle->hdcp_lock); + + if (send_msg) + hdcp_lib_send_message(handle); + if (rc && !atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->clean); - - mutex_unlock(&handle->hdcp_lock); } static void hdcp_lib_cleanup_work(struct kthread_work *work) { struct hdcp_lib_handle *handle = container_of(work, struct hdcp_lib_handle, clean); + struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID}; if (!handle) { pr_err("invalid input\n"); @@ -1008,18 +989,18 @@ static void hdcp_lib_cleanup_work(struct kthread_work *work) mutex_lock(&handle->hdcp_lock); - if (atomic_read(&handle->hdcp_off_pending)) { - pr_err("hdcp off underway\n"); - goto exit; - } + cdata.context = handle->client_ctx; + cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_FAILED; hdcp_lib_txmtr_deinit(handle); hdcp_lib_library_unload(handle); - if (handle->wakeup_cmd != HDCP_WKUP_CMD_STOP) - hdcp_lib_report_error(handle); -exit: mutex_unlock(&handle->hdcp_lock); + + if (atomic_read(&handle->hdcp_off_pending)) + atomic_set(&handle->hdcp_off_pending, 0); + else + hdcp_lib_wakeup_client(handle, &cdata); } static void hdcp_lib_msg_recvd_work(struct kthread_work *work) @@ -1031,6 +1012,7 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work) char *msg; struct hdcp_lib_handle *handle = container_of(work, struct hdcp_lib_handle, msg_recvd); + struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID}; if (!handle) { pr_err("invalid handle\n"); @@ -1042,8 +1024,10 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work) msg = handle->last_msg_recvd_buf; msglen = handle->last_msg_recvd_len; + cdata.context = handle->client_ctx; + if (msglen <= 0) { - pr_err("invalid msg\n"); + pr_err("invalid msg len\n"); rc = -EINVAL; goto exit; } @@ -1074,7 +1058,11 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work) /* get next message from sink if we receive H PRIME on no store km */ if ((msg[0] == AKE_SEND_H_PRIME_MESSAGE_ID) && handle->no_stored_km_flag) { - hdcp_lib_recv_message(handle); + handle->hdcp_timeout = rsp_buf->timeout; + + cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; + cdata.timeout = handle->hdcp_timeout; + goto exit; } @@ -1120,15 +1108,21 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work) handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; - if (!atomic_read(&handle->hdcp_off_pending)) - hdcp_lib_send_message(handle); + if (!atomic_read(&handle->hdcp_off_pending)) { + cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE; + cdata.send_msg_buf = handle->listener_buf; + cdata.send_msg_len = handle->msglen; + cdata.timeout = handle->hdcp_timeout; + } + exit: kzfree(handle->last_msg_recvd_buf); + mutex_unlock(&handle->hdcp_lock); + + hdcp_lib_wakeup_client(handle, &cdata); if (rc && !atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->clean); - - mutex_unlock(&handle->hdcp_lock); } /* APIs exposed to all clients */ diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c index 8d4ad007efba..1ef90afe3f32 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c @@ -50,13 +50,13 @@ struct hdmi_hdcp2p2_ctrl { enum hdmi_hdcp2p2_sink_status sink_status; /* Is sink connected */ struct hdmi_hdcp_init_data init_data; /* Feature data from HDMI drv */ struct mutex mutex; /* mutex to protect access to ctrl */ + struct mutex wakeup_mutex; /* mutex to protect access to wakeup call*/ struct hdmi_hdcp_ops *ops; void *lib_ctx; /* Handle to HDCP 2.2 Trustzone library */ - struct hdcp_txmtr_ops *txmtr_ops; /* Ops for driver to call into TZ */ - struct hdcp_client_ops *client_ops; /* Ops for driver to export to TZ */ + struct hdcp_txmtr_ops *lib; /* Ops for driver to call into TZ */ struct completion rxstatus_completion; /* Rx status interrupt */ - enum hdmi_hdcp_cmd wakeup_cmd; + enum hdmi_hdcp_wakeup_cmd wakeup_cmd; char *send_msg_buf; uint32_t send_msg_len; uint32_t timeout; @@ -69,6 +69,80 @@ struct hdmi_hdcp2p2_ctrl { struct kthread_work recv_msg; }; +static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) +{ + struct hdmi_hdcp2p2_ctrl *ctrl; + + if (!data) { + pr_err("invalid input\n"); + return -EINVAL; + } + + ctrl = data->context; + if (!ctrl) { + pr_err("invalid ctrl\n"); + return -EINVAL; + } + + mutex_lock(&ctrl->wakeup_mutex); + + pr_debug("wakeup_cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd)); + + ctrl->wakeup_cmd = data->cmd; + ctrl->timeout = data->timeout; + + if (data->send_msg_len) { + ctrl->send_msg_len = data->send_msg_len; + + ctrl->send_msg_buf = kzalloc( + data->send_msg_len, GFP_KERNEL); + + if (!ctrl->send_msg_buf) + goto exit; + + memcpy(ctrl->send_msg_buf, data->send_msg_buf, + ctrl->send_msg_len); + } + + switch (ctrl->wakeup_cmd) { + case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE: + if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) + queue_kthread_work(&ctrl->worker, &ctrl->send_msg); + break; + case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE: + if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) + queue_kthread_work(&ctrl->worker, &ctrl->recv_msg); + break; + case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS: + case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: + if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) + queue_kthread_work(&ctrl->worker, &ctrl->status); + break; + case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: + queue_kthread_work(&ctrl->worker, &ctrl->auth); + break; + default: + pr_err("invalid wakeup command %d\n", ctrl->wakeup_cmd); + } +exit: + mutex_unlock(&ctrl->wakeup_mutex); + return 0; +} + +static inline void hdmi_hdcp2p2_wakeup_lib(struct hdmi_hdcp2p2_ctrl *ctrl, + struct hdcp_lib_wakeup_data *data) +{ + int rc = 0; + + if (ctrl && ctrl->lib && ctrl->lib->wakeup && + data && (data->cmd != HDCP_LIB_WKUP_CMD_INVALID)) { + rc = ctrl->lib->wakeup(data); + if (rc) + pr_err("error sending %s to lib\n", + hdcp_lib_cmd_to_str(data->cmd)); + } +} + static void hdmi_hdcp2p2_reset(struct hdmi_hdcp2p2_ctrl *ctrl) { if (!ctrl) { @@ -83,6 +157,7 @@ static void hdmi_hdcp2p2_reset(struct hdmi_hdcp2p2_ctrl *ctrl) static void hdmi_hdcp2p2_off(void *input) { struct hdmi_hdcp2p2_ctrl *ctrl = (struct hdmi_hdcp2p2_ctrl *)input; + struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_AUTHENTICATE}; if (!ctrl) { pr_err("invalid input\n"); @@ -93,25 +168,25 @@ static void hdmi_hdcp2p2_off(void *input) flush_kthread_worker(&ctrl->worker); - mutex_lock(&ctrl->mutex); - queue_kthread_work(&ctrl->worker, &ctrl->auth); - mutex_unlock(&ctrl->mutex); + cdata.context = input; + + hdmi_hdcp2p2_wakeup(&cdata); } static int hdmi_hdcp2p2_authenticate(void *input) { struct hdmi_hdcp2p2_ctrl *ctrl = input; + struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_AUTHENTICATE}; int rc = 0; flush_kthread_worker(&ctrl->worker); - mutex_lock(&ctrl->mutex); ctrl->sink_status = SINK_CONNECTED; atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING); - queue_kthread_work(&ctrl->worker, &ctrl->auth); + cdata.context = input; + hdmi_hdcp2p2_wakeup(&cdata); - mutex_unlock(&ctrl->mutex); return rc; } @@ -208,7 +283,7 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev, } pr_debug("notification of minimum level change received\n"); - res = ctrl->txmtr_ops-> + res = ctrl->lib-> hdcp_query_stream_type(ctrl->lib_ctx); return count; @@ -398,7 +473,7 @@ static bool hdmi_hdcp2p2_feature_supported(void *input) goto end; } - lib = ctrl->txmtr_ops; + lib = ctrl->lib; if (!lib) { pr_err("invalid lib ops data\n"); goto end; @@ -416,8 +491,7 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work) int rc = 0; struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, send_msg); - struct hdcp_txmtr_ops *lib = NULL; - enum hdcp_lib_wakeup_cmd cmd; + struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID}; if (!ctrl) { pr_err("invalid input\n"); @@ -426,34 +500,27 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work) mutex_lock(&ctrl->mutex); + cdata.context = ctrl->lib_ctx; + if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { pr_err("hdcp is off\n"); goto exit; } - lib = ctrl->txmtr_ops; - - if (!lib) { - pr_err("invalid lib data\n"); - goto exit; - } - /* Forward the message to the sink */ rc = hdmi_hdcp2p2_ddc_write_message(ctrl, - ctrl->send_msg_buf, - (size_t)ctrl->send_msg_len); + ctrl->send_msg_buf, (size_t)ctrl->send_msg_len); if (rc) { pr_err("Error sending msg to sink %d\n", rc); - cmd = HDCP_WKUP_CMD_MSG_SEND_FAILED; + cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED; } else { - cmd = HDCP_WKUP_CMD_MSG_SEND_SUCCESS; + cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS; } - - if (lib->wakeup) - lib->wakeup(ctrl->lib_ctx, cmd, 0, 0); exit: kzfree(ctrl->send_msg_buf); mutex_unlock(&ctrl->mutex); + + hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); } static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) @@ -463,11 +530,10 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) char *recvd_msg_buf = NULL; struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, recv_msg); - struct hdcp_txmtr_ops *lib = NULL; - enum hdcp_lib_wakeup_cmd cmd; struct hdmi_tx_hdcp2p2_ddc_data hdcp2p2_ddc_data; struct hdmi_tx_ddc_ctrl *ddc_ctrl; struct msm_hdmi_mode_timing_info *timing; + struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID}; if (!ctrl) { pr_err("invalid input\n"); @@ -476,13 +542,7 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) mutex_lock(&ctrl->mutex); - lib = ctrl->txmtr_ops; - - if (!lib) { - pr_err("invalid lib data\n"); - rc = -EINVAL; - goto exit; - } + cdata.context = ctrl->lib_ctx; if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { pr_err("hdcp is off\n"); @@ -539,20 +599,20 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) hdmi_hdcp2p2_ddc_abort(ctrl); hdmi_hdcp2p2_ddc_reset(ddc_ctrl); hdmi_hdcp2p2_ddc_disable(ddc_ctrl); + + cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS; + cdata.recvd_msg_buf = recvd_msg_buf; + cdata.recvd_msg_len = msg_size; exit: if (rc == -ETIMEDOUT) - cmd = HDCP_WKUP_CMD_MSG_RECV_TIMEOUT; + cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT; else if (rc) - cmd = HDCP_WKUP_CMD_MSG_RECV_FAILED; - else - cmd = HDCP_WKUP_CMD_MSG_RECV_SUCCESS; + cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED; - if (lib->wakeup) - lib->wakeup(ctrl->lib_ctx, cmd, - recvd_msg_buf, msg_size); + mutex_unlock(&ctrl->mutex); + hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); kfree(recvd_msg_buf); - mutex_unlock(&ctrl->mutex); } static void hdmi_hdcp2p2_auth_status_work(struct kthread_work *work) @@ -572,9 +632,9 @@ static void hdmi_hdcp2p2_auth_status_work(struct kthread_work *work) goto exit; } - if (ctrl->wakeup_cmd == HDMI_HDCP_STATUS_FAIL) { + if (ctrl->wakeup_cmd == HDMI_HDCP_WKUP_CMD_STATUS_FAILED) { hdmi_hdcp2p2_auth_failed(ctrl); - } else if (ctrl->wakeup_cmd == HDMI_HDCP_STATUS_SUCCESS) { + } else if (ctrl->wakeup_cmd == HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS) { /* Enable interrupts */ u32 regval = DSS_REG_R(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2); @@ -598,8 +658,7 @@ static void hdmi_hdcp2p2_auth_work(struct kthread_work *work) { struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, auth); - enum hdcp_lib_wakeup_cmd cmd; - struct hdcp_txmtr_ops *lib = NULL; + struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID}; if (!ctrl) { pr_err("invalid input\n"); @@ -608,93 +667,31 @@ static void hdmi_hdcp2p2_auth_work(struct kthread_work *work) mutex_lock(&ctrl->mutex); - if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { - pr_err("hdcp is off\n"); - goto exit; - } + cdata.context = ctrl->lib_ctx; - lib = ctrl->txmtr_ops; - if (lib && lib->wakeup) { - if (atomic_read(&ctrl->auth_state) == - HDCP_STATE_AUTHENTICATING) - cmd = HDCP_WKUP_CMD_START; - else - cmd = HDCP_WKUP_CMD_STOP; + if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTHENTICATING) + cdata.cmd = HDCP_LIB_WKUP_CMD_START; + else + cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; - lib->wakeup(ctrl->lib_ctx, cmd, 0, 0); - } -exit: mutex_unlock(&ctrl->mutex); -} - -static int hdmi_hdcp2p2_wakeup(void *client_ctx, enum hdmi_hdcp_cmd cmd, - char *msg, uint32_t msglen, uint32_t timeout) -{ - struct hdmi_hdcp2p2_ctrl *ctrl = client_ctx; - - if (!ctrl) { - pr_err("invalid input\n"); - return -EINVAL; - } - - mutex_lock(&ctrl->mutex); - - pr_debug("wakeup_cmd: %s\n", hdmi_hdcp_cmd_to_str(cmd)); - - if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { - pr_err("hdcp is off\n"); - goto exit; - } - - ctrl->wakeup_cmd = cmd; - ctrl->send_msg_len = msglen; - ctrl->timeout = timeout; - - if (msglen) { - ctrl->send_msg_buf = kzalloc( - ctrl->send_msg_len, GFP_KERNEL); - - if (!ctrl->send_msg_buf) - goto exit; - memcpy(ctrl->send_msg_buf, msg, msglen); - } - - switch (ctrl->wakeup_cmd) { - case HDMI_HDCP_SEND_MESSAGE: - queue_kthread_work(&ctrl->worker, &ctrl->send_msg); - break; - case HDMI_HDCP_RECV_MESSAGE: - queue_kthread_work(&ctrl->worker, &ctrl->recv_msg); - break; - case HDMI_HDCP_STATUS_SUCCESS: - case HDMI_HDCP_STATUS_FAIL: - queue_kthread_work(&ctrl->worker, &ctrl->status); - break; - default: - pr_err("invalid wakeup command %d\n", - ctrl->wakeup_cmd); - } -exit: - mutex_unlock(&ctrl->mutex); - return 0; + hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); } void hdmi_hdcp2p2_deinit(void *input) { struct hdmi_hdcp2p2_ctrl *ctrl = (struct hdmi_hdcp2p2_ctrl *)input; - struct hdcp_txmtr_ops *lib = NULL; + struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID}; if (!ctrl) { pr_err("invalid input\n"); return; } - lib = ctrl->txmtr_ops; - - if (lib && lib->wakeup) - lib->wakeup(ctrl->lib_ctx, - HDCP_WKUP_CMD_STOP, 0, 0); + cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; + cdata.context = ctrl->lib_ctx; + hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); kthread_stop(ctrl->thread); @@ -742,8 +739,7 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data) return ERR_PTR(-ENOMEM); ctrl->init_data = *init_data; - ctrl->client_ops = &client_ops; - ctrl->txmtr_ops = &txmtr_ops; + ctrl->lib = &txmtr_ops; rc = sysfs_create_group(init_data->sysfs_kobj, &hdmi_hdcp2p2_fs_attr_group); @@ -760,10 +756,10 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data) ctrl->ops = &ops; mutex_init(&ctrl->mutex); + mutex_init(&ctrl->wakeup_mutex); rc = hdcp_library_register(&ctrl->lib_ctx, - ctrl->client_ops, - ctrl->txmtr_ops, ctrl); + &client_ops, ctrl->lib, ctrl); if (rc) { pr_err("Unable to register with HDCP 2.2 library\n"); goto error; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index 859fd396ca14..c55e76c11cf2 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -1242,7 +1242,7 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) rc = hdmi_tx_config_avmute(hdmi_ctrl, true); } - if (hdmi_ctrl->hpd_state) { + if (hdmi_ctrl->hpd_state && hdmi_ctrl->panel_power_on) { DEV_DBG("%s: Reauthenticating\n", __func__); rc = hdmi_ctrl->hdcp_ops->hdmi_hdcp_reauthenticate( hdmi_ctrl->hdcp_feature_data); diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h index 8d7f19ad97ff..51cc4a1b6e6e 100644 --- a/include/linux/hdcp_qseecom.h +++ b/include/linux/hdcp_qseecom.h @@ -15,63 +15,83 @@ #include <linux/types.h> enum hdcp_lib_wakeup_cmd { - HDCP_WKUP_CMD_START, - HDCP_WKUP_CMD_STOP, - HDCP_WKUP_CMD_MSG_SEND_SUCCESS, - HDCP_WKUP_CMD_MSG_SEND_FAILED, - HDCP_WKUP_CMD_MSG_RECV_SUCCESS, - HDCP_WKUP_CMD_MSG_RECV_FAILED, - HDCP_WKUP_CMD_MSG_RECV_TIMEOUT, + HDCP_LIB_WKUP_CMD_INVALID, + HDCP_LIB_WKUP_CMD_START, + HDCP_LIB_WKUP_CMD_STOP, + HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS, + HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED, + HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS, + HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED, + HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT, }; -enum hdmi_hdcp_cmd { - HDMI_HDCP_SEND_MESSAGE, - HDMI_HDCP_RECV_MESSAGE, - HDMI_HDCP_STATUS_SUCCESS, - HDMI_HDCP_STATUS_FAIL +enum hdmi_hdcp_wakeup_cmd { + HDMI_HDCP_WKUP_CMD_INVALID, + HDMI_HDCP_WKUP_CMD_SEND_MESSAGE, + HDMI_HDCP_WKUP_CMD_RECV_MESSAGE, + HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS, + HDMI_HDCP_WKUP_CMD_STATUS_FAILED, + HDMI_HDCP_WKUP_CMD_AUTHENTICATE +}; + +struct hdcp_lib_wakeup_data { + enum hdcp_lib_wakeup_cmd cmd; + void *context; + char *recvd_msg_buf; + uint32_t recvd_msg_len; + uint32_t timeout; +}; + +struct hdmi_hdcp_wakeup_data { + enum hdmi_hdcp_wakeup_cmd cmd; + void *context; + char *send_msg_buf; + uint32_t send_msg_len; + uint32_t timeout; }; static inline char *hdmi_hdcp_cmd_to_str(uint32_t cmd) { switch (cmd) { - case HDMI_HDCP_SEND_MESSAGE: - return "HDMI_HDCP_SEND_MESSAGE"; - case HDMI_HDCP_RECV_MESSAGE: - return "HDMI_HDCP_RECV_MESSAGE"; - case HDMI_HDCP_STATUS_SUCCESS: - return "HDMI_HDCP_STATUS_SUCCESS"; - case HDMI_HDCP_STATUS_FAIL: - return "HDMI_HDCP_STATUS_FAIL"; + case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE: + return "HDMI_HDCP_WKUP_CMD_SEND_MESSAGE"; + case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE: + return "HDMI_HDCP_WKUP_CMD_RECV_MESSAGE"; + case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS: + return "HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS"; + case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: + return "HDMI_HDCP_WKUP_CMD_STATUS_FAIL"; + case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: + return "HDMI_HDCP_WKUP_CMD_AUTHENTICATE"; default: return "???"; } } -static inline char *hdcp_cmd_to_str(uint32_t cmd) +static inline char *hdcp_lib_cmd_to_str(uint32_t cmd) { switch (cmd) { - case HDCP_WKUP_CMD_START: - return "HDCP_WKUP_CMD_START"; - case HDCP_WKUP_CMD_STOP: - return "HDCP_WKUP_CMD_STOP"; - case HDCP_WKUP_CMD_MSG_SEND_SUCCESS: - return "HDCP_WKUP_CMD_MSG_SEND_SUCCESS"; - case HDCP_WKUP_CMD_MSG_SEND_FAILED: - return "HDCP_WKUP_CMD_MSG_SEND_FAILED"; - case HDCP_WKUP_CMD_MSG_RECV_SUCCESS: - return "HDCP_WKUP_CMD_MSG_RECV_SUCCESS"; - case HDCP_WKUP_CMD_MSG_RECV_FAILED: - return "HDCP_WKUP_CMD_MSG_RECV_FAILED"; - case HDCP_WKUP_CMD_MSG_RECV_TIMEOUT: - return "HDCP_WKUP_CMD_MSG_RECV_TIMEOUT"; + case HDCP_LIB_WKUP_CMD_START: + return "HDCP_LIB_WKUP_CMD_START"; + case HDCP_LIB_WKUP_CMD_STOP: + return "HDCP_LIB_WKUP_CMD_STOP"; + case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS: + return "HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS"; + case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED: + return "HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED"; + case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS: + return "HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS"; + case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED: + return "HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED"; + case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT: + return "HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT"; default: return "???"; } } struct hdcp_txmtr_ops { - int (*wakeup)(void *phdcpcontext, enum hdcp_lib_wakeup_cmd cmd, - char *msg, uint32_t len); + int (*wakeup)(struct hdcp_lib_wakeup_data *data); bool (*feature_supported)(void *phdcpcontext); int (*hdcp_txmtr_get_state)(void *phdcpcontext, @@ -80,8 +100,7 @@ struct hdcp_txmtr_ops { }; struct hdcp_client_ops { - int (*wakeup)(void *client_ctx, enum hdmi_hdcp_cmd cmd, - char *msg, uint32_t msglen, uint32_t timeout); + int (*wakeup)(struct hdmi_hdcp_wakeup_data *data); }; int hdcp_library_register(void **pphdcpcontext, |
