Commit 76775776 authored by Jacek Anaszewski's avatar Jacek Anaszewski Committed by Mauro Carvalho Chehab

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

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: default avatarJacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 4e63959e
...@@ -185,6 +185,37 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool on) ...@@ -185,6 +185,37 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool on)
return ret; return ret;
} }
/**
* __fimc_pipeline_enable - enable power of all pipeline subdevs
* and the sensor clock
* @ep: video pipeline structure
* @fmd: fimc media device
*
* Called with the graph mutex held.
*/
static int __fimc_pipeline_enable(struct exynos_media_pipeline *ep,
struct fimc_md *fmd)
{
struct fimc_pipeline *p = to_fimc_pipeline(ep);
int ret;
/* Enable PXLASYNC clock if this pipeline includes FIMC-IS */
if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) {
ret = clk_prepare_enable(fmd->wbclk[CLK_IDX_WB_B]);
if (ret < 0)
return ret;
}
ret = fimc_pipeline_s_power(p, 1);
if (!ret)
return 0;
if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])
clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);
return ret;
}
/** /**
* __fimc_pipeline_open - update the pipeline information, enable power * __fimc_pipeline_open - update the pipeline information, enable power
* of all pipeline subdevs and the sensor clock * of all pipeline subdevs and the sensor clock
...@@ -199,7 +230,6 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, ...@@ -199,7 +230,6 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
struct fimc_md *fmd = entity_to_fimc_mdev(me); struct fimc_md *fmd = entity_to_fimc_mdev(me);
struct fimc_pipeline *p = to_fimc_pipeline(ep); struct fimc_pipeline *p = to_fimc_pipeline(ep);
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
int ret;
if (WARN_ON(p == NULL || me == NULL)) if (WARN_ON(p == NULL || me == NULL))
return -EINVAL; return -EINVAL;
...@@ -208,24 +238,16 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, ...@@ -208,24 +238,16 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
fimc_pipeline_prepare(p, me); fimc_pipeline_prepare(p, me);
sd = p->subdevs[IDX_SENSOR]; sd = p->subdevs[IDX_SENSOR];
if (sd == NULL) if (sd == NULL) {
return -EINVAL; pr_warn("%s(): No sensor subdev\n", __func__);
/*
/* Disable PXLASYNC clock if this pipeline includes FIMC-IS */ * Pipeline open cannot fail so as to make it possible
if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) { * for the user space to configure the pipeline.
ret = clk_prepare_enable(fmd->wbclk[CLK_IDX_WB_B]); */
if (ret < 0)
return ret;
}
ret = fimc_pipeline_s_power(p, 1);
if (!ret)
return 0; return 0;
}
if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) return __fimc_pipeline_enable(ep, fmd);
clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);
return ret;
} }
/** /**
...@@ -269,10 +291,43 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on) ...@@ -269,10 +291,43 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
{ IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP }, { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP },
}; };
struct fimc_pipeline *p = to_fimc_pipeline(ep); struct fimc_pipeline *p = to_fimc_pipeline(ep);
struct fimc_md *fmd = entity_to_fimc_mdev(&p->subdevs[IDX_CSIS]->entity);
enum fimc_subdev_index sd_id;
int i, ret = 0; int i, ret = 0;
if (p->subdevs[IDX_SENSOR] == NULL) if (p->subdevs[IDX_SENSOR] == NULL) {
return -ENODEV; if (!fmd->user_subdev_api) {
/*
* Sensor must be already discovered if we
* aren't in the user_subdev_api mode
*/
return -ENODEV;
}
/* Get pipeline sink entity */
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;
/*
* Sensor could have been linked between open and STREAMON -
* check if this is the case.
*/
fimc_pipeline_prepare(p, &p->subdevs[sd_id]->entity);
if (p->subdevs[IDX_SENSOR] == NULL)
return -ENODEV;
ret = __fimc_pipeline_enable(ep, fmd);
if (ret < 0)
return ret;
}
for (i = 0; i < IDX_MAX; i++) { for (i = 0; i < IDX_MAX; i++) {
unsigned int idx = seq[on][i]; unsigned int idx = seq[on][i];
...@@ -282,8 +337,10 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on) ...@@ -282,8 +337,10 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
goto error; goto error;
} }
return 0; return 0;
error: error:
fimc_pipeline_s_power(p, !on);
for (; i >= 0; i--) { for (; i >= 0; i--) {
unsigned int idx = seq[on][i]; unsigned int idx = seq[on][i];
v4l2_subdev_call(p->subdevs[idx], video, s_stream, !on); v4l2_subdev_call(p->subdevs[idx], video, s_stream, !on);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment