示例#1
0
文件: fimc-lite.c 项目: 19Dan01/linux
static int fimc_lite_release(struct file *file)
{
	struct fimc_lite *fimc = video_drvdata(file);
	struct media_entity *entity = &fimc->ve.vdev.entity;

	mutex_lock(&fimc->lock);

	if (v4l2_fh_is_singular_file(file) &&
	    atomic_read(&fimc->out_path) == FIMC_IO_DMA) {
		if (fimc->streaming) {
			media_entity_pipeline_stop(entity);
			fimc->streaming = false;
		}
		fimc_lite_stop_capture(fimc, false);
		fimc_pipeline_call(&fimc->ve, close);
		clear_bit(ST_FLITE_IN_USE, &fimc->state);

		mutex_lock(&entity->parent->graph_mutex);
		entity->use_count--;
		mutex_unlock(&entity->parent->graph_mutex);
	}

	_vb2_fop_release(file, NULL);
	pm_runtime_put(&fimc->pdev->dev);
	clear_bit(ST_FLITE_SUSPENDED, &fimc->state);

	mutex_unlock(&fimc->lock);
	return 0;
}
示例#2
0
static int fimc_lite_open(struct file *file)
{
	struct fimc_lite *fimc = video_drvdata(file);
	int ret;

	if (mutex_lock_interruptible(&fimc->lock))
		return -ERESTARTSYS;

	set_bit(ST_FLITE_IN_USE, &fimc->state);
	ret = pm_runtime_get_sync(&fimc->pdev->dev);
	if (ret < 0)
		goto done;

	ret = v4l2_fh_open(file);
	if (ret < 0)
		goto done;

	if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) {
		ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
					 &fimc->vfd.entity, true);
		if (ret < 0) {
			pm_runtime_put_sync(&fimc->pdev->dev);
			fimc->ref_count--;
			v4l2_fh_release(file);
			clear_bit(ST_FLITE_IN_USE, &fimc->state);
		}

		fimc_lite_clear_event_counters(fimc);
	}
