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@xxxxxxxxx> --- drivers/misc/mei/hdcp/mei_hdcp.c | 94 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c index 4cd6fdd01181..ba7550215b7f 100644 --- a/drivers/misc/mei/hdcp/mei_hdcp.c +++ b/drivers/misc/mei/hdcp/mei_hdcp.c @@ -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); } -- 2.7.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel