summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatenda Chipeperekwa <tatendac@codeaurora.org>2015-09-25 17:00:00 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:46:07 -0700
commitc76b5e3acf68a4e0711a2ad0f5c826ae46530cbf (patch)
treec424d65c86bf8b63d3cc06c40442c707b05f5527
parentcc97a775f4f367e920ebcb6398389ff44279c67a (diff)
msm: mdss: hdmi: check if hdcp2p2 app is present during hpd
Check if the hdcp2p2 app is present every time the hdmi cable is connected. If the app is not present, then we consider hdcp-2.2 as not supported on the target. This scenario occurs on devices that are not hdcp-2.2 provisioned, and with this change hdmi core continues in non-encrypted mode. Change-Id: I72ebcc1e6844f46dbbc974efb6ba926948e1bbde Signed-off-by: Tatenda Chipeperekwa <tatendac@codeaurora.org>
-rw-r--r--drivers/misc/hdcp.c27
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_hdcp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c24
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c51
-rw-r--r--include/linux/hdcp_qseecom.h1
5 files changed, 83 insertions, 21 deletions
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index 7054e74654fe..e42d4fb5587e 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -863,6 +863,27 @@ exit:
return rc;
}
+static bool hdcp2p2_client_feature_supported(void *phdcpcontext)
+{
+ int rc = 0;
+ bool supported = false;
+ struct hdcp2p2_handle *handle = phdcpcontext;
+
+ if (!handle) {
+ pr_err("invalid input\n");
+ goto end;
+ }
+
+ rc = hdcp2p2_library_load(handle);
+ if (!rc) {
+ pr_debug("HDCP2p2 supported\n");
+ hdcp2p2_library_unload(handle);
+ supported = true;
+ }
+end:
+ return supported;
+}
+
static int hdcp2p2_client_start(void *phdcpcontext)
{
int rc = 0;
@@ -1135,6 +1156,7 @@ int hdcp_library_register(void **pphdcpcontext,
/* populate ops to be called by client */
txmtr_ops->start = hdcp2p2_client_start;
txmtr_ops->stop = hdcp2p2_client_stop;
+ txmtr_ops->feature_supported = hdcp2p2_client_feature_supported;
txmtr_ops->process_message = hdcp2p2_txmtr_process_message;
txmtr_ops->hdcp_txmtr_query_stream_type =
hdcp2p2_txmtr_query_stream_type;
@@ -1166,7 +1188,8 @@ int hdcp_library_register(void **pphdcpcontext,
}
*((struct hdcp2p2_handle **)pphdcpcontext) = handle;
- pr_debug("hdcp lib successfully initialized\n");
+
+ pr_debug("hdcp lib successfully registered\n");
return 0;
error:
@@ -1196,6 +1219,8 @@ void hdcp_library_deregister(void *phdcpcontext)
if (handle->hdcp_workqueue)
destroy_workqueue(handle->hdcp_workqueue);
+ mutex_destroy(&handle->hdcp_lock);
+
kzfree(handle->listener_buf);
kzfree(handle);
}
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
index 901aaefac387..c6e151812a4c 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
@@ -43,6 +43,7 @@ struct hdmi_hdcp_ops {
int (*hdmi_hdcp_isr)(void *ptr);
int (*hdmi_hdcp_reauthenticate)(void *input);
int (*hdmi_hdcp_authenticate)(void *hdcp_ctrl);
+ bool (*feature_supported)(void *input);
void (*hdmi_hdcp_off)(void *hdcp_ctrl);
};
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
index ca7f7c082da9..060adcf5d319 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
@@ -554,6 +554,29 @@ static int hdcp2p2_isr(void *input)
return 0;
}
+static bool hdcp2p2_feature_supported(void *input)
+{
+ struct hdcp2p2_ctrl *hdcp2p2_ctrl = input;
+ struct hdcp_txmtr_ops *lib = NULL;
+ bool supported = false;
+
+ if (!hdcp2p2_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ goto end;
+ }
+
+ lib = hdcp2p2_ctrl->txmtr_ops;
+ if (!lib) {
+ DEV_ERR("%s: invalid lib ops data\n", __func__);
+ goto end;
+ }
+
+ if (lib->feature_supported)
+ supported = lib->feature_supported(
+ hdcp2p2_ctrl->hdcp_lib_handle);
+end:
+ return supported;
+}
static void hdcp2p2_reset(struct hdcp2p2_ctrl *hdcp2p2_ctrl)
{
@@ -781,6 +804,7 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
.hdmi_hdcp_isr = hdcp2p2_isr,
.hdmi_hdcp_reauthenticate = hdcp2p2_reauthenticate,
.hdmi_hdcp_authenticate = hdcp2p2_authenticate,
+ .feature_supported = hdcp2p2_feature_supported,
.hdmi_hdcp_off = hdcp2p2_off
};
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index ae004c5042bb..c6dced49ef04 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -1600,6 +1600,36 @@ error:
return status;
} /* hdmi_tx_read_sink_info */
+static void hdmi_tx_update_hdcp_info(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ void *fd = NULL;
+ struct hdmi_hdcp_ops *ops = NULL;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ /* check first if hdcp2p2 is supported */
+ fd = hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2];
+ if (fd)
+ ops = hdmi_hdcp2p2_start(fd);
+
+ if (ops && ops->feature_supported)
+ hdmi_ctrl->hdcp22_present = ops->feature_supported(fd);
+ else
+ hdmi_ctrl->hdcp22_present = false;
+
+ if (!hdmi_ctrl->hdcp22_present && hdmi_ctrl->hdcp14_present) {
+ fd = hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP];
+ ops = hdmi_hdcp_start(fd);
+ }
+
+ /* update internal data about hdcp */
+ hdmi_ctrl->hdcp_feature_data = fd;
+ hdmi_ctrl->hdcp_ops = ops;
+}
+
static void hdmi_tx_hpd_int_work(struct work_struct *work)
{
struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
@@ -1629,26 +1659,7 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work)
if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
DEV_ERR("%s: Failed to disable ddc power\n", __func__);
- /* Figure out HDCP capabilities of sink */
- hdmi_ctrl->hdcp_ops = NULL;
- hdmi_ctrl->hdcp_feature_data =
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2];
- if (hdmi_ctrl->hdcp_feature_data)
- hdmi_ctrl->hdcp_ops =
- hdmi_hdcp2p2_start(
- hdmi_ctrl->hdcp_feature_data);
-
- if (hdmi_ctrl->hdcp_ops)
- hdmi_ctrl->hdcp22_present = true;
- else
- hdmi_ctrl->hdcp22_present = false;
-
- if (!hdmi_ctrl->hdcp22_present && hdmi_ctrl->hdcp14_present) {
- hdmi_ctrl->hdcp_feature_data =
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP];
- hdmi_ctrl->hdcp_ops =
- hdmi_hdcp_start(hdmi_ctrl->hdcp_feature_data);
- }
+ hdmi_tx_update_hdcp_info(hdmi_ctrl);
hdmi_tx_send_cable_notification(hdmi_ctrl, true);
} else {
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index a8f50dc1d90c..0a31b66e6a72 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -17,6 +17,7 @@
struct hdcp_txmtr_ops {
int (*start)(void *phdcpcontext);
int (*stop)(void *phdcpcontext);
+ bool (*feature_supported)(void *phdcpcontext);
int (*process_message)(void *phdcpcontext,
unsigned char *msg, uint32_t msg_size);