summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjay Singh Parmar <aparmar@codeaurora.org>2016-12-21 17:01:28 -0800
committerAjay Singh Parmar <aparmar@codeaurora.org>2016-12-21 19:46:55 -0800
commitc1f984bb5779b9ef2bc1780f47bb2cc67d362626 (patch)
treefd9faa034071e33c67e76c86df9c0e6f40edfdbf
parentbd5d2212f7c92e9e00d2a4ab85080e0f95ef7d86 (diff)
msm: mdss: hdcp_1x: fix cp_irq and bstatus read
Check if cp_irq has been raised by sink, if so, read bstatus register to check the status of hdcp at sink side. Clear the cp_irq after reading bstatus. Also, fix the bstatus read size which is one byte. Change-Id: I46231f82878f8d2557aa06ccfa5c74f67252c6f8 Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_hdcp_1x.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.c b/drivers/video/fbdev/msm/mdss_hdcp_1x.c
index 212f3be96bf2..08307fe8eb16 100644
--- a/drivers/video/fbdev/msm/mdss_hdcp_1x.c
+++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.c
@@ -195,7 +195,7 @@ struct hdcp_reg_set {
#define HDCP_DP_SINK_ADDR_MAP \
{{"bcaps", 0x68028, 1}, {"bksv", 0x68000, 5}, {"r0'", 0x68005, 2}, \
- {"binfo", 0x6802A, 2}, {"cp_irq_status", 0x68029, 2}, \
+ {"binfo", 0x6802A, 2}, {"cp_irq_status", 0x68029, 1}, \
{"ksv-fifo", 0x6802C, 0}, {"v_h0", 0x68014, 4}, {"v_h1", 0x68018, 4}, \
{"v_h2", 0x6801C, 4}, {"v_h3", 0x68020, 4}, {"v_h4", 0x68024, 4}, \
{"an", 0x6800C, 8}, {"aksv", 0x68007, 5}, {"ainfo", 0x6803B, 1} }
@@ -1763,6 +1763,30 @@ static void hdcp_1x_update_client_reg_set(struct hdcp_1x *hdcp)
}
}
+static bool hdcp_1x_is_cp_irq_raised(struct hdcp_1x *hdcp)
+{
+ int ret;
+ u8 buf = 0;
+ struct hdcp_sink_addr sink = {"irq", 0x201, 1};
+
+ ret = hdcp_1x_read(hdcp, &sink, &buf, false);
+ if (IS_ERR_VALUE(ret))
+ pr_err("error reading irq_vector\n");
+
+ return buf & BIT(2) ? true : false;
+}
+
+static void hdcp_1x_clear_cp_irq(struct hdcp_1x *hdcp)
+{
+ int ret;
+ u8 buf = BIT(2);
+ struct hdcp_sink_addr sink = {"irq", 0x201, 1};
+
+ ret = hdcp_1x_write(hdcp, &sink, &buf);
+ if (IS_ERR_VALUE(ret))
+ pr_err("error clearing irq_vector\n");
+}
+
static int hdcp_1x_cp_irq(void *input)
{
struct hdcp_1x *hdcp = (struct hdcp_1x *)input;
@@ -1771,14 +1795,19 @@ static int hdcp_1x_cp_irq(void *input)
if (!hdcp) {
pr_err("invalid input\n");
- goto end;
+ goto irq_not_handled;
+ }
+
+ if (!hdcp_1x_is_cp_irq_raised(hdcp)) {
+ pr_debug("cp_irq not raised\n");
+ goto irq_not_handled;
}
ret = hdcp_1x_read(hdcp, &hdcp->sink_addr.cp_irq_status,
&buf, false);
if (IS_ERR_VALUE(ret)) {
pr_err("error reading cp_irq_status\n");
- return ret;
+ goto irq_not_handled;
}
if ((buf & BIT(2)) || (buf & BIT(3))) {
@@ -1793,27 +1822,23 @@ static int hdcp_1x_cp_irq(void *input)
complete_all(&hdcp->sink_r0_available);
hdcp_1x_update_auth_status(hdcp);
-
- goto end;
- }
-
- if (buf & BIT(1)) {
+ } else if (buf & BIT(1)) {
pr_debug("R0' AVAILABLE\n");
hdcp->sink_r0_ready = true;
complete_all(&hdcp->sink_r0_available);
- goto end;
- }
-
- if ((buf & BIT(0))) {
+ } else if ((buf & BIT(0))) {
pr_debug("KSVs READY\n");
hdcp->ksv_ready = true;
- goto end;
+ } else {
+ pr_debug("spurious interrupt\n");
}
- return -EINVAL;
-end:
+ hdcp_1x_clear_cp_irq(hdcp);
return 0;
+
+irq_not_handled:
+ return -EINVAL;
}
void *hdcp_1x_init(struct hdcp_init_data *init_data)