[3/3] exynos4-is: Open shouldn't fail when sensor entity is not linked

Message ID 1412758013-23608-3-git-send-email-j.anaszewski@samsung.com (mailing list archive)
State RFC, archived
Delegated to: Sylwester Nawrocki
Headers

Commit Message

Jacek Anaszewski Oct. 8, 2014, 8:46 a.m. UTC
  In order to allow for automatic media device entities linking
from the level of libv4l plugin the open system call shouldn't
fail, as the libv4l plugins can begin their job not until it
succeeds.
This patch allows for leaving the  pipeline not linked on
open and postpones verifying it to the moment when streamon
callback is called.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/platform/exynos4-is/media-dev.c |   45 ++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 4 deletions(-)
  

Patch

diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index c867c46..3732663 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -217,7 +217,7 @@  static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
 		fimc_pipeline_prepare(p, me);
 
 	sd = p->subdevs[IDX_SENSOR];
-	if (sd == NULL)
+	if (sd == NULL && !fmd->user_subdev_api)
 		return -EINVAL;
 
 	/* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
@@ -277,10 +277,46 @@  static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
 		{ IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP },
 	};
 	struct fimc_pipeline *p = to_fimc_pipeline(ep);
-	int i, ret = 0;
+	struct fimc_md *fmd = entity_to_fimc_mdev(&p->subdevs[IDX_CSIS]->entity);
+	enum fimc_subdev_index sd_id;
+	int i = 0, ret = 0;
 
-	if (p->subdevs[IDX_SENSOR] == NULL)
-		return -ENODEV;
+	/*
+	 * Sensor might not be discovered upon device open
+	 * due to not linked pipeline. User space is expected to
+	 * link the pipeline prior calling VIDIOC_STREAMON ioctl,
+	 * when in user_subdev_api mode.
+	 */
+	while (p->subdevs[IDX_SENSOR] == NULL) {
+		/*
+		 * Sensor must be already discovered if
+		 * we are in non user_subdev_api mode.
+		 */
+		if (!fmd->user_subdev_api) {
+			return -ENODEV;
+		} else if (i++ == 0) {
+			/* Determine which entity is last in the pipeline */
+			if (p->subdevs[IDX_FIMC])
+				sd_id = IDX_FIMC;
+			else if (p->subdevs[IDX_IS_ISP])
+				sd_id = IDX_IS_ISP;
+			else if (p->subdevs[IDX_FLITE])
+				sd_id = IDX_FLITE;
+			else
+				return -ENODEV;
+
+			ret = __fimc_pipeline_open(ep,
+					&p->subdevs[sd_id]->entity,
+					true);
+			if (ret < 0)
+				return ret;
+
+			if (p->subdevs[IDX_SENSOR] == NULL)
+				return -ENODEV;
+		} else {
+			return -ENODEV;
+		}
+	}
 
 	/* Wait until all devices in the chain are powered up */
 	async_synchronize_full_domain(&ep->async_domain);
@@ -293,6 +329,7 @@  static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
 		if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
 			goto error;
 	}
+
 	return 0;
 error:
 	for (; i >= 0; i--) {