@@ -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--) {