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 <steve_longerb...@mentor.com>
---
Changes since v5:
- add call to v4l2_async_notifier_init().
Changes since v4:
- none
Changes since v3:
- v4l2_async_register_fwnode_subdev() no longer supports parsing
  port sub-devices, so call
  v4l2_async_notifier_parse_fwnode_endpoints_by_port() directly.
---
 drivers/staging/media/imx/imx-media-csi.c | 57 ++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 4647206..19ef377 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1780,6 +1780,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;
@@ -1849,7 +1904,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;
 
-- 
2.7.4

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to