Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8428539 authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab
Browse files

media: v4l: fwnode: Add a helper function for parsing generic references



Add function v4l2_fwnode_reference_parse() for parsing them as async
sub-devices. This can be done on e.g. flash or lens async sub-devices that
are not part of but are associated with a sensor.

Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Acked-by: default avatarNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: default avatarSebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent baf249e4
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -509,6 +509,75 @@ int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
}
EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port);

/*
 * v4l2_fwnode_reference_parse - parse references for async sub-devices
 * @dev: the device node the properties of which are parsed for references
 * @notifier: the async notifier where the async subdevs will be added
 * @prop: the name of the property
 *
 * Return: 0 on success
 *	   -ENOENT if no entries were found
 *	   -ENOMEM if memory allocation failed
 *	   -EINVAL if property parsing failed
 */
static int v4l2_fwnode_reference_parse(
	struct device *dev, struct v4l2_async_notifier *notifier,
	const char *prop)
{
	struct fwnode_reference_args args;
	unsigned int index;
	int ret;

	for (index = 0;
	     !(ret = fwnode_property_get_reference_args(
		       dev_fwnode(dev), prop, NULL, 0, index, &args));
	     index++)
		fwnode_handle_put(args.fwnode);

	if (!index)
		return -ENOENT;

	/*
	 * Note that right now both -ENODATA and -ENOENT may signal
	 * out-of-bounds access. Return the error in cases other than that.
	 */
	if (ret != -ENOENT && ret != -ENODATA)
		return ret;

	ret = v4l2_async_notifier_realloc(notifier,
					  notifier->num_subdevs + index);
	if (ret)
		return ret;

	for (index = 0; !fwnode_property_get_reference_args(
		     dev_fwnode(dev), prop, NULL, 0, index, &args);
	     index++) {
		struct v4l2_async_subdev *asd;

		if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
			ret = -EINVAL;
			goto error;
		}

		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
		if (!asd) {
			ret = -ENOMEM;
			goto error;
		}

		notifier->subdevs[notifier->num_subdevs] = asd;
		asd->match.fwnode.fwnode = args.fwnode;
		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
		notifier->num_subdevs++;
	}

	return 0;

error:
	fwnode_handle_put(args.fwnode);
	return ret;
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");