+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;
+}
+