summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/hdcp.c321
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_hdcp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c296
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c8
-rw-r--r--include/linux/hdcp_qseecom.h14
5 files changed, 413 insertions, 227 deletions
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index b6675fcbaaaa..66b1135fe855 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -126,11 +126,12 @@
/*This API calls the library deinit function */
#define HDCP_LIB_DEINIT SERVICE_TXMTR_CREATE_CMD(12)
-enum hdcp_app_status {
- LOADED,
- UNLOADED,
- FAILED = -1,
-};
+#define HDCP_LIB_EXECUTE(x) {\
+ if (handle->tethered)\
+ hdcp_lib_##x(handle);\
+ else\
+ queue_kthread_work(&handle->worker, &handle->wk_##x);\
+}
enum hdcp_state {
HDCP_STATE_INIT = 0x00,
@@ -337,12 +338,12 @@ struct hdcp_lib_handle {
bool feature_supported;
void *client_ctx;
struct hdcp_client_ops *client_ops;
- struct mutex hdcp_lock;
struct mutex msg_lock;
struct mutex wakeup_mutex;
enum hdcp_state hdcp_state;
enum hdcp_lib_wakeup_cmd wakeup_cmd;
bool repeater_flag;
+ bool tethered;
struct qseecom_handle *qseecom_handle;
int last_msg_sent;
char *last_msg_recvd_buf;
@@ -353,13 +354,13 @@ struct hdcp_lib_handle {
struct completion topo_wait;
struct kthread_worker worker;
- struct kthread_work init;
- struct kthread_work msg_sent;
- struct kthread_work msg_recvd;
- struct kthread_work timeout;
- struct kthread_work clean;
- struct kthread_work topology;
- struct kthread_work stream;
+ 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_topology;
+ struct kthread_work wk_stream;
};
struct hdcp_lib_message_map {
@@ -367,6 +368,13 @@ struct hdcp_lib_message_map {
const char *msg_name;
};
+static void hdcp_lib_clean(struct hdcp_lib_handle *handle);
+static void hdcp_lib_init(struct hdcp_lib_handle *handle);
+static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle);
+static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle);
+static void hdcp_lib_timeout(struct hdcp_lib_handle *handle);
+static void hdcp_lib_stream(struct hdcp_lib_handle *handle);
+
static struct qseecom_handle *hdcp1_handle;
static bool hdcp1_supported = true;
@@ -467,7 +475,7 @@ static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle)
return 0;
error:
if (!atomic_read(&handle->hdcp_off))
- queue_kthread_work(&handle->worker, &handle->clean);
+ HDCP_LIB_EXECUTE(clean);
return rc;
}
@@ -678,21 +686,17 @@ exit:
return rc;
}
-static void hdcp_lib_query_stream_type_work(struct kthread_work *work)
+static void hdcp_lib_stream(struct hdcp_lib_handle *handle)
{
int rc = 0;
struct hdcp_query_stream_type_req *req_buf;
struct hdcp_query_stream_type_rsp *rsp_buf;
- struct hdcp_lib_handle *handle = container_of(work,
- struct hdcp_lib_handle, stream);
if (!handle) {
pr_err("invalid handle\n");
return;
}
- mutex_lock(&handle->hdcp_lock);
-
/* send command to TZ */
req_buf = (struct hdcp_query_stream_type_req *)handle->
qseecom_handle->sbuf;
@@ -724,12 +728,18 @@ static void hdcp_lib_query_stream_type_work(struct kthread_work *work)
handle->hdcp_timeout = rsp_buf->timeout;
handle->msglen = rsp_buf->msglen;
exit:
- mutex_unlock(&handle->hdcp_lock);
-
if (!rc && !atomic_read(&handle->hdcp_off))
hdcp_lib_send_message(handle);
}
+static void hdcp_lib_query_stream_work(struct kthread_work *work)
+{
+ struct hdcp_lib_handle *handle = container_of(work,
+ struct hdcp_lib_handle, wk_stream);
+
+ hdcp_lib_stream(handle);
+}
+
static bool hdcp_lib_client_feature_supported(void *phdcpcontext)
{
int rc = 0;
@@ -759,46 +769,46 @@ exit:
static void hdcp_lib_check_worker_status(struct hdcp_lib_handle *handle)
{
- if (!list_empty(&handle->init.node))
+ if (!list_empty(&handle->wk_init.node))
pr_debug("init work queued\n");
- if (handle->worker.current_work == &handle->init)
+ if (handle->worker.current_work == &handle->wk_init)
pr_debug("init work executing\n");
- if (!list_empty(&handle->msg_sent.node))
+ if (!list_empty(&handle->wk_msg_sent.node))
pr_debug("msg_sent work queued\n");
- if (handle->worker.current_work == &handle->msg_sent)
+ if (handle->worker.current_work == &handle->wk_msg_sent)
pr_debug("msg_sent work executing\n");
- if (!list_empty(&handle->msg_recvd.node))
+ if (!list_empty(&handle->wk_msg_recvd.node))
pr_debug("msg_recvd work queued\n");
- if (handle->worker.current_work == &handle->msg_recvd)
+ if (handle->worker.current_work == &handle->wk_msg_recvd)
pr_debug("msg_recvd work executing\n");
- if (!list_empty(&handle->timeout.node))
+ if (!list_empty(&handle->wk_timeout.node))
pr_debug("timeout work queued\n");
- if (handle->worker.current_work == &handle->timeout)
+ if (handle->worker.current_work == &handle->wk_timeout)
pr_debug("timeout work executing\n");
- if (!list_empty(&handle->clean.node))
+ if (!list_empty(&handle->wk_clean.node))
pr_debug("clean work queued\n");
- if (handle->worker.current_work == &handle->clean)
+ if (handle->worker.current_work == &handle->wk_clean)
pr_debug("clean work executing\n");
- if (!list_empty(&handle->topology.node))
+ if (!list_empty(&handle->wk_topology.node))
pr_debug("topology work queued\n");
- if (handle->worker.current_work == &handle->topology)
+ if (handle->worker.current_work == &handle->wk_topology)
pr_debug("topology work executing\n");
- if (!list_empty(&handle->stream.node))
+ if (!list_empty(&handle->wk_stream.node))
pr_debug("stream work queued\n");
- if (handle->worker.current_work == &handle->stream)
+ if (handle->worker.current_work == &handle->wk_stream)
pr_debug("stream work executing\n");
}
@@ -829,6 +839,28 @@ exit:
return rc;
}
+static void hdcp_lib_update_exec_type(void *ctx, bool tethered)
+{
+ struct hdcp_lib_handle *handle = ctx;
+
+ if (!handle)
+ return;
+
+ mutex_lock(&handle->wakeup_mutex);
+
+ if (handle->tethered == tethered) {
+ pr_debug("exec mode same as %s\n",
+ tethered ? "tethered" : "threaded");
+ } else {
+ handle->tethered = tethered;
+
+ pr_debug("exec mode changed to %s\n",
+ tethered ? "tethered" : "threaded");
+ }
+
+ mutex_unlock(&handle->wakeup_mutex);
+}
+
static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
{
struct hdcp_lib_handle *handle;
@@ -846,9 +878,9 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
handle->wakeup_cmd = data->cmd;
handle->timeout_left = data->timeout;
- pr_debug("%s, timeout left: %dms\n",
+ pr_debug("%s, timeout left: %dms, tethered %d\n",
hdcp_lib_cmd_to_str(handle->wakeup_cmd),
- handle->timeout_left);
+ handle->timeout_left, handle->tethered);
rc = hdcp_lib_check_valid_state(handle);
if (rc)
@@ -885,42 +917,42 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
atomic_set(&handle->hdcp_off, 0);
handle->hdcp_state = HDCP_STATE_INIT;
- queue_kthread_work(&handle->worker, &handle->init);
+ HDCP_LIB_EXECUTE(init);
break;
case HDCP_LIB_WKUP_CMD_STOP:
atomic_set(&handle->hdcp_off, 1);
- queue_kthread_work(&handle->worker, &handle->clean);
+
+ HDCP_LIB_EXECUTE(clean);
break;
case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS:
handle->last_msg_sent = handle->listener_buf[0];
- queue_kthread_work(&handle->worker, &handle->msg_sent);
+ HDCP_LIB_EXECUTE(msg_sent);
break;
case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED:
case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED:
- queue_kthread_work(&handle->worker, &handle->clean);
+ HDCP_LIB_EXECUTE(clean);
break;
case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS:
- queue_kthread_work(&handle->worker, &handle->msg_recvd);
+ HDCP_LIB_EXECUTE(msg_recvd);
break;
case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT:
- queue_kthread_work(&handle->worker, &handle->timeout);
+ HDCP_LIB_EXECUTE(timeout);
break;
case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE:
- queue_kthread_work(&handle->worker, &handle->stream);
+ HDCP_LIB_EXECUTE(stream);
break;
default:
pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
}
exit:
mutex_unlock(&handle->wakeup_mutex);
+
return rc;
}
-static void hdcp_lib_msg_sent_work(struct kthread_work *work)
+static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle)
{
- 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) {
@@ -928,13 +960,6 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work)
return;
}
- if (handle->wakeup_cmd != HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) {
- pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
- return;
- }
-
- mutex_lock(&handle->hdcp_lock);
-
cdata.context = handle->client_ctx;
switch (handle->last_msg_sent) {
@@ -942,15 +967,15 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work)
if (handle->repeater_flag) {
if (!atomic_read(&handle->hdcp_off))
queue_kthread_work(&handle->worker,
- &handle->topology);
+ &handle->wk_topology);
}
- if (!hdcp_lib_enable_encryption(handle))
+ if (!hdcp_lib_enable_encryption(handle)) {
cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS;
- else
+ } else {
if (!atomic_read(&handle->hdcp_off))
- queue_kthread_work(&handle->worker,
- &handle->clean);
+ HDCP_LIB_EXECUTE(clean);
+ }
break;
case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
pr_debug("Repeater authentication successful\n");
@@ -960,72 +985,70 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work)
cdata.timeout = handle->timeout_left;
}
- mutex_unlock(&handle->hdcp_lock);
-
hdcp_lib_wakeup_client(handle, &cdata);
}
-static void hdcp_lib_init_work(struct kthread_work *work)
+static void hdcp_lib_msg_sent_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);
+ struct hdcp_lib_handle, wk_msg_sent);
+
+ if (handle->wakeup_cmd != HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) {
+ pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
+ return;
+ }
+
+ hdcp_lib_msg_sent(handle);
+}
+
+static void hdcp_lib_init(struct hdcp_lib_handle *handle)
+{
+ int rc = 0;
if (!handle) {
pr_err("invalid handle\n");
return;
}
- mutex_lock(&handle->hdcp_lock);
+ if (handle->wakeup_cmd != HDCP_LIB_WKUP_CMD_START) {
+ pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
+ return;
+ }
- if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_START) {
- rc = hdcp_lib_library_load(handle);
- if (rc)
- goto exit;
+ rc = hdcp_lib_library_load(handle);
+ if (rc)
+ goto exit;
- rc = hdcp_lib_txmtr_init(handle);
- if (rc)
- goto exit;
+ rc = hdcp_lib_txmtr_init(handle);
+ if (rc)
+ goto exit;
- send_msg = true;
- } else if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_STOP) {
- rc = hdcp_lib_txmtr_deinit(handle);
- if (rc)
- goto exit;
+ hdcp_lib_send_message(handle);
- rc = hdcp_lib_library_unload(handle);
- if (rc)
- goto exit;
- } else {
- pr_err("invalid wakeup cmd: %d\n", handle->wakeup_cmd);
- }
+ return;
exit:
- mutex_unlock(&handle->hdcp_lock);
+ HDCP_LIB_EXECUTE(clean);
+}
- if (send_msg)
- hdcp_lib_send_message(handle);
+static void hdcp_lib_init_work(struct kthread_work *work)
+{
+ struct hdcp_lib_handle *handle = container_of(work,
+ struct hdcp_lib_handle, wk_init);
- if (rc && !atomic_read(&handle->hdcp_off))
- queue_kthread_work(&handle->worker, &handle->clean);
+ hdcp_lib_init(handle);
}
-static void hdcp_lib_manage_timeout_work(struct kthread_work *work)
+static void hdcp_lib_timeout(struct hdcp_lib_handle *handle)
{
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,
- struct hdcp_lib_handle, timeout);
if (!handle) {
pr_err("invalid handle\n");
return;
}
- mutex_lock(&handle->hdcp_lock);
-
req_buf = (struct hdcp_send_timeout_req *)
(handle->qseecom_handle->sbuf);
req_buf->commandid = HDCP_TXMTR_SEND_MESSAGE_TIMEOUT;
@@ -1068,23 +1091,24 @@ static void hdcp_lib_manage_timeout_work(struct kthread_work *work)
handle->hdcp_timeout = rsp_buf->timeout;
handle->msglen = rsp_buf->msglen;
- send_msg = true;
+ hdcp_lib_send_message(handle);
}
}
error:
- mutex_unlock(&handle->hdcp_lock);
+ if (!atomic_read(&handle->hdcp_off))
+ HDCP_LIB_EXECUTE(clean);
+}
- if (send_msg)
- hdcp_lib_send_message(handle);
+static void hdcp_lib_manage_timeout_work(struct kthread_work *work)
+{
+ struct hdcp_lib_handle *handle = container_of(work,
+ struct hdcp_lib_handle, wk_timeout);
- if (rc && !atomic_read(&handle->hdcp_off))
- queue_kthread_work(&handle->worker, &handle->clean);
+ hdcp_lib_timeout(handle);
}
-static void hdcp_lib_cleanup_work(struct kthread_work *work)
+static void hdcp_lib_clean(struct hdcp_lib_handle *handle)
{
- 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) {
@@ -1092,15 +1116,11 @@ static void hdcp_lib_cleanup_work(struct kthread_work *work)
return;
};
- mutex_lock(&handle->hdcp_lock);
-
- cdata.context = handle->client_ctx;
- cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_FAILED;
-
hdcp_lib_txmtr_deinit(handle);
hdcp_lib_library_unload(handle);
- mutex_unlock(&handle->hdcp_lock);
+ cdata.context = handle->client_ctx;
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_FAILED;
if (!atomic_read(&handle->hdcp_off))
hdcp_lib_wakeup_client(handle, &cdata);
@@ -1108,23 +1128,29 @@ static void hdcp_lib_cleanup_work(struct kthread_work *work)
atomic_set(&handle->hdcp_off, 1);
}
-static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
+
+static void hdcp_lib_cleanup_work(struct kthread_work *work)
+{
+ struct hdcp_lib_handle *handle = container_of(work,
+ struct hdcp_lib_handle, wk_clean);
+
+ hdcp_lib_clean(handle);
+}
+
+static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
{
int rc = 0;
+ struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID};
struct hdcp_rcvd_msg_req *req_buf;
struct hdcp_rcvd_msg_rsp *rsp_buf;
uint32_t msglen;
- char *msg = NULL;
- 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};
+ char *msg;
if (!handle) {
pr_err("invalid handle\n");
return;
}
- mutex_lock(&handle->hdcp_lock);
cdata.context = handle->client_ctx;
mutex_lock(&handle->msg_lock);
@@ -1233,19 +1259,26 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
exit:
kzfree(msg);
- mutex_unlock(&handle->hdcp_lock);
hdcp_lib_wakeup_client(handle, &cdata);
if (rc && !atomic_read(&handle->hdcp_off))
- queue_kthread_work(&handle->worker, &handle->clean);
+ HDCP_LIB_EXECUTE(clean);
+}
+
+static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
+{
+ struct hdcp_lib_handle *handle = container_of(work,
+ struct hdcp_lib_handle, wk_msg_recvd);
+
+ hdcp_lib_msg_recvd(handle);
}
static void hdcp_lib_topology_work(struct kthread_work *work)
{
u32 timeout;
struct hdcp_lib_handle *handle = container_of(work,
- struct hdcp_lib_handle, topology);
+ struct hdcp_lib_handle, wk_topology);
if (!handle) {
pr_err("invalid input\n");
@@ -1258,7 +1291,7 @@ static void hdcp_lib_topology_work(struct kthread_work *work)
pr_err("topology receiver id list timeout\n");
if (!atomic_read(&handle->hdcp_off))
- queue_kthread_work(&handle->worker, &handle->clean);
+ HDCP_LIB_EXECUTE(clean);
}
}
@@ -1329,32 +1362,35 @@ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb)
return 0;
}
-int hdcp_library_register(void **pphdcpcontext,
- struct hdcp_client_ops *client_ops,
- struct hdcp_txmtr_ops *txmtr_ops,
- void *client_ctx)
+int hdcp_library_register(struct hdcp_register_data *data)
{
int rc = 0;
struct hdcp_lib_handle *handle = NULL;
- if (!pphdcpcontext) {
- pr_err("invalid input: context passed\n");
+ if (!data) {
+ pr_err("invalid input\n");
return -EINVAL;
}
- if (!txmtr_ops) {
+ if (!data->txmtr_ops) {
pr_err("invalid input: txmtr context\n");
return -EINVAL;
}
- if (!client_ops) {
+ if (!data->client_ops) {
pr_err("invalid input: client_ops\n");
return -EINVAL;
}
+ if (!data->hdcp_ctx) {
+ pr_err("invalid input: hdcp_ctx\n");
+ return -EINVAL;
+ }
+
/* populate ops to be called by client */
- txmtr_ops->feature_supported = hdcp_lib_client_feature_supported;
- txmtr_ops->wakeup = hdcp_lib_wakeup;
+ data->txmtr_ops->feature_supported = hdcp_lib_client_feature_supported;
+ data->txmtr_ops->wakeup = hdcp_lib_wakeup;
+ data->txmtr_ops->update_exec_type = hdcp_lib_update_exec_type;
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
if (!handle) {
@@ -1362,24 +1398,26 @@ int hdcp_library_register(void **pphdcpcontext,
goto unlock;
}
- handle->client_ctx = client_ctx;
- handle->client_ops = client_ops;
+ handle->client_ctx = data->client_ctx;
+ handle->client_ops = data->client_ops;
+ handle->tethered = data->tethered;
+
+ pr_debug("tethered %d\n", handle->tethered);
atomic_set(&handle->hdcp_off, 0);
- mutex_init(&handle->hdcp_lock);
mutex_init(&handle->msg_lock);
mutex_init(&handle->wakeup_mutex);
init_kthread_worker(&handle->worker);
- init_kthread_work(&handle->init, hdcp_lib_init_work);
- init_kthread_work(&handle->msg_sent, hdcp_lib_msg_sent_work);
- init_kthread_work(&handle->msg_recvd, hdcp_lib_msg_recvd_work);
- init_kthread_work(&handle->timeout, hdcp_lib_manage_timeout_work);
- init_kthread_work(&handle->clean, hdcp_lib_cleanup_work);
- init_kthread_work(&handle->topology, hdcp_lib_topology_work);
- init_kthread_work(&handle->stream, hdcp_lib_query_stream_type_work);
+ init_kthread_work(&handle->wk_init, hdcp_lib_init_work);
+ init_kthread_work(&handle->wk_msg_sent, hdcp_lib_msg_sent_work);
+ init_kthread_work(&handle->wk_msg_recvd, hdcp_lib_msg_recvd_work);
+ init_kthread_work(&handle->wk_timeout, hdcp_lib_manage_timeout_work);
+ init_kthread_work(&handle->wk_clean, hdcp_lib_cleanup_work);
+ init_kthread_work(&handle->wk_topology, hdcp_lib_topology_work);
+ init_kthread_work(&handle->wk_stream, hdcp_lib_query_stream_work);
init_completion(&handle->topo_wait);
@@ -1389,7 +1427,7 @@ int hdcp_library_register(void **pphdcpcontext,
goto error;
}
- *((struct hdcp_lib_handle **)pphdcpcontext) = handle;
+ *data->hdcp_ctx = handle;
handle->thread = kthread_run(kthread_worker_fn,
&handle->worker, "hdcp_tz_lib");
@@ -1423,7 +1461,6 @@ void hdcp_library_deregister(void *phdcpcontext)
kzfree(handle->qseecom_handle);
kzfree(handle->last_msg_recvd_buf);
- mutex_destroy(&handle->hdcp_lock);
mutex_destroy(&handle->wakeup_mutex);
kzfree(handle->listener_buf);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
index 2e8a5126d6fd..7dda3ff5c67d 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
@@ -40,6 +40,7 @@ struct hdmi_hdcp_init_data {
u32 phy_addr;
u32 hdmi_tx_ver;
struct msm_hdmi_mode_timing_info *timing;
+ bool tethered;
};
struct hdmi_hdcp_ops {
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
index 8607d95c2fa6..78936832ab30 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
@@ -51,6 +51,7 @@ enum hdmi_hdcp2p2_sink_status {
struct hdmi_hdcp2p2_ctrl {
atomic_t auth_state;
+ bool tethered;
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 */
@@ -77,6 +78,11 @@ struct hdmi_hdcp2p2_ctrl {
struct delayed_work link_check_work;
};
+static int hdmi_hdcp2p2_auth(struct hdmi_hdcp2p2_ctrl *ctrl);
+static void hdmi_hdcp2p2_send_msg(struct hdmi_hdcp2p2_ctrl *ctrl);
+static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl);
+static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl);
+
static inline bool hdmi_hdcp2p2_is_valid_state(struct hdmi_hdcp2p2_ctrl *ctrl)
{
if (ctrl->wakeup_cmd == HDMI_HDCP_WKUP_CMD_AUTHENTICATE)
@@ -133,9 +139,9 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data)
mutex_lock(&ctrl->wakeup_mutex);
- pr_debug("cmd: %s, timeout %dms\n",
+ pr_debug("cmd: %s, timeout %dms, tethered %d\n",
hdmi_hdcp_cmd_to_str(data->cmd),
- data->timeout);
+ data->timeout, ctrl->tethered);
ctrl->wakeup_cmd = data->cmd;
@@ -152,6 +158,9 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data)
if (hdmi_hdcp2p2_copy_buf(ctrl, data))
goto exit;
+ if (ctrl->tethered)
+ goto exit;
+
switch (ctrl->wakeup_cmd) {
case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE:
queue_kthread_work(&ctrl->worker, &ctrl->send_msg);
@@ -179,6 +188,9 @@ static inline int hdmi_hdcp2p2_wakeup_lib(struct hdmi_hdcp2p2_ctrl *ctrl,
{
int rc = 0;
+ if (ctrl)
+ ctrl->wakeup_cmd = HDMI_HDCP_WKUP_CMD_INVALID;
+
if (ctrl && ctrl->lib && ctrl->lib->wakeup &&
data && (data->cmd != HDCP_LIB_WKUP_CMD_INVALID)) {
rc = ctrl->lib->wakeup(data);
@@ -190,6 +202,55 @@ static inline int hdmi_hdcp2p2_wakeup_lib(struct hdmi_hdcp2p2_ctrl *ctrl,
return rc;
}
+static void hdmi_hdcp2p2_run(struct hdmi_hdcp2p2_ctrl *ctrl)
+{
+ if (!ctrl) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ while (1) {
+ switch (ctrl->wakeup_cmd) {
+ case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE:
+ hdmi_hdcp2p2_send_msg(ctrl);
+ break;
+
+ case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE:
+ hdmi_hdcp2p2_recv_msg(ctrl);
+ break;
+
+ case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS:
+ case HDMI_HDCP_WKUP_CMD_STATUS_FAILED:
+ hdmi_hdcp2p2_auth_status(ctrl);
+ default:
+ goto exit;
+ }
+ }
+exit:
+ ctrl->wakeup_cmd = HDMI_HDCP_WKUP_CMD_INVALID;
+}
+
+int hdmi_hdcp2p2_authenticate_tethered(struct hdmi_hdcp2p2_ctrl *ctrl)
+{
+ int rc = 0;
+
+ if (!ctrl) {
+ pr_err("invalid input\n");
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ rc = hdmi_hdcp2p2_auth(ctrl);
+ if (rc) {
+ pr_err("auth failed %d\n", rc);
+ goto exit;
+ }
+
+ hdmi_hdcp2p2_run(ctrl);
+exit:
+ return rc;
+}
+
static void hdmi_hdcp2p2_reset(struct hdmi_hdcp2p2_ctrl *ctrl)
{
if (!ctrl) {
@@ -217,17 +278,27 @@ static void hdmi_hdcp2p2_off(void *input)
hdmi_hdcp2p2_ddc_disable(ctrl->init_data.ddc_ctrl);
- cdata.context = input;
-
- hdmi_hdcp2p2_wakeup(&cdata);
+ if (ctrl->tethered) {
+ hdmi_hdcp2p2_auth(ctrl);
+ } else {
+ 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};
+ u32 regval;
int rc = 0;
+ /* Enable authentication success interrupt */
+ regval = DSS_REG_R(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2);
+ regval |= BIT(1) | BIT(2);
+
+ DSS_REG_W(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2, regval);
+
flush_kthread_worker(&ctrl->worker);
ctrl->sink_status = SINK_CONNECTED;
@@ -237,15 +308,18 @@ static int hdmi_hdcp2p2_authenticate(void *input)
hdmi_scrambler_ddc_disable(ctrl->init_data.ddc_ctrl);
hdmi_hdcp2p2_ddc_disable(ctrl->init_data.ddc_ctrl);
- cdata.context = input;
- hdmi_hdcp2p2_wakeup(&cdata);
+ if (ctrl->tethered) {
+ hdmi_hdcp2p2_authenticate_tethered(ctrl);
+ } else {
+ cdata.context = input;
+ hdmi_hdcp2p2_wakeup(&cdata);
+ }
return rc;
}
static int hdmi_hdcp2p2_reauthenticate(void *input)
{
- int rc = 0;
struct hdmi_hdcp2p2_ctrl *ctrl = (struct hdmi_hdcp2p2_ctrl *)input;
if (!ctrl) {
@@ -255,11 +329,8 @@ static int hdmi_hdcp2p2_reauthenticate(void *input)
hdmi_hdcp2p2_reset((struct hdmi_hdcp2p2_ctrl *)input);
- rc = hdmi_hdcp2p2_authenticate(input);
-
- return rc;
+ return hdmi_hdcp2p2_authenticate(input);
}
-
static ssize_t hdmi_hdcp2p2_sysfs_rda_sink_status(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -281,6 +352,54 @@ static ssize_t hdmi_hdcp2p2_sysfs_rda_sink_status(struct device *dev,
return ret;
}
+static ssize_t hdmi_hdcp2p2_sysfs_rda_tethered(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct hdmi_hdcp2p2_ctrl *ctrl =
+ hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP2P2);
+
+ if (!ctrl) {
+ pr_err("invalid input\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctrl->mutex);
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", ctrl->tethered);
+ mutex_unlock(&ctrl->mutex);
+
+ return ret;
+}
+
+static ssize_t hdmi_hdcp2p2_sysfs_wta_tethered(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_hdcp2p2_ctrl *ctrl =
+ hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP2P2);
+ int rc, tethered;
+
+ if (!ctrl) {
+ pr_err("invalid input\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctrl->mutex);
+ rc = kstrtoint(buf, 10, &tethered);
+ if (rc) {
+ pr_err("kstrtoint failed. rc=%d\n", rc);
+ goto exit;
+ }
+
+ ctrl->tethered = !!tethered;
+
+ if (ctrl->lib && ctrl->lib->update_exec_type && ctrl->lib_ctx)
+ ctrl->lib->update_exec_type(ctrl->lib_ctx, ctrl->tethered);
+exit:
+ mutex_unlock(&ctrl->mutex);
+
+ return count;
+}
+
static ssize_t hdmi_hdcp2p2_sysfs_rda_trigger(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -366,6 +485,9 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev,
cdata.context = ctrl->lib_ctx;
hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
+ if (ctrl->tethered)
+ hdmi_hdcp2p2_run(ctrl);
+
if (enc_notify && ctrl->init_data.notify_status)
ctrl->init_data.notify_status(ctrl->init_data.cb_data, enc_lvl);
@@ -424,7 +546,7 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl,
return rc;
}
-static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl,
+int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl,
u8 *buf, size_t size)
{
struct hdmi_tx_ddc_data ddc_data;
@@ -503,12 +625,15 @@ static DEVICE_ATTR(sink_status, S_IRUGO, hdmi_hdcp2p2_sysfs_rda_sink_status,
NULL);
static DEVICE_ATTR(hdcp2_version, S_IRUGO, hdmi_hdcp2p2_sysfs_rda_hdcp2_version,
NULL);
+static DEVICE_ATTR(tethered, S_IRUGO | S_IWUSR, hdmi_hdcp2p2_sysfs_rda_tethered,
+ hdmi_hdcp2p2_sysfs_wta_tethered);
static struct attribute *hdmi_hdcp2p2_fs_attrs[] = {
&dev_attr_trigger.attr,
&dev_attr_min_level_change.attr,
&dev_attr_sink_status.attr,
&dev_attr_hdcp2_version.attr,
+ &dev_attr_tethered.attr,
NULL,
};
@@ -541,22 +666,19 @@ end:
return supported;
}
-static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work)
+static void hdmi_hdcp2p2_send_msg(struct hdmi_hdcp2p2_ctrl *ctrl)
{
int rc = 0;
- struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
- struct hdmi_hdcp2p2_ctrl, send_msg);
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
- char *msg;
uint32_t msglen;
+ char *msg = NULL;
if (!ctrl) {
pr_err("invalid input\n");
- return;
+ rc = -EINVAL;
+ goto exit;
}
- mutex_lock(&ctrl->mutex);
-
cdata.context = ctrl->lib_ctx;
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
@@ -569,12 +691,14 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work)
if (!msglen) {
mutex_unlock(&ctrl->msg_lock);
+ rc = -EINVAL;
goto exit;
}
msg = kzalloc(msglen, GFP_KERNEL);
if (!msg) {
mutex_unlock(&ctrl->msg_lock);
+ rc = -ENOMEM;
goto exit;
}
@@ -591,41 +715,46 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work)
cdata.timeout = ctrl->timeout_left;
}
exit:
- kzfree(msg);
- mutex_unlock(&ctrl->mutex);
+ kfree(msg);
hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
}
-static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
+static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work)
{
- int rc = 0;
- int timeout_hsync;
- char *recvd_msg_buf = NULL;
struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
- struct hdmi_hdcp2p2_ctrl, recv_msg);
+ struct hdmi_hdcp2p2_ctrl, send_msg);
+
+ hdmi_hdcp2p2_send_msg(ctrl);
+}
+
+static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl)
+{
+ int rc, timeout_hsync;
+ char *recvd_msg_buf = NULL;
struct hdmi_tx_hdcp2p2_ddc_data *ddc_data;
struct hdmi_tx_ddc_ctrl *ddc_ctrl;
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
if (!ctrl) {
pr_err("invalid input\n");
- return;
+ rc = -EINVAL;
+ goto exit;
}
- mutex_lock(&ctrl->mutex);
-
cdata.context = ctrl->lib_ctx;
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
- pr_err("hdcp is off\n");
+ ddc_ctrl = ctrl->init_data.ddc_ctrl;
+ if (!ddc_ctrl) {
+ pr_err("invalid ddc ctrl\n");
+ rc = -EINVAL;
goto exit;
}
- ddc_ctrl = ctrl->init_data.ddc_ctrl;
- if (!ddc_ctrl)
+ if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+ pr_err("hdcp is off\n");
goto exit;
-
+ }
hdmi_ddc_config(ddc_ctrl);
ddc_data = &ddc_ctrl->hdcp2p2_ddc_data;
@@ -667,13 +796,17 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
}
recvd_msg_buf = kzalloc(ddc_data->message_size, GFP_KERNEL);
- if (!recvd_msg_buf)
+ if (!recvd_msg_buf) {
+ rc = -ENOMEM;
goto exit;
+ }
rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf,
ddc_data->message_size, ctrl->timeout_left);
- if (rc)
+ if (rc) {
pr_err("error reading message %d\n", rc);
+ goto exit;
+ }
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS;
cdata.recvd_msg_buf = recvd_msg_buf;
@@ -685,12 +818,19 @@ exit:
else if (rc)
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED;
- mutex_unlock(&ctrl->mutex);
hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
kfree(recvd_msg_buf);
}
+static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
+{
+ struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
+ struct hdmi_hdcp2p2_ctrl, recv_msg);
+
+ hdmi_hdcp2p2_recv_msg(ctrl);
+}
+
static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl)
{
struct hdmi_tx_ddc_ctrl *ddc_ctrl;
@@ -726,48 +866,38 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl)
return hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, false);
}
-static void hdmi_hdcp2p2_auth_status_work(struct kthread_work *work)
+static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl)
{
- struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
- struct hdmi_hdcp2p2_ctrl, status);
-
if (!ctrl) {
pr_err("invalid input\n");
return;
}
- mutex_lock(&ctrl->mutex);
-
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
pr_err("hdcp is off\n");
- goto exit;
+ return;
}
if (ctrl->wakeup_cmd == HDMI_HDCP_WKUP_CMD_STATUS_FAILED) {
hdmi_hdcp2p2_auth_failed(ctrl);
} 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);
- pr_debug("Now authenticated. Enabling interrupts\n");
- regval |= BIT(1);
- regval |= BIT(2);
- regval |= BIT(5);
-
- DSS_REG_W(ctrl->init_data.core_io,
- HDMI_HDCP_INT_CTRL2, regval);
-
ctrl->init_data.notify_status(ctrl->init_data.cb_data,
HDCP_STATE_AUTHENTICATED);
if (!hdmi_hdcp2p2_link_check(ctrl))
- schedule_delayed_work(&ctrl->link_check_work,
- msecs_to_jiffies(HDCP2P2_LINK_CHECK_TIME_MS));
+ queue_kthread_work(&ctrl->worker, &ctrl->link);
}
-exit:
- mutex_unlock(&ctrl->mutex);
}
+static void hdmi_hdcp2p2_auth_status_work(struct kthread_work *work)
+{
+ struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
+ struct hdmi_hdcp2p2_ctrl, status);
+
+ hdmi_hdcp2p2_auth_status(ctrl);
+}
+
+
static void hdmi_hdcp2p2_link_schedule_work(struct work_struct *work)
{
struct hdmi_hdcp2p2_ctrl *ctrl = container_of(to_delayed_work(work),
@@ -792,8 +922,6 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work)
return;
}
- mutex_lock(&ctrl->mutex);
-
cdata.context = ctrl->lib_ctx;
ddc_ctrl = ctrl->init_data.ddc_ctrl;
@@ -842,15 +970,14 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work)
}
}
exit:
- mutex_unlock(&ctrl->mutex);
-
hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
kfree(recvd_msg_buf);
+ if (ctrl->tethered)
+ hdmi_hdcp2p2_run(ctrl);
+
if (rc) {
- /* notify hdmi tx about auth failure */
hdmi_hdcp2p2_auth_failed(ctrl);
-
return;
}
@@ -859,19 +986,16 @@ exit:
msecs_to_jiffies(HDCP2P2_LINK_CHECK_TIME_MS));
}
-static void hdmi_hdcp2p2_auth_work(struct kthread_work *work)
+static int hdmi_hdcp2p2_auth(struct hdmi_hdcp2p2_ctrl *ctrl)
{
- struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
- struct hdmi_hdcp2p2_ctrl, auth);
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
+ int rc = 0;
if (!ctrl) {
pr_err("invalid input\n");
- return;
+ return -EINVAL;
}
- mutex_lock(&ctrl->mutex);
-
cdata.context = ctrl->lib_ctx;
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTHENTICATING)
@@ -879,10 +1003,19 @@ static void hdmi_hdcp2p2_auth_work(struct kthread_work *work)
else
cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
- mutex_unlock(&ctrl->mutex);
-
- if (hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata))
+ rc = hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
+ if (rc)
hdmi_hdcp2p2_auth_failed(ctrl);
+
+ return rc;
+}
+
+static void hdmi_hdcp2p2_auth_work(struct kthread_work *work)
+{
+ struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
+ struct hdmi_hdcp2p2_ctrl, auth);
+
+ hdmi_hdcp2p2_auth(ctrl);
}
void hdmi_hdcp2p2_deinit(void *input)
@@ -912,8 +1045,8 @@ void hdmi_hdcp2p2_deinit(void *input)
void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
{
- struct hdmi_hdcp2p2_ctrl *ctrl;
int rc;
+ struct hdmi_hdcp2p2_ctrl *ctrl;
static struct hdmi_hdcp_ops ops = {
.hdmi_hdcp_reauthenticate = hdmi_hdcp2p2_reauthenticate,
.hdmi_hdcp_authenticate = hdmi_hdcp2p2_authenticate,
@@ -926,6 +1059,7 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
};
static struct hdcp_txmtr_ops txmtr_ops;
+ struct hdcp_register_data register_data;
pr_debug("HDCP2P2 feature initialization\n");
@@ -947,6 +1081,7 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
ctrl->init_data = *init_data;
ctrl->lib = &txmtr_ops;
+ ctrl->tethered = init_data->tethered;
rc = sysfs_create_group(init_data->sysfs_kobj,
&hdmi_hdcp2p2_fs_attr_group);
@@ -964,8 +1099,13 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
mutex_init(&ctrl->msg_lock);
mutex_init(&ctrl->wakeup_mutex);
- rc = hdcp_library_register(&ctrl->lib_ctx,
- &client_ops, ctrl->lib, ctrl);
+ register_data.hdcp_ctx = &ctrl->lib_ctx;
+ register_data.client_ops = &client_ops;
+ register_data.txmtr_ops = &txmtr_ops;
+ register_data.client_ctx = ctrl;
+ register_data.tethered = ctrl->tethered;
+
+ rc = hdcp_library_register(&register_data);
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 a88648bad161..ed66718c5e5c 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -1563,9 +1563,9 @@ end:
static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
struct fb_info *fbi)
{
- struct hdmi_edid_init_data edid_init_data;
- struct hdmi_hdcp_init_data hdcp_init_data;
- struct hdmi_cec_init_data cec_init_data;
+ struct hdmi_edid_init_data edid_init_data = {0};
+ struct hdmi_hdcp_init_data hdcp_init_data = {0};
+ struct hdmi_cec_init_data cec_init_data = {0};
struct resource *res = NULL;
void *fd = NULL;
@@ -4332,6 +4332,8 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
case MDSS_EVENT_BLANK:
if (hdmi_tx_is_hdcp_enabled(hdmi_ctrl)) {
+ flush_delayed_work(&hdmi_ctrl->hdcp_cb_work);
+
DEV_DBG("%s: Turning off HDCP\n", __func__);
hdmi_ctrl->hdcp_ops->hdmi_hdcp_off(
hdmi_ctrl->hdcp_data);
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index 94caf29cba9f..ab39126b41ef 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -96,7 +96,7 @@ static inline char *hdcp_lib_cmd_to_str(uint32_t cmd)
struct hdcp_txmtr_ops {
int (*wakeup)(struct hdcp_lib_wakeup_data *data);
bool (*feature_supported)(void *phdcpcontext);
-
+ void (*update_exec_type)(void *ctx, bool tethered);
int (*hdcp_txmtr_get_state)(void *phdcpcontext,
uint32_t *state);
};
@@ -105,9 +105,15 @@ struct hdcp_client_ops {
int (*wakeup)(struct hdmi_hdcp_wakeup_data *data);
};
-int hdcp_library_register(void **pphdcpcontext,
- struct hdcp_client_ops *client_ops,
- struct hdcp_txmtr_ops *txmtr_ops, void *client_ctx);
+struct hdcp_register_data {
+ struct hdcp_client_ops *client_ops;
+ struct hdcp_txmtr_ops *txmtr_ops;
+ void *client_ctx;
+ void **hdcp_ctx;
+ bool tethered;
+};
+
+int hdcp_library_register(struct hdcp_register_data *data);
void hdcp_library_deregister(void *phdcpcontext);
bool hdcp1_check_if_supported_load_app(void);
int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb);