media: imx: csi: Register a subdev notifier
authorSteve Longerbeam <slongerbeam@gmail.com>
Sat, 29 Sep 2018 19:54:11 +0000 (15:54 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Thu, 4 Oct 2018 19:35:56 +0000 (15:35 -0400)
Parse neighbor remote devices on the CSI port, and add them to a subdev
notifier, by calling v4l2_async_notifier_parse_fwnode_endpoints_by_port()
using the CSI's port id. And register the subdev notifier for the CSI.

Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/staging/media/imx/imx-media-csi.c

index 4acdd7a..bca1384 100644 (file)
@@ -1783,6 +1783,61 @@ static const struct v4l2_subdev_internal_ops csi_internal_ops = {
        .unregistered = csi_unregistered,
 };
 
+static int imx_csi_parse_endpoint(struct device *dev,
+                                 struct v4l2_fwnode_endpoint *vep,
+                                 struct v4l2_async_subdev *asd)
+{
+       return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
+}
+
+static int imx_csi_async_register(struct csi_priv *priv)
+{
+       struct v4l2_async_notifier *notifier;
+       struct fwnode_handle *fwnode;
+       unsigned int port;
+       int ret;
+
+       notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
+       if (!notifier)
+               return -ENOMEM;
+
+       v4l2_async_notifier_init(notifier);
+
+       fwnode = dev_fwnode(priv->dev);
+
+       /* get this CSI's port id */
+       ret = fwnode_property_read_u32(fwnode, "reg", &port);
+       if (ret < 0)
+               goto out_free;
+
+       ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
+               priv->dev->parent, notifier, sizeof(struct v4l2_async_subdev),
+               port, imx_csi_parse_endpoint);
+       if (ret < 0)
+               goto out_cleanup;
+
+       ret = v4l2_async_subdev_notifier_register(&priv->sd, notifier);
+       if (ret < 0)
+               goto out_cleanup;
+
+       ret = v4l2_async_register_subdev(&priv->sd);
+       if (ret < 0)
+               goto out_unregister;
+
+       priv->sd.subdev_notifier = notifier;
+
+       return 0;
+
+out_unregister:
+       v4l2_async_notifier_unregister(notifier);
+out_cleanup:
+       v4l2_async_notifier_cleanup(notifier);
+out_free:
+       kfree(notifier);
+
+       return ret;
+}
+
 static int imx_csi_probe(struct platform_device *pdev)
 {
        struct ipu_client_platformdata *pdata;
@@ -1852,7 +1907,7 @@ static int imx_csi_probe(struct platform_device *pdev)
                        goto free;
        }
 
-       ret = v4l2_async_register_subdev(&priv->sd);
+       ret = imx_csi_async_register(priv);
        if (ret)
                goto free;