static void fimc_is_sen_buffer_queue(struct vb2_buffer *vb)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
	struct fimc_is_queue *queue;
	struct fimc_is_video *video;
	struct fimc_is_device_sensor *device;

#ifdef DBG_STREAMING
	mdbgv_sensor("%s(%d)\n", vctx, __func__, vb->v4l2_buf.index);
#endif

	queue = GET_DST_QUEUE(vctx);
	device = vctx->device;
	video = vctx->video;
	if (!video) {
		merr("video is NULL", device);
		return;
	}

	ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
	if (ret) {
		merr("fimc_is_queue_buffer_queue is fail(%d)", device, ret);
		return;
	}

	ret = fimc_is_sensor_buffer_queue(device, vb->v4l2_buf.index);
	if (ret) {
		merr("fimc_is_sensor_buffer_queue is fail(%d)", device, ret);
		return;
	}
}
static int fimc_is_sen_start_streaming(struct vb2_queue *q,
	unsigned int count)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = q->drv_priv;
	struct fimc_is_queue *queue;
	struct fimc_is_device_sensor *device;

	BUG_ON(!vctx);

	mdbgv_sensor("%s\n", vctx, __func__);

	queue = GET_DST_QUEUE(vctx);
	device = vctx->device;

	if (!test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state) &&
		test_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state)) {
		set_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state);
		fimc_is_sensor_back_start(device);
	} else {
		err("already stream on or buffer is not ready(%ld)",
			queue->state);
		clear_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
		clear_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
		fimc_is_sensor_back_stop(device);
		ret = -EINVAL;
	}

	return 0;
}
static int fimc_is_sen_stop_streaming(struct vb2_queue *q)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = q->drv_priv;
	struct fimc_is_queue *queue;
	struct fimc_is_device_sensor *device;

	BUG_ON(!vctx);

	mdbgv_sensor("%s\n", vctx, __func__);

	queue = GET_DST_QUEUE(vctx);
	device = vctx->device;

	if (test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
		clear_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state);
		clear_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
		clear_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
		ret = fimc_is_sensor_back_stop(device);
	} else {
		err("already stream off");
		ret = -EINVAL;
	}

	return ret;
}
static int fimc_is_sen_video_set_format_mplane(struct file *file, void *fh,
	struct v4l2_format *format)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = file->private_data;
	struct fimc_is_queue *queue;
	struct fimc_is_device_sensor *device;

	BUG_ON(!vctx);

	mdbgv_sensor("%s\n", vctx, __func__);

	queue = GET_DST_QUEUE(vctx);
	device = vctx->device;

	ret = fimc_is_video_set_format_mplane(file, vctx, format);
	if (ret) {
		merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
		goto p_err;
	}

	ret = fimc_is_sensor_s_format(device,
		&queue->framecfg.format,
		queue->framecfg.width,
		queue->framecfg.height);
	if (ret) {
		merr("fimc_is_sensor_s_format is fail(%d)", vctx, ret);
		goto p_err;
	}

p_err:
	return ret;
}
static int fimc_is_sen_queue_setup(struct vb2_queue *vbq,
	const struct v4l2_format *fmt,
	unsigned int *num_buffers, unsigned int *num_planes,
	unsigned int sizes[],
	void *allocators[])
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = vbq->drv_priv;
	struct fimc_is_video *video;
	struct fimc_is_queue *queue;

	BUG_ON(!vctx);
	BUG_ON(!vctx->video);

	mdbgv_sensor("%s\n", vctx, __func__);

	queue = GET_DST_QUEUE(vctx);
	video = vctx->video;

	ret = fimc_is_queue_setup(queue,
		video->alloc_ctx,
		num_planes,
		sizes,
		allocators);
	if (ret)
		merr("fimc_is_queue_setup is fail(%d)", vctx, ret);

	return ret;
}
static int fimc_is_scp_video_set_crop(struct file *file, void *fh,
	struct v4l2_crop *crop)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = file->private_data;
	struct fimc_is_queue *queue;
	struct fimc_is_device_ischain *ischain;

	BUG_ON(!vctx);

	mdbgv_scp("%s\n", vctx, __func__);

	queue = GET_DST_QUEUE(vctx);
	ischain = vctx->device;
	if (!ischain) {
		merr("ischain is NULL", vctx);
		ret = -EINVAL;
		goto p_err;
	}

	ret = fimc_is_ischain_scp_s_format(ischain,
		queue->framecfg.format.pixelformat,
		crop->c.width,
		crop->c.height);
	if (ret)
		merr("fimc_is_ischain_scp_s_format is fail(%d)", vctx, ret);

p_err:
	return ret;
}
static int fimc_is_scp_stop_streaming(struct vb2_queue *q)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = q->drv_priv;
	struct fimc_is_queue *queue;
	struct fimc_is_device_ischain *device;
	struct fimc_is_subdev *subdev;

	BUG_ON(!vctx);

	mdbgv_scp("%s\n", vctx, __func__);

	queue = GET_DST_QUEUE(vctx);
	device = vctx->device;
	if (!device) {
		err("device is NULL");
		ret = -EINVAL;
		goto p_err;
	}
	subdev = &device->scp;

	ret = fimc_is_queue_stop_streaming(queue, device, subdev, vctx);
	if (ret)
		merr("fimc_is_queue_stop_streaming is fail(%d)", vctx, ret);

