summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);