Signed-off-by: Ramalingam C <ramalingam.c@xxxxxxxxx>
---
drivers/misc/mei/hdcp/mei_hdcp.c | 55
+++++++++++++++++++++++++++++++++++++++-
drivers/misc/mei/hdcp/mei_hdcp.h | 9 +++++++
include/linux/mei_hdcp.h | 47 ++++++++++++++++++++++++++++++++++
3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644
include/linux/mei_hdcp.h
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c
b/drivers/misc/mei/hdcp/mei_hdcp.c
index 25df7034cfb4..63f77800a6f7 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -55,18 +55,71 @@ static int mei_hdcp_probe(struct mei_cl_device
*cldev,
mei_cldev_set_drvdata(cldev, &mei_hdcp);
ret = mei_cldev_enable(cldev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ goto err;
+ }
+
+ if (mei_hdcp.notify_on_cldev_change)
+ mei_hdcp.notify_on_cldev_change(mei_hdcp.client, cldev);
+
+ return 0;
+err:
+ if (mei_hdcp.notify_on_cldev_change)
+ mei_hdcp.notify_on_cldev_change(mei_hdcp.client, NULL);
return ret;
}
static int mei_hdcp_remove(struct mei_cl_device *cldev) {
+ struct mei_hdcp *mei_hdcp = mei_cldev_get_drvdata(cldev);
+
+ if (mei_hdcp->notify_on_cldev_change)
+ mei_hdcp->notify_on_cldev_change(mei_hdcp->client, NULL);
+
mei_cldev_disable(cldev);
+
return 0;
}
+int mei_hdcp_cldev_get_reference(void *client_data,
+ struct mei_cl_device **cldev,
+ void (*notify_change)(void *client,
+ struct mei_cl_device
+ *cldev))
+{
+ if (!notify_change || !client_data)
+ return -EINVAL;
+
+ if (mei_hdcp.ref_cnt)
+ return -EBUSY;
+
+ if (!mei_cldev_active_and_enabled(mei_hdcp.cldev)) {
+ if (!notify_change)
+ return -EAGAIN;
+ } else {
+ *cldev = mei_hdcp.cldev;
+ }
+
+ mei_hdcp.ref_cnt++;
+ mei_hdcp.client = client_data;
+ mei_hdcp.notify_on_cldev_change = notify_change;
+
+ return 0;
+}
+EXPORT_SYMBOL(mei_hdcp_cldev_get_reference);
+
+void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev) {
+ if (cldev == mei_hdcp.cldev) {
+ mei_hdcp.ref_cnt--;
+ mei_hdcp.client = NULL;
+ mei_hdcp.notify_on_cldev_change = NULL;
+ }
+}
+EXPORT_SYMBOL(mei_hdcp_cldev_put_reference);
+
#define WIDI_HECI_CLIENT_GUID UUID_LE(0xB638AB7E, 0x94E2,
0x4EA2, 0xA5, \
0x52, 0xD1, 0xC5, 0x4B, \
0x62, 0x7F, 0x04)
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h
b/drivers/misc/mei/hdcp/mei_hdcp.h
index c06c0d767c4f..7d792b5ad703 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.h
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -27,6 +27,15 @@
struct mei_hdcp {
struct mei_cl_device *cldev;
+
+ /* Reference to the HDCP2.2 service consumer */
+ void *client;
+
+ /* Callback function for the consumer on cl_device state change */
+ void (*notify_on_cldev_change)(void *client,
+ struct mei_cl_device *cldev);
+
+ int ref_cnt;
};
#endif /* __MEI_HDCP_H__ */
diff --git a/include/linux/mei_hdcp.h b/include/linux/mei_hdcp.h new file
mode 100644 index 000000000000..774b26da0c26
--- /dev/null
+++ b/include/linux/mei_hdcp.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+and its
+ * documentation for any purpose is hereby granted without fee,
+provided that
+ * the above copyright notice appear in all copies and that both that
+copyright
+ * notice and this permission notice appear in supporting
+documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without
+specific,
+ * written prior permission. The copyright holders make no
+representations
+ * about the suitability of this software for any purpose. It is
+provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
THIS
+SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN
+NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL,
+INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS
+OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR
+OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR
+PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _LINUX_MEI_HDCP_H
+#define _LINUX_MEI_HDCP_H
+
+#ifdef CONFIG_INTEL_MEI_HDCP
+int mei_hdcp_cldev_get_reference(void *client_data,
+ struct mei_cl_device **cldev,
+ void (*notify_change)(void *client,
+ struct mei_cl_device
+ *cldev));
+void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev); #else
+static inline int mei_hdcp_cldev_get_reference(void *client_data,
+ struct mei_cl_device **cldev,
+ void (*notify_change)(void *client,
+ struct mei_cl_device
+ *cldev))
+{
+ return -ENODEV;
+}
+static inline
+void mei_hdcp_cldev_put_reference(struct mei_cl_device *cldev) {}
+#endif /* defined (CONFIG_INTEL_MEI_HDCP) */ #endif /* defined
+(_LINUX_MEI_HDCP_H) */
--
2.7.4