done:
	mutex_unlock(&fimc->lock);
	return ret;
}
示例#3
0
static void isp_video_capture_stop_streaming(struct vb2_queue *q)
{
	struct fimc_isp *isp = vb2_get_drv_priv(q);
	struct fimc_is *is = fimc_isp_to_is(isp);
	struct param_dma_output *dma = __get_isp_dma2(is);
	int ret;

	ret = fimc_pipeline_call(&isp->video_capture.ve, set_stream, 0);
	if (ret < 0)
		return;

	dma->cmd = DMA_OUTPUT_COMMAND_DISABLE;
	dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE;
	dma->buffer_number = 0;
	dma->buffer_address = 0;
	dma->dma_out_mask = 0;

	fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT);
	__fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT);

	ret = fimc_is_itf_s_param(is, false);
	if (ret < 0)
		dev_warn(&is->pdev->dev, "%s: DMA stop failed\n", __func__);

	fimc_is_hw_set_isp_buf_mask(is, 0);

	clear_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state);
	clear_bit(ST_ISP_VID_CAP_STREAMING, &isp->state);

	isp->video_capture.buf_count = 0;
}
示例#4
0
文件: fimc-lite.c 项目: FoundYa/linux
static int fimc_lite_close(struct file *file)
{
	struct fimc_lite *fimc = video_drvdata(file);
	int ret;

	if (mutex_lock_interruptible(&fimc->lock))
		return -ERESTARTSYS;

	if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) {
		clear_bit(ST_FLITE_IN_USE, &fimc->state);
		fimc_lite_stop_capture(fimc, false);
		fimc_pipeline_call(fimc, close, &fimc->pipeline);
		clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
	}

	pm_runtime_put(&fimc->pdev->dev);

	if (fimc->ref_count == 0)
		vb2_queue_release(&fimc->vb_queue);

	ret = v4l2_fh_release(file);

	mutex_unlock(&fimc->lock);
	return ret;
}
示例#5
0
static int isp_video_release(struct file *file)
{
	struct fimc_isp *isp = video_drvdata(file);
	struct fimc_is_video *ivc = &isp->video_capture;
	struct media_entity *entity = &ivc->ve.vdev.entity;
	struct media_device *mdev = entity->graph_obj.mdev;

	mutex_lock(&isp->video_lock);

	if (v4l2_fh_is_singular_file(file) && ivc->streaming) {
		media_entity_pipeline_stop(entity);
		ivc->streaming = 0;
	}

	vb2_fop_release(file);

	if (v4l2_fh_is_singular_file(file)) {
		fimc_pipeline_call(&ivc->ve, close);

		mutex_lock(&mdev->graph_mutex);
		entity->use_count--;
		mutex_unlock(&mdev->graph_mutex);
	}

	pm_runtime_put(&isp->pdev->dev);
	mutex_unlock(&isp->video_lock);

	return 0;
}
示例#6
0
int fimc_capture_resume(struct fimc_dev *fimc)
{
	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
	struct fimc_vid_buffer *buf;
	int i;

	if (!test_and_clear_bit(ST_CAPT_SUSPENDED, &fimc->state))
		return 0;

	INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
	vid_cap->buf_index = 0;
	fimc_pipeline_call(fimc, open, &fimc->pipeline,
			   &vid_cap->vfd.entity, false);
	fimc_capture_hw_init(fimc);

	clear_bit(ST_CAPT_SUSPENDED, &fimc->state);

	for (i = 0; i < vid_cap->reqbufs_count; i++) {
		if (list_empty(&vid_cap->pending_buf_q))
			break;
		buf = fimc_pending_queue_pop(vid_cap);
		buffer_queue(&buf->vb);
	}
	return 0;

}
示例#7
0
static int start_streaming(struct vb2_queue *q, unsigned int count)
{
	struct fimc_lite *fimc = q->drv_priv;
	int ret;

	fimc->frame_count = 0;

	ret = fimc_lite_hw_init(fimc);
	if (ret) {
		fimc_lite_reinit(fimc, false);
		return ret;
	}

	set_bit(ST_FLITE_PENDING, &fimc->state);

	if (!list_empty(&fimc->active_buf_q) &&
	    !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) {
		flite_hw_capture_start(fimc);

		if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
			fimc_pipeline_call(fimc, set_stream,
					   &fimc->pipeline, 1);
	}
	if (debug > 0)
		flite_hw_dump_regs(fimc, __func__);

	return 0;
}
示例#8
0
文件: fimc-lite.c 项目: 19Dan01/linux
static int start_streaming(struct vb2_queue *q, unsigned int count)
{
	struct fimc_lite *fimc = q->drv_priv;
	unsigned long flags;
	int ret;

	spin_lock_irqsave(&fimc->slock, flags);

	fimc->buf_index = 0;
	fimc->frame_count = 0;

	spin_unlock_irqrestore(&fimc->slock, flags);

	ret = fimc_lite_hw_init(fimc, false);
	if (ret) {
		fimc_lite_reinit(fimc, false);
		return ret;
	}

	set_bit(ST_FLITE_PENDING, &fimc->state);

	if (!list_empty(&fimc->active_buf_q) &&
	    !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) {
		flite_hw_capture_start(fimc);

		if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
			fimc_pipeline_call(&fimc->ve, set_stream, 1);
	}
	if (debug > 0)
		flite_hw_dump_regs(fimc, __func__);

	return 0;
}
示例#9
0
static int start_streaming(struct vb2_queue *q, unsigned int count)
{
	struct fimc_ctx *ctx = q->drv_priv;
	struct fimc_dev *fimc = ctx->fimc_dev;
	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
	int min_bufs;
	int ret;

	vid_cap->frame_count = 0;

	ret = fimc_capture_hw_init(fimc);
	if (ret) {
		fimc_capture_state_cleanup(fimc, false);
		return ret;
	}

	set_bit(ST_CAPT_PEND, &fimc->state);

	min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1;

	if (vid_cap->active_buf_cnt >= min_bufs &&
	    !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) {
		fimc_activate_capture(ctx);

		if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
			fimc_pipeline_call(fimc, set_stream,
					   &fimc->pipeline, 1);
	}

	return 0;
}
示例#10
0
static void buffer_queue(struct vb2_buffer *vb)
{
	struct flite_buffer *buf
		= container_of(vb, struct flite_buffer, vb);
	struct fimc_lite *fimc = vb2_get_drv_priv(vb->vb2_queue);
	unsigned long flags;

	spin_lock_irqsave(&fimc->slock, flags);
	buf->paddr = vb2_dma_contig_plane_dma_addr(vb, 0);

	if (!test_bit(ST_FLITE_SUSPENDED, &fimc->state) &&
	    !test_bit(ST_FLITE_STREAM, &fimc->state) &&
	    list_empty(&fimc->active_buf_q)) {
		flite_hw_set_output_addr(fimc, buf->paddr);
		fimc_lite_active_queue_add(fimc, buf);
	} else {
		fimc_lite_pending_queue_add(fimc, buf);
	}

	if (vb2_is_streaming(&fimc->vb_queue) &&
	    !list_empty(&fimc->pending_buf_q) &&
	    !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) {
		flite_hw_capture_start(fimc);
		spin_unlock_irqrestore(&fimc->slock, flags);

		if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
			fimc_pipeline_call(fimc, set_stream,
					   &fimc->pipeline, 1);
		return;
	}
	spin_unlock_irqrestore(&fimc->slock, flags);
}
示例#11
0
static int fimc_capture_close(struct file *file)
{
	struct fimc_dev *fimc = video_drvdata(file);
	int ret;

	dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);

	if (mutex_lock_interruptible(&fimc->lock))
		return -ERESTARTSYS;

	if (--fimc->vid_cap.refcnt == 0) {
		clear_bit(ST_CAPT_BUSY, &fimc->state);
		fimc_stop_capture(fimc, false);
		fimc_pipeline_call(fimc, close, &fimc->pipeline);
		clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
	}

	pm_runtime_put(&fimc->pdev->dev);

	if (fimc->vid_cap.refcnt == 0) {
		vb2_queue_release(&fimc->vid_cap.vbq);
		fimc_ctrls_delete(fimc->vid_cap.ctx);
	}

	ret = v4l2_fh_release(file);

	mutex_unlock(&fimc->lock);
	return ret;
}
示例#12
0
static int fimc_lite_resume(struct device *dev)
{
	struct fimc_lite *fimc = dev_get_drvdata(dev);
	struct flite_buffer *buf;
	unsigned long flags;
	int i;

	spin_lock_irqsave(&fimc->slock, flags);
	if (!test_and_clear_bit(ST_LPM, &fimc->state) ||
	    !test_bit(ST_FLITE_IN_USE, &fimc->state)) {
		spin_unlock_irqrestore(&fimc->slock, flags);
		return 0;
	}
	flite_hw_reset(fimc);
	spin_unlock_irqrestore(&fimc->slock, flags);

	if (!test_and_clear_bit(ST_FLITE_SUSPENDED, &fimc->state))
		return 0;

	INIT_LIST_HEAD(&fimc->active_buf_q);
	fimc_pipeline_call(fimc, open, &fimc->pipeline,
			   &fimc->vfd.entity, false);
	fimc_lite_hw_init(fimc);
	clear_bit(ST_FLITE_SUSPENDED, &fimc->state);

	for (i = 0; i < fimc->reqbufs_count; i++) {
		if (list_empty(&fimc->pending_buf_q))
			break;
		buf = fimc_lite_pending_queue_pop(fimc);
		buffer_queue(&buf->vb);
	}
	return 0;
}
示例#13
0
int fimc_capture_suspend(struct fimc_dev *fimc)
{
	bool suspend = fimc_capture_busy(fimc);

	int ret = fimc_stop_capture(fimc, suspend);
	if (ret)
		return ret;
	return fimc_pipeline_call(fimc, close, &fimc->pipeline);
}
示例#14
0
static int fimc_lite_suspend(struct device *dev)
{
	struct fimc_lite *fimc = dev_get_drvdata(dev);
	bool suspend = test_bit(ST_FLITE_IN_USE, &fimc->state);
	int ret;

	if (test_and_set_bit(ST_LPM, &fimc->state))
		return 0;

	ret = fimc_lite_stop_capture(fimc, suspend);
	if (ret < 0 || !fimc_lite_active(fimc))
		return ret;

	return fimc_pipeline_call(fimc, close, &fimc->pipeline);
}
示例#15
0
文件: fimc-lite.c 项目: 19Dan01/linux
static int fimc_lite_open(struct file *file)
{
	struct fimc_lite *fimc = video_drvdata(file);
	struct media_entity *me = &fimc->ve.vdev.entity;
	int ret;

	mutex_lock(&fimc->lock);
	if (atomic_read(&fimc->out_path) != FIMC_IO_DMA) {
		ret = -EBUSY;
		goto unlock;
	}

	set_bit(ST_FLITE_IN_USE, &fimc->state);
	ret = pm_runtime_get_sync(&fimc->pdev->dev);
	if (ret < 0)
		goto unlock;

	ret = v4l2_fh_open(file);
	if (ret < 0)
		goto err_pm;

	if (!v4l2_fh_is_singular_file(file) ||
	    atomic_read(&fimc->out_path) != FIMC_IO_DMA)
		goto unlock;

	mutex_lock(&me->parent->graph_mutex);

	ret = fimc_pipeline_call(&fimc->ve, open, me, true);

	/* Mark video pipeline ending at this video node as in use. */
	if (ret == 0)
		me->use_count++;

	mutex_unlock(&me->parent->graph_mutex);

	if (!ret) {
		fimc_lite_clear_event_counters(fimc);
		goto unlock;
	}

	v4l2_fh_release(file);
err_pm:
	pm_runtime_put_sync(&fimc->pdev->dev);
	clear_bit(ST_FLITE_IN_USE, &fimc->state);
unlock:
	mutex_unlock(&fimc->lock);
	return ret;
}
示例#16
0
static void buffer_queue(struct vb2_buffer *vb)
{
	struct fimc_vid_buffer *buf
		= container_of(vb, struct fimc_vid_buffer, vb);
	struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
	struct fimc_dev *fimc = ctx->fimc_dev;
	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
	unsigned long flags;
	int min_bufs;

	spin_lock_irqsave(&fimc->slock, flags);
	fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr);

	if (!test_bit(ST_CAPT_SUSPENDED, &fimc->state) &&
	    !test_bit(ST_CAPT_STREAM, &fimc->state) &&
	    vid_cap->active_buf_cnt < FIMC_MAX_OUT_BUFS) {
		/* Setup the buffer directly for processing. */
		int buf_id = (vid_cap->reqbufs_count == 1) ? -1 :
				vid_cap->buf_index;

		fimc_hw_set_output_addr(fimc, &buf->paddr, buf_id);
		buf->index = vid_cap->buf_index;
		fimc_active_queue_add(vid_cap, buf);

		if (++vid_cap->buf_index >= FIMC_MAX_OUT_BUFS)
			vid_cap->buf_index = 0;
	} else {
		fimc_pending_queue_add(vid_cap, buf);
	}

	min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1;


	if (vb2_is_streaming(&vid_cap->vbq) &&
	    vid_cap->active_buf_cnt >= min_bufs &&
	    !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) {
		fimc_activate_capture(ctx);
		spin_unlock_irqrestore(&fimc->slock, flags);

		if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
			fimc_pipeline_call(fimc, set_stream,
					   &fimc->pipeline, 1);
		return;
	}
	spin_unlock_irqrestore(&fimc->slock, flags);
}
示例#17
0
static int fimc_capture_open(struct file *file)
{
	struct fimc_dev *fimc = video_drvdata(file);
	int ret = -EBUSY;

	dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);

	if (mutex_lock_interruptible(&fimc->lock))
		return -ERESTARTSYS;

	if (fimc_m2m_active(fimc))
		goto unlock;

	set_bit(ST_CAPT_BUSY, &fimc->state);
	ret = pm_runtime_get_sync(&fimc->pdev->dev);
	if (ret < 0)
		goto unlock;

	ret = v4l2_fh_open(file);
	if (ret) {
		pm_runtime_put(&fimc->pdev->dev);
		goto unlock;
	}

	if (++fimc->vid_cap.refcnt == 1) {
		ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
					 &fimc->vid_cap.vfd.entity, true);

		if (!ret && !fimc->vid_cap.user_subdev_api)
			ret = fimc_capture_set_default_format(fimc);

		if (!ret)
			ret = fimc_capture_ctrls_create(fimc);

		if (ret < 0) {
			clear_bit(ST_CAPT_BUSY, &fimc->state);
			pm_runtime_put_sync(&fimc->pdev->dev);
			fimc->vid_cap.refcnt--;
			v4l2_fh_release(file);
		}
	}
