summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjay Singh Parmar <aparmar@codeaurora.org>2015-10-01 13:24:06 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:46:20 -0700
commit38fdd3f630696356da2575fe8f0ea51cecd95b5c (patch)
tree8d9eea7c7a9274d0eb9b218df9c6cad5597648e7
parente8591b7730777af87c1ea2b6d7742118c2531bf3 (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.c202
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c244
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c2
-rw-r--r--include/linux/hdcp_qseecom.h97
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,