Ejemplo n.º 1
0
/**
 * __fimc_pipeline_open - update the pipeline information, enable power
 *                        of all pipeline subdevs and the sensor clock
 * @me: media entity to start graph walk with
 * @prepare: true to walk the current pipeline and acquire all subdevs
 *
 * Called with the graph mutex held.
 */
static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
				struct media_entity *me, bool prepare)
{
	struct fimc_md *fmd = entity_to_fimc_mdev(me);
	struct fimc_pipeline *p = to_fimc_pipeline(ep);
	struct v4l2_subdev *sd;
	int ret;

	if (WARN_ON(p == NULL || me == NULL))
		return -EINVAL;

	if (prepare)
		fimc_pipeline_prepare(p, me);

	sd = p->subdevs[IDX_SENSOR];
	if (sd == NULL)
		return -EINVAL;

	/* Disable 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_shutdown - disable the sensor clock and pipeline power
 * @fimc: fimc device terminating the pipeline
 *
 * Disable power of all subdevs in the pipeline and turn off the external
 * sensor clock.
 * Called with the graph mutex held.
 */
int __fimc_pipeline_shutdown(struct fimc_dev *fimc)
{
	int ret = 0;

	if (fimc->pipeline.sensor) {
		ret = fimc_pipeline_s_power(fimc, 0);
		fimc_md_set_camclk(fimc->pipeline.sensor, false);
	}
	return ret == -ENXIO ? 0 : ret;
}
Ejemplo n.º 3
0
/**
 * __fimc_pipeline_close - disable the sensor clock and pipeline power
 * @fimc: fimc device terminating the pipeline
 *
 * Disable power of all subdevs in the pipeline and turn off the external
 * sensor clock.
 * Called with the graph mutex held.
 */
static int __fimc_pipeline_close(struct fimc_pipeline *p)
{
	int ret = 0;

	if (p->subdevs[IDX_SENSOR]) {
		ret = fimc_pipeline_s_power(p, 0);
		fimc_md_set_camclk(p->subdevs[IDX_SENSOR], false);
	}
	return ret == -ENXIO ? 0 : ret;
}
/**
 * __fimc_pipeline_initialize - update the pipeline information, enable power
 *                              of all pipeline subdevs and the sensor clock
 * @me: media entity to start graph walk with
 * @prep: true to acquire sensor (and csis) subdevs
 *
 * This function must be called with the graph mutex held.
 */
static int __fimc_pipeline_initialize(struct fimc_dev *fimc,
				      struct media_entity *me, bool prep)
{
	int ret;

	if (prep)
		fimc_pipeline_prepare(fimc, me);
	if (fimc->pipeline.sensor == NULL)
		return -EINVAL;
	ret = fimc_md_set_camclk(fimc->pipeline.sensor, true);
	if (ret)
		return ret;
	return fimc_pipeline_s_power(fimc, 1);
}
Ejemplo n.º 5
0
/**
 * __fimc_pipeline_open - update the pipeline information, enable power
 *                        of all pipeline subdevs and the sensor clock
 * @me: media entity to start graph walk with
 * @prep: true to acquire sensor (and csis) subdevs
 *
 * This function must be called with the graph mutex held.
 */
static int __fimc_pipeline_open(struct fimc_pipeline *p,
				struct media_entity *me, bool prep)
{
	int ret;

	if (prep)
		fimc_pipeline_prepare(p, me);

	if (p->subdevs[IDX_SENSOR] == NULL)
		return -EINVAL;

	ret = fimc_md_set_camclk(p->subdevs[IDX_SENSOR], true);
	if (ret)
		return ret;

	return fimc_pipeline_s_power(p, 1);
}
Ejemplo n.º 6
0
/**
 * __fimc_pipeline_close - disable the sensor clock and pipeline power
 * @fimc: fimc device terminating the pipeline
 *
 * Disable power of all subdevs and turn the external sensor clock off.
 */
static int __fimc_pipeline_close(struct exynos_media_pipeline *ep)
{
	struct fimc_pipeline *p = to_fimc_pipeline(ep);
	struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL;
	struct fimc_md *fmd;
	int ret;

	if (sd == NULL) {
		pr_warn("%s(): No sensor subdev\n", __func__);
		return 0;
	}

	ret = fimc_pipeline_s_power(p, 0);

	fmd = entity_to_fimc_mdev(&sd->entity);

	/* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
	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 == -ENXIO ? 0 : ret;
}
Ejemplo n.º 7
0
/**
 * __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;
}
Ejemplo n.º 8
0
/**
 * __fimc_pipeline_close - disable the sensor clock and pipeline power
 * @fimc: fimc device terminating the pipeline
 *
 * Disable power of all subdevs and turn the external sensor clock off.
 */
static int __fimc_pipeline_close(struct fimc_pipeline *p)
{
	struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL;
	struct fimc_md *fmd;
	int ret = 0;

	if (WARN_ON(sd == NULL))
		return -EINVAL;

	if (p->subdevs[IDX_SENSOR]) {
		ret = fimc_pipeline_s_power(p, 0);
		fimc_md_set_camclk(sd, false);
	}

	fmd = entity_to_fimc_mdev(&sd->entity);

	/* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
	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 == -ENXIO ? 0 : ret;
}
Ejemplo n.º 9
0
/**
 * __fimc_pipeline_s_stream - call s_stream() on pipeline subdevs
 * @pipeline: video pipeline structure
 * @on: passed as the s_stream() callback argument
 */
static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
{
	static const u8 seq[2][IDX_MAX] = {
		{ IDX_FIMC, IDX_SENSOR, IDX_IS_ISP, IDX_CSIS, IDX_FLITE },
		{ IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP },
	};
	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;

	if (p->subdevs[IDX_SENSOR] == NULL) {
		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++) {
		unsigned int idx = seq[on][i];

		ret = v4l2_subdev_call(p->subdevs[idx], video, s_stream, on);

		if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
			goto error;
	}

	return 0;
error:
	fimc_pipeline_s_power(p, !on);
	for (; i >= 0; i--) {
		unsigned int idx = seq[on][i];
		v4l2_subdev_call(p->subdevs[idx], video, s_stream, !on);
	}
	return ret;
}