]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
xilinx: v4l: dma: Stop subdevs in reverse order of starting
authorVishal Sagar <vishal.sagar@xilinx.com>
Tue, 23 Oct 2018 10:19:26 +0000 (15:49 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Thu, 1 Nov 2018 09:14:48 +0000 (10:14 +0100)
Patch fixes the incorrect sequence of stopping subdevs in a media
pipeline. The order of stopping should be reverse the order of starting
a video pipe. The video pipe should be started from sink to source and
be disabled from source to sink.

Signed-off-by: Vishal Sagar <vishal.sagar@xilinx.com>
Reviewed-by: Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/media/platform/xilinx/xilinx-dma.c

index 977b2bb9d6db7cb2ce6685b19729fe627692e762..79e58067ace26f6f91a3116040fa675b287f92c3 100644 (file)
 #define XVIP_DMA_MIN_HEIGHT            1U
 #define XVIP_DMA_MAX_HEIGHT            8191U
 
+struct xventity_list {
+       struct list_head list;
+       struct media_entity *entity;
+};
+
 /* -----------------------------------------------------------------------------
  * Helper functions
  */
@@ -96,6 +101,61 @@ static int xvip_dma_verify_format(struct xvip_dma *dma)
  * Pipeline Stream Management
  */
 
+static int xvip_entity_start_stop(struct xvip_composite_device *xdev,
+                                 struct media_entity *entity, bool start)
+{
+       struct v4l2_subdev *subdev;
+       bool is_streaming;
+       int ret = 0;
+
+       dev_dbg(xdev->dev, "%s entity %s\n",
+               start ? "Starting" : "Stopping", entity->name);
+       subdev = media_entity_to_v4l2_subdev(entity);
+
+       /* This is to maintain list of stream on/off devices */
+       is_streaming = xvip_subdev_set_streaming(xdev, subdev, start);
+
+       /*
+        * start or stop the subdev only once in case if they are
+        * shared between sub-graphs
+        */
+       if (start && !is_streaming) {
+               /* power-on subdevice */
+               ret = v4l2_subdev_call(subdev, core, s_power, 1);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       dev_err(xdev->dev,
+                               "s_power on failed on subdev\n");
+                       xvip_subdev_set_streaming(xdev, subdev, 0);
+                       return ret;
+               }
+
+               /* stream-on subdevice */
+               ret = v4l2_subdev_call(subdev, video, s_stream, 1);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       dev_err(xdev->dev,
+                               "s_stream on failed on subdev\n");
+                       v4l2_subdev_call(subdev, core, s_power, 0);
+                       xvip_subdev_set_streaming(xdev, subdev, 0);
+               }
+       } else if (!start && is_streaming) {
+               /* stream-off subdevice */
+               ret = v4l2_subdev_call(subdev, video, s_stream, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       dev_err(xdev->dev,
+                               "s_stream off failed on subdev\n");
+                       xvip_subdev_set_streaming(xdev, subdev, 1);
+               }
+
+               /* power-off subdevice */
+               ret = v4l2_subdev_call(subdev, core, s_power, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD)
+                       dev_err(xdev->dev,
+                               "s_power off failed on subdev\n");
+       }
+
+       return ret;
+}
+
 /**
  * xvip_pipeline_start_stop - Start ot stop streaming on a pipeline
  * @xdev: Composite video device
@@ -113,9 +173,9 @@ static int xvip_pipeline_start_stop(struct xvip_composite_device *xdev,
        struct media_graph graph;
        struct media_entity *entity = &dma->video.entity;
        struct media_device *mdev = entity->graph_obj.mdev;
-       struct v4l2_subdev *subdev;
-       bool is_streaming;
-       int ret;
+       struct xventity_list *temp, *_temp;
+       LIST_HEAD(ent_list);
+       int ret = 0;
 
        mutex_lock(&mdev->graph_mutex);
 
@@ -126,54 +186,44 @@ static int xvip_pipeline_start_stop(struct xvip_composite_device *xdev,
 
        media_graph_walk_start(&graph, entity);
 
+       /* get the list of entities */
        while ((entity = media_graph_walk_next(&graph))) {
+               struct xventity_list *ele;
+
                /* We want to stream on/off only subdevs */
                if (!is_media_entity_v4l2_subdev(entity))
                        continue;
 
-               subdev = media_entity_to_v4l2_subdev(entity);
-
-               /* This is to maintain list of stream on/off devices */
-               is_streaming = xvip_subdev_set_streaming(xdev, subdev, start);
+               /* Maintain the pipeline sequence in a list */
+               ele = kzalloc(sizeof(*ele), GFP_KERNEL);
+               if (!ele) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
 
-               /*
-                * start or stop the subdev only once in case if they are
-                * shared between sub-graphs
-                */
-               if (start && !is_streaming) {
-                       /* power-on subdevice */
-                       ret = v4l2_subdev_call(subdev, core, s_power, 1);
-                       if (ret < 0 && ret != -ENOIOCTLCMD) {
-                               dev_err(xdev->dev,
-                                       "s_power on failed on subdev\n");
-                               xvip_subdev_set_streaming(xdev, subdev, 0);
-                               goto error;
-                       }
+               ele->entity = entity;
+               list_add(&ele->list, &ent_list);
+       }
 
-                       /* stream-on subdevice */
-                       ret = v4l2_subdev_call(subdev, video, s_stream, 1);
-                       if (ret < 0 && ret != -ENOIOCTLCMD) {
-                               dev_err(xdev->dev,
-                                       "s_stream on failed on subdev\n");
-                               v4l2_subdev_call(subdev, core, s_power, 0);
-                               xvip_subdev_set_streaming(xdev, subdev, 0);
-                       }
-               } else if (!start && is_streaming) {
-                       /* stream-off subdevice */
-                       ret = v4l2_subdev_call(subdev, video, s_stream, 0);
-                       if (ret < 0 && ret != -ENOIOCTLCMD) {
-                               dev_err(xdev->dev,
-                                       "s_stream off failed on subdev\n");
-                               xvip_subdev_set_streaming(xdev, subdev, 1);
+       if (start) {
+               list_for_each_entry_safe(temp, _temp, &ent_list, list) {
+                       /* Enable all subdevs from sink to source */
+                       ret = xvip_entity_start_stop(xdev, temp->entity, start);
+                       if (ret < 0) {
+                               dev_err(xdev->dev, "ret = %d for entity %s\n",
+                                       ret, temp->entity->name);
+                               break;
                        }
-
-                       /* power-off subdevice */
-                       ret = v4l2_subdev_call(subdev, core, s_power, 0);
-                       if (ret < 0 && ret != -ENOIOCTLCMD)
-                               dev_err(xdev->dev,
-                                       "s_power off failed on subdev\n");
-
                }
+       } else {
+               list_for_each_entry_safe_reverse(temp, _temp, &ent_list, list)
+                       /* Enable all subdevs from source to sink */
+                       xvip_entity_start_stop(xdev, temp->entity, start);
+       }
+
+       list_for_each_entry_safe(temp, _temp, &ent_list, list) {
+               list_del(&temp->list);
+               kfree(temp);
        }
 
 error:
@@ -271,11 +321,10 @@ static int xvip_pipeline_validate(struct xvip_pipeline *pipe,
 
                dma = to_xvip_dma(media_entity_to_video_device(entity));
 
-               if (dma->pad.flags & MEDIA_PAD_FL_SINK) {
+               if (dma->pad.flags & MEDIA_PAD_FL_SINK)
                        num_outputs++;
-               } else {
+               else
                        num_inputs++;
-               }
        }
 
        mutex_unlock(&mdev->graph_mutex);