@@ -31,6 +31,83 @@
#include <linux/slab.h>
#include <linux/uuid.h>
#include <linux/mei_cl_bus.h>
+#include <linux/component.h>
+#include <drm/i915_component.h>
+
+bool mei_hdcp_component_registered;
+static struct mei_cl_device *mei_cldev;
+
+struct i915_hdcp_component_ops mei_hdcp_component_ops = {
+ .owner = THIS_MODULE,
+ .initiate_hdcp2_session = NULL,
+ .verify_receiver_cert_prepare_km = NULL,
+ .verify_hprime = NULL,
+ .store_pairing_info = NULL,
+ .initiate_locality_check = NULL,
+ .verify_lprime = NULL,
+ .get_session_key = NULL,
+ .repeater_check_flow_prepare_ack = NULL,
+ .verify_mprime = NULL,
+ .enable_hdcp_authentication = NULL,
+ .close_hdcp_session = NULL,
+};
+
+static int mei_hdcp_component_bind(struct device *mei_kdev,
+ struct device *i915_kdev, void *data)
+{
+ struct i915_hdcp_component *comp = data;
+
+ WARN_ON(!mutex_is_locked(&comp->mutex));
+ if (WARN_ON(comp->ops || comp->dev))
+ return -EEXIST;
+
+ dev_info(mei_kdev, "MEI HDCP comp bind\n");
+ comp->ops = &mei_hdcp_component_ops;
+ comp->i915_kdev = i915_kdev;
+ comp->mei_cldev = mei_cldev;
+ mei_cldev_set_drvdata(mei_cldev, (void *)comp);
+
+ return 0;
+}
+
+static void mei_hdcp_component_unbind(struct device *mei_kdev,
+ struct device *i915_kdev, void *data)
+{
+ struct i915_hdcp_component *comp = data;
+
+ WARN_ON(!mutex_is_locked(&comp->mutex));
+ dev_info(mei_kdev, "MEI HDCP comp unbind\n");
+ comp->ops = NULL;
+ comp->dev = NULL;
+ comp->mei_cldev = NULL;
+}
+
+static const struct component_ops mei_hdcp_component_bind_ops = {
+ .bind = mei_hdcp_component_bind,
+ .unbind = mei_hdcp_component_unbind,
+};
+
+void mei_hdcp_component_init(struct device *dev)
+{
+ int ret;
+
+ ret = component_add(dev, &mei_hdcp_component_bind_ops);
+ if (ret < 0) {
+ dev_err(dev, "Failed to add MEI HDCP comp (%d)\n", ret);
+ return;
+ }
+
+ mei_hdcp_component_registered = true;
+}
+
+void mei_hdcp_component_cleanup(struct device *dev)
+{
+ if (!mei_hdcp_component_registered)
+ return;
+
+ component_del(dev, &mei_hdcp_component_bind_ops);
+ mei_hdcp_component_registered = false;
+}
static int mei_hdcp_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
@@ -38,15 +115,28 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
int ret;
ret = mei_cldev_enable(cldev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ return ret;
+ }
- return ret;
+ mei_cldev = cldev;
+ mei_hdcp_component_init(&cldev->dev);
+ return 0;
}
static int mei_hdcp_remove(struct mei_cl_device *cldev)
{
+ struct i915_hdcp_component *comp;
+
+ comp = mei_cldev_get_drvdata(cldev);
+ if (comp && comp->master_ops && comp->master_ops->pull_down_interface)
+ comp->master_ops->pull_down_interface(comp->i915_kdev);
+
+ mei_cldev = NULL;
mei_cldev_set_drvdata(cldev, NULL);
+ mei_hdcp_component_cleanup(&cldev->dev);
+
return mei_cldev_disable(cldev);
}
Mei hdcp driver is designed as component slave for the I915 component master. v2: Rebased. v3: Notifier chain is adopted for cldev state update [Tomas] v4: Made static dummy functions as inline in mei_hdcp.h API for polling client device status IS_ENABLED used in header, for config status for mei_hdcp. v5: Replacing the notifier with component framework. [Daniel] Signed-off-by: Ramalingam C <ramalingam.c@intel.com> --- drivers/misc/mei/hdcp/mei_hdcp.c | 94 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-)