Commit c893500a authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Mauro Carvalho Chehab
Browse files

media: imx: csi: Register a subdev notifier



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: default avatarSteve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent c5afc789
Loading
Loading
Loading
Loading
+56 −1
Original line number Diff line number Diff line
@@ -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;