media: rcar-vin: Parse parallel input on Gen3
authorJacopo Mondi <jacopo+renesas@jmondi.org>
Tue, 12 Jun 2018 09:43:28 +0000 (05:43 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Wed, 4 Jul 2018 13:21:04 +0000 (09:21 -0400)
The rcar-vin driver so far had a mutually exclusive code path for
handling parallel and CSI-2 video input subdevices, with only the CSI-2
use case supporting media-controller. As we add support for parallel
inputs to Gen3 media-controller compliant code path now parse both port@0
and port@1, handling the media-controller use case in the parallel
bound/unbind notifier operations.

Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Acked-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/rcar-vin/rcar-core.c

index 7f84c7b..e9b5b83 100644 (file)
@@ -397,6 +397,11 @@ static int rvin_parallel_subdevice_attach(struct rvin_dev *vin,
        ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
        vin->parallel->sink_pad = ret < 0 ? 0 : ret;
 
+       if (vin->info->use_mc) {
+               vin->parallel->subdev = subdev;
+               return 0;
+       }
+
        /* Find compatible subdevices mbus format */
        vin->mbus_code = 0;
        code.index = 0;
@@ -458,10 +463,12 @@ static int rvin_parallel_subdevice_attach(struct rvin_dev *vin,
 static void rvin_parallel_subdevice_detach(struct rvin_dev *vin)
 {
        rvin_v4l2_unregister(vin);
-       v4l2_ctrl_handler_free(&vin->ctrl_handler);
-
-       vin->vdev.ctrl_handler = NULL;
        vin->parallel->subdev = NULL;
+
+       if (!vin->info->use_mc) {
+               v4l2_ctrl_handler_free(&vin->ctrl_handler);
+               vin->vdev.ctrl_handler = NULL;
+       }
 }
 
 static int rvin_parallel_notify_complete(struct v4l2_async_notifier *notifier)
@@ -550,18 +557,19 @@ static int rvin_parallel_parse_v4l2(struct device *dev,
        return 0;
 }
 
-static int rvin_parallel_graph_init(struct rvin_dev *vin)
+static int rvin_parallel_init(struct rvin_dev *vin)
 {
        int ret;
 
-       ret = v4l2_async_notifier_parse_fwnode_endpoints(
-               vin->dev, &vin->notifier,
-               sizeof(struct rvin_parallel_entity), rvin_parallel_parse_v4l2);
+       ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
+               vin->dev, &vin->notifier, sizeof(struct rvin_parallel_entity),
+               0, rvin_parallel_parse_v4l2);
        if (ret)
                return ret;
 
+       /* If using mc, it's fine not to have any input registered. */
        if (!vin->parallel)
-               return -ENODEV;
+               return vin->info->use_mc ? 0 : -ENODEV;
 
        vin_dbg(vin, "Found parallel subdevice %pOF\n",
                to_of_node(vin->parallel->asd.match.fwnode));
@@ -1122,20 +1130,35 @@ static int rcar_vin_probe(struct platform_device *pdev)
                return ret;
 
        platform_set_drvdata(pdev, vin);
-       if (vin->info->use_mc)
+
+       if (vin->info->use_mc) {
                ret = rvin_mc_init(vin);
-       else
-               ret = rvin_parallel_graph_init(vin);
-       if (ret < 0)
-               goto error;
+               if (ret)
+                       goto error_dma_unregister;
+       }
+
+       ret = rvin_parallel_init(vin);
+       if (ret)
+               goto error_group_unregister;
 
        pm_suspend_ignore_children(&pdev->dev, true);
        pm_runtime_enable(&pdev->dev);
 
        return 0;
-error:
+
+error_group_unregister:
+       if (vin->info->use_mc) {
+               mutex_lock(&vin->group->lock);
+               if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) {
+                       v4l2_async_notifier_unregister(&vin->group->notifier);
+                       v4l2_async_notifier_cleanup(&vin->group->notifier);
+               }
+               mutex_unlock(&vin->group->lock);
+               rvin_group_put(vin);
+       }
+
+error_dma_unregister:
        rvin_dma_unregister(vin);
-       v4l2_async_notifier_cleanup(&vin->notifier);
 
        return ret;
 }