p_err:
	return ret;
}
static void fimc_is_scp_buffer_queue(struct vb2_buffer *vb)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
	struct fimc_is_queue *queue;
	struct fimc_is_video *video;
	struct fimc_is_device_ischain *device;
	struct fimc_is_subdev *subdev;

	BUG_ON(!vctx);

#ifdef DBG_STREAMING
	dbg_scp("%s\n", __func__);
#endif

	queue = GET_DST_QUEUE(vctx);
	video = vctx->video;
	device = vctx->device;
	subdev = &device->scp;

	ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
	if (ret) {
		merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
		return;
	}

	ret = fimc_is_subdev_buffer_queue(subdev, vb->v4l2_buf.index);
	if (ret) {
		merr("fimc_is_subdev_buffer_queue is fail(%d)", vctx, ret);
		return;
	}
}
static int fimc_is_scp_video_set_format_mplane(struct file *file, void *fh,
	struct v4l2_format *format)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = file->private_data;
	struct fimc_is_queue *queue;
	struct fimc_is_device_ischain *ischain;

	BUG_ON(!vctx);
	BUG_ON(!vctx->device);
	BUG_ON(!format);

	mdbgv_scp("%s\n", vctx, __func__);

	queue = GET_DST_QUEUE(vctx);
	ischain = vctx->device;

	ret = fimc_is_video_set_format_mplane(file, vctx, format);
	if (ret) {
		merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
		goto p_err;
	}

	ret = fimc_is_ischain_scp_s_format(ischain,
		queue->framecfg.format.pixelformat,
		queue->framecfg.width,
		queue->framecfg.height);
	if (ret)
		merr("fimc_is_ischain_scp_s_format is fail(%d)", vctx, ret);

p_err:
	return ret;
}
static void fimc_is_3a1_buffer_queue(struct vb2_buffer *vb)
{
	u32 index;
	struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
	struct fimc_is_device_ischain *device;
	struct fimc_is_subdev *leader;
	struct fimc_is_video *video;
	struct fimc_is_queue *queue;

	BUG_ON(!vctx);
	index = vb->v4l2_buf.index;

#ifdef DBG_STREAMING
	mdbgv_3a1("%s(%02d:%d)\n", vctx, __func__, vb->v4l2_buf.type, index);
#endif

	video = vctx->video;
	device = vctx->device;
	leader = &device->group_3ax.leader;

	if (V4L2_TYPE_IS_OUTPUT(vb->v4l2_buf.type)) {
		queue = GET_SRC_QUEUE(vctx);
		fimc_is_queue_buffer_queue(queue, video->vb2, vb);
		fimc_is_ischain_3a1_buffer_queue(device, queue, index);
	} else {
		queue = GET_DST_QUEUE(vctx);
		fimc_is_queue_buffer_queue(queue, video->vb2, vb);
		fimc_is_subdev_buffer_queue(leader, index);
	}
}
int buffer_done(struct fimc_is_video_ctx *vctx, u32 index)
{
	int ret = 0;
	struct fimc_is_queue *queue;

	BUG_ON(!vctx);
	BUG_ON(!vctx->video);
	BUG_ON(index >= FRAMEMGR_MAX_REQUEST);
	BUG_ON(vctx->type == FIMC_IS_VIDEO_TYPE_M2M);

	switch (vctx->type) {
	case FIMC_IS_VIDEO_TYPE_OUTPUT:
		queue = GET_SRC_QUEUE(vctx);
		queue_done(vctx, queue, index, VB2_BUF_STATE_DONE);
		break;
	case FIMC_IS_VIDEO_TYPE_CAPTURE:
		queue = GET_DST_QUEUE(vctx);
		queue_done(vctx, queue, index, VB2_BUF_STATE_DONE);
		break;
	default:
		merr("invalid type(%d)", vctx, vctx->type);
		ret = -EINVAL;
		break;
	}

	return ret;
}
static int fimc_is_scp_start_streaming(struct vb2_queue *q,
	unsigned int count)
{
	int ret = 0;
	struct fimc_is_video_ctx *vctx = q->drv_priv;
	struct fimc_is_queue *queue;
	struct fimc_is_device_ischain *device;
	struct fimc_is_subdev *subdev;

	BUG_ON(!vctx);

	mdbgv_scp("%s\n", vctx, __func__);

	queue = GET_DST_QUEUE(vctx);
	device = vctx->device;
	subdev = &device->scp;

	ret = fimc_is_queue_start_streaming(queue, device, subdev, vctx);
	if (ret)
		merr("fimc_is_queue_start_streaming is fail(%d)", vctx, ret);

	return ret;
}