From: Hans Verkuil <hverkuil@xs4all.nl>
To: "Niklas Söderlund" <niklas.soderlund+renesas@ragnatech.se>,
"Laurent Pinchart" <laurent.pinchart@ideasonboard.com>,
linux-media@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org,
tomoharu.fukawa.eb@renesas.com,
Kieran Bingham <kieran.bingham@ideasonboard.com>
Subject: Re: [PATCH v12 28/33] rcar-vin: parse Gen3 OF and setup media graph
Date: Fri, 9 Mar 2018 16:45:38 +0100 [thread overview]
Message-ID: <cb19f23a-7bfb-539c-5135-c185d56c78d7@xs4all.nl> (raw)
In-Reply-To: <20180307220511.9826-29-niklas.soderlund+renesas@ragnatech.se>
On 07/03/18 23:05, Niklas Söderlund wrote:
> The parsing and registering CSI-2 subdevices with the v4l2 async
> framework is a collaborative effort shared between the VIN instances
> which are part of the group. When the last VIN in the group is probed it
> asks all other VINs to parse its share of OF and record the async
> subdevices it finds in the notifier belonging to the last probed VIN.
>
> Once all CSI-2 subdevices in this notifier are bound proceed to register
> all VIN video devices of the group and crate media device links between
> all CSI-2 and VIN entities according to the SoC specific routing
> configuration.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Regards,
Hans
> ---
> drivers/media/platform/rcar-vin/rcar-core.c | 246 +++++++++++++++++++++++++++-
> drivers/media/platform/rcar-vin/rcar-vin.h | 12 +-
> 2 files changed, 254 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
> index fd4478095ac4e5b1..52fad495533bc427 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -27,6 +27,23 @@
>
> #include "rcar-vin.h"
>
> +/*
> + * The companion CSI-2 receiver driver (rcar-csi2) is known
> + * and we know it has one source pad (pad 0) and four sink
> + * pads (pad 1-4). So to translate a pad on the remote
> + * CSI-2 receiver to/from the VIN internal channel number simply
> + * subtract/add one from the pad/channel number.
> + */
> +#define rvin_group_csi_pad_to_channel(pad) ((pad) - 1)
> +#define rvin_group_csi_channel_to_pad(channel) ((channel) + 1)
> +
> +/*
> + * Not all VINs are created equal, master VINs control the
> + * routing for other VIN's. We can figure out which VIN is
> + * master by looking at a VINs id.
> + */
> +#define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
> +
> /* -----------------------------------------------------------------------------
> * Gen3 CSI2 Group Allocator
> */
> @@ -409,6 +426,216 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
> return 0;
> }
>
> +/* -----------------------------------------------------------------------------
> + * Group async notifier
> + */
> +
> +static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
> +{
> + struct rvin_dev *vin = notifier_to_vin(notifier);
> + const struct rvin_group_route *route;
> + unsigned int i;
> + int ret;
> +
> + ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
> + if (ret) {
> + vin_err(vin, "Failed to register subdev nodes\n");
> + return ret;
> + }
> +
> + /* Register all video nodes for the group. */
> + for (i = 0; i < RCAR_VIN_NUM; i++) {
> + if (vin->group->vin[i]) {
> + ret = rvin_v4l2_register(vin->group->vin[i]);
> + if (ret)
> + return ret;
> + }
> + }
> +
> + /* 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->csi[route->csi].subdev)
> + continue;
> +
> + source = &vin->group->csi[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_group_notify_unbind(struct v4l2_async_notifier *notifier,
> + struct v4l2_subdev *subdev,
> + struct v4l2_async_subdev *asd)
> +{
> + struct rvin_dev *vin = notifier_to_vin(notifier);
> + unsigned int i;
> +
> + for (i = 0; i < RCAR_VIN_NUM; i++)
> + if (vin->group->vin[i])
> + rvin_v4l2_unregister(vin->group->vin[i]);
> +
> + mutex_lock(&vin->group->lock);
> +
> + for (i = 0; i < RVIN_CSI_MAX; i++) {
> + if (vin->group->csi[i].fwnode != asd->match.fwnode)
> + continue;
> + vin->group->csi[i].subdev = NULL;
> + vin_dbg(vin, "Unbind CSI-2 %s from slot %u\n", subdev->name, i);
> + break;
> + }
> +
> + mutex_unlock(&vin->group->lock);
> +}
> +
> +static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
> + struct v4l2_subdev *subdev,
> + struct v4l2_async_subdev *asd)
> +{
> + struct rvin_dev *vin = notifier_to_vin(notifier);
> + unsigned int i;
> +
> + mutex_lock(&vin->group->lock);
> +
> + for (i = 0; i < RVIN_CSI_MAX; i++) {
> + if (vin->group->csi[i].fwnode != asd->match.fwnode)
> + continue;
> + vin->group->csi[i].subdev = subdev;
> + vin_dbg(vin, "Bound CSI-2 %s to slot %u\n", subdev->name, i);
> + break;
> + }
> +
> + mutex_unlock(&vin->group->lock);
> +
> + return 0;
> +}
> +
> +static const struct v4l2_async_notifier_operations rvin_group_notify_ops = {
> + .bound = rvin_group_notify_bound,
> + .unbind = rvin_group_notify_unbind,
> + .complete = rvin_group_notify_complete,
> +};
> +
> +static int rvin_mc_parse_of_endpoint(struct device *dev,
> + struct v4l2_fwnode_endpoint *vep,
> + struct v4l2_async_subdev *asd)
> +{
> + struct rvin_dev *vin = dev_get_drvdata(dev);
> +
> + if (vep->base.port != 1 || vep->base.id >= RVIN_CSI_MAX)
> + return -EINVAL;
> +
> + if (!of_device_is_available(to_of_node(asd->match.fwnode))) {
> +
> + vin_dbg(vin, "OF device %pOF disabled, ignoring\n",
> + to_of_node(asd->match.fwnode));
> + return -ENOTCONN;
> +
> + }
> +
> + if (vin->group->csi[vep->base.id].fwnode) {
> + vin_dbg(vin, "OF device %pOF already handled\n",
> + to_of_node(asd->match.fwnode));
> + return -ENOTCONN;
> + }
> +
> + vin->group->csi[vep->base.id].fwnode = asd->match.fwnode;
> +
> + vin_dbg(vin, "Add group OF device %pOF to slot %u\n",
> + to_of_node(asd->match.fwnode), vep->base.id);
> +
> + return 0;
> +}
> +
> +static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
> +{
> + unsigned int count = 0;
> + unsigned int i;
> + int ret;
> +
> + mutex_lock(&vin->group->lock);
> +
> + /* If there already is a notifier something has gone wrong, bail out. */
> + if (WARN_ON(vin->group->notifier)) {
> + mutex_unlock(&vin->group->lock);
> + return -EINVAL;
> + }
> +
> + /* If not all VIN's are registered don't register the notifier. */
> + for (i = 0; i < RCAR_VIN_NUM; i++)
> + if (vin->group->vin[i])
> + count++;
> +
> + if (vin->group->count != count) {
> + mutex_unlock(&vin->group->lock);
> + return 0;
> + }
> +
> + /*
> + * Have all VIN's look for subdevices. Some subdevices will overlap
> + * but the parser function can handle it, so each subdevice will
> + * only be registered once with the notifier.
> + */
> +
> + vin->group->notifier = &vin->notifier;
> +
> + for (i = 0; i < RCAR_VIN_NUM; i++) {
> + if (!vin->group->vin[i])
> + continue;
> +
> + ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> + vin->group->vin[i]->dev, vin->group->notifier,
> + sizeof(struct v4l2_async_subdev), 1,
> + rvin_mc_parse_of_endpoint);
> + if (ret) {
> + mutex_unlock(&vin->group->lock);
> + return ret;
> + }
> + }
> +
> + mutex_unlock(&vin->group->lock);
> +
> + vin->group->notifier->ops = &rvin_group_notify_ops;
> +
> + ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
> + if (ret < 0) {
> + vin_err(vin, "Notifier registration failed\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> static int rvin_mc_init(struct rvin_dev *vin)
> {
> int ret;
> @@ -422,7 +649,15 @@ static int rvin_mc_init(struct rvin_dev *vin)
> if (ret)
> return ret;
>
> - return rvin_group_get(vin);
> + ret = rvin_group_get(vin);
> + if (ret)
> + return ret;
> +
> + ret = rvin_mc_parse_of_graph(vin);
> + if (ret)
> + rvin_group_put(vin);
> +
> + return ret;
> }
>
> /* -----------------------------------------------------------------------------
> @@ -542,10 +777,15 @@ static int rcar_vin_remove(struct platform_device *pdev)
> v4l2_async_notifier_unregister(&vin->notifier);
> v4l2_async_notifier_cleanup(&vin->notifier);
>
> - if (vin->info->use_mc)
> + if (vin->info->use_mc) {
> + mutex_lock(&vin->group->lock);
> + if (vin->group->notifier == &vin->notifier)
> + vin->group->notifier = NULL;
> + mutex_unlock(&vin->group->lock);
> rvin_group_put(vin);
> - else
> + } else {
> v4l2_ctrl_handler_free(&vin->ctrl_handler);
> + }
>
> rvin_dma_unregister(vin);
>
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
> index 9a68a5909fe07ec7..631dd382c9ccb114 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -223,9 +223,13 @@ struct rvin_dev {
> *
> * @mdev: media device which represents the group
> *
> - * @lock: protects the count and vin members
> + * @lock: protects the count, notifier, vin and csi members
> * @count: number of enabled VIN instances found in DT
> + * @notifier: pointer to the notifier of a VIN which handles the
> + * groups async sub-devices.
> * @vin: VIN instances which are part of the group
> + * @csi: array of pairs of fwnode and subdev pointers
> + * to all CSI-2 subdevices.
> */
> struct rvin_group {
> struct kref refcount;
> @@ -234,7 +238,13 @@ struct rvin_group {
>
> struct mutex lock;
> unsigned int count;
> + struct v4l2_async_notifier *notifier;
> struct rvin_dev *vin[RCAR_VIN_NUM];
> +
> + struct {
> + struct fwnode_handle *fwnode;
> + struct v4l2_subdev *subdev;
> + } csi[RVIN_CSI_MAX];
> };
>
> int rvin_dma_register(struct rvin_dev *vin, int irq);
>
next prev parent reply other threads:[~2018-03-09 15:45 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-07 22:04 [PATCH v12 00/33] rcar-vin: Add Gen3 with media controller Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 01/33] dt-bindings: media: rcar_vin: Reverse SoC part number list Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 02/33] dt-bindings: media: rcar_vin: add device tree support for r8a774[35] Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 03/33] rcar-vin: add Gen3 devicetree bindings documentation Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 04/33] rcar-vin: rename poorly named initialize and cleanup functions Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 05/33] rcar-vin: unregister video device on driver removal Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 06/33] rcar-vin: move subdevice handling to async callbacks Niklas Söderlund
2018-03-09 15:16 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 07/33] rcar-vin: move model information to own struct Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 08/33] rcar-vin: move max width and height information to chip information Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 09/33] rcar-vin: move functions regarding scaling Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 10/33] rcar-vin: all Gen2 boards can scale simplify logic Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 11/33] rcar-vin: set a default field to fallback on Niklas Söderlund
2018-03-09 15:25 ` Hans Verkuil
2018-03-09 16:17 ` Niklas Söderlund
2018-03-09 16:28 ` Hans Verkuil
2018-03-09 17:07 ` Niklas Söderlund
2018-03-09 17:13 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 12/33] rcar-vin: fix handling of single field frames (top, bottom and alternate fields) Niklas Söderlund
2018-03-09 15:28 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 13/33] rcar-vin: update bytesperline and sizeimage calculation Niklas Söderlund
2018-03-09 15:29 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 14/33] rcar-vin: align pixelformat check Niklas Söderlund
2018-03-09 15:30 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 15/33] rcar-vin: break out format alignment and checking Niklas Söderlund
2018-03-09 15:30 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 16/33] rcar-vin: simplify how formats are set and reset Niklas Söderlund
2018-03-09 15:34 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 17/33] rcar-vin: cache video standard Niklas Söderlund
2018-03-09 15:39 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 18/33] rcar-vin: move media bus configuration to struct rvin_dev Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 19/33] rcar-vin: enable Gen3 hardware configuration Niklas Söderlund
2018-03-07 22:04 ` [PATCH v12 20/33] rcar-vin: add function to manipulate Gen3 chsel value Niklas Söderlund
2018-03-09 15:40 ` Hans Verkuil
2018-03-07 22:04 ` [PATCH v12 21/33] rcar-vin: add flag to switch to media controller mode Niklas Söderlund
2018-03-07 22:05 ` [PATCH v12 22/33] rcar-vin: use different v4l2 operations in " Niklas Söderlund
2018-03-07 22:05 ` [PATCH v12 23/33] rcar-vin: force default colorspace for media centric mode Niklas Söderlund
2018-03-09 15:41 ` Hans Verkuil
2018-03-07 22:05 ` [PATCH v12 24/33] rcar-vin: prepare for media controller mode initialization Niklas Söderlund
2018-03-07 22:05 ` [PATCH v12 25/33] rcar-vin: add group allocator functions Niklas Söderlund
2018-03-09 15:42 ` Hans Verkuil
2018-03-07 22:05 ` [PATCH v12 26/33] rcar-vin: change name of video device Niklas Söderlund
2018-03-09 15:43 ` Hans Verkuil
2018-03-07 22:05 ` [PATCH v12 27/33] rcar-vin: add chsel information to rvin_info Niklas Söderlund
2018-03-09 15:43 ` Hans Verkuil
2018-03-07 22:05 ` [PATCH v12 28/33] rcar-vin: parse Gen3 OF and setup media graph Niklas Söderlund
2018-03-09 15:45 ` Hans Verkuil [this message]
2018-03-07 22:05 ` [PATCH v12 29/33] rcar-vin: add link notify for Gen3 Niklas Söderlund
2018-03-09 15:46 ` Hans Verkuil
2018-03-07 22:05 ` [PATCH v12 30/33] rcar-vin: extend {start,stop}_streaming to work with media controller Niklas Söderlund
2018-03-09 15:47 ` Hans Verkuil
2018-03-07 22:05 ` [PATCH v12 31/33] rcar-vin: enable support for r8a7795 Niklas Söderlund
2018-03-09 15:47 ` Hans Verkuil
2018-03-07 22:05 ` [PATCH v12 32/33] rcar-vin: enable support for r8a7796 Niklas Söderlund
2018-03-09 15:48 ` Hans Verkuil
2018-03-07 22:05 ` [PATCH v12 33/33] rcar-vin: enable support for r8a77970 Niklas Söderlund
2018-03-09 15:48 ` Hans Verkuil
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cb19f23a-7bfb-539c-5135-c185d56c78d7@xs4all.nl \
--to=hverkuil@xs4all.nl \
--cc=kieran.bingham@ideasonboard.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=niklas.soderlund+renesas@ragnatech.se \
--cc=tomoharu.fukawa.eb@renesas.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).