unlock:
	mutex_unlock(&fimc->lock);
	return ret;
}
示例#18
0
/*
 * Reinitialize the driver so it is ready to start the streaming again.
 * Set fimc->state to indicate stream off and the hardware shut down state.
 * If not suspending (@suspend is false), return any buffers to videobuf2.
 * Otherwise put any owned buffers onto the pending buffers queue, so they
 * can be re-spun when the device is being resumed. Also perform FIMC
 * software reset and disable streaming on the whole pipeline if required.
 */
static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
{
	struct fimc_vid_cap *cap = &fimc->vid_cap;
	struct fimc_vid_buffer *buf;
	unsigned long flags;
	bool streaming;

	spin_lock_irqsave(&fimc->slock, flags);
	streaming = fimc->state & (1 << ST_CAPT_ISP_STREAM);

	fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_SHUT |
			 1 << ST_CAPT_STREAM | 1 << ST_CAPT_ISP_STREAM);
	if (suspend)
		fimc->state |= (1 << ST_CAPT_SUSPENDED);
	else
		fimc->state &= ~(1 << ST_CAPT_PEND | 1 << ST_CAPT_SUSPENDED);

	/* Release unused buffers */
	while (!suspend && !list_empty(&cap->pending_buf_q)) {
		buf = fimc_pending_queue_pop(cap);
		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
	}
	/* If suspending put unused buffers onto pending queue */
	while (!list_empty(&cap->active_buf_q)) {
		buf = fimc_active_queue_pop(cap);
		if (suspend)
			fimc_pending_queue_add(cap, buf);
		else
			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
	}

	fimc_hw_reset(fimc);
	cap->buf_index = 0;

	spin_unlock_irqrestore(&fimc->slock, flags);

	if (streaming)
		return fimc_pipeline_call(fimc, set_stream,
					  &fimc->pipeline, 0);
	else
		return 0;
}
示例#19
0
static int isp_video_capture_start_streaming(struct vb2_queue *q,
						unsigned int count)
{
	struct fimc_isp *isp = vb2_get_drv_priv(q);
	struct fimc_is *is = fimc_isp_to_is(isp);
	struct param_dma_output *dma = __get_isp_dma2(is);
	struct fimc_is_video *video = &isp->video_capture;
	int ret;

	if (!test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state) ||
	    test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state))
		return 0;


	dma->cmd = DMA_OUTPUT_COMMAND_ENABLE;
	dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_ENABLE;
	dma->buffer_address = is->is_dma_p_region +
				DMA2_OUTPUT_ADDR_ARRAY_OFFS;
	dma->buffer_number = video->reqbufs_count;
	dma->dma_out_mask = video->buf_mask;

	isp_dbg(2, &video->ve.vdev,
		"buf_count: %d, planes: %d, dma addr table: %#x\n",
		video->buf_count, video->format->memplanes,
		dma->buffer_address);

	fimc_is_mem_barrier();

	fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT);
	__fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT);

	ret = fimc_is_itf_s_param(is, false);
	if (ret < 0)
		return ret;

	ret = fimc_pipeline_call(&video->ve, set_stream, 1);
	if (ret < 0)
		return ret;

	set_bit(ST_ISP_VID_CAP_STREAMING, &isp->state);
	return ret;
}
示例#20
0
/*
 * Reinitialize the driver so it is ready to start the streaming again.
 * Set fimc->state to indicate stream off and the hardware shut down state.
 * If not suspending (@suspend is false), return any buffers to videobuf2.
 * Otherwise put any owned buffers onto the pending buffers queue, so they
 * can be re-spun when the device is being resumed. Also perform FIMC
 * software reset and disable streaming on the whole pipeline if required.
 */
static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
{
	struct flite_buffer *buf;
	unsigned long flags;
	bool streaming;

	spin_lock_irqsave(&fimc->slock, flags);
	streaming = fimc->state & (1 << ST_SENSOR_STREAM);

	fimc->state &= ~(1 << ST_FLITE_RUN | 1 << ST_FLITE_OFF |
			 1 << ST_FLITE_STREAM | 1 << ST_SENSOR_STREAM);
	if (suspend)
		fimc->state |= (1 << ST_FLITE_SUSPENDED);
	else
		fimc->state &= ~(1 << ST_FLITE_PENDING |
				 1 << ST_FLITE_SUSPENDED);

	/* Release unused buffers */
	while (!suspend && !list_empty(&fimc->pending_buf_q)) {
		buf = fimc_lite_pending_queue_pop(fimc);
		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
	}
	/* If suspending put unused buffers onto pending queue */
	while (!list_empty(&fimc->active_buf_q)) {
		buf = fimc_lite_active_queue_pop(fimc);
		if (suspend)
			fimc_lite_pending_queue_add(fimc, buf);
		else
			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
	}

	spin_unlock_irqrestore(&fimc->slock, flags);

	flite_hw_reset(fimc);

	if (!streaming)
		return 0;

	return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0);
}
示例#21
0
static int isp_video_open(struct file *file)
{
	struct fimc_isp *isp = video_drvdata(file);
	struct exynos_video_entity *ve = &isp->video_capture.ve;
	struct media_entity *me = &ve->vdev.entity;
	int ret;

	if (mutex_lock_interruptible(&isp->video_lock))
		return -ERESTARTSYS;

	ret = v4l2_fh_open(file);
	if (ret < 0)
		goto unlock;

	ret = pm_runtime_get_sync(&isp->pdev->dev);
	if (ret < 0)
		goto rel_fh;

	if (v4l2_fh_is_singular_file(file)) {
		mutex_lock(&me->graph_obj.mdev->graph_mutex);

		ret = fimc_pipeline_call(ve, open, me, true);

		/* Mark the video pipeline as in use. */
		if (ret == 0)
			me->use_count++;

		mutex_unlock(&me->graph_obj.mdev->graph_mutex);
	}
	if (!ret)
		goto unlock;
rel_fh:
	v4l2_fh_release(file);
unlock:
	mutex_unlock(&isp->video_lock);
	return ret;
}