Commit cfef0c83 authored by Niklas Söderlund's avatar Niklas Söderlund Committed by Mauro Carvalho Chehab
Browse files

media: rcar-vin: Create a callback to setup media links



New IP versions will have different media graphs and require a different
link setup. Breakout the specific link setup to a callback that are
associated with the group.

Signed-off-by: default avatarNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: default avatarJacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 9c833001
Loading
Loading
Loading
Loading
+56 −45
Original line number Diff line number Diff line
@@ -247,7 +247,8 @@ static void rvin_group_cleanup(struct rvin_group *group)
	mutex_destroy(&group->lock);
}

static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin,
			   int (*link_setup)(struct rvin_dev *))
{
	struct media_device *mdev = &group->mdev;
	const struct of_device_id *match;
@@ -263,6 +264,8 @@ static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)

	vin_dbg(vin, "found %u enabled VIN's in DT", group->count);

	group->link_setup = link_setup;

	mdev->dev = vin->dev;
	mdev->ops = &rvin_media_ops;

@@ -295,7 +298,8 @@ static void rvin_group_release(struct kref *kref)
	mutex_unlock(&rvin_group_lock);
}

static int rvin_group_get(struct rvin_dev *vin)
static int rvin_group_get(struct rvin_dev *vin,
			  int (*link_setup)(struct rvin_dev *))
{
	struct rvin_group *group;
	u32 id;
@@ -327,7 +331,7 @@ static int rvin_group_get(struct rvin_dev *vin)
			goto err_group;
		}

		ret = rvin_group_init(group, vin);
		ret = rvin_group_init(group, vin, link_setup);
		if (ret) {
			kfree(group);
			vin_err(vin, "Failed to initialize group\n");
@@ -386,7 +390,6 @@ static void rvin_group_put(struct rvin_dev *vin)
static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
{
	struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
	const struct rvin_group_route *route;
	unsigned int i;
	int ret;

@@ -410,46 +413,7 @@ static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
		}
	}

	/* Create all media device links between VINs and CSI-2's. */
	mutex_lock(&vin->group->lock);
	for (route = vin->info->routes; route->mask; route++) {
		struct media_pad *source_pad, *sink_pad;
		struct media_entity *source, *sink;
		unsigned int source_idx;

		/* Check that VIN is part of the group. */
		if (!vin->group->vin[route->vin])
			continue;

		/* Check that VIN' master is part of the group. */
		if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
			continue;

		/* Check that CSI-2 is part of the group. */
		if (!vin->group->remotes[route->csi].subdev)
			continue;

		source = &vin->group->remotes[route->csi].subdev->entity;
		source_idx = rvin_group_csi_channel_to_pad(route->channel);
		source_pad = &source->pads[source_idx];

		sink = &vin->group->vin[route->vin]->vdev.entity;
		sink_pad = &sink->pads[0];

		/* Skip if link already exists. */
		if (media_entity_find_link(source_pad, sink_pad))
			continue;

		ret = media_create_pad_link(source, source_idx, sink, 0, 0);
		if (ret) {
			vin_err(vin, "Error adding link from %s to %s\n",
				source->name, sink->name);
			break;
		}
	}
	mutex_unlock(&vin->group->lock);

	return ret;
	return vin->group->link_setup(vin);
}

static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
@@ -953,6 +917,53 @@ static int rvin_parallel_init(struct rvin_dev *vin)
 * CSI-2
 */

static int rvin_csi2_setup_links(struct rvin_dev *vin)
{
	const struct rvin_group_route *route;
	int ret = -EINVAL;

	/* Create all media device links between VINs and CSI-2's. */
	mutex_lock(&vin->group->lock);
	for (route = vin->info->routes; route->mask; route++) {
		struct media_pad *source_pad, *sink_pad;
		struct media_entity *source, *sink;
		unsigned int source_idx;

		/* Check that VIN is part of the group. */
		if (!vin->group->vin[route->vin])
			continue;

		/* Check that VIN' master is part of the group. */
		if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
			continue;

		/* Check that CSI-2 is part of the group. */
		if (!vin->group->remotes[route->csi].subdev)
			continue;

		source = &vin->group->remotes[route->csi].subdev->entity;
		source_idx = rvin_group_csi_channel_to_pad(route->channel);
		source_pad = &source->pads[source_idx];

		sink = &vin->group->vin[route->vin]->vdev.entity;
		sink_pad = &sink->pads[0];

		/* Skip if link already exists. */
		if (media_entity_find_link(source_pad, sink_pad))
			continue;

		ret = media_create_pad_link(source, source_idx, sink, 0, 0);
		if (ret) {
			vin_err(vin, "Error adding link from %s to %s\n",
				source->name, sink->name);
			break;
		}
	}
	mutex_unlock(&vin->group->lock);

	return ret;
}

static void rvin_csi2_cleanup(struct rvin_dev *vin)
{
	rvin_parallel_cleanup(vin);
@@ -974,7 +985,7 @@ static int rvin_csi2_init(struct rvin_dev *vin)
	if (ret < 0)
		return ret;

	ret = rvin_group_get(vin);
	ret = rvin_group_get(vin, rvin_csi2_setup_links);
	if (ret)
		goto err_controls;

+3 −0
Original line number Diff line number Diff line
@@ -269,6 +269,7 @@ struct rvin_dev {
 * @count:		number of enabled VIN instances found in DT
 * @notifier:		group notifier for CSI-2 async subdevices
 * @vin:		VIN instances which are part of the group
 * @link_setup:		Callback to create all links for the media graph
 * @remotes:		array of pairs of fwnode and subdev pointers
 *			to all remote subdevices.
 */
@@ -282,6 +283,8 @@ struct rvin_group {
	struct v4l2_async_notifier notifier;
	struct rvin_dev *vin[RCAR_VIN_NUM];

	int (*link_setup)(struct rvin_dev *vin);

	struct {
		struct v4l2_async_subdev *asd;
		struct v4l2_subdev *subdev;