diff mbox

[v3,04/12] media: rkisp1: add rockchip isp1 driver

Message ID 20171206111939.1153-5-jacob-chen@iotwrt.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jacob Chen Dec. 6, 2017, 11:19 a.m. UTC
From: Jacob Chen <jacob2.chen@rock-chips.com>

This commit adds a ISP(Camera) v4l2 driver for rockchip rk3288/rk3399 SoC.

Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
Signed-off-by: Yichong Zhong <zyc@rock-chips.com>
Signed-off-by: Jacob Chen <cc@rock-chips.com>
Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/media/platform/Kconfig                    |   10 +
 drivers/media/platform/Makefile                   |    1 +
 drivers/media/platform/rockchip/isp1/Makefile     |    7 +
 drivers/media/platform/rockchip/isp1/capture.c    | 1684 +++++++++++++++++++++
 drivers/media/platform/rockchip/isp1/capture.h    |  194 +++
 drivers/media/platform/rockchip/isp1/common.h     |  137 ++
 drivers/media/platform/rockchip/isp1/dev.c        |  655 ++++++++
 drivers/media/platform/rockchip/isp1/dev.h        |  120 ++
 drivers/media/platform/rockchip/isp1/isp_params.c | 1543 +++++++++++++++++++
 drivers/media/platform/rockchip/isp1/isp_params.h |   76 +
 drivers/media/platform/rockchip/isp1/isp_stats.c  |  521 +++++++
 drivers/media/platform/rockchip/isp1/isp_stats.h  |   85 ++
 drivers/media/platform/rockchip/isp1/regs.c       |  264 ++++
 drivers/media/platform/rockchip/isp1/regs.h       | 1582 +++++++++++++++++++
 drivers/media/platform/rockchip/isp1/rkisp1.c     | 1201 +++++++++++++++
 drivers/media/platform/rockchip/isp1/rkisp1.h     |  131 ++
 16 files changed, 8211 insertions(+)
 create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.c
 create mode 100644 drivers/media/platform/rockchip/isp1/capture.h
 create mode 100644 drivers/media/platform/rockchip/isp1/common.h
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
 create mode 100644 drivers/media/platform/rockchip/isp1/dev.h
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.h
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.c
 create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.h
 create mode 100644 drivers/media/platform/rockchip/isp1/regs.c
 create mode 100644 drivers/media/platform/rockchip/isp1/regs.h
 create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.c
 create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.h

Comments

Hans Verkuil Dec. 13, 2017, 4:07 p.m. UTC | #1
On 06/12/17 12:19, Jacob Chen wrote:
> From: Jacob Chen <jacob2.chen@rock-chips.com>
> 
> This commit adds a ISP(Camera) v4l2 driver for rockchip rk3288/rk3399 SoC.
> 
> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
> Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
> Signed-off-by: Yichong Zhong <zyc@rock-chips.com>
> Signed-off-by: Jacob Chen <cc@rock-chips.com>
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
> Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
> Signed-off-by: Tomasz Figa <tfiga@chromium.org>
> ---
>  drivers/media/platform/Kconfig                    |   10 +
>  drivers/media/platform/Makefile                   |    1 +
>  drivers/media/platform/rockchip/isp1/Makefile     |    7 +
>  drivers/media/platform/rockchip/isp1/capture.c    | 1684 +++++++++++++++++++++
>  drivers/media/platform/rockchip/isp1/capture.h    |  194 +++
>  drivers/media/platform/rockchip/isp1/common.h     |  137 ++
>  drivers/media/platform/rockchip/isp1/dev.c        |  655 ++++++++
>  drivers/media/platform/rockchip/isp1/dev.h        |  120 ++
>  drivers/media/platform/rockchip/isp1/isp_params.c | 1543 +++++++++++++++++++
>  drivers/media/platform/rockchip/isp1/isp_params.h |   76 +
>  drivers/media/platform/rockchip/isp1/isp_stats.c  |  521 +++++++
>  drivers/media/platform/rockchip/isp1/isp_stats.h  |   85 ++
>  drivers/media/platform/rockchip/isp1/regs.c       |  264 ++++
>  drivers/media/platform/rockchip/isp1/regs.h       | 1582 +++++++++++++++++++
>  drivers/media/platform/rockchip/isp1/rkisp1.c     | 1201 +++++++++++++++
>  drivers/media/platform/rockchip/isp1/rkisp1.h     |  131 ++
>  16 files changed, 8211 insertions(+)
>  create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
>  create mode 100644 drivers/media/platform/rockchip/isp1/capture.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/capture.h
>  create mode 100644 drivers/media/platform/rockchip/isp1/common.h
>  create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/dev.h
>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.h
>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.h
>  create mode 100644 drivers/media/platform/rockchip/isp1/regs.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/regs.h
>  create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.h
> 
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index fd0c99859d6f..062fffc9ffb6 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -117,6 +117,16 @@ config VIDEO_QCOM_CAMSS
>  	select VIDEOBUF2_DMA_SG
>  	select V4L2_FWNODE
>  
> +config VIDEO_ROCKCHIP_ISP1
> +	tristate "Rockchip Image Signal Processing v1 Unit driver"
> +	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
> +	depends on ARCH_ROCKCHIP || COMPILE_TEST
> +	select VIDEOBUF2_DMA_CONTIG
> +	select V4L2_FWNODE
> +	default n
> +	---help---
> +	  Support for ISP1 on the rockchip SoC.
> +
>  config VIDEO_S3C_CAMIF
>  	tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
>  	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> index 003b0bb2cddf..d235908df63e 100644
> --- a/drivers/media/platform/Makefile
> +++ b/drivers/media/platform/Makefile
> @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1)	+= rcar_fdp1.o
>  obj-$(CONFIG_VIDEO_RENESAS_JPU) 	+= rcar_jpu.o
>  obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1/
>  
> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1)	+= rockchip/isp1/
>  obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)	+= rockchip/rga/
>  
>  obj-y	+= omap/
> diff --git a/drivers/media/platform/rockchip/isp1/Makefile b/drivers/media/platform/rockchip/isp1/Makefile
> new file mode 100644
> index 000000000000..8f52f959398e
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/Makefile
> @@ -0,0 +1,7 @@
> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += 	video_rkisp1.o
> +video_rkisp1-objs 	   += 	rkisp1.o \
> +				dev.o \
> +				regs.o \
> +				isp_stats.o \
> +				isp_params.o \
> +				capture.o
> diff --git a/drivers/media/platform/rockchip/isp1/capture.c b/drivers/media/platform/rockchip/isp1/capture.c
> new file mode 100644
> index 000000000000..5e43b5420a45
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/capture.c
> @@ -0,0 +1,1684 @@

<snip>

> +static void rkisp1_destroy_dummy_buf(struct rkisp1_stream *stream)
> +{
> +	struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
> +	struct rkisp1_device *dev = stream->ispdev;
> +
> +	dma_free_coherent(dev->dev, dummy_buf->size,
> +			  dummy_buf->vaddr, dummy_buf->dma_addr);
> +}
> +
> +static void rkisp1_stop_streaming(struct vb2_queue *queue)
> +{
> +	struct rkisp1_stream *stream = queue->drv_priv;
> +	struct rkisp1_vdev_node *node = &stream->vnode;
> +	struct rkisp1_device *dev = stream->ispdev;
> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
> +	struct rkisp1_buffer *buf;
> +	unsigned long lock_flags = 0;
> +	int ret;
> +
> +	rkisp1_stream_stop(stream);
> +	/* call to the other devices */
> +	media_pipeline_stop(&node->vdev.entity);
> +	ret = dev->pipe.set_stream(&dev->pipe, false);
> +	if (ret < 0)
> +		return;

Shouldn't it release buffers in this error case as well? It's generally a
bad design if a close/release/stop-like function can return an error, after
all, what should you do with that?

> +
> +	/* release buffers */
> +	spin_lock_irqsave(&stream->vbq_lock, lock_flags);
> +	if (stream->curr_buf) {
> +		list_add_tail(&stream->curr_buf->queue, &stream->buf_queue);
> +		stream->curr_buf = NULL;
> +	}
> +	if (stream->next_buf) {
> +		list_add_tail(&stream->next_buf->queue, &stream->buf_queue);
> +		stream->next_buf = NULL;
> +	}
> +	while (!list_empty(&stream->buf_queue)) {
> +		buf = list_first_entry(&stream->buf_queue,
> +				       struct rkisp1_buffer, queue);
> +		list_del(&buf->queue);
> +		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> +	}
> +	spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
> +
> +	ret = dev->pipe.close(&dev->pipe);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret);
> +		return;

Same here, are you sure you can skip the rkisp1_destroy_dummy_buf call here?

> +	}
> +
> +	rkisp1_destroy_dummy_buf(stream);
> +}
> +
> +static int rkisp1_stream_start(struct rkisp1_stream *stream)
> +{
> +	struct v4l2_device *v4l2_dev = &stream->ispdev->v4l2_dev;
> +	int ret;
> +
> +	ret = rkisp1_config_rsz(stream, false);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "config rsz failed with error %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = rkisp1_config_dcrop(stream, false);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "config dcrop failed with error %d\n", ret);
> +		return ret;
> +	}
> +
> +	return rkisp1_start(stream);
> +}
> +
> +static int
> +rkisp1_start_streaming(struct vb2_queue *queue, unsigned int count)
> +{
> +	struct rkisp1_stream *stream = queue->drv_priv;
> +	struct rkisp1_vdev_node *node = &stream->vnode;
> +	struct rkisp1_device *dev = stream->ispdev;
> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
> +	int ret;
> +
> +	if (stream->state != RKISP1_STATE_READY) {
> +		v4l2_err(v4l2_dev, "stream %d in bad state(%d) for streaming\n",
> +			 stream->id, stream->state);
> +		return -EBUSY;

This feels like more of a WARN_ON to me. It should never happen, right?

> +	}
> +
> +	ret = rkisp1_create_dummy_buf(stream);
> +	if (ret < 0)
> +		return ret;

If start_streaming fails, then you need to return all buffers back to vb2 with
vb2_buffer_done(..., VB2_BUF_STATE_QUEUED). Just like in stop_streaming, but with
a different state. So please check all the error paths in this function.

> +
> +	/* enable clocks/power-domains */
> +	ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "open cif pipeline failed %d\n", ret);
> +		goto destroy_dummy_buf;
> +	}
> +
> +	/* configure stream hardware to start */
> +	ret = rkisp1_stream_start(stream);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "start streaming failed\n");
> +		goto close_pipe;
> +	}
> +
> +	/* start sub-devices */
> +	ret = dev->pipe.set_stream(&dev->pipe, true);
> +	if (ret < 0)
> +		goto stop_stream;
> +
> +	ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe);
> +	if (ret < 0) {
> +		v4l2_err(&dev->v4l2_dev, "start pipeline failed %d\n", ret);
> +		goto pipe_stream_off;
> +	}
> +
> +	return 0;
> +
> +pipe_stream_off:
> +	dev->pipe.set_stream(&dev->pipe, false);
> +stop_stream:
> +	rkisp1_stream_stop(stream);
> +close_pipe:
> +	dev->pipe.close(&dev->pipe);
> +destroy_dummy_buf:
> +	rkisp1_destroy_dummy_buf(stream);
> +
> +	return ret;
> +}
> +
> +static struct vb2_ops rkisp1_vb2_ops = {
> +	.queue_setup = rkisp1_queue_setup,
> +	.buf_queue = rkisp1_buf_queue,
> +	.wait_prepare = vb2_ops_wait_prepare,
> +	.wait_finish = vb2_ops_wait_finish,
> +	.stop_streaming = rkisp1_stop_streaming,
> +	.start_streaming = rkisp1_start_streaming,
> +};
> +
> +static int rkisp_init_vb2_queue(struct vb2_queue *q,
> +				struct rkisp1_stream *stream,
> +				enum v4l2_buf_type buf_type)
> +{
> +	struct rkisp1_vdev_node *node;
> +
> +	node = queue_to_node(q);
> +
> +	q->type = buf_type;
> +	q->io_modes = VB2_MMAP | VB2_DMABUF;
> +	q->drv_priv = stream;
> +	q->ops = &rkisp1_vb2_ops;
> +	q->mem_ops = &vb2_dma_contig_memops;
> +	q->buf_struct_size = sizeof(struct rkisp1_buffer);
> +	q->min_buffers_needed = CIF_ISP_REQ_BUFS_MIN;
> +	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
> +	q->lock = &node->vlock;
> +	q->dev = stream->ispdev->dev;
> +
> +	return vb2_queue_init(q);
> +}
> +
> +static void rkisp1_set_fmt(struct rkisp1_stream *stream,
> +			   struct v4l2_pix_format_mplane *pixm,
> +			   bool try)
> +{
> +	const struct capture_fmt *fmt;
> +	const struct stream_config *config = stream->config;
> +	struct rkisp1_stream *other_stream =
> +			&stream->ispdev->stream[!stream->id];
> +	unsigned int imagsize = 0;
> +	unsigned int planes;
> +	u32 xsubs = 1, ysubs = 1;
> +	int i;
> +
> +	fmt = find_fmt(stream, pixm->pixelformat);
> +	if (!fmt)
> +		fmt = config->fmts;
> +
> +	/* do checks on resolution */
> +	pixm->width = clamp_t(u32, pixm->width, config->min_rsz_width,
> +			      config->max_rsz_width);
> +	pixm->height = clamp_t(u32, pixm->height, config->min_rsz_height,
> +			      config->max_rsz_height);
> +	pixm->num_planes = fmt->mplanes;
> +	pixm->field = V4L2_FIELD_NONE;
> +
> +	/* output full range by default, take effect in isp_params */
> +	if (!pixm->quantization)
> +		pixm->quantization = V4L2_QUANTIZATION_FULL_RANGE;
> +	/* can not change quantization when stream-on */
> +	if (other_stream->state == RKISP1_STATE_STREAMING)
> +		pixm->quantization = other_stream->out_fmt.quantization;
> +
> +	/* calculate size */
> +	fcc_xysubs(fmt->fourcc, &xsubs, &ysubs);
> +	planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes;
> +	for (i = 0; i < planes; i++) {
> +		struct v4l2_plane_pix_format *plane_fmt;
> +		int width, height, bytesperline;
> +
> +		plane_fmt = pixm->plane_fmt + i;
> +
> +		if (i == 0) {
> +			width = pixm->width;
> +			height = pixm->height;
> +		} else {
> +			width = pixm->width / xsubs;
> +			height = pixm->height / ysubs;
> +		}
> +
> +		bytesperline = width * DIV_ROUND_UP(fmt->bpp[i], 8);
> +		/* stride is only available for sp stream and y plane */
> +		if (stream->id != RKISP1_STREAM_SP || i != 0 ||
> +		    plane_fmt->bytesperline < bytesperline)
> +			plane_fmt->bytesperline = bytesperline;
> +
> +		plane_fmt->sizeimage = plane_fmt->bytesperline * height;
> +
> +		imagsize += plane_fmt->sizeimage;
> +	}
> +
> +	/* convert to non-MPLANE format.
> +	 * it's important since we want to unify none-MPLANE
> +	 * and MPLANE.
> +	 */
> +	if (fmt->mplanes == 1)
> +		pixm->plane_fmt[0].sizeimage = imagsize;
> +
> +	if (!try) {
> +		stream->out_isp_fmt = *fmt;
> +		stream->out_fmt = *pixm;
> +
> +		if (stream->id == RKISP1_STREAM_SP) {
> +			stream->u.sp.y_stride =
> +				pixm->plane_fmt[0].bytesperline /
> +				DIV_ROUND_UP(fmt->bpp[0], 8);
> +		} else {
> +			stream->u.mp.raw_enable = (fmt->fmt_type == FMT_BAYER);
> +		}
> +		v4l2_dbg(1, rkisp1_debug, &stream->ispdev->v4l2_dev,
> +			 "%s: stream: %d req(%d, %d) out(%d, %d)\n", __func__,
> +			 stream->id, pixm->width, pixm->height,
> +			 stream->out_fmt.width, stream->out_fmt.height);
> +
> +		/* set quantization to isp_params */
> +		rkisp1_configure_isp(NULL, NULL, pixm->quantization);
> +	}
> +}
> +
> +/************************* v4l2_file_operations***************************/
> +void rkisp1_stream_init(struct rkisp1_device *dev, u32 id)
> +{
> +	struct rkisp1_stream *stream = &dev->stream[id];
> +	struct v4l2_pix_format_mplane pixm;
> +
> +	memset(stream, 0, sizeof(*stream));
> +	stream->id = id;
> +	stream->ispdev = dev;
> +
> +	INIT_LIST_HEAD(&stream->buf_queue);
> +	init_waitqueue_head(&stream->done);
> +	spin_lock_init(&stream->vbq_lock);
> +	if (stream->id == RKISP1_STREAM_SP) {
> +		stream->ops = &rkisp1_sp_streams_ops;
> +		stream->config = &rkisp1_sp_stream_config;
> +	} else {
> +		stream->ops = &rkisp1_mp_streams_ops;
> +		stream->config = &rkisp1_mp_stream_config;
> +	}
> +
> +	stream->state = RKISP1_STATE_READY;
> +
> +	memset(&pixm, 0, sizeof(pixm));
> +	pixm.pixelformat = V4L2_PIX_FMT_YUYV;
> +	pixm.width = RKISP1_DEFAULT_WIDTH;
> +	pixm.height = RKISP1_DEFAULT_HEIGHT;
> +	rkisp1_set_fmt(stream, &pixm, false);
> +
> +	stream->dcrop.left = 0;
> +	stream->dcrop.top = 0;
> +	stream->dcrop.width = RKISP1_DEFAULT_WIDTH;
> +	stream->dcrop.height = RKISP1_DEFAULT_HEIGHT;
> +}
> +
> +static const struct v4l2_file_operations rkisp1_fops = {
> +	.open = v4l2_fh_open,
> +	.release = vb2_fop_release,
> +	.unlocked_ioctl = video_ioctl2,
> +	.poll = vb2_fop_poll,
> +	.mmap = vb2_fop_mmap,
> +};
> +
> +/*
> + * mp and sp v4l2_ioctl_ops
> + */
> +
> +/* keep for compatibility */
> +static int rkisp1_enum_input(struct file *file, void *priv,
> +			     struct v4l2_input *input)
> +{
> +	if (input->index > 0)
> +		return -EINVAL;
> +

Please fill in v4l2_input.

> +	return 0;
> +}
> +
> +static int rkisp1_try_fmt_vid_cap_mplane(struct file *file, void *fh,
> +					 struct v4l2_format *f)
> +{
> +	struct rkisp1_stream *stream = video_drvdata(file);
> +
> +	rkisp1_set_fmt(stream, &f->fmt.pix_mp, true);
> +
> +	return 0;
> +}
> +
> +static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
> +					  struct v4l2_fmtdesc *f)
> +{
> +	struct rkisp1_stream *stream = video_drvdata(file);
> +	const struct capture_fmt *fmt = NULL;
> +
> +	if (f->index >= stream->config->fmt_size)
> +		return -EINVAL;
> +
> +	fmt = &stream->config->fmts[f->index];
> +	f->pixelformat = fmt->fourcc;
> +
> +	return 0;
> +}
> +
> +static int rkisp1_s_fmt_vid_cap_mplane(struct file *file,
> +				       void *priv, struct v4l2_format *f)
> +{
> +	struct rkisp1_stream *stream = video_drvdata(file);
> +	struct video_device *vdev = &stream->vnode.vdev;
> +	struct rkisp1_vdev_node *node = vdev_to_node(vdev);
> +	struct rkisp1_device *dev = stream->ispdev;
> +
> +	if (vb2_is_busy(&node->buf_queue)) {
> +		v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
> +		return -EBUSY;
> +	}
> +
> +	rkisp1_set_fmt(stream, &f->fmt.pix_mp, false);
> +
> +	return 0;
> +}
> +
> +static int rkisp1_g_fmt_vid_cap_mplane(struct file *file, void *fh,
> +				       struct v4l2_format *f)
> +{
> +	struct rkisp1_stream *stream = video_drvdata(file);
> +
> +	f->fmt.pix_mp = stream->out_fmt;
> +
> +	return 0;
> +}
> +
> +static int rkisp1_g_selection(struct file *file, void *prv,
> +			      struct v4l2_selection *sel)
> +{
> +	struct rkisp1_stream *stream = video_drvdata(file);
> +	struct rkisp1_device *dev = stream->ispdev;
> +	struct v4l2_rect *dcrop = &stream->dcrop;
> +	struct v4l2_rect *input_win;
> +
> +	input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
> +
> +	switch (sel->target) {
> +	case V4L2_SEL_TGT_CROP_BOUNDS:
> +		sel->r.width = input_win->width;
> +		sel->r.height = input_win->height;
> +		sel->r.left = 0;
> +		sel->r.top = 0;
> +		break;
> +	case V4L2_SEL_TGT_CROP:
> +		sel->r = *dcrop;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct v4l2_rect *rkisp1_update_crop(struct rkisp1_stream *stream,
> +					    struct v4l2_rect *sel,
> +					    const struct v4l2_rect *in)
> +{
> +	/* Not crop for MP bayer raw data */
> +	if (stream->id == RKISP1_STREAM_MP &&
> +	    stream->out_isp_fmt.fmt_type == FMT_BAYER) {
> +		sel->left = 0;
> +		sel->top = 0;
> +		sel->width = in->width;
> +		sel->height = in->height;
> +		return sel;
> +	}
> +
> +	sel->left = ALIGN(sel->left, 2);
> +	sel->width = ALIGN(sel->width, 2);
> +	sel->left = clamp_t(u32, sel->left, 0,
> +			    in->width - STREAM_MIN_MP_SP_INPUT_WIDTH);
> +	sel->top = clamp_t(u32, sel->top, 0,
> +			   in->height - STREAM_MIN_MP_SP_INPUT_HEIGHT);
> +	sel->width = clamp_t(u32, sel->width, STREAM_MIN_MP_SP_INPUT_WIDTH,
> +			     in->width - sel->left);
> +	sel->height = clamp_t(u32, sel->height, STREAM_MIN_MP_SP_INPUT_HEIGHT,
> +			      in->height - sel->top);
> +	return sel;
> +}
> +
> +static int rkisp1_s_selection(struct file *file, void *prv,
> +			      struct v4l2_selection *sel)
> +{
> +	struct rkisp1_stream *stream = video_drvdata(file);
> +	struct rkisp1_device *dev = stream->ispdev;
> +	struct v4l2_rect *dcrop = &stream->dcrop;
> +	const struct v4l2_rect *input_win;
> +

You probably need a vb2_is_busy() call here. Normally you cannot change the selection
while streaming.

> +	input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
> +
> +	if (sel->target != V4L2_SEL_TGT_CROP)
> +		return -EINVAL;
> +
> +	if (sel->flags != 0)
> +		return -EINVAL;
> +
> +	if (sel->target == V4L2_SEL_TGT_CROP) {
> +		*dcrop = *rkisp1_update_crop(stream, &sel->r, input_win);
> +		v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> +			 "stream %d crop(%d,%d)/%dx%d\n", stream->id,
> +			 dcrop->left, dcrop->top, dcrop->width, dcrop->height);
> +	}
> +
> +	return 0;
> +}
> +
> +static int rkisp1_querycap(struct file *file, void *priv,
> +			   struct v4l2_capability *cap)
> +{
> +	struct rkisp1_stream *stream = video_drvdata(file);
> +	struct device *dev = stream->ispdev->dev;
> +
> +	strlcpy(cap->driver, dev->driver->name, sizeof(cap->driver));
> +	strlcpy(cap->card, dev->driver->name, sizeof(cap->card));
> +	snprintf(cap->bus_info, sizeof(cap->bus_info),
> +		 "platform:%s", dev_name(dev));
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ioctl_ops rkisp1_v4l2_ioctl_ops = {
> +	.vidioc_reqbufs = vb2_ioctl_reqbufs,
> +	.vidioc_querybuf = vb2_ioctl_querybuf,
> +	.vidioc_create_bufs = vb2_ioctl_create_bufs,
> +	.vidioc_qbuf = vb2_ioctl_qbuf,
> +	.vidioc_expbuf = vb2_ioctl_expbuf,
> +	.vidioc_dqbuf = vb2_ioctl_dqbuf,
> +	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
> +	.vidioc_streamon = vb2_ioctl_streamon,
> +	.vidioc_streamoff = vb2_ioctl_streamoff,
> +	.vidioc_enum_input = rkisp1_enum_input,
> +	.vidioc_try_fmt_vid_cap_mplane = rkisp1_try_fmt_vid_cap_mplane,
> +	.vidioc_enum_fmt_vid_cap_mplane = rkisp1_enum_fmt_vid_cap_mplane,
> +	.vidioc_s_fmt_vid_cap_mplane = rkisp1_s_fmt_vid_cap_mplane,
> +	.vidioc_g_fmt_vid_cap_mplane = rkisp1_g_fmt_vid_cap_mplane,
> +	.vidioc_s_selection = rkisp1_s_selection,
> +	.vidioc_g_selection = rkisp1_g_selection,
> +	.vidioc_querycap = rkisp1_querycap,
> +};
> +
> +static void rkisp1_unregister_stream_vdev(struct rkisp1_stream *stream)
> +{
> +	media_entity_cleanup(&stream->vnode.vdev.entity);
> +	video_unregister_device(&stream->vnode.vdev);
> +}
> +
> +void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev)
> +{
> +	struct rkisp1_stream *mp_stream = &dev->stream[RKISP1_STREAM_MP];
> +	struct rkisp1_stream *sp_stream = &dev->stream[RKISP1_STREAM_SP];
> +
> +	rkisp1_unregister_stream_vdev(mp_stream);
> +	rkisp1_unregister_stream_vdev(sp_stream);
> +}
> +
> +static int rkisp1_register_stream_vdev(struct rkisp1_stream *stream)
> +{
> +	struct rkisp1_device *dev = stream->ispdev;
> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
> +	struct video_device *vdev = &stream->vnode.vdev;
> +	struct rkisp1_vdev_node *node;
> +	int ret;
> +
> +	strlcpy(vdev->name,
> +		stream->id == RKISP1_STREAM_SP ? SP_VDEV_NAME : MP_VDEV_NAME,
> +		sizeof(vdev->name));
> +	node = vdev_to_node(vdev);
> +	mutex_init(&node->vlock);
> +
> +	vdev->ioctl_ops = &rkisp1_v4l2_ioctl_ops;
> +	vdev->release = video_device_release_empty;
> +	vdev->fops = &rkisp1_fops;
> +	vdev->minor = -1;
> +	vdev->v4l2_dev = v4l2_dev;
> +	vdev->lock = &node->vlock;
> +	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
> +				V4L2_CAP_STREAMING;
> +	video_set_drvdata(vdev, stream);
> +	vdev->vfl_dir = VFL_DIR_RX;
> +	node->pad.flags = MEDIA_PAD_FL_SINK;
> +
> +	rkisp_init_vb2_queue(&node->buf_queue, stream,
> +			     V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
> +	vdev->queue = &node->buf_queue;
> +
> +	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev,
> +			 "video_register_device failed with error %d\n", ret);
> +		return ret;
> +	}
> +
> +	vdev->entity.function = MEDIA_ENT_F_IO_V4L;
> +	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
> +	if (ret < 0)
> +		goto unreg;
> +
> +	return 0;
> +unreg:
> +	video_unregister_device(vdev);
> +	return ret;
> +}
> +
> +int rkisp1_register_stream_vdevs(struct rkisp1_device *dev)
> +{
> +	struct rkisp1_stream *stream;
> +	int i, j, ret;
> +
> +	for (i = 0; i < RKISP1_MAX_STREAM; i++) {
> +		stream = &dev->stream[i];
> +		stream->ispdev = dev;
> +		ret = rkisp1_register_stream_vdev(stream);
> +		if (ret < 0)
> +			goto err;
> +	}
> +
> +	return 0;
> +err:
> +	for (j = 0; j < i; j++) {
> +		stream = &dev->stream[j];
> +		rkisp1_unregister_stream_vdev(stream);
> +	}
> +
> +	return ret;
> +}
> +
> +/****************  Interrupter Handler ****************/
> +
> +void rkisp1_mi_isr(struct rkisp1_stream *stream)
> +{
> +	struct rkisp1_device *dev = stream->ispdev;
> +	void __iomem *base = stream->ispdev->base_addr;
> +	u32 val;
> +
> +	stream->ops->clr_frame_end_int(base);
> +	if (stream->ops->is_frame_end_int_masked(base)) {
> +		val = mi_get_masked_int_status(base);
> +		v4l2_err(&dev->v4l2_dev, "icr err: 0x%x\n", val);
> +	}
> +
> +	if (stream->stopping) {
> +		/* Make sure stream is actually stopped, whose state
> +		 * can be read from the shadow register, before wake_up()
> +		 * thread which would immediately free all frame buffers.
> +		 * stop_mi() takes effect at the next frame end
> +		 * that sync the configurations to shadow regs.
> +		 */
> +		if (stream->ops->is_stream_stopped(dev->base_addr)) {
> +			stream->stopping = false;
> +			stream->state = RKISP1_STATE_READY;
> +			wake_up(&stream->done);
> +		} else {
> +			stream->ops->stop_mi(stream);
> +		}
> +	} else {
> +		mi_frame_end(stream);
> +	}
> +}
> diff --git a/drivers/media/platform/rockchip/isp1/capture.h b/drivers/media/platform/rockchip/isp1/capture.h
> new file mode 100644
> index 000000000000..f0989103daa1
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/capture.h
> @@ -0,0 +1,194 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef _RKISP1_PATH_VIDEO_H
> +#define _RKISP1_PATH_VIDEO_H
> +
> +#include "common.h"
> +
> +struct rkisp1_stream;
> +
> +/*
> + * @fourcc: pixel format
> + * @mbus_code: pixel format over bus
> + * @fmt_type: helper filed for pixel format
> + * @bpp: bits per pixel
> + * @bayer_pat: bayer patten type
> + * @cplanes: number of colour planes
> + * @mplanes: number of stored memory planes
> + * @uv_swap: if cb cr swaped, for yuv
> + * @write_format: defines how YCbCr self picture data is written to memory
> + * @input_format: defines sp input format
> + * @output_format: defines sp output format
> + */
> +struct capture_fmt {
> +	u32 fourcc;
> +	u32 mbus_code;
> +	u8 fmt_type;
> +	u8 cplanes;
> +	u8 mplanes;
> +	u8 uv_swap;
> +	u32 write_format;
> +	u32 output_format;
> +	u8 bpp[VIDEO_MAX_PLANES];
> +};
> +
> +enum rkisp1_sp_inp {
> +	RKISP1_SP_INP_ISP,
> +	RKISP1_SP_INP_DMA_SP,
> +	RKISP1_SP_INP_MAX
> +};
> +
> +struct rkisp1_stream_sp {
> +	int y_stride;
> +	enum rkisp1_sp_inp input_sel;
> +};
> +
> +struct rkisp1_stream_mp {
> +	bool raw_enable;
> +};
> +
> +/* Different config between selfpath and mainpath */
> +struct stream_config {
> +	const struct capture_fmt *fmts;
> +	int fmt_size;
> +	/* constrains */
> +	const int max_rsz_width;
> +	const int max_rsz_height;
> +	const int min_rsz_width;
> +	const int min_rsz_height;
> +	/* registers */
> +	struct {
> +		u32 ctrl;
> +		u32 ctrl_shd;
> +		u32 scale_hy;
> +		u32 scale_hcr;
> +		u32 scale_hcb;
> +		u32 scale_vy;
> +		u32 scale_vc;
> +		u32 scale_lut;
> +		u32 scale_lut_addr;
> +		u32 scale_hy_shd;
> +		u32 scale_hcr_shd;
> +		u32 scale_hcb_shd;
> +		u32 scale_vy_shd;
> +		u32 scale_vc_shd;
> +		u32 phase_hy;
> +		u32 phase_hc;
> +		u32 phase_vy;
> +		u32 phase_vc;
> +		u32 phase_hy_shd;
> +		u32 phase_hc_shd;
> +		u32 phase_vy_shd;
> +		u32 phase_vc_shd;
> +	} rsz;
> +	struct {
> +		u32 ctrl;
> +		u32 yuvmode_mask;
> +		u32 rawmode_mask;
> +		u32 h_offset;
> +		u32 v_offset;
> +		u32 h_size;
> +		u32 v_size;
> +	} dual_crop;
> +	struct {
> +		u32 y_size_init;
> +		u32 cb_size_init;
> +		u32 cr_size_init;
> +		u32 y_base_ad_init;
> +		u32 cb_base_ad_init;
> +		u32 cr_base_ad_init;
> +		u32 y_offs_cnt_init;
> +		u32 cb_offs_cnt_init;
> +		u32 cr_offs_cnt_init;
> +	} mi;
> +};
> +
> +/* Different reg ops between selfpath and mainpath */
> +struct streams_ops {
> +	int (*config_mi)(struct rkisp1_stream *stream);
> +	void (*stop_mi)(struct rkisp1_stream *stream);
> +	void (*enable_mi)(struct rkisp1_stream *stream);
> +	void (*disable_mi)(struct rkisp1_stream *stream);
> +	void (*set_data_path)(void __iomem *base);
> +	void (*clr_frame_end_int)(void __iomem *base);
> +	bool (*is_frame_end_int_masked)(void __iomem *base);
> +	bool (*is_stream_stopped)(void __iomem *base);
> +};
> +
> +/*
> + * struct rkisp1_stream - ISP capture video device
> + *
> + * @out_isp_fmt: output isp format
> + * @out_fmt: output buffer size
> + * @dcrop: coordinates of dual-crop
> + *
> + * @vbq_lock: lock to protect buf_queue
> + * @buf_queue: queued buffer list
> + * @dummy_buf: dummy space to store dropped data
> + *
> + * rkisp1 use shadowsock registers, so it need two buffer at a time
> + * @curr_buf: the buffer used for current frame
> + * @next_buf: the buffer used for next frame
> + */
> +struct rkisp1_stream {
> +	u32 id;
> +	struct rkisp1_device *ispdev;
> +	struct rkisp1_vdev_node vnode;
> +	enum rkisp1_state state;
> +	enum rkisp1_state saved_state;
> +	struct capture_fmt out_isp_fmt;
> +	struct v4l2_pix_format_mplane out_fmt;
> +	struct v4l2_rect dcrop;
> +	struct streams_ops *ops;
> +	struct stream_config *config;
> +	spinlock_t vbq_lock;
> +	struct list_head buf_queue;
> +	struct rkisp1_dummy_buffer dummy_buf;
> +	struct rkisp1_buffer *curr_buf;
> +	struct rkisp1_buffer *next_buf;
> +	bool stopping;
> +	wait_queue_head_t done;
> +	union {
> +		struct rkisp1_stream_sp sp;
> +		struct rkisp1_stream_mp mp;
> +	} u;
> +};
> +
> +void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev);
> +int rkisp1_register_stream_vdevs(struct rkisp1_device *dev);
> +void rkisp1_mi_isr(struct rkisp1_stream *stream);
> +void rkisp1_stream_init(struct rkisp1_device *dev, u32 id);
> +
> +#endif /* _RKISP1_PATH_VIDEO_H */
> diff --git a/drivers/media/platform/rockchip/isp1/common.h b/drivers/media/platform/rockchip/isp1/common.h
> new file mode 100644
> index 000000000000..1adfb9039b60
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/common.h
> @@ -0,0 +1,137 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef _RKISP1_COMMON_H
> +#define _RKISP1_COMMON_H
> +
> +#include <linux/mutex.h>
> +#include <media/media-device.h>
> +#include <media/media-entity.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-device.h>
> +#include <media/videobuf2-v4l2.h>
> +
> +#define RKISP1_DEFAULT_WIDTH		800
> +#define RKISP1_DEFAULT_HEIGHT		600
> +
> +#define RKISP1_MAX_STREAM		2
> +#define RKISP1_STREAM_SP		0
> +#define RKISP1_STREAM_MP		1
> +
> +#define RKISP1_PLANE_Y			0
> +#define RKISP1_PLANE_CB			1
> +#define RKISP1_PLANE_CR			2
> +
> +enum rkisp1_sd_type {
> +	RKISP1_SD_SENSOR,
> +	RKISP1_SD_PHY_CSI,
> +	RKISP1_SD_VCM,
> +	RKISP1_SD_FLASH,
> +	RKISP1_SD_MAX,
> +};
> +
> +/* One structure per video node */
> +struct rkisp1_vdev_node {
> +	struct vb2_queue buf_queue;
> +	/* vfd lock */
> +	struct mutex vlock;
> +	struct video_device vdev;
> +	struct media_pad pad;
> +};
> +
> +enum rkisp1_fmt_pix_type {
> +	FMT_YUV,
> +	FMT_RGB,
> +	FMT_BAYER,
> +	FMT_JPEG,
> +	FMT_MAX
> +};
> +
> +enum rkisp1_fmt_raw_pat_type {
> +	RAW_RGGB = 0,
> +	RAW_GRBG,
> +	RAW_GBRG,
> +	RAW_BGGR,
> +};
> +
> +enum rkisp1_state {
> +	/* path not yet opened: */
> +	RKISP1_STATE_DISABLED,
> +	/* path opened and configured, ready for streaming: */
> +	RKISP1_STATE_READY,
> +	/* path is streaming: */
> +	RKISP1_STATE_STREAMING
> +};
> +
> +struct rkisp1_buffer {
> +	struct vb2_v4l2_buffer vb;
> +	struct list_head queue;
> +	union {
> +		u32 buff_addr[VIDEO_MAX_PLANES];
> +		void *vaddr[VIDEO_MAX_PLANES];
> +	};
> +};
> +
> +struct rkisp1_dummy_buffer {
> +	void *vaddr;
> +	dma_addr_t dma_addr;
> +	u32 size;
> +};
> +
> +extern int rkisp1_debug;
> +
> +static inline
> +struct rkisp1_vdev_node *vdev_to_node(struct video_device *vdev)
> +{
> +	return container_of(vdev, struct rkisp1_vdev_node, vdev);
> +}
> +
> +static inline struct rkisp1_vdev_node *queue_to_node(struct vb2_queue *q)
> +{
> +	return container_of(q, struct rkisp1_vdev_node, buf_queue);
> +}
> +
> +static inline struct rkisp1_buffer *to_rkisp1_buffer(struct vb2_v4l2_buffer *vb)
> +{
> +	return container_of(vb, struct rkisp1_buffer, vb);
> +}
> +
> +static inline struct vb2_queue *to_vb2_queue(struct file *file)
> +{
> +	struct rkisp1_vdev_node *vnode = video_drvdata(file);
> +
> +	return &vnode->buf_queue;
> +}
> +
> +#endif /* _RKISP1_COMMON_H */
> diff --git a/drivers/media/platform/rockchip/isp1/dev.c b/drivers/media/platform/rockchip/isp1/dev.c
> new file mode 100644
> index 000000000000..025aa3a019a8
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/dev.c
> @@ -0,0 +1,655 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/pinctrl/consumer.h>
> +#include "common.h"
> +#include "regs.h"
> +
> +struct isp_match_data {
> +	const char * const *clks;
> +	int size;
> +};
> +
> +int rkisp1_debug;
> +module_param_named(debug, rkisp1_debug, int, 0644);
> +MODULE_PARM_DESC(debug, "Debug level (0-1)");
> +
> +/***************************** pipeline operations*******************************/
> +
> +static int __isp_pipeline_prepare(struct rkisp1_pipeline *p,
> +				  struct media_entity *me)
> +{
> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> +	struct v4l2_subdev *sd;
> +	int i;
> +
> +	p->num_subdevs = 0;
> +	memset(p->subdevs, 0, sizeof(p->subdevs));
> +
> +	while (1) {
> +		struct media_pad *pad = NULL;
> +
> +		/* Find remote source pad */
> +		for (i = 0; i < me->num_pads; i++) {
> +			struct media_pad *spad = &me->pads[i];
> +
> +			if (!(spad->flags & MEDIA_PAD_FL_SINK))
> +				continue;
> +			pad = media_entity_remote_pad(spad);
> +			if (pad)
> +				break;
> +		}
> +
> +		if (!pad)
> +			break;
> +
> +		sd = media_entity_to_v4l2_subdev(pad->entity);
> +		if (sd != &dev->isp_sdev.sd)
> +			p->subdevs[p->num_subdevs++] = sd;
> +
> +		me = &sd->entity;
> +		if (me->num_pads == 1)
> +			break;
> +	}
> +	return 0;
> +}
> +
> +static int __subdev_set_power(struct v4l2_subdev *sd, int on)
> +{
> +	int ret;
> +
> +	if (!sd)
> +		return -ENXIO;
> +
> +	ret = v4l2_subdev_call(sd, core, s_power, on);
> +
> +	return ret != -ENOIOCTLCMD ? ret : 0;
> +}
> +
> +static int __isp_pipeline_s_power(struct rkisp1_pipeline *p, bool on)
> +{
> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> +	int i, ret;
> +
> +	if (on) {
> +		__subdev_set_power(&dev->isp_sdev.sd, true);
> +
> +		for (i = p->num_subdevs - 1; i >= 0; --i) {
> +			ret = __subdev_set_power(p->subdevs[i], true);
> +			if (ret < 0 && ret != -ENXIO)
> +				goto err_power_off;
> +		}
> +	} else {
> +		for (i = 0; i < p->num_subdevs; ++i)
> +			__subdev_set_power(p->subdevs[i], false);
> +
> +		__subdev_set_power(&dev->isp_sdev.sd, false);
> +	}
> +
> +	return 0;
> +
> +err_power_off:
> +	for (++i; i < p->num_subdevs; ++i)
> +		__subdev_set_power(p->subdevs[i], false);
> +	__subdev_set_power(&dev->isp_sdev.sd, true);
> +	return ret;
> +}
> +
> +static int rkisp1_pipeline_open(struct rkisp1_pipeline *p,
> +				struct media_entity *me,
> +				bool prepare)
> +{
> +	int ret;
> +
> +	if (WARN_ON(!p || !me))
> +		return -EINVAL;
> +	if (atomic_inc_return(&p->power_cnt) > 1)
> +		return 0;
> +
> +	/* go through media graphic and get subdevs */
> +	if (prepare)
> +		__isp_pipeline_prepare(p, me);
> +
> +	if (!p->num_subdevs)
> +		return -EINVAL;
> +
> +	ret = __isp_pipeline_s_power(p, 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int rkisp1_pipeline_close(struct rkisp1_pipeline *p)
> +{
> +	int ret;
> +
> +	if (atomic_dec_return(&p->power_cnt) > 0)
> +		return 0;
> +	ret = __isp_pipeline_s_power(p, 0);
> +
> +	return ret == -ENXIO ? 0 : ret;
> +}
> +
> +/*
> + * stream-on order: isp_subdev, mipi dphy, sensor
> + * stream-off order: mipi dphy, sensor, isp_subdev
> + */
> +static int rkisp1_pipeline_set_stream(struct rkisp1_pipeline *p, bool on)
> +{
> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> +	int i, ret;
> +
> +	if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
> +	    (!on && atomic_dec_return(&p->stream_cnt) > 0))
> +		return 0;
> +
> +	if (on)
> +		v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, true);
> +
> +	/* phy -> sensor */
> +	for (i = 0; i < p->num_subdevs; ++i) {
> +		ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
> +		if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
> +			goto err_stream_off;
> +	}
> +
> +	if (!on)
> +		v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
> +
> +	return 0;
> +
> +err_stream_off:
> +	for (--i; i >= 0; --i)
> +		v4l2_subdev_call(p->subdevs[i], video, s_stream, false);
> +	v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
> +	return ret;
> +}
> +
> +/***************************** media controller *******************************/
> +/* See http://opensource.rock-chips.com/wiki_Rockchip-isp1 for Topology */
> +
> +static int rkisp1_create_links(struct rkisp1_device *dev)
> +{
> +	struct media_entity *source, *sink;
> +	unsigned int flags, s, pad;
> +	int ret;
> +
> +	/* sensor links(or mipi-phy) */
> +	for (s = 0; s < dev->num_sensors; ++s) {
> +		struct rkisp1_sensor_info *sensor = &dev->sensors[s];
> +
> +		for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
> +			if (sensor->sd->entity.pads[pad].flags &
> +				MEDIA_PAD_FL_SOURCE)
> +				break;
> +
> +		if (pad == sensor->sd->entity.num_pads) {
> +			dev_err(dev->dev,
> +				"failed to find src pad for %s\n",
> +				sensor->sd->name);
> +
> +			return -ENXIO;
> +		}
> +
> +		ret = media_create_pad_link(
> +				&sensor->sd->entity, pad,
> +				&dev->isp_sdev.sd.entity,
> +				RKISP1_ISP_PAD_SINK + s,
> +				s ? 0 : MEDIA_LNK_FL_ENABLED);
> +		if (ret) {
> +			dev_err(dev->dev,
> +				"failed to create link for %s\n",
> +				sensor->sd->name);
> +			return ret;
> +		}
> +	}
> +
> +	/* params links */
> +	source = &dev->params_vdev.vnode.vdev.entity;
> +	sink = &dev->isp_sdev.sd.entity;
> +	flags = MEDIA_LNK_FL_ENABLED;
> +	ret = media_create_pad_link(source, 0, sink,
> +				       RKISP1_ISP_PAD_SINK_PARAMS, flags);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* create isp internal links */
> +	/* SP links */
> +	source = &dev->isp_sdev.sd.entity;
> +	sink = &dev->stream[RKISP1_STREAM_SP].vnode.vdev.entity;
> +	ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
> +				       sink, 0, flags);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* MP links */
> +	source = &dev->isp_sdev.sd.entity;
> +	sink = &dev->stream[RKISP1_STREAM_MP].vnode.vdev.entity;
> +	ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
> +				       sink, 0, flags);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* 3A stats links */
> +	source = &dev->isp_sdev.sd.entity;
> +	sink = &dev->stats_vdev.vnode.vdev.entity;
> +	return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS,
> +					sink, 0, flags);
> +}
> +
> +static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
> +{
> +	struct rkisp1_device *dev;
> +	int ret;
> +
> +	dev = container_of(notifier, struct rkisp1_device, notifier);
> +
> +	mutex_lock(&dev->media_dev.graph_mutex);
> +	ret = rkisp1_create_links(dev);
> +	if (ret < 0)
> +		goto unlock;
> +	ret = v4l2_device_register_subdev_nodes(&dev->v4l2_dev);
> +	if (ret < 0)
> +		goto unlock;
> +
> +	v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n");
> +
> +unlock:
> +	mutex_unlock(&dev->media_dev.graph_mutex);
> +	return ret;
> +}
> +
> +struct rkisp1_async_subdev {
> +	struct v4l2_async_subdev asd;
> +	struct v4l2_mbus_config mbus;
> +};
> +
> +static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
> +				 struct v4l2_subdev *subdev,
> +				 struct v4l2_async_subdev *asd)
> +{
> +	struct rkisp1_device *isp_dev = container_of(notifier,
> +					struct rkisp1_device, notifier);
> +	struct rkisp1_async_subdev *s_asd = container_of(asd,
> +					struct rkisp1_async_subdev, asd);
> +
> +	if (isp_dev->num_sensors == ARRAY_SIZE(isp_dev->sensors))
> +		return -EBUSY;
> +
> +	isp_dev->sensors[isp_dev->num_sensors].mbus = s_asd->mbus;
> +	isp_dev->sensors[isp_dev->num_sensors].sd = subdev;
> +	++isp_dev->num_sensors;
> +
> +	v4l2_dbg(1, rkisp1_debug, subdev, "Async registered subdev\n");
> +
> +	return 0;
> +}
> +
> +static int rkisp1_fwnode_parse(struct device *dev,
> +			       struct v4l2_fwnode_endpoint *vep,
> +			       struct v4l2_async_subdev *asd)
> +{
> +	struct rkisp1_async_subdev *rk_asd =
> +			container_of(asd, struct rkisp1_async_subdev, asd);
> +	struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel;
> +
> +	/*
> +	 * MIPI sensor is linked with a mipi dphy and its media bus config can
> +	 * not be get in here
> +	 */
> +	if (vep->bus_type != V4L2_MBUS_BT656 &&
> +		vep->bus_type != V4L2_MBUS_PARALLEL)
> +		return 0;
> +
> +	rk_asd->mbus.flags = bus->flags;
> +	rk_asd->mbus.type = vep->bus_type;
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
> +	.bound = subdev_notifier_bound,
> +	.complete = subdev_notifier_complete,
> +};
> +
> +static int isp_subdev_notifier(struct rkisp1_device *isp_dev)
> +{
> +	struct v4l2_async_notifier *ntf = &isp_dev->notifier;
> +	struct device *dev = isp_dev->dev;
> +	int ret;
> +
> +	ret = v4l2_async_notifier_parse_fwnode_endpoints(
> +		dev, ntf, sizeof(struct rkisp1_async_subdev),
> +		rkisp1_fwnode_parse);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (!ntf->num_subdevs)
> +		return -ENODEV;	/* no endpoint */
> +
> +	ntf->ops = &subdev_notifier_ops;
> +
> +	return v4l2_async_notifier_register(&isp_dev->v4l2_dev, ntf);
> +}
> +
> +/***************************** platform deive *******************************/
> +
> +static int rkisp1_register_platform_subdevs(struct rkisp1_device *dev)
> +{
> +	int ret;
> +
> +	ret = rkisp1_register_isp_subdev(dev, &dev->v4l2_dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = rkisp1_register_stream_vdevs(dev);
> +	if (ret < 0)
> +		goto err_unreg_isp_subdev;
> +
> +	ret = rkisp1_register_stats_vdev(&dev->stats_vdev, &dev->v4l2_dev, dev);
> +	if (ret < 0)
> +		goto err_unreg_stream_vdev;
> +
> +	ret = rkisp1_register_params_vdev(&dev->params_vdev, &dev->v4l2_dev,
> +					  dev);
> +	if (ret < 0)
> +		goto err_unreg_stats_vdev;
> +
> +	ret = isp_subdev_notifier(dev);
> +	if (ret < 0) {
> +		v4l2_err(&dev->v4l2_dev,
> +			 "Failed to register subdev notifier(%d)\n", ret);
> +		goto err_unreg_params_vdev;
> +	}
> +
> +	return 0;
> +err_unreg_params_vdev:
> +	rkisp1_unregister_params_vdev(&dev->params_vdev);
> +err_unreg_stats_vdev:
> +	rkisp1_unregister_stats_vdev(&dev->stats_vdev);
> +err_unreg_stream_vdev:
> +	rkisp1_unregister_stream_vdevs(dev);
> +err_unreg_isp_subdev:
> +	rkisp1_unregister_isp_subdev(dev);
> +	return ret;
> +}
> +
> +static const char * const rk3399_isp_clks[] = {
> +	"clk_isp",
> +	"aclk_isp",
> +	"hclk_isp",
> +	"aclk_isp_wrap",
> +	"hclk_isp_wrap",
> +};
> +
> +static const char * const rk3288_isp_clks[] = {
> +	"clk_isp",
> +	"aclk_isp",
> +	"hclk_isp",
> +	"pclk_isp_in",
> +	"sclk_isp_jpe",
> +};
> +
> +static const struct isp_match_data rk3288_isp_clk_data = {
> +	.clks = rk3288_isp_clks,
> +	.size = ARRAY_SIZE(rk3288_isp_clks),
> +};
> +
> +static const struct isp_match_data rk3399_isp_clk_data = {
> +	.clks = rk3399_isp_clks,
> +	.size = ARRAY_SIZE(rk3399_isp_clks),
> +};
> +
> +static const struct of_device_id rkisp1_plat_of_match[] = {
> +	{
> +		.compatible = "rockchip,rk3288-cif-isp",
> +		.data = &rk3288_isp_clk_data,
> +	}, {
> +		.compatible = "rockchip,rk3399-cif-isp",
> +		.data = &rk3399_isp_clk_data,
> +	},
> +	{},
> +};
> +
> +static irqreturn_t rkisp1_irq_handler(int irq, void *cntxt)
> +{
> +	struct device *dev = cntxt;
> +	struct rkisp1_device *rkisp1_dev = dev_get_drvdata(dev);
> +	void __iomem *base = rkisp1_dev->base_addr;
> +	unsigned int mis_val, i;
> +
> +	mis_val = readl(rkisp1_dev->base_addr + CIF_ISP_MIS);
> +	if (mis_val)
> +		rkisp1_isp_isr(mis_val, rkisp1_dev);
> +
> +	mis_val = readl(rkisp1_dev->base_addr + CIF_MIPI_MIS);
> +	if (mis_val)
> +		rkisp1_mipi_isr(mis_val, rkisp1_dev);
> +
> +	for (i = 0; i < RKISP1_MAX_STREAM; ++i) {
> +		struct rkisp1_stream *stream = &rkisp1_dev->stream[i];
> +
> +		if (stream->ops->is_frame_end_int_masked(base))
> +			rkisp1_mi_isr(stream);
> +	}
> +
> +	clr_all_int(base);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void rkisp1_disable_sys_clk(struct rkisp1_device *rkisp1_dev)
> +{
> +	int i;
> +
> +	for (i = rkisp1_dev->clk_size - 1; i >= 0; i--)
> +		clk_disable_unprepare(rkisp1_dev->clks[i]);
> +}
> +
> +static int rkisp1_enable_sys_clk(struct rkisp1_device *rkisp1_dev)
> +{
> +	int i, ret = -EINVAL;
> +
> +	for (i = 0; i < rkisp1_dev->clk_size; i++) {
> +		ret = clk_prepare_enable(rkisp1_dev->clks[i]);
> +		if (ret < 0)
> +			goto err;
> +	}
> +	return 0;
> +err:
> +	for (--i; i >= 0; --i)
> +		clk_disable_unprepare(rkisp1_dev->clks[i]);
> +	return ret;
> +}
> +
> +static int rkisp1_plat_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct device_node *node = pdev->dev.of_node;
> +	struct device *dev = &pdev->dev;
> +	struct v4l2_device *v4l2_dev;
> +	struct rkisp1_device *isp_dev;
> +	const struct isp_match_data *clk_data;
> +
> +	struct resource *res;
> +	int i, ret, irq;
> +
> +	match = of_match_node(rkisp1_plat_of_match, node);
> +	isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
> +	if (!isp_dev)
> +		return -ENOMEM;
> +
> +	dev_set_drvdata(dev, isp_dev);
> +	isp_dev->dev = dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	isp_dev->base_addr = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(isp_dev->base_addr))
> +		return PTR_ERR(isp_dev->base_addr);
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return irq;
> +
> +	ret = devm_request_irq(dev, irq, rkisp1_irq_handler, IRQF_SHARED,
> +			       dev_driver_string(dev), dev);
> +	if (ret < 0) {
> +		dev_err(dev, "request irq failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	isp_dev->irq = irq;
> +	clk_data = match->data;
> +	for (i = 0; i < clk_data->size; i++) {
> +		struct clk *clk = devm_clk_get(dev, clk_data->clks[i]);
> +
> +		if (IS_ERR(clk)) {
> +			dev_err(dev, "failed to get %s\n", clk_data->clks[i]);
> +			return PTR_ERR(clk);
> +		}
> +		isp_dev->clks[i] = clk;
> +	}
> +	isp_dev->clk_size = clk_data->size;
> +
> +	atomic_set(&isp_dev->pipe.power_cnt, 0);
> +	atomic_set(&isp_dev->pipe.stream_cnt, 0);
> +	isp_dev->pipe.open = rkisp1_pipeline_open;
> +	isp_dev->pipe.close = rkisp1_pipeline_close;
> +	isp_dev->pipe.set_stream = rkisp1_pipeline_set_stream;
> +
> +	rkisp1_stream_init(isp_dev, RKISP1_STREAM_SP);
> +	rkisp1_stream_init(isp_dev, RKISP1_STREAM_MP);
> +
> +	strlcpy(isp_dev->media_dev.model, "rkisp1",
> +		sizeof(isp_dev->media_dev.model));
> +	isp_dev->media_dev.dev = &pdev->dev;
> +	media_device_init(&isp_dev->media_dev);
> +
> +	v4l2_dev = &isp_dev->v4l2_dev;
> +	v4l2_dev->mdev = &isp_dev->media_dev;
> +	strlcpy(v4l2_dev->name, "rkisp1", sizeof(v4l2_dev->name));
> +	v4l2_ctrl_handler_init(&isp_dev->ctrl_handler, 5);
> +	v4l2_dev->ctrl_handler = &isp_dev->ctrl_handler;
> +
> +	ret = v4l2_device_register(isp_dev->dev, &isp_dev->v4l2_dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = media_device_register(&isp_dev->media_dev);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "Failed to register media device: %d\n",
> +			 ret);
> +		goto err_unreg_v4l2_dev;
> +	}
> +
> +	/* create & register platefom subdev (from of_node) */
> +	ret = rkisp1_register_platform_subdevs(isp_dev);
> +	if (ret < 0)
> +		goto err_unreg_media_dev;
> +
> +	pm_runtime_enable(&pdev->dev);
> +
> +	return 0;
> +
> +err_unreg_media_dev:
> +	media_device_unregister(&isp_dev->media_dev);
> +err_unreg_v4l2_dev:
> +	v4l2_device_unregister(&isp_dev->v4l2_dev);
> +	return ret;
> +}
> +
> +static int rkisp1_plat_remove(struct platform_device *pdev)
> +{
> +	struct rkisp1_device *isp_dev = platform_get_drvdata(pdev);
> +
> +	pm_runtime_disable(&pdev->dev);
> +	media_device_unregister(&isp_dev->media_dev);
> +	v4l2_device_unregister(&isp_dev->v4l2_dev);
> +	rkisp1_unregister_params_vdev(&isp_dev->params_vdev);
> +	rkisp1_unregister_stats_vdev(&isp_dev->stats_vdev);
> +	rkisp1_unregister_stream_vdevs(isp_dev);
> +	rkisp1_unregister_isp_subdev(isp_dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
> +{
> +	struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
> +
> +	rkisp1_disable_sys_clk(isp_dev);
> +	return pinctrl_pm_select_sleep_state(dev);
> +}
> +
> +static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
> +{
> +	struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
> +	int ret;
> +
> +	ret = pinctrl_pm_select_default_state(dev);
> +	if (ret < 0)
> +		return ret;
> +	rkisp1_enable_sys_clk(isp_dev);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops rkisp1_plat_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> +				pm_runtime_force_resume)
> +	SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver rkisp1_plat_drv = {
> +	.driver = {
> +		   .name = DRIVER_NAME,
> +		   .of_match_table = of_match_ptr(rkisp1_plat_of_match),
> +		   .pm = &rkisp1_plat_pm_ops,
> +	},
> +	.probe = rkisp1_plat_probe,
> +	.remove = rkisp1_plat_remove,
> +};
> +
> +module_platform_driver(rkisp1_plat_drv);
> +MODULE_AUTHOR("Rockchip Camera/ISP team");
> +MODULE_DESCRIPTION("Rockchip ISP1 platform driver");
> +MODULE_LICENSE("Dual BSD/GPL");
> diff --git a/drivers/media/platform/rockchip/isp1/dev.h b/drivers/media/platform/rockchip/isp1/dev.h
> new file mode 100644
> index 000000000000..f28cde364b8d
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/dev.h
> @@ -0,0 +1,120 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef _RKISP1_DEV_H
> +#define _RKISP1_DEV_H
> +
> +#include "capture.h"
> +#include "rkisp1.h"
> +#include "isp_params.h"
> +#include "isp_stats.h"
> +
> +#define DRIVER_NAME "rkisp1"
> +#define ISP_VDEV_NAME DRIVER_NAME  "_ispdev"
> +#define SP_VDEV_NAME DRIVER_NAME   "_selfpath"
> +#define MP_VDEV_NAME DRIVER_NAME   "_mainpath"
> +#define DMA_VDEV_NAME DRIVER_NAME  "_dmapath"
> +
> +#define GRP_ID_SENSOR			BIT(0)
> +#define GRP_ID_MIPIPHY			BIT(1)
> +#define GRP_ID_ISP			BIT(2)
> +#define GRP_ID_ISP_MP			BIT(3)
> +#define GRP_ID_ISP_SP			BIT(4)
> +
> +#define RKISP1_MAX_BUS_CLK	8
> +#define RKISP1_MAX_SENSOR	2
> +#define RKISP1_MAX_PIPELINE	4
> +
> +/*
> + * struct rkisp1_pipeline - An ISP hardware pipeline
> + *
> + * Capture device call other devices via pipeline
> + *
> + * @num_subdevs: number of linked subdevs
> + * @power_cnt: pipeline power count
> + * @stream_cnt: stream power count
> + */
> +struct rkisp1_pipeline {
> +	struct media_pipeline pipe;
> +	int num_subdevs;
> +	atomic_t power_cnt;
> +	atomic_t stream_cnt;
> +	struct v4l2_subdev *subdevs[RKISP1_MAX_PIPELINE];
> +	int (*open)(struct rkisp1_pipeline *p,
> +		    struct media_entity *me, bool prepare);
> +	int (*close)(struct rkisp1_pipeline *p);
> +	int (*set_stream)(struct rkisp1_pipeline *p, bool on);
> +};
> +
> +/*
> + * struct rkisp1_sensor_info - Sensor infomations
> + * @mbus: media bus configuration
> + */
> +struct rkisp1_sensor_info {
> +	struct v4l2_subdev *sd;
> +	struct v4l2_mbus_config mbus;
> +};
> +
> +/*
> + * struct rkisp1_device - ISP platform device
> + * @base_addr: base register address
> + * @active_sensor: sensor in-use, set when streaming on
> + * @isp_sdev: ISP sub-device
> + * @rkisp1_stream: capture video device
> + * @stats_vdev: ISP statistics output device
> + * @params_vdev: ISP input parameters device
> + */
> +struct rkisp1_device {
> +	void __iomem *base_addr;
> +	int irq;
> +	struct device *dev;
> +	struct clk *clks[RKISP1_MAX_BUS_CLK];
> +	int clk_size;
> +	struct v4l2_device v4l2_dev;
> +	struct v4l2_ctrl_handler ctrl_handler;
> +	struct media_device media_dev;
> +	struct v4l2_async_notifier notifier;
> +	struct v4l2_subdev *subdevs[RKISP1_SD_MAX];
> +	struct rkisp1_sensor_info *active_sensor;
> +	struct rkisp1_sensor_info sensors[RKISP1_MAX_SENSOR];
> +	int num_sensors;
> +	struct rkisp1_isp_subdev isp_sdev;
> +	struct rkisp1_stream stream[RKISP1_MAX_STREAM];
> +	struct rkisp1_isp_stats_vdev stats_vdev;
> +	struct rkisp1_isp_params_vdev params_vdev;
> +	struct rkisp1_pipeline pipe;
> +	struct vb2_alloc_ctx *alloc_ctx;
> +};
> +
> +#endif
> diff --git a/drivers/media/platform/rockchip/isp1/isp_params.c b/drivers/media/platform/rockchip/isp1/isp_params.c
> new file mode 100644
> index 000000000000..5a145b0a704e
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/isp_params.c
> @@ -0,0 +1,1543 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include <media/v4l2-common.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/videobuf2-core.h>
> +#include <media/videobuf2-vmalloc.h>	/* for ISP params */
> +#include "dev.h"
> +#include "regs.h"
> +
> +#define RKISP1_ISP_PARAMS_REQ_BUFS_MIN	2
> +#define RKISP1_ISP_PARAMS_REQ_BUFS_MAX	8
> +
> +#define BLS_START_H_MAX_IS_VALID(val)	((val) < CIFISP_BLS_START_H_MAX)
> +#define BLS_STOP_H_MAX_IS_VALID(val)	((val) < CIFISP_BLS_STOP_H_MAX)
> +
> +#define BLS_START_V_MAX_IS_VALID(val)	((val) < CIFISP_BLS_START_V_MAX)
> +#define BLS_STOP_V_MAX_IS_VALID(val)	((val) < CIFISP_BLS_STOP_V_MAX)
> +
> +#define BLS_SAMPLE_MAX_IS_VALID(val)	((val) < CIFISP_BLS_SAMPLES_MAX)
> +
> +#define BLS_FIX_SUB_IS_VALID(val)	\
> +	((val) > (s16) CIFISP_BLS_FIX_SUB_MIN && (val) < CIFISP_BLS_FIX_SUB_MAX)
> +
> +#define RKISP1_ISP_DPCC_LINE_THRESH(n)	(CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * (n))
> +#define RKISP1_ISP_DPCC_LINE_MAD_FAC(n) (CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * (n))
> +#define RKISP1_ISP_DPCC_PG_FAC(n)	(CIF_ISP_DPCC_PG_FAC_1 + 0x14 * (n))
> +#define RKISP1_ISP_DPCC_RND_THRESH(n)	(CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * (n))
> +#define RKISP1_ISP_DPCC_RG_FAC(n)	(CIF_ISP_DPCC_RG_FAC_1 + 0x14 * (n))
> +#define RKISP1_ISP_CC_COEFF(n)		(CIF_ISP_CC_COEFF_0 + (n) * 4)
> +
> +static inline void rkisp1_iowrite32(struct rkisp1_isp_params_vdev *params_vdev,
> +				    u32 value, u32 addr)
> +{
> +	iowrite32(value, params_vdev->dev->base_addr + addr);
> +}
> +
> +static inline u32 rkisp1_ioread32(struct rkisp1_isp_params_vdev *params_vdev,
> +				  u32 addr)
> +{
> +	return ioread32(params_vdev->dev->base_addr + addr);
> +}
> +
> +static inline void isp_param_set_bits(struct rkisp1_isp_params_vdev
> +					     *params_vdev,
> +				      u32 reg, u32 bit_mask)
> +{
> +	u32 val;
> +
> +	val = rkisp1_ioread32(params_vdev, reg);
> +	rkisp1_iowrite32(params_vdev, val | bit_mask, reg);
> +}
> +
> +static inline void isp_param_clear_bits(struct rkisp1_isp_params_vdev
> +					       *params_vdev,
> +					u32 reg, u32 bit_mask)
> +{
> +	u32 val;
> +
> +	val = rkisp1_ioread32(params_vdev, reg);
> +	rkisp1_iowrite32(params_vdev, val & ~bit_mask, reg);
> +}
> +
> +/* ISP BP interface function */
> +static void dpcc_config(struct rkisp1_isp_params_vdev *params_vdev,
> +			const struct cifisp_dpcc_config *arg)
> +{
> +	unsigned int i;
> +
> +	rkisp1_iowrite32(params_vdev, arg->mode, CIF_ISP_DPCC_MODE);
> +	rkisp1_iowrite32(params_vdev, arg->output_mode,
> +			 CIF_ISP_DPCC_OUTPUT_MODE);
> +	rkisp1_iowrite32(params_vdev, arg->set_use, CIF_ISP_DPCC_SET_USE);
> +
> +	rkisp1_iowrite32(params_vdev, arg->methods[0].method,
> +			 CIF_ISP_DPCC_METHODS_SET_1);
> +	rkisp1_iowrite32(params_vdev, arg->methods[1].method,
> +			 CIF_ISP_DPCC_METHODS_SET_2);
> +	rkisp1_iowrite32(params_vdev, arg->methods[2].method,
> +			 CIF_ISP_DPCC_METHODS_SET_3);
> +	for (i = 0; i < CIFISP_DPCC_METHODS_MAX; i++) {
> +		rkisp1_iowrite32(params_vdev, arg->methods[i].line_thresh,
> +				 RKISP1_ISP_DPCC_LINE_THRESH(i));
> +		rkisp1_iowrite32(params_vdev, arg->methods[i].line_mad_fac,
> +				 RKISP1_ISP_DPCC_LINE_MAD_FAC(i));
> +		rkisp1_iowrite32(params_vdev, arg->methods[i].pg_fac,
> +				 RKISP1_ISP_DPCC_PG_FAC(i));
> +		rkisp1_iowrite32(params_vdev, arg->methods[i].rnd_thresh,
> +				 RKISP1_ISP_DPCC_RND_THRESH(i));
> +		rkisp1_iowrite32(params_vdev, arg->methods[i].rg_fac,
> +				 RKISP1_ISP_DPCC_RG_FAC(i));
> +	}
> +
> +	rkisp1_iowrite32(params_vdev, arg->rnd_offs, CIF_ISP_DPCC_RND_OFFS);
> +	rkisp1_iowrite32(params_vdev, arg->ro_limits, CIF_ISP_DPCC_RO_LIMITS);
> +}
> +
> +/* ISP black level subtraction interface function */
> +static void bls_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_bls_config *arg)
> +{
> +	u32 new_control = 0;
> +
> +	/* fixed subtraction values */
> +	if (!arg->enable_auto) {
> +		const struct cifisp_bls_fixed_val *pval = &arg->fixed_val;
> +
> +		switch (params_vdev->raw_type) {
> +		case RAW_BGGR:
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->r, CIF_ISP_BLS_D_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->gr, CIF_ISP_BLS_C_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->gb, CIF_ISP_BLS_B_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->b, CIF_ISP_BLS_A_FIXED);
> +			break;
> +		case RAW_GBRG:
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->r, CIF_ISP_BLS_C_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->gr, CIF_ISP_BLS_D_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->gb, CIF_ISP_BLS_A_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->b, CIF_ISP_BLS_B_FIXED);
> +			break;
> +		case RAW_GRBG:
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->r, CIF_ISP_BLS_B_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->gr, CIF_ISP_BLS_A_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->gb, CIF_ISP_BLS_D_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->b, CIF_ISP_BLS_C_FIXED);
> +			break;
> +		case RAW_RGGB:
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->r, CIF_ISP_BLS_A_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->gr, CIF_ISP_BLS_B_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->gb, CIF_ISP_BLS_C_FIXED);
> +			rkisp1_iowrite32(params_vdev,
> +					 pval->b, CIF_ISP_BLS_D_FIXED);
> +			break;
> +		default:
> +			break;
> +		}
> +
> +		new_control = CIF_ISP_BLS_MODE_FIXED;
> +	} else {
> +		if (arg->en_windows & BIT(1)) {
> +			rkisp1_iowrite32(params_vdev, arg->bls_window2.h_offs,
> +					 CIF_ISP_BLS_H2_START);
> +			rkisp1_iowrite32(params_vdev, arg->bls_window2.h_size,
> +					 CIF_ISP_BLS_H2_STOP);
> +			rkisp1_iowrite32(params_vdev, arg->bls_window2.v_offs,
> +					 CIF_ISP_BLS_V2_START);
> +			rkisp1_iowrite32(params_vdev, arg->bls_window2.v_size,
> +					 CIF_ISP_BLS_V2_STOP);
> +			new_control |= CIF_ISP_BLS_WINDOW_2;
> +		}
> +
> +		if (arg->en_windows & BIT(0)) {
> +			rkisp1_iowrite32(params_vdev, arg->bls_window1.h_offs,
> +					 CIF_ISP_BLS_H1_START);
> +			rkisp1_iowrite32(params_vdev, arg->bls_window1.h_size,
> +					 CIF_ISP_BLS_H1_STOP);
> +			rkisp1_iowrite32(params_vdev, arg->bls_window1.v_offs,
> +					 CIF_ISP_BLS_V1_START);
> +			rkisp1_iowrite32(params_vdev, arg->bls_window1.v_size,
> +					 CIF_ISP_BLS_V1_STOP);
> +			new_control |= CIF_ISP_BLS_WINDOW_1;
> +		}
> +
> +		rkisp1_iowrite32(params_vdev, arg->bls_samples,
> +				 CIF_ISP_BLS_SAMPLES);
> +
> +		new_control |= CIF_ISP_BLS_MODE_MEASURED;
> +	}
> +	rkisp1_iowrite32(params_vdev, new_control, CIF_ISP_BLS_CTRL);
> +}
> +
> +/* ISP LS correction interface function */
> +static void
> +__lsc_correct_matrix_config(struct rkisp1_isp_params_vdev *params_vdev,
> +			    const struct cifisp_lsc_config *pconfig)
> +{
> +	int i, j;
> +	unsigned int isp_lsc_status, sram_addr, isp_lsc_table_sel;
> +	unsigned int data;
> +
> +	isp_lsc_status = rkisp1_ioread32(params_vdev, CIF_ISP_LSC_STATUS);
> +
> +	/* CIF_ISP_LSC_TABLE_ADDRESS_153 = ( 17 * 18 ) >> 1 */
> +	sram_addr = (isp_lsc_status & CIF_ISP_LSC_ACTIVE_TABLE) ?
> +		     CIF_ISP_LSC_TABLE_ADDRESS_0 :
> +		     CIF_ISP_LSC_TABLE_ADDRESS_153;
> +	rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_R_TABLE_ADDR);
> +	rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_GR_TABLE_ADDR);
> +	rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_GB_TABLE_ADDR);
> +	rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_B_TABLE_ADDR);
> +
> +	/* program data tables (table size is 9 * 17 = 153) */
> +	for (i = 0; i < ((CIF_ISP_LSC_SECTORS_MAX + 1) *
> +	     (CIF_ISP_LSC_SECTORS_MAX + 1));
> +	     i += CIF_ISP_LSC_SECTORS_MAX + 1) {
> +		/*
> +		 * 17 sectors with 2 values in one DWORD = 9
> +		 * DWORDs (2nd value of last DWORD unused)
> +		 */
> +		for (j = 0; j < (CIF_ISP_LSC_SECTORS_MAX + 1); j += 2) {
> +			data = CIF_ISP_LSC_TABLE_DATA(
> +					pconfig->r_data_tbl[i + j],
> +					pconfig->r_data_tbl[i + j + 1]);
> +			rkisp1_iowrite32(params_vdev, data,
> +					 CIF_ISP_LSC_R_TABLE_DATA);
> +
> +			data = CIF_ISP_LSC_TABLE_DATA(
> +					pconfig->gr_data_tbl[i + j],
> +					pconfig->gr_data_tbl[i + j + 1]);
> +			rkisp1_iowrite32(params_vdev, data,
> +					 CIF_ISP_LSC_GR_TABLE_DATA);
> +
> +			data = CIF_ISP_LSC_TABLE_DATA(
> +					pconfig->gb_data_tbl[i + j],
> +					pconfig->gb_data_tbl[i + j + 1]);
> +			rkisp1_iowrite32(params_vdev, data,
> +					 CIF_ISP_LSC_GB_TABLE_DATA);
> +
> +			data = CIF_ISP_LSC_TABLE_DATA(
> +					pconfig->b_data_tbl[i + j],
> +					pconfig->b_data_tbl[i + j + 1]);
> +			rkisp1_iowrite32(params_vdev, data,
> +					 CIF_ISP_LSC_B_TABLE_DATA);
> +		}
> +	}
> +
> +	isp_lsc_table_sel = (isp_lsc_status & CIF_ISP_LSC_ACTIVE_TABLE) ?
> +				CIF_ISP_LSC_TABLE_0 : CIF_ISP_LSC_TABLE_1;
> +	rkisp1_iowrite32(params_vdev, isp_lsc_table_sel, CIF_ISP_LSC_TABLE_SEL);
> +}
> +
> +static void lsc_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_lsc_config *arg)
> +{
> +	int i;
> +	u32 lsc_ctrl;
> +	unsigned int data;
> +
> +	/* To config must be off , store the current status firstly */
> +	lsc_ctrl = rkisp1_ioread32(params_vdev, CIF_ISP_LSC_CTRL);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_LSC_CTRL,
> +			     CIF_ISP_LSC_CTRL_ENA);
> +	__lsc_correct_matrix_config(params_vdev, arg);
> +
> +	for (i = 0; i < 4; i++) {
> +		/* program x size tables */
> +		data = CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2],
> +					arg->x_size_tbl[i * 2 + 1]);
> +		rkisp1_iowrite32(params_vdev, data,
> +				 CIF_ISP_LSC_XSIZE_01 + i * 4);
> +
> +		/* program x grad tables */
> +		data = CIF_ISP_LSC_SECT_SIZE(arg->x_grad_tbl[i * 2],
> +					arg->x_grad_tbl[i * 2 + 1]);
> +		rkisp1_iowrite32(params_vdev, data,
> +				 CIF_ISP_LSC_XGRAD_01 + i * 4);
> +
> +		/* program y size tables */
> +		data = CIF_ISP_LSC_SECT_SIZE(arg->y_size_tbl[i * 2],
> +					arg->y_size_tbl[i * 2 + 1]);
> +		rkisp1_iowrite32(params_vdev, data,
> +				 CIF_ISP_LSC_YSIZE_01 + i * 4);
> +
> +		/* program y grad tables */
> +		data = CIF_ISP_LSC_SECT_SIZE(arg->y_grad_tbl[i * 2],
> +					arg->y_grad_tbl[i * 2 + 1]);
> +		rkisp1_iowrite32(params_vdev, data,
> +				 CIF_ISP_LSC_YGRAD_01 + i * 4);
> +	}
> +
> +	/* restore the bls ctrl status */
> +	if (lsc_ctrl & CIF_ISP_LSC_CTRL_ENA) {
> +		isp_param_set_bits(params_vdev,
> +				   CIF_ISP_LSC_CTRL,
> +				   CIF_ISP_LSC_CTRL_ENA);
> +	} else {
> +		isp_param_clear_bits(params_vdev,
> +				     CIF_ISP_LSC_CTRL,
> +				     CIF_ISP_LSC_CTRL_ENA);
> +	}
> +}
> +
> +/* ISP Filtering function */
> +static void flt_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_flt_config *arg)
> +{
> +	rkisp1_iowrite32(params_vdev, arg->thresh_bl0, CIF_ISP_FILT_THRESH_BL0);
> +	rkisp1_iowrite32(params_vdev, arg->thresh_bl1, CIF_ISP_FILT_THRESH_BL1);
> +	rkisp1_iowrite32(params_vdev, arg->thresh_sh0, CIF_ISP_FILT_THRESH_SH0);
> +	rkisp1_iowrite32(params_vdev, arg->thresh_sh1, CIF_ISP_FILT_THRESH_SH1);
> +	rkisp1_iowrite32(params_vdev, arg->fac_bl0, CIF_ISP_FILT_FAC_BL0);
> +	rkisp1_iowrite32(params_vdev, arg->fac_bl1, CIF_ISP_FILT_FAC_BL1);
> +	rkisp1_iowrite32(params_vdev, arg->fac_mid, CIF_ISP_FILT_FAC_MID);
> +	rkisp1_iowrite32(params_vdev, arg->fac_sh0, CIF_ISP_FILT_FAC_SH0);
> +	rkisp1_iowrite32(params_vdev, arg->fac_sh1, CIF_ISP_FILT_FAC_SH1);
> +	rkisp1_iowrite32(params_vdev, arg->lum_weight, CIF_ISP_FILT_LUM_WEIGHT);
> +
> +	rkisp1_iowrite32(params_vdev, (arg->mode ? CIF_ISP_FLT_MODE_DNR : 0) |
> +			 CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) |
> +			 CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) |
> +			 CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1),
> +			 CIF_ISP_FILT_MODE);
> +}
> +
> +/* ISP demosaic interface function */
> +static int bdm_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		      const struct cifisp_bdm_config *arg)
> +{
> +	/* set demosaic threshold */
> +	rkisp1_iowrite32(params_vdev, arg->demosaic_th, CIF_ISP_DEMOSAIC);
> +	return 0;
> +}
> +
> +/* ISP GAMMA correction interface function */
> +static void sdg_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_sdg_config *arg)
> +{
> +	int i;
> +
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->xa_pnts.gamma_dx0, CIF_ISP_GAMMA_DX_LO);
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->xa_pnts.gamma_dx1, CIF_ISP_GAMMA_DX_HI);
> +
> +	for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
> +		rkisp1_iowrite32(params_vdev, arg->curve_r.gamma_y[i],
> +				 CIF_ISP_GAMMA_R_Y0 + i * 4);
> +		rkisp1_iowrite32(params_vdev, arg->curve_g.gamma_y[i],
> +				 CIF_ISP_GAMMA_G_Y0 + i * 4);
> +		rkisp1_iowrite32(params_vdev, arg->curve_b.gamma_y[i],
> +				 CIF_ISP_GAMMA_B_Y0 + i * 4);
> +	}
> +}
> +
> +/* ISP GAMMA correction interface function */
> +static void goc_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_goc_config *arg)
> +{
> +	int i;
> +
> +	isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
> +			     CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> +	rkisp1_iowrite32(params_vdev, arg->mode, CIF_ISP_GAMMA_OUT_MODE);
> +
> +	for (i = 0; i < CIFISP_GAMMA_OUT_MAX_SAMPLES; i++)
> +		rkisp1_iowrite32(params_vdev, arg->gamma_y[i],
> +				 CIF_ISP_GAMMA_OUT_Y_0 + i * 4);
> +}
> +
> +/* ISP Cross Talk */
> +static void ctk_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_ctk_config *arg)
> +{
> +	rkisp1_iowrite32(params_vdev, arg->coeff0, CIF_ISP_CT_COEFF_0);
> +	rkisp1_iowrite32(params_vdev, arg->coeff1, CIF_ISP_CT_COEFF_1);
> +	rkisp1_iowrite32(params_vdev, arg->coeff2, CIF_ISP_CT_COEFF_2);
> +	rkisp1_iowrite32(params_vdev, arg->coeff3, CIF_ISP_CT_COEFF_3);
> +	rkisp1_iowrite32(params_vdev, arg->coeff4, CIF_ISP_CT_COEFF_4);
> +	rkisp1_iowrite32(params_vdev, arg->coeff5, CIF_ISP_CT_COEFF_5);
> +	rkisp1_iowrite32(params_vdev, arg->coeff6, CIF_ISP_CT_COEFF_6);
> +	rkisp1_iowrite32(params_vdev, arg->coeff7, CIF_ISP_CT_COEFF_7);
> +	rkisp1_iowrite32(params_vdev, arg->coeff8, CIF_ISP_CT_COEFF_8);
> +	rkisp1_iowrite32(params_vdev, arg->ct_offset_r, CIF_ISP_CT_OFFSET_R);
> +	rkisp1_iowrite32(params_vdev, arg->ct_offset_g, CIF_ISP_CT_OFFSET_G);
> +	rkisp1_iowrite32(params_vdev, arg->ct_offset_b, CIF_ISP_CT_OFFSET_B);
> +}
> +
> +static void ctk_enable(struct rkisp1_isp_params_vdev *params_vdev, bool en)
> +{
> +	if (en)
> +		return;
> +
> +	/* Write back the default values. */
> +	rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_0);
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_1);
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_2);
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_3);
> +	rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_4);
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_5);
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_6);
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_7);
> +	rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_8);
> +
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_R);
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_G);
> +	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_B);
> +}
> +
> +/* ISP White Balance Mode */
> +static void awb_meas_config(struct rkisp1_isp_params_vdev *params_vdev,
> +			    const struct cifisp_awb_meas_config *arg)
> +{
> +	/* based on the mode,configure the awb module */
> +	if (arg->awb_mode == CIFISP_AWB_MODE_YCBCR) {
> +		/* Reference Cb and Cr */
> +		rkisp1_iowrite32(params_vdev,
> +				 CIF_ISP_AWB_REF_CR_SET(arg->awb_ref_cr) |
> +				 arg->awb_ref_cb, CIF_ISP_AWB_REF);
> +		/* Yc Threshold */
> +		rkisp1_iowrite32(params_vdev,
> +				 CIF_ISP_AWB_MAX_Y_SET(arg->max_y) |
> +				 CIF_ISP_AWB_MIN_Y_SET(arg->min_y) |
> +				 CIF_ISP_AWB_MAX_CS_SET(arg->max_csum) |
> +				 arg->min_c, CIF_ISP_AWB_THRESH);
> +	}
> +
> +	/* window offset */
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->awb_wnd.v_offs, CIF_ISP_AWB_WND_V_OFFS);
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->awb_wnd.h_offs, CIF_ISP_AWB_WND_H_OFFS);
> +	/* AWB window size */
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->awb_wnd.v_size, CIF_ISP_AWB_WND_V_SIZE);
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->awb_wnd.h_size, CIF_ISP_AWB_WND_H_SIZE);
> +	/* Number of frames */
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->frames, CIF_ISP_AWB_FRAMES);
> +}
> +
> +static void awb_meas_enable(struct rkisp1_isp_params_vdev *params_vdev,
> +			    const struct cifisp_awb_meas_config *arg, bool en)
> +{
> +	u32 reg_val = rkisp1_ioread32(params_vdev, CIF_ISP_AWB_PROP);
> +
> +	/* switch off */
> +	reg_val &= CIF_ISP_AWB_MODE_MASK_NONE;
> +
> +	if (en) {
> +		if (arg->awb_mode == CIFISP_AWB_MODE_RGB)
> +			reg_val |= CIF_ISP_AWB_MODE_RGB_EN;
> +		else
> +			reg_val |= CIF_ISP_AWB_MODE_YCBCR_EN;
> +
> +		rkisp1_iowrite32(params_vdev, reg_val, CIF_ISP_AWB_PROP);
> +
> +		/* Measurements require AWB block be active. */
> +		/* TODO: need to enable here ? awb_gain_enable has done this */
> +		isp_param_set_bits(params_vdev, CIF_ISP_CTRL,
> +				   CIF_ISP_CTRL_ISP_AWB_ENA);
> +	} else {
> +		rkisp1_iowrite32(params_vdev,
> +				 reg_val, CIF_ISP_AWB_PROP);
> +		isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
> +				     CIF_ISP_CTRL_ISP_AWB_ENA);
> +	}
> +}
> +
> +static void awb_gain_config(struct rkisp1_isp_params_vdev *params_vdev,
> +			    const struct cifisp_awb_gain_config *arg)
> +{
> +	rkisp1_iowrite32(params_vdev,
> +			 CIF_ISP_AWB_GAIN_R_SET(arg->gain_green_r) |
> +			 arg->gain_green_b, CIF_ISP_AWB_GAIN_G);
> +
> +	rkisp1_iowrite32(params_vdev, CIF_ISP_AWB_GAIN_R_SET(arg->gain_red) |
> +			 arg->gain_blue, CIF_ISP_AWB_GAIN_RB);
> +}
> +
> +static void aec_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_aec_config *arg)
> +{
> +	unsigned int block_hsize, block_vsize;
> +
> +	rkisp1_iowrite32(params_vdev,
> +			 ((arg->autostop) ? CIF_ISP_EXP_CTRL_AUTOSTOP : 0) |
> +			 ((arg->mode == CIFISP_EXP_MEASURING_MODE_1) ?
> +			 CIF_ISP_EXP_CTRL_MEASMODE_1 : 0), CIF_ISP_EXP_CTRL);
> +
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->meas_window.h_offs, CIF_ISP_EXP_H_OFFSET);
> +	rkisp1_iowrite32(params_vdev,
> +			 arg->meas_window.v_offs, CIF_ISP_EXP_V_OFFSET);
> +
> +	block_hsize = arg->meas_window.h_size / CIF_ISP_EXP_COLUMN_NUM - 1;
> +	block_vsize = arg->meas_window.v_size / CIF_ISP_EXP_ROW_NUM - 1;
> +
> +	rkisp1_iowrite32(params_vdev, CIF_ISP_EXP_H_SIZE_SET(block_hsize),
> +			 CIF_ISP_EXP_H_SIZE);
> +	rkisp1_iowrite32(params_vdev, CIF_ISP_EXP_V_SIZE_SET(block_vsize),
> +			 CIF_ISP_EXP_V_SIZE);
> +}
> +
> +static void cproc_config(struct rkisp1_isp_params_vdev *params_vdev,
> +			 const struct cifisp_cproc_config *arg)
> +{
> +	struct cifisp_isp_other_cfg *cur_other_cfg = &params_vdev->cur_params.others;
> +	struct cifisp_ie_config *cur_ie_config = &cur_other_cfg->ie_config;
> +	u32 effect = cur_ie_config->effect;
> +	u32 quantization = params_vdev->quantization;
> +
> +	rkisp1_iowrite32(params_vdev, arg->contrast, CIF_C_PROC_CONTRAST);
> +	rkisp1_iowrite32(params_vdev, arg->hue, CIF_C_PROC_HUE);
> +	rkisp1_iowrite32(params_vdev, arg->sat, CIF_C_PROC_SATURATION);
> +	rkisp1_iowrite32(params_vdev, arg->brightness, CIF_C_PROC_BRIGHTNESS);
> +
> +	if (quantization != V4L2_QUANTIZATION_FULL_RANGE ||
> +	    effect != V4L2_COLORFX_NONE) {
> +		isp_param_clear_bits(params_vdev, CIF_C_PROC_CTRL,
> +				     CIF_C_PROC_YOUT_FULL |
> +				     CIF_C_PROC_YIN_FULL |
> +				     CIF_C_PROC_COUT_FULL);
> +	} else {
> +		isp_param_set_bits(params_vdev, CIF_C_PROC_CTRL,
> +				   CIF_C_PROC_YOUT_FULL |
> +				   CIF_C_PROC_YIN_FULL |
> +				   CIF_C_PROC_COUT_FULL);
> +	}
> +}
> +
> +static void hst_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_hst_config *arg)
> +{
> +	unsigned int block_hsize, block_vsize;
> +	static const u32 hist_weight_regs[] = {
> +		CIF_ISP_HIST_WEIGHT_00TO30, CIF_ISP_HIST_WEIGHT_40TO21,
> +		CIF_ISP_HIST_WEIGHT_31TO12, CIF_ISP_HIST_WEIGHT_22TO03,
> +		CIF_ISP_HIST_WEIGHT_13TO43, CIF_ISP_HIST_WEIGHT_04TO34,
> +		CIF_ISP_HIST_WEIGHT_44,
> +	};
> +	int i;
> +	const u8 *weight;
> +
> +	rkisp1_iowrite32(params_vdev,
> +			 CIF_ISP_HIST_PREDIV_SET(arg->histogram_predivider),
> +			 CIF_ISP_HIST_PROP);
> +	rkisp1_iowrite32(params_vdev,
> +			arg->meas_window.h_offs,
> +			CIF_ISP_HIST_H_OFFS);
> +	rkisp1_iowrite32(params_vdev,
> +			arg->meas_window.v_offs,
> +			CIF_ISP_HIST_V_OFFS);
> +
> +	block_hsize = arg->meas_window.h_size / CIF_ISP_HIST_COLUMN_NUM - 1;
> +	block_vsize = arg->meas_window.v_size / CIF_ISP_HIST_ROW_NUM - 1;
> +
> +	rkisp1_iowrite32(params_vdev, block_hsize, CIF_ISP_HIST_H_SIZE);
> +	rkisp1_iowrite32(params_vdev, block_vsize, CIF_ISP_HIST_V_SIZE);
> +
> +	weight = arg->hist_weight;
> +	for (i = 0; i < ARRAY_SIZE(hist_weight_regs); ++i, weight += 4)
> +		rkisp1_iowrite32(params_vdev, CIF_ISP_HIST_WEIGHT_SET(
> +				 weight[0], weight[1], weight[2], weight[3]),
> +				 hist_weight_regs[i]);
> +}
> +
> +static void hst_enable(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_hst_config *arg, bool en)
> +{
> +	if (en)	{
> +		u32 hist_prop = rkisp1_ioread32(params_vdev, CIF_ISP_HIST_PROP);
> +
> +		hist_prop &= ~CIF_ISP_HIST_PROP_MODE_MASK;
> +		hist_prop |= arg->mode;
> +		isp_param_set_bits(params_vdev, CIF_ISP_HIST_PROP, hist_prop);
> +	} else {
> +		isp_param_clear_bits(params_vdev, CIF_ISP_HIST_PROP,
> +				CIF_ISP_HIST_PROP_MODE_MASK);
> +	}
> +}
> +
> +static void afm_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_afc_config *arg)
> +{
> +	int i;
> +	size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->afm_win),
> +				  arg->num_afm_win);
> +
> +	/* Switch off to configure. Enabled during normal flow in frame isr. */
> +	isp_param_clear_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
> +
> +	for (i = 0; i < num_of_win; i++) {
> +		rkisp1_iowrite32(params_vdev,
> +				 CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_offs) |
> +				 CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_offs),
> +				 CIF_ISP_AFM_LT_A + i * 8);
> +		rkisp1_iowrite32(params_vdev,
> +				 CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_size +
> +						      arg->afm_win[i].h_offs) |
> +				 CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_size +
> +						      arg->afm_win[i].v_offs),
> +				 CIF_ISP_AFM_RB_A + i * 8);
> +	}
> +	rkisp1_iowrite32(params_vdev, arg->thres, CIF_ISP_AFM_THRES);
> +	rkisp1_iowrite32(params_vdev, arg->var_shift, CIF_ISP_AFM_VAR_SHIFT);
> +}
> +
> +static void ie_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		      const struct cifisp_ie_config *arg)
> +{
> +	u32 eff_ctrl;
> +
> +	eff_ctrl = rkisp1_ioread32(params_vdev, CIF_IMG_EFF_CTRL);
> +	eff_ctrl &= ~CIF_IMG_EFF_CTRL_MODE_MASK;
> +
> +	if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE)
> +		eff_ctrl |= CIF_IMG_EFF_CTRL_YCBCR_FULL;
> +
> +	switch (arg->effect) {
> +	case V4L2_COLORFX_SEPIA:
> +		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SEPIA;
> +		break;
> +	case V4L2_COLORFX_SET_CBCR:
> +		rkisp1_iowrite32(params_vdev, arg->eff_tint, CIF_IMG_EFF_TINT);
> +		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SEPIA;
> +		break;
> +		/*
> +		 * Color selection is similar to water color(AQUA):
> +		 * grayscale + selected color w threshold
> +		 */
> +	case V4L2_COLORFX_AQUA:
> +		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_COLOR_SEL;
> +		rkisp1_iowrite32(params_vdev, arg->color_sel,
> +				 CIF_IMG_EFF_COLOR_SEL);
> +		break;
> +	case V4L2_COLORFX_EMBOSS:
> +		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_EMBOSS;
> +		rkisp1_iowrite32(params_vdev, arg->eff_mat_1,
> +				 CIF_IMG_EFF_MAT_1);
> +		rkisp1_iowrite32(params_vdev, arg->eff_mat_2,
> +				 CIF_IMG_EFF_MAT_2);
> +		rkisp1_iowrite32(params_vdev, arg->eff_mat_3,
> +				 CIF_IMG_EFF_MAT_3);
> +		break;
> +	case V4L2_COLORFX_SKETCH:
> +		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SKETCH;
> +		rkisp1_iowrite32(params_vdev, arg->eff_mat_3,
> +				 CIF_IMG_EFF_MAT_3);
> +		rkisp1_iowrite32(params_vdev, arg->eff_mat_4,
> +				 CIF_IMG_EFF_MAT_4);
> +		rkisp1_iowrite32(params_vdev, arg->eff_mat_5,
> +				 CIF_IMG_EFF_MAT_5);
> +		break;
> +	case V4L2_COLORFX_BW:
> +		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_BLACKWHITE;
> +		break;
> +	case V4L2_COLORFX_NEGATIVE:
> +		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_NEGATIVE;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	rkisp1_iowrite32(params_vdev, eff_ctrl, CIF_IMG_EFF_CTRL);
> +}
> +
> +static void ie_enable(struct rkisp1_isp_params_vdev *params_vdev, bool en)
> +{
> +	if (en) {
> +		isp_param_set_bits(params_vdev, CIF_ICCL, CIF_ICCL_IE_CLK);
> +		rkisp1_iowrite32(params_vdev, CIF_IMG_EFF_CTRL_ENABLE,
> +				 CIF_IMG_EFF_CTRL);
> +		isp_param_set_bits(params_vdev, CIF_IMG_EFF_CTRL,
> +				   CIF_IMG_EFF_CTRL_CFG_UPD);
> +	} else {
> +		/* Disable measurement */
> +		isp_param_clear_bits(params_vdev, CIF_IMG_EFF_CTRL,
> +				     CIF_IMG_EFF_CTRL_ENABLE);
> +		isp_param_clear_bits(params_vdev, CIF_ICCL, CIF_ICCL_IE_CLK);
> +	}
> +}
> +
> +static void csm_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       bool full_range)
> +{
> +	static const u16 full_range_coeff[] = {
> +		0x0026, 0x004b, 0x000f,
> +		0x01ea, 0x01d6, 0x0040,
> +		0x0040, 0x01ca, 0x01f6
> +	};
> +	static const u16 limited_range_coeff[] = {
> +		0x0021, 0x0040, 0x000d,
> +		0x01ed, 0x01db, 0x0038,
> +		0x0038, 0x01d1, 0x01f7,
> +	};
> +	int i;
> +
> +	if (full_range) {
> +		for (i = 0; i < ARRAY_SIZE(full_range_coeff); i++)
> +			rkisp1_iowrite32(params_vdev, full_range_coeff[i],
> +					 CIF_ISP_CC_COEFF_0 + i * 4);
> +
> +		isp_param_set_bits(params_vdev, CIF_ISP_CTRL,
> +				   CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
> +				   CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA);
> +	} else {
> +		for (i = 0; i < ARRAY_SIZE(limited_range_coeff); i++)
> +			rkisp1_iowrite32(params_vdev, limited_range_coeff[i],
> +					 CIF_ISP_CC_COEFF_0 + i * 4);
> +
> +		isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
> +				     CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
> +				     CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA);
> +	}
> +}
> +
> +/* ISP De-noise Pre-Filter(DPF) function */
> +static void dpf_config(struct rkisp1_isp_params_vdev *params_vdev,
> +		       const struct cifisp_dpf_config *arg)
> +{
> +	unsigned int isp_dpf_mode;
> +	unsigned int spatial_coeff;
> +	unsigned int i;
> +
> +	switch (arg->gain.mode) {
> +	case CIFISP_DPF_GAIN_USAGE_NF_GAINS:
> +		isp_dpf_mode = CIF_ISP_DPF_MODE_USE_NF_GAIN |
> +				CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
> +		break;
> +	case CIFISP_DPF_GAIN_USAGE_LSC_GAINS:
> +		isp_dpf_mode = CIF_ISP_DPF_MODE_LSC_GAIN_COMP;
> +		break;
> +	case CIFISP_DPF_GAIN_USAGE_NF_LSC_GAINS:
> +		isp_dpf_mode = CIF_ISP_DPF_MODE_USE_NF_GAIN |
> +				CIF_ISP_DPF_MODE_AWB_GAIN_COMP |
> +				CIF_ISP_DPF_MODE_LSC_GAIN_COMP;
> +		break;
> +	case CIFISP_DPF_GAIN_USAGE_AWB_GAINS:
> +		isp_dpf_mode = CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
> +		break;
> +	case CIFISP_DPF_GAIN_USAGE_AWB_LSC_GAINS:
> +		isp_dpf_mode = CIF_ISP_DPF_MODE_LSC_GAIN_COMP |
> +				CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
> +		break;
> +	case CIFISP_DPF_GAIN_USAGE_DISABLED:
> +	default:
> +		isp_dpf_mode = 0;
> +		break;
> +	}
> +
> +	if (arg->nll.scale_mode == CIFISP_NLL_SCALE_LOGARITHMIC)
> +		isp_dpf_mode |= CIF_ISP_DPF_MODE_NLL_SEGMENTATION;
> +	if (arg->rb_flt.fltsize == CIFISP_DPF_RB_FILTERSIZE_9x9)
> +		isp_dpf_mode |= CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9;
> +	if (!arg->rb_flt.r_enable)
> +		isp_dpf_mode |= CIF_ISP_DPF_MODE_R_FLT_DIS;
> +	if (!arg->rb_flt.b_enable)
> +		isp_dpf_mode |= CIF_ISP_DPF_MODE_B_FLT_DIS;
> +	if (!arg->g_flt.gb_enable)
> +		isp_dpf_mode |= CIF_ISP_DPF_MODE_GB_FLT_DIS;
> +	if (!arg->g_flt.gr_enable)
> +		isp_dpf_mode |= CIF_ISP_DPF_MODE_GR_FLT_DIS;
> +
> +	isp_param_set_bits(params_vdev, CIF_ISP_DPF_MODE, isp_dpf_mode);
> +	rkisp1_iowrite32(params_vdev, arg->gain.nf_b_gain,
> +			 CIF_ISP_DPF_NF_GAIN_B);
> +	rkisp1_iowrite32(params_vdev, arg->gain.nf_r_gain,
> +			 CIF_ISP_DPF_NF_GAIN_R);
> +	rkisp1_iowrite32(params_vdev, arg->gain.nf_gb_gain,
> +			 CIF_ISP_DPF_NF_GAIN_GB);
> +	rkisp1_iowrite32(params_vdev, arg->gain.nf_gr_gain,
> +			 CIF_ISP_DPF_NF_GAIN_GR);
> +
> +	for (i = 0; i < CIFISP_DPF_MAX_NLF_COEFFS; i++) {
> +		rkisp1_iowrite32(params_vdev, arg->nll.coeff[i],
> +				 CIF_ISP_DPF_NULL_COEFF_0 + i * 4);
> +	}
> +
> +	spatial_coeff = arg->g_flt.spatial_coeff[0] |
> +			(arg->g_flt.spatial_coeff[1] << 8) |
> +			(arg->g_flt.spatial_coeff[2] << 16) |
> +			(arg->g_flt.spatial_coeff[3] << 24);
> +	rkisp1_iowrite32(params_vdev, spatial_coeff,
> +			 CIF_ISP_DPF_S_WEIGHT_G_1_4);
> +
> +	spatial_coeff = arg->g_flt.spatial_coeff[4] |
> +			(arg->g_flt.spatial_coeff[5] << 8);
> +	rkisp1_iowrite32(params_vdev, spatial_coeff,
> +			 CIF_ISP_DPF_S_WEIGHT_G_5_6);
> +
> +	spatial_coeff = arg->rb_flt.spatial_coeff[0] |
> +			(arg->rb_flt.spatial_coeff[1] << 8) |
> +			(arg->rb_flt.spatial_coeff[2] << 16) |
> +			(arg->rb_flt.spatial_coeff[3] << 24);
> +	rkisp1_iowrite32(params_vdev, spatial_coeff,
> +			 CIF_ISP_DPF_S_WEIGHT_RB_1_4);
> +
> +	spatial_coeff = arg->rb_flt.spatial_coeff[4] |
> +			(arg->rb_flt.spatial_coeff[5] << 8);
> +	rkisp1_iowrite32(params_vdev, spatial_coeff,
> +			CIF_ISP_DPF_S_WEIGHT_RB_5_6);
> +}
> +
> +static void dpf_strength_config(struct rkisp1_isp_params_vdev *params_vdev,
> +				const struct cifisp_dpf_strength_config *arg)
> +{
> +	rkisp1_iowrite32(params_vdev, arg->b, CIF_ISP_DPF_STRENGTH_B);
> +	rkisp1_iowrite32(params_vdev, arg->g, CIF_ISP_DPF_STRENGTH_G);
> +	rkisp1_iowrite32(params_vdev, arg->r, CIF_ISP_DPF_STRENGTH_R);
> +}
> +
> +static __maybe_unused

Why maybe unused? Add a comment explaining this.

> +void __isp_isr_other_config(struct rkisp1_isp_params_vdev *params_vdev,
> +			    const struct rkisp1_isp_params_cfg *new_params)
> +{
> +	unsigned int module_en_update, module_cfg_update, module_ens;
> +
> +	module_en_update = new_params->module_en_update;
> +	module_cfg_update = new_params->module_cfg_update;
> +	module_ens = new_params->module_ens;
> +
> +	if ((module_en_update & CIFISP_MODULE_DPCC) ||
> +	    (module_cfg_update & CIFISP_MODULE_DPCC)) {
> +		/*update dpc config */
> +		if ((module_cfg_update & CIFISP_MODULE_DPCC))
> +			dpcc_config(params_vdev,
> +					&new_params->others.dpcc_config);
> +
> +		if (module_en_update & CIFISP_MODULE_DPCC) {
> +			if (!!(module_ens & CIFISP_MODULE_DPCC))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_DPCC_MODE,
> +						   CIF_ISP_DPCC_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_DPCC_MODE,
> +						     CIF_ISP_DPCC_ENA);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_BLS) ||
> +	    (module_cfg_update & CIFISP_MODULE_BLS)) {
> +		/* update bls config */
> +		if ((module_cfg_update & CIFISP_MODULE_BLS))
> +			bls_config(params_vdev, &new_params->others.bls_config);
> +
> +		if (module_en_update & CIFISP_MODULE_BLS) {
> +			if (!!(module_ens & CIFISP_MODULE_BLS))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_BLS_CTRL,
> +						   CIF_ISP_BLS_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_BLS_CTRL,
> +						     CIF_ISP_BLS_ENA);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_SDG) ||
> +	    (module_cfg_update & CIFISP_MODULE_SDG)) {
> +		/* update sdg config */
> +		if ((module_cfg_update & CIFISP_MODULE_SDG))
> +			sdg_config(params_vdev, &new_params->others.sdg_config);
> +
> +		if (module_en_update & CIFISP_MODULE_SDG) {
> +			if (!!(module_ens & CIFISP_MODULE_SDG))
> +				isp_param_set_bits(params_vdev,
> +						CIF_ISP_CTRL,
> +						CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						CIF_ISP_CTRL,
> +						CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_LSC) ||
> +	    (module_cfg_update & CIFISP_MODULE_LSC)) {
> +		/* update lsc config */
> +		if ((module_cfg_update & CIFISP_MODULE_LSC))
> +			lsc_config(params_vdev, &new_params->others.lsc_config);
> +
> +		if (module_en_update & CIFISP_MODULE_LSC) {
> +			if (!!(module_ens & CIFISP_MODULE_LSC))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_LSC_CTRL,
> +						   CIF_ISP_LSC_CTRL_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_LSC_CTRL,
> +						     CIF_ISP_LSC_CTRL_ENA);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_AWB_GAIN) ||
> +	    (module_cfg_update & CIFISP_MODULE_AWB_GAIN)) {
> +		/* update awb gains */
> +		if ((module_cfg_update & CIFISP_MODULE_AWB_GAIN))
> +			awb_gain_config(params_vdev,
> +					&new_params->others.awb_gain_config);
> +
> +		if (module_en_update & CIFISP_MODULE_AWB_GAIN) {
> +			if (!!(module_ens & CIFISP_MODULE_AWB_GAIN))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_CTRL,
> +						   CIF_ISP_CTRL_ISP_AWB_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_CTRL,
> +						     CIF_ISP_CTRL_ISP_AWB_ENA);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_BDM) ||
> +	    (module_cfg_update & CIFISP_MODULE_BDM)) {
> +		/* update bdm config */
> +		if ((module_cfg_update & CIFISP_MODULE_BDM))
> +			bdm_config(params_vdev, &new_params->others.bdm_config);
> +
> +		if (module_en_update & CIFISP_MODULE_BDM) {
> +			if (!!(module_ens & CIFISP_MODULE_BDM))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_DEMOSAIC,
> +						   CIF_ISP_DEMOSAIC_BYPASS);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_DEMOSAIC,
> +						     CIF_ISP_DEMOSAIC_BYPASS);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_FLT) ||
> +	    (module_cfg_update & CIFISP_MODULE_FLT)) {
> +		/* update filter config */
> +		if ((module_cfg_update & CIFISP_MODULE_FLT))
> +			flt_config(params_vdev, &new_params->others.flt_config);
> +
> +		if (module_en_update & CIFISP_MODULE_FLT) {
> +			if (!!(module_ens & CIFISP_MODULE_FLT))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_FILT_MODE,
> +						   CIF_ISP_FLT_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_FILT_MODE,
> +						     CIF_ISP_FLT_ENA);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_CTK) ||
> +	    (module_cfg_update & CIFISP_MODULE_CTK)) {
> +		/* update ctk config */
> +		if ((module_cfg_update & CIFISP_MODULE_CTK))
> +			ctk_config(params_vdev, &new_params->others.ctk_config);
> +
> +		if (module_en_update & CIFISP_MODULE_CTK)
> +			ctk_enable(params_vdev,
> +				   !!(module_ens & CIFISP_MODULE_CTK));
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_GOC) ||
> +	    (module_cfg_update & CIFISP_MODULE_GOC)) {
> +		/* update goc config */
> +		if ((module_cfg_update & CIFISP_MODULE_GOC))
> +			goc_config(params_vdev, &new_params->others.goc_config);
> +
> +		if (module_en_update & CIFISP_MODULE_GOC) {
> +			if (!!(module_ens & CIFISP_MODULE_GOC))
> +				isp_param_set_bits(params_vdev,
> +						CIF_ISP_CTRL,
> +						CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						CIF_ISP_CTRL,
> +						CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_CPROC) ||
> +	    (module_cfg_update & CIFISP_MODULE_CPROC)) {
> +		/* update cproc config */
> +		if ((module_cfg_update & CIFISP_MODULE_CPROC)) {
> +			cproc_config(params_vdev,
> +				     &new_params->others.cproc_config);
> +
> +		}
> +
> +		if (module_en_update & CIFISP_MODULE_CPROC) {
> +			if (!!(module_ens & CIFISP_MODULE_CPROC))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_C_PROC_CTRL,
> +						   CIF_C_PROC_CTR_ENABLE);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						   CIF_C_PROC_CTRL,
> +						   CIF_C_PROC_CTR_ENABLE);
> +		}
> +	}
> +
> +
> +	if ((module_en_update & CIFISP_MODULE_IE) ||
> +	    (module_cfg_update & CIFISP_MODULE_IE)) {
> +		/* update ie config */
> +		if ((module_cfg_update & CIFISP_MODULE_IE))
> +			ie_config(params_vdev, &new_params->others.ie_config);
> +
> +		if (module_en_update & CIFISP_MODULE_IE)
> +			ie_enable(params_vdev,
> +				   !!(module_ens & CIFISP_MODULE_IE));
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_DPF) ||
> +	    (module_cfg_update & CIFISP_MODULE_DPF)) {
> +		/* update dpf  config */
> +		if ((module_cfg_update & CIFISP_MODULE_DPF))
> +			dpf_config(params_vdev, &new_params->others.dpf_config);
> +
> +		if (module_en_update & CIFISP_MODULE_DPF) {
> +			if (!!(module_ens & CIFISP_MODULE_DPF))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_DPF_MODE,
> +						   CIF_ISP_DPF_MODE_EN);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_DPF_MODE,
> +						     CIF_ISP_DPF_MODE_EN);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_DPF_STRENGTH) ||
> +	    (module_cfg_update & CIFISP_MODULE_DPF_STRENGTH)) {
> +		/* update dpf strength config */
> +		dpf_strength_config(params_vdev,
> +				    &new_params->others.dpf_strength_config);
> +	}
> +}
> +
> +static __maybe_unused
> +void __isp_isr_meas_config(struct rkisp1_isp_params_vdev *params_vdev,
> +			   struct  rkisp1_isp_params_cfg *new_params)
> +{
> +	unsigned int module_en_update, module_cfg_update, module_ens;
> +
> +	module_en_update = new_params->module_en_update;
> +	module_cfg_update = new_params->module_cfg_update;
> +	module_ens = new_params->module_ens;
> +
> +	if ((module_en_update & CIFISP_MODULE_AWB) ||
> +	    (module_cfg_update & CIFISP_MODULE_AWB)) {
> +		/* update awb config */
> +		if ((module_cfg_update & CIFISP_MODULE_AWB))
> +			awb_meas_config(params_vdev,
> +					&new_params->meas.awb_meas_config);
> +
> +		if (module_en_update & CIFISP_MODULE_AWB)
> +			awb_meas_enable(params_vdev,
> +					&new_params->meas.awb_meas_config,
> +					!!(module_ens & CIFISP_MODULE_AWB));
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_AFC) ||
> +	    (module_cfg_update & CIFISP_MODULE_AFC)) {
> +		/* update afc config */
> +		if ((module_cfg_update & CIFISP_MODULE_AFC))
> +			afm_config(params_vdev, &new_params->meas.afc_config);
> +
> +		if (module_en_update & CIFISP_MODULE_AFC) {
> +			if (!!(module_ens & CIFISP_MODULE_AFC))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_AFM_CTRL,
> +						   CIF_ISP_AFM_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_AFM_CTRL,
> +						     CIF_ISP_AFM_ENA);
> +		}
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_HST) ||
> +	    (module_cfg_update & CIFISP_MODULE_HST)) {
> +		/* update hst config */
> +		if ((module_cfg_update & CIFISP_MODULE_HST))
> +			hst_config(params_vdev, &new_params->meas.hst_config);
> +
> +		if (module_en_update & CIFISP_MODULE_HST)
> +			hst_enable(params_vdev,
> +				   &new_params->meas.hst_config,
> +				   !!(module_ens & CIFISP_MODULE_HST));
> +	}
> +
> +	if ((module_en_update & CIFISP_MODULE_AEC) ||
> +	    (module_cfg_update & CIFISP_MODULE_AEC)) {
> +		/* update aec config */
> +		if ((module_cfg_update & CIFISP_MODULE_AEC))
> +			aec_config(params_vdev, &new_params->meas.aec_config);
> +
> +		if (module_en_update & CIFISP_MODULE_AEC) {
> +			if (!!(module_ens & CIFISP_MODULE_AEC))
> +				isp_param_set_bits(params_vdev,
> +						   CIF_ISP_EXP_CTRL,
> +						   CIF_ISP_EXP_ENA);
> +			else
> +				isp_param_clear_bits(params_vdev,
> +						     CIF_ISP_EXP_CTRL,
> +						     CIF_ISP_EXP_ENA);
> +		}
> +	}
> +}
> +
> +void rkisp1_params_isr(struct rkisp1_isp_params_vdev *params_vdev, u32 isp_mis)
> +{
> +	struct rkisp1_isp_params_cfg *new_params;
> +	struct rkisp1_buffer *cur_buf = NULL;
> +
> +	spin_lock(&params_vdev->config_lock);
> +	if (!params_vdev->streamon) {
> +		spin_unlock(&params_vdev->config_lock);
> +		return;
> +	}
> +
> +	/* get one empty buffer */
> +	if (!list_empty(&params_vdev->params))
> +		cur_buf = list_first_entry(&params_vdev->params,
> +					   struct rkisp1_buffer, queue);
> +	spin_unlock(&params_vdev->config_lock);
> +
> +	if (!cur_buf)
> +		return;
> +
> +	new_params = (struct rkisp1_isp_params_cfg *)(cur_buf->vaddr[0]);
> +
> +	if (isp_mis & CIF_ISP_FRAME) {
> +		__isp_isr_other_config(params_vdev, new_params);
> +		__isp_isr_meas_config(params_vdev, new_params);
> +		spin_lock(&params_vdev->config_lock);
> +		list_del(&cur_buf->queue);
> +		spin_unlock(&params_vdev->config_lock);
> +		vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
> +	}
> +}
> +
> +static const struct cifisp_awb_meas_config awb_params_default_config = {
> +	{
> +		0, 0, RKISP1_DEFAULT_WIDTH, RKISP1_DEFAULT_HEIGHT
> +	},
> +	CIFISP_AWB_MODE_YCBCR, 200, 30, 20, 20, 0, 128, 128
> +};
> +
> +static const struct cifisp_aec_config aec_params_default_config = {
> +	CIFISP_EXP_MEASURING_MODE_0,
> +	CIFISP_EXP_CTRL_AUTOSTOP_0,
> +	{
> +		RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2,
> +		RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1
> +	}
> +};
> +
> +static const struct cifisp_hst_config hst_params_default_config = {
> +	CIFISP_HISTOGRAM_MODE_RGB_COMBINED,
> +	3,
> +	{
> +		RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2,
> +		RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1
> +	},
> +	{
> +		0, /* To be filled in with 0x01 at runtime. */
> +	}
> +};
> +
> +static const struct cifisp_afc_config afc_params_default_config = {
> +	1,
> +	{
> +		{
> +			300, 225, 200, 150
> +		}
> +	},
> +	4,
> +	14
> +};
> +
> +static
> +void rkisp1_params_config_parameter(struct rkisp1_isp_params_vdev *params_vdev)
> +{
> +	struct cifisp_hst_config hst = hst_params_default_config;
> +
> +	spin_lock(&params_vdev->config_lock);
> +
> +	awb_meas_config(params_vdev, &awb_params_default_config);
> +	awb_meas_enable(params_vdev, &awb_params_default_config, true);
> +
> +	aec_config(params_vdev, &aec_params_default_config);
> +	isp_param_set_bits(params_vdev, CIF_ISP_EXP_CTRL, CIF_ISP_EXP_ENA);
> +
> +	afm_config(params_vdev, &afc_params_default_config);
> +	isp_param_set_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
> +
> +	memset(hst.hist_weight, 0x01, sizeof(hst.hist_weight));
> +	hst_config(params_vdev, &hst);
> +	isp_param_set_bits(params_vdev, CIF_ISP_HIST_PROP,
> +			   ~CIF_ISP_HIST_PROP_MODE_MASK |
> +			   hst_params_default_config.mode);
> +
> +	/* set the  range */
> +	if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE)
> +		csm_config(params_vdev, true);
> +	else
> +		csm_config(params_vdev, false);
> +
> +	/* override the default things */
> +	__isp_isr_other_config(params_vdev, &params_vdev->cur_params);
> +	__isp_isr_meas_config(params_vdev, &params_vdev->cur_params);
> +
> +	spin_unlock(&params_vdev->config_lock);
> +}
> +
> +/* Not called when the camera active, thus not isr protection. */
> +void rkisp1_configure_isp(struct rkisp1_isp_params_vdev *params_vdev,
> +			  struct ispsd_in_fmt *in_fmt,
> +			  enum v4l2_quantization quantization)
> +{
> +	if (!params_vdev)
> +		return;
> +
> +	if (quantization)
> +		params_vdev->quantization = quantization;
> +	if (in_fmt)
> +		params_vdev->raw_type = in_fmt->bayer_pat;
> +	if (params_vdev)
> +		rkisp1_params_config_parameter(params_vdev);
> +}
> +
> +/* Not called when the camera active, thus not isr protection. */
> +void rkisp1_disable_isp(struct rkisp1_isp_params_vdev *params_vdev)
> +{
> +	isp_param_clear_bits(params_vdev, CIF_ISP_DPCC_MODE, CIF_ISP_DPCC_ENA);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_LSC_CTRL,
> +			     CIF_ISP_LSC_CTRL_ENA);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_BLS_CTRL, CIF_ISP_BLS_ENA);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
> +			     CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
> +			     CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_DEMOSAIC,
> +			     CIF_ISP_DEMOSAIC_BYPASS);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_FILT_MODE, CIF_ISP_FLT_ENA);
> +	awb_meas_enable(params_vdev, NULL, false);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
> +			     CIF_ISP_CTRL_ISP_AWB_ENA);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_EXP_CTRL, CIF_ISP_EXP_ENA);
> +	ctk_enable(params_vdev, false);
> +	isp_param_clear_bits(params_vdev, CIF_C_PROC_CTRL,
> +			     CIF_C_PROC_CTR_ENABLE);
> +	hst_enable(params_vdev, NULL, false);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
> +	ie_enable(params_vdev, false);
> +	isp_param_clear_bits(params_vdev, CIF_ISP_DPF_MODE,
> +			     CIF_ISP_DPF_MODE_EN);
> +}
> +
> +static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv,
> +					   struct v4l2_fmtdesc *f)
> +{
> +	struct video_device *video = video_devdata(file);
> +	struct rkisp1_isp_params_vdev *params_vdev = video_get_drvdata(video);
> +
> +	if (f->index > 0 || f->type != video->queue->type)
> +		return -EINVAL;
> +
> +	f->pixelformat = params_vdev->vdev_fmt.fmt.meta.dataformat;
> +
> +	return 0;
> +}
> +
> +static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh,
> +					struct v4l2_format *f)
> +{
> +	struct video_device *video = video_devdata(file);
> +	struct rkisp1_isp_params_vdev *params_vdev = video_get_drvdata(video);
> +	struct v4l2_meta_format *meta = &f->fmt.meta;
> +
> +	if (f->type != video->queue->type)
> +		return -EINVAL;
> +
> +	memset(meta, 0, sizeof(*meta));
> +	meta->dataformat = params_vdev->vdev_fmt.fmt.meta.dataformat;
> +	meta->buffersize = params_vdev->vdev_fmt.fmt.meta.buffersize;
> +
> +	return 0;
> +}
> +
> +static int rkisp1_params_querycap(struct file *file,
> +				  void *priv, struct v4l2_capability *cap)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	strcpy(cap->driver, DRIVER_NAME);
> +	strlcpy(cap->card, vdev->name, sizeof(cap->card));
> +	strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
> +
> +	return 0;
> +}
> +
> +/* ISP params video device IOCTLs */
> +static const struct v4l2_ioctl_ops rkisp1_params_ioctl = {
> +	.vidioc_reqbufs = vb2_ioctl_reqbufs,
> +	.vidioc_querybuf = vb2_ioctl_querybuf,
> +	.vidioc_create_bufs = vb2_ioctl_create_bufs,
> +	.vidioc_qbuf = vb2_ioctl_qbuf,
> +	.vidioc_dqbuf = vb2_ioctl_dqbuf,
> +	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
> +	.vidioc_expbuf = vb2_ioctl_expbuf,
> +	.vidioc_streamon = vb2_ioctl_streamon,
> +	.vidioc_streamoff = vb2_ioctl_streamoff,
> +	.vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out,
> +	.vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> +	.vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> +	.vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> +	.vidioc_querycap = rkisp1_params_querycap
> +};
> +
> +static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
> +					 unsigned int *num_buffers,
> +					 unsigned int *num_planes,
> +					 unsigned int sizes[],
> +					 struct device *alloc_devs[])
> +{
> +	struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
> +
> +	*num_buffers = clamp_t(u32, *num_buffers,
> +			       RKISP1_ISP_PARAMS_REQ_BUFS_MIN,
> +			       RKISP1_ISP_PARAMS_REQ_BUFS_MAX);
> +
> +	*num_planes = 1;
> +
> +	sizes[0] = sizeof(struct rkisp1_isp_params_cfg);
> +
> +	INIT_LIST_HEAD(&params_vdev->params);
> +	params_vdev->first_params = true;
> +
> +	return 0;
> +}
> +
> +static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> +{
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct rkisp1_buffer *params_buf = to_rkisp1_buffer(vbuf);
> +	struct vb2_queue *vq = vb->vb2_queue;
> +	struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
> +	struct rkisp1_isp_params_cfg *new_params;
> +	unsigned long flags;
> +
> +	if (params_vdev->first_params) {
> +		new_params = (struct rkisp1_isp_params_cfg *)
> +			(vb2_plane_vaddr(vb, 0));
> +		vb2_buffer_done(&params_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
> +		params_vdev->first_params = false;
> +		params_vdev->cur_params = *new_params;
> +		return;
> +	}
> +
> +	params_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
> +	spin_lock_irqsave(&params_vdev->config_lock, flags);
> +	list_add_tail(&params_buf->queue, &params_vdev->params);
> +	spin_unlock_irqrestore(&params_vdev->config_lock, flags);
> +}
> +
> +static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
> +{
> +	struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
> +	struct rkisp1_buffer *buf;
> +	unsigned long flags;
> +	int i;
> +
> +	/* stop params input firstly */
> +	spin_lock_irqsave(&params_vdev->config_lock, flags);
> +	params_vdev->streamon = false;
> +	spin_unlock_irqrestore(&params_vdev->config_lock, flags);
> +
> +	for (i = 0; i < RKISP1_ISP_PARAMS_REQ_BUFS_MAX; i++) {
> +		spin_lock_irqsave(&params_vdev->config_lock, flags);
> +		if (!list_empty(&params_vdev->params)) {
> +			buf = list_first_entry(&params_vdev->params,
> +					       struct rkisp1_buffer, queue);
> +			list_del(&buf->queue);
> +			spin_unlock_irqrestore(&params_vdev->config_lock,
> +					       flags);
> +		} else {
> +			spin_unlock_irqrestore(&params_vdev->config_lock,
> +					       flags);
> +			break;
> +		}
> +
> +		if (buf)
> +			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> +		buf = NULL;
> +	}
> +}
> +
> +static int
> +rkisp1_params_vb2_start_streaming(struct vb2_queue *queue, unsigned int count)
> +{
> +	struct rkisp1_isp_params_vdev *params_vdev = queue->drv_priv;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&params_vdev->config_lock, flags);
> +	params_vdev->streamon = true;
> +	spin_unlock_irqrestore(&params_vdev->config_lock, flags);
> +
> +	return 0;
> +}
> +
> +static struct vb2_ops rkisp1_params_vb2_ops = {
> +	.queue_setup = rkisp1_params_vb2_queue_setup,
> +	.wait_prepare = vb2_ops_wait_prepare,
> +	.wait_finish = vb2_ops_wait_finish,
> +	.buf_queue = rkisp1_params_vb2_buf_queue,
> +	.start_streaming = rkisp1_params_vb2_start_streaming,
> +	.stop_streaming = rkisp1_params_vb2_stop_streaming,
> +
> +};
> +
> +struct v4l2_file_operations rkisp1_params_fops = {
> +	.mmap = vb2_fop_mmap,
> +	.unlocked_ioctl = video_ioctl2,
> +	.poll = vb2_fop_poll,
> +	.open = v4l2_fh_open,
> +	.release = vb2_fop_release
> +};
> +
> +static int
> +rkisp1_params_init_vb2_queue(struct vb2_queue *q,
> +			     struct rkisp1_isp_params_vdev *params_vdev)
> +{
> +	struct rkisp1_vdev_node *node;
> +
> +	node = queue_to_node(q);
> +
> +	q->type = V4L2_BUF_TYPE_META_OUTPUT;
> +	q->io_modes = VB2_MMAP | VB2_USERPTR;

Either add VB2_DMABUF or drop exp_buf from rkisp1_params_ioctl.

> +	q->drv_priv = params_vdev;
> +	q->ops = &rkisp1_params_vb2_ops;
> +	q->mem_ops = &vb2_vmalloc_memops;
> +	q->buf_struct_size = sizeof(struct rkisp1_buffer);
> +	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
> +	q->lock = &node->vlock;
> +
> +	return vb2_queue_init(q);
> +}
> +
> +static void rkisp1_init_params_vdev(struct rkisp1_isp_params_vdev *params_vdev)
> +{
> +	params_vdev->vdev_fmt.fmt.meta.dataformat =
> +		V4L2_META_FMT_RK_ISP1_PARAMS;
> +	params_vdev->vdev_fmt.fmt.meta.buffersize =
> +		sizeof(struct rkisp1_isp_params_cfg);
> +}
> +
> +int rkisp1_register_params_vdev(struct rkisp1_isp_params_vdev *params_vdev,
> +				struct v4l2_device *v4l2_dev,
> +				struct rkisp1_device *dev)
> +{
> +	int ret;
> +	struct rkisp1_vdev_node *node = &params_vdev->vnode;
> +	struct video_device *vdev = &node->vdev;
> +
> +	params_vdev->dev = dev;
> +	mutex_init(&node->vlock);
> +	spin_lock_init(&params_vdev->config_lock);
> +
> +	strlcpy(vdev->name, "rkisp1-input-params", sizeof(vdev->name));
> +
> +	video_set_drvdata(vdev, params_vdev);
> +	vdev->ioctl_ops = &rkisp1_params_ioctl;
> +	vdev->fops = &rkisp1_params_fops;
> +	vdev->release = video_device_release_empty;
> +	/*
> +	 * Provide a mutex to v4l2 core. It will be used
> +	 * to protect all fops and v4l2 ioctls.
> +	 */
> +	vdev->lock = &node->vlock;
> +	vdev->v4l2_dev = v4l2_dev;
> +	vdev->queue = &node->buf_queue;
> +	vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT;
> +	vdev->vfl_dir = VFL_DIR_TX;
> +	rkisp1_params_init_vb2_queue(vdev->queue, params_vdev);
> +	rkisp1_init_params_vdev(params_vdev);
> +	video_set_drvdata(vdev, params_vdev);
> +
> +	node->pad.flags = MEDIA_PAD_FL_SOURCE;
> +	vdev->entity.function = MEDIA_ENT_F_IO_V4L;
> +	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
> +	if (ret < 0)
> +		goto err_release_queue;
> +	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
> +	if (ret < 0) {
> +		dev_err(&vdev->dev,
> +			"could not register Video for Linux device\n");
> +		goto err_cleanup_media_entity;
> +	}
> +	return 0;
> +err_cleanup_media_entity:
> +	media_entity_cleanup(&vdev->entity);
> +err_release_queue:
> +	vb2_queue_release(vdev->queue);
> +	return ret;
> +}
> +
> +void rkisp1_unregister_params_vdev(struct rkisp1_isp_params_vdev *params_vdev)
> +{
> +	struct rkisp1_vdev_node *node = &params_vdev->vnode;
> +	struct video_device *vdev = &node->vdev;
> +
> +	video_unregister_device(vdev);
> +	media_entity_cleanup(&vdev->entity);
> +	vb2_queue_release(vdev->queue);
> +}
> diff --git a/drivers/media/platform/rockchip/isp1/isp_params.h b/drivers/media/platform/rockchip/isp1/isp_params.h
> new file mode 100644
> index 000000000000..0d6a2f2a151f
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/isp_params.h
> @@ -0,0 +1,76 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef _RKISP1_ISP_H
> +#define _RKISP1_ISP_H
> +
> +#include <linux/rkisp1-config.h>
> +#include "common.h"
> +
> +/*
> + * struct rkisp1_isp_subdev - ISP input parameters device
> + *
> + * @cur_params: Current ISP parameters
> + * @first_params: the first params should take effect immediately
> + */
> +struct rkisp1_isp_params_vdev {
> +	struct rkisp1_vdev_node vnode;
> +	struct rkisp1_device *dev;
> +
> +	spinlock_t config_lock;
> +	struct list_head params;
> +	struct rkisp1_isp_params_cfg cur_params;
> +	struct v4l2_format vdev_fmt;
> +	bool streamon;
> +	bool first_params;
> +
> +	enum v4l2_quantization quantization;
> +	enum rkisp1_fmt_raw_pat_type raw_type;
> +};
> +
> +/* config params before ISP streaming */
> +void rkisp1_configure_isp(struct rkisp1_isp_params_vdev *params_vdev,
> +			  struct ispsd_in_fmt *in_fmt,
> +			  enum v4l2_quantization quantization);
> +void rkisp1_disable_isp(struct rkisp1_isp_params_vdev *params_vdev);
> +
> +int rkisp1_register_params_vdev(struct rkisp1_isp_params_vdev *params_vdev,
> +				struct v4l2_device *v4l2_dev,
> +				struct rkisp1_device *dev);
> +
> +void rkisp1_unregister_params_vdev(struct rkisp1_isp_params_vdev *params_vdev);
> +
> +void rkisp1_params_isr(struct rkisp1_isp_params_vdev *params_vdev, u32 isp_mis);
> +
> +#endif /* _RKISP1_ISP_H */
> diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.c b/drivers/media/platform/rockchip/isp1/isp_stats.c
> new file mode 100644
> index 000000000000..bb25c6384498
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/isp_stats.c
> @@ -0,0 +1,521 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include <media/v4l2-common.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/videobuf2-core.h>
> +#include <media/videobuf2-vmalloc.h>	/* for ISP statistics */
> +#include "dev.h"
> +#include "regs.h"
> +
> +#define RKISP1_ISP_STATS_REQ_BUFS_MIN 2
> +#define RKISP1_ISP_STATS_REQ_BUFS_MAX 8
> +
> +static int rkisp1_stats_enum_fmt_meta_cap(struct file *file, void *priv,
> +					  struct v4l2_fmtdesc *f)
> +{
> +	struct video_device *video = video_devdata(file);
> +	struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
> +
> +	if (f->index > 0 || f->type != video->queue->type)
> +		return -EINVAL;
> +
> +	f->pixelformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
> +	return 0;
> +}
> +
> +static int rkisp1_stats_g_fmt_meta_cap(struct file *file, void *priv,
> +				       struct v4l2_format *f)
> +{
> +	struct video_device *video = video_devdata(file);
> +	struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
> +	struct v4l2_meta_format *meta = &f->fmt.meta;
> +
> +	if (f->type != video->queue->type)
> +		return -EINVAL;
> +
> +	memset(meta, 0, sizeof(*meta));
> +	meta->dataformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
> +	meta->buffersize = stats_vdev->vdev_fmt.fmt.meta.buffersize;
> +
> +	return 0;
> +}
> +
> +static int rkisp1_stats_querycap(struct file *file,
> +				 void *priv, struct v4l2_capability *cap)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	strcpy(cap->driver, DRIVER_NAME);
> +	strlcpy(cap->card, vdev->name, sizeof(cap->card));
> +	strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
> +
> +	return 0;
> +}
> +
> +/* ISP video device IOCTLs */
> +static const struct v4l2_ioctl_ops rkisp1_stats_ioctl = {
> +	.vidioc_reqbufs = vb2_ioctl_reqbufs,
> +	.vidioc_querybuf = vb2_ioctl_querybuf,
> +	.vidioc_create_bufs = vb2_ioctl_create_bufs,
> +	.vidioc_qbuf = vb2_ioctl_qbuf,
> +	.vidioc_dqbuf = vb2_ioctl_dqbuf,
> +	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
> +	.vidioc_expbuf = vb2_ioctl_expbuf,
> +	.vidioc_streamon = vb2_ioctl_streamon,
> +	.vidioc_streamoff = vb2_ioctl_streamoff,
> +	.vidioc_enum_fmt_meta_cap = rkisp1_stats_enum_fmt_meta_cap,
> +	.vidioc_g_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
> +	.vidioc_s_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
> +	.vidioc_try_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
> +	.vidioc_querycap = rkisp1_stats_querycap
> +};
> +
> +struct v4l2_file_operations rkisp1_stats_fops = {
> +	.mmap = vb2_fop_mmap,
> +	.unlocked_ioctl = video_ioctl2,
> +	.poll = vb2_fop_poll,
> +	.open = v4l2_fh_open,
> +	.release = vb2_fop_release
> +};
> +
> +static int rkisp1_stats_vb2_queue_setup(struct vb2_queue *vq,
> +					unsigned int *num_buffers,
> +					unsigned int *num_planes,
> +					unsigned int sizes[],
> +					struct device *alloc_devs[])
> +{
> +	struct rkisp1_isp_stats_vdev *stats_vdev = vq->drv_priv;
> +
> +	*num_planes = 1;
> +
> +	*num_buffers = clamp_t(u32, *num_buffers, RKISP1_ISP_STATS_REQ_BUFS_MIN,
> +			       RKISP1_ISP_STATS_REQ_BUFS_MAX);
> +
> +	sizes[0] = sizeof(struct rkisp1_stat_buffer);
> +
> +	INIT_LIST_HEAD(&stats_vdev->stat);
> +
> +	return 0;
> +}
> +
> +static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb)
> +{
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct rkisp1_buffer *stats_buf = to_rkisp1_buffer(vbuf);
> +	struct vb2_queue *vq = vb->vb2_queue;
> +	struct rkisp1_isp_stats_vdev *stats_dev = vq->drv_priv;
> +	unsigned long flags;
> +
> +	stats_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
> +	spin_lock_irqsave(&stats_dev->irq_lock, flags);
> +	list_add_tail(&stats_buf->queue, &stats_dev->stat);
> +	spin_unlock_irqrestore(&stats_dev->irq_lock, flags);
> +}
> +
> +static void rkisp1_stats_vb2_stop_streaming(struct vb2_queue *vq)
> +{
> +	struct rkisp1_isp_stats_vdev *stats_vdev = vq->drv_priv;
> +	struct rkisp1_buffer *buf;
> +	unsigned long flags;
> +	int i;
> +
> +	/* stop stats received firstly */
> +	spin_lock_irqsave(&stats_vdev->irq_lock, flags);
> +	stats_vdev->streamon = false;
> +	spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
> +
> +	drain_workqueue(stats_vdev->readout_wq);
> +
> +	for (i = 0; i < RKISP1_ISP_STATS_REQ_BUFS_MAX; i++) {
> +		spin_lock_irqsave(&stats_vdev->irq_lock, flags);
> +		if (!list_empty(&stats_vdev->stat)) {
> +			buf = list_first_entry(&stats_vdev->stat,
> +					       struct rkisp1_buffer, queue);
> +			list_del(&buf->queue);
> +			spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
> +		} else {
> +			spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
> +			break;
> +		}
> +
> +		if (buf)
> +			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> +		buf = NULL;
> +	}
> +}
> +
> +static int
> +rkisp1_stats_vb2_start_streaming(struct vb2_queue *queue,
> +				 unsigned int count)
> +{
> +	struct rkisp1_isp_stats_vdev *stats_vdev = queue->drv_priv;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&stats_vdev->irq_lock, flags);
> +	stats_vdev->streamon = true;
> +	spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
> +
> +	return 0;
> +}
> +
> +static struct vb2_ops rkisp1_stats_vb2_ops = {
> +	.queue_setup = rkisp1_stats_vb2_queue_setup,
> +	.buf_queue = rkisp1_stats_vb2_buf_queue,
> +	.wait_prepare = vb2_ops_wait_prepare,
> +	.wait_finish = vb2_ops_wait_finish,
> +	.stop_streaming = rkisp1_stats_vb2_stop_streaming,
> +	.start_streaming = rkisp1_stats_vb2_start_streaming,
> +};
> +
> +static int rkisp1_stats_init_vb2_queue(struct vb2_queue *q,
> +				       struct rkisp1_isp_stats_vdev *stats_vdev)
> +{
> +	struct rkisp1_vdev_node *node;
> +
> +	node = queue_to_node(q);
> +
> +	q->type = V4L2_BUF_TYPE_META_CAPTURE;
> +	q->io_modes = VB2_MMAP | VB2_USERPTR;

Either add VB2_DMABUF or drop expbuf from rkisp1_stats_ioctl.

> +	q->drv_priv = stats_vdev;
> +	q->ops = &rkisp1_stats_vb2_ops;
> +	q->mem_ops = &vb2_vmalloc_memops;
> +	q->buf_struct_size = sizeof(struct rkisp1_buffer);
> +	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
> +	q->lock = &node->vlock;
> +
> +	return vb2_queue_init(q);
> +}
> +
> +static void rkisp1_stats_get_awb_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
> +				      struct rkisp1_stat_buffer *pbuf)
> +{
> +	/* Protect against concurrent access from ISR? */
> +	u32 reg_val;
> +
> +	pbuf->meas_type |= CIFISP_STAT_AWB;
> +	reg_val = readl(stats_vdev->dev->base_addr + CIF_ISP_AWB_WHITE_CNT);
> +	pbuf->params.awb.awb_mean[0].cnt = CIF_ISP_AWB_GET_PIXEL_CNT(reg_val);
> +	reg_val = readl(stats_vdev->dev->base_addr + CIF_ISP_AWB_MEAN);
> +
> +	pbuf->params.awb.awb_mean[0].mean_cr_or_r =
> +		CIF_ISP_AWB_GET_MEAN_CR_R(reg_val);
> +	pbuf->params.awb.awb_mean[0].mean_cb_or_b =
> +		CIF_ISP_AWB_GET_MEAN_CB_B(reg_val);
> +	pbuf->params.awb.awb_mean[0].mean_y_or_g =
> +		CIF_ISP_AWB_GET_MEAN_Y_G(reg_val);
> +}
> +
> +static void rkisp1_stats_get_aec_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
> +				      struct rkisp1_stat_buffer *pbuf)
> +{
> +	unsigned int i;
> +	void __iomem *addr = stats_vdev->dev->base_addr + CIF_ISP_EXP_MEAN_00;
> +
> +	pbuf->meas_type |= CIFISP_STAT_AUTOEXP;
> +	for (i = 0; i < CIFISP_AE_MEAN_MAX; i++)
> +		pbuf->params.ae.exp_mean[i] = (u8)readl(addr + i * 4);
> +}
> +
> +static void rkisp1_stats_get_afc_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
> +				      struct rkisp1_stat_buffer *pbuf)
> +{
> +	void __iomem *base_addr;
> +	struct cifisp_af_stat *af;
> +
> +	pbuf->meas_type = CIFISP_STAT_AFM_FIN;
> +
> +	af = &pbuf->params.af;
> +	base_addr = stats_vdev->dev->base_addr;
> +	af->window[0].sum = readl(base_addr + CIF_ISP_AFM_SUM_A);
> +	af->window[0].lum = readl(base_addr + CIF_ISP_AFM_LUM_A);
> +	af->window[1].sum = readl(base_addr + CIF_ISP_AFM_SUM_B);
> +	af->window[1].lum = readl(base_addr + CIF_ISP_AFM_LUM_B);
> +	af->window[2].sum = readl(base_addr + CIF_ISP_AFM_SUM_C);
> +	af->window[2].lum = readl(base_addr + CIF_ISP_AFM_LUM_C);
> +}
> +
> +static void rkisp1_stats_get_hst_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
> +				      struct rkisp1_stat_buffer *pbuf)
> +{
> +	int i;
> +	void __iomem *addr = stats_vdev->dev->base_addr + CIF_ISP_HIST_BIN_0;
> +
> +	pbuf->meas_type |= CIFISP_STAT_HIST;
> +	for (i = 0; i < CIFISP_HIST_BIN_N_MAX; i++)
> +		pbuf->params.hist.hist_bins[i] = readl(addr + (i * 4));
> +}
> +
> +static void rkisp1_stats_get_bls_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
> +				      struct rkisp1_stat_buffer *pbuf)
> +{
> +	struct rkisp1_device *dev = stats_vdev->dev;
> +	const struct ispsd_in_fmt *in_fmt =
> +			rkisp1_get_ispsd_in_fmt(&dev->isp_sdev);
> +	void __iomem *base = stats_vdev->dev->base_addr;
> +	struct cifisp_bls_meas_val *bls_val;
> +
> +	bls_val = &pbuf->params.ae.bls_val;
> +	if (in_fmt->bayer_pat == RAW_BGGR) {
> +		bls_val->meas_b = readl(base + CIF_ISP_BLS_A_MEASURED);
> +		bls_val->meas_gb = readl(base + CIF_ISP_BLS_B_MEASURED);
> +		bls_val->meas_gr = readl(base + CIF_ISP_BLS_C_MEASURED);
> +		bls_val->meas_r = readl(base + CIF_ISP_BLS_D_MEASURED);
> +	} else if (in_fmt->bayer_pat == RAW_GBRG) {
> +		bls_val->meas_gb = readl(base + CIF_ISP_BLS_A_MEASURED);
> +		bls_val->meas_b = readl(base + CIF_ISP_BLS_B_MEASURED);
> +		bls_val->meas_r = readl(base + CIF_ISP_BLS_C_MEASURED);
> +		bls_val->meas_gr = readl(base + CIF_ISP_BLS_D_MEASURED);
> +	} else if (in_fmt->bayer_pat == RAW_GRBG) {
> +		bls_val->meas_gr = readl(base + CIF_ISP_BLS_A_MEASURED);
> +		bls_val->meas_r = readl(base + CIF_ISP_BLS_B_MEASURED);
> +		bls_val->meas_b = readl(base + CIF_ISP_BLS_C_MEASURED);
> +		bls_val->meas_gb = readl(base + CIF_ISP_BLS_D_MEASURED);
> +	} else if (in_fmt->bayer_pat == RAW_RGGB) {
> +		bls_val->meas_r = readl(base + CIF_ISP_BLS_A_MEASURED);
> +		bls_val->meas_gr = readl(base + CIF_ISP_BLS_B_MEASURED);
> +		bls_val->meas_gb = readl(base + CIF_ISP_BLS_C_MEASURED);
> +		bls_val->meas_b = readl(base + CIF_ISP_BLS_D_MEASURED);
> +	}
> +}
> +
> +static void
> +rkisp1_stats_send_measurement(struct rkisp1_isp_stats_vdev *stats_vdev,
> +			      struct rkisp1_isp_readout_work *meas_work)
> +{
> +	unsigned long lock_flags = 0;
> +	unsigned int cur_frame_id = -1;
> +	struct rkisp1_stat_buffer *cur_stat_buf;
> +	struct rkisp1_buffer *cur_buf = NULL;
> +
> +	spin_lock_irqsave(&stats_vdev->irq_lock, lock_flags);
> +	cur_frame_id = atomic_read(&stats_vdev->dev->isp_sdev.frm_sync_seq) - 1;
> +	if (cur_frame_id != meas_work->frame_id) {
> +		v4l2_warn(stats_vdev->vnode.vdev.v4l2_dev,
> +			  "Measurement late(%d, %d)\n",
> +			  cur_frame_id, meas_work->frame_id);
> +	}
> +	/* get one empty buffer */
> +	if (!list_empty(&stats_vdev->stat)) {
> +		cur_buf = list_first_entry(&stats_vdev->stat,
> +					   struct rkisp1_buffer, queue);
> +		list_del(&cur_buf->queue);
> +	}
> +	spin_unlock_irqrestore(&stats_vdev->irq_lock, lock_flags);
> +
> +	if (!cur_buf)
> +		return;
> +
> +	cur_stat_buf =
> +		(struct rkisp1_stat_buffer *)(cur_buf->vaddr[0]);
> +
> +	if (meas_work->isp_ris & CIF_ISP_AWB_DONE) {
> +		rkisp1_stats_get_awb_meas(stats_vdev, cur_stat_buf);
> +		cur_stat_buf->meas_type |= CIFISP_STAT_AWB;
> +	}
> +
> +	if (meas_work->isp_ris & CIF_ISP_AFM_FIN) {
> +		rkisp1_stats_get_afc_meas(stats_vdev, cur_stat_buf);
> +		cur_stat_buf->meas_type |= CIFISP_STAT_AFM_FIN;
> +	}
> +
> +	if (meas_work->isp_ris & CIF_ISP_EXP_END) {
> +		rkisp1_stats_get_aec_meas(stats_vdev, cur_stat_buf);
> +		rkisp1_stats_get_bls_meas(stats_vdev, cur_stat_buf);
> +		cur_stat_buf->meas_type |= CIFISP_STAT_AUTOEXP;
> +	}
> +
> +	if (meas_work->isp_ris & CIF_ISP_HIST_MEASURE_RDY) {
> +		rkisp1_stats_get_hst_meas(stats_vdev, cur_stat_buf);
> +		cur_stat_buf->meas_type |= CIFISP_STAT_HIST;
> +	}
> +
> +	vb2_set_plane_payload(&cur_buf->vb.vb2_buf, 0,
> +			      sizeof(struct rkisp1_stat_buffer));
> +	cur_buf->vb.sequence = cur_frame_id;
> +	cur_buf->vb.vb2_buf.timestamp = ktime_get_ns();
> +	vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
> +}
> +
> +static void rkisp1_stats_readout_work(struct work_struct *work)
> +{
> +	struct rkisp1_isp_readout_work *readout_work = container_of(work,
> +						struct rkisp1_isp_readout_work,
> +						work);
> +	struct rkisp1_isp_stats_vdev *stats_vdev = readout_work->stats_vdev;
> +
> +	if (readout_work->readout == RKISP1_ISP_READOUT_MEAS)
> +		rkisp1_stats_send_measurement(stats_vdev, readout_work);
> +
> +	kfree(readout_work);
> +}
> +
> +int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris)
> +{
> +	unsigned int isp_mis_tmp = 0;
> +	struct rkisp1_isp_readout_work *work;
> +	unsigned int cur_frame_id =
> +		atomic_read(&stats_vdev->dev->isp_sdev.frm_sync_seq) - 1;
> +#ifdef LOG_ISR_EXE_TIME
> +	ktime_t in_t = ktime_get();
> +#endif
> +
> +	writel((CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN | CIF_ISP_EXP_END |
> +		CIF_ISP_HIST_MEASURE_RDY),
> +		stats_vdev->dev->base_addr + CIF_ISP_ICR);
> +
> +	isp_mis_tmp = readl(stats_vdev->dev->base_addr + CIF_ISP_MIS);
> +	if (isp_mis_tmp &
> +		(CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
> +		 CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
> +		v4l2_err(stats_vdev->vnode.vdev.v4l2_dev,
> +			 "isp icr 3A info err: 0x%x\n",
> +			 isp_mis_tmp);
> +
> +	if (isp_ris & (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN | CIF_ISP_EXP_END |
> +		CIF_ISP_HIST_MEASURE_RDY)) {
> +		work = (struct rkisp1_isp_readout_work *)
> +			kzalloc(sizeof(struct rkisp1_isp_readout_work),
> +				GFP_ATOMIC);
> +		if (work) {
> +			INIT_WORK(&work->work,
> +				  rkisp1_stats_readout_work);
> +			work->readout = RKISP1_ISP_READOUT_MEAS;
> +			work->stats_vdev = stats_vdev;
> +			work->frame_id = cur_frame_id;
> +			work->isp_ris = isp_ris;
> +			if (!queue_work(stats_vdev->readout_wq,
> +					&work->work))
> +				kfree(work);
> +		} else {
> +			v4l2_err(stats_vdev->vnode.vdev.v4l2_dev,
> +				 "Could not allocate work\n");
> +		}
> +	}
> +
> +#ifdef LOG_ISR_EXE_TIME
> +	if (isp_ris & (CIF_ISP_EXP_END | CIF_ISP_AWB_DONE |
> +		       CIF_ISP_FRAME | CIF_ISP_HIST_MEASURE_RDY)) {
> +		unsigned int diff_us =
> +		    ktime_to_us(ktime_sub(ktime_get(), in_t));
> +
> +		if (diff_us > g_longest_isr_time)
> +			g_longest_isr_time = diff_us;
> +
> +		v4l2_info(stats_vdev->vnode.vdev.v4l2_dev,
> +			  "isp_isr time %d %d\n", diff_us, g_longest_isr_time);
> +	}
> +#endif
> +
> +	return 0;
> +}
> +
> +static void rkisp1_init_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev)
> +{
> +	stats_vdev->vdev_fmt.fmt.meta.dataformat =
> +		V4L2_META_FMT_RK_ISP1_STAT_3A;
> +	stats_vdev->vdev_fmt.fmt.meta.buffersize =
> +		sizeof(struct rkisp1_stat_buffer);
> +}
> +
> +int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev,
> +			       struct v4l2_device *v4l2_dev,
> +			       struct rkisp1_device *dev)
> +{
> +	int ret;
> +	struct rkisp1_vdev_node *node = &stats_vdev->vnode;
> +	struct video_device *vdev = &node->vdev;
> +
> +	stats_vdev->dev = dev;
> +	mutex_init(&node->vlock);
> +	INIT_LIST_HEAD(&stats_vdev->stat);
> +	spin_lock_init(&stats_vdev->irq_lock);
> +
> +	strlcpy(vdev->name, "rkisp1-statistics", sizeof(vdev->name));
> +
> +	video_set_drvdata(vdev, stats_vdev);
> +	vdev->ioctl_ops = &rkisp1_stats_ioctl;
> +	vdev->fops = &rkisp1_stats_fops;
> +	vdev->release = video_device_release_empty;
> +	vdev->lock = &node->vlock;
> +	vdev->v4l2_dev = v4l2_dev;
> +	vdev->queue = &node->buf_queue;
> +	vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING;
> +	vdev->vfl_dir =  VFL_DIR_RX;
> +	rkisp1_stats_init_vb2_queue(vdev->queue, stats_vdev);
> +	rkisp1_init_stats_vdev(stats_vdev);
> +	video_set_drvdata(vdev, stats_vdev);
> +
> +	node->pad.flags = MEDIA_PAD_FL_SINK;
> +	vdev->entity.function = MEDIA_ENT_F_IO_V4L;
> +	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
> +	if (ret < 0)
> +		goto err_release_queue;
> +
> +	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
> +	if (ret < 0) {
> +		dev_err(&vdev->dev,
> +			"could not register Video for Linux device\n");
> +		goto err_cleanup_media_entity;
> +	}
> +
> +	stats_vdev->readout_wq =
> +	    alloc_workqueue("measurement_queue",
> +			    WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
> +
> +	if (!stats_vdev->readout_wq) {
> +		ret = -ENOMEM;
> +			goto err_unreg_vdev;
> +	}
> +
> +	return 0;
> +err_unreg_vdev:
> +	video_unregister_device(vdev);
> +err_cleanup_media_entity:
> +	media_entity_cleanup(&vdev->entity);
> +err_release_queue:
> +	vb2_queue_release(vdev->queue);
> +	return ret;
> +}
> +
> +void rkisp1_unregister_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev)
> +{
> +	struct rkisp1_vdev_node *node = &stats_vdev->vnode;
> +	struct video_device *vdev = &node->vdev;
> +
> +	destroy_workqueue(stats_vdev->readout_wq);
> +	video_unregister_device(vdev);
> +	media_entity_cleanup(&vdev->entity);
> +	vb2_queue_release(vdev->queue);
> +}
> diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.h b/drivers/media/platform/rockchip/isp1/isp_stats.h
> new file mode 100644
> index 000000000000..71fd4e447fd9
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/isp_stats.h
> @@ -0,0 +1,85 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef _RKISP1_ISP_STATS_H
> +#define _RKISP1_ISP_STATS_H
> +
> +#include <linux/rkisp1-config.h>
> +#include "common.h"
> +
> +struct rkisp1_isp_stats_vdev;
> +
> +enum rkisp1_isp_readout_cmd {
> +	RKISP1_ISP_READOUT_MEAS,
> +	RKISP1_ISP_READOUT_META,
> +};
> +
> +struct rkisp1_isp_readout_work {
> +	struct work_struct work;
> +	struct rkisp1_isp_stats_vdev *stats_vdev;
> +
> +	unsigned int frame_id;
> +	unsigned int isp_ris;
> +	enum rkisp1_isp_readout_cmd readout;
> +	struct vb2_buffer *vb;
> +};
> +
> +/*
> + * struct rkisp1_isp_stats_vdev - ISP Statistics device
> + *
> + * @irq_lock: buffer queue lock
> + * @stat: stats buffer list
> + * @readout_wq: workqueue for statistics information read
> + */
> +struct rkisp1_isp_stats_vdev {
> +	struct rkisp1_vdev_node vnode;
> +	struct rkisp1_device *dev;
> +
> +	spinlock_t irq_lock;
> +	struct list_head stat;
> +	struct v4l2_format vdev_fmt;
> +	bool streamon;
> +
> +	struct workqueue_struct *readout_wq;
> +};
> +
> +int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris);
> +
> +int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev,
> +			       struct v4l2_device *v4l2_dev,
> +			       struct rkisp1_device *dev);
> +
> +void rkisp1_unregister_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev);
> +
> +#endif /* _RKISP1_ISP_STATS_H */
> diff --git a/drivers/media/platform/rockchip/isp1/regs.c b/drivers/media/platform/rockchip/isp1/regs.c
> new file mode 100644
> index 000000000000..46b9898044d4
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/regs.c
> @@ -0,0 +1,264 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include <media/v4l2-common.h>
> +#include "regs.h"
> +
> +void disable_dcrop(struct rkisp1_stream *stream, bool async)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +	void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
> +	u32 dc_ctrl = readl(dc_ctrl_addr);
> +	u32 mask = ~(stream->config->dual_crop.yuvmode_mask |
> +			stream->config->dual_crop.rawmode_mask);
> +	u32 val = dc_ctrl & mask;
> +
> +	if (async)
> +		val |= CIF_DUAL_CROP_GEN_CFG_UPD;
> +	else
> +		val |= CIF_DUAL_CROP_CFG_UPD;
> +	writel(val, dc_ctrl_addr);
> +}
> +
> +void config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect, bool async)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +	void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
> +	u32 dc_ctrl = readl(dc_ctrl_addr);
> +
> +	writel(rect->left, base + stream->config->dual_crop.h_offset);
> +	writel(rect->top, base + stream->config->dual_crop.v_offset);
> +	writel(rect->width, base + stream->config->dual_crop.h_size);
> +	writel(rect->height, base + stream->config->dual_crop.v_size);
> +	dc_ctrl |= stream->config->dual_crop.yuvmode_mask;
> +	if (async)
> +		dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
> +	else
> +		dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
> +	writel(dc_ctrl, dc_ctrl_addr);
> +}
> +
> +void dump_rsz_regs(struct rkisp1_stream *stream)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	pr_info("RSZ_CTRL 0x%08x/0x%08x\n"
> +			"RSZ_SCALE_HY %d/%d\n"
> +			"RSZ_SCALE_HCB %d/%d\n"
> +			"RSZ_SCALE_HCR %d/%d\n"
> +			"RSZ_SCALE_VY %d/%d\n"
> +			"RSZ_SCALE_VC %d/%d\n"
> +			"RSZ_PHASE_HY %d/%d\n"
> +			"RSZ_PHASE_HC %d/%d\n"
> +			"RSZ_PHASE_VY %d/%d\n"
> +			"RSZ_PHASE_VC %d/%d\n",
> +			readl(base + stream->config->rsz.ctrl),
> +			readl(base + stream->config->rsz.ctrl_shd),
> +			readl(base + stream->config->rsz.scale_hy),
> +			readl(base + stream->config->rsz.scale_hy_shd),
> +			readl(base + stream->config->rsz.scale_hcb),
> +			readl(base + stream->config->rsz.scale_hcb_shd),
> +			readl(base + stream->config->rsz.scale_hcr),
> +			readl(base + stream->config->rsz.scale_hcr_shd),
> +			readl(base + stream->config->rsz.scale_vy),
> +			readl(base + stream->config->rsz.scale_vy_shd),
> +			readl(base + stream->config->rsz.scale_vc),
> +			readl(base + stream->config->rsz.scale_vc_shd),
> +			readl(base + stream->config->rsz.phase_hy),
> +			readl(base + stream->config->rsz.phase_hy_shd),
> +			readl(base + stream->config->rsz.phase_hc),
> +			readl(base + stream->config->rsz.phase_hc_shd),
> +			readl(base + stream->config->rsz.phase_vy),
> +			readl(base + stream->config->rsz.phase_vy_shd),
> +			readl(base + stream->config->rsz.phase_vc),
> +			readl(base + stream->config->rsz.phase_vc_shd));
> +}
> +
> +static void update_rsz_shadow(struct rkisp1_stream *stream)
> +{
> +	void *addr = stream->ispdev->base_addr + stream->config->rsz.ctrl;
> +	u32 ctrl_cfg = readl(addr);
> +
> +	writel(CIF_RSZ_CTRL_CFG_UPD | ctrl_cfg, addr);
> +}
> +
> +static void set_scale(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
> +		struct v4l2_rect *in_c, struct v4l2_rect *out_y,
> +		struct v4l2_rect *out_c)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +	void __iomem *scale_hy_addr = base + stream->config->rsz.scale_hy;
> +	void __iomem *scale_hcr_addr = base + stream->config->rsz.scale_hcr;
> +	void __iomem *scale_hcb_addr = base + stream->config->rsz.scale_hcb;
> +	void __iomem *scale_vy_addr = base + stream->config->rsz.scale_vy;
> +	void __iomem *scale_vc_addr = base + stream->config->rsz.scale_vc;
> +	void __iomem *rsz_ctrl_addr = base + stream->config->rsz.ctrl;
> +	u32 scale_hy, scale_hc, scale_vy, scale_vc, rsz_ctrl = 0;
> +
> +	if (in_y->width < out_y->width) {
> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE |
> +				CIF_RSZ_CTRL_SCALE_HY_UP;
> +		scale_hy = ((in_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
> +				(out_y->width - 1);
> +		writel(scale_hy, scale_hy_addr);
> +	} else if (in_y->width > out_y->width) {
> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE;
> +		scale_hy = ((out_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
> +				(in_y->width - 1) + 1;
> +		writel(scale_hy, scale_hy_addr);
> +	}
> +	if (in_c->width < out_c->width) {
> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE |
> +				CIF_RSZ_CTRL_SCALE_HC_UP;
> +		scale_hc = ((in_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
> +				(out_c->width - 1);
> +		writel(scale_hc, scale_hcb_addr);
> +		writel(scale_hc, scale_hcr_addr);
> +	} else if (in_c->width > out_c->width) {
> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE;
> +		scale_hc = ((out_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
> +				(in_c->width - 1) + 1;
> +		writel(scale_hc, scale_hcb_addr);
> +		writel(scale_hc, scale_hcr_addr);
> +	}
> +
> +	if (in_y->height < out_y->height) {
> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE |
> +				CIF_RSZ_CTRL_SCALE_VY_UP;
> +		scale_vy = ((in_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
> +				(out_y->height - 1);
> +		writel(scale_vy, scale_vy_addr);
> +	} else if (in_y->height > out_y->height) {
> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE;
> +		scale_vy = ((out_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
> +				(in_y->height - 1) + 1;
> +		writel(scale_vy, scale_vy_addr);
> +	}
> +
> +	if (in_c->height < out_c->height) {
> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE |
> +				CIF_RSZ_CTRL_SCALE_VC_UP;
> +		scale_vc = ((in_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
> +				(out_c->height - 1);
> +		writel(scale_vc, scale_vc_addr);
> +	} else if (in_c->height > out_c->height) {
> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE;
> +		scale_vc = ((out_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
> +				(in_c->height - 1) + 1;
> +		writel(scale_vc, scale_vc_addr);
> +	}
> +
> +	writel(rsz_ctrl, rsz_ctrl_addr);
> +}
> +
> +void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
> +	struct v4l2_rect *in_c, struct v4l2_rect *out_y,
> +	struct v4l2_rect *out_c, bool async)
> +{
> +	int i = 0;
> +
> +	/* No phase offset */
> +	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_hy);
> +	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_hc);
> +	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_vy);
> +	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_vc);
> +
> +	/* Linear interpolation */
> +	for (i = 0; i < 64; i++) {
> +		writel(i, stream->ispdev->base_addr + stream->config->rsz.scale_lut_addr);
> +		writel(i, stream->ispdev->base_addr + stream->config->rsz.scale_lut);
> +	}
> +
> +	set_scale(stream, in_y, in_c, out_y, out_c);
> +
> +	if (!async)
> +		update_rsz_shadow(stream);
> +}
> +
> +void disable_rsz(struct rkisp1_stream *stream, bool async)
> +{
> +	writel(0, stream->ispdev->base_addr + stream->config->rsz.ctrl);
> +
> +	if (!async)
> +		update_rsz_shadow(stream);
> +}
> +
> +void config_mi_ctrl(struct rkisp1_stream *stream)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +	u32 reg;
> +
> +	reg = readl(addr) & ~GENMASK(17, 16);
> +	writel(reg | CIF_MI_CTRL_BURST_LEN_LUM_64, addr);
> +	reg = readl(addr) & ~GENMASK(19, 18);
> +	writel(reg | CIF_MI_CTRL_BURST_LEN_CHROM_64, addr);
> +	reg = readl(addr);
> +	writel(reg | CIF_MI_CTRL_INIT_BASE_EN, addr);
> +	reg = readl(addr);
> +	writel(reg | CIF_MI_CTRL_INIT_OFFSET_EN, addr);
> +}
> +
> +void mp_clr_frame_end_int(void __iomem *base)
> +{
> +	writel(CIF_MI_MP_FRAME, base + CIF_MI_ICR);
> +}
> +
> +void sp_clr_frame_end_int(void __iomem *base)
> +{
> +	writel(CIF_MI_SP_FRAME, base + CIF_MI_ICR);
> +}
> +
> +bool mp_is_frame_end_int_masked(void __iomem *base)
> +{
> +	return (mi_get_masked_int_status(base) & CIF_MI_MP_FRAME);
> +}
> +
> +bool sp_is_frame_end_int_masked(void __iomem *base)
> +{
> +	return (mi_get_masked_int_status(base) & CIF_MI_SP_FRAME);
> +}
> +
> +bool mp_is_stream_stopped(void __iomem *base)
> +{
> +	int en;
> +
> +	en = CIF_MI_CTRL_SHD_MP_IN_ENABLED | CIF_MI_CTRL_SHD_RAW_OUT_ENABLED;
> +	return !(readl(base + CIF_MI_CTRL_SHD) & en);
> +}
> +
> +bool sp_is_stream_stopped(void __iomem *base)
> +{
> +	return !(readl(base + CIF_MI_CTRL_SHD) & CIF_MI_CTRL_SHD_SP_IN_ENABLED);
> +}
> diff --git a/drivers/media/platform/rockchip/isp1/regs.h b/drivers/media/platform/rockchip/isp1/regs.h
> new file mode 100644
> index 000000000000..e8709b639bc2
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/regs.h
> @@ -0,0 +1,1582 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef _RKISP1_REGS_H
> +#define _RKISP1_REGS_H
> +#include "dev.h"
> +
> +/* ISP_CTRL */
> +#define CIF_ISP_CTRL_ISP_ENABLE			BIT(0)
> +#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT		(0 << 1)
> +#define CIF_ISP_CTRL_ISP_MODE_ITU656		(1 << 1)
> +#define CIF_ISP_CTRL_ISP_MODE_ITU601		(2 << 1)
> +#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601	(3 << 1)
> +#define CIF_ISP_CTRL_ISP_MODE_DATA_MODE		(4 << 1)
> +#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656	(5 << 1)
> +#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656	(6 << 1)
> +#define CIF_ISP_CTRL_ISP_INFORM_ENABLE		BIT(4)
> +#define CIF_ISP_CTRL_ISP_GAMMA_IN_ENA		BIT(6)
> +#define CIF_ISP_CTRL_ISP_AWB_ENA		BIT(7)
> +#define CIF_ISP_CTRL_ISP_CFG_UPD_PERMANENT	BIT(8)
> +#define CIF_ISP_CTRL_ISP_CFG_UPD		BIT(9)
> +#define CIF_ISP_CTRL_ISP_GEN_CFG_UPD		BIT(10)
> +#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA		BIT(11)
> +#define CIF_ISP_CTRL_ISP_FLASH_MODE_ENA		BIT(12)
> +#define CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA		BIT(13)
> +#define CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA		BIT(14)
> +
> +/* ISP_ACQ_PROP */
> +#define CIF_ISP_ACQ_PROP_POS_EDGE		BIT(0)
> +#define CIF_ISP_ACQ_PROP_HSYNC_LOW		BIT(1)
> +#define CIF_ISP_ACQ_PROP_VSYNC_LOW		BIT(2)
> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB		(0 << 3)
> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG		(1 << 3)
> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG		(2 << 3)
> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR		(3 << 3)
> +#define CIF_ISP_ACQ_PROP_BAYER_PAT(pat)		((pat) << 3)
> +#define CIF_ISP_ACQ_PROP_YCBYCR			(0 << 7)
> +#define CIF_ISP_ACQ_PROP_YCRYCB			(1 << 7)
> +#define CIF_ISP_ACQ_PROP_CBYCRY			(2 << 7)
> +#define CIF_ISP_ACQ_PROP_CRYCBY			(3 << 7)
> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_ALL		(0 << 9)
> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_EVEN		(1 << 9)
> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_ODD		(2 << 9)
> +#define CIF_ISP_ACQ_PROP_IN_SEL_12B		(0 << 12)
> +#define CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO	(1 << 12)
> +#define CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB		(2 << 12)
> +#define CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO		(3 << 12)
> +#define CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB		(4 << 12)
> +
> +/* VI_DPCL */
> +#define CIF_VI_DPCL_DMA_JPEG			(0 << 0)
> +#define CIF_VI_DPCL_MP_MUX_MRSZ_MI		(1 << 0)
> +#define CIF_VI_DPCL_MP_MUX_MRSZ_JPEG		(2 << 0)
> +#define CIF_VI_DPCL_CHAN_MODE_MP		(1 << 2)
> +#define CIF_VI_DPCL_CHAN_MODE_SP		(2 << 2)
> +#define CIF_VI_DPCL_CHAN_MODE_MPSP		(3 << 2)
> +#define CIF_VI_DPCL_DMA_SW_SPMUX		(0 << 4)
> +#define CIF_VI_DPCL_DMA_SW_SI			(1 << 4)
> +#define CIF_VI_DPCL_DMA_SW_IE			(2 << 4)
> +#define CIF_VI_DPCL_DMA_SW_JPEG			(3 << 4)
> +#define CIF_VI_DPCL_DMA_SW_ISP			(4 << 4)
> +#define CIF_VI_DPCL_IF_SEL_PARALLEL		(0 << 8)
> +#define CIF_VI_DPCL_IF_SEL_SMIA			(1 << 8)
> +#define CIF_VI_DPCL_IF_SEL_MIPI			(2 << 8)
> +#define CIF_VI_DPCL_DMA_IE_MUX_DMA		BIT(10)
> +#define CIF_VI_DPCL_DMA_SP_MUX_DMA		BIT(11)
> +
> +/* ISP_IMSC - ISP_MIS - ISP_RIS - ISP_ICR - ISP_ISR */
> +#define CIF_ISP_OFF				BIT(0)
> +#define CIF_ISP_FRAME				BIT(1)
> +#define CIF_ISP_DATA_LOSS			BIT(2)
> +#define CIF_ISP_PIC_SIZE_ERROR			BIT(3)
> +#define CIF_ISP_AWB_DONE			BIT(4)
> +#define CIF_ISP_FRAME_IN			BIT(5)
> +#define CIF_ISP_V_START				BIT(6)
> +#define CIF_ISP_H_START				BIT(7)
> +#define CIF_ISP_FLASH_ON			BIT(8)
> +#define CIF_ISP_FLASH_OFF			BIT(9)
> +#define CIF_ISP_SHUTTER_ON			BIT(10)
> +#define CIF_ISP_SHUTTER_OFF			BIT(11)
> +#define CIF_ISP_AFM_SUM_OF			BIT(12)
> +#define CIF_ISP_AFM_LUM_OF			BIT(13)
> +#define CIF_ISP_AFM_FIN				BIT(14)
> +#define CIF_ISP_HIST_MEASURE_RDY		BIT(15)
> +#define CIF_ISP_FLASH_CAP			BIT(17)
> +#define CIF_ISP_EXP_END				BIT(18)
> +#define CIF_ISP_VSM_END				BIT(19)
> +
> +/* ISP_ERR */
> +#define CIF_ISP_ERR_INFORM_SIZE			BIT(0)
> +#define CIF_ISP_ERR_IS_SIZE			BIT(1)
> +#define CIF_ISP_ERR_OUTFORM_SIZE		BIT(2)
> +
> +/* MI_CTRL */
> +#define CIF_MI_CTRL_MP_ENABLE			(1 << 0)
> +#define CIF_MI_CTRL_SP_ENABLE			(2 << 0)
> +#define CIF_MI_CTRL_JPEG_ENABLE			(4 << 0)
> +#define CIF_MI_CTRL_RAW_ENABLE			(8 << 0)
> +#define CIF_MI_CTRL_HFLIP			BIT(4)
> +#define CIF_MI_CTRL_VFLIP			BIT(5)
> +#define CIF_MI_CTRL_ROT				BIT(6)
> +#define CIF_MI_BYTE_SWAP			BIT(7)
> +#define CIF_MI_SP_Y_FULL_YUV2RGB		BIT(8)
> +#define CIF_MI_SP_CBCR_FULL_YUV2RGB		BIT(9)
> +#define CIF_MI_SP_422NONCOSITEED		BIT(10)
> +#define CIF_MI_MP_PINGPONG_ENABEL		BIT(11)
> +#define CIF_MI_SP_PINGPONG_ENABEL		BIT(12)
> +#define CIF_MI_MP_AUTOUPDATE_ENABLE		BIT(13)
> +#define CIF_MI_SP_AUTOUPDATE_ENABLE		BIT(14)
> +#define CIF_MI_LAST_PIXEL_SIG_ENABLE		BIT(15)
> +#define CIF_MI_CTRL_BURST_LEN_LUM_16		(0 << 16)
> +#define CIF_MI_CTRL_BURST_LEN_LUM_32		(1 << 16)
> +#define CIF_MI_CTRL_BURST_LEN_LUM_64		(2 << 16)
> +#define CIF_MI_CTRL_BURST_LEN_CHROM_16		(0 << 18)
> +#define CIF_MI_CTRL_BURST_LEN_CHROM_32		(1 << 18)
> +#define CIF_MI_CTRL_BURST_LEN_CHROM_64		(2 << 18)
> +#define CIF_MI_CTRL_INIT_BASE_EN		BIT(20)
> +#define CIF_MI_CTRL_INIT_OFFSET_EN		BIT(21)
> +#define MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8	(0 << 22)
> +#define MI_CTRL_MP_WRITE_YUV_SPLA		(1 << 22)
> +#define MI_CTRL_MP_WRITE_YUVINT			(2 << 22)
> +#define MI_CTRL_MP_WRITE_RAW12			(2 << 22)
> +#define MI_CTRL_SP_WRITE_PLA			(0 << 24)
> +#define MI_CTRL_SP_WRITE_SPLA			(1 << 24)
> +#define MI_CTRL_SP_WRITE_INT			(2 << 24)
> +#define MI_CTRL_SP_INPUT_YUV400			(0 << 26)
> +#define MI_CTRL_SP_INPUT_YUV420			(1 << 26)
> +#define MI_CTRL_SP_INPUT_YUV422			(2 << 26)
> +#define MI_CTRL_SP_INPUT_YUV444			(3 << 26)
> +#define MI_CTRL_SP_OUTPUT_YUV400		(0 << 28)
> +#define MI_CTRL_SP_OUTPUT_YUV420		(1 << 28)
> +#define MI_CTRL_SP_OUTPUT_YUV422		(2 << 28)
> +#define MI_CTRL_SP_OUTPUT_YUV444		(3 << 28)
> +#define MI_CTRL_SP_OUTPUT_RGB565		(4 << 28)
> +#define MI_CTRL_SP_OUTPUT_RGB666		(5 << 28)
> +#define MI_CTRL_SP_OUTPUT_RGB888		(6 << 28)
> +
> +#define MI_CTRL_MP_FMT_MASK			GENMASK(23, 22)
> +#define MI_CTRL_SP_FMT_MASK			GENMASK(30, 24)
> +
> +/* MI_INIT */
> +#define CIF_MI_INIT_SKIP			BIT(2)
> +#define CIF_MI_INIT_SOFT_UPD			BIT(4)
> +
> +/* MI_CTRL_SHD */
> +#define CIF_MI_CTRL_SHD_MP_IN_ENABLED		BIT(0)
> +#define CIF_MI_CTRL_SHD_SP_IN_ENABLED		BIT(1)
> +#define CIF_MI_CTRL_SHD_JPEG_IN_ENABLED		BIT(2)
> +#define CIF_MI_CTRL_SHD_RAW_IN_ENABLED		BIT(3)
> +#define CIF_MI_CTRL_SHD_MP_OUT_ENABLED		BIT(16)
> +#define CIF_MI_CTRL_SHD_SP_OUT_ENABLED		BIT(17)
> +#define CIF_MI_CTRL_SHD_JPEG_OUT_ENABLED	BIT(18)
> +#define CIF_MI_CTRL_SHD_RAW_OUT_ENABLED		BIT(19)
> +
> +/* RSZ_CTRL */
> +#define CIF_RSZ_CTRL_SCALE_HY_ENABLE		BIT(0)
> +#define CIF_RSZ_CTRL_SCALE_HC_ENABLE		BIT(1)
> +#define CIF_RSZ_CTRL_SCALE_VY_ENABLE		BIT(2)
> +#define CIF_RSZ_CTRL_SCALE_VC_ENABLE		BIT(3)
> +#define CIF_RSZ_CTRL_SCALE_HY_UP		BIT(4)
> +#define CIF_RSZ_CTRL_SCALE_HC_UP		BIT(5)
> +#define CIF_RSZ_CTRL_SCALE_VY_UP		BIT(6)
> +#define CIF_RSZ_CTRL_SCALE_VC_UP		BIT(7)
> +#define CIF_RSZ_CTRL_CFG_UPD			BIT(8)
> +#define CIF_RSZ_CTRL_CFG_UPD_AUTO		BIT(9)
> +#define CIF_RSZ_SCALER_FACTOR			BIT(16)
> +
> +/* MI_IMSC - MI_MIS - MI_RIS - MI_ICR - MI_ISR */
> +#define CIF_MI_MP_FRAME				BIT(0)
> +#define CIF_MI_SP_FRAME				BIT(1)
> +#define CIF_MI_MBLK_LINE			BIT(2)
> +#define CIF_MI_FILL_MP_Y			BIT(3)
> +#define CIF_MI_WRAP_MP_Y			BIT(4)
> +#define CIF_MI_WRAP_MP_CB			BIT(5)
> +#define CIF_MI_WRAP_MP_CR			BIT(6)
> +#define CIF_MI_WRAP_SP_Y			BIT(7)
> +#define CIF_MI_WRAP_SP_CB			BIT(8)
> +#define CIF_MI_WRAP_SP_CR			BIT(9)
> +#define CIF_MI_DMA_READY			BIT(11)
> +
> +/* MI_STATUS */
> +#define CIF_MI_STATUS_MP_Y_FIFO_FULL		BIT(0)
> +#define CIF_MI_STATUS_SP_Y_FIFO_FULL		BIT(4)
> +
> +/* MI_DMA_CTRL */
> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_16	(0 << 0)
> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_32	(1 << 0)
> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_64	(2 << 0)
> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_16	(0 << 2)
> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_32	(1 << 2)
> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64	(2 << 2)
> +#define CIF_MI_DMA_CTRL_READ_FMT_PLANAR		(0 << 4)
> +#define CIF_MI_DMA_CTRL_READ_FMT_SPLANAR	(1 << 4)
> +#define CIF_MI_DMA_CTRL_FMT_YUV400		(0 << 6)
> +#define CIF_MI_DMA_CTRL_FMT_YUV420		(1 << 6)
> +#define CIF_MI_DMA_CTRL_READ_FMT_PACKED		(2 << 4)
> +#define CIF_MI_DMA_CTRL_FMT_YUV422		(2 << 6)
> +#define CIF_MI_DMA_CTRL_FMT_YUV444		(3 << 6)
> +#define CIF_MI_DMA_CTRL_BYTE_SWAP		BIT(8)
> +#define CIF_MI_DMA_CTRL_CONTINUOUS_ENA		BIT(9)
> +#define CIF_MI_DMA_CTRL_RGB_BAYER_NO		(0 << 12)
> +#define CIF_MI_DMA_CTRL_RGB_BAYER_8BIT		(1 << 12)
> +#define CIF_MI_DMA_CTRL_RGB_BAYER_16BIT		(2 << 12)
> +/* MI_DMA_START */
> +#define CIF_MI_DMA_START_ENABLE			BIT(0)
> +/* MI_XTD_FORMAT_CTRL  */
> +#define CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP	BIT(0)
> +#define CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP	BIT(1)
> +#define CIF_MI_XTD_FMT_CTRL_DMA_CB_CR_SWAP	BIT(2)
> +
> +/* CCL */
> +#define CIF_CCL_CIF_CLK_DIS			BIT(2)
> +/* ICCL */
> +#define CIF_ICCL_ISP_CLK			BIT(0)
> +#define CIF_ICCL_CP_CLK				BIT(1)
> +#define CIF_ICCL_RES_2				BIT(2)
> +#define CIF_ICCL_MRSZ_CLK			BIT(3)
> +#define CIF_ICCL_SRSZ_CLK			BIT(4)
> +#define CIF_ICCL_JPEG_CLK			BIT(5)
> +#define CIF_ICCL_MI_CLK				BIT(6)
> +#define CIF_ICCL_RES_7				BIT(7)
> +#define CIF_ICCL_IE_CLK				BIT(8)
> +#define CIF_ICCL_SIMP_CLK			BIT(9)
> +#define CIF_ICCL_SMIA_CLK			BIT(10)
> +#define CIF_ICCL_MIPI_CLK			BIT(11)
> +#define CIF_ICCL_DCROP_CLK			BIT(12)
> +/* IRCL */
> +#define CIF_IRCL_ISP_SW_RST			BIT(0)
> +#define CIF_IRCL_CP_SW_RST			BIT(1)
> +#define CIF_IRCL_YCS_SW_RST			BIT(2)
> +#define CIF_IRCL_MRSZ_SW_RST			BIT(3)
> +#define CIF_IRCL_SRSZ_SW_RST			BIT(4)
> +#define CIF_IRCL_JPEG_SW_RST			BIT(5)
> +#define CIF_IRCL_MI_SW_RST			BIT(6)
> +#define CIF_IRCL_CIF_SW_RST			BIT(7)
> +#define CIF_IRCL_IE_SW_RST			BIT(8)
> +#define CIF_IRCL_SI_SW_RST			BIT(9)
> +#define CIF_IRCL_MIPI_SW_RST			BIT(11)
> +
> +/* C_PROC_CTR */
> +#define CIF_C_PROC_CTR_ENABLE			BIT(0)
> +#define CIF_C_PROC_YOUT_FULL			BIT(1)
> +#define CIF_C_PROC_YIN_FULL			BIT(2)
> +#define CIF_C_PROC_COUT_FULL			BIT(3)
> +#define CIF_C_PROC_CTRL_RESERVED		0xFFFFFFFE
> +#define CIF_C_PROC_CONTRAST_RESERVED		0xFFFFFF00
> +#define CIF_C_PROC_BRIGHTNESS_RESERVED		0xFFFFFF00
> +#define CIF_C_PROC_HUE_RESERVED			0xFFFFFF00
> +#define CIF_C_PROC_SATURATION_RESERVED		0xFFFFFF00
> +#define CIF_C_PROC_MACC_RESERVED		0xE000E000
> +#define CIF_C_PROC_TONE_RESERVED		0xF000
> +/* DUAL_CROP_CTRL */
> +#define CIF_DUAL_CROP_MP_MODE_BYPASS		(0 << 0)
> +#define CIF_DUAL_CROP_MP_MODE_YUV		(1 << 0)
> +#define CIF_DUAL_CROP_MP_MODE_RAW		(2 << 0)
> +#define CIF_DUAL_CROP_SP_MODE_BYPASS		(0 << 2)
> +#define CIF_DUAL_CROP_SP_MODE_YUV		(1 << 2)
> +#define CIF_DUAL_CROP_SP_MODE_RAW		(2 << 2)
> +#define CIF_DUAL_CROP_CFG_UPD_PERMANENT		BIT(4)
> +#define CIF_DUAL_CROP_CFG_UPD			BIT(5)
> +#define CIF_DUAL_CROP_GEN_CFG_UPD		BIT(6)
> +
> +/* IMG_EFF_CTRL */
> +#define CIF_IMG_EFF_CTRL_ENABLE			BIT(0)
> +#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE	(0 << 1)
> +#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE		(1 << 1)
> +#define CIF_IMG_EFF_CTRL_MODE_SEPIA		(2 << 1)
> +#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL		(3 << 1)
> +#define CIF_IMG_EFF_CTRL_MODE_EMBOSS		(4 << 1)
> +#define CIF_IMG_EFF_CTRL_MODE_SKETCH		(5 << 1)
> +#define CIF_IMG_EFF_CTRL_MODE_SHARPEN		(6 << 1)
> +#define CIF_IMG_EFF_CTRL_CFG_UPD		BIT(4)
> +#define CIF_IMG_EFF_CTRL_YCBCR_FULL		BIT(5)
> +
> +#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE_SHIFT	0
> +#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE_SHIFT	1
> +#define CIF_IMG_EFF_CTRL_MODE_SEPIA_SHIFT	2
> +#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL_SHIFT	3
> +#define CIF_IMG_EFF_CTRL_MODE_EMBOSS_SHIFT	4
> +#define CIF_IMG_EFF_CTRL_MODE_SKETCH_SHIFT	5
> +#define CIF_IMG_EFF_CTRL_MODE_SHARPEN_SHIFT	6
> +#define CIF_IMG_EFF_CTRL_MODE_MASK		0xE
> +
> +/* IMG_EFF_COLOR_SEL */
> +#define CIF_IMG_EFF_COLOR_RGB			0
> +#define CIF_IMG_EFF_COLOR_B			(1 << 0)
> +#define CIF_IMG_EFF_COLOR_G			(2 << 0)
> +#define CIF_IMG_EFF_COLOR_GB			(3 << 0)
> +#define CIF_IMG_EFF_COLOR_R			(4 << 0)
> +#define CIF_IMG_EFF_COLOR_RB			(5 << 0)
> +#define CIF_IMG_EFF_COLOR_RG			(6 << 0)
> +#define CIF_IMG_EFF_COLOR_RGB2			(7 << 0)
> +
> +/* MIPI_CTRL */
> +#define CIF_MIPI_CTRL_OUTPUT_ENA		BIT(0)
> +#define CIF_MIPI_CTRL_SHUTDOWNLANES(a)		(((a) & 0xF) << 8)
> +#define CIF_MIPI_CTRL_NUM_LANES(a)		(((a) & 0x3) << 12)
> +#define CIF_MIPI_CTRL_ERR_SOT_HS_SKIP		BIT(16)
> +#define CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP	BIT(17)
> +#define CIF_MIPI_CTRL_CLOCKLANE_ENA		BIT(18)
> +
> +/* MIPI_DATA_SEL */
> +#define CIF_MIPI_DATA_SEL_VC(a)			(((a) & 0x3) << 6)
> +#define CIF_MIPI_DATA_SEL_DT(a)			(((a) & 0x3F) << 0)
> +/* MIPI DATA_TYPE */
> +#define CIF_CSI2_DT_YUV420_8b			0x18
> +#define CIF_CSI2_DT_YUV420_10b			0x19
> +#define CIF_CSI2_DT_YUV422_8b			0x1E
> +#define CIF_CSI2_DT_YUV422_10b			0x1F
> +#define CIF_CSI2_DT_RGB565			0x22
> +#define CIF_CSI2_DT_RGB666			0x23
> +#define CIF_CSI2_DT_RGB888			0x24
> +#define CIF_CSI2_DT_RAW8			0x2A
> +#define CIF_CSI2_DT_RAW10			0x2B
> +#define CIF_CSI2_DT_RAW12			0x2C
> +
> +/* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */
> +#define CIF_MIPI_SYNC_FIFO_OVFLW(a)		(((a) & 0xF) << 0)
> +#define CIF_MIPI_ERR_SOT(a)			(((a) & 0xF) << 4)
> +#define CIF_MIPI_ERR_SOT_SYNC(a)		(((a) & 0xF) << 8)
> +#define CIF_MIPI_ERR_EOT_SYNC(a)		(((a) & 0xF) << 12)
> +#define CIF_MIPI_ERR_CTRL(a)			(((a) & 0xF) << 16)
> +#define CIF_MIPI_ERR_PROTOCOL			BIT(20)
> +#define CIF_MIPI_ERR_ECC1			BIT(21)
> +#define CIF_MIPI_ERR_ECC2			BIT(22)
> +#define CIF_MIPI_ERR_CS				BIT(23)
> +#define CIF_MIPI_FRAME_END			BIT(24)
> +#define CIF_MIPI_ADD_DATA_OVFLW			BIT(25)
> +#define CIF_MIPI_ADD_DATA_WATER_MARK		BIT(26)
> +
> +#define CIF_MIPI_ERR_CSI  (CIF_MIPI_ERR_PROTOCOL | \
> +	CIF_MIPI_ERR_ECC1 | \
> +	CIF_MIPI_ERR_ECC2 | \
> +	CIF_MIPI_ERR_CS)
> +
> +#define CIF_MIPI_ERR_DPHY  (CIF_MIPI_ERR_SOT(3) | \
> +	CIF_MIPI_ERR_SOT_SYNC(3) | \
> +	CIF_MIPI_ERR_EOT_SYNC(3) | \
> +	CIF_MIPI_ERR_CTRL(3))
> +
> +/* SUPER_IMPOSE */
> +#define CIF_SUPER_IMP_CTRL_NORMAL_MODE		BIT(0)
> +#define CIF_SUPER_IMP_CTRL_REF_IMG_MEM		BIT(1)
> +#define CIF_SUPER_IMP_CTRL_TRANSP_DIS		BIT(2)
> +
> +/* ISP HISTOGRAM CALCULATION : ISP_HIST_PROP */
> +#define CIF_ISP_HIST_PROP_MODE_DIS		(0 << 0)
> +#define CIF_ISP_HIST_PROP_MODE_RGB		(1 << 0)
> +#define CIF_ISP_HIST_PROP_MODE_RED		(2 << 0)
> +#define CIF_ISP_HIST_PROP_MODE_GREEN		(3 << 0)
> +#define CIF_ISP_HIST_PROP_MODE_BLUE		(4 << 0)
> +#define CIF_ISP_HIST_PROP_MODE_LUM		(5 << 0)
> +#define CIF_ISP_HIST_PROP_MODE_MASK		0x7
> +#define CIF_ISP_HIST_PREDIV_SET(x)		(((x) & 0x7F) << 3)
> +#define CIF_ISP_HIST_WEIGHT_SET(v0, v1, v2, v3)	\
> +				     (((v0) & 0x1F) | (((v1) & 0x1F) << 8)  |\
> +				     (((v2) & 0x1F) << 16) | \
> +				     (((v3) & 0x1F) << 24))
> +
> +#define CIF_ISP_HIST_WINDOW_OFFSET_RESERVED	0xFFFFF000
> +#define CIF_ISP_HIST_WINDOW_SIZE_RESERVED	0xFFFFF800
> +#define CIF_ISP_HIST_WEIGHT_RESERVED		0xE0E0E0E0
> +#define CIF_ISP_MAX_HIST_PREDIVIDER		0x0000007F
> +#define CIF_ISP_HIST_ROW_NUM			5
> +#define CIF_ISP_HIST_COLUMN_NUM			5
> +
> +/* AUTO FOCUS MEASUREMENT:  ISP_AFM_CTRL */
> +#define ISP_AFM_CTRL_ENABLE			BIT(0)
> +
> +/* SHUTTER CONTROL */
> +#define CIF_ISP_SH_CTRL_SH_ENA			BIT(0)
> +#define CIF_ISP_SH_CTRL_REP_EN			BIT(1)
> +#define CIF_ISP_SH_CTRL_SRC_SH_TRIG		BIT(2)
> +#define CIF_ISP_SH_CTRL_EDGE_POS		BIT(3)
> +#define CIF_ISP_SH_CTRL_POL_LOW			BIT(4)
> +
> +/* FLASH MODULE */
> +/* ISP_FLASH_CMD */
> +#define CIF_FLASH_CMD_PRELIGHT_ON		BIT(0)
> +#define CIF_FLASH_CMD_FLASH_ON			BIT(1)
> +#define CIF_FLASH_CMD_PRE_FLASH_ON		BIT(2)
> +/* ISP_FLASH_CONFIG */
> +#define CIF_FLASH_CONFIG_PRELIGHT_END		BIT(0)
> +#define CIF_FLASH_CONFIG_VSYNC_POS		BIT(1)
> +#define CIF_FLASH_CONFIG_PRELIGHT_LOW		BIT(2)
> +#define CIF_FLASH_CONFIG_SRC_FL_TRIG		BIT(3)
> +#define CIF_FLASH_CONFIG_DELAY(a)		(((a) & 0xF) << 4)
> +
> +/* Demosaic:  ISP_DEMOSAIC */
> +#define CIF_ISP_DEMOSAIC_BYPASS			BIT(10)
> +#define CIF_ISP_DEMOSAIC_TH(x)			((x) & 0xFF)
> +
> +/* AWB */
> +/* ISP_AWB_PROP */
> +#define CIF_ISP_AWB_YMAX_CMP_EN			BIT(2)
> +#define CIFISP_AWB_YMAX_READ(x)			(((x) >> 2) & 1)
> +#define CIF_ISP_AWB_MODE_RGB_EN			((1 << 31) | (0x2 << 0))
> +#define CIF_ISP_AWB_MODE_YCBCR_EN		((0 << 31) | (0x2 << 0))
> +#define CIF_ISP_AWB_MODE_YCBCR_EN		((0 << 31) | (0x2 << 0))
> +#define CIF_ISP_AWB_MODE_MASK_NONE		0xFFFFFFFC
> +#define CIF_ISP_AWB_MODE_READ(x)		((x) & 3)
> +/* ISP_AWB_GAIN_RB, ISP_AWB_GAIN_G  */
> +#define CIF_ISP_AWB_GAIN_R_SET(x)		(((x) & 0x3FF) << 16)
> +#define CIF_ISP_AWB_GAIN_R_READ(x)		(((x) >> 16) & 0x3FF)
> +#define CIF_ISP_AWB_GAIN_B_SET(x)		((x) & 0x3FFF)
> +#define CIF_ISP_AWB_GAIN_B_READ(x)		((x) & 0x3FFF)
> +/* ISP_AWB_REF */
> +#define CIF_ISP_AWB_REF_CR_SET(x)		(((x) & 0xFF) << 8)
> +#define CIF_ISP_AWB_REF_CR_READ(x)		(((x) >> 8) & 0xFF)
> +#define CIF_ISP_AWB_REF_CB_READ(x)		((x) & 0xFF)
> +/* ISP_AWB_THRESH */
> +#define CIF_ISP_AWB_MAX_CS_SET(x)		(((x) & 0xFF) << 8)
> +#define CIF_ISP_AWB_MAX_CS_READ(x)		(((x) >> 8) & 0xFF)
> +#define CIF_ISP_AWB_MIN_C_READ(x)		((x) & 0xFF)
> +#define CIF_ISP_AWB_MIN_Y_SET(x)		(((x) & 0xFF) << 16)
> +#define CIF_ISP_AWB_MIN_Y_READ(x)		(((x) >> 16) & 0xFF)
> +#define CIF_ISP_AWB_MAX_Y_SET(x)		(((x) & 0xFF) << 24)
> +#define CIF_ISP_AWB_MAX_Y_READ(x)		(((x) >> 24) & 0xFF)
> +/* ISP_AWB_MEAN */
> +#define CIF_ISP_AWB_GET_MEAN_CR_R(x)		((x) & 0xFF)
> +#define CIF_ISP_AWB_GET_MEAN_CB_B(x)		(((x) >> 8) & 0xFF)
> +#define CIF_ISP_AWB_GET_MEAN_Y_G(x)		(((x) >> 16) & 0xFF)
> +/* ISP_AWB_WHITE_CNT */
> +#define CIF_ISP_AWB_GET_PIXEL_CNT(x)		((x) & 0x3FFFFFF)
> +
> +#define CIF_ISP_AWB_GAINS_MAX_VAL		0x000003FF
> +#define CIF_ISP_AWB_WINDOW_OFFSET_MAX		0x00000FFF
> +#define CIF_ISP_AWB_WINDOW_MAX_SIZE		0x00001FFF
> +#define CIF_ISP_AWB_CBCR_MAX_REF		0x000000FF
> +#define CIF_ISP_AWB_THRES_MAX_YC		0x000000FF
> +
> +/* AE */
> +/* ISP_EXP_CTRL */
> +#define CIF_ISP_EXP_ENA				BIT(0)
> +#define CIF_ISP_EXP_CTRL_AUTOSTOP		BIT(1)
> +/*
> + *'1' luminance calculation according to  Y=(R+G+B) x 0.332 (85/256)
> + *'0' luminance calculation according to Y=16+0.25R+0.5G+0.1094B
> + */
> +#define CIF_ISP_EXP_CTRL_MEASMODE_1		BIT(31)
> +
> +/* ISP_EXP_H_SIZE */
> +#define CIF_ISP_EXP_H_SIZE_SET(x)		((x) & 0x7FF)
> +#define CIF_ISP_EXP_HEIGHT_MASK			0x000007FF
> +/* ISP_EXP_V_SIZE : vertical size must be a multiple of 2). */
> +#define CIF_ISP_EXP_V_SIZE_SET(x)		((x) & 0x7FE)
> +
> +/* ISP_EXP_H_OFFSET */
> +#define CIF_ISP_EXP_H_OFFSET_SET(x)		((x) & 0x1FFF)
> +#define CIF_ISP_EXP_MAX_HOFFS			2424
> +/* ISP_EXP_V_OFFSET */
> +#define CIF_ISP_EXP_V_OFFSET_SET(x)		((x) & 0x1FFF)
> +#define CIF_ISP_EXP_MAX_VOFFS			1806
> +
> +#define CIF_ISP_EXP_ROW_NUM			5
> +#define CIF_ISP_EXP_COLUMN_NUM			5
> +#define CIF_ISP_EXP_NUM_LUMA_REGS \
> +	(CIF_ISP_EXP_ROW_NUM * CIF_ISP_EXP_COLUMN_NUM)
> +#define CIF_ISP_EXP_BLOCK_MAX_HSIZE		516
> +#define CIF_ISP_EXP_BLOCK_MIN_HSIZE		35
> +#define CIF_ISP_EXP_BLOCK_MAX_VSIZE		390
> +#define CIF_ISP_EXP_BLOCK_MIN_VSIZE		28
> +#define CIF_ISP_EXP_MAX_HSIZE	\
> +	(CIF_ISP_EXP_BLOCK_MAX_HSIZE * CIF_ISP_EXP_COLUMN_NUM + 1)
> +#define CIF_ISP_EXP_MIN_HSIZE	\
> +	(CIF_ISP_EXP_BLOCK_MIN_HSIZE * CIF_ISP_EXP_COLUMN_NUM + 1)
> +#define CIF_ISP_EXP_MAX_VSIZE	\
> +	(CIF_ISP_EXP_BLOCK_MAX_VSIZE * CIF_ISP_EXP_ROW_NUM + 1)
> +#define CIF_ISP_EXP_MIN_VSIZE	\
> +	(CIF_ISP_EXP_BLOCK_MIN_VSIZE * CIF_ISP_EXP_ROW_NUM + 1)
> +
> +/* LSC: ISP_LSC_CTRL */
> +#define CIF_ISP_LSC_CTRL_ENA			BIT(0)
> +#define CIF_ISP_LSC_SECT_SIZE_RESERVED		0xFC00FC00
> +#define CIF_ISP_LSC_GRAD_RESERVED		0xF000F000
> +#define CIF_ISP_LSC_SAMPLE_RESERVED		0xF000F000
> +#define CIF_ISP_LSC_SECTORS_MAX			16
> +#define CIF_ISP_LSC_TABLE_DATA(v0, v1)     \
> +	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 12))
> +#define CIF_ISP_LSC_SECT_SIZE(v0, v1)      \
> +	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
> +#define CIF_ISP_LSC_GRAD_SIZE(v0, v1)      \
> +	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
> +
> +/* LSC: ISP_LSC_TABLE_SEL */
> +#define CIF_ISP_LSC_TABLE_0			0
> +#define CIF_ISP_LSC_TABLE_1			1
> +
> +/* LSC: ISP_LSC_STATUS */
> +#define CIF_ISP_LSC_ACTIVE_TABLE		BIT(1)
> +#define CIF_ISP_LSC_TABLE_ADDRESS_0		0
> +#define CIF_ISP_LSC_TABLE_ADDRESS_153		153
> +
> +/* FLT */
> +/* ISP_FILT_MODE */
> +#define CIF_ISP_FLT_ENA				BIT(0)
> +
> +/*
> + * 0: green filter static mode (active filter factor = FILT_FAC_MID)
> + * 1: dynamic noise reduction/sharpen Default
> + */
> +#define CIF_ISP_FLT_MODE_DNR			BIT(1)
> +#define CIF_ISP_FLT_MODE_MAX			1
> +#define CIF_ISP_FLT_CHROMA_V_MODE(x)		(((x) & 0x3) << 4)
> +#define CIF_ISP_FLT_CHROMA_H_MODE(x)		(((x) & 0x3) << 6)
> +#define CIF_ISP_FLT_CHROMA_MODE_MAX		3
> +#define CIF_ISP_FLT_GREEN_STAGE1(x)		(((x) & 0xF) << 8)
> +#define CIF_ISP_FLT_GREEN_STAGE1_MAX		8
> +#define CIF_ISP_FLT_THREAD_RESERVED		0xFFFFFC00
> +#define CIF_ISP_FLT_FAC_RESERVED		0xFFFFFFC0
> +#define CIF_ISP_FLT_LUM_WEIGHT_RESERVED		0xFFF80000
> +
> +#define CIF_ISP_CTK_COEFF_RESERVED		0xFFFFF800
> +#define CIF_ISP_XTALK_OFFSET_RESERVED		0xFFFFF000
> +
> +/* GOC */
> +#define CIF_ISP_GAMMA_OUT_MODE_EQU		BIT(0)
> +#define CIF_ISP_GOC_MODE_MAX			1
> +#define CIF_ISP_GOC_RESERVED			0xFFFFF800
> +/* ISP_CTRL BIT 11*/
> +#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA_READ(x)	(((x) >> 11) & 1)
> +
> +/* DPCC */
> +/* ISP_DPCC_MODE */
> +#define CIF_ISP_DPCC_ENA			BIT(0)
> +#define CIF_ISP_DPCC_MODE_MAX			0x07
> +#define CIF_ISP_DPCC_OUTPUTMODE_MAX		0x0F
> +#define CIF_ISP_DPCC_SETUSE_MAX			0x0F
> +#define CIF_ISP_DPCC_METHODS_SET_RESERVED	0xFFFFE000
> +#define CIF_ISP_DPCC_LINE_THRESH_RESERVED	0xFFFF0000
> +#define CIF_ISP_DPCC_LINE_MAD_FAC_RESERVED	0xFFFFC0C0
> +#define CIF_ISP_DPCC_PG_FAC_RESERVED		0xFFFFC0C0
> +#define CIF_ISP_DPCC_RND_THRESH_RESERVED	0xFFFF0000
> +#define CIF_ISP_DPCC_RG_FAC_RESERVED		0xFFFFC0C0
> +#define CIF_ISP_DPCC_RO_LIMIT_RESERVED		0xFFFFF000
> +#define CIF_ISP_DPCC_RND_OFFS_RESERVED		0xFFFFF000
> +
> +/* BLS */
> +/* ISP_BLS_CTRL */
> +#define CIF_ISP_BLS_ENA				BIT(0)
> +#define CIF_ISP_BLS_MODE_MEASURED		BIT(1)
> +#define CIF_ISP_BLS_MODE_FIXED			0
> +#define CIF_ISP_BLS_WINDOW_1			(1 << 2)
> +#define CIF_ISP_BLS_WINDOW_2			(2 << 2)
> +
> +/* GAMMA-IN */
> +#define CIFISP_DEGAMMA_X_RESERVED	\
> +	((1 << 31) | (1 << 27) | (1 << 23) | (1 << 19) |\
> +	(1 << 15) | (1 << 11) | (1 << 7) | (1 << 3))
> +#define CIFISP_DEGAMMA_Y_RESERVED               0xFFFFF000
> +
> +/* AFM */
> +#define CIF_ISP_AFM_ENA				BIT(0)
> +#define CIF_ISP_AFM_THRES_RESERVED		0xFFFF0000
> +#define CIF_ISP_AFM_VAR_SHIFT_RESERVED		0xFFF8FFF8
> +#define CIF_ISP_AFM_WINDOW_X_RESERVED		0xE000
> +#define CIF_ISP_AFM_WINDOW_Y_RESERVED		0xF000
> +#define CIF_ISP_AFM_WINDOW_X_MIN		0x5
> +#define CIF_ISP_AFM_WINDOW_Y_MIN		0x2
> +#define CIF_ISP_AFM_WINDOW_X(x)			(((x) & 0x1FFF) << 16)
> +#define CIF_ISP_AFM_WINDOW_Y(x)			((x) & 0x1FFF)
> +
> +/* DPF */
> +#define CIF_ISP_DPF_MODE_EN			BIT(0)
> +#define CIF_ISP_DPF_MODE_B_FLT_DIS		BIT(1)
> +#define CIF_ISP_DPF_MODE_GB_FLT_DIS		BIT(2)
> +#define CIF_ISP_DPF_MODE_GR_FLT_DIS		BIT(3)
> +#define CIF_ISP_DPF_MODE_R_FLT_DIS		BIT(4)
> +#define CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9		BIT(5)
> +#define CIF_ISP_DPF_MODE_NLL_SEGMENTATION	BIT(6)
> +#define CIF_ISP_DPF_MODE_AWB_GAIN_COMP		BIT(7)
> +#define CIF_ISP_DPF_MODE_LSC_GAIN_COMP		BIT(8)
> +#define CIF_ISP_DPF_MODE_USE_NF_GAIN		BIT(9)
> +#define CIF_ISP_DPF_NF_GAIN_RESERVED		0xFFFFF000
> +#define CIF_ISP_DPF_SPATIAL_COEFF_MAX		0x1F
> +#define CIF_ISP_DPF_NLL_COEFF_N_MAX		0x3FF
> +
> +/* =================================================================== */
> +/*                            CIF Registers                            */
> +/* =================================================================== */
> +#define CIF_CTRL_BASE			0x00000000
> +#define CIF_CCL				(CIF_CTRL_BASE + 0x00000000)
> +#define CIF_VI_ID			(CIF_CTRL_BASE + 0x00000008)
> +#define CIF_ICCL			(CIF_CTRL_BASE + 0x00000010)
> +#define CIF_IRCL			(CIF_CTRL_BASE + 0x00000014)
> +#define CIF_VI_DPCL			(CIF_CTRL_BASE + 0x00000018)
> +
> +#define CIF_IMG_EFF_BASE		0x00000200
> +#define CIF_IMG_EFF_CTRL		(CIF_IMG_EFF_BASE + 0x00000000)
> +#define CIF_IMG_EFF_COLOR_SEL		(CIF_IMG_EFF_BASE + 0x00000004)
> +#define CIF_IMG_EFF_MAT_1		(CIF_IMG_EFF_BASE + 0x00000008)
> +#define CIF_IMG_EFF_MAT_2		(CIF_IMG_EFF_BASE + 0x0000000C)
> +#define CIF_IMG_EFF_MAT_3		(CIF_IMG_EFF_BASE + 0x00000010)
> +#define CIF_IMG_EFF_MAT_4		(CIF_IMG_EFF_BASE + 0x00000014)
> +#define CIF_IMG_EFF_MAT_5		(CIF_IMG_EFF_BASE + 0x00000018)
> +#define CIF_IMG_EFF_TINT		(CIF_IMG_EFF_BASE + 0x0000001C)
> +#define CIF_IMG_EFF_CTRL_SHD		(CIF_IMG_EFF_BASE + 0x00000020)
> +#define CIF_IMG_EFF_SHARPEN		(CIF_IMG_EFF_BASE + 0x00000024)
> +
> +#define CIF_SUPER_IMP_BASE		0x00000300
> +#define CIF_SUPER_IMP_CTRL		(CIF_SUPER_IMP_BASE + 0x00000000)
> +#define CIF_SUPER_IMP_OFFSET_X		(CIF_SUPER_IMP_BASE + 0x00000004)
> +#define CIF_SUPER_IMP_OFFSET_Y		(CIF_SUPER_IMP_BASE + 0x00000008)
> +#define CIF_SUPER_IMP_COLOR_Y		(CIF_SUPER_IMP_BASE + 0x0000000C)
> +#define CIF_SUPER_IMP_COLOR_CB		(CIF_SUPER_IMP_BASE + 0x00000010)
> +#define CIF_SUPER_IMP_COLOR_CR		(CIF_SUPER_IMP_BASE + 0x00000014)
> +
> +#define CIF_ISP_BASE			0x00000400
> +#define CIF_ISP_CTRL			(CIF_ISP_BASE + 0x00000000)
> +#define CIF_ISP_ACQ_PROP		(CIF_ISP_BASE + 0x00000004)
> +#define CIF_ISP_ACQ_H_OFFS		(CIF_ISP_BASE + 0x00000008)
> +#define CIF_ISP_ACQ_V_OFFS		(CIF_ISP_BASE + 0x0000000C)
> +#define CIF_ISP_ACQ_H_SIZE		(CIF_ISP_BASE + 0x00000010)
> +#define CIF_ISP_ACQ_V_SIZE		(CIF_ISP_BASE + 0x00000014)
> +#define CIF_ISP_ACQ_NR_FRAMES		(CIF_ISP_BASE + 0x00000018)
> +#define CIF_ISP_GAMMA_DX_LO		(CIF_ISP_BASE + 0x0000001C)
> +#define CIF_ISP_GAMMA_DX_HI		(CIF_ISP_BASE + 0x00000020)
> +#define CIF_ISP_GAMMA_R_Y0		(CIF_ISP_BASE + 0x00000024)
> +#define CIF_ISP_GAMMA_R_Y1		(CIF_ISP_BASE + 0x00000028)
> +#define CIF_ISP_GAMMA_R_Y2		(CIF_ISP_BASE + 0x0000002C)
> +#define CIF_ISP_GAMMA_R_Y3		(CIF_ISP_BASE + 0x00000030)
> +#define CIF_ISP_GAMMA_R_Y4		(CIF_ISP_BASE + 0x00000034)
> +#define CIF_ISP_GAMMA_R_Y5		(CIF_ISP_BASE + 0x00000038)
> +#define CIF_ISP_GAMMA_R_Y6		(CIF_ISP_BASE + 0x0000003C)
> +#define CIF_ISP_GAMMA_R_Y7		(CIF_ISP_BASE + 0x00000040)
> +#define CIF_ISP_GAMMA_R_Y8		(CIF_ISP_BASE + 0x00000044)
> +#define CIF_ISP_GAMMA_R_Y9		(CIF_ISP_BASE + 0x00000048)
> +#define CIF_ISP_GAMMA_R_Y10		(CIF_ISP_BASE + 0x0000004C)
> +#define CIF_ISP_GAMMA_R_Y11		(CIF_ISP_BASE + 0x00000050)
> +#define CIF_ISP_GAMMA_R_Y12		(CIF_ISP_BASE + 0x00000054)
> +#define CIF_ISP_GAMMA_R_Y13		(CIF_ISP_BASE + 0x00000058)
> +#define CIF_ISP_GAMMA_R_Y14		(CIF_ISP_BASE + 0x0000005C)
> +#define CIF_ISP_GAMMA_R_Y15		(CIF_ISP_BASE + 0x00000060)
> +#define CIF_ISP_GAMMA_R_Y16		(CIF_ISP_BASE + 0x00000064)
> +#define CIF_ISP_GAMMA_G_Y0		(CIF_ISP_BASE + 0x00000068)
> +#define CIF_ISP_GAMMA_G_Y1		(CIF_ISP_BASE + 0x0000006C)
> +#define CIF_ISP_GAMMA_G_Y2		(CIF_ISP_BASE + 0x00000070)
> +#define CIF_ISP_GAMMA_G_Y3		(CIF_ISP_BASE + 0x00000074)
> +#define CIF_ISP_GAMMA_G_Y4		(CIF_ISP_BASE + 0x00000078)
> +#define CIF_ISP_GAMMA_G_Y5		(CIF_ISP_BASE + 0x0000007C)
> +#define CIF_ISP_GAMMA_G_Y6		(CIF_ISP_BASE + 0x00000080)
> +#define CIF_ISP_GAMMA_G_Y7		(CIF_ISP_BASE + 0x00000084)
> +#define CIF_ISP_GAMMA_G_Y8		(CIF_ISP_BASE + 0x00000088)
> +#define CIF_ISP_GAMMA_G_Y9		(CIF_ISP_BASE + 0x0000008C)
> +#define CIF_ISP_GAMMA_G_Y10		(CIF_ISP_BASE + 0x00000090)
> +#define CIF_ISP_GAMMA_G_Y11		(CIF_ISP_BASE + 0x00000094)
> +#define CIF_ISP_GAMMA_G_Y12		(CIF_ISP_BASE + 0x00000098)
> +#define CIF_ISP_GAMMA_G_Y13		(CIF_ISP_BASE + 0x0000009C)
> +#define CIF_ISP_GAMMA_G_Y14		(CIF_ISP_BASE + 0x000000A0)
> +#define CIF_ISP_GAMMA_G_Y15		(CIF_ISP_BASE + 0x000000A4)
> +#define CIF_ISP_GAMMA_G_Y16		(CIF_ISP_BASE + 0x000000A8)
> +#define CIF_ISP_GAMMA_B_Y0		(CIF_ISP_BASE + 0x000000AC)
> +#define CIF_ISP_GAMMA_B_Y1		(CIF_ISP_BASE + 0x000000B0)
> +#define CIF_ISP_GAMMA_B_Y2		(CIF_ISP_BASE + 0x000000B4)
> +#define CIF_ISP_GAMMA_B_Y3		(CIF_ISP_BASE + 0x000000B8)
> +#define CIF_ISP_GAMMA_B_Y4		(CIF_ISP_BASE + 0x000000BC)
> +#define CIF_ISP_GAMMA_B_Y5		(CIF_ISP_BASE + 0x000000C0)
> +#define CIF_ISP_GAMMA_B_Y6		(CIF_ISP_BASE + 0x000000C4)
> +#define CIF_ISP_GAMMA_B_Y7		(CIF_ISP_BASE + 0x000000C8)
> +#define CIF_ISP_GAMMA_B_Y8		(CIF_ISP_BASE + 0x000000CC)
> +#define CIF_ISP_GAMMA_B_Y9		(CIF_ISP_BASE + 0x000000D0)
> +#define CIF_ISP_GAMMA_B_Y10		(CIF_ISP_BASE + 0x000000D4)
> +#define CIF_ISP_GAMMA_B_Y11		(CIF_ISP_BASE + 0x000000D8)
> +#define CIF_ISP_GAMMA_B_Y12		(CIF_ISP_BASE + 0x000000DC)
> +#define CIF_ISP_GAMMA_B_Y13		(CIF_ISP_BASE + 0x000000E0)
> +#define CIF_ISP_GAMMA_B_Y14		(CIF_ISP_BASE + 0x000000E4)
> +#define CIF_ISP_GAMMA_B_Y15		(CIF_ISP_BASE + 0x000000E8)
> +#define CIF_ISP_GAMMA_B_Y16		(CIF_ISP_BASE + 0x000000EC)
> +#define CIF_ISP_AWB_PROP		(CIF_ISP_BASE + 0x00000110)
> +#define CIF_ISP_AWB_WND_H_OFFS		(CIF_ISP_BASE + 0x00000114)
> +#define CIF_ISP_AWB_WND_V_OFFS		(CIF_ISP_BASE + 0x00000118)
> +#define CIF_ISP_AWB_WND_H_SIZE		(CIF_ISP_BASE + 0x0000011C)
> +#define CIF_ISP_AWB_WND_V_SIZE		(CIF_ISP_BASE + 0x00000120)
> +#define CIF_ISP_AWB_FRAMES		(CIF_ISP_BASE + 0x00000124)
> +#define CIF_ISP_AWB_REF			(CIF_ISP_BASE + 0x00000128)
> +#define CIF_ISP_AWB_THRESH		(CIF_ISP_BASE + 0x0000012C)
> +#define CIF_ISP_AWB_GAIN_G		(CIF_ISP_BASE + 0x00000138)
> +#define CIF_ISP_AWB_GAIN_RB		(CIF_ISP_BASE + 0x0000013C)
> +#define CIF_ISP_AWB_WHITE_CNT		(CIF_ISP_BASE + 0x00000140)
> +#define CIF_ISP_AWB_MEAN		(CIF_ISP_BASE + 0x00000144)
> +#define CIF_ISP_CC_COEFF_0		(CIF_ISP_BASE + 0x00000170)
> +#define CIF_ISP_CC_COEFF_1		(CIF_ISP_BASE + 0x00000174)
> +#define CIF_ISP_CC_COEFF_2		(CIF_ISP_BASE + 0x00000178)
> +#define CIF_ISP_CC_COEFF_3		(CIF_ISP_BASE + 0x0000017C)
> +#define CIF_ISP_CC_COEFF_4		(CIF_ISP_BASE + 0x00000180)
> +#define CIF_ISP_CC_COEFF_5		(CIF_ISP_BASE + 0x00000184)
> +#define CIF_ISP_CC_COEFF_6		(CIF_ISP_BASE + 0x00000188)
> +#define CIF_ISP_CC_COEFF_7		(CIF_ISP_BASE + 0x0000018C)
> +#define CIF_ISP_CC_COEFF_8		(CIF_ISP_BASE + 0x00000190)
> +#define CIF_ISP_OUT_H_OFFS		(CIF_ISP_BASE + 0x00000194)
> +#define CIF_ISP_OUT_V_OFFS		(CIF_ISP_BASE + 0x00000198)
> +#define CIF_ISP_OUT_H_SIZE		(CIF_ISP_BASE + 0x0000019C)
> +#define CIF_ISP_OUT_V_SIZE		(CIF_ISP_BASE + 0x000001A0)
> +#define CIF_ISP_DEMOSAIC		(CIF_ISP_BASE + 0x000001A4)
> +#define CIF_ISP_FLAGS_SHD		(CIF_ISP_BASE + 0x000001A8)
> +#define CIF_ISP_OUT_H_OFFS_SHD		(CIF_ISP_BASE + 0x000001AC)
> +#define CIF_ISP_OUT_V_OFFS_SHD		(CIF_ISP_BASE + 0x000001B0)
> +#define CIF_ISP_OUT_H_SIZE_SHD		(CIF_ISP_BASE + 0x000001B4)
> +#define CIF_ISP_OUT_V_SIZE_SHD		(CIF_ISP_BASE + 0x000001B8)
> +#define CIF_ISP_IMSC			(CIF_ISP_BASE + 0x000001BC)
> +#define CIF_ISP_RIS			(CIF_ISP_BASE + 0x000001C0)
> +#define CIF_ISP_MIS			(CIF_ISP_BASE + 0x000001C4)
> +#define CIF_ISP_ICR			(CIF_ISP_BASE + 0x000001C8)
> +#define CIF_ISP_ISR			(CIF_ISP_BASE + 0x000001CC)
> +#define CIF_ISP_CT_COEFF_0		(CIF_ISP_BASE + 0x000001D0)
> +#define CIF_ISP_CT_COEFF_1		(CIF_ISP_BASE + 0x000001D4)
> +#define CIF_ISP_CT_COEFF_2		(CIF_ISP_BASE + 0x000001D8)
> +#define CIF_ISP_CT_COEFF_3		(CIF_ISP_BASE + 0x000001DC)
> +#define CIF_ISP_CT_COEFF_4		(CIF_ISP_BASE + 0x000001E0)
> +#define CIF_ISP_CT_COEFF_5		(CIF_ISP_BASE + 0x000001E4)
> +#define CIF_ISP_CT_COEFF_6		(CIF_ISP_BASE + 0x000001E8)
> +#define CIF_ISP_CT_COEFF_7		(CIF_ISP_BASE + 0x000001EC)
> +#define CIF_ISP_CT_COEFF_8		(CIF_ISP_BASE + 0x000001F0)
> +#define CIF_ISP_GAMMA_OUT_MODE		(CIF_ISP_BASE + 0x000001F4)
> +#define CIF_ISP_GAMMA_OUT_Y_0		(CIF_ISP_BASE + 0x000001F8)
> +#define CIF_ISP_GAMMA_OUT_Y_1		(CIF_ISP_BASE + 0x000001FC)
> +#define CIF_ISP_GAMMA_OUT_Y_2		(CIF_ISP_BASE + 0x00000200)
> +#define CIF_ISP_GAMMA_OUT_Y_3		(CIF_ISP_BASE + 0x00000204)
> +#define CIF_ISP_GAMMA_OUT_Y_4		(CIF_ISP_BASE + 0x00000208)
> +#define CIF_ISP_GAMMA_OUT_Y_5		(CIF_ISP_BASE + 0x0000020C)
> +#define CIF_ISP_GAMMA_OUT_Y_6		(CIF_ISP_BASE + 0x00000210)
> +#define CIF_ISP_GAMMA_OUT_Y_7		(CIF_ISP_BASE + 0x00000214)
> +#define CIF_ISP_GAMMA_OUT_Y_8		(CIF_ISP_BASE + 0x00000218)
> +#define CIF_ISP_GAMMA_OUT_Y_9		(CIF_ISP_BASE + 0x0000021C)
> +#define CIF_ISP_GAMMA_OUT_Y_10		(CIF_ISP_BASE + 0x00000220)
> +#define CIF_ISP_GAMMA_OUT_Y_11		(CIF_ISP_BASE + 0x00000224)
> +#define CIF_ISP_GAMMA_OUT_Y_12		(CIF_ISP_BASE + 0x00000228)
> +#define CIF_ISP_GAMMA_OUT_Y_13		(CIF_ISP_BASE + 0x0000022C)
> +#define CIF_ISP_GAMMA_OUT_Y_14		(CIF_ISP_BASE + 0x00000230)
> +#define CIF_ISP_GAMMA_OUT_Y_15		(CIF_ISP_BASE + 0x00000234)
> +#define CIF_ISP_GAMMA_OUT_Y_16		(CIF_ISP_BASE + 0x00000238)
> +#define CIF_ISP_ERR			(CIF_ISP_BASE + 0x0000023C)
> +#define CIF_ISP_ERR_CLR			(CIF_ISP_BASE + 0x00000240)
> +#define CIF_ISP_FRAME_COUNT		(CIF_ISP_BASE + 0x00000244)
> +#define CIF_ISP_CT_OFFSET_R		(CIF_ISP_BASE + 0x00000248)
> +#define CIF_ISP_CT_OFFSET_G		(CIF_ISP_BASE + 0x0000024C)
> +#define CIF_ISP_CT_OFFSET_B		(CIF_ISP_BASE + 0x00000250)
> +
> +#define CIF_ISP_FLASH_BASE		0x00000660
> +#define CIF_ISP_FLASH_CMD		(CIF_ISP_FLASH_BASE + 0x00000000)
> +#define CIF_ISP_FLASH_CONFIG		(CIF_ISP_FLASH_BASE + 0x00000004)
> +#define CIF_ISP_FLASH_PREDIV		(CIF_ISP_FLASH_BASE + 0x00000008)
> +#define CIF_ISP_FLASH_DELAY		(CIF_ISP_FLASH_BASE + 0x0000000C)
> +#define CIF_ISP_FLASH_TIME		(CIF_ISP_FLASH_BASE + 0x00000010)
> +#define CIF_ISP_FLASH_MAXP		(CIF_ISP_FLASH_BASE + 0x00000014)
> +
> +#define CIF_ISP_SH_BASE			0x00000680
> +#define CIF_ISP_SH_CTRL			(CIF_ISP_SH_BASE + 0x00000000)
> +#define CIF_ISP_SH_PREDIV		(CIF_ISP_SH_BASE + 0x00000004)
> +#define CIF_ISP_SH_DELAY		(CIF_ISP_SH_BASE + 0x00000008)
> +#define CIF_ISP_SH_TIME			(CIF_ISP_SH_BASE + 0x0000000C)
> +
> +#define CIF_C_PROC_BASE			0x00000800
> +#define CIF_C_PROC_CTRL			(CIF_C_PROC_BASE + 0x00000000)
> +#define CIF_C_PROC_CONTRAST		(CIF_C_PROC_BASE + 0x00000004)
> +#define CIF_C_PROC_BRIGHTNESS		(CIF_C_PROC_BASE + 0x00000008)
> +#define CIF_C_PROC_SATURATION		(CIF_C_PROC_BASE + 0x0000000C)
> +#define CIF_C_PROC_HUE			(CIF_C_PROC_BASE + 0x00000010)
> +
> +#define CIF_DUAL_CROP_BASE		0x00000880
> +#define CIF_DUAL_CROP_CTRL		(CIF_DUAL_CROP_BASE + 0x00000000)
> +#define CIF_DUAL_CROP_M_H_OFFS		(CIF_DUAL_CROP_BASE + 0x00000004)
> +#define CIF_DUAL_CROP_M_V_OFFS		(CIF_DUAL_CROP_BASE + 0x00000008)
> +#define CIF_DUAL_CROP_M_H_SIZE		(CIF_DUAL_CROP_BASE + 0x0000000C)
> +#define CIF_DUAL_CROP_M_V_SIZE		(CIF_DUAL_CROP_BASE + 0x00000010)
> +#define CIF_DUAL_CROP_S_H_OFFS		(CIF_DUAL_CROP_BASE + 0x00000014)
> +#define CIF_DUAL_CROP_S_V_OFFS		(CIF_DUAL_CROP_BASE + 0x00000018)
> +#define CIF_DUAL_CROP_S_H_SIZE		(CIF_DUAL_CROP_BASE + 0x0000001C)
> +#define CIF_DUAL_CROP_S_V_SIZE		(CIF_DUAL_CROP_BASE + 0x00000020)
> +#define CIF_DUAL_CROP_M_H_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000024)
> +#define CIF_DUAL_CROP_M_V_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000028)
> +#define CIF_DUAL_CROP_M_H_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x0000002C)
> +#define CIF_DUAL_CROP_M_V_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x00000030)
> +#define CIF_DUAL_CROP_S_H_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000034)
> +#define CIF_DUAL_CROP_S_V_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000038)
> +#define CIF_DUAL_CROP_S_H_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x0000003C)
> +#define CIF_DUAL_CROP_S_V_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x00000040)
> +
> +#define CIF_MRSZ_BASE			0x00000C00
> +#define CIF_MRSZ_CTRL			(CIF_MRSZ_BASE + 0x00000000)
> +#define CIF_MRSZ_SCALE_HY		(CIF_MRSZ_BASE + 0x00000004)
> +#define CIF_MRSZ_SCALE_HCB		(CIF_MRSZ_BASE + 0x00000008)
> +#define CIF_MRSZ_SCALE_HCR		(CIF_MRSZ_BASE + 0x0000000C)
> +#define CIF_MRSZ_SCALE_VY		(CIF_MRSZ_BASE + 0x00000010)
> +#define CIF_MRSZ_SCALE_VC		(CIF_MRSZ_BASE + 0x00000014)
> +#define CIF_MRSZ_PHASE_HY		(CIF_MRSZ_BASE + 0x00000018)
> +#define CIF_MRSZ_PHASE_HC		(CIF_MRSZ_BASE + 0x0000001C)
> +#define CIF_MRSZ_PHASE_VY		(CIF_MRSZ_BASE + 0x00000020)
> +#define CIF_MRSZ_PHASE_VC		(CIF_MRSZ_BASE + 0x00000024)
> +#define CIF_MRSZ_SCALE_LUT_ADDR		(CIF_MRSZ_BASE + 0x00000028)
> +#define CIF_MRSZ_SCALE_LUT		(CIF_MRSZ_BASE + 0x0000002C)
> +#define CIF_MRSZ_CTRL_SHD		(CIF_MRSZ_BASE + 0x00000030)
> +#define CIF_MRSZ_SCALE_HY_SHD		(CIF_MRSZ_BASE + 0x00000034)
> +#define CIF_MRSZ_SCALE_HCB_SHD		(CIF_MRSZ_BASE + 0x00000038)
> +#define CIF_MRSZ_SCALE_HCR_SHD		(CIF_MRSZ_BASE + 0x0000003C)
> +#define CIF_MRSZ_SCALE_VY_SHD		(CIF_MRSZ_BASE + 0x00000040)
> +#define CIF_MRSZ_SCALE_VC_SHD		(CIF_MRSZ_BASE + 0x00000044)
> +#define CIF_MRSZ_PHASE_HY_SHD		(CIF_MRSZ_BASE + 0x00000048)
> +#define CIF_MRSZ_PHASE_HC_SHD		(CIF_MRSZ_BASE + 0x0000004C)
> +#define CIF_MRSZ_PHASE_VY_SHD		(CIF_MRSZ_BASE + 0x00000050)
> +#define CIF_MRSZ_PHASE_VC_SHD		(CIF_MRSZ_BASE + 0x00000054)
> +
> +#define CIF_SRSZ_BASE			0x00001000
> +#define CIF_SRSZ_CTRL			(CIF_SRSZ_BASE + 0x00000000)
> +#define CIF_SRSZ_SCALE_HY		(CIF_SRSZ_BASE + 0x00000004)
> +#define CIF_SRSZ_SCALE_HCB		(CIF_SRSZ_BASE + 0x00000008)
> +#define CIF_SRSZ_SCALE_HCR		(CIF_SRSZ_BASE + 0x0000000C)
> +#define CIF_SRSZ_SCALE_VY		(CIF_SRSZ_BASE + 0x00000010)
> +#define CIF_SRSZ_SCALE_VC		(CIF_SRSZ_BASE + 0x00000014)
> +#define CIF_SRSZ_PHASE_HY		(CIF_SRSZ_BASE + 0x00000018)
> +#define CIF_SRSZ_PHASE_HC		(CIF_SRSZ_BASE + 0x0000001C)
> +#define CIF_SRSZ_PHASE_VY		(CIF_SRSZ_BASE + 0x00000020)
> +#define CIF_SRSZ_PHASE_VC		(CIF_SRSZ_BASE + 0x00000024)
> +#define CIF_SRSZ_SCALE_LUT_ADDR		(CIF_SRSZ_BASE + 0x00000028)
> +#define CIF_SRSZ_SCALE_LUT		(CIF_SRSZ_BASE + 0x0000002C)
> +#define CIF_SRSZ_CTRL_SHD		(CIF_SRSZ_BASE + 0x00000030)
> +#define CIF_SRSZ_SCALE_HY_SHD		(CIF_SRSZ_BASE + 0x00000034)
> +#define CIF_SRSZ_SCALE_HCB_SHD		(CIF_SRSZ_BASE + 0x00000038)
> +#define CIF_SRSZ_SCALE_HCR_SHD		(CIF_SRSZ_BASE + 0x0000003C)
> +#define CIF_SRSZ_SCALE_VY_SHD		(CIF_SRSZ_BASE + 0x00000040)
> +#define CIF_SRSZ_SCALE_VC_SHD		(CIF_SRSZ_BASE + 0x00000044)
> +#define CIF_SRSZ_PHASE_HY_SHD		(CIF_SRSZ_BASE + 0x00000048)
> +#define CIF_SRSZ_PHASE_HC_SHD		(CIF_SRSZ_BASE + 0x0000004C)
> +#define CIF_SRSZ_PHASE_VY_SHD		(CIF_SRSZ_BASE + 0x00000050)
> +#define CIF_SRSZ_PHASE_VC_SHD		(CIF_SRSZ_BASE + 0x00000054)
> +
> +#define CIF_MI_BASE			0x00001400
> +#define CIF_MI_CTRL			(CIF_MI_BASE + 0x00000000)
> +#define CIF_MI_INIT			(CIF_MI_BASE + 0x00000004)
> +#define CIF_MI_MP_Y_BASE_AD_INIT	(CIF_MI_BASE + 0x00000008)
> +#define CIF_MI_MP_Y_SIZE_INIT		(CIF_MI_BASE + 0x0000000C)
> +#define CIF_MI_MP_Y_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000010)
> +#define CIF_MI_MP_Y_OFFS_CNT_START	(CIF_MI_BASE + 0x00000014)
> +#define CIF_MI_MP_Y_IRQ_OFFS_INIT	(CIF_MI_BASE + 0x00000018)
> +#define CIF_MI_MP_CB_BASE_AD_INIT	(CIF_MI_BASE + 0x0000001C)
> +#define CIF_MI_MP_CB_SIZE_INIT		(CIF_MI_BASE + 0x00000020)
> +#define CIF_MI_MP_CB_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000024)
> +#define CIF_MI_MP_CB_OFFS_CNT_START	(CIF_MI_BASE + 0x00000028)
> +#define CIF_MI_MP_CR_BASE_AD_INIT	(CIF_MI_BASE + 0x0000002C)
> +#define CIF_MI_MP_CR_SIZE_INIT		(CIF_MI_BASE + 0x00000030)
> +#define CIF_MI_MP_CR_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000034)
> +#define CIF_MI_MP_CR_OFFS_CNT_START	(CIF_MI_BASE + 0x00000038)
> +#define CIF_MI_SP_Y_BASE_AD_INIT	(CIF_MI_BASE + 0x0000003C)
> +#define CIF_MI_SP_Y_SIZE_INIT		(CIF_MI_BASE + 0x00000040)
> +#define CIF_MI_SP_Y_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000044)
> +#define CIF_MI_SP_Y_OFFS_CNT_START	(CIF_MI_BASE + 0x00000048)
> +#define CIF_MI_SP_Y_LLENGTH		(CIF_MI_BASE + 0x0000004C)
> +#define CIF_MI_SP_CB_BASE_AD_INIT	(CIF_MI_BASE + 0x00000050)
> +#define CIF_MI_SP_CB_SIZE_INIT		(CIF_MI_BASE + 0x00000054)
> +#define CIF_MI_SP_CB_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000058)
> +#define CIF_MI_SP_CB_OFFS_CNT_START	(CIF_MI_BASE + 0x0000005C)
> +#define CIF_MI_SP_CR_BASE_AD_INIT	(CIF_MI_BASE + 0x00000060)
> +#define CIF_MI_SP_CR_SIZE_INIT		(CIF_MI_BASE + 0x00000064)
> +#define CIF_MI_SP_CR_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000068)
> +#define CIF_MI_SP_CR_OFFS_CNT_START	(CIF_MI_BASE + 0x0000006C)
> +#define CIF_MI_BYTE_CNT			(CIF_MI_BASE + 0x00000070)
> +#define CIF_MI_CTRL_SHD			(CIF_MI_BASE + 0x00000074)
> +#define CIF_MI_MP_Y_BASE_AD_SHD		(CIF_MI_BASE + 0x00000078)
> +#define CIF_MI_MP_Y_SIZE_SHD		(CIF_MI_BASE + 0x0000007C)
> +#define CIF_MI_MP_Y_OFFS_CNT_SHD	(CIF_MI_BASE + 0x00000080)
> +#define CIF_MI_MP_Y_IRQ_OFFS_SHD	(CIF_MI_BASE + 0x00000084)
> +#define CIF_MI_MP_CB_BASE_AD_SHD	(CIF_MI_BASE + 0x00000088)
> +#define CIF_MI_MP_CB_SIZE_SHD		(CIF_MI_BASE + 0x0000008C)
> +#define CIF_MI_MP_CB_OFFS_CNT_SHD	(CIF_MI_BASE + 0x00000090)
> +#define CIF_MI_MP_CR_BASE_AD_SHD	(CIF_MI_BASE + 0x00000094)
> +#define CIF_MI_MP_CR_SIZE_SHD		(CIF_MI_BASE + 0x00000098)
> +#define CIF_MI_MP_CR_OFFS_CNT_SHD	(CIF_MI_BASE + 0x0000009C)
> +#define CIF_MI_SP_Y_BASE_AD_SHD		(CIF_MI_BASE + 0x000000A0)
> +#define CIF_MI_SP_Y_SIZE_SHD		(CIF_MI_BASE + 0x000000A4)
> +#define CIF_MI_SP_Y_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000A8)
> +#define CIF_MI_SP_CB_BASE_AD_SHD	(CIF_MI_BASE + 0x000000B0)
> +#define CIF_MI_SP_CB_SIZE_SHD		(CIF_MI_BASE + 0x000000B4)
> +#define CIF_MI_SP_CB_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000B8)
> +#define CIF_MI_SP_CR_BASE_AD_SHD	(CIF_MI_BASE + 0x000000BC)
> +#define CIF_MI_SP_CR_SIZE_SHD		(CIF_MI_BASE + 0x000000C0)
> +#define CIF_MI_SP_CR_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000C4)
> +#define CIF_MI_DMA_Y_PIC_START_AD	(CIF_MI_BASE + 0x000000C8)
> +#define CIF_MI_DMA_Y_PIC_WIDTH		(CIF_MI_BASE + 0x000000CC)
> +#define CIF_MI_DMA_Y_LLENGTH		(CIF_MI_BASE + 0x000000D0)
> +#define CIF_MI_DMA_Y_PIC_SIZE		(CIF_MI_BASE + 0x000000D4)
> +#define CIF_MI_DMA_CB_PIC_START_AD	(CIF_MI_BASE + 0x000000D8)
> +#define CIF_MI_DMA_CR_PIC_START_AD	(CIF_MI_BASE + 0x000000E8)
> +#define CIF_MI_IMSC			(CIF_MI_BASE + 0x000000F8)
> +#define CIF_MI_RIS			(CIF_MI_BASE + 0x000000FC)
> +#define CIF_MI_MIS			(CIF_MI_BASE + 0x00000100)
> +#define CIF_MI_ICR			(CIF_MI_BASE + 0x00000104)
> +#define CIF_MI_ISR			(CIF_MI_BASE + 0x00000108)
> +#define CIF_MI_STATUS			(CIF_MI_BASE + 0x0000010C)
> +#define CIF_MI_STATUS_CLR		(CIF_MI_BASE + 0x00000110)
> +#define CIF_MI_SP_Y_PIC_WIDTH		(CIF_MI_BASE + 0x00000114)
> +#define CIF_MI_SP_Y_PIC_HEIGHT		(CIF_MI_BASE + 0x00000118)
> +#define CIF_MI_SP_Y_PIC_SIZE		(CIF_MI_BASE + 0x0000011C)
> +#define CIF_MI_DMA_CTRL			(CIF_MI_BASE + 0x00000120)
> +#define CIF_MI_DMA_START		(CIF_MI_BASE + 0x00000124)
> +#define CIF_MI_DMA_STATUS		(CIF_MI_BASE + 0x00000128)
> +#define CIF_MI_PIXEL_COUNT		(CIF_MI_BASE + 0x0000012C)
> +#define CIF_MI_MP_Y_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000130)
> +#define CIF_MI_MP_CB_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000134)
> +#define CIF_MI_MP_CR_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000138)
> +#define CIF_MI_SP_Y_BASE_AD_INIT2	(CIF_MI_BASE + 0x0000013C)
> +#define CIF_MI_SP_CB_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000140)
> +#define CIF_MI_SP_CR_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000144)
> +#define CIF_MI_XTD_FORMAT_CTRL		(CIF_MI_BASE + 0x00000148)
> +
> +#define CIF_SMIA_BASE			0x00001A00
> +#define CIF_SMIA_CTRL			(CIF_SMIA_BASE + 0x00000000)
> +#define CIF_SMIA_STATUS			(CIF_SMIA_BASE + 0x00000004)
> +#define CIF_SMIA_IMSC			(CIF_SMIA_BASE + 0x00000008)
> +#define CIF_SMIA_RIS			(CIF_SMIA_BASE + 0x0000000C)
> +#define CIF_SMIA_MIS			(CIF_SMIA_BASE + 0x00000010)
> +#define CIF_SMIA_ICR			(CIF_SMIA_BASE + 0x00000014)
> +#define CIF_SMIA_ISR			(CIF_SMIA_BASE + 0x00000018)
> +#define CIF_SMIA_DATA_FORMAT_SEL	(CIF_SMIA_BASE + 0x0000001C)
> +#define CIF_SMIA_SOF_EMB_DATA_LINES	(CIF_SMIA_BASE + 0x00000020)
> +#define CIF_SMIA_EMB_HSTART		(CIF_SMIA_BASE + 0x00000024)
> +#define CIF_SMIA_EMB_HSIZE		(CIF_SMIA_BASE + 0x00000028)
> +#define CIF_SMIA_EMB_VSTART		(CIF_SMIA_BASE + 0x0000002c)
> +#define CIF_SMIA_NUM_LINES		(CIF_SMIA_BASE + 0x00000030)
> +#define CIF_SMIA_EMB_DATA_FIFO		(CIF_SMIA_BASE + 0x00000034)
> +#define CIF_SMIA_EMB_DATA_WATERMARK	(CIF_SMIA_BASE + 0x00000038)
> +
> +#define CIF_MIPI_BASE			0x00001C00
> +#define CIF_MIPI_CTRL			(CIF_MIPI_BASE + 0x00000000)
> +#define CIF_MIPI_STATUS			(CIF_MIPI_BASE + 0x00000004)
> +#define CIF_MIPI_IMSC			(CIF_MIPI_BASE + 0x00000008)
> +#define CIF_MIPI_RIS			(CIF_MIPI_BASE + 0x0000000C)
> +#define CIF_MIPI_MIS			(CIF_MIPI_BASE + 0x00000010)
> +#define CIF_MIPI_ICR			(CIF_MIPI_BASE + 0x00000014)
> +#define CIF_MIPI_ISR			(CIF_MIPI_BASE + 0x00000018)
> +#define CIF_MIPI_CUR_DATA_ID		(CIF_MIPI_BASE + 0x0000001C)
> +#define CIF_MIPI_IMG_DATA_SEL		(CIF_MIPI_BASE + 0x00000020)
> +#define CIF_MIPI_ADD_DATA_SEL_1		(CIF_MIPI_BASE + 0x00000024)
> +#define CIF_MIPI_ADD_DATA_SEL_2		(CIF_MIPI_BASE + 0x00000028)
> +#define CIF_MIPI_ADD_DATA_SEL_3		(CIF_MIPI_BASE + 0x0000002C)
> +#define CIF_MIPI_ADD_DATA_SEL_4		(CIF_MIPI_BASE + 0x00000030)
> +#define CIF_MIPI_ADD_DATA_FIFO		(CIF_MIPI_BASE + 0x00000034)
> +#define CIF_MIPI_FIFO_FILL_LEVEL	(CIF_MIPI_BASE + 0x00000038)
> +#define CIF_MIPI_COMPRESSED_MODE	(CIF_MIPI_BASE + 0x0000003C)
> +#define CIF_MIPI_FRAME			(CIF_MIPI_BASE + 0x00000040)
> +#define CIF_MIPI_GEN_SHORT_DT		(CIF_MIPI_BASE + 0x00000044)
> +#define CIF_MIPI_GEN_SHORT_8_9		(CIF_MIPI_BASE + 0x00000048)
> +#define CIF_MIPI_GEN_SHORT_A_B		(CIF_MIPI_BASE + 0x0000004C)
> +#define CIF_MIPI_GEN_SHORT_C_D		(CIF_MIPI_BASE + 0x00000050)
> +#define CIF_MIPI_GEN_SHORT_E_F		(CIF_MIPI_BASE + 0x00000054)
> +
> +#define CIF_ISP_AFM_BASE		0x00002000
> +#define CIF_ISP_AFM_CTRL		(CIF_ISP_AFM_BASE + 0x00000000)
> +#define CIF_ISP_AFM_LT_A		(CIF_ISP_AFM_BASE + 0x00000004)
> +#define CIF_ISP_AFM_RB_A		(CIF_ISP_AFM_BASE + 0x00000008)
> +#define CIF_ISP_AFM_LT_B		(CIF_ISP_AFM_BASE + 0x0000000C)
> +#define CIF_ISP_AFM_RB_B		(CIF_ISP_AFM_BASE + 0x00000010)
> +#define CIF_ISP_AFM_LT_C		(CIF_ISP_AFM_BASE + 0x00000014)
> +#define CIF_ISP_AFM_RB_C		(CIF_ISP_AFM_BASE + 0x00000018)
> +#define CIF_ISP_AFM_THRES		(CIF_ISP_AFM_BASE + 0x0000001C)
> +#define CIF_ISP_AFM_VAR_SHIFT		(CIF_ISP_AFM_BASE + 0x00000020)
> +#define CIF_ISP_AFM_SUM_A		(CIF_ISP_AFM_BASE + 0x00000024)
> +#define CIF_ISP_AFM_SUM_B		(CIF_ISP_AFM_BASE + 0x00000028)
> +#define CIF_ISP_AFM_SUM_C		(CIF_ISP_AFM_BASE + 0x0000002C)
> +#define CIF_ISP_AFM_LUM_A		(CIF_ISP_AFM_BASE + 0x00000030)
> +#define CIF_ISP_AFM_LUM_B		(CIF_ISP_AFM_BASE + 0x00000034)
> +#define CIF_ISP_AFM_LUM_C		(CIF_ISP_AFM_BASE + 0x00000038)
> +
> +#define CIF_ISP_LSC_BASE		0x00002200
> +#define CIF_ISP_LSC_CTRL		(CIF_ISP_LSC_BASE + 0x00000000)
> +#define CIF_ISP_LSC_R_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000004)
> +#define CIF_ISP_LSC_GR_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000008)
> +#define CIF_ISP_LSC_B_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x0000000C)
> +#define CIF_ISP_LSC_GB_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000010)
> +#define CIF_ISP_LSC_R_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000014)
> +#define CIF_ISP_LSC_GR_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000018)
> +#define CIF_ISP_LSC_B_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x0000001C)
> +#define CIF_ISP_LSC_GB_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000020)
> +#define CIF_ISP_LSC_XGRAD_01		(CIF_ISP_LSC_BASE + 0x00000024)
> +#define CIF_ISP_LSC_XGRAD_23		(CIF_ISP_LSC_BASE + 0x00000028)
> +#define CIF_ISP_LSC_XGRAD_45		(CIF_ISP_LSC_BASE + 0x0000002C)
> +#define CIF_ISP_LSC_XGRAD_67		(CIF_ISP_LSC_BASE + 0x00000030)
> +#define CIF_ISP_LSC_YGRAD_01		(CIF_ISP_LSC_BASE + 0x00000034)
> +#define CIF_ISP_LSC_YGRAD_23		(CIF_ISP_LSC_BASE + 0x00000038)
> +#define CIF_ISP_LSC_YGRAD_45		(CIF_ISP_LSC_BASE + 0x0000003C)
> +#define CIF_ISP_LSC_YGRAD_67		(CIF_ISP_LSC_BASE + 0x00000040)
> +#define CIF_ISP_LSC_XSIZE_01		(CIF_ISP_LSC_BASE + 0x00000044)
> +#define CIF_ISP_LSC_XSIZE_23		(CIF_ISP_LSC_BASE + 0x00000048)
> +#define CIF_ISP_LSC_XSIZE_45		(CIF_ISP_LSC_BASE + 0x0000004C)
> +#define CIF_ISP_LSC_XSIZE_67		(CIF_ISP_LSC_BASE + 0x00000050)
> +#define CIF_ISP_LSC_YSIZE_01		(CIF_ISP_LSC_BASE + 0x00000054)
> +#define CIF_ISP_LSC_YSIZE_23		(CIF_ISP_LSC_BASE + 0x00000058)
> +#define CIF_ISP_LSC_YSIZE_45		(CIF_ISP_LSC_BASE + 0x0000005C)
> +#define CIF_ISP_LSC_YSIZE_67		(CIF_ISP_LSC_BASE + 0x00000060)
> +#define CIF_ISP_LSC_TABLE_SEL		(CIF_ISP_LSC_BASE + 0x00000064)
> +#define CIF_ISP_LSC_STATUS		(CIF_ISP_LSC_BASE + 0x00000068)
> +
> +#define CIF_ISP_IS_BASE			0x00002300
> +#define CIF_ISP_IS_CTRL			(CIF_ISP_IS_BASE + 0x00000000)
> +#define CIF_ISP_IS_RECENTER		(CIF_ISP_IS_BASE + 0x00000004)
> +#define CIF_ISP_IS_H_OFFS		(CIF_ISP_IS_BASE + 0x00000008)
> +#define CIF_ISP_IS_V_OFFS		(CIF_ISP_IS_BASE + 0x0000000C)
> +#define CIF_ISP_IS_H_SIZE		(CIF_ISP_IS_BASE + 0x00000010)
> +#define CIF_ISP_IS_V_SIZE		(CIF_ISP_IS_BASE + 0x00000014)
> +#define CIF_ISP_IS_MAX_DX		(CIF_ISP_IS_BASE + 0x00000018)
> +#define CIF_ISP_IS_MAX_DY		(CIF_ISP_IS_BASE + 0x0000001C)
> +#define CIF_ISP_IS_DISPLACE		(CIF_ISP_IS_BASE + 0x00000020)
> +#define CIF_ISP_IS_H_OFFS_SHD		(CIF_ISP_IS_BASE + 0x00000024)
> +#define CIF_ISP_IS_V_OFFS_SHD		(CIF_ISP_IS_BASE + 0x00000028)
> +#define CIF_ISP_IS_H_SIZE_SHD		(CIF_ISP_IS_BASE + 0x0000002C)
> +#define CIF_ISP_IS_V_SIZE_SHD		(CIF_ISP_IS_BASE + 0x00000030)
> +
> +#define CIF_ISP_HIST_BASE		0x00002400
> +
> +#define CIF_ISP_HIST_PROP		(CIF_ISP_HIST_BASE + 0x00000000)
> +#define CIF_ISP_HIST_H_OFFS		(CIF_ISP_HIST_BASE + 0x00000004)
> +#define CIF_ISP_HIST_V_OFFS		(CIF_ISP_HIST_BASE + 0x00000008)
> +#define CIF_ISP_HIST_H_SIZE		(CIF_ISP_HIST_BASE + 0x0000000C)
> +#define CIF_ISP_HIST_V_SIZE		(CIF_ISP_HIST_BASE + 0x00000010)
> +#define CIF_ISP_HIST_BIN_0		(CIF_ISP_HIST_BASE + 0x00000014)
> +#define CIF_ISP_HIST_BIN_1		(CIF_ISP_HIST_BASE + 0x00000018)
> +#define CIF_ISP_HIST_BIN_2		(CIF_ISP_HIST_BASE + 0x0000001C)
> +#define CIF_ISP_HIST_BIN_3		(CIF_ISP_HIST_BASE + 0x00000020)
> +#define CIF_ISP_HIST_BIN_4		(CIF_ISP_HIST_BASE + 0x00000024)
> +#define CIF_ISP_HIST_BIN_5		(CIF_ISP_HIST_BASE + 0x00000028)
> +#define CIF_ISP_HIST_BIN_6		(CIF_ISP_HIST_BASE + 0x0000002C)
> +#define CIF_ISP_HIST_BIN_7		(CIF_ISP_HIST_BASE + 0x00000030)
> +#define CIF_ISP_HIST_BIN_8		(CIF_ISP_HIST_BASE + 0x00000034)
> +#define CIF_ISP_HIST_BIN_9		(CIF_ISP_HIST_BASE + 0x00000038)
> +#define CIF_ISP_HIST_BIN_10		(CIF_ISP_HIST_BASE + 0x0000003C)
> +#define CIF_ISP_HIST_BIN_11		(CIF_ISP_HIST_BASE + 0x00000040)
> +#define CIF_ISP_HIST_BIN_12		(CIF_ISP_HIST_BASE + 0x00000044)
> +#define CIF_ISP_HIST_BIN_13		(CIF_ISP_HIST_BASE + 0x00000048)
> +#define CIF_ISP_HIST_BIN_14		(CIF_ISP_HIST_BASE + 0x0000004C)
> +#define CIF_ISP_HIST_BIN_15		(CIF_ISP_HIST_BASE + 0x00000050)
> +#define CIF_ISP_HIST_WEIGHT_00TO30	(CIF_ISP_HIST_BASE + 0x00000054)
> +#define CIF_ISP_HIST_WEIGHT_40TO21	(CIF_ISP_HIST_BASE + 0x00000058)
> +#define CIF_ISP_HIST_WEIGHT_31TO12	(CIF_ISP_HIST_BASE + 0x0000005C)
> +#define CIF_ISP_HIST_WEIGHT_22TO03	(CIF_ISP_HIST_BASE + 0x00000060)
> +#define CIF_ISP_HIST_WEIGHT_13TO43	(CIF_ISP_HIST_BASE + 0x00000064)
> +#define CIF_ISP_HIST_WEIGHT_04TO34	(CIF_ISP_HIST_BASE + 0x00000068)
> +#define CIF_ISP_HIST_WEIGHT_44		(CIF_ISP_HIST_BASE + 0x0000006C)
> +
> +#define CIF_ISP_FILT_BASE		0x00002500
> +#define CIF_ISP_FILT_MODE		(CIF_ISP_FILT_BASE + 0x00000000)
> +#define CIF_ISP_FILT_THRESH_BL0		(CIF_ISP_FILT_BASE + 0x00000028)
> +#define CIF_ISP_FILT_THRESH_BL1		(CIF_ISP_FILT_BASE + 0x0000002c)
> +#define CIF_ISP_FILT_THRESH_SH0		(CIF_ISP_FILT_BASE + 0x00000030)
> +#define CIF_ISP_FILT_THRESH_SH1		(CIF_ISP_FILT_BASE + 0x00000034)
> +#define CIF_ISP_FILT_LUM_WEIGHT		(CIF_ISP_FILT_BASE + 0x00000038)
> +#define CIF_ISP_FILT_FAC_SH1		(CIF_ISP_FILT_BASE + 0x0000003c)
> +#define CIF_ISP_FILT_FAC_SH0		(CIF_ISP_FILT_BASE + 0x00000040)
> +#define CIF_ISP_FILT_FAC_MID		(CIF_ISP_FILT_BASE + 0x00000044)
> +#define CIF_ISP_FILT_FAC_BL0		(CIF_ISP_FILT_BASE + 0x00000048)
> +#define CIF_ISP_FILT_FAC_BL1		(CIF_ISP_FILT_BASE + 0x0000004C)
> +
> +#define CIF_ISP_CAC_BASE		0x00002580
> +#define CIF_ISP_CAC_CTRL		(CIF_ISP_CAC_BASE + 0x00000000)
> +#define CIF_ISP_CAC_COUNT_START		(CIF_ISP_CAC_BASE + 0x00000004)
> +#define CIF_ISP_CAC_A			(CIF_ISP_CAC_BASE + 0x00000008)
> +#define CIF_ISP_CAC_B			(CIF_ISP_CAC_BASE + 0x0000000C)
> +#define CIF_ISP_CAC_C			(CIF_ISP_CAC_BASE + 0x00000010)
> +#define CIF_ISP_X_NORM			(CIF_ISP_CAC_BASE + 0x00000014)
> +#define CIF_ISP_Y_NORM			(CIF_ISP_CAC_BASE + 0x00000018)
> +
> +#define CIF_ISP_EXP_BASE		0x00002600
> +#define CIF_ISP_EXP_CTRL		(CIF_ISP_EXP_BASE + 0x00000000)
> +#define CIF_ISP_EXP_H_OFFSET		(CIF_ISP_EXP_BASE + 0x00000004)
> +#define CIF_ISP_EXP_V_OFFSET		(CIF_ISP_EXP_BASE + 0x00000008)
> +#define CIF_ISP_EXP_H_SIZE		(CIF_ISP_EXP_BASE + 0x0000000C)
> +#define CIF_ISP_EXP_V_SIZE		(CIF_ISP_EXP_BASE + 0x00000010)
> +#define CIF_ISP_EXP_MEAN_00		(CIF_ISP_EXP_BASE + 0x00000014)
> +#define CIF_ISP_EXP_MEAN_10		(CIF_ISP_EXP_BASE + 0x00000018)
> +#define CIF_ISP_EXP_MEAN_20		(CIF_ISP_EXP_BASE + 0x0000001c)
> +#define CIF_ISP_EXP_MEAN_30		(CIF_ISP_EXP_BASE + 0x00000020)
> +#define CIF_ISP_EXP_MEAN_40		(CIF_ISP_EXP_BASE + 0x00000024)
> +#define CIF_ISP_EXP_MEAN_01		(CIF_ISP_EXP_BASE + 0x00000028)
> +#define CIF_ISP_EXP_MEAN_11		(CIF_ISP_EXP_BASE + 0x0000002c)
> +#define CIF_ISP_EXP_MEAN_21		(CIF_ISP_EXP_BASE + 0x00000030)
> +#define CIF_ISP_EXP_MEAN_31		(CIF_ISP_EXP_BASE + 0x00000034)
> +#define CIF_ISP_EXP_MEAN_41		(CIF_ISP_EXP_BASE + 0x00000038)
> +#define CIF_ISP_EXP_MEAN_02		(CIF_ISP_EXP_BASE + 0x0000003c)
> +#define CIF_ISP_EXP_MEAN_12		(CIF_ISP_EXP_BASE + 0x00000040)
> +#define CIF_ISP_EXP_MEAN_22		(CIF_ISP_EXP_BASE + 0x00000044)
> +#define CIF_ISP_EXP_MEAN_32		(CIF_ISP_EXP_BASE + 0x00000048)
> +#define CIF_ISP_EXP_MEAN_42		(CIF_ISP_EXP_BASE + 0x0000004c)
> +#define CIF_ISP_EXP_MEAN_03		(CIF_ISP_EXP_BASE + 0x00000050)
> +#define CIF_ISP_EXP_MEAN_13		(CIF_ISP_EXP_BASE + 0x00000054)
> +#define CIF_ISP_EXP_MEAN_23		(CIF_ISP_EXP_BASE + 0x00000058)
> +#define CIF_ISP_EXP_MEAN_33		(CIF_ISP_EXP_BASE + 0x0000005c)
> +#define CIF_ISP_EXP_MEAN_43		(CIF_ISP_EXP_BASE + 0x00000060)
> +#define CIF_ISP_EXP_MEAN_04		(CIF_ISP_EXP_BASE + 0x00000064)
> +#define CIF_ISP_EXP_MEAN_14		(CIF_ISP_EXP_BASE + 0x00000068)
> +#define CIF_ISP_EXP_MEAN_24		(CIF_ISP_EXP_BASE + 0x0000006c)
> +#define CIF_ISP_EXP_MEAN_34		(CIF_ISP_EXP_BASE + 0x00000070)
> +#define CIF_ISP_EXP_MEAN_44		(CIF_ISP_EXP_BASE + 0x00000074)
> +
> +#define CIF_ISP_BLS_BASE		0x00002700
> +#define CIF_ISP_BLS_CTRL		(CIF_ISP_BLS_BASE + 0x00000000)
> +#define CIF_ISP_BLS_SAMPLES		(CIF_ISP_BLS_BASE + 0x00000004)
> +#define CIF_ISP_BLS_H1_START		(CIF_ISP_BLS_BASE + 0x00000008)
> +#define CIF_ISP_BLS_H1_STOP		(CIF_ISP_BLS_BASE + 0x0000000c)
> +#define CIF_ISP_BLS_V1_START		(CIF_ISP_BLS_BASE + 0x00000010)
> +#define CIF_ISP_BLS_V1_STOP		(CIF_ISP_BLS_BASE + 0x00000014)
> +#define CIF_ISP_BLS_H2_START		(CIF_ISP_BLS_BASE + 0x00000018)
> +#define CIF_ISP_BLS_H2_STOP		(CIF_ISP_BLS_BASE + 0x0000001c)
> +#define CIF_ISP_BLS_V2_START		(CIF_ISP_BLS_BASE + 0x00000020)
> +#define CIF_ISP_BLS_V2_STOP		(CIF_ISP_BLS_BASE + 0x00000024)
> +#define CIF_ISP_BLS_A_FIXED		(CIF_ISP_BLS_BASE + 0x00000028)
> +#define CIF_ISP_BLS_B_FIXED		(CIF_ISP_BLS_BASE + 0x0000002c)
> +#define CIF_ISP_BLS_C_FIXED		(CIF_ISP_BLS_BASE + 0x00000030)
> +#define CIF_ISP_BLS_D_FIXED		(CIF_ISP_BLS_BASE + 0x00000034)
> +#define CIF_ISP_BLS_A_MEASURED		(CIF_ISP_BLS_BASE + 0x00000038)
> +#define CIF_ISP_BLS_B_MEASURED		(CIF_ISP_BLS_BASE + 0x0000003c)
> +#define CIF_ISP_BLS_C_MEASURED		(CIF_ISP_BLS_BASE + 0x00000040)
> +#define CIF_ISP_BLS_D_MEASURED		(CIF_ISP_BLS_BASE + 0x00000044)
> +
> +#define CIF_ISP_DPF_BASE		0x00002800
> +#define CIF_ISP_DPF_MODE		(CIF_ISP_DPF_BASE + 0x00000000)
> +#define CIF_ISP_DPF_STRENGTH_R		(CIF_ISP_DPF_BASE + 0x00000004)
> +#define CIF_ISP_DPF_STRENGTH_G		(CIF_ISP_DPF_BASE + 0x00000008)
> +#define CIF_ISP_DPF_STRENGTH_B		(CIF_ISP_DPF_BASE + 0x0000000C)
> +#define CIF_ISP_DPF_S_WEIGHT_G_1_4	(CIF_ISP_DPF_BASE + 0x00000010)
> +#define CIF_ISP_DPF_S_WEIGHT_G_5_6	(CIF_ISP_DPF_BASE + 0x00000014)
> +#define CIF_ISP_DPF_S_WEIGHT_RB_1_4	(CIF_ISP_DPF_BASE + 0x00000018)
> +#define CIF_ISP_DPF_S_WEIGHT_RB_5_6	(CIF_ISP_DPF_BASE + 0x0000001C)
> +#define CIF_ISP_DPF_NULL_COEFF_0	(CIF_ISP_DPF_BASE + 0x00000020)
> +#define CIF_ISP_DPF_NULL_COEFF_1	(CIF_ISP_DPF_BASE + 0x00000024)
> +#define CIF_ISP_DPF_NULL_COEFF_2	(CIF_ISP_DPF_BASE + 0x00000028)
> +#define CIF_ISP_DPF_NULL_COEFF_3	(CIF_ISP_DPF_BASE + 0x0000002C)
> +#define CIF_ISP_DPF_NULL_COEFF_4	(CIF_ISP_DPF_BASE + 0x00000030)
> +#define CIF_ISP_DPF_NULL_COEFF_5	(CIF_ISP_DPF_BASE + 0x00000034)
> +#define CIF_ISP_DPF_NULL_COEFF_6	(CIF_ISP_DPF_BASE + 0x00000038)
> +#define CIF_ISP_DPF_NULL_COEFF_7	(CIF_ISP_DPF_BASE + 0x0000003C)
> +#define CIF_ISP_DPF_NULL_COEFF_8	(CIF_ISP_DPF_BASE + 0x00000040)
> +#define CIF_ISP_DPF_NULL_COEFF_9	(CIF_ISP_DPF_BASE + 0x00000044)
> +#define CIF_ISP_DPF_NULL_COEFF_10	(CIF_ISP_DPF_BASE + 0x00000048)
> +#define CIF_ISP_DPF_NULL_COEFF_11	(CIF_ISP_DPF_BASE + 0x0000004C)
> +#define CIF_ISP_DPF_NULL_COEFF_12	(CIF_ISP_DPF_BASE + 0x00000050)
> +#define CIF_ISP_DPF_NULL_COEFF_13	(CIF_ISP_DPF_BASE + 0x00000054)
> +#define CIF_ISP_DPF_NULL_COEFF_14	(CIF_ISP_DPF_BASE + 0x00000058)
> +#define CIF_ISP_DPF_NULL_COEFF_15	(CIF_ISP_DPF_BASE + 0x0000005C)
> +#define CIF_ISP_DPF_NULL_COEFF_16	(CIF_ISP_DPF_BASE + 0x00000060)
> +#define CIF_ISP_DPF_NF_GAIN_R		(CIF_ISP_DPF_BASE + 0x00000064)
> +#define CIF_ISP_DPF_NF_GAIN_GR		(CIF_ISP_DPF_BASE + 0x00000068)
> +#define CIF_ISP_DPF_NF_GAIN_GB		(CIF_ISP_DPF_BASE + 0x0000006C)
> +#define CIF_ISP_DPF_NF_GAIN_B		(CIF_ISP_DPF_BASE + 0x00000070)
> +
> +#define CIF_ISP_DPCC_BASE		0x00002900
> +#define CIF_ISP_DPCC_MODE		(CIF_ISP_DPCC_BASE + 0x00000000)
> +#define CIF_ISP_DPCC_OUTPUT_MODE	(CIF_ISP_DPCC_BASE + 0x00000004)
> +#define CIF_ISP_DPCC_SET_USE		(CIF_ISP_DPCC_BASE + 0x00000008)
> +#define CIF_ISP_DPCC_METHODS_SET_1	(CIF_ISP_DPCC_BASE + 0x0000000C)
> +#define CIF_ISP_DPCC_METHODS_SET_2	(CIF_ISP_DPCC_BASE + 0x00000010)
> +#define CIF_ISP_DPCC_METHODS_SET_3	(CIF_ISP_DPCC_BASE + 0x00000014)
> +#define CIF_ISP_DPCC_LINE_THRESH_1	(CIF_ISP_DPCC_BASE + 0x00000018)
> +#define CIF_ISP_DPCC_LINE_MAD_FAC_1	(CIF_ISP_DPCC_BASE + 0x0000001C)
> +#define CIF_ISP_DPCC_PG_FAC_1		(CIF_ISP_DPCC_BASE + 0x00000020)
> +#define CIF_ISP_DPCC_RND_THRESH_1	(CIF_ISP_DPCC_BASE + 0x00000024)
> +#define CIF_ISP_DPCC_RG_FAC_1		(CIF_ISP_DPCC_BASE + 0x00000028)
> +#define CIF_ISP_DPCC_LINE_THRESH_2	(CIF_ISP_DPCC_BASE + 0x0000002C)
> +#define CIF_ISP_DPCC_LINE_MAD_FAC_2	(CIF_ISP_DPCC_BASE + 0x00000030)
> +#define CIF_ISP_DPCC_PG_FAC_2		(CIF_ISP_DPCC_BASE + 0x00000034)
> +#define CIF_ISP_DPCC_RND_THRESH_2	(CIF_ISP_DPCC_BASE + 0x00000038)
> +#define CIF_ISP_DPCC_RG_FAC_2		(CIF_ISP_DPCC_BASE + 0x0000003C)
> +#define CIF_ISP_DPCC_LINE_THRESH_3	(CIF_ISP_DPCC_BASE + 0x00000040)
> +#define CIF_ISP_DPCC_LINE_MAD_FAC_3	(CIF_ISP_DPCC_BASE + 0x00000044)
> +#define CIF_ISP_DPCC_PG_FAC_3		(CIF_ISP_DPCC_BASE + 0x00000048)
> +#define CIF_ISP_DPCC_RND_THRESH_3	(CIF_ISP_DPCC_BASE + 0x0000004C)
> +#define CIF_ISP_DPCC_RG_FAC_3		(CIF_ISP_DPCC_BASE + 0x00000050)
> +#define CIF_ISP_DPCC_RO_LIMITS		(CIF_ISP_DPCC_BASE + 0x00000054)
> +#define CIF_ISP_DPCC_RND_OFFS		(CIF_ISP_DPCC_BASE + 0x00000058)
> +#define CIF_ISP_DPCC_BPT_CTRL		(CIF_ISP_DPCC_BASE + 0x0000005C)
> +#define CIF_ISP_DPCC_BPT_NUMBER		(CIF_ISP_DPCC_BASE + 0x00000060)
> +#define CIF_ISP_DPCC_BPT_ADDR		(CIF_ISP_DPCC_BASE + 0x00000064)
> +#define CIF_ISP_DPCC_BPT_DATA		(CIF_ISP_DPCC_BASE + 0x00000068)
> +
> +#define CIF_ISP_WDR_BASE		0x00002A00
> +#define CIF_ISP_WDR_CTRL		(CIF_ISP_WDR_BASE + 0x00000000)
> +#define CIF_ISP_WDR_TONECURVE_1		(CIF_ISP_WDR_BASE + 0x00000004)
> +#define CIF_ISP_WDR_TONECURVE_2		(CIF_ISP_WDR_BASE + 0x00000008)
> +#define CIF_ISP_WDR_TONECURVE_3		(CIF_ISP_WDR_BASE + 0x0000000C)
> +#define CIF_ISP_WDR_TONECURVE_4		(CIF_ISP_WDR_BASE + 0x00000010)
> +#define CIF_ISP_WDR_TONECURVE_YM_0	(CIF_ISP_WDR_BASE + 0x00000014)
> +#define CIF_ISP_WDR_TONECURVE_YM_1	(CIF_ISP_WDR_BASE + 0x00000018)
> +#define CIF_ISP_WDR_TONECURVE_YM_2	(CIF_ISP_WDR_BASE + 0x0000001C)
> +#define CIF_ISP_WDR_TONECURVE_YM_3	(CIF_ISP_WDR_BASE + 0x00000020)
> +#define CIF_ISP_WDR_TONECURVE_YM_4	(CIF_ISP_WDR_BASE + 0x00000024)
> +#define CIF_ISP_WDR_TONECURVE_YM_5	(CIF_ISP_WDR_BASE + 0x00000028)
> +#define CIF_ISP_WDR_TONECURVE_YM_6	(CIF_ISP_WDR_BASE + 0x0000002C)
> +#define CIF_ISP_WDR_TONECURVE_YM_7	(CIF_ISP_WDR_BASE + 0x00000030)
> +#define CIF_ISP_WDR_TONECURVE_YM_8	(CIF_ISP_WDR_BASE + 0x00000034)
> +#define CIF_ISP_WDR_TONECURVE_YM_9	(CIF_ISP_WDR_BASE + 0x00000038)
> +#define CIF_ISP_WDR_TONECURVE_YM_10	(CIF_ISP_WDR_BASE + 0x0000003C)
> +#define CIF_ISP_WDR_TONECURVE_YM_11	(CIF_ISP_WDR_BASE + 0x00000040)
> +#define CIF_ISP_WDR_TONECURVE_YM_12	(CIF_ISP_WDR_BASE + 0x00000044)
> +#define CIF_ISP_WDR_TONECURVE_YM_13	(CIF_ISP_WDR_BASE + 0x00000048)
> +#define CIF_ISP_WDR_TONECURVE_YM_14	(CIF_ISP_WDR_BASE + 0x0000004C)
> +#define CIF_ISP_WDR_TONECURVE_YM_15	(CIF_ISP_WDR_BASE + 0x00000050)
> +#define CIF_ISP_WDR_TONECURVE_YM_16	(CIF_ISP_WDR_BASE + 0x00000054)
> +#define CIF_ISP_WDR_TONECURVE_YM_17	(CIF_ISP_WDR_BASE + 0x00000058)
> +#define CIF_ISP_WDR_TONECURVE_YM_18	(CIF_ISP_WDR_BASE + 0x0000005C)
> +#define CIF_ISP_WDR_TONECURVE_YM_19	(CIF_ISP_WDR_BASE + 0x00000060)
> +#define CIF_ISP_WDR_TONECURVE_YM_20	(CIF_ISP_WDR_BASE + 0x00000064)
> +#define CIF_ISP_WDR_TONECURVE_YM_21	(CIF_ISP_WDR_BASE + 0x00000068)
> +#define CIF_ISP_WDR_TONECURVE_YM_22	(CIF_ISP_WDR_BASE + 0x0000006C)
> +#define CIF_ISP_WDR_TONECURVE_YM_23	(CIF_ISP_WDR_BASE + 0x00000070)
> +#define CIF_ISP_WDR_TONECURVE_YM_24	(CIF_ISP_WDR_BASE + 0x00000074)
> +#define CIF_ISP_WDR_TONECURVE_YM_25	(CIF_ISP_WDR_BASE + 0x00000078)
> +#define CIF_ISP_WDR_TONECURVE_YM_26	(CIF_ISP_WDR_BASE + 0x0000007C)
> +#define CIF_ISP_WDR_TONECURVE_YM_27	(CIF_ISP_WDR_BASE + 0x00000080)
> +#define CIF_ISP_WDR_TONECURVE_YM_28	(CIF_ISP_WDR_BASE + 0x00000084)
> +#define CIF_ISP_WDR_TONECURVE_YM_29	(CIF_ISP_WDR_BASE + 0x00000088)
> +#define CIF_ISP_WDR_TONECURVE_YM_30	(CIF_ISP_WDR_BASE + 0x0000008C)
> +#define CIF_ISP_WDR_TONECURVE_YM_31	(CIF_ISP_WDR_BASE + 0x00000090)
> +#define CIF_ISP_WDR_TONECURVE_YM_32	(CIF_ISP_WDR_BASE + 0x00000094)
> +#define CIF_ISP_WDR_OFFSET		(CIF_ISP_WDR_BASE + 0x00000098)
> +#define CIF_ISP_WDR_DELTAMIN		(CIF_ISP_WDR_BASE + 0x0000009C)
> +#define CIF_ISP_WDR_TONECURVE_1_SHD	(CIF_ISP_WDR_BASE + 0x000000A0)
> +#define CIF_ISP_WDR_TONECURVE_2_SHD	(CIF_ISP_WDR_BASE + 0x000000A4)
> +#define CIF_ISP_WDR_TONECURVE_3_SHD	(CIF_ISP_WDR_BASE + 0x000000A8)
> +#define CIF_ISP_WDR_TONECURVE_4_SHD	(CIF_ISP_WDR_BASE + 0x000000AC)
> +#define CIF_ISP_WDR_TONECURVE_YM_0_SHD	(CIF_ISP_WDR_BASE + 0x000000B0)
> +#define CIF_ISP_WDR_TONECURVE_YM_1_SHD	(CIF_ISP_WDR_BASE + 0x000000B4)
> +#define CIF_ISP_WDR_TONECURVE_YM_2_SHD	(CIF_ISP_WDR_BASE + 0x000000B8)
> +#define CIF_ISP_WDR_TONECURVE_YM_3_SHD	(CIF_ISP_WDR_BASE + 0x000000BC)
> +#define CIF_ISP_WDR_TONECURVE_YM_4_SHD	(CIF_ISP_WDR_BASE + 0x000000C0)
> +#define CIF_ISP_WDR_TONECURVE_YM_5_SHD	(CIF_ISP_WDR_BASE + 0x000000C4)
> +#define CIF_ISP_WDR_TONECURVE_YM_6_SHD	(CIF_ISP_WDR_BASE + 0x000000C8)
> +#define CIF_ISP_WDR_TONECURVE_YM_7_SHD	(CIF_ISP_WDR_BASE + 0x000000CC)
> +#define CIF_ISP_WDR_TONECURVE_YM_8_SHD	(CIF_ISP_WDR_BASE + 0x000000D0)
> +#define CIF_ISP_WDR_TONECURVE_YM_9_SHD	(CIF_ISP_WDR_BASE + 0x000000D4)
> +#define CIF_ISP_WDR_TONECURVE_YM_10_SHD	(CIF_ISP_WDR_BASE + 0x000000D8)
> +#define CIF_ISP_WDR_TONECURVE_YM_11_SHD	(CIF_ISP_WDR_BASE + 0x000000DC)
> +#define CIF_ISP_WDR_TONECURVE_YM_12_SHD	(CIF_ISP_WDR_BASE + 0x000000E0)
> +#define CIF_ISP_WDR_TONECURVE_YM_13_SHD	(CIF_ISP_WDR_BASE + 0x000000E4)
> +#define CIF_ISP_WDR_TONECURVE_YM_14_SHD	(CIF_ISP_WDR_BASE + 0x000000E8)
> +#define CIF_ISP_WDR_TONECURVE_YM_15_SHD	(CIF_ISP_WDR_BASE + 0x000000EC)
> +#define CIF_ISP_WDR_TONECURVE_YM_16_SHD	(CIF_ISP_WDR_BASE + 0x000000F0)
> +#define CIF_ISP_WDR_TONECURVE_YM_17_SHD	(CIF_ISP_WDR_BASE + 0x000000F4)
> +#define CIF_ISP_WDR_TONECURVE_YM_18_SHD	(CIF_ISP_WDR_BASE + 0x000000F8)
> +#define CIF_ISP_WDR_TONECURVE_YM_19_SHD	(CIF_ISP_WDR_BASE + 0x000000FC)
> +#define CIF_ISP_WDR_TONECURVE_YM_20_SHD	(CIF_ISP_WDR_BASE + 0x00000100)
> +#define CIF_ISP_WDR_TONECURVE_YM_21_SHD	(CIF_ISP_WDR_BASE + 0x00000104)
> +#define CIF_ISP_WDR_TONECURVE_YM_22_SHD	(CIF_ISP_WDR_BASE + 0x00000108)
> +#define CIF_ISP_WDR_TONECURVE_YM_23_SHD	(CIF_ISP_WDR_BASE + 0x0000010C)
> +#define CIF_ISP_WDR_TONECURVE_YM_24_SHD	(CIF_ISP_WDR_BASE + 0x00000110)
> +#define CIF_ISP_WDR_TONECURVE_YM_25_SHD	(CIF_ISP_WDR_BASE + 0x00000114)
> +#define CIF_ISP_WDR_TONECURVE_YM_26_SHD	(CIF_ISP_WDR_BASE + 0x00000118)
> +#define CIF_ISP_WDR_TONECURVE_YM_27_SHD	(CIF_ISP_WDR_BASE + 0x0000011C)
> +#define CIF_ISP_WDR_TONECURVE_YM_28_SHD	(CIF_ISP_WDR_BASE + 0x00000120)
> +#define CIF_ISP_WDR_TONECURVE_YM_29_SHD	(CIF_ISP_WDR_BASE + 0x00000124)
> +#define CIF_ISP_WDR_TONECURVE_YM_30_SHD	(CIF_ISP_WDR_BASE + 0x00000128)
> +#define CIF_ISP_WDR_TONECURVE_YM_31_SHD	(CIF_ISP_WDR_BASE + 0x0000012C)
> +#define CIF_ISP_WDR_TONECURVE_YM_32_SHD	(CIF_ISP_WDR_BASE + 0x00000130)
> +
> +#define CIF_ISP_VSM_BASE		0x00002F00
> +#define CIF_ISP_VSM_MODE		(CIF_ISP_VSM_BASE + 0x00000000)
> +#define CIF_ISP_VSM_H_OFFS		(CIF_ISP_VSM_BASE + 0x00000004)
> +#define CIF_ISP_VSM_V_OFFS		(CIF_ISP_VSM_BASE + 0x00000008)
> +#define CIF_ISP_VSM_H_SIZE		(CIF_ISP_VSM_BASE + 0x0000000C)
> +#define CIF_ISP_VSM_V_SIZE		(CIF_ISP_VSM_BASE + 0x00000010)
> +#define CIF_ISP_VSM_H_SEGMENTS		(CIF_ISP_VSM_BASE + 0x00000014)
> +#define CIF_ISP_VSM_V_SEGMENTS		(CIF_ISP_VSM_BASE + 0x00000018)
> +#define CIF_ISP_VSM_DELTA_H		(CIF_ISP_VSM_BASE + 0x0000001C)
> +#define CIF_ISP_VSM_DELTA_V		(CIF_ISP_VSM_BASE + 0x00000020)
> +
> +void disable_dcrop(struct rkisp1_stream *stream, bool async);
> +void config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect,
> +		  bool async);
> +
> +void dump_rsz_regs(struct rkisp1_stream *stream);
> +void disable_rsz(struct rkisp1_stream *stream, bool async);
> +void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
> +		struct v4l2_rect *in_c, struct v4l2_rect *out_y,
> +		struct v4l2_rect *out_c, bool async);
> +
> +void config_mi_ctrl(struct rkisp1_stream *stream);
> +
> +void mp_clr_frame_end_int(void __iomem *base);
> +void sp_clr_frame_end_int(void __iomem *base);
> +
> +bool mp_is_frame_end_int_masked(void __iomem *base);
> +bool sp_is_frame_end_int_masked(void __iomem *base);
> +bool mp_is_stream_stopped(void __iomem *base);
> +bool sp_is_stream_stopped(void __iomem *base);
> +
> +static inline void mi_set_y_size(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.y_size_init);
> +}
> +
> +static inline void mi_set_cb_size(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.cb_size_init);
> +}
> +
> +static inline void mi_set_cr_size(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.cr_size_init);
> +}
> +
> +static inline void mi_set_y_addr(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.y_base_ad_init);
> +}
> +
> +static inline void mi_set_cb_addr(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.cb_base_ad_init);
> +}
> +
> +static inline void mi_set_cr_addr(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.cr_base_ad_init);
> +}
> +
> +static inline void mi_set_y_offset(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.y_offs_cnt_init);
> +}
> +
> +static inline void mi_set_cb_offset(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.cb_offs_cnt_init);
> +}
> +
> +static inline void mi_set_cr_offset(struct rkisp1_stream *stream, int val)
> +{
> +	void __iomem *base = stream->ispdev->base_addr;
> +
> +	writel(val, base + stream->config->mi.cr_offs_cnt_init);
> +}
> +
> +static inline void mp_set_chain_mode(void __iomem *base)
> +{
> +	u32 dpcl = readl(base + CIF_VI_DPCL);
> +
> +	dpcl |= CIF_VI_DPCL_CHAN_MODE_MP;
> +	writel(dpcl, base + CIF_VI_DPCL);
> +}
> +
> +static inline void sp_set_chain_mode(void __iomem *base)
> +{
> +	u32 dpcl = readl(base + CIF_VI_DPCL);
> +
> +	dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
> +	writel(dpcl, base + CIF_VI_DPCL);
> +}
> +
> +static inline void mp_set_data_path(void __iomem *base)
> +{
> +	u32 dpcl = readl(base + CIF_VI_DPCL);
> +
> +	dpcl = dpcl | CIF_VI_DPCL_CHAN_MODE_MP | CIF_VI_DPCL_MP_MUX_MRSZ_MI;
> +	writel(dpcl, base + CIF_VI_DPCL);
> +}
> +
> +static inline void sp_set_data_path(void __iomem *base)
> +{
> +	u32 dpcl = readl(base + CIF_VI_DPCL);
> +
> +	dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
> +	writel(dpcl, base + CIF_VI_DPCL);
> +}
> +
> +static inline void mp_frame_end_int_enable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_IMSC;
> +
> +	writel(CIF_MI_MP_FRAME | readl(addr), addr);
> +}
> +
> +static inline void sp_frame_end_int_enable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_IMSC;
> +
> +	writel(CIF_MI_SP_FRAME | readl(addr), addr);
> +}
> +
> +static inline void mp_frame_end_int_disable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_IMSC;
> +
> +	writel(~CIF_MI_MP_FRAME & readl(addr), addr);
> +}
> +
> +static inline void sp_frame_end_int_disable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_IMSC;
> +
> +	writel(~CIF_MI_SP_FRAME & readl(addr), addr);
> +}
> +
> +static inline void clr_mpsp_frame_end_int(void __iomem *base)
> +{
> +	writel(CIF_MI_SP_FRAME | CIF_MI_MP_FRAME, base + CIF_MI_ICR);
> +}
> +
> +static inline void clr_mp_crop_rsz_int(void __iomem *base)
> +{
> +	writel(~CIF_MI_MP_FRAME, base + CIF_MI_ICR);
> +}
> +
> +static inline void clr_sp_crop_rsz_int(void __iomem *base)
> +{
> +	writel(~CIF_MI_SP_FRAME, base + CIF_MI_ICR);
> +}
> +
> +static inline void clr_all_int(void __iomem *base)
> +{
> +	writel(~0, base + CIF_MI_ICR);
> +}
> +
> +static inline void mp_set_uv_swap(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_XTD_FORMAT_CTRL;
> +	u32 reg = readl(addr) & ~BIT(0);
> +
> +	writel(reg | CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP, addr);
> +}
> +
> +static inline void sp_set_uv_swap(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_XTD_FORMAT_CTRL;
> +	u32 reg = readl(addr) & ~BIT(1);
> +
> +	writel(reg | CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP, addr);
> +}
> +
> +static inline void sp_set_y_width(void __iomem *base, u32 val)
> +{
> +	writel(val, base + CIF_MI_SP_Y_PIC_WIDTH);
> +}
> +
> +static inline void sp_set_y_height(void __iomem *base, u32 val)
> +{
> +	writel(val, base + CIF_MI_SP_Y_PIC_HEIGHT);
> +}
> +
> +static inline void sp_set_y_line_length(void __iomem *base, u32 val)
> +{
> +	writel(val, base + CIF_MI_SP_Y_LLENGTH);
> +}
> +
> +static inline void mp_mi_ctrl_set_format(void __iomem *base, u32 val)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +	u32 reg = readl(addr) & ~MI_CTRL_MP_FMT_MASK;
> +
> +	writel(reg | val, addr);
> +}
> +
> +static inline void sp_mi_ctrl_set_format(void __iomem *base, u32 val)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +	u32 reg = readl(addr) & ~MI_CTRL_SP_FMT_MASK;
> +
> +	writel(reg | val, addr);
> +}
> +
> +static inline void mi_ctrl_mpyuv_enable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(CIF_MI_CTRL_MP_ENABLE | readl(addr), addr);
> +}
> +
> +static inline void mi_ctrl_mpyuv_disable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(~CIF_MI_CTRL_MP_ENABLE & readl(addr), addr);
> +}
> +
> +static inline void mi_ctrl_mp_disable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(~(CIF_MI_CTRL_MP_ENABLE | CIF_MI_CTRL_RAW_ENABLE) & readl(addr),
> +	       addr);
> +}
> +
> +static inline void mi_ctrl_spyuv_enable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(CIF_MI_CTRL_SP_ENABLE | readl(addr), addr);
> +}
> +
> +static inline void mi_ctrl_spyuv_disable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(~CIF_MI_CTRL_SP_ENABLE & readl(addr), addr);
> +}
> +
> +static inline void mi_ctrl_sp_disable(void __iomem *base)
> +{
> +	mi_ctrl_spyuv_disable(base);
> +}
> +
> +static inline void mi_ctrl_mpraw_enable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(CIF_MI_CTRL_RAW_ENABLE | readl(addr), addr);
> +}
> +
> +static inline void mi_ctrl_mpraw_disable(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(~CIF_MI_CTRL_RAW_ENABLE & readl(addr), addr);
> +}
> +
> +static inline void mp_mi_ctrl_autoupdate_en(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(readl(addr) | CIF_MI_MP_AUTOUPDATE_ENABLE, addr);
> +}
> +
> +static inline void sp_mi_ctrl_autoupdate_en(void __iomem *base)
> +{
> +	void __iomem *addr = base + CIF_MI_CTRL;
> +
> +	writel(readl(addr) | CIF_MI_SP_AUTOUPDATE_ENABLE, addr);
> +}
> +
> +static inline void force_cfg_update(void __iomem *base)
> +{
> +	writel(CIF_MI_INIT_SOFT_UPD, base + CIF_MI_INIT);
> +}
> +
> +static inline u32 mi_get_masked_int_status(void __iomem *base)
> +{
> +	return readl(base + CIF_MI_MIS);
> +}
> +
> +#endif /* _RKISP1_REGS_H */
> diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.c b/drivers/media/platform/rockchip/isp1/rkisp1.c
> new file mode 100644
> index 000000000000..7ce98b80f447
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/rkisp1.c
> @@ -0,0 +1,1201 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include <linux/iopoll.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/videodev2.h>
> +#include <linux/vmalloc.h>
> +#include <media/v4l2-event.h>
> +
> +#include "common.h"
> +#include "regs.h"
> +
> +#define CIF_ISP_INPUT_W_MAX		4032
> +#define CIF_ISP_INPUT_H_MAX		3024
> +#define CIF_ISP_INPUT_W_MIN		32
> +#define CIF_ISP_INPUT_H_MIN		32
> +#define CIF_ISP_OUTPUT_W_MAX		CIF_ISP_INPUT_W_MAX
> +#define CIF_ISP_OUTPUT_H_MAX		CIF_ISP_INPUT_H_MAX
> +#define CIF_ISP_OUTPUT_W_MIN		CIF_ISP_INPUT_W_MIN
> +#define CIF_ISP_OUTPUT_H_MIN		CIF_ISP_INPUT_H_MIN
> +
> +/*
> + * NOTE: MIPI controller and input MUX are also configured in this file,
> + * because ISP Subdev is not only describe ISP submodule(input size,format, output size, format),
> + * but also a virtual route device.
> + */
> +
> +/*
> + * There are many variables named with format/frame in below code,
> + * please see here for their meaning.
> + *
> + * Cropping regions of ISP
> + *
> + * +---------------------------------------------------------+
> + * | Sensor image                                            |
> + * | +---------------------------------------------------+   |
> + * | | ISP_ACQ (for black level)                         |   |
> + * | | in_frm                                            |   |
> + * | | +--------------------------------------------+    |   |
> + * | | |    ISP_OUT                                 |    |   |
> + * | | |    in_crop                                 |    |   |
> + * | | |    +---------------------------------+     |    |   |
> + * | | |    |   ISP_IS                        |     |    |   |
> + * | | |    |   rkisp1_isp_subdev: out_crop   |     |    |   |
> + * | | |    +---------------------------------+     |    |   |
> + * | | +--------------------------------------------+    |   |
> + * | +---------------------------------------------------+   |
> + * +---------------------------------------------------------+
> + */
> +
> +static inline struct rkisp1_device *sd_to_isp_dev(struct v4l2_subdev *sd)
> +{
> +	return container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev);
> +}
> +
> +/* Get sensor by enabled media link */
> +static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
> +{
> +	struct media_pad *local;
> +	struct media_entity *sensor_me;
> +
> +	local = &sd->entity.pads[RKISP1_ISP_PAD_SINK];
> +	sensor_me = media_entity_remote_pad(local)->entity;
> +
> +	return media_entity_to_v4l2_subdev(sensor_me);
> +}
> +
> +static struct rkisp1_sensor_info *sd_to_sensor(struct rkisp1_device *dev,
> +					       struct v4l2_subdev *sd)
> +{
> +	int i;
> +
> +	for (i = 0; i < dev->num_sensors; ++i)
> +		if (dev->sensors[i].sd == sd)
> +			return &dev->sensors[i];
> +
> +	return NULL;
> +}
> +
> +/****************  register operations ****************/
> +
> +/*
> + * Image Stabilization.
> + * This should only be called when configuring CIF
> + * or at the frame end interrupt
> + */
> +static void rkisp1_config_ism(struct rkisp1_device *dev)
> +{
> +	void __iomem *base = dev->base_addr;
> +	struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop;
> +	u32 val;
> +
> +	writel(0, base + CIF_ISP_IS_RECENTER);
> +	writel(0, base + CIF_ISP_IS_MAX_DX);
> +	writel(0, base + CIF_ISP_IS_MAX_DY);
> +	writel(0, base + CIF_ISP_IS_DISPLACE);
> +	writel(out_crop->left, base + CIF_ISP_IS_H_OFFS);
> +	writel(out_crop->top, base + CIF_ISP_IS_V_OFFS);
> +	writel(out_crop->width, base + CIF_ISP_IS_H_SIZE);
> +	writel(out_crop->height, base + CIF_ISP_IS_V_SIZE);
> +
> +	/* IS(Image Stabilization) is always on, working as output crop */
> +	writel(1, base + CIF_ISP_IS_CTRL);
> +	val = readl(base + CIF_ISP_CTRL);
> +	val |= CIF_ISP_CTRL_ISP_CFG_UPD;
> +	writel(val, base + CIF_ISP_CTRL);
> +}
> +
> +/*
> + * configure isp blocks with input format, size......
> + */
> +static int rkisp1_config_isp(struct rkisp1_device *dev)
> +{
> +	struct ispsd_in_fmt *in_fmt;
> +	struct ispsd_out_fmt *out_fmt;
> +	struct v4l2_mbus_framefmt *in_frm;
> +	struct v4l2_rect *out_crop, *in_crop;
> +	struct rkisp1_sensor_info *sensor;
> +	void __iomem *base = dev->base_addr;
> +	u32 isp_ctrl = 0;
> +	u32 irq_mask = 0;
> +	u32 signal = 0;
> +	u32 acq_mult = 0;
> +	u32 val;
> +
> +	sensor = dev->active_sensor;
> +	in_frm = &dev->isp_sdev.in_frm;
> +	in_fmt = &dev->isp_sdev.in_fmt;
> +	out_fmt = &dev->isp_sdev.out_fmt;
> +	out_crop = &dev->isp_sdev.out_crop;
> +	in_crop = &dev->isp_sdev.in_crop;
> +	val = readl(base + CIF_ICCL);
> +	writel(val | CIF_ICCL_ISP_CLK, base + CIF_ICCL);
> +
> +	if (in_fmt->fmt_type == FMT_BAYER) {
> +		acq_mult = 1;
> +		if (out_fmt->fmt_type == FMT_BAYER) {
> +			if (sensor->mbus.type == V4L2_MBUS_BT656)
> +				isp_ctrl =
> +					CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656;
> +			else
> +				isp_ctrl =
> +					CIF_ISP_CTRL_ISP_MODE_RAW_PICT;
> +		} else {
> +			writel(CIF_ISP_DEMOSAIC_TH(0xc),
> +			       base + CIF_ISP_DEMOSAIC);
> +
> +			if (sensor->mbus.type == V4L2_MBUS_BT656)
> +				isp_ctrl = CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656;
> +			else
> +				isp_ctrl = CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601;
> +		}
> +	} else if (in_fmt->fmt_type == FMT_YUV) {
> +		acq_mult = 2;
> +		if (sensor->mbus.type == V4L2_MBUS_CSI2) {
> +			isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
> +		} else {
> +			if (sensor->mbus.type == V4L2_MBUS_BT656)
> +				isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU656;
> +			else
> +				isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
> +
> +		}
> +
> +		irq_mask |= CIF_ISP_DATA_LOSS;
> +	}
> +
> +	/* Set up input acquisition properties */
> +	if (sensor->mbus.type == V4L2_MBUS_BT656 ||
> +	    sensor->mbus.type == V4L2_MBUS_PARALLEL) {
> +		if (sensor->mbus.flags &
> +			V4L2_MBUS_PCLK_SAMPLE_RISING)
> +			signal = CIF_ISP_ACQ_PROP_POS_EDGE;
> +	}
> +
> +	if (sensor->mbus.type == V4L2_MBUS_PARALLEL) {
> +		if (sensor->mbus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
> +			signal |= CIF_ISP_ACQ_PROP_VSYNC_LOW;
> +
> +		if (sensor->mbus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
> +			signal |= CIF_ISP_ACQ_PROP_HSYNC_LOW;
> +	}
> +
> +	writel(isp_ctrl, base + CIF_ISP_CTRL);
> +	writel(signal | in_fmt->yuv_seq |
> +	       CIF_ISP_ACQ_PROP_BAYER_PAT(in_fmt->bayer_pat) |
> +	       CIF_ISP_ACQ_PROP_FIELD_SEL_ALL, base + CIF_ISP_ACQ_PROP);
> +	writel(0, base + CIF_ISP_ACQ_NR_FRAMES);
> +
> +	/* Acquisition Size */
> +	writel(0, base + CIF_ISP_ACQ_H_OFFS);
> +	writel(0, base + CIF_ISP_ACQ_V_OFFS);
> +	writel(acq_mult * in_frm->width, base + CIF_ISP_ACQ_H_SIZE);
> +	writel(in_frm->height, base + CIF_ISP_ACQ_V_SIZE);
> +
> +	/* ISP Out Area */
> +	writel(in_crop->left, base + CIF_ISP_OUT_H_OFFS);
> +	writel(in_crop->top, base + CIF_ISP_OUT_V_OFFS);
> +	writel(in_crop->width, base + CIF_ISP_OUT_H_SIZE);
> +	writel(in_crop->height, base + CIF_ISP_OUT_V_SIZE);
> +
> +	/* interrupt mask */
> +	irq_mask |= CIF_ISP_FRAME | CIF_ISP_V_START | CIF_ISP_PIC_SIZE_ERROR |
> +		    CIF_ISP_FRAME_IN;
> +	writel(irq_mask, base + CIF_ISP_IMSC);
> +
> +	if (out_fmt->fmt_type == FMT_BAYER)
> +		rkisp1_disable_isp(&dev->params_vdev);
> +	else
> +		rkisp1_configure_isp(&dev->params_vdev, in_fmt, 0);
> +
> +	return 0;
> +}
> +
> +static int rkisp1_config_dvp(struct rkisp1_device *dev)
> +{
> +	struct ispsd_in_fmt *in_fmt = &dev->isp_sdev.in_fmt;
> +	void __iomem *base = dev->base_addr;
> +	u32 val, input_sel;
> +
> +	switch (in_fmt->bus_width) {
> +	case 8:
> +		input_sel = CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO;
> +		break;
> +	case 10:
> +		input_sel = CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO;
> +		break;
> +	case 12:
> +		input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
> +		break;
> +	default:
> +		v4l2_err(&dev->v4l2_dev, "Invalid bus width\n");
> +		return -EINVAL;
> +	}
> +
> +	val = readl(base + CIF_ISP_ACQ_PROP);
> +	writel(val | input_sel, base + CIF_ISP_ACQ_PROP);
> +
> +	return 0;
> +}
> +
> +static int rkisp1_config_mipi(struct rkisp1_device *dev)
> +{
> +	u32 mipi_ctrl, val;
> +	void __iomem *base = dev->base_addr;
> +	struct ispsd_in_fmt *in_fmt = &dev->isp_sdev.in_fmt;
> +	struct rkisp1_sensor_info *sensor = dev->active_sensor;
> +	int lanes;
> +
> +	/*
> +	 * sensor->mbus is set in isp or d-phy notifier_bound function
> +	 */
> +	switch (sensor->mbus.flags & V4L2_MBUS_CSI2_LANES) {
> +	case V4L2_MBUS_CSI2_4_LANE:
> +		lanes = 4;
> +		break;
> +	case V4L2_MBUS_CSI2_3_LANE:
> +		lanes = 3;
> +		break;
> +	case V4L2_MBUS_CSI2_2_LANE:
> +		lanes = 2;
> +		break;
> +	case V4L2_MBUS_CSI2_1_LANE:
> +		lanes = 1;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	val = readl(base + CIF_ICCL);
> +	writel(val | CIF_ICCL_MIPI_CLK, base + CIF_ICCL);
> +
> +	mipi_ctrl = CIF_MIPI_CTRL_NUM_LANES(lanes - 1) |
> +		    CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) |
> +		    CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP |
> +		    CIF_MIPI_CTRL_CLOCKLANE_ENA;
> +
> +	writel(mipi_ctrl, base + CIF_MIPI_CTRL);
> +
> +	/* Configure Data Type and Virtual Channel */
> +	writel(CIF_MIPI_DATA_SEL_DT(in_fmt->mipi_dt) | CIF_MIPI_DATA_SEL_VC(0),
> +	       base + CIF_MIPI_IMG_DATA_SEL);
> +
> +	/* Clear MIPI interrupts */
> +	writel(~0, base + CIF_MIPI_ICR);
> +	/*
> +	 * Disable CIF_MIPI_ERR_DPHY interrupt here temporary for
> +	 * isp bus may be dead when switch isp.
> +	 */
> +	writel(CIF_MIPI_FRAME_END | CIF_MIPI_ERR_CSI | CIF_MIPI_ERR_DPHY |
> +	       CIF_MIPI_SYNC_FIFO_OVFLW(0x03) | CIF_MIPI_ADD_DATA_OVFLW,
> +	       base + CIF_MIPI_IMSC);
> +
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "\n  MIPI_CTRL 0x%08x\n"
> +		 "  MIPI_IMG_DATA_SEL 0x%08x\n"
> +		 "  MIPI_STATUS 0x%08x\n"
> +		 "  MIPI_IMSC 0x%08x\n",
> +		 readl(base + CIF_MIPI_CTRL),
> +		 readl(base + CIF_MIPI_IMG_DATA_SEL),
> +		 readl(base + CIF_MIPI_STATUS),
> +		 readl(base + CIF_MIPI_IMSC));
> +
> +	return 0;
> +}
> +
> +/* Configure MUX */
> +static int rkisp1_config_path(struct rkisp1_device *dev)
> +{
> +	int ret = 0;
> +	struct rkisp1_sensor_info *sensor = dev->active_sensor;
> +	u32 dpcl = readl(dev->base_addr + CIF_VI_DPCL);
> +
> +	if (sensor->mbus.type == V4L2_MBUS_BT656 ||
> +	    sensor->mbus.type == V4L2_MBUS_PARALLEL) {
> +		ret = rkisp1_config_dvp(dev);
> +		dpcl |= CIF_VI_DPCL_IF_SEL_PARALLEL;
> +	} else if (sensor->mbus.type == V4L2_MBUS_CSI2) {
> +		ret = rkisp1_config_mipi(dev);
> +		dpcl |= CIF_VI_DPCL_IF_SEL_MIPI;
> +	}
> +
> +	writel(dpcl, dev->base_addr + CIF_VI_DPCL);
> +
> +	return ret;
> +}
> +
> +/* Hareware configure Entry */
> +static int rkisp1_config_cif(struct rkisp1_device *dev)
> +{
> +	int ret = 0;
> +	u32 cif_id;
> +
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> +		 "SP state = %d, MP state = %d\n",
> +		 dev->stream[RKISP1_STREAM_SP].state,
> +		 dev->stream[RKISP1_STREAM_MP].state);
> +
> +	cif_id = readl(dev->base_addr + CIF_VI_ID);
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "CIF_ID 0x%08x\n", cif_id);
> +
> +	ret = rkisp1_config_isp(dev);
> +	if (ret < 0)
> +		return ret;
> +	ret = rkisp1_config_path(dev);
> +	if (ret < 0)
> +		return ret;
> +	rkisp1_config_ism(dev);
> +
> +	return 0;
> +}
> +
> +/* Mess register operations to stop isp */
> +static int rkisp1_isp_stop(struct rkisp1_device *dev)
> +{
> +	void __iomem *base = dev->base_addr;
> +	u32 val;
> +
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> +		 "SP state = %d, MP state = %d\n",
> +		 dev->stream[RKISP1_STREAM_SP].state,
> +		 dev->stream[RKISP1_STREAM_MP].state);
> +
> +	/*
> +	 * ISP(mi) stop in mi frame end -> Stop ISP(mipi) ->
> +	 * Stop ISP(isp) ->wait for ISP isp off
> +	 */
> +	/* stop and clear MI, MIPI, and ISP interrupts */
> +	writel(0, base + CIF_MIPI_IMSC);
> +	writel(~0, base + CIF_MIPI_ICR);
> +
> +	writel(0, base + CIF_ISP_IMSC);
> +	writel(~0, base + CIF_ISP_ICR);
> +
> +	writel(0, base + CIF_MI_IMSC);
> +	writel(~0, base + CIF_MI_ICR);
> +	val = readl(base + CIF_MIPI_CTRL);
> +	writel(val & (~CIF_MIPI_CTRL_OUTPUT_ENA), base + CIF_MIPI_CTRL);
> +	/* stop ISP */
> +	val = readl(base + CIF_ISP_CTRL);
> +	val &= ~(CIF_ISP_CTRL_ISP_INFORM_ENABLE | CIF_ISP_CTRL_ISP_ENABLE);
> +	writel(val, base + CIF_ISP_CTRL);
> +
> +	val = readl(base + CIF_ISP_CTRL);
> +	writel(val | CIF_ISP_CTRL_ISP_CFG_UPD, base + CIF_ISP_CTRL);
> +
> +	readx_poll_timeout(readl, base + CIF_ISP_RIS,
> +			   val, val & CIF_ISP_OFF, 20, 100);
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> +		"state(MP:%d, SP:%d), MI_CTRL:%x, ISP_CTRL:%x, MIPI_CTRL:%x\n",
> +		 dev->stream[RKISP1_STREAM_SP].state,
> +		 dev->stream[RKISP1_STREAM_MP].state,
> +		 readl(base + CIF_MI_CTRL),
> +		 readl(base + CIF_ISP_CTRL),
> +		 readl(base + CIF_MIPI_CTRL));
> +
> +	writel(CIF_IRCL_MIPI_SW_RST | CIF_IRCL_ISP_SW_RST, base + CIF_IRCL);
> +	writel(0x0, base + CIF_IRCL);
> +
> +	return 0;
> +}
> +
> +/* Mess register operations to start isp */
> +static int rkisp1_isp_start(struct rkisp1_device *dev)
> +{
> +	struct rkisp1_sensor_info *sensor = dev->active_sensor;
> +	void __iomem *base = dev->base_addr;
> +	u32 val;
> +
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> +		 "SP state = %d, MP state = %d\n",
> +		 dev->stream[RKISP1_STREAM_SP].state,
> +		 dev->stream[RKISP1_STREAM_MP].state);
> +
> +	/* Activate MIPI */
> +	if (sensor->mbus.type == V4L2_MBUS_CSI2) {
> +		val = readl(base + CIF_MIPI_CTRL);
> +		writel(val | CIF_MIPI_CTRL_OUTPUT_ENA, base + CIF_MIPI_CTRL);
> +	}
> +	/* Activate ISP */
> +	val = readl(base + CIF_ISP_CTRL);
> +	val |= CIF_ISP_CTRL_ISP_CFG_UPD | CIF_ISP_CTRL_ISP_ENABLE |
> +	       CIF_ISP_CTRL_ISP_INFORM_ENABLE;
> +	writel(val, base + CIF_ISP_CTRL);
> +
> +	/* XXX: Is the 1000us too long?
> +	 * CIF spec says to wait for sufficient time after enabling
> +	 * the MIPI interface and before starting the sensor output.
> +	 */
> +	usleep_range(1000, 1200);
> +
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> +		 "SP state = %d, MP state = %d MI_CTRL 0x%08x\n"
> +		 "  ISP_CTRL 0x%08x MIPI_CTRL 0x%08x\n",
> +		 dev->stream[RKISP1_STREAM_SP].state,
> +		 dev->stream[RKISP1_STREAM_MP].state,
> +		 readl(base + CIF_MI_CTRL),
> +		 readl(base + CIF_ISP_CTRL),
> +		 readl(base + CIF_MIPI_CTRL));
> +
> +	return 0;
> +}
> +
> +static void rkisp1_config_clk(struct rkisp1_device *dev)
> +{
> +	u32 val = CIF_ICCL_ISP_CLK | CIF_ICCL_CP_CLK | CIF_ICCL_MRSZ_CLK |
> +		CIF_ICCL_SRSZ_CLK | CIF_ICCL_JPEG_CLK | CIF_ICCL_MI_CLK |
> +		CIF_ICCL_MIPI_CLK | CIF_ICCL_DCROP_CLK;
> +
> +	writel(val, dev->base_addr + CIF_ICCL);
> +}
> +
> +/***************************** isp sub-devs *******************************/
> +
> +static const struct ispsd_in_fmt rkisp1_isp_input_formats[] = {
> +	{
> +		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW10,
> +		.bayer_pat	= RAW_BGGR,
> +		.bus_width	= 10,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW10,
> +		.bayer_pat	= RAW_RGGB,
> +		.bus_width	= 10,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW10,
> +		.bayer_pat	= RAW_GBRG,
> +		.bus_width	= 10,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW10,
> +		.bayer_pat	= RAW_GRBG,
> +		.bus_width	= 10,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW12,
> +		.bayer_pat	= RAW_RGGB,
> +		.bus_width	= 12,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW12,
> +		.bayer_pat	= RAW_BGGR,
> +		.bus_width	= 12,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW12,
> +		.bayer_pat	= RAW_GBRG,
> +		.bus_width	= 12,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW12,
> +		.bayer_pat	= RAW_GRBG,
> +		.bus_width	= 12,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW8,
> +		.bayer_pat	= RAW_RGGB,
> +		.bus_width	= 8,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW8,
> +		.bayer_pat	= RAW_BGGR,
> +		.bus_width	= 8,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW8,
> +		.bayer_pat	= RAW_GBRG,
> +		.bus_width	= 8,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
> +		.fmt_type	= FMT_BAYER,
> +		.mipi_dt	= CIF_CSI2_DT_RAW8,
> +		.bayer_pat	= RAW_GRBG,
> +		.bus_width	= 8,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_YUYV8_1X16,
> +		.fmt_type	= FMT_YUV,
> +		.mipi_dt	= CIF_CSI2_DT_YUV422_8b,
> +		.yuv_seq	= CIF_ISP_ACQ_PROP_YCBYCR,
> +		.bus_width	= 16,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_YVYU8_1X16,
> +		.fmt_type	= FMT_YUV,
> +		.mipi_dt	= CIF_CSI2_DT_YUV422_8b,
> +		.yuv_seq	= CIF_ISP_ACQ_PROP_YCRYCB,
> +		.bus_width	= 16,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_UYVY8_1X16,
> +		.fmt_type	= FMT_YUV,
> +		.mipi_dt	= CIF_CSI2_DT_YUV422_8b,
> +		.yuv_seq	= CIF_ISP_ACQ_PROP_CBYCRY,
> +		.bus_width	= 16,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_VYUY8_1X16,
> +		.fmt_type	= FMT_YUV,
> +		.mipi_dt	= CIF_CSI2_DT_YUV422_8b,
> +		.yuv_seq	= CIF_ISP_ACQ_PROP_CRYCBY,
> +		.bus_width	= 16,
> +	},
> +};
> +
> +static const struct ispsd_out_fmt rkisp1_isp_output_formats[] = {
> +	{
> +		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
> +		.fmt_type	= FMT_YUV,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
> +		.fmt_type	= FMT_BAYER,
> +	}, {
> +		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
> +		.fmt_type	= FMT_BAYER,
> +	},
> +};
> +
> +static const struct ispsd_in_fmt *find_in_fmt(u32 mbus_code)
> +{
> +	const struct ispsd_in_fmt *fmt;
> +	int i, array_size = ARRAY_SIZE(rkisp1_isp_input_formats);
> +
> +	for (i = 0; i < array_size; i++) {
> +		fmt = &rkisp1_isp_input_formats[i];
> +		if (fmt->mbus_code == mbus_code)
> +			return fmt;
> +	}
> +
> +	return NULL;
> +}
> +
> +static const struct ispsd_out_fmt *find_out_fmt(u32 mbus_code)
> +{
> +	const struct ispsd_out_fmt *fmt;
> +	int i, array_size = ARRAY_SIZE(rkisp1_isp_output_formats);
> +
> +	for (i = 0; i < array_size; i++) {
> +		fmt = &rkisp1_isp_output_formats[i];
> +		if (fmt->mbus_code == mbus_code)
> +			return fmt;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int rkisp1_isp_sd_enum_mbus_code(struct v4l2_subdev *sd,
> +					struct v4l2_subdev_pad_config *cfg,
> +					struct v4l2_subdev_mbus_code_enum *code)
> +{
> +	int i = code->index;
> +
> +	if (code->pad == RKISP1_ISP_PAD_SINK) {
> +		if (i >= ARRAY_SIZE(rkisp1_isp_input_formats))
> +			return -EINVAL;
> +		code->code = rkisp1_isp_input_formats[i].mbus_code;
> +	} else {
> +		if (i >= ARRAY_SIZE(rkisp1_isp_output_formats))
> +			return -EINVAL;
> +		code->code = rkisp1_isp_output_formats[i].mbus_code;
> +	}
> +
> +	return 0;
> +}
> +
> +#define sd_to_isp_sd(_sd) container_of(_sd, struct rkisp1_isp_subdev, sd)
> +static int rkisp1_isp_sd_get_fmt(struct v4l2_subdev *sd,
> +				 struct v4l2_subdev_pad_config *cfg,
> +				 struct v4l2_subdev_format *fmt)
> +{
> +	struct v4l2_mbus_framefmt *mf = &fmt->format;
> +	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
> +
> +	if ((fmt->pad != RKISP1_ISP_PAD_SINK) &&
> +	    (fmt->pad != RKISP1_ISP_PAD_SOURCE_PATH))
> +		return -EINVAL;
> +
> +	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> +		mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
> +		fmt->format = *mf;
> +		return 0;
> +	}
> +
> +	if (fmt->pad == RKISP1_ISP_PAD_SINK) {
> +		*mf = isp_sd->in_frm;
> +	} else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
> +		/* format of source pad */
> +		*mf = isp_sd->in_frm;
> +		/* window size of source pad */
> +		mf->width = isp_sd->out_crop.width;
> +		mf->height = isp_sd->out_crop.height;
> +	}
> +	mf->field = V4L2_FIELD_NONE;
> +
> +	return 0;
> +}
> +
> +static void rkisp1_isp_sd_try_fmt(struct v4l2_subdev *sd,
> +				  unsigned int pad,
> +				  struct v4l2_mbus_framefmt *fmt)
> +{
> +	struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
> +	struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
> +	const struct ispsd_in_fmt *in_fmt;
> +	const struct ispsd_out_fmt *out_fmt;
> +
> +	switch (pad) {
> +	case RKISP1_ISP_PAD_SINK:
> +		in_fmt = find_in_fmt(fmt->code);
> +		if (in_fmt)
> +			fmt->code = in_fmt->mbus_code;
> +		else
> +			fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
> +		fmt->width  = clamp_t(u32, fmt->width, CIF_ISP_INPUT_W_MIN,
> +				      CIF_ISP_INPUT_W_MAX);
> +		fmt->height = clamp_t(u32, fmt->height, CIF_ISP_INPUT_H_MIN,
> +				      CIF_ISP_INPUT_H_MAX);
> +		break;
> +	case RKISP1_ISP_PAD_SOURCE_PATH:
> +		out_fmt = find_out_fmt(fmt->code);
> +		if (out_fmt)
> +			fmt->code = out_fmt->mbus_code;
> +		else
> +			fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
> +		/* window size is set in s_selection */
> +		fmt->width  = isp_sd->out_crop.width;
> +		fmt->height = isp_sd->out_crop.height;
> +		break;
> +	}
> +
> +	fmt->field = V4L2_FIELD_NONE;
> +}
> +
> +static int rkisp1_isp_sd_set_fmt(struct v4l2_subdev *sd,
> +				 struct v4l2_subdev_pad_config *cfg,
> +				 struct v4l2_subdev_format *fmt)
> +{
> +	struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
> +	struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
> +	struct v4l2_mbus_framefmt *mf = &fmt->format;
> +
> +	if ((fmt->pad != RKISP1_ISP_PAD_SINK) &&
> +	    (fmt->pad != RKISP1_ISP_PAD_SOURCE_PATH))
> +		return -EINVAL;
> +
> +	rkisp1_isp_sd_try_fmt(sd, fmt->pad, mf);
> +
> +	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> +		struct v4l2_mbus_framefmt *try_mf;
> +
> +		mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
> +		*try_mf = *mf;
> +		return 0;
> +	}
> +
> +	if (fmt->pad == RKISP1_ISP_PAD_SINK) {
> +		const struct ispsd_in_fmt *in_fmt;
> +
> +		in_fmt = find_in_fmt(mf->code);
> +		isp_sd->in_fmt = *in_fmt;
> +		isp_sd->in_frm = *mf;
> +	} else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
> +		const struct ispsd_out_fmt *out_fmt;
> +
> +		/* Ignore width/height */
> +		out_fmt = find_out_fmt(mf->code);
> +		isp_sd->out_fmt = *out_fmt;
> +	}
> +
> +	return 0;
> +}
> +
> +static void rkisp1_isp_sd_try_crop(struct v4l2_subdev *sd,
> +				  struct v4l2_subdev_pad_config *cfg,
> +				  struct v4l2_subdev_selection *sel)
> +{
> +	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
> +	struct v4l2_mbus_framefmt in_frm = isp_sd->in_frm;
> +	struct v4l2_rect in_crop = isp_sd->in_crop;
> +	struct v4l2_rect *input = &sel->r;
> +
> +	if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
> +		in_frm = *v4l2_subdev_get_try_format(sd, cfg, RKISP1_ISP_PAD_SINK);
> +		in_crop = *v4l2_subdev_get_try_crop(sd, cfg, RKISP1_ISP_PAD_SINK);
> +	}
> +
> +	input->left = ALIGN(input->left, 2);
> +	input->width = ALIGN(input->width, 2);
> +
> +	if (sel->pad == RKISP1_ISP_PAD_SINK) {
> +		input->left = clamp_t(u32, input->left, 0, in_frm.width);
> +		input->top = clamp_t(u32, input->top, 0, in_frm.height);
> +		input->width = clamp_t(u32, input->width, CIF_ISP_INPUT_W_MIN,
> +				in_frm.width - input->left);
> +		input->height = clamp_t(u32, input->height,
> +				CIF_ISP_INPUT_H_MIN,
> +				in_frm.height - input->top);
> +	} else if (sel->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
> +		input->left = clamp_t(u32, input->left, 0, in_crop.width);
> +		input->top = clamp_t(u32, input->top, 0, in_crop.height);
> +		input->width = clamp_t(u32, input->width, CIF_ISP_OUTPUT_W_MIN,
> +				in_crop.width - input->left);
> +		input->height = clamp_t(u32, input->height, CIF_ISP_OUTPUT_H_MIN,
> +				in_crop.height - input->top);
> +	}
> +}
> +
> +static int rkisp1_isp_sd_get_selection(struct v4l2_subdev *sd,
> +				       struct v4l2_subdev_pad_config *cfg,
> +				       struct v4l2_subdev_selection *sel)
> +{
> +	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
> +
> +	if (sel->pad != RKISP1_ISP_PAD_SOURCE_PATH &&
> +	    sel->pad != RKISP1_ISP_PAD_SINK)
> +		return -EINVAL;
> +
> +	if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
> +		struct v4l2_rect *try_sel;
> +
> +		try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
> +		sel->r = *try_sel;
> +		return 0;
> +	}
> +
> +	switch (sel->target) {
> +	case V4L2_SEL_TGT_CROP_BOUNDS:
> +		if (sel->pad == RKISP1_ISP_PAD_SINK) {
> +			sel->r.height = isp_sd->in_frm.height;
> +			sel->r.width = isp_sd->in_frm.width;
> +			sel->r.left = 0;
> +			sel->r.top = 0;
> +		} else {
> +			sel->r = isp_sd->in_crop;
> +		}
> +		break;
> +	case V4L2_SEL_TGT_CROP:
> +		if (sel->pad == RKISP1_ISP_PAD_SINK)
> +			sel->r = isp_sd->in_crop;
> +		else
> +			sel->r = isp_sd->out_crop;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rkisp1_isp_sd_set_selection(struct v4l2_subdev *sd,
> +				       struct v4l2_subdev_pad_config *cfg,
> +				       struct v4l2_subdev_selection *sel)
> +{
> +	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
> +	struct rkisp1_device *dev = sd_to_isp_dev(sd);
> +
> +	if (sel->pad != RKISP1_ISP_PAD_SOURCE_PATH &&
> +	    sel->pad != RKISP1_ISP_PAD_SINK)
> +		return -EINVAL;
> +	if (sel->target != V4L2_SEL_TGT_CROP)
> +		return -EINVAL;
> +
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
> +		 "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, sel->pad,
> +		 sel->r.left, sel->r.top, sel->r.width, sel->r.height);
> +	rkisp1_isp_sd_try_crop(sd, cfg, sel);
> +
> +	if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
> +		struct v4l2_rect *try_sel;
> +
> +		try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
> +		*try_sel = sel->r;
> +		return 0;
> +	}
> +
> +	if (sel->pad == RKISP1_ISP_PAD_SINK)
> +		isp_sd->in_crop = sel->r;
> +	else
> +		isp_sd->out_crop = sel->r;
> +
> +	return 0;
> +}
> +
> +static int rkisp1_isp_sd_s_stream(struct v4l2_subdev *sd, int on)
> +{
> +	struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
> +	struct rkisp1_sensor_info *sensor;
> +	struct v4l2_subdev *sensor_sd;
> +	int ret = 0;
> +
> +	if (!on)
> +		return rkisp1_isp_stop(isp_dev);
> +
> +	sensor_sd = get_remote_sensor(sd);
> +	if (!sensor_sd)
> +		return -ENODEV;
> +
> +	sensor = sd_to_sensor(isp_dev, sensor_sd);
> +	/*
> +	 * Update sensor bus configuration. This is only effective
> +	 * for sensors chained off an external CSI2 PHY.
> +	 */
> +	ret = v4l2_subdev_call(sensor->sd, video, g_mbus_config,
> +			       &sensor->mbus);

What do you use g_mbus_config for? Typically this information should
come from the device tree. I want to remove this op in the not-too-distant
future since it really makes no sense.

> +	if (ret && ret != -ENOIOCTLCMD)
> +		return ret;
> +	isp_dev->active_sensor = sensor;
> +
> +	atomic_set(&isp_dev->isp_sdev.frm_sync_seq, 0);
> +	ret = rkisp1_config_cif(isp_dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	return rkisp1_isp_start(isp_dev);
> +}
> +
> +static int rkisp1_isp_sd_s_power(struct v4l2_subdev *sd, int on)
> +{
> +	struct rkisp1_device *dev = sd_to_isp_dev(sd);
> +	int ret;
> +
> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "s_power: %d\n", on);
> +
> +	if (on) {
> +		ret = pm_runtime_get_sync(dev->dev);
> +		if (ret < 0)
> +			return ret;
> +
> +		rkisp1_config_clk(dev);
> +	} else {
> +		ret = pm_runtime_put(dev->dev);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rkisp1_subdev_link_validate(struct media_link *link)
> +{
> +	if (link->source->index == RKISP1_ISP_PAD_SINK_PARAMS)
> +		return 0;
> +
> +	return v4l2_subdev_link_validate(link);
> +}
> +
> +static int rkisp1_subdev_fmt_link_validate(struct v4l2_subdev *sd,
> +			     struct media_link *link,
> +			     struct v4l2_subdev_format *source_fmt,
> +			     struct v4l2_subdev_format *sink_fmt)
> +{
> +	if (source_fmt->format.code != sink_fmt->format.code)
> +		return -EINVAL;
> +
> +	/* Crop is available */
> +	if (source_fmt->format.width < sink_fmt->format.width ||
> +		source_fmt->format.height < sink_fmt->format.height)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static void
> +riksp1_isp_queue_event_sof(struct rkisp1_isp_subdev *isp)
> +{
> +	struct v4l2_event event = {
> +		.type = V4L2_EVENT_FRAME_SYNC,
> +		.u.frame_sync.frame_sequence =
> +			atomic_inc_return(&isp->frm_sync_seq) - 1,
> +	};
> +	v4l2_event_queue(isp->sd.devnode, &event);
> +}
> +
> +static int rkisp1_isp_sd_subs_evt(struct v4l2_subdev *sd, struct v4l2_fh *fh,
> +				  struct v4l2_event_subscription *sub)
> +{
> +	if (sub->type != V4L2_EVENT_FRAME_SYNC)
> +		return -EINVAL;
> +
> +	/* Line number. For now only zero accepted. */
> +	if (sub->id != 0)
> +		return -EINVAL;
> +
> +	return v4l2_event_subscribe(fh, sub, 0, NULL);
> +}
> +
> +static const struct v4l2_subdev_pad_ops rkisp1_isp_sd_pad_ops = {
> +	.enum_mbus_code = rkisp1_isp_sd_enum_mbus_code,
> +	.get_selection = rkisp1_isp_sd_get_selection,
> +	.set_selection = rkisp1_isp_sd_set_selection,
> +	.get_fmt = rkisp1_isp_sd_get_fmt,
> +	.set_fmt = rkisp1_isp_sd_set_fmt,
> +	.link_validate = rkisp1_subdev_fmt_link_validate,
> +};
> +
> +static const struct media_entity_operations rkisp1_isp_sd_media_ops = {
> +	.link_validate = rkisp1_subdev_link_validate,
> +};
> +
> +static const struct v4l2_subdev_video_ops rkisp1_isp_sd_video_ops = {
> +	.s_stream = rkisp1_isp_sd_s_stream,
> +};
> +
> +static const struct v4l2_subdev_core_ops rkisp1_isp_core_ops = {
> +	.subscribe_event = rkisp1_isp_sd_subs_evt,
> +	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
> +	.s_power = rkisp1_isp_sd_s_power,
> +};
> +
> +static struct v4l2_subdev_ops rkisp1_isp_sd_ops = {
> +	.core = &rkisp1_isp_core_ops,
> +	.video = &rkisp1_isp_sd_video_ops,
> +	.pad = &rkisp1_isp_sd_pad_ops,
> +};
> +
> +static void rkisp1_isp_sd_init_default_fmt(struct rkisp1_isp_subdev *isp_sd)
> +{
> +	struct v4l2_mbus_framefmt *in_frm = &isp_sd->in_frm;
> +	struct v4l2_rect *in_crop = &isp_sd->in_crop;
> +	struct v4l2_rect *out_crop = &isp_sd->out_crop;
> +	struct ispsd_in_fmt *in_fmt = &isp_sd->in_fmt;
> +	struct ispsd_out_fmt *out_fmt = &isp_sd->out_fmt;
> +
> +	*in_fmt = rkisp1_isp_input_formats[0];
> +	in_frm->width = RKISP1_DEFAULT_WIDTH;
> +	in_frm->height = RKISP1_DEFAULT_HEIGHT;
> +	in_frm->code = in_fmt->mbus_code;
> +
> +	in_crop->width = in_frm->width;
> +	in_crop->height = in_frm->height;
> +	in_crop->left = 0;
> +	in_crop->top = 0;
> +
> +	/* propagate to source */
> +	*out_crop = *in_crop;
> +	*out_fmt = rkisp1_isp_output_formats[0];
> +}
> +
> +int rkisp1_register_isp_subdev(struct rkisp1_device *isp_dev,
> +			       struct v4l2_device *v4l2_dev)
> +{
> +	struct rkisp1_isp_subdev *isp_sdev = &isp_dev->isp_sdev;
> +	struct v4l2_subdev *sd = &isp_sdev->sd;
> +	int ret;
> +
> +	v4l2_subdev_init(sd, &rkisp1_isp_sd_ops);
> +	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
> +	sd->entity.ops = &rkisp1_isp_sd_media_ops;
> +	snprintf(sd->name, sizeof(sd->name), "rkisp1-isp-subdev");
> +
> +	isp_sdev->pads[RKISP1_ISP_PAD_SINK].flags =
> +		MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
> +	isp_sdev->pads[RKISP1_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
> +	isp_sdev->pads[RKISP1_ISP_PAD_SOURCE_PATH].flags = MEDIA_PAD_FL_SOURCE;
> +	isp_sdev->pads[RKISP1_ISP_PAD_SOURCE_STATS].flags = MEDIA_PAD_FL_SOURCE;
> +	sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
> +	ret = media_entity_pads_init(&sd->entity, RKISP1_ISP_PAD_MAX,
> +				     isp_sdev->pads);
> +	if (ret < 0)
> +		return ret;
> +
> +	sd->owner = THIS_MODULE;
> +	v4l2_set_subdevdata(sd, isp_dev);
> +
> +	sd->grp_id = GRP_ID_ISP;
> +	ret = v4l2_device_register_subdev(v4l2_dev, sd);
> +	if (ret < 0) {
> +		v4l2_err(sd, "Failed to register isp subdev\n");
> +		goto err_cleanup_media_entity;
> +	}
> +
> +	rkisp1_isp_sd_init_default_fmt(isp_sdev);
> +
> +	return 0;
> +err_cleanup_media_entity:
> +	media_entity_cleanup(&sd->entity);
> +	return ret;
> +}
> +
> +void rkisp1_unregister_isp_subdev(struct rkisp1_device *isp_dev)
> +{
> +	struct v4l2_subdev *sd = &isp_dev->isp_sdev.sd;
> +
> +	v4l2_device_unregister_subdev(sd);
> +	media_entity_cleanup(&sd->entity);
> +}
> +
> +/****************  Interrupter Handler ****************/
> +
> +void rkisp1_mipi_isr(unsigned int mis, struct rkisp1_device *dev)
> +{
> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
> +	void __iomem *base = dev->base_addr;
> +	u32 val;
> +
> +	writel(~0, base + CIF_MIPI_ICR);
> +
> +	/*
> +	 * Disable DPHY errctrl interrupt, because this dphy
> +	 * erctrl signal is asserted until the next changes
> +	 * of line state. This time is may be too long and cpu
> +	 * is hold in this interrupt.
> +	 */
> +	if (mis & CIF_MIPI_ERR_CTRL(0x0f)) {
> +		val = readl(base + CIF_MIPI_IMSC);
> +		writel(val & ~CIF_MIPI_ERR_CTRL(0x0f), base + CIF_MIPI_IMSC);
> +		dev->isp_sdev.dphy_errctrl_disabled = true;
> +	}
> +
> +	/*
> +	 * Enable DPHY errctrl interrupt again, if mipi have receive
> +	 * the whole frame without any error.
> +	 */
> +	if (mis == CIF_MIPI_FRAME_END) {
> +		/*
> +		 * Enable DPHY errctrl interrupt again, if mipi have receive
> +		 * the whole frame without any error.
> +		 */
> +		if (dev->isp_sdev.dphy_errctrl_disabled) {
> +			val = readl(base + CIF_MIPI_IMSC);
> +			val |= CIF_MIPI_ERR_CTRL(0x0f);
> +			writel(val, base + CIF_MIPI_IMSC);
> +			dev->isp_sdev.dphy_errctrl_disabled = false;
> +		}
> +	} else {
> +		v4l2_warn(v4l2_dev, "MIPI mis error: 0x%08x\n", mis);
> +	}
> +}
> +
> +void rkisp1_isp_isr(unsigned int isp_mis, struct rkisp1_device *dev)
> +{
> +	void __iomem *base = dev->base_addr;
> +	unsigned int isp_mis_tmp = 0;
> +	unsigned int isp_err = 0;
> +
> +	/* start edge of v_sync */
> +	if (isp_mis & CIF_ISP_V_START) {
> +		riksp1_isp_queue_event_sof(&dev->isp_sdev);
> +
> +		writel(CIF_ISP_V_START, base + CIF_ISP_ICR);
> +		isp_mis_tmp = readl(base + CIF_ISP_MIS);
> +		if (isp_mis_tmp & CIF_ISP_V_START)
> +			v4l2_err(&dev->v4l2_dev, "isp icr v_statr err: 0x%x\n",
> +				 isp_mis_tmp);
> +	}
> +
> +	if ((isp_mis & CIF_ISP_PIC_SIZE_ERROR)) {
> +		/* Clear pic_size_error */
> +		writel(CIF_ISP_PIC_SIZE_ERROR, base + CIF_ISP_ICR);
> +		isp_err = readl(base + CIF_ISP_ERR);
> +		v4l2_err(&dev->v4l2_dev,
> +				"CIF_ISP_PIC_SIZE_ERROR (0x%08x)", isp_err);
> +		writel(isp_err, base + CIF_ISP_ERR_CLR);
> +	} else if ((isp_mis & CIF_ISP_DATA_LOSS)) {
> +		/* Clear data_loss */
> +		writel(CIF_ISP_DATA_LOSS, base + CIF_ISP_ICR);
> +		v4l2_err(&dev->v4l2_dev, "CIF_ISP_DATA_LOSS\n");
> +		writel(CIF_ISP_DATA_LOSS, base + CIF_ISP_ICR);
> +	}
> +
> +	/* sampled input frame is complete */
> +	if (isp_mis & CIF_ISP_FRAME_IN) {
> +		writel(CIF_ISP_FRAME_IN, base + CIF_ISP_ICR);
> +		isp_mis_tmp = readl(base + CIF_ISP_MIS);
> +		if (isp_mis_tmp & CIF_ISP_FRAME_IN)
> +			v4l2_err(&dev->v4l2_dev, "isp icr frame_in err: 0x%x\n",
> +				 isp_mis_tmp);
> +	}
> +
> +	/* frame was completely put out */
> +	if (isp_mis & CIF_ISP_FRAME) {
> +		u32 isp_ris = 0;
> +		/* Clear Frame In (ISP) */
> +		writel(CIF_ISP_FRAME, base + CIF_ISP_ICR);
> +		isp_mis_tmp = readl(base + CIF_ISP_MIS);
> +		if (isp_mis_tmp & CIF_ISP_FRAME)
> +			v4l2_err(&dev->v4l2_dev,
> +				 "isp icr frame end err: 0x%x\n", isp_mis_tmp);
> +
> +		isp_ris = readl(base + CIF_ISP_RIS);
> +		if (isp_ris & (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
> +				CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
> +			rkisp1_stats_isr(&dev->stats_vdev, isp_ris);
> +	}
> +
> +	/*
> +	 * Then update changed configs. Some of them involve
> +	 * lot of register writes. Do those only one per frame.
> +	 * Do the updates in the order of the processing flow.
> +	 */
> +	rkisp1_params_isr(&dev->params_vdev, isp_mis);
> +}
> diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.h b/drivers/media/platform/rockchip/isp1/rkisp1.h
> new file mode 100644
> index 000000000000..274cafbe2d4d
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/rkisp1.h
> @@ -0,0 +1,131 @@
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef _RKISP1_H
> +#define _RKISP1_H
> +
> +#include <linux/platform_device.h>
> +#include <media/v4l2-fwnode.h>
> +#include "common.h"
> +
> +struct rkisp1_stream;
> +
> +/*
> + * struct ispsd_in_fmt - ISP intput-pad format
> + *
> + * Translate mbus_code to hardware format values
> + *
> + * @bus_width: used for parallel
> + */
> +struct ispsd_in_fmt {
> +	u32 mbus_code;
> +	u8 fmt_type;
> +	u32 mipi_dt;
> +	u32 yuv_seq;
> +	enum rkisp1_fmt_raw_pat_type bayer_pat;
> +	u8 bus_width;
> +};
> +
> +struct ispsd_out_fmt {
> +	u32 mbus_code;
> +	u8 fmt_type;
> +};
> +
> +struct rkisp1_ie_config {
> +	unsigned int effect;
> +};
> +
> +enum rkisp1_isp_pad {
> +	RKISP1_ISP_PAD_SINK,
> +	RKISP1_ISP_PAD_SINK_PARAMS,
> +	RKISP1_ISP_PAD_SOURCE_PATH,
> +	RKISP1_ISP_PAD_SOURCE_STATS,
> +	RKISP1_ISP_PAD_MAX
> +};
> +
> +/*
> + * struct rkisp1_isp_subdev - ISP sub-device
> + *
> + * See Cropping regions of ISP in rkisp1.c for details
> + * @in_frm: input size, don't have to be equal to sensor size
> + * @in_fmt: intput format
> + * @in_crop: crop for sink pad
> + * @out_fmt: output format
> + * @out_crop: output size
> + *
> + * @dphy_errctrl_disabled: if dphy errctrl is disabled(avoid endless interrupt)
> + * @frm_sync_seq: frame sequence, to sync frame_id between video devices.
> + */
> +struct rkisp1_isp_subdev {
> +	struct v4l2_subdev sd;
> +	struct media_pad pads[RKISP1_ISP_PAD_MAX];
> +	struct v4l2_ctrl_handler ctrl_handler;
> +	struct v4l2_mbus_framefmt in_frm;
> +	struct ispsd_in_fmt in_fmt;
> +	struct v4l2_rect in_crop;
> +	struct ispsd_out_fmt out_fmt;
> +	struct v4l2_rect out_crop;
> +	bool dphy_errctrl_disabled;
> +	atomic_t frm_sync_seq;
> +};
> +
> +int rkisp1_register_isp_subdev(struct rkisp1_device *isp_dev,
> +			       struct v4l2_device *v4l2_dev);
> +
> +void rkisp1_unregister_isp_subdev(struct rkisp1_device *isp_dev);
> +
> +void rkisp1_mipi_isr(unsigned int mipi_mis, struct rkisp1_device *dev);
> +
> +void rkisp1_isp_isr(unsigned int isp_mis, struct rkisp1_device *dev);
> +
> +/* Avoid direct access to rkisp1_isp_subdev in capture.c */
> +static inline
> +struct ispsd_out_fmt *rkisp1_get_ispsd_out_fmt(struct rkisp1_isp_subdev *isp_sdev)
> +{
> +	return &isp_sdev->out_fmt;
> +}
> +
> +static inline
> +struct ispsd_in_fmt *rkisp1_get_ispsd_in_fmt(struct rkisp1_isp_subdev *isp_sdev)
> +{
> +	return &isp_sdev->in_fmt;
> +}
> +
> +static inline
> +struct v4l2_rect *rkisp1_get_isp_sd_win(struct rkisp1_isp_subdev *isp_sdev)
> +{
> +	return &isp_sdev->out_crop;
> +}
> +
> +#endif /* _RKISP1_H */
> 

Perhaps when you post v4 you can split up this patch in 2 or 3 smaller patches.
Certainly regs.[ch] can easily be put in a separate patch. It's hard to review
a single very large patch like this.

Regards,

	Hans
Jacob Chen Dec. 18, 2017, 12:10 p.m. UTC | #2
Hi Hans,

2017-12-14 0:07 GMT+08:00 Hans Verkuil <hverkuil@xs4all.nl>:
> On 06/12/17 12:19, Jacob Chen wrote:
>> From: Jacob Chen <jacob2.chen@rock-chips.com>
>>
>> This commit adds a ISP(Camera) v4l2 driver for rockchip rk3288/rk3399 SoC.
>>
>> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
>> Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
>> Signed-off-by: Yichong Zhong <zyc@rock-chips.com>
>> Signed-off-by: Jacob Chen <cc@rock-chips.com>
>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
>> Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
>> Signed-off-by: Tomasz Figa <tfiga@chromium.org>
>> ---
>>  drivers/media/platform/Kconfig                    |   10 +
>>  drivers/media/platform/Makefile                   |    1 +
>>  drivers/media/platform/rockchip/isp1/Makefile     |    7 +
>>  drivers/media/platform/rockchip/isp1/capture.c    | 1684 +++++++++++++++++++++
>>  drivers/media/platform/rockchip/isp1/capture.h    |  194 +++
>>  drivers/media/platform/rockchip/isp1/common.h     |  137 ++
>>  drivers/media/platform/rockchip/isp1/dev.c        |  655 ++++++++
>>  drivers/media/platform/rockchip/isp1/dev.h        |  120 ++
>>  drivers/media/platform/rockchip/isp1/isp_params.c | 1543 +++++++++++++++++++
>>  drivers/media/platform/rockchip/isp1/isp_params.h |   76 +
>>  drivers/media/platform/rockchip/isp1/isp_stats.c  |  521 +++++++
>>  drivers/media/platform/rockchip/isp1/isp_stats.h  |   85 ++
>>  drivers/media/platform/rockchip/isp1/regs.c       |  264 ++++
>>  drivers/media/platform/rockchip/isp1/regs.h       | 1582 +++++++++++++++++++
>>  drivers/media/platform/rockchip/isp1/rkisp1.c     | 1201 +++++++++++++++
>>  drivers/media/platform/rockchip/isp1/rkisp1.h     |  131 ++
>>  16 files changed, 8211 insertions(+)
>>  create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
>>  create mode 100644 drivers/media/platform/rockchip/isp1/capture.c
>>  create mode 100644 drivers/media/platform/rockchip/isp1/capture.h
>>  create mode 100644 drivers/media/platform/rockchip/isp1/common.h
>>  create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
>>  create mode 100644 drivers/media/platform/rockchip/isp1/dev.h
>>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.c
>>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_params.h
>>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.c
>>  create mode 100644 drivers/media/platform/rockchip/isp1/isp_stats.h
>>  create mode 100644 drivers/media/platform/rockchip/isp1/regs.c
>>  create mode 100644 drivers/media/platform/rockchip/isp1/regs.h
>>  create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.c
>>  create mode 100644 drivers/media/platform/rockchip/isp1/rkisp1.h
>>
>> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
>> index fd0c99859d6f..062fffc9ffb6 100644
>> --- a/drivers/media/platform/Kconfig
>> +++ b/drivers/media/platform/Kconfig
>> @@ -117,6 +117,16 @@ config VIDEO_QCOM_CAMSS
>>       select VIDEOBUF2_DMA_SG
>>       select V4L2_FWNODE
>>
>> +config VIDEO_ROCKCHIP_ISP1
>> +     tristate "Rockchip Image Signal Processing v1 Unit driver"
>> +     depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
>> +     depends on ARCH_ROCKCHIP || COMPILE_TEST
>> +     select VIDEOBUF2_DMA_CONTIG
>> +     select V4L2_FWNODE
>> +     default n
>> +     ---help---
>> +       Support for ISP1 on the rockchip SoC.
>> +
>>  config VIDEO_S3C_CAMIF
>>       tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
>>       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
>> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
>> index 003b0bb2cddf..d235908df63e 100644
>> --- a/drivers/media/platform/Makefile
>> +++ b/drivers/media/platform/Makefile
>> @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1)    += rcar_fdp1.o
>>  obj-$(CONFIG_VIDEO_RENESAS_JPU)      += rcar_jpu.o
>>  obj-$(CONFIG_VIDEO_RENESAS_VSP1)     += vsp1/
>>
>> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1)    += rockchip/isp1/
>>  obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)     += rockchip/rga/
>>
>>  obj-y        += omap/
>> diff --git a/drivers/media/platform/rockchip/isp1/Makefile b/drivers/media/platform/rockchip/isp1/Makefile
>> new file mode 100644
>> index 000000000000..8f52f959398e
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/Makefile
>> @@ -0,0 +1,7 @@
>> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) +=         video_rkisp1.o
>> +video_rkisp1-objs       +=   rkisp1.o \
>> +                             dev.o \
>> +                             regs.o \
>> +                             isp_stats.o \
>> +                             isp_params.o \
>> +                             capture.o
>> diff --git a/drivers/media/platform/rockchip/isp1/capture.c b/drivers/media/platform/rockchip/isp1/capture.c
>> new file mode 100644
>> index 000000000000..5e43b5420a45
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/capture.c
>> @@ -0,0 +1,1684 @@
>
> <snip>
>
>> +static void rkisp1_destroy_dummy_buf(struct rkisp1_stream *stream)
>> +{
>> +     struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
>> +     struct rkisp1_device *dev = stream->ispdev;
>> +
>> +     dma_free_coherent(dev->dev, dummy_buf->size,
>> +                       dummy_buf->vaddr, dummy_buf->dma_addr);
>> +}
>> +
>> +static void rkisp1_stop_streaming(struct vb2_queue *queue)
>> +{
>> +     struct rkisp1_stream *stream = queue->drv_priv;
>> +     struct rkisp1_vdev_node *node = &stream->vnode;
>> +     struct rkisp1_device *dev = stream->ispdev;
>> +     struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
>> +     struct rkisp1_buffer *buf;
>> +     unsigned long lock_flags = 0;
>> +     int ret;
>> +
>> +     rkisp1_stream_stop(stream);
>> +     /* call to the other devices */
>> +     media_pipeline_stop(&node->vdev.entity);
>> +     ret = dev->pipe.set_stream(&dev->pipe, false);
>> +     if (ret < 0)
>> +             return;
>
> Shouldn't it release buffers in this error case as well? It's generally a
> bad design if a close/release/stop-like function can return an error, after
> all, what should you do with that?
>

OK, so i'd like to make it just throw a warning since we can't stop
stoping streaming here.
It won't failed in this driver, but it might failed in sensor driver.

>> +
>> +     /* release buffers */
>> +     spin_lock_irqsave(&stream->vbq_lock, lock_flags);
>> +     if (stream->curr_buf) {
>> +             list_add_tail(&stream->curr_buf->queue, &stream->buf_queue);
>> +             stream->curr_buf = NULL;
>> +     }
>> +     if (stream->next_buf) {
>> +             list_add_tail(&stream->next_buf->queue, &stream->buf_queue);
>> +             stream->next_buf = NULL;
>> +     }
>> +     while (!list_empty(&stream->buf_queue)) {
>> +             buf = list_first_entry(&stream->buf_queue,
>> +                                    struct rkisp1_buffer, queue);
>> +             list_del(&buf->queue);
>> +             vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
>> +     }
>> +     spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
>> +
>> +     ret = dev->pipe.close(&dev->pipe);
>> +     if (ret < 0) {
>> +             v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret);
>> +             return;
>
> Same here, are you sure you can skip the rkisp1_destroy_dummy_buf call here?
>
>> +     }
>> +
>> +     rkisp1_destroy_dummy_buf(stream);
>> +}
>> +
>> +static int rkisp1_stream_start(struct rkisp1_stream *stream)
>> +{
>> +     struct v4l2_device *v4l2_dev = &stream->ispdev->v4l2_dev;
>> +     int ret;
>> +
>> +     ret = rkisp1_config_rsz(stream, false);
>> +     if (ret < 0) {
>> +             v4l2_err(v4l2_dev, "config rsz failed with error %d\n", ret);
>> +             return ret;
>> +     }
>> +
>> +     ret = rkisp1_config_dcrop(stream, false);
>> +     if (ret < 0) {
>> +             v4l2_err(v4l2_dev, "config dcrop failed with error %d\n", ret);
>> +             return ret;
>> +     }
>> +
>> +     return rkisp1_start(stream);
>> +}
>> +
>> +static int
>> +rkisp1_start_streaming(struct vb2_queue *queue, unsigned int count)
>> +{
>> +     struct rkisp1_stream *stream = queue->drv_priv;
>> +     struct rkisp1_vdev_node *node = &stream->vnode;
>> +     struct rkisp1_device *dev = stream->ispdev;
>> +     struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
>> +     int ret;
>> +
>> +     if (stream->state != RKISP1_STATE_READY) {
>> +             v4l2_err(v4l2_dev, "stream %d in bad state(%d) for streaming\n",
>> +                      stream->id, stream->state);
>> +             return -EBUSY;
>
> This feels like more of a WARN_ON to me. It should never happen, right?
>
>> +     }
>> +
>> +     ret = rkisp1_create_dummy_buf(stream);
>> +     if (ret < 0)
>> +             return ret;
>
> If start_streaming fails, then you need to return all buffers back to vb2 with
> vb2_buffer_done(..., VB2_BUF_STATE_QUEUED). Just like in stop_streaming, but with
> a different state. So please check all the error paths in this function.
>

Dummy bufs are not vb2, they are just a space allocated by dma_alloc_coherent.

>> +
>> +     /* enable clocks/power-domains */
>> +     ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true);
>> +     if (ret < 0) {
>> +             v4l2_err(v4l2_dev, "open cif pipeline failed %d\n", ret);
>> +             goto destroy_dummy_buf;
>> +     }
>> +
>> +     /* configure stream hardware to start */
>> +     ret = rkisp1_stream_start(stream);
>> +     if (ret < 0) {
>> +             v4l2_err(v4l2_dev, "start streaming failed\n");
>> +             goto close_pipe;
>> +     }
>> +
>> +     /* start sub-devices */
>> +     ret = dev->pipe.set_stream(&dev->pipe, true);
>> +     if (ret < 0)
>> +             goto stop_stream;
>> +
>> +     ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe);
>> +     if (ret < 0) {
>> +             v4l2_err(&dev->v4l2_dev, "start pipeline failed %d\n", ret);
>> +             goto pipe_stream_off;
>> +     }
>> +
>> +     return 0;
>> +
>> +pipe_stream_off:
>> +     dev->pipe.set_stream(&dev->pipe, false);
>> +stop_stream:
>> +     rkisp1_stream_stop(stream);
>> +close_pipe:
>> +     dev->pipe.close(&dev->pipe);
>> +destroy_dummy_buf:
>> +     rkisp1_destroy_dummy_buf(stream);
>> +
>> +     return ret;
>> +}
>> +
>> +static struct vb2_ops rkisp1_vb2_ops = {
>> +     .queue_setup = rkisp1_queue_setup,
>> +     .buf_queue = rkisp1_buf_queue,
>> +     .wait_prepare = vb2_ops_wait_prepare,
>> +     .wait_finish = vb2_ops_wait_finish,
>> +     .stop_streaming = rkisp1_stop_streaming,
>> +     .start_streaming = rkisp1_start_streaming,
>> +};
>> +
>> +static int rkisp_init_vb2_queue(struct vb2_queue *q,
>> +                             struct rkisp1_stream *stream,
>> +                             enum v4l2_buf_type buf_type)
>> +{
>> +     struct rkisp1_vdev_node *node;
>> +
>> +     node = queue_to_node(q);
>> +
>> +     q->type = buf_type;
>> +     q->io_modes = VB2_MMAP | VB2_DMABUF;
>> +     q->drv_priv = stream;
>> +     q->ops = &rkisp1_vb2_ops;
>> +     q->mem_ops = &vb2_dma_contig_memops;
>> +     q->buf_struct_size = sizeof(struct rkisp1_buffer);
>> +     q->min_buffers_needed = CIF_ISP_REQ_BUFS_MIN;
>> +     q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
>> +     q->lock = &node->vlock;
>> +     q->dev = stream->ispdev->dev;
>> +
>> +     return vb2_queue_init(q);
>> +}
>> +
>> +static void rkisp1_set_fmt(struct rkisp1_stream *stream,
>> +                        struct v4l2_pix_format_mplane *pixm,
>> +                        bool try)
>> +{
>> +     const struct capture_fmt *fmt;
>> +     const struct stream_config *config = stream->config;
>> +     struct rkisp1_stream *other_stream =
>> +                     &stream->ispdev->stream[!stream->id];
>> +     unsigned int imagsize = 0;
>> +     unsigned int planes;
>> +     u32 xsubs = 1, ysubs = 1;
>> +     int i;
>> +
>> +     fmt = find_fmt(stream, pixm->pixelformat);
>> +     if (!fmt)
>> +             fmt = config->fmts;
>> +
>> +     /* do checks on resolution */
>> +     pixm->width = clamp_t(u32, pixm->width, config->min_rsz_width,
>> +                           config->max_rsz_width);
>> +     pixm->height = clamp_t(u32, pixm->height, config->min_rsz_height,
>> +                           config->max_rsz_height);
>> +     pixm->num_planes = fmt->mplanes;
>> +     pixm->field = V4L2_FIELD_NONE;
>> +
>> +     /* output full range by default, take effect in isp_params */
>> +     if (!pixm->quantization)
>> +             pixm->quantization = V4L2_QUANTIZATION_FULL_RANGE;
>> +     /* can not change quantization when stream-on */
>> +     if (other_stream->state == RKISP1_STATE_STREAMING)
>> +             pixm->quantization = other_stream->out_fmt.quantization;
>> +
>> +     /* calculate size */
>> +     fcc_xysubs(fmt->fourcc, &xsubs, &ysubs);
>> +     planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes;
>> +     for (i = 0; i < planes; i++) {
>> +             struct v4l2_plane_pix_format *plane_fmt;
>> +             int width, height, bytesperline;
>> +
>> +             plane_fmt = pixm->plane_fmt + i;
>> +
>> +             if (i == 0) {
>> +                     width = pixm->width;
>> +                     height = pixm->height;
>> +             } else {
>> +                     width = pixm->width / xsubs;
>> +                     height = pixm->height / ysubs;
>> +             }
>> +
>> +             bytesperline = width * DIV_ROUND_UP(fmt->bpp[i], 8);
>> +             /* stride is only available for sp stream and y plane */
>> +             if (stream->id != RKISP1_STREAM_SP || i != 0 ||
>> +                 plane_fmt->bytesperline < bytesperline)
>> +                     plane_fmt->bytesperline = bytesperline;
>> +
>> +             plane_fmt->sizeimage = plane_fmt->bytesperline * height;
>> +
>> +             imagsize += plane_fmt->sizeimage;
>> +     }
>> +
>> +     /* convert to non-MPLANE format.
>> +      * it's important since we want to unify none-MPLANE
>> +      * and MPLANE.
>> +      */
>> +     if (fmt->mplanes == 1)
>> +             pixm->plane_fmt[0].sizeimage = imagsize;
>> +
>> +     if (!try) {
>> +             stream->out_isp_fmt = *fmt;
>> +             stream->out_fmt = *pixm;
>> +
>> +             if (stream->id == RKISP1_STREAM_SP) {
>> +                     stream->u.sp.y_stride =
>> +                             pixm->plane_fmt[0].bytesperline /
>> +                             DIV_ROUND_UP(fmt->bpp[0], 8);
>> +             } else {
>> +                     stream->u.mp.raw_enable = (fmt->fmt_type == FMT_BAYER);
>> +             }
>> +             v4l2_dbg(1, rkisp1_debug, &stream->ispdev->v4l2_dev,
>> +                      "%s: stream: %d req(%d, %d) out(%d, %d)\n", __func__,
>> +                      stream->id, pixm->width, pixm->height,
>> +                      stream->out_fmt.width, stream->out_fmt.height);
>> +
>> +             /* set quantization to isp_params */
>> +             rkisp1_configure_isp(NULL, NULL, pixm->quantization);
>> +     }
>> +}
>> +
>> +/************************* v4l2_file_operations***************************/
>> +void rkisp1_stream_init(struct rkisp1_device *dev, u32 id)
>> +{
>> +     struct rkisp1_stream *stream = &dev->stream[id];
>> +     struct v4l2_pix_format_mplane pixm;
>> +
>> +     memset(stream, 0, sizeof(*stream));
>> +     stream->id = id;
>> +     stream->ispdev = dev;
>> +
>> +     INIT_LIST_HEAD(&stream->buf_queue);
>> +     init_waitqueue_head(&stream->done);
>> +     spin_lock_init(&stream->vbq_lock);
>> +     if (stream->id == RKISP1_STREAM_SP) {
>> +             stream->ops = &rkisp1_sp_streams_ops;
>> +             stream->config = &rkisp1_sp_stream_config;
>> +     } else {
>> +             stream->ops = &rkisp1_mp_streams_ops;
>> +             stream->config = &rkisp1_mp_stream_config;
>> +     }
>> +
>> +     stream->state = RKISP1_STATE_READY;
>> +
>> +     memset(&pixm, 0, sizeof(pixm));
>> +     pixm.pixelformat = V4L2_PIX_FMT_YUYV;
>> +     pixm.width = RKISP1_DEFAULT_WIDTH;
>> +     pixm.height = RKISP1_DEFAULT_HEIGHT;
>> +     rkisp1_set_fmt(stream, &pixm, false);
>> +
>> +     stream->dcrop.left = 0;
>> +     stream->dcrop.top = 0;
>> +     stream->dcrop.width = RKISP1_DEFAULT_WIDTH;
>> +     stream->dcrop.height = RKISP1_DEFAULT_HEIGHT;
>> +}
>> +
>> +static const struct v4l2_file_operations rkisp1_fops = {
>> +     .open = v4l2_fh_open,
>> +     .release = vb2_fop_release,
>> +     .unlocked_ioctl = video_ioctl2,
>> +     .poll = vb2_fop_poll,
>> +     .mmap = vb2_fop_mmap,
>> +};
>> +
>> +/*
>> + * mp and sp v4l2_ioctl_ops
>> + */
>> +
>> +/* keep for compatibility */
>> +static int rkisp1_enum_input(struct file *file, void *priv,
>> +                          struct v4l2_input *input)
>> +{
>> +     if (input->index > 0)
>> +             return -EINVAL;
>> +
>
> Please fill in v4l2_input.
>
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_try_fmt_vid_cap_mplane(struct file *file, void *fh,
>> +                                      struct v4l2_format *f)
>> +{
>> +     struct rkisp1_stream *stream = video_drvdata(file);
>> +
>> +     rkisp1_set_fmt(stream, &f->fmt.pix_mp, true);
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
>> +                                       struct v4l2_fmtdesc *f)
>> +{
>> +     struct rkisp1_stream *stream = video_drvdata(file);
>> +     const struct capture_fmt *fmt = NULL;
>> +
>> +     if (f->index >= stream->config->fmt_size)
>> +             return -EINVAL;
>> +
>> +     fmt = &stream->config->fmts[f->index];
>> +     f->pixelformat = fmt->fourcc;
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_s_fmt_vid_cap_mplane(struct file *file,
>> +                                    void *priv, struct v4l2_format *f)
>> +{
>> +     struct rkisp1_stream *stream = video_drvdata(file);
>> +     struct video_device *vdev = &stream->vnode.vdev;
>> +     struct rkisp1_vdev_node *node = vdev_to_node(vdev);
>> +     struct rkisp1_device *dev = stream->ispdev;
>> +
>> +     if (vb2_is_busy(&node->buf_queue)) {
>> +             v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
>> +             return -EBUSY;
>> +     }
>> +
>> +     rkisp1_set_fmt(stream, &f->fmt.pix_mp, false);
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_g_fmt_vid_cap_mplane(struct file *file, void *fh,
>> +                                    struct v4l2_format *f)
>> +{
>> +     struct rkisp1_stream *stream = video_drvdata(file);
>> +
>> +     f->fmt.pix_mp = stream->out_fmt;
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_g_selection(struct file *file, void *prv,
>> +                           struct v4l2_selection *sel)
>> +{
>> +     struct rkisp1_stream *stream = video_drvdata(file);
>> +     struct rkisp1_device *dev = stream->ispdev;
>> +     struct v4l2_rect *dcrop = &stream->dcrop;
>> +     struct v4l2_rect *input_win;
>> +
>> +     input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
>> +
>> +     switch (sel->target) {
>> +     case V4L2_SEL_TGT_CROP_BOUNDS:
>> +             sel->r.width = input_win->width;
>> +             sel->r.height = input_win->height;
>> +             sel->r.left = 0;
>> +             sel->r.top = 0;
>> +             break;
>> +     case V4L2_SEL_TGT_CROP:
>> +             sel->r = *dcrop;
>> +             break;
>> +     default:
>> +             return -EINVAL;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static struct v4l2_rect *rkisp1_update_crop(struct rkisp1_stream *stream,
>> +                                         struct v4l2_rect *sel,
>> +                                         const struct v4l2_rect *in)
>> +{
>> +     /* Not crop for MP bayer raw data */
>> +     if (stream->id == RKISP1_STREAM_MP &&
>> +         stream->out_isp_fmt.fmt_type == FMT_BAYER) {
>> +             sel->left = 0;
>> +             sel->top = 0;
>> +             sel->width = in->width;
>> +             sel->height = in->height;
>> +             return sel;
>> +     }
>> +
>> +     sel->left = ALIGN(sel->left, 2);
>> +     sel->width = ALIGN(sel->width, 2);
>> +     sel->left = clamp_t(u32, sel->left, 0,
>> +                         in->width - STREAM_MIN_MP_SP_INPUT_WIDTH);
>> +     sel->top = clamp_t(u32, sel->top, 0,
>> +                        in->height - STREAM_MIN_MP_SP_INPUT_HEIGHT);
>> +     sel->width = clamp_t(u32, sel->width, STREAM_MIN_MP_SP_INPUT_WIDTH,
>> +                          in->width - sel->left);
>> +     sel->height = clamp_t(u32, sel->height, STREAM_MIN_MP_SP_INPUT_HEIGHT,
>> +                           in->height - sel->top);
>> +     return sel;
>> +}
>> +
>> +static int rkisp1_s_selection(struct file *file, void *prv,
>> +                           struct v4l2_selection *sel)
>> +{
>> +     struct rkisp1_stream *stream = video_drvdata(file);
>> +     struct rkisp1_device *dev = stream->ispdev;
>> +     struct v4l2_rect *dcrop = &stream->dcrop;
>> +     const struct v4l2_rect *input_win;
>> +
>
> You probably need a vb2_is_busy() call here. Normally you cannot change the selection
> while streaming.
>
>> +     input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
>> +
>> +     if (sel->target != V4L2_SEL_TGT_CROP)
>> +             return -EINVAL;
>> +
>> +     if (sel->flags != 0)
>> +             return -EINVAL;
>> +
>> +     if (sel->target == V4L2_SEL_TGT_CROP) {
>> +             *dcrop = *rkisp1_update_crop(stream, &sel->r, input_win);
>> +             v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +                      "stream %d crop(%d,%d)/%dx%d\n", stream->id,
>> +                      dcrop->left, dcrop->top, dcrop->width, dcrop->height);
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_querycap(struct file *file, void *priv,
>> +                        struct v4l2_capability *cap)
>> +{
>> +     struct rkisp1_stream *stream = video_drvdata(file);
>> +     struct device *dev = stream->ispdev->dev;
>> +
>> +     strlcpy(cap->driver, dev->driver->name, sizeof(cap->driver));
>> +     strlcpy(cap->card, dev->driver->name, sizeof(cap->card));
>> +     snprintf(cap->bus_info, sizeof(cap->bus_info),
>> +              "platform:%s", dev_name(dev));
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct v4l2_ioctl_ops rkisp1_v4l2_ioctl_ops = {
>> +     .vidioc_reqbufs = vb2_ioctl_reqbufs,
>> +     .vidioc_querybuf = vb2_ioctl_querybuf,
>> +     .vidioc_create_bufs = vb2_ioctl_create_bufs,
>> +     .vidioc_qbuf = vb2_ioctl_qbuf,
>> +     .vidioc_expbuf = vb2_ioctl_expbuf,
>> +     .vidioc_dqbuf = vb2_ioctl_dqbuf,
>> +     .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
>> +     .vidioc_streamon = vb2_ioctl_streamon,
>> +     .vidioc_streamoff = vb2_ioctl_streamoff,
>> +     .vidioc_enum_input = rkisp1_enum_input,
>> +     .vidioc_try_fmt_vid_cap_mplane = rkisp1_try_fmt_vid_cap_mplane,
>> +     .vidioc_enum_fmt_vid_cap_mplane = rkisp1_enum_fmt_vid_cap_mplane,
>> +     .vidioc_s_fmt_vid_cap_mplane = rkisp1_s_fmt_vid_cap_mplane,
>> +     .vidioc_g_fmt_vid_cap_mplane = rkisp1_g_fmt_vid_cap_mplane,
>> +     .vidioc_s_selection = rkisp1_s_selection,
>> +     .vidioc_g_selection = rkisp1_g_selection,
>> +     .vidioc_querycap = rkisp1_querycap,
>> +};
>> +
>> +static void rkisp1_unregister_stream_vdev(struct rkisp1_stream *stream)
>> +{
>> +     media_entity_cleanup(&stream->vnode.vdev.entity);
>> +     video_unregister_device(&stream->vnode.vdev);
>> +}
>> +
>> +void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev)
>> +{
>> +     struct rkisp1_stream *mp_stream = &dev->stream[RKISP1_STREAM_MP];
>> +     struct rkisp1_stream *sp_stream = &dev->stream[RKISP1_STREAM_SP];
>> +
>> +     rkisp1_unregister_stream_vdev(mp_stream);
>> +     rkisp1_unregister_stream_vdev(sp_stream);
>> +}
>> +
>> +static int rkisp1_register_stream_vdev(struct rkisp1_stream *stream)
>> +{
>> +     struct rkisp1_device *dev = stream->ispdev;
>> +     struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
>> +     struct video_device *vdev = &stream->vnode.vdev;
>> +     struct rkisp1_vdev_node *node;
>> +     int ret;
>> +
>> +     strlcpy(vdev->name,
>> +             stream->id == RKISP1_STREAM_SP ? SP_VDEV_NAME : MP_VDEV_NAME,
>> +             sizeof(vdev->name));
>> +     node = vdev_to_node(vdev);
>> +     mutex_init(&node->vlock);
>> +
>> +     vdev->ioctl_ops = &rkisp1_v4l2_ioctl_ops;
>> +     vdev->release = video_device_release_empty;
>> +     vdev->fops = &rkisp1_fops;
>> +     vdev->minor = -1;
>> +     vdev->v4l2_dev = v4l2_dev;
>> +     vdev->lock = &node->vlock;
>> +     vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
>> +                             V4L2_CAP_STREAMING;
>> +     video_set_drvdata(vdev, stream);
>> +     vdev->vfl_dir = VFL_DIR_RX;
>> +     node->pad.flags = MEDIA_PAD_FL_SINK;
>> +
>> +     rkisp_init_vb2_queue(&node->buf_queue, stream,
>> +                          V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
>> +     vdev->queue = &node->buf_queue;
>> +
>> +     ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
>> +     if (ret < 0) {
>> +             v4l2_err(v4l2_dev,
>> +                      "video_register_device failed with error %d\n", ret);
>> +             return ret;
>> +     }
>> +
>> +     vdev->entity.function = MEDIA_ENT_F_IO_V4L;
>> +     ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
>> +     if (ret < 0)
>> +             goto unreg;
>> +
>> +     return 0;
>> +unreg:
>> +     video_unregister_device(vdev);
>> +     return ret;
>> +}
>> +
>> +int rkisp1_register_stream_vdevs(struct rkisp1_device *dev)
>> +{
>> +     struct rkisp1_stream *stream;
>> +     int i, j, ret;
>> +
>> +     for (i = 0; i < RKISP1_MAX_STREAM; i++) {
>> +             stream = &dev->stream[i];
>> +             stream->ispdev = dev;
>> +             ret = rkisp1_register_stream_vdev(stream);
>> +             if (ret < 0)
>> +                     goto err;
>> +     }
>> +
>> +     return 0;
>> +err:
>> +     for (j = 0; j < i; j++) {
>> +             stream = &dev->stream[j];
>> +             rkisp1_unregister_stream_vdev(stream);
>> +     }
>> +
>> +     return ret;
>> +}
>> +
>> +/****************  Interrupter Handler ****************/
>> +
>> +void rkisp1_mi_isr(struct rkisp1_stream *stream)
>> +{
>> +     struct rkisp1_device *dev = stream->ispdev;
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +     u32 val;
>> +
>> +     stream->ops->clr_frame_end_int(base);
>> +     if (stream->ops->is_frame_end_int_masked(base)) {
>> +             val = mi_get_masked_int_status(base);
>> +             v4l2_err(&dev->v4l2_dev, "icr err: 0x%x\n", val);
>> +     }
>> +
>> +     if (stream->stopping) {
>> +             /* Make sure stream is actually stopped, whose state
>> +              * can be read from the shadow register, before wake_up()
>> +              * thread which would immediately free all frame buffers.
>> +              * stop_mi() takes effect at the next frame end
>> +              * that sync the configurations to shadow regs.
>> +              */
>> +             if (stream->ops->is_stream_stopped(dev->base_addr)) {
>> +                     stream->stopping = false;
>> +                     stream->state = RKISP1_STATE_READY;
>> +                     wake_up(&stream->done);
>> +             } else {
>> +                     stream->ops->stop_mi(stream);
>> +             }
>> +     } else {
>> +             mi_frame_end(stream);
>> +     }
>> +}
>> diff --git a/drivers/media/platform/rockchip/isp1/capture.h b/drivers/media/platform/rockchip/isp1/capture.h
>> new file mode 100644
>> index 000000000000..f0989103daa1
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/capture.h
>> @@ -0,0 +1,194 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef _RKISP1_PATH_VIDEO_H
>> +#define _RKISP1_PATH_VIDEO_H
>> +
>> +#include "common.h"
>> +
>> +struct rkisp1_stream;
>> +
>> +/*
>> + * @fourcc: pixel format
>> + * @mbus_code: pixel format over bus
>> + * @fmt_type: helper filed for pixel format
>> + * @bpp: bits per pixel
>> + * @bayer_pat: bayer patten type
>> + * @cplanes: number of colour planes
>> + * @mplanes: number of stored memory planes
>> + * @uv_swap: if cb cr swaped, for yuv
>> + * @write_format: defines how YCbCr self picture data is written to memory
>> + * @input_format: defines sp input format
>> + * @output_format: defines sp output format
>> + */
>> +struct capture_fmt {
>> +     u32 fourcc;
>> +     u32 mbus_code;
>> +     u8 fmt_type;
>> +     u8 cplanes;
>> +     u8 mplanes;
>> +     u8 uv_swap;
>> +     u32 write_format;
>> +     u32 output_format;
>> +     u8 bpp[VIDEO_MAX_PLANES];
>> +};
>> +
>> +enum rkisp1_sp_inp {
>> +     RKISP1_SP_INP_ISP,
>> +     RKISP1_SP_INP_DMA_SP,
>> +     RKISP1_SP_INP_MAX
>> +};
>> +
>> +struct rkisp1_stream_sp {
>> +     int y_stride;
>> +     enum rkisp1_sp_inp input_sel;
>> +};
>> +
>> +struct rkisp1_stream_mp {
>> +     bool raw_enable;
>> +};
>> +
>> +/* Different config between selfpath and mainpath */
>> +struct stream_config {
>> +     const struct capture_fmt *fmts;
>> +     int fmt_size;
>> +     /* constrains */
>> +     const int max_rsz_width;
>> +     const int max_rsz_height;
>> +     const int min_rsz_width;
>> +     const int min_rsz_height;
>> +     /* registers */
>> +     struct {
>> +             u32 ctrl;
>> +             u32 ctrl_shd;
>> +             u32 scale_hy;
>> +             u32 scale_hcr;
>> +             u32 scale_hcb;
>> +             u32 scale_vy;
>> +             u32 scale_vc;
>> +             u32 scale_lut;
>> +             u32 scale_lut_addr;
>> +             u32 scale_hy_shd;
>> +             u32 scale_hcr_shd;
>> +             u32 scale_hcb_shd;
>> +             u32 scale_vy_shd;
>> +             u32 scale_vc_shd;
>> +             u32 phase_hy;
>> +             u32 phase_hc;
>> +             u32 phase_vy;
>> +             u32 phase_vc;
>> +             u32 phase_hy_shd;
>> +             u32 phase_hc_shd;
>> +             u32 phase_vy_shd;
>> +             u32 phase_vc_shd;
>> +     } rsz;
>> +     struct {
>> +             u32 ctrl;
>> +             u32 yuvmode_mask;
>> +             u32 rawmode_mask;
>> +             u32 h_offset;
>> +             u32 v_offset;
>> +             u32 h_size;
>> +             u32 v_size;
>> +     } dual_crop;
>> +     struct {
>> +             u32 y_size_init;
>> +             u32 cb_size_init;
>> +             u32 cr_size_init;
>> +             u32 y_base_ad_init;
>> +             u32 cb_base_ad_init;
>> +             u32 cr_base_ad_init;
>> +             u32 y_offs_cnt_init;
>> +             u32 cb_offs_cnt_init;
>> +             u32 cr_offs_cnt_init;
>> +     } mi;
>> +};
>> +
>> +/* Different reg ops between selfpath and mainpath */
>> +struct streams_ops {
>> +     int (*config_mi)(struct rkisp1_stream *stream);
>> +     void (*stop_mi)(struct rkisp1_stream *stream);
>> +     void (*enable_mi)(struct rkisp1_stream *stream);
>> +     void (*disable_mi)(struct rkisp1_stream *stream);
>> +     void (*set_data_path)(void __iomem *base);
>> +     void (*clr_frame_end_int)(void __iomem *base);
>> +     bool (*is_frame_end_int_masked)(void __iomem *base);
>> +     bool (*is_stream_stopped)(void __iomem *base);
>> +};
>> +
>> +/*
>> + * struct rkisp1_stream - ISP capture video device
>> + *
>> + * @out_isp_fmt: output isp format
>> + * @out_fmt: output buffer size
>> + * @dcrop: coordinates of dual-crop
>> + *
>> + * @vbq_lock: lock to protect buf_queue
>> + * @buf_queue: queued buffer list
>> + * @dummy_buf: dummy space to store dropped data
>> + *
>> + * rkisp1 use shadowsock registers, so it need two buffer at a time
>> + * @curr_buf: the buffer used for current frame
>> + * @next_buf: the buffer used for next frame
>> + */
>> +struct rkisp1_stream {
>> +     u32 id;
>> +     struct rkisp1_device *ispdev;
>> +     struct rkisp1_vdev_node vnode;
>> +     enum rkisp1_state state;
>> +     enum rkisp1_state saved_state;
>> +     struct capture_fmt out_isp_fmt;
>> +     struct v4l2_pix_format_mplane out_fmt;
>> +     struct v4l2_rect dcrop;
>> +     struct streams_ops *ops;
>> +     struct stream_config *config;
>> +     spinlock_t vbq_lock;
>> +     struct list_head buf_queue;
>> +     struct rkisp1_dummy_buffer dummy_buf;
>> +     struct rkisp1_buffer *curr_buf;
>> +     struct rkisp1_buffer *next_buf;
>> +     bool stopping;
>> +     wait_queue_head_t done;
>> +     union {
>> +             struct rkisp1_stream_sp sp;
>> +             struct rkisp1_stream_mp mp;
>> +     } u;
>> +};
>> +
>> +void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev);
>> +int rkisp1_register_stream_vdevs(struct rkisp1_device *dev);
>> +void rkisp1_mi_isr(struct rkisp1_stream *stream);
>> +void rkisp1_stream_init(struct rkisp1_device *dev, u32 id);
>> +
>> +#endif /* _RKISP1_PATH_VIDEO_H */
>> diff --git a/drivers/media/platform/rockchip/isp1/common.h b/drivers/media/platform/rockchip/isp1/common.h
>> new file mode 100644
>> index 000000000000..1adfb9039b60
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/common.h
>> @@ -0,0 +1,137 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef _RKISP1_COMMON_H
>> +#define _RKISP1_COMMON_H
>> +
>> +#include <linux/mutex.h>
>> +#include <media/media-device.h>
>> +#include <media/media-entity.h>
>> +#include <media/v4l2-ctrls.h>
>> +#include <media/v4l2-device.h>
>> +#include <media/videobuf2-v4l2.h>
>> +
>> +#define RKISP1_DEFAULT_WIDTH         800
>> +#define RKISP1_DEFAULT_HEIGHT                600
>> +
>> +#define RKISP1_MAX_STREAM            2
>> +#define RKISP1_STREAM_SP             0
>> +#define RKISP1_STREAM_MP             1
>> +
>> +#define RKISP1_PLANE_Y                       0
>> +#define RKISP1_PLANE_CB                      1
>> +#define RKISP1_PLANE_CR                      2
>> +
>> +enum rkisp1_sd_type {
>> +     RKISP1_SD_SENSOR,
>> +     RKISP1_SD_PHY_CSI,
>> +     RKISP1_SD_VCM,
>> +     RKISP1_SD_FLASH,
>> +     RKISP1_SD_MAX,
>> +};
>> +
>> +/* One structure per video node */
>> +struct rkisp1_vdev_node {
>> +     struct vb2_queue buf_queue;
>> +     /* vfd lock */
>> +     struct mutex vlock;
>> +     struct video_device vdev;
>> +     struct media_pad pad;
>> +};
>> +
>> +enum rkisp1_fmt_pix_type {
>> +     FMT_YUV,
>> +     FMT_RGB,
>> +     FMT_BAYER,
>> +     FMT_JPEG,
>> +     FMT_MAX
>> +};
>> +
>> +enum rkisp1_fmt_raw_pat_type {
>> +     RAW_RGGB = 0,
>> +     RAW_GRBG,
>> +     RAW_GBRG,
>> +     RAW_BGGR,
>> +};
>> +
>> +enum rkisp1_state {
>> +     /* path not yet opened: */
>> +     RKISP1_STATE_DISABLED,
>> +     /* path opened and configured, ready for streaming: */
>> +     RKISP1_STATE_READY,
>> +     /* path is streaming: */
>> +     RKISP1_STATE_STREAMING
>> +};
>> +
>> +struct rkisp1_buffer {
>> +     struct vb2_v4l2_buffer vb;
>> +     struct list_head queue;
>> +     union {
>> +             u32 buff_addr[VIDEO_MAX_PLANES];
>> +             void *vaddr[VIDEO_MAX_PLANES];
>> +     };
>> +};
>> +
>> +struct rkisp1_dummy_buffer {
>> +     void *vaddr;
>> +     dma_addr_t dma_addr;
>> +     u32 size;
>> +};
>> +
>> +extern int rkisp1_debug;
>> +
>> +static inline
>> +struct rkisp1_vdev_node *vdev_to_node(struct video_device *vdev)
>> +{
>> +     return container_of(vdev, struct rkisp1_vdev_node, vdev);
>> +}
>> +
>> +static inline struct rkisp1_vdev_node *queue_to_node(struct vb2_queue *q)
>> +{
>> +     return container_of(q, struct rkisp1_vdev_node, buf_queue);
>> +}
>> +
>> +static inline struct rkisp1_buffer *to_rkisp1_buffer(struct vb2_v4l2_buffer *vb)
>> +{
>> +     return container_of(vb, struct rkisp1_buffer, vb);
>> +}
>> +
>> +static inline struct vb2_queue *to_vb2_queue(struct file *file)
>> +{
>> +     struct rkisp1_vdev_node *vnode = video_drvdata(file);
>> +
>> +     return &vnode->buf_queue;
>> +}
>> +
>> +#endif /* _RKISP1_COMMON_H */
>> diff --git a/drivers/media/platform/rockchip/isp1/dev.c b/drivers/media/platform/rockchip/isp1/dev.c
>> new file mode 100644
>> index 000000000000..025aa3a019a8
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/dev.c
>> @@ -0,0 +1,655 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_graph.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/pm_runtime.h>
>> +#include <linux/pinctrl/consumer.h>
>> +#include "common.h"
>> +#include "regs.h"
>> +
>> +struct isp_match_data {
>> +     const char * const *clks;
>> +     int size;
>> +};
>> +
>> +int rkisp1_debug;
>> +module_param_named(debug, rkisp1_debug, int, 0644);
>> +MODULE_PARM_DESC(debug, "Debug level (0-1)");
>> +
>> +/***************************** pipeline operations*******************************/
>> +
>> +static int __isp_pipeline_prepare(struct rkisp1_pipeline *p,
>> +                               struct media_entity *me)
>> +{
>> +     struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
>> +     struct v4l2_subdev *sd;
>> +     int i;
>> +
>> +     p->num_subdevs = 0;
>> +     memset(p->subdevs, 0, sizeof(p->subdevs));
>> +
>> +     while (1) {
>> +             struct media_pad *pad = NULL;
>> +
>> +             /* Find remote source pad */
>> +             for (i = 0; i < me->num_pads; i++) {
>> +                     struct media_pad *spad = &me->pads[i];
>> +
>> +                     if (!(spad->flags & MEDIA_PAD_FL_SINK))
>> +                             continue;
>> +                     pad = media_entity_remote_pad(spad);
>> +                     if (pad)
>> +                             break;
>> +             }
>> +
>> +             if (!pad)
>> +                     break;
>> +
>> +             sd = media_entity_to_v4l2_subdev(pad->entity);
>> +             if (sd != &dev->isp_sdev.sd)
>> +                     p->subdevs[p->num_subdevs++] = sd;
>> +
>> +             me = &sd->entity;
>> +             if (me->num_pads == 1)
>> +                     break;
>> +     }
>> +     return 0;
>> +}
>> +
>> +static int __subdev_set_power(struct v4l2_subdev *sd, int on)
>> +{
>> +     int ret;
>> +
>> +     if (!sd)
>> +             return -ENXIO;
>> +
>> +     ret = v4l2_subdev_call(sd, core, s_power, on);
>> +
>> +     return ret != -ENOIOCTLCMD ? ret : 0;
>> +}
>> +
>> +static int __isp_pipeline_s_power(struct rkisp1_pipeline *p, bool on)
>> +{
>> +     struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
>> +     int i, ret;
>> +
>> +     if (on) {
>> +             __subdev_set_power(&dev->isp_sdev.sd, true);
>> +
>> +             for (i = p->num_subdevs - 1; i >= 0; --i) {
>> +                     ret = __subdev_set_power(p->subdevs[i], true);
>> +                     if (ret < 0 && ret != -ENXIO)
>> +                             goto err_power_off;
>> +             }
>> +     } else {
>> +             for (i = 0; i < p->num_subdevs; ++i)
>> +                     __subdev_set_power(p->subdevs[i], false);
>> +
>> +             __subdev_set_power(&dev->isp_sdev.sd, false);
>> +     }
>> +
>> +     return 0;
>> +
>> +err_power_off:
>> +     for (++i; i < p->num_subdevs; ++i)
>> +             __subdev_set_power(p->subdevs[i], false);
>> +     __subdev_set_power(&dev->isp_sdev.sd, true);
>> +     return ret;
>> +}
>> +
>> +static int rkisp1_pipeline_open(struct rkisp1_pipeline *p,
>> +                             struct media_entity *me,
>> +                             bool prepare)
>> +{
>> +     int ret;
>> +
>> +     if (WARN_ON(!p || !me))
>> +             return -EINVAL;
>> +     if (atomic_inc_return(&p->power_cnt) > 1)
>> +             return 0;
>> +
>> +     /* go through media graphic and get subdevs */
>> +     if (prepare)
>> +             __isp_pipeline_prepare(p, me);
>> +
>> +     if (!p->num_subdevs)
>> +             return -EINVAL;
>> +
>> +     ret = __isp_pipeline_s_power(p, 1);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_pipeline_close(struct rkisp1_pipeline *p)
>> +{
>> +     int ret;
>> +
>> +     if (atomic_dec_return(&p->power_cnt) > 0)
>> +             return 0;
>> +     ret = __isp_pipeline_s_power(p, 0);
>> +
>> +     return ret == -ENXIO ? 0 : ret;
>> +}
>> +
>> +/*
>> + * stream-on order: isp_subdev, mipi dphy, sensor
>> + * stream-off order: mipi dphy, sensor, isp_subdev
>> + */
>> +static int rkisp1_pipeline_set_stream(struct rkisp1_pipeline *p, bool on)
>> +{
>> +     struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
>> +     int i, ret;
>> +
>> +     if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
>> +         (!on && atomic_dec_return(&p->stream_cnt) > 0))
>> +             return 0;
>> +
>> +     if (on)
>> +             v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, true);
>> +
>> +     /* phy -> sensor */
>> +     for (i = 0; i < p->num_subdevs; ++i) {
>> +             ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
>> +             if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
>> +                     goto err_stream_off;
>> +     }
>> +
>> +     if (!on)
>> +             v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
>> +
>> +     return 0;
>> +
>> +err_stream_off:
>> +     for (--i; i >= 0; --i)
>> +             v4l2_subdev_call(p->subdevs[i], video, s_stream, false);
>> +     v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
>> +     return ret;
>> +}
>> +
>> +/***************************** media controller *******************************/
>> +/* See http://opensource.rock-chips.com/wiki_Rockchip-isp1 for Topology */
>> +
>> +static int rkisp1_create_links(struct rkisp1_device *dev)
>> +{
>> +     struct media_entity *source, *sink;
>> +     unsigned int flags, s, pad;
>> +     int ret;
>> +
>> +     /* sensor links(or mipi-phy) */
>> +     for (s = 0; s < dev->num_sensors; ++s) {
>> +             struct rkisp1_sensor_info *sensor = &dev->sensors[s];
>> +
>> +             for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
>> +                     if (sensor->sd->entity.pads[pad].flags &
>> +                             MEDIA_PAD_FL_SOURCE)
>> +                             break;
>> +
>> +             if (pad == sensor->sd->entity.num_pads) {
>> +                     dev_err(dev->dev,
>> +                             "failed to find src pad for %s\n",
>> +                             sensor->sd->name);
>> +
>> +                     return -ENXIO;
>> +             }
>> +
>> +             ret = media_create_pad_link(
>> +                             &sensor->sd->entity, pad,
>> +                             &dev->isp_sdev.sd.entity,
>> +                             RKISP1_ISP_PAD_SINK + s,
>> +                             s ? 0 : MEDIA_LNK_FL_ENABLED);
>> +             if (ret) {
>> +                     dev_err(dev->dev,
>> +                             "failed to create link for %s\n",
>> +                             sensor->sd->name);
>> +                     return ret;
>> +             }
>> +     }
>> +
>> +     /* params links */
>> +     source = &dev->params_vdev.vnode.vdev.entity;
>> +     sink = &dev->isp_sdev.sd.entity;
>> +     flags = MEDIA_LNK_FL_ENABLED;
>> +     ret = media_create_pad_link(source, 0, sink,
>> +                                    RKISP1_ISP_PAD_SINK_PARAMS, flags);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     /* create isp internal links */
>> +     /* SP links */
>> +     source = &dev->isp_sdev.sd.entity;
>> +     sink = &dev->stream[RKISP1_STREAM_SP].vnode.vdev.entity;
>> +     ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
>> +                                    sink, 0, flags);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     /* MP links */
>> +     source = &dev->isp_sdev.sd.entity;
>> +     sink = &dev->stream[RKISP1_STREAM_MP].vnode.vdev.entity;
>> +     ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
>> +                                    sink, 0, flags);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     /* 3A stats links */
>> +     source = &dev->isp_sdev.sd.entity;
>> +     sink = &dev->stats_vdev.vnode.vdev.entity;
>> +     return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS,
>> +                                     sink, 0, flags);
>> +}
>> +
>> +static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
>> +{
>> +     struct rkisp1_device *dev;
>> +     int ret;
>> +
>> +     dev = container_of(notifier, struct rkisp1_device, notifier);
>> +
>> +     mutex_lock(&dev->media_dev.graph_mutex);
>> +     ret = rkisp1_create_links(dev);
>> +     if (ret < 0)
>> +             goto unlock;
>> +     ret = v4l2_device_register_subdev_nodes(&dev->v4l2_dev);
>> +     if (ret < 0)
>> +             goto unlock;
>> +
>> +     v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n");
>> +
>> +unlock:
>> +     mutex_unlock(&dev->media_dev.graph_mutex);
>> +     return ret;
>> +}
>> +
>> +struct rkisp1_async_subdev {
>> +     struct v4l2_async_subdev asd;
>> +     struct v4l2_mbus_config mbus;
>> +};
>> +
>> +static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
>> +                              struct v4l2_subdev *subdev,
>> +                              struct v4l2_async_subdev *asd)
>> +{
>> +     struct rkisp1_device *isp_dev = container_of(notifier,
>> +                                     struct rkisp1_device, notifier);
>> +     struct rkisp1_async_subdev *s_asd = container_of(asd,
>> +                                     struct rkisp1_async_subdev, asd);
>> +
>> +     if (isp_dev->num_sensors == ARRAY_SIZE(isp_dev->sensors))
>> +             return -EBUSY;
>> +
>> +     isp_dev->sensors[isp_dev->num_sensors].mbus = s_asd->mbus;
>> +     isp_dev->sensors[isp_dev->num_sensors].sd = subdev;
>> +     ++isp_dev->num_sensors;
>> +
>> +     v4l2_dbg(1, rkisp1_debug, subdev, "Async registered subdev\n");
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_fwnode_parse(struct device *dev,
>> +                            struct v4l2_fwnode_endpoint *vep,
>> +                            struct v4l2_async_subdev *asd)
>> +{
>> +     struct rkisp1_async_subdev *rk_asd =
>> +                     container_of(asd, struct rkisp1_async_subdev, asd);
>> +     struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel;
>> +
>> +     /*
>> +      * MIPI sensor is linked with a mipi dphy and its media bus config can
>> +      * not be get in here
>> +      */
>> +     if (vep->bus_type != V4L2_MBUS_BT656 &&
>> +             vep->bus_type != V4L2_MBUS_PARALLEL)
>> +             return 0;
>> +
>> +     rk_asd->mbus.flags = bus->flags;
>> +     rk_asd->mbus.type = vep->bus_type;
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
>> +     .bound = subdev_notifier_bound,
>> +     .complete = subdev_notifier_complete,
>> +};
>> +
>> +static int isp_subdev_notifier(struct rkisp1_device *isp_dev)
>> +{
>> +     struct v4l2_async_notifier *ntf = &isp_dev->notifier;
>> +     struct device *dev = isp_dev->dev;
>> +     int ret;
>> +
>> +     ret = v4l2_async_notifier_parse_fwnode_endpoints(
>> +             dev, ntf, sizeof(struct rkisp1_async_subdev),
>> +             rkisp1_fwnode_parse);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     if (!ntf->num_subdevs)
>> +             return -ENODEV; /* no endpoint */
>> +
>> +     ntf->ops = &subdev_notifier_ops;
>> +
>> +     return v4l2_async_notifier_register(&isp_dev->v4l2_dev, ntf);
>> +}
>> +
>> +/***************************** platform deive *******************************/
>> +
>> +static int rkisp1_register_platform_subdevs(struct rkisp1_device *dev)
>> +{
>> +     int ret;
>> +
>> +     ret = rkisp1_register_isp_subdev(dev, &dev->v4l2_dev);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     ret = rkisp1_register_stream_vdevs(dev);
>> +     if (ret < 0)
>> +             goto err_unreg_isp_subdev;
>> +
>> +     ret = rkisp1_register_stats_vdev(&dev->stats_vdev, &dev->v4l2_dev, dev);
>> +     if (ret < 0)
>> +             goto err_unreg_stream_vdev;
>> +
>> +     ret = rkisp1_register_params_vdev(&dev->params_vdev, &dev->v4l2_dev,
>> +                                       dev);
>> +     if (ret < 0)
>> +             goto err_unreg_stats_vdev;
>> +
>> +     ret = isp_subdev_notifier(dev);
>> +     if (ret < 0) {
>> +             v4l2_err(&dev->v4l2_dev,
>> +                      "Failed to register subdev notifier(%d)\n", ret);
>> +             goto err_unreg_params_vdev;
>> +     }
>> +
>> +     return 0;
>> +err_unreg_params_vdev:
>> +     rkisp1_unregister_params_vdev(&dev->params_vdev);
>> +err_unreg_stats_vdev:
>> +     rkisp1_unregister_stats_vdev(&dev->stats_vdev);
>> +err_unreg_stream_vdev:
>> +     rkisp1_unregister_stream_vdevs(dev);
>> +err_unreg_isp_subdev:
>> +     rkisp1_unregister_isp_subdev(dev);
>> +     return ret;
>> +}
>> +
>> +static const char * const rk3399_isp_clks[] = {
>> +     "clk_isp",
>> +     "aclk_isp",
>> +     "hclk_isp",
>> +     "aclk_isp_wrap",
>> +     "hclk_isp_wrap",
>> +};
>> +
>> +static const char * const rk3288_isp_clks[] = {
>> +     "clk_isp",
>> +     "aclk_isp",
>> +     "hclk_isp",
>> +     "pclk_isp_in",
>> +     "sclk_isp_jpe",
>> +};
>> +
>> +static const struct isp_match_data rk3288_isp_clk_data = {
>> +     .clks = rk3288_isp_clks,
>> +     .size = ARRAY_SIZE(rk3288_isp_clks),
>> +};
>> +
>> +static const struct isp_match_data rk3399_isp_clk_data = {
>> +     .clks = rk3399_isp_clks,
>> +     .size = ARRAY_SIZE(rk3399_isp_clks),
>> +};
>> +
>> +static const struct of_device_id rkisp1_plat_of_match[] = {
>> +     {
>> +             .compatible = "rockchip,rk3288-cif-isp",
>> +             .data = &rk3288_isp_clk_data,
>> +     }, {
>> +             .compatible = "rockchip,rk3399-cif-isp",
>> +             .data = &rk3399_isp_clk_data,
>> +     },
>> +     {},
>> +};
>> +
>> +static irqreturn_t rkisp1_irq_handler(int irq, void *cntxt)
>> +{
>> +     struct device *dev = cntxt;
>> +     struct rkisp1_device *rkisp1_dev = dev_get_drvdata(dev);
>> +     void __iomem *base = rkisp1_dev->base_addr;
>> +     unsigned int mis_val, i;
>> +
>> +     mis_val = readl(rkisp1_dev->base_addr + CIF_ISP_MIS);
>> +     if (mis_val)
>> +             rkisp1_isp_isr(mis_val, rkisp1_dev);
>> +
>> +     mis_val = readl(rkisp1_dev->base_addr + CIF_MIPI_MIS);
>> +     if (mis_val)
>> +             rkisp1_mipi_isr(mis_val, rkisp1_dev);
>> +
>> +     for (i = 0; i < RKISP1_MAX_STREAM; ++i) {
>> +             struct rkisp1_stream *stream = &rkisp1_dev->stream[i];
>> +
>> +             if (stream->ops->is_frame_end_int_masked(base))
>> +                     rkisp1_mi_isr(stream);
>> +     }
>> +
>> +     clr_all_int(base);
>> +
>> +     return IRQ_HANDLED;
>> +}
>> +
>> +static void rkisp1_disable_sys_clk(struct rkisp1_device *rkisp1_dev)
>> +{
>> +     int i;
>> +
>> +     for (i = rkisp1_dev->clk_size - 1; i >= 0; i--)
>> +             clk_disable_unprepare(rkisp1_dev->clks[i]);
>> +}
>> +
>> +static int rkisp1_enable_sys_clk(struct rkisp1_device *rkisp1_dev)
>> +{
>> +     int i, ret = -EINVAL;
>> +
>> +     for (i = 0; i < rkisp1_dev->clk_size; i++) {
>> +             ret = clk_prepare_enable(rkisp1_dev->clks[i]);
>> +             if (ret < 0)
>> +                     goto err;
>> +     }
>> +     return 0;
>> +err:
>> +     for (--i; i >= 0; --i)
>> +             clk_disable_unprepare(rkisp1_dev->clks[i]);
>> +     return ret;
>> +}
>> +
>> +static int rkisp1_plat_probe(struct platform_device *pdev)
>> +{
>> +     const struct of_device_id *match;
>> +     struct device_node *node = pdev->dev.of_node;
>> +     struct device *dev = &pdev->dev;
>> +     struct v4l2_device *v4l2_dev;
>> +     struct rkisp1_device *isp_dev;
>> +     const struct isp_match_data *clk_data;
>> +
>> +     struct resource *res;
>> +     int i, ret, irq;
>> +
>> +     match = of_match_node(rkisp1_plat_of_match, node);
>> +     isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
>> +     if (!isp_dev)
>> +             return -ENOMEM;
>> +
>> +     dev_set_drvdata(dev, isp_dev);
>> +     isp_dev->dev = dev;
>> +
>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     isp_dev->base_addr = devm_ioremap_resource(dev, res);
>> +     if (IS_ERR(isp_dev->base_addr))
>> +             return PTR_ERR(isp_dev->base_addr);
>> +
>> +     irq = platform_get_irq(pdev, 0);
>> +     if (irq < 0)
>> +             return irq;
>> +
>> +     ret = devm_request_irq(dev, irq, rkisp1_irq_handler, IRQF_SHARED,
>> +                            dev_driver_string(dev), dev);
>> +     if (ret < 0) {
>> +             dev_err(dev, "request irq failed: %d\n", ret);
>> +             return ret;
>> +     }
>> +
>> +     isp_dev->irq = irq;
>> +     clk_data = match->data;
>> +     for (i = 0; i < clk_data->size; i++) {
>> +             struct clk *clk = devm_clk_get(dev, clk_data->clks[i]);
>> +
>> +             if (IS_ERR(clk)) {
>> +                     dev_err(dev, "failed to get %s\n", clk_data->clks[i]);
>> +                     return PTR_ERR(clk);
>> +             }
>> +             isp_dev->clks[i] = clk;
>> +     }
>> +     isp_dev->clk_size = clk_data->size;
>> +
>> +     atomic_set(&isp_dev->pipe.power_cnt, 0);
>> +     atomic_set(&isp_dev->pipe.stream_cnt, 0);
>> +     isp_dev->pipe.open = rkisp1_pipeline_open;
>> +     isp_dev->pipe.close = rkisp1_pipeline_close;
>> +     isp_dev->pipe.set_stream = rkisp1_pipeline_set_stream;
>> +
>> +     rkisp1_stream_init(isp_dev, RKISP1_STREAM_SP);
>> +     rkisp1_stream_init(isp_dev, RKISP1_STREAM_MP);
>> +
>> +     strlcpy(isp_dev->media_dev.model, "rkisp1",
>> +             sizeof(isp_dev->media_dev.model));
>> +     isp_dev->media_dev.dev = &pdev->dev;
>> +     media_device_init(&isp_dev->media_dev);
>> +
>> +     v4l2_dev = &isp_dev->v4l2_dev;
>> +     v4l2_dev->mdev = &isp_dev->media_dev;
>> +     strlcpy(v4l2_dev->name, "rkisp1", sizeof(v4l2_dev->name));
>> +     v4l2_ctrl_handler_init(&isp_dev->ctrl_handler, 5);
>> +     v4l2_dev->ctrl_handler = &isp_dev->ctrl_handler;
>> +
>> +     ret = v4l2_device_register(isp_dev->dev, &isp_dev->v4l2_dev);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     ret = media_device_register(&isp_dev->media_dev);
>> +     if (ret < 0) {
>> +             v4l2_err(v4l2_dev, "Failed to register media device: %d\n",
>> +                      ret);
>> +             goto err_unreg_v4l2_dev;
>> +     }
>> +
>> +     /* create & register platefom subdev (from of_node) */
>> +     ret = rkisp1_register_platform_subdevs(isp_dev);
>> +     if (ret < 0)
>> +             goto err_unreg_media_dev;
>> +
>> +     pm_runtime_enable(&pdev->dev);
>> +
>> +     return 0;
>> +
>> +err_unreg_media_dev:
>> +     media_device_unregister(&isp_dev->media_dev);
>> +err_unreg_v4l2_dev:
>> +     v4l2_device_unregister(&isp_dev->v4l2_dev);
>> +     return ret;
>> +}
>> +
>> +static int rkisp1_plat_remove(struct platform_device *pdev)
>> +{
>> +     struct rkisp1_device *isp_dev = platform_get_drvdata(pdev);
>> +
>> +     pm_runtime_disable(&pdev->dev);
>> +     media_device_unregister(&isp_dev->media_dev);
>> +     v4l2_device_unregister(&isp_dev->v4l2_dev);
>> +     rkisp1_unregister_params_vdev(&isp_dev->params_vdev);
>> +     rkisp1_unregister_stats_vdev(&isp_dev->stats_vdev);
>> +     rkisp1_unregister_stream_vdevs(isp_dev);
>> +     rkisp1_unregister_isp_subdev(isp_dev);
>> +
>> +     return 0;
>> +}
>> +
>> +static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
>> +{
>> +     struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
>> +
>> +     rkisp1_disable_sys_clk(isp_dev);
>> +     return pinctrl_pm_select_sleep_state(dev);
>> +}
>> +
>> +static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
>> +{
>> +     struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
>> +     int ret;
>> +
>> +     ret = pinctrl_pm_select_default_state(dev);
>> +     if (ret < 0)
>> +             return ret;
>> +     rkisp1_enable_sys_clk(isp_dev);
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct dev_pm_ops rkisp1_plat_pm_ops = {
>> +     SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
>> +                             pm_runtime_force_resume)
>> +     SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL)
>> +};
>> +
>> +static struct platform_driver rkisp1_plat_drv = {
>> +     .driver = {
>> +                .name = DRIVER_NAME,
>> +                .of_match_table = of_match_ptr(rkisp1_plat_of_match),
>> +                .pm = &rkisp1_plat_pm_ops,
>> +     },
>> +     .probe = rkisp1_plat_probe,
>> +     .remove = rkisp1_plat_remove,
>> +};
>> +
>> +module_platform_driver(rkisp1_plat_drv);
>> +MODULE_AUTHOR("Rockchip Camera/ISP team");
>> +MODULE_DESCRIPTION("Rockchip ISP1 platform driver");
>> +MODULE_LICENSE("Dual BSD/GPL");
>> diff --git a/drivers/media/platform/rockchip/isp1/dev.h b/drivers/media/platform/rockchip/isp1/dev.h
>> new file mode 100644
>> index 000000000000..f28cde364b8d
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/dev.h
>> @@ -0,0 +1,120 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef _RKISP1_DEV_H
>> +#define _RKISP1_DEV_H
>> +
>> +#include "capture.h"
>> +#include "rkisp1.h"
>> +#include "isp_params.h"
>> +#include "isp_stats.h"
>> +
>> +#define DRIVER_NAME "rkisp1"
>> +#define ISP_VDEV_NAME DRIVER_NAME  "_ispdev"
>> +#define SP_VDEV_NAME DRIVER_NAME   "_selfpath"
>> +#define MP_VDEV_NAME DRIVER_NAME   "_mainpath"
>> +#define DMA_VDEV_NAME DRIVER_NAME  "_dmapath"
>> +
>> +#define GRP_ID_SENSOR                        BIT(0)
>> +#define GRP_ID_MIPIPHY                       BIT(1)
>> +#define GRP_ID_ISP                   BIT(2)
>> +#define GRP_ID_ISP_MP                        BIT(3)
>> +#define GRP_ID_ISP_SP                        BIT(4)
>> +
>> +#define RKISP1_MAX_BUS_CLK   8
>> +#define RKISP1_MAX_SENSOR    2
>> +#define RKISP1_MAX_PIPELINE  4
>> +
>> +/*
>> + * struct rkisp1_pipeline - An ISP hardware pipeline
>> + *
>> + * Capture device call other devices via pipeline
>> + *
>> + * @num_subdevs: number of linked subdevs
>> + * @power_cnt: pipeline power count
>> + * @stream_cnt: stream power count
>> + */
>> +struct rkisp1_pipeline {
>> +     struct media_pipeline pipe;
>> +     int num_subdevs;
>> +     atomic_t power_cnt;
>> +     atomic_t stream_cnt;
>> +     struct v4l2_subdev *subdevs[RKISP1_MAX_PIPELINE];
>> +     int (*open)(struct rkisp1_pipeline *p,
>> +                 struct media_entity *me, bool prepare);
>> +     int (*close)(struct rkisp1_pipeline *p);
>> +     int (*set_stream)(struct rkisp1_pipeline *p, bool on);
>> +};
>> +
>> +/*
>> + * struct rkisp1_sensor_info - Sensor infomations
>> + * @mbus: media bus configuration
>> + */
>> +struct rkisp1_sensor_info {
>> +     struct v4l2_subdev *sd;
>> +     struct v4l2_mbus_config mbus;
>> +};
>> +
>> +/*
>> + * struct rkisp1_device - ISP platform device
>> + * @base_addr: base register address
>> + * @active_sensor: sensor in-use, set when streaming on
>> + * @isp_sdev: ISP sub-device
>> + * @rkisp1_stream: capture video device
>> + * @stats_vdev: ISP statistics output device
>> + * @params_vdev: ISP input parameters device
>> + */
>> +struct rkisp1_device {
>> +     void __iomem *base_addr;
>> +     int irq;
>> +     struct device *dev;
>> +     struct clk *clks[RKISP1_MAX_BUS_CLK];
>> +     int clk_size;
>> +     struct v4l2_device v4l2_dev;
>> +     struct v4l2_ctrl_handler ctrl_handler;
>> +     struct media_device media_dev;
>> +     struct v4l2_async_notifier notifier;
>> +     struct v4l2_subdev *subdevs[RKISP1_SD_MAX];
>> +     struct rkisp1_sensor_info *active_sensor;
>> +     struct rkisp1_sensor_info sensors[RKISP1_MAX_SENSOR];
>> +     int num_sensors;
>> +     struct rkisp1_isp_subdev isp_sdev;
>> +     struct rkisp1_stream stream[RKISP1_MAX_STREAM];
>> +     struct rkisp1_isp_stats_vdev stats_vdev;
>> +     struct rkisp1_isp_params_vdev params_vdev;
>> +     struct rkisp1_pipeline pipe;
>> +     struct vb2_alloc_ctx *alloc_ctx;
>> +};
>> +
>> +#endif
>> diff --git a/drivers/media/platform/rockchip/isp1/isp_params.c b/drivers/media/platform/rockchip/isp1/isp_params.c
>> new file mode 100644
>> index 000000000000..5a145b0a704e
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/isp_params.c
>> @@ -0,0 +1,1543 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#include <media/v4l2-common.h>
>> +#include <media/v4l2-ioctl.h>
>> +#include <media/videobuf2-core.h>
>> +#include <media/videobuf2-vmalloc.h> /* for ISP params */
>> +#include "dev.h"
>> +#include "regs.h"
>> +
>> +#define RKISP1_ISP_PARAMS_REQ_BUFS_MIN       2
>> +#define RKISP1_ISP_PARAMS_REQ_BUFS_MAX       8
>> +
>> +#define BLS_START_H_MAX_IS_VALID(val)        ((val) < CIFISP_BLS_START_H_MAX)
>> +#define BLS_STOP_H_MAX_IS_VALID(val) ((val) < CIFISP_BLS_STOP_H_MAX)
>> +
>> +#define BLS_START_V_MAX_IS_VALID(val)        ((val) < CIFISP_BLS_START_V_MAX)
>> +#define BLS_STOP_V_MAX_IS_VALID(val) ((val) < CIFISP_BLS_STOP_V_MAX)
>> +
>> +#define BLS_SAMPLE_MAX_IS_VALID(val) ((val) < CIFISP_BLS_SAMPLES_MAX)
>> +
>> +#define BLS_FIX_SUB_IS_VALID(val)    \
>> +     ((val) > (s16) CIFISP_BLS_FIX_SUB_MIN && (val) < CIFISP_BLS_FIX_SUB_MAX)
>> +
>> +#define RKISP1_ISP_DPCC_LINE_THRESH(n)       (CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * (n))
>> +#define RKISP1_ISP_DPCC_LINE_MAD_FAC(n) (CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * (n))
>> +#define RKISP1_ISP_DPCC_PG_FAC(n)    (CIF_ISP_DPCC_PG_FAC_1 + 0x14 * (n))
>> +#define RKISP1_ISP_DPCC_RND_THRESH(n)        (CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * (n))
>> +#define RKISP1_ISP_DPCC_RG_FAC(n)    (CIF_ISP_DPCC_RG_FAC_1 + 0x14 * (n))
>> +#define RKISP1_ISP_CC_COEFF(n)               (CIF_ISP_CC_COEFF_0 + (n) * 4)
>> +
>> +static inline void rkisp1_iowrite32(struct rkisp1_isp_params_vdev *params_vdev,
>> +                                 u32 value, u32 addr)
>> +{
>> +     iowrite32(value, params_vdev->dev->base_addr + addr);
>> +}
>> +
>> +static inline u32 rkisp1_ioread32(struct rkisp1_isp_params_vdev *params_vdev,
>> +                               u32 addr)
>> +{
>> +     return ioread32(params_vdev->dev->base_addr + addr);
>> +}
>> +
>> +static inline void isp_param_set_bits(struct rkisp1_isp_params_vdev
>> +                                          *params_vdev,
>> +                                   u32 reg, u32 bit_mask)
>> +{
>> +     u32 val;
>> +
>> +     val = rkisp1_ioread32(params_vdev, reg);
>> +     rkisp1_iowrite32(params_vdev, val | bit_mask, reg);
>> +}
>> +
>> +static inline void isp_param_clear_bits(struct rkisp1_isp_params_vdev
>> +                                            *params_vdev,
>> +                                     u32 reg, u32 bit_mask)
>> +{
>> +     u32 val;
>> +
>> +     val = rkisp1_ioread32(params_vdev, reg);
>> +     rkisp1_iowrite32(params_vdev, val & ~bit_mask, reg);
>> +}
>> +
>> +/* ISP BP interface function */
>> +static void dpcc_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                     const struct cifisp_dpcc_config *arg)
>> +{
>> +     unsigned int i;
>> +
>> +     rkisp1_iowrite32(params_vdev, arg->mode, CIF_ISP_DPCC_MODE);
>> +     rkisp1_iowrite32(params_vdev, arg->output_mode,
>> +                      CIF_ISP_DPCC_OUTPUT_MODE);
>> +     rkisp1_iowrite32(params_vdev, arg->set_use, CIF_ISP_DPCC_SET_USE);
>> +
>> +     rkisp1_iowrite32(params_vdev, arg->methods[0].method,
>> +                      CIF_ISP_DPCC_METHODS_SET_1);
>> +     rkisp1_iowrite32(params_vdev, arg->methods[1].method,
>> +                      CIF_ISP_DPCC_METHODS_SET_2);
>> +     rkisp1_iowrite32(params_vdev, arg->methods[2].method,
>> +                      CIF_ISP_DPCC_METHODS_SET_3);
>> +     for (i = 0; i < CIFISP_DPCC_METHODS_MAX; i++) {
>> +             rkisp1_iowrite32(params_vdev, arg->methods[i].line_thresh,
>> +                              RKISP1_ISP_DPCC_LINE_THRESH(i));
>> +             rkisp1_iowrite32(params_vdev, arg->methods[i].line_mad_fac,
>> +                              RKISP1_ISP_DPCC_LINE_MAD_FAC(i));
>> +             rkisp1_iowrite32(params_vdev, arg->methods[i].pg_fac,
>> +                              RKISP1_ISP_DPCC_PG_FAC(i));
>> +             rkisp1_iowrite32(params_vdev, arg->methods[i].rnd_thresh,
>> +                              RKISP1_ISP_DPCC_RND_THRESH(i));
>> +             rkisp1_iowrite32(params_vdev, arg->methods[i].rg_fac,
>> +                              RKISP1_ISP_DPCC_RG_FAC(i));
>> +     }
>> +
>> +     rkisp1_iowrite32(params_vdev, arg->rnd_offs, CIF_ISP_DPCC_RND_OFFS);
>> +     rkisp1_iowrite32(params_vdev, arg->ro_limits, CIF_ISP_DPCC_RO_LIMITS);
>> +}
>> +
>> +/* ISP black level subtraction interface function */
>> +static void bls_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_bls_config *arg)
>> +{
>> +     u32 new_control = 0;
>> +
>> +     /* fixed subtraction values */
>> +     if (!arg->enable_auto) {
>> +             const struct cifisp_bls_fixed_val *pval = &arg->fixed_val;
>> +
>> +             switch (params_vdev->raw_type) {
>> +             case RAW_BGGR:
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->r, CIF_ISP_BLS_D_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->gr, CIF_ISP_BLS_C_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->gb, CIF_ISP_BLS_B_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->b, CIF_ISP_BLS_A_FIXED);
>> +                     break;
>> +             case RAW_GBRG:
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->r, CIF_ISP_BLS_C_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->gr, CIF_ISP_BLS_D_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->gb, CIF_ISP_BLS_A_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->b, CIF_ISP_BLS_B_FIXED);
>> +                     break;
>> +             case RAW_GRBG:
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->r, CIF_ISP_BLS_B_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->gr, CIF_ISP_BLS_A_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->gb, CIF_ISP_BLS_D_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->b, CIF_ISP_BLS_C_FIXED);
>> +                     break;
>> +             case RAW_RGGB:
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->r, CIF_ISP_BLS_A_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->gr, CIF_ISP_BLS_B_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->gb, CIF_ISP_BLS_C_FIXED);
>> +                     rkisp1_iowrite32(params_vdev,
>> +                                      pval->b, CIF_ISP_BLS_D_FIXED);
>> +                     break;
>> +             default:
>> +                     break;
>> +             }
>> +
>> +             new_control = CIF_ISP_BLS_MODE_FIXED;
>> +     } else {
>> +             if (arg->en_windows & BIT(1)) {
>> +                     rkisp1_iowrite32(params_vdev, arg->bls_window2.h_offs,
>> +                                      CIF_ISP_BLS_H2_START);
>> +                     rkisp1_iowrite32(params_vdev, arg->bls_window2.h_size,
>> +                                      CIF_ISP_BLS_H2_STOP);
>> +                     rkisp1_iowrite32(params_vdev, arg->bls_window2.v_offs,
>> +                                      CIF_ISP_BLS_V2_START);
>> +                     rkisp1_iowrite32(params_vdev, arg->bls_window2.v_size,
>> +                                      CIF_ISP_BLS_V2_STOP);
>> +                     new_control |= CIF_ISP_BLS_WINDOW_2;
>> +             }
>> +
>> +             if (arg->en_windows & BIT(0)) {
>> +                     rkisp1_iowrite32(params_vdev, arg->bls_window1.h_offs,
>> +                                      CIF_ISP_BLS_H1_START);
>> +                     rkisp1_iowrite32(params_vdev, arg->bls_window1.h_size,
>> +                                      CIF_ISP_BLS_H1_STOP);
>> +                     rkisp1_iowrite32(params_vdev, arg->bls_window1.v_offs,
>> +                                      CIF_ISP_BLS_V1_START);
>> +                     rkisp1_iowrite32(params_vdev, arg->bls_window1.v_size,
>> +                                      CIF_ISP_BLS_V1_STOP);
>> +                     new_control |= CIF_ISP_BLS_WINDOW_1;
>> +             }
>> +
>> +             rkisp1_iowrite32(params_vdev, arg->bls_samples,
>> +                              CIF_ISP_BLS_SAMPLES);
>> +
>> +             new_control |= CIF_ISP_BLS_MODE_MEASURED;
>> +     }
>> +     rkisp1_iowrite32(params_vdev, new_control, CIF_ISP_BLS_CTRL);
>> +}
>> +
>> +/* ISP LS correction interface function */
>> +static void
>> +__lsc_correct_matrix_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                         const struct cifisp_lsc_config *pconfig)
>> +{
>> +     int i, j;
>> +     unsigned int isp_lsc_status, sram_addr, isp_lsc_table_sel;
>> +     unsigned int data;
>> +
>> +     isp_lsc_status = rkisp1_ioread32(params_vdev, CIF_ISP_LSC_STATUS);
>> +
>> +     /* CIF_ISP_LSC_TABLE_ADDRESS_153 = ( 17 * 18 ) >> 1 */
>> +     sram_addr = (isp_lsc_status & CIF_ISP_LSC_ACTIVE_TABLE) ?
>> +                  CIF_ISP_LSC_TABLE_ADDRESS_0 :
>> +                  CIF_ISP_LSC_TABLE_ADDRESS_153;
>> +     rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_R_TABLE_ADDR);
>> +     rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_GR_TABLE_ADDR);
>> +     rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_GB_TABLE_ADDR);
>> +     rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_B_TABLE_ADDR);
>> +
>> +     /* program data tables (table size is 9 * 17 = 153) */
>> +     for (i = 0; i < ((CIF_ISP_LSC_SECTORS_MAX + 1) *
>> +          (CIF_ISP_LSC_SECTORS_MAX + 1));
>> +          i += CIF_ISP_LSC_SECTORS_MAX + 1) {
>> +             /*
>> +              * 17 sectors with 2 values in one DWORD = 9
>> +              * DWORDs (2nd value of last DWORD unused)
>> +              */
>> +             for (j = 0; j < (CIF_ISP_LSC_SECTORS_MAX + 1); j += 2) {
>> +                     data = CIF_ISP_LSC_TABLE_DATA(
>> +                                     pconfig->r_data_tbl[i + j],
>> +                                     pconfig->r_data_tbl[i + j + 1]);
>> +                     rkisp1_iowrite32(params_vdev, data,
>> +                                      CIF_ISP_LSC_R_TABLE_DATA);
>> +
>> +                     data = CIF_ISP_LSC_TABLE_DATA(
>> +                                     pconfig->gr_data_tbl[i + j],
>> +                                     pconfig->gr_data_tbl[i + j + 1]);
>> +                     rkisp1_iowrite32(params_vdev, data,
>> +                                      CIF_ISP_LSC_GR_TABLE_DATA);
>> +
>> +                     data = CIF_ISP_LSC_TABLE_DATA(
>> +                                     pconfig->gb_data_tbl[i + j],
>> +                                     pconfig->gb_data_tbl[i + j + 1]);
>> +                     rkisp1_iowrite32(params_vdev, data,
>> +                                      CIF_ISP_LSC_GB_TABLE_DATA);
>> +
>> +                     data = CIF_ISP_LSC_TABLE_DATA(
>> +                                     pconfig->b_data_tbl[i + j],
>> +                                     pconfig->b_data_tbl[i + j + 1]);
>> +                     rkisp1_iowrite32(params_vdev, data,
>> +                                      CIF_ISP_LSC_B_TABLE_DATA);
>> +             }
>> +     }
>> +
>> +     isp_lsc_table_sel = (isp_lsc_status & CIF_ISP_LSC_ACTIVE_TABLE) ?
>> +                             CIF_ISP_LSC_TABLE_0 : CIF_ISP_LSC_TABLE_1;
>> +     rkisp1_iowrite32(params_vdev, isp_lsc_table_sel, CIF_ISP_LSC_TABLE_SEL);
>> +}
>> +
>> +static void lsc_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_lsc_config *arg)
>> +{
>> +     int i;
>> +     u32 lsc_ctrl;
>> +     unsigned int data;
>> +
>> +     /* To config must be off , store the current status firstly */
>> +     lsc_ctrl = rkisp1_ioread32(params_vdev, CIF_ISP_LSC_CTRL);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_LSC_CTRL,
>> +                          CIF_ISP_LSC_CTRL_ENA);
>> +     __lsc_correct_matrix_config(params_vdev, arg);
>> +
>> +     for (i = 0; i < 4; i++) {
>> +             /* program x size tables */
>> +             data = CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2],
>> +                                     arg->x_size_tbl[i * 2 + 1]);
>> +             rkisp1_iowrite32(params_vdev, data,
>> +                              CIF_ISP_LSC_XSIZE_01 + i * 4);
>> +
>> +             /* program x grad tables */
>> +             data = CIF_ISP_LSC_SECT_SIZE(arg->x_grad_tbl[i * 2],
>> +                                     arg->x_grad_tbl[i * 2 + 1]);
>> +             rkisp1_iowrite32(params_vdev, data,
>> +                              CIF_ISP_LSC_XGRAD_01 + i * 4);
>> +
>> +             /* program y size tables */
>> +             data = CIF_ISP_LSC_SECT_SIZE(arg->y_size_tbl[i * 2],
>> +                                     arg->y_size_tbl[i * 2 + 1]);
>> +             rkisp1_iowrite32(params_vdev, data,
>> +                              CIF_ISP_LSC_YSIZE_01 + i * 4);
>> +
>> +             /* program y grad tables */
>> +             data = CIF_ISP_LSC_SECT_SIZE(arg->y_grad_tbl[i * 2],
>> +                                     arg->y_grad_tbl[i * 2 + 1]);
>> +             rkisp1_iowrite32(params_vdev, data,
>> +                              CIF_ISP_LSC_YGRAD_01 + i * 4);
>> +     }
>> +
>> +     /* restore the bls ctrl status */
>> +     if (lsc_ctrl & CIF_ISP_LSC_CTRL_ENA) {
>> +             isp_param_set_bits(params_vdev,
>> +                                CIF_ISP_LSC_CTRL,
>> +                                CIF_ISP_LSC_CTRL_ENA);
>> +     } else {
>> +             isp_param_clear_bits(params_vdev,
>> +                                  CIF_ISP_LSC_CTRL,
>> +                                  CIF_ISP_LSC_CTRL_ENA);
>> +     }
>> +}
>> +
>> +/* ISP Filtering function */
>> +static void flt_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_flt_config *arg)
>> +{
>> +     rkisp1_iowrite32(params_vdev, arg->thresh_bl0, CIF_ISP_FILT_THRESH_BL0);
>> +     rkisp1_iowrite32(params_vdev, arg->thresh_bl1, CIF_ISP_FILT_THRESH_BL1);
>> +     rkisp1_iowrite32(params_vdev, arg->thresh_sh0, CIF_ISP_FILT_THRESH_SH0);
>> +     rkisp1_iowrite32(params_vdev, arg->thresh_sh1, CIF_ISP_FILT_THRESH_SH1);
>> +     rkisp1_iowrite32(params_vdev, arg->fac_bl0, CIF_ISP_FILT_FAC_BL0);
>> +     rkisp1_iowrite32(params_vdev, arg->fac_bl1, CIF_ISP_FILT_FAC_BL1);
>> +     rkisp1_iowrite32(params_vdev, arg->fac_mid, CIF_ISP_FILT_FAC_MID);
>> +     rkisp1_iowrite32(params_vdev, arg->fac_sh0, CIF_ISP_FILT_FAC_SH0);
>> +     rkisp1_iowrite32(params_vdev, arg->fac_sh1, CIF_ISP_FILT_FAC_SH1);
>> +     rkisp1_iowrite32(params_vdev, arg->lum_weight, CIF_ISP_FILT_LUM_WEIGHT);
>> +
>> +     rkisp1_iowrite32(params_vdev, (arg->mode ? CIF_ISP_FLT_MODE_DNR : 0) |
>> +                      CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) |
>> +                      CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) |
>> +                      CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1),
>> +                      CIF_ISP_FILT_MODE);
>> +}
>> +
>> +/* ISP demosaic interface function */
>> +static int bdm_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                   const struct cifisp_bdm_config *arg)
>> +{
>> +     /* set demosaic threshold */
>> +     rkisp1_iowrite32(params_vdev, arg->demosaic_th, CIF_ISP_DEMOSAIC);
>> +     return 0;
>> +}
>> +
>> +/* ISP GAMMA correction interface function */
>> +static void sdg_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_sdg_config *arg)
>> +{
>> +     int i;
>> +
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->xa_pnts.gamma_dx0, CIF_ISP_GAMMA_DX_LO);
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->xa_pnts.gamma_dx1, CIF_ISP_GAMMA_DX_HI);
>> +
>> +     for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
>> +             rkisp1_iowrite32(params_vdev, arg->curve_r.gamma_y[i],
>> +                              CIF_ISP_GAMMA_R_Y0 + i * 4);
>> +             rkisp1_iowrite32(params_vdev, arg->curve_g.gamma_y[i],
>> +                              CIF_ISP_GAMMA_G_Y0 + i * 4);
>> +             rkisp1_iowrite32(params_vdev, arg->curve_b.gamma_y[i],
>> +                              CIF_ISP_GAMMA_B_Y0 + i * 4);
>> +     }
>> +}
>> +
>> +/* ISP GAMMA correction interface function */
>> +static void goc_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_goc_config *arg)
>> +{
>> +     int i;
>> +
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
>> +                          CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
>> +     rkisp1_iowrite32(params_vdev, arg->mode, CIF_ISP_GAMMA_OUT_MODE);
>> +
>> +     for (i = 0; i < CIFISP_GAMMA_OUT_MAX_SAMPLES; i++)
>> +             rkisp1_iowrite32(params_vdev, arg->gamma_y[i],
>> +                              CIF_ISP_GAMMA_OUT_Y_0 + i * 4);
>> +}
>> +
>> +/* ISP Cross Talk */
>> +static void ctk_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_ctk_config *arg)
>> +{
>> +     rkisp1_iowrite32(params_vdev, arg->coeff0, CIF_ISP_CT_COEFF_0);
>> +     rkisp1_iowrite32(params_vdev, arg->coeff1, CIF_ISP_CT_COEFF_1);
>> +     rkisp1_iowrite32(params_vdev, arg->coeff2, CIF_ISP_CT_COEFF_2);
>> +     rkisp1_iowrite32(params_vdev, arg->coeff3, CIF_ISP_CT_COEFF_3);
>> +     rkisp1_iowrite32(params_vdev, arg->coeff4, CIF_ISP_CT_COEFF_4);
>> +     rkisp1_iowrite32(params_vdev, arg->coeff5, CIF_ISP_CT_COEFF_5);
>> +     rkisp1_iowrite32(params_vdev, arg->coeff6, CIF_ISP_CT_COEFF_6);
>> +     rkisp1_iowrite32(params_vdev, arg->coeff7, CIF_ISP_CT_COEFF_7);
>> +     rkisp1_iowrite32(params_vdev, arg->coeff8, CIF_ISP_CT_COEFF_8);
>> +     rkisp1_iowrite32(params_vdev, arg->ct_offset_r, CIF_ISP_CT_OFFSET_R);
>> +     rkisp1_iowrite32(params_vdev, arg->ct_offset_g, CIF_ISP_CT_OFFSET_G);
>> +     rkisp1_iowrite32(params_vdev, arg->ct_offset_b, CIF_ISP_CT_OFFSET_B);
>> +}
>> +
>> +static void ctk_enable(struct rkisp1_isp_params_vdev *params_vdev, bool en)
>> +{
>> +     if (en)
>> +             return;
>> +
>> +     /* Write back the default values. */
>> +     rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_0);
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_1);
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_2);
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_3);
>> +     rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_4);
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_5);
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_6);
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_7);
>> +     rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_8);
>> +
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_R);
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_G);
>> +     rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_B);
>> +}
>> +
>> +/* ISP White Balance Mode */
>> +static void awb_meas_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                         const struct cifisp_awb_meas_config *arg)
>> +{
>> +     /* based on the mode,configure the awb module */
>> +     if (arg->awb_mode == CIFISP_AWB_MODE_YCBCR) {
>> +             /* Reference Cb and Cr */
>> +             rkisp1_iowrite32(params_vdev,
>> +                              CIF_ISP_AWB_REF_CR_SET(arg->awb_ref_cr) |
>> +                              arg->awb_ref_cb, CIF_ISP_AWB_REF);
>> +             /* Yc Threshold */
>> +             rkisp1_iowrite32(params_vdev,
>> +                              CIF_ISP_AWB_MAX_Y_SET(arg->max_y) |
>> +                              CIF_ISP_AWB_MIN_Y_SET(arg->min_y) |
>> +                              CIF_ISP_AWB_MAX_CS_SET(arg->max_csum) |
>> +                              arg->min_c, CIF_ISP_AWB_THRESH);
>> +     }
>> +
>> +     /* window offset */
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->awb_wnd.v_offs, CIF_ISP_AWB_WND_V_OFFS);
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->awb_wnd.h_offs, CIF_ISP_AWB_WND_H_OFFS);
>> +     /* AWB window size */
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->awb_wnd.v_size, CIF_ISP_AWB_WND_V_SIZE);
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->awb_wnd.h_size, CIF_ISP_AWB_WND_H_SIZE);
>> +     /* Number of frames */
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->frames, CIF_ISP_AWB_FRAMES);
>> +}
>> +
>> +static void awb_meas_enable(struct rkisp1_isp_params_vdev *params_vdev,
>> +                         const struct cifisp_awb_meas_config *arg, bool en)
>> +{
>> +     u32 reg_val = rkisp1_ioread32(params_vdev, CIF_ISP_AWB_PROP);
>> +
>> +     /* switch off */
>> +     reg_val &= CIF_ISP_AWB_MODE_MASK_NONE;
>> +
>> +     if (en) {
>> +             if (arg->awb_mode == CIFISP_AWB_MODE_RGB)
>> +                     reg_val |= CIF_ISP_AWB_MODE_RGB_EN;
>> +             else
>> +                     reg_val |= CIF_ISP_AWB_MODE_YCBCR_EN;
>> +
>> +             rkisp1_iowrite32(params_vdev, reg_val, CIF_ISP_AWB_PROP);
>> +
>> +             /* Measurements require AWB block be active. */
>> +             /* TODO: need to enable here ? awb_gain_enable has done this */
>> +             isp_param_set_bits(params_vdev, CIF_ISP_CTRL,
>> +                                CIF_ISP_CTRL_ISP_AWB_ENA);
>> +     } else {
>> +             rkisp1_iowrite32(params_vdev,
>> +                              reg_val, CIF_ISP_AWB_PROP);
>> +             isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
>> +                                  CIF_ISP_CTRL_ISP_AWB_ENA);
>> +     }
>> +}
>> +
>> +static void awb_gain_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                         const struct cifisp_awb_gain_config *arg)
>> +{
>> +     rkisp1_iowrite32(params_vdev,
>> +                      CIF_ISP_AWB_GAIN_R_SET(arg->gain_green_r) |
>> +                      arg->gain_green_b, CIF_ISP_AWB_GAIN_G);
>> +
>> +     rkisp1_iowrite32(params_vdev, CIF_ISP_AWB_GAIN_R_SET(arg->gain_red) |
>> +                      arg->gain_blue, CIF_ISP_AWB_GAIN_RB);
>> +}
>> +
>> +static void aec_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_aec_config *arg)
>> +{
>> +     unsigned int block_hsize, block_vsize;
>> +
>> +     rkisp1_iowrite32(params_vdev,
>> +                      ((arg->autostop) ? CIF_ISP_EXP_CTRL_AUTOSTOP : 0) |
>> +                      ((arg->mode == CIFISP_EXP_MEASURING_MODE_1) ?
>> +                      CIF_ISP_EXP_CTRL_MEASMODE_1 : 0), CIF_ISP_EXP_CTRL);
>> +
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->meas_window.h_offs, CIF_ISP_EXP_H_OFFSET);
>> +     rkisp1_iowrite32(params_vdev,
>> +                      arg->meas_window.v_offs, CIF_ISP_EXP_V_OFFSET);
>> +
>> +     block_hsize = arg->meas_window.h_size / CIF_ISP_EXP_COLUMN_NUM - 1;
>> +     block_vsize = arg->meas_window.v_size / CIF_ISP_EXP_ROW_NUM - 1;
>> +
>> +     rkisp1_iowrite32(params_vdev, CIF_ISP_EXP_H_SIZE_SET(block_hsize),
>> +                      CIF_ISP_EXP_H_SIZE);
>> +     rkisp1_iowrite32(params_vdev, CIF_ISP_EXP_V_SIZE_SET(block_vsize),
>> +                      CIF_ISP_EXP_V_SIZE);
>> +}
>> +
>> +static void cproc_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                      const struct cifisp_cproc_config *arg)
>> +{
>> +     struct cifisp_isp_other_cfg *cur_other_cfg = &params_vdev->cur_params.others;
>> +     struct cifisp_ie_config *cur_ie_config = &cur_other_cfg->ie_config;
>> +     u32 effect = cur_ie_config->effect;
>> +     u32 quantization = params_vdev->quantization;
>> +
>> +     rkisp1_iowrite32(params_vdev, arg->contrast, CIF_C_PROC_CONTRAST);
>> +     rkisp1_iowrite32(params_vdev, arg->hue, CIF_C_PROC_HUE);
>> +     rkisp1_iowrite32(params_vdev, arg->sat, CIF_C_PROC_SATURATION);
>> +     rkisp1_iowrite32(params_vdev, arg->brightness, CIF_C_PROC_BRIGHTNESS);
>> +
>> +     if (quantization != V4L2_QUANTIZATION_FULL_RANGE ||
>> +         effect != V4L2_COLORFX_NONE) {
>> +             isp_param_clear_bits(params_vdev, CIF_C_PROC_CTRL,
>> +                                  CIF_C_PROC_YOUT_FULL |
>> +                                  CIF_C_PROC_YIN_FULL |
>> +                                  CIF_C_PROC_COUT_FULL);
>> +     } else {
>> +             isp_param_set_bits(params_vdev, CIF_C_PROC_CTRL,
>> +                                CIF_C_PROC_YOUT_FULL |
>> +                                CIF_C_PROC_YIN_FULL |
>> +                                CIF_C_PROC_COUT_FULL);
>> +     }
>> +}
>> +
>> +static void hst_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_hst_config *arg)
>> +{
>> +     unsigned int block_hsize, block_vsize;
>> +     static const u32 hist_weight_regs[] = {
>> +             CIF_ISP_HIST_WEIGHT_00TO30, CIF_ISP_HIST_WEIGHT_40TO21,
>> +             CIF_ISP_HIST_WEIGHT_31TO12, CIF_ISP_HIST_WEIGHT_22TO03,
>> +             CIF_ISP_HIST_WEIGHT_13TO43, CIF_ISP_HIST_WEIGHT_04TO34,
>> +             CIF_ISP_HIST_WEIGHT_44,
>> +     };
>> +     int i;
>> +     const u8 *weight;
>> +
>> +     rkisp1_iowrite32(params_vdev,
>> +                      CIF_ISP_HIST_PREDIV_SET(arg->histogram_predivider),
>> +                      CIF_ISP_HIST_PROP);
>> +     rkisp1_iowrite32(params_vdev,
>> +                     arg->meas_window.h_offs,
>> +                     CIF_ISP_HIST_H_OFFS);
>> +     rkisp1_iowrite32(params_vdev,
>> +                     arg->meas_window.v_offs,
>> +                     CIF_ISP_HIST_V_OFFS);
>> +
>> +     block_hsize = arg->meas_window.h_size / CIF_ISP_HIST_COLUMN_NUM - 1;
>> +     block_vsize = arg->meas_window.v_size / CIF_ISP_HIST_ROW_NUM - 1;
>> +
>> +     rkisp1_iowrite32(params_vdev, block_hsize, CIF_ISP_HIST_H_SIZE);
>> +     rkisp1_iowrite32(params_vdev, block_vsize, CIF_ISP_HIST_V_SIZE);
>> +
>> +     weight = arg->hist_weight;
>> +     for (i = 0; i < ARRAY_SIZE(hist_weight_regs); ++i, weight += 4)
>> +             rkisp1_iowrite32(params_vdev, CIF_ISP_HIST_WEIGHT_SET(
>> +                              weight[0], weight[1], weight[2], weight[3]),
>> +                              hist_weight_regs[i]);
>> +}
>> +
>> +static void hst_enable(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_hst_config *arg, bool en)
>> +{
>> +     if (en) {
>> +             u32 hist_prop = rkisp1_ioread32(params_vdev, CIF_ISP_HIST_PROP);
>> +
>> +             hist_prop &= ~CIF_ISP_HIST_PROP_MODE_MASK;
>> +             hist_prop |= arg->mode;
>> +             isp_param_set_bits(params_vdev, CIF_ISP_HIST_PROP, hist_prop);
>> +     } else {
>> +             isp_param_clear_bits(params_vdev, CIF_ISP_HIST_PROP,
>> +                             CIF_ISP_HIST_PROP_MODE_MASK);
>> +     }
>> +}
>> +
>> +static void afm_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_afc_config *arg)
>> +{
>> +     int i;
>> +     size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->afm_win),
>> +                               arg->num_afm_win);
>> +
>> +     /* Switch off to configure. Enabled during normal flow in frame isr. */
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
>> +
>> +     for (i = 0; i < num_of_win; i++) {
>> +             rkisp1_iowrite32(params_vdev,
>> +                              CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_offs) |
>> +                              CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_offs),
>> +                              CIF_ISP_AFM_LT_A + i * 8);
>> +             rkisp1_iowrite32(params_vdev,
>> +                              CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_size +
>> +                                                   arg->afm_win[i].h_offs) |
>> +                              CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_size +
>> +                                                   arg->afm_win[i].v_offs),
>> +                              CIF_ISP_AFM_RB_A + i * 8);
>> +     }
>> +     rkisp1_iowrite32(params_vdev, arg->thres, CIF_ISP_AFM_THRES);
>> +     rkisp1_iowrite32(params_vdev, arg->var_shift, CIF_ISP_AFM_VAR_SHIFT);
>> +}
>> +
>> +static void ie_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                   const struct cifisp_ie_config *arg)
>> +{
>> +     u32 eff_ctrl;
>> +
>> +     eff_ctrl = rkisp1_ioread32(params_vdev, CIF_IMG_EFF_CTRL);
>> +     eff_ctrl &= ~CIF_IMG_EFF_CTRL_MODE_MASK;
>> +
>> +     if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE)
>> +             eff_ctrl |= CIF_IMG_EFF_CTRL_YCBCR_FULL;
>> +
>> +     switch (arg->effect) {
>> +     case V4L2_COLORFX_SEPIA:
>> +             eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SEPIA;
>> +             break;
>> +     case V4L2_COLORFX_SET_CBCR:
>> +             rkisp1_iowrite32(params_vdev, arg->eff_tint, CIF_IMG_EFF_TINT);
>> +             eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SEPIA;
>> +             break;
>> +             /*
>> +              * Color selection is similar to water color(AQUA):
>> +              * grayscale + selected color w threshold
>> +              */
>> +     case V4L2_COLORFX_AQUA:
>> +             eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_COLOR_SEL;
>> +             rkisp1_iowrite32(params_vdev, arg->color_sel,
>> +                              CIF_IMG_EFF_COLOR_SEL);
>> +             break;
>> +     case V4L2_COLORFX_EMBOSS:
>> +             eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_EMBOSS;
>> +             rkisp1_iowrite32(params_vdev, arg->eff_mat_1,
>> +                              CIF_IMG_EFF_MAT_1);
>> +             rkisp1_iowrite32(params_vdev, arg->eff_mat_2,
>> +                              CIF_IMG_EFF_MAT_2);
>> +             rkisp1_iowrite32(params_vdev, arg->eff_mat_3,
>> +                              CIF_IMG_EFF_MAT_3);
>> +             break;
>> +     case V4L2_COLORFX_SKETCH:
>> +             eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SKETCH;
>> +             rkisp1_iowrite32(params_vdev, arg->eff_mat_3,
>> +                              CIF_IMG_EFF_MAT_3);
>> +             rkisp1_iowrite32(params_vdev, arg->eff_mat_4,
>> +                              CIF_IMG_EFF_MAT_4);
>> +             rkisp1_iowrite32(params_vdev, arg->eff_mat_5,
>> +                              CIF_IMG_EFF_MAT_5);
>> +             break;
>> +     case V4L2_COLORFX_BW:
>> +             eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_BLACKWHITE;
>> +             break;
>> +     case V4L2_COLORFX_NEGATIVE:
>> +             eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_NEGATIVE;
>> +             break;
>> +     default:
>> +             break;
>> +     }
>> +
>> +     rkisp1_iowrite32(params_vdev, eff_ctrl, CIF_IMG_EFF_CTRL);
>> +}
>> +
>> +static void ie_enable(struct rkisp1_isp_params_vdev *params_vdev, bool en)
>> +{
>> +     if (en) {
>> +             isp_param_set_bits(params_vdev, CIF_ICCL, CIF_ICCL_IE_CLK);
>> +             rkisp1_iowrite32(params_vdev, CIF_IMG_EFF_CTRL_ENABLE,
>> +                              CIF_IMG_EFF_CTRL);
>> +             isp_param_set_bits(params_vdev, CIF_IMG_EFF_CTRL,
>> +                                CIF_IMG_EFF_CTRL_CFG_UPD);
>> +     } else {
>> +             /* Disable measurement */
>> +             isp_param_clear_bits(params_vdev, CIF_IMG_EFF_CTRL,
>> +                                  CIF_IMG_EFF_CTRL_ENABLE);
>> +             isp_param_clear_bits(params_vdev, CIF_ICCL, CIF_ICCL_IE_CLK);
>> +     }
>> +}
>> +
>> +static void csm_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    bool full_range)
>> +{
>> +     static const u16 full_range_coeff[] = {
>> +             0x0026, 0x004b, 0x000f,
>> +             0x01ea, 0x01d6, 0x0040,
>> +             0x0040, 0x01ca, 0x01f6
>> +     };
>> +     static const u16 limited_range_coeff[] = {
>> +             0x0021, 0x0040, 0x000d,
>> +             0x01ed, 0x01db, 0x0038,
>> +             0x0038, 0x01d1, 0x01f7,
>> +     };
>> +     int i;
>> +
>> +     if (full_range) {
>> +             for (i = 0; i < ARRAY_SIZE(full_range_coeff); i++)
>> +                     rkisp1_iowrite32(params_vdev, full_range_coeff[i],
>> +                                      CIF_ISP_CC_COEFF_0 + i * 4);
>> +
>> +             isp_param_set_bits(params_vdev, CIF_ISP_CTRL,
>> +                                CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
>> +                                CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA);
>> +     } else {
>> +             for (i = 0; i < ARRAY_SIZE(limited_range_coeff); i++)
>> +                     rkisp1_iowrite32(params_vdev, limited_range_coeff[i],
>> +                                      CIF_ISP_CC_COEFF_0 + i * 4);
>> +
>> +             isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
>> +                                  CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
>> +                                  CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA);
>> +     }
>> +}
>> +
>> +/* ISP De-noise Pre-Filter(DPF) function */
>> +static void dpf_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                    const struct cifisp_dpf_config *arg)
>> +{
>> +     unsigned int isp_dpf_mode;
>> +     unsigned int spatial_coeff;
>> +     unsigned int i;
>> +
>> +     switch (arg->gain.mode) {
>> +     case CIFISP_DPF_GAIN_USAGE_NF_GAINS:
>> +             isp_dpf_mode = CIF_ISP_DPF_MODE_USE_NF_GAIN |
>> +                             CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
>> +             break;
>> +     case CIFISP_DPF_GAIN_USAGE_LSC_GAINS:
>> +             isp_dpf_mode = CIF_ISP_DPF_MODE_LSC_GAIN_COMP;
>> +             break;
>> +     case CIFISP_DPF_GAIN_USAGE_NF_LSC_GAINS:
>> +             isp_dpf_mode = CIF_ISP_DPF_MODE_USE_NF_GAIN |
>> +                             CIF_ISP_DPF_MODE_AWB_GAIN_COMP |
>> +                             CIF_ISP_DPF_MODE_LSC_GAIN_COMP;
>> +             break;
>> +     case CIFISP_DPF_GAIN_USAGE_AWB_GAINS:
>> +             isp_dpf_mode = CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
>> +             break;
>> +     case CIFISP_DPF_GAIN_USAGE_AWB_LSC_GAINS:
>> +             isp_dpf_mode = CIF_ISP_DPF_MODE_LSC_GAIN_COMP |
>> +                             CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
>> +             break;
>> +     case CIFISP_DPF_GAIN_USAGE_DISABLED:
>> +     default:
>> +             isp_dpf_mode = 0;
>> +             break;
>> +     }
>> +
>> +     if (arg->nll.scale_mode == CIFISP_NLL_SCALE_LOGARITHMIC)
>> +             isp_dpf_mode |= CIF_ISP_DPF_MODE_NLL_SEGMENTATION;
>> +     if (arg->rb_flt.fltsize == CIFISP_DPF_RB_FILTERSIZE_9x9)
>> +             isp_dpf_mode |= CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9;
>> +     if (!arg->rb_flt.r_enable)
>> +             isp_dpf_mode |= CIF_ISP_DPF_MODE_R_FLT_DIS;
>> +     if (!arg->rb_flt.b_enable)
>> +             isp_dpf_mode |= CIF_ISP_DPF_MODE_B_FLT_DIS;
>> +     if (!arg->g_flt.gb_enable)
>> +             isp_dpf_mode |= CIF_ISP_DPF_MODE_GB_FLT_DIS;
>> +     if (!arg->g_flt.gr_enable)
>> +             isp_dpf_mode |= CIF_ISP_DPF_MODE_GR_FLT_DIS;
>> +
>> +     isp_param_set_bits(params_vdev, CIF_ISP_DPF_MODE, isp_dpf_mode);
>> +     rkisp1_iowrite32(params_vdev, arg->gain.nf_b_gain,
>> +                      CIF_ISP_DPF_NF_GAIN_B);
>> +     rkisp1_iowrite32(params_vdev, arg->gain.nf_r_gain,
>> +                      CIF_ISP_DPF_NF_GAIN_R);
>> +     rkisp1_iowrite32(params_vdev, arg->gain.nf_gb_gain,
>> +                      CIF_ISP_DPF_NF_GAIN_GB);
>> +     rkisp1_iowrite32(params_vdev, arg->gain.nf_gr_gain,
>> +                      CIF_ISP_DPF_NF_GAIN_GR);
>> +
>> +     for (i = 0; i < CIFISP_DPF_MAX_NLF_COEFFS; i++) {
>> +             rkisp1_iowrite32(params_vdev, arg->nll.coeff[i],
>> +                              CIF_ISP_DPF_NULL_COEFF_0 + i * 4);
>> +     }
>> +
>> +     spatial_coeff = arg->g_flt.spatial_coeff[0] |
>> +                     (arg->g_flt.spatial_coeff[1] << 8) |
>> +                     (arg->g_flt.spatial_coeff[2] << 16) |
>> +                     (arg->g_flt.spatial_coeff[3] << 24);
>> +     rkisp1_iowrite32(params_vdev, spatial_coeff,
>> +                      CIF_ISP_DPF_S_WEIGHT_G_1_4);
>> +
>> +     spatial_coeff = arg->g_flt.spatial_coeff[4] |
>> +                     (arg->g_flt.spatial_coeff[5] << 8);
>> +     rkisp1_iowrite32(params_vdev, spatial_coeff,
>> +                      CIF_ISP_DPF_S_WEIGHT_G_5_6);
>> +
>> +     spatial_coeff = arg->rb_flt.spatial_coeff[0] |
>> +                     (arg->rb_flt.spatial_coeff[1] << 8) |
>> +                     (arg->rb_flt.spatial_coeff[2] << 16) |
>> +                     (arg->rb_flt.spatial_coeff[3] << 24);
>> +     rkisp1_iowrite32(params_vdev, spatial_coeff,
>> +                      CIF_ISP_DPF_S_WEIGHT_RB_1_4);
>> +
>> +     spatial_coeff = arg->rb_flt.spatial_coeff[4] |
>> +                     (arg->rb_flt.spatial_coeff[5] << 8);
>> +     rkisp1_iowrite32(params_vdev, spatial_coeff,
>> +                     CIF_ISP_DPF_S_WEIGHT_RB_5_6);
>> +}
>> +
>> +static void dpf_strength_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                             const struct cifisp_dpf_strength_config *arg)
>> +{
>> +     rkisp1_iowrite32(params_vdev, arg->b, CIF_ISP_DPF_STRENGTH_B);
>> +     rkisp1_iowrite32(params_vdev, arg->g, CIF_ISP_DPF_STRENGTH_G);
>> +     rkisp1_iowrite32(params_vdev, arg->r, CIF_ISP_DPF_STRENGTH_R);
>> +}
>> +
>> +static __maybe_unused
>
> Why maybe unused? Add a comment explaining this.
>
>> +void __isp_isr_other_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                         const struct rkisp1_isp_params_cfg *new_params)
>> +{
>> +     unsigned int module_en_update, module_cfg_update, module_ens;
>> +
>> +     module_en_update = new_params->module_en_update;
>> +     module_cfg_update = new_params->module_cfg_update;
>> +     module_ens = new_params->module_ens;
>> +
>> +     if ((module_en_update & CIFISP_MODULE_DPCC) ||
>> +         (module_cfg_update & CIFISP_MODULE_DPCC)) {
>> +             /*update dpc config */
>> +             if ((module_cfg_update & CIFISP_MODULE_DPCC))
>> +                     dpcc_config(params_vdev,
>> +                                     &new_params->others.dpcc_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_DPCC) {
>> +                     if (!!(module_ens & CIFISP_MODULE_DPCC))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_DPCC_MODE,
>> +                                                CIF_ISP_DPCC_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_DPCC_MODE,
>> +                                                  CIF_ISP_DPCC_ENA);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_BLS) ||
>> +         (module_cfg_update & CIFISP_MODULE_BLS)) {
>> +             /* update bls config */
>> +             if ((module_cfg_update & CIFISP_MODULE_BLS))
>> +                     bls_config(params_vdev, &new_params->others.bls_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_BLS) {
>> +                     if (!!(module_ens & CIFISP_MODULE_BLS))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_BLS_CTRL,
>> +                                                CIF_ISP_BLS_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_BLS_CTRL,
>> +                                                  CIF_ISP_BLS_ENA);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_SDG) ||
>> +         (module_cfg_update & CIFISP_MODULE_SDG)) {
>> +             /* update sdg config */
>> +             if ((module_cfg_update & CIFISP_MODULE_SDG))
>> +                     sdg_config(params_vdev, &new_params->others.sdg_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_SDG) {
>> +                     if (!!(module_ens & CIFISP_MODULE_SDG))
>> +                             isp_param_set_bits(params_vdev,
>> +                                             CIF_ISP_CTRL,
>> +                                             CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                             CIF_ISP_CTRL,
>> +                                             CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_LSC) ||
>> +         (module_cfg_update & CIFISP_MODULE_LSC)) {
>> +             /* update lsc config */
>> +             if ((module_cfg_update & CIFISP_MODULE_LSC))
>> +                     lsc_config(params_vdev, &new_params->others.lsc_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_LSC) {
>> +                     if (!!(module_ens & CIFISP_MODULE_LSC))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_LSC_CTRL,
>> +                                                CIF_ISP_LSC_CTRL_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_LSC_CTRL,
>> +                                                  CIF_ISP_LSC_CTRL_ENA);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_AWB_GAIN) ||
>> +         (module_cfg_update & CIFISP_MODULE_AWB_GAIN)) {
>> +             /* update awb gains */
>> +             if ((module_cfg_update & CIFISP_MODULE_AWB_GAIN))
>> +                     awb_gain_config(params_vdev,
>> +                                     &new_params->others.awb_gain_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_AWB_GAIN) {
>> +                     if (!!(module_ens & CIFISP_MODULE_AWB_GAIN))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_CTRL,
>> +                                                CIF_ISP_CTRL_ISP_AWB_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_CTRL,
>> +                                                  CIF_ISP_CTRL_ISP_AWB_ENA);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_BDM) ||
>> +         (module_cfg_update & CIFISP_MODULE_BDM)) {
>> +             /* update bdm config */
>> +             if ((module_cfg_update & CIFISP_MODULE_BDM))
>> +                     bdm_config(params_vdev, &new_params->others.bdm_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_BDM) {
>> +                     if (!!(module_ens & CIFISP_MODULE_BDM))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_DEMOSAIC,
>> +                                                CIF_ISP_DEMOSAIC_BYPASS);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_DEMOSAIC,
>> +                                                  CIF_ISP_DEMOSAIC_BYPASS);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_FLT) ||
>> +         (module_cfg_update & CIFISP_MODULE_FLT)) {
>> +             /* update filter config */
>> +             if ((module_cfg_update & CIFISP_MODULE_FLT))
>> +                     flt_config(params_vdev, &new_params->others.flt_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_FLT) {
>> +                     if (!!(module_ens & CIFISP_MODULE_FLT))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_FILT_MODE,
>> +                                                CIF_ISP_FLT_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_FILT_MODE,
>> +                                                  CIF_ISP_FLT_ENA);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_CTK) ||
>> +         (module_cfg_update & CIFISP_MODULE_CTK)) {
>> +             /* update ctk config */
>> +             if ((module_cfg_update & CIFISP_MODULE_CTK))
>> +                     ctk_config(params_vdev, &new_params->others.ctk_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_CTK)
>> +                     ctk_enable(params_vdev,
>> +                                !!(module_ens & CIFISP_MODULE_CTK));
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_GOC) ||
>> +         (module_cfg_update & CIFISP_MODULE_GOC)) {
>> +             /* update goc config */
>> +             if ((module_cfg_update & CIFISP_MODULE_GOC))
>> +                     goc_config(params_vdev, &new_params->others.goc_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_GOC) {
>> +                     if (!!(module_ens & CIFISP_MODULE_GOC))
>> +                             isp_param_set_bits(params_vdev,
>> +                                             CIF_ISP_CTRL,
>> +                                             CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                             CIF_ISP_CTRL,
>> +                                             CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_CPROC) ||
>> +         (module_cfg_update & CIFISP_MODULE_CPROC)) {
>> +             /* update cproc config */
>> +             if ((module_cfg_update & CIFISP_MODULE_CPROC)) {
>> +                     cproc_config(params_vdev,
>> +                                  &new_params->others.cproc_config);
>> +
>> +             }
>> +
>> +             if (module_en_update & CIFISP_MODULE_CPROC) {
>> +                     if (!!(module_ens & CIFISP_MODULE_CPROC))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_C_PROC_CTRL,
>> +                                                CIF_C_PROC_CTR_ENABLE);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                CIF_C_PROC_CTRL,
>> +                                                CIF_C_PROC_CTR_ENABLE);
>> +             }
>> +     }
>> +
>> +
>> +     if ((module_en_update & CIFISP_MODULE_IE) ||
>> +         (module_cfg_update & CIFISP_MODULE_IE)) {
>> +             /* update ie config */
>> +             if ((module_cfg_update & CIFISP_MODULE_IE))
>> +                     ie_config(params_vdev, &new_params->others.ie_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_IE)
>> +                     ie_enable(params_vdev,
>> +                                !!(module_ens & CIFISP_MODULE_IE));
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_DPF) ||
>> +         (module_cfg_update & CIFISP_MODULE_DPF)) {
>> +             /* update dpf  config */
>> +             if ((module_cfg_update & CIFISP_MODULE_DPF))
>> +                     dpf_config(params_vdev, &new_params->others.dpf_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_DPF) {
>> +                     if (!!(module_ens & CIFISP_MODULE_DPF))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_DPF_MODE,
>> +                                                CIF_ISP_DPF_MODE_EN);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_DPF_MODE,
>> +                                                  CIF_ISP_DPF_MODE_EN);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_DPF_STRENGTH) ||
>> +         (module_cfg_update & CIFISP_MODULE_DPF_STRENGTH)) {
>> +             /* update dpf strength config */
>> +             dpf_strength_config(params_vdev,
>> +                                 &new_params->others.dpf_strength_config);
>> +     }
>> +}
>> +
>> +static __maybe_unused
>> +void __isp_isr_meas_config(struct rkisp1_isp_params_vdev *params_vdev,
>> +                        struct  rkisp1_isp_params_cfg *new_params)
>> +{
>> +     unsigned int module_en_update, module_cfg_update, module_ens;
>> +
>> +     module_en_update = new_params->module_en_update;
>> +     module_cfg_update = new_params->module_cfg_update;
>> +     module_ens = new_params->module_ens;
>> +
>> +     if ((module_en_update & CIFISP_MODULE_AWB) ||
>> +         (module_cfg_update & CIFISP_MODULE_AWB)) {
>> +             /* update awb config */
>> +             if ((module_cfg_update & CIFISP_MODULE_AWB))
>> +                     awb_meas_config(params_vdev,
>> +                                     &new_params->meas.awb_meas_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_AWB)
>> +                     awb_meas_enable(params_vdev,
>> +                                     &new_params->meas.awb_meas_config,
>> +                                     !!(module_ens & CIFISP_MODULE_AWB));
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_AFC) ||
>> +         (module_cfg_update & CIFISP_MODULE_AFC)) {
>> +             /* update afc config */
>> +             if ((module_cfg_update & CIFISP_MODULE_AFC))
>> +                     afm_config(params_vdev, &new_params->meas.afc_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_AFC) {
>> +                     if (!!(module_ens & CIFISP_MODULE_AFC))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_AFM_CTRL,
>> +                                                CIF_ISP_AFM_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_AFM_CTRL,
>> +                                                  CIF_ISP_AFM_ENA);
>> +             }
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_HST) ||
>> +         (module_cfg_update & CIFISP_MODULE_HST)) {
>> +             /* update hst config */
>> +             if ((module_cfg_update & CIFISP_MODULE_HST))
>> +                     hst_config(params_vdev, &new_params->meas.hst_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_HST)
>> +                     hst_enable(params_vdev,
>> +                                &new_params->meas.hst_config,
>> +                                !!(module_ens & CIFISP_MODULE_HST));
>> +     }
>> +
>> +     if ((module_en_update & CIFISP_MODULE_AEC) ||
>> +         (module_cfg_update & CIFISP_MODULE_AEC)) {
>> +             /* update aec config */
>> +             if ((module_cfg_update & CIFISP_MODULE_AEC))
>> +                     aec_config(params_vdev, &new_params->meas.aec_config);
>> +
>> +             if (module_en_update & CIFISP_MODULE_AEC) {
>> +                     if (!!(module_ens & CIFISP_MODULE_AEC))
>> +                             isp_param_set_bits(params_vdev,
>> +                                                CIF_ISP_EXP_CTRL,
>> +                                                CIF_ISP_EXP_ENA);
>> +                     else
>> +                             isp_param_clear_bits(params_vdev,
>> +                                                  CIF_ISP_EXP_CTRL,
>> +                                                  CIF_ISP_EXP_ENA);
>> +             }
>> +     }
>> +}
>> +
>> +void rkisp1_params_isr(struct rkisp1_isp_params_vdev *params_vdev, u32 isp_mis)
>> +{
>> +     struct rkisp1_isp_params_cfg *new_params;
>> +     struct rkisp1_buffer *cur_buf = NULL;
>> +
>> +     spin_lock(&params_vdev->config_lock);
>> +     if (!params_vdev->streamon) {
>> +             spin_unlock(&params_vdev->config_lock);
>> +             return;
>> +     }
>> +
>> +     /* get one empty buffer */
>> +     if (!list_empty(&params_vdev->params))
>> +             cur_buf = list_first_entry(&params_vdev->params,
>> +                                        struct rkisp1_buffer, queue);
>> +     spin_unlock(&params_vdev->config_lock);
>> +
>> +     if (!cur_buf)
>> +             return;
>> +
>> +     new_params = (struct rkisp1_isp_params_cfg *)(cur_buf->vaddr[0]);
>> +
>> +     if (isp_mis & CIF_ISP_FRAME) {
>> +             __isp_isr_other_config(params_vdev, new_params);
>> +             __isp_isr_meas_config(params_vdev, new_params);
>> +             spin_lock(&params_vdev->config_lock);
>> +             list_del(&cur_buf->queue);
>> +             spin_unlock(&params_vdev->config_lock);
>> +             vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
>> +     }
>> +}
>> +
>> +static const struct cifisp_awb_meas_config awb_params_default_config = {
>> +     {
>> +             0, 0, RKISP1_DEFAULT_WIDTH, RKISP1_DEFAULT_HEIGHT
>> +     },
>> +     CIFISP_AWB_MODE_YCBCR, 200, 30, 20, 20, 0, 128, 128
>> +};
>> +
>> +static const struct cifisp_aec_config aec_params_default_config = {
>> +     CIFISP_EXP_MEASURING_MODE_0,
>> +     CIFISP_EXP_CTRL_AUTOSTOP_0,
>> +     {
>> +             RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2,
>> +             RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1
>> +     }
>> +};
>> +
>> +static const struct cifisp_hst_config hst_params_default_config = {
>> +     CIFISP_HISTOGRAM_MODE_RGB_COMBINED,
>> +     3,
>> +     {
>> +             RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2,
>> +             RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1
>> +     },
>> +     {
>> +             0, /* To be filled in with 0x01 at runtime. */
>> +     }
>> +};
>> +
>> +static const struct cifisp_afc_config afc_params_default_config = {
>> +     1,
>> +     {
>> +             {
>> +                     300, 225, 200, 150
>> +             }
>> +     },
>> +     4,
>> +     14
>> +};
>> +
>> +static
>> +void rkisp1_params_config_parameter(struct rkisp1_isp_params_vdev *params_vdev)
>> +{
>> +     struct cifisp_hst_config hst = hst_params_default_config;
>> +
>> +     spin_lock(&params_vdev->config_lock);
>> +
>> +     awb_meas_config(params_vdev, &awb_params_default_config);
>> +     awb_meas_enable(params_vdev, &awb_params_default_config, true);
>> +
>> +     aec_config(params_vdev, &aec_params_default_config);
>> +     isp_param_set_bits(params_vdev, CIF_ISP_EXP_CTRL, CIF_ISP_EXP_ENA);
>> +
>> +     afm_config(params_vdev, &afc_params_default_config);
>> +     isp_param_set_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
>> +
>> +     memset(hst.hist_weight, 0x01, sizeof(hst.hist_weight));
>> +     hst_config(params_vdev, &hst);
>> +     isp_param_set_bits(params_vdev, CIF_ISP_HIST_PROP,
>> +                        ~CIF_ISP_HIST_PROP_MODE_MASK |
>> +                        hst_params_default_config.mode);
>> +
>> +     /* set the  range */
>> +     if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE)
>> +             csm_config(params_vdev, true);
>> +     else
>> +             csm_config(params_vdev, false);
>> +
>> +     /* override the default things */
>> +     __isp_isr_other_config(params_vdev, &params_vdev->cur_params);
>> +     __isp_isr_meas_config(params_vdev, &params_vdev->cur_params);
>> +
>> +     spin_unlock(&params_vdev->config_lock);
>> +}
>> +
>> +/* Not called when the camera active, thus not isr protection. */
>> +void rkisp1_configure_isp(struct rkisp1_isp_params_vdev *params_vdev,
>> +                       struct ispsd_in_fmt *in_fmt,
>> +                       enum v4l2_quantization quantization)
>> +{
>> +     if (!params_vdev)
>> +             return;
>> +
>> +     if (quantization)
>> +             params_vdev->quantization = quantization;
>> +     if (in_fmt)
>> +             params_vdev->raw_type = in_fmt->bayer_pat;
>> +     if (params_vdev)
>> +             rkisp1_params_config_parameter(params_vdev);
>> +}
>> +
>> +/* Not called when the camera active, thus not isr protection. */
>> +void rkisp1_disable_isp(struct rkisp1_isp_params_vdev *params_vdev)
>> +{
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_DPCC_MODE, CIF_ISP_DPCC_ENA);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_LSC_CTRL,
>> +                          CIF_ISP_LSC_CTRL_ENA);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_BLS_CTRL, CIF_ISP_BLS_ENA);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
>> +                          CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
>> +                          CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_DEMOSAIC,
>> +                          CIF_ISP_DEMOSAIC_BYPASS);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_FILT_MODE, CIF_ISP_FLT_ENA);
>> +     awb_meas_enable(params_vdev, NULL, false);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
>> +                          CIF_ISP_CTRL_ISP_AWB_ENA);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_EXP_CTRL, CIF_ISP_EXP_ENA);
>> +     ctk_enable(params_vdev, false);
>> +     isp_param_clear_bits(params_vdev, CIF_C_PROC_CTRL,
>> +                          CIF_C_PROC_CTR_ENABLE);
>> +     hst_enable(params_vdev, NULL, false);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
>> +     ie_enable(params_vdev, false);
>> +     isp_param_clear_bits(params_vdev, CIF_ISP_DPF_MODE,
>> +                          CIF_ISP_DPF_MODE_EN);
>> +}
>> +
>> +static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv,
>> +                                        struct v4l2_fmtdesc *f)
>> +{
>> +     struct video_device *video = video_devdata(file);
>> +     struct rkisp1_isp_params_vdev *params_vdev = video_get_drvdata(video);
>> +
>> +     if (f->index > 0 || f->type != video->queue->type)
>> +             return -EINVAL;
>> +
>> +     f->pixelformat = params_vdev->vdev_fmt.fmt.meta.dataformat;
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh,
>> +                                     struct v4l2_format *f)
>> +{
>> +     struct video_device *video = video_devdata(file);
>> +     struct rkisp1_isp_params_vdev *params_vdev = video_get_drvdata(video);
>> +     struct v4l2_meta_format *meta = &f->fmt.meta;
>> +
>> +     if (f->type != video->queue->type)
>> +             return -EINVAL;
>> +
>> +     memset(meta, 0, sizeof(*meta));
>> +     meta->dataformat = params_vdev->vdev_fmt.fmt.meta.dataformat;
>> +     meta->buffersize = params_vdev->vdev_fmt.fmt.meta.buffersize;
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_params_querycap(struct file *file,
>> +                               void *priv, struct v4l2_capability *cap)
>> +{
>> +     struct video_device *vdev = video_devdata(file);
>> +
>> +     strcpy(cap->driver, DRIVER_NAME);
>> +     strlcpy(cap->card, vdev->name, sizeof(cap->card));
>> +     strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
>> +
>> +     return 0;
>> +}
>> +
>> +/* ISP params video device IOCTLs */
>> +static const struct v4l2_ioctl_ops rkisp1_params_ioctl = {
>> +     .vidioc_reqbufs = vb2_ioctl_reqbufs,
>> +     .vidioc_querybuf = vb2_ioctl_querybuf,
>> +     .vidioc_create_bufs = vb2_ioctl_create_bufs,
>> +     .vidioc_qbuf = vb2_ioctl_qbuf,
>> +     .vidioc_dqbuf = vb2_ioctl_dqbuf,
>> +     .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
>> +     .vidioc_expbuf = vb2_ioctl_expbuf,
>> +     .vidioc_streamon = vb2_ioctl_streamon,
>> +     .vidioc_streamoff = vb2_ioctl_streamoff,
>> +     .vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out,
>> +     .vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
>> +     .vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
>> +     .vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
>> +     .vidioc_querycap = rkisp1_params_querycap
>> +};
>> +
>> +static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
>> +                                      unsigned int *num_buffers,
>> +                                      unsigned int *num_planes,
>> +                                      unsigned int sizes[],
>> +                                      struct device *alloc_devs[])
>> +{
>> +     struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
>> +
>> +     *num_buffers = clamp_t(u32, *num_buffers,
>> +                            RKISP1_ISP_PARAMS_REQ_BUFS_MIN,
>> +                            RKISP1_ISP_PARAMS_REQ_BUFS_MAX);
>> +
>> +     *num_planes = 1;
>> +
>> +     sizes[0] = sizeof(struct rkisp1_isp_params_cfg);
>> +
>> +     INIT_LIST_HEAD(&params_vdev->params);
>> +     params_vdev->first_params = true;
>> +
>> +     return 0;
>> +}
>> +
>> +static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
>> +{
>> +     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +     struct rkisp1_buffer *params_buf = to_rkisp1_buffer(vbuf);
>> +     struct vb2_queue *vq = vb->vb2_queue;
>> +     struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
>> +     struct rkisp1_isp_params_cfg *new_params;
>> +     unsigned long flags;
>> +
>> +     if (params_vdev->first_params) {
>> +             new_params = (struct rkisp1_isp_params_cfg *)
>> +                     (vb2_plane_vaddr(vb, 0));
>> +             vb2_buffer_done(&params_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
>> +             params_vdev->first_params = false;
>> +             params_vdev->cur_params = *new_params;
>> +             return;
>> +     }
>> +
>> +     params_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
>> +     spin_lock_irqsave(&params_vdev->config_lock, flags);
>> +     list_add_tail(&params_buf->queue, &params_vdev->params);
>> +     spin_unlock_irqrestore(&params_vdev->config_lock, flags);
>> +}
>> +
>> +static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
>> +{
>> +     struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
>> +     struct rkisp1_buffer *buf;
>> +     unsigned long flags;
>> +     int i;
>> +
>> +     /* stop params input firstly */
>> +     spin_lock_irqsave(&params_vdev->config_lock, flags);
>> +     params_vdev->streamon = false;
>> +     spin_unlock_irqrestore(&params_vdev->config_lock, flags);
>> +
>> +     for (i = 0; i < RKISP1_ISP_PARAMS_REQ_BUFS_MAX; i++) {
>> +             spin_lock_irqsave(&params_vdev->config_lock, flags);
>> +             if (!list_empty(&params_vdev->params)) {
>> +                     buf = list_first_entry(&params_vdev->params,
>> +                                            struct rkisp1_buffer, queue);
>> +                     list_del(&buf->queue);
>> +                     spin_unlock_irqrestore(&params_vdev->config_lock,
>> +                                            flags);
>> +             } else {
>> +                     spin_unlock_irqrestore(&params_vdev->config_lock,
>> +                                            flags);
>> +                     break;
>> +             }
>> +
>> +             if (buf)
>> +                     vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
>> +             buf = NULL;
>> +     }
>> +}
>> +
>> +static int
>> +rkisp1_params_vb2_start_streaming(struct vb2_queue *queue, unsigned int count)
>> +{
>> +     struct rkisp1_isp_params_vdev *params_vdev = queue->drv_priv;
>> +     unsigned long flags;
>> +
>> +     spin_lock_irqsave(&params_vdev->config_lock, flags);
>> +     params_vdev->streamon = true;
>> +     spin_unlock_irqrestore(&params_vdev->config_lock, flags);
>> +
>> +     return 0;
>> +}
>> +
>> +static struct vb2_ops rkisp1_params_vb2_ops = {
>> +     .queue_setup = rkisp1_params_vb2_queue_setup,
>> +     .wait_prepare = vb2_ops_wait_prepare,
>> +     .wait_finish = vb2_ops_wait_finish,
>> +     .buf_queue = rkisp1_params_vb2_buf_queue,
>> +     .start_streaming = rkisp1_params_vb2_start_streaming,
>> +     .stop_streaming = rkisp1_params_vb2_stop_streaming,
>> +
>> +};
>> +
>> +struct v4l2_file_operations rkisp1_params_fops = {
>> +     .mmap = vb2_fop_mmap,
>> +     .unlocked_ioctl = video_ioctl2,
>> +     .poll = vb2_fop_poll,
>> +     .open = v4l2_fh_open,
>> +     .release = vb2_fop_release
>> +};
>> +
>> +static int
>> +rkisp1_params_init_vb2_queue(struct vb2_queue *q,
>> +                          struct rkisp1_isp_params_vdev *params_vdev)
>> +{
>> +     struct rkisp1_vdev_node *node;
>> +
>> +     node = queue_to_node(q);
>> +
>> +     q->type = V4L2_BUF_TYPE_META_OUTPUT;
>> +     q->io_modes = VB2_MMAP | VB2_USERPTR;
>
> Either add VB2_DMABUF or drop exp_buf from rkisp1_params_ioctl.
>
>> +     q->drv_priv = params_vdev;
>> +     q->ops = &rkisp1_params_vb2_ops;
>> +     q->mem_ops = &vb2_vmalloc_memops;
>> +     q->buf_struct_size = sizeof(struct rkisp1_buffer);
>> +     q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
>> +     q->lock = &node->vlock;
>> +
>> +     return vb2_queue_init(q);
>> +}
>> +
>> +static void rkisp1_init_params_vdev(struct rkisp1_isp_params_vdev *params_vdev)
>> +{
>> +     params_vdev->vdev_fmt.fmt.meta.dataformat =
>> +             V4L2_META_FMT_RK_ISP1_PARAMS;
>> +     params_vdev->vdev_fmt.fmt.meta.buffersize =
>> +             sizeof(struct rkisp1_isp_params_cfg);
>> +}
>> +
>> +int rkisp1_register_params_vdev(struct rkisp1_isp_params_vdev *params_vdev,
>> +                             struct v4l2_device *v4l2_dev,
>> +                             struct rkisp1_device *dev)
>> +{
>> +     int ret;
>> +     struct rkisp1_vdev_node *node = &params_vdev->vnode;
>> +     struct video_device *vdev = &node->vdev;
>> +
>> +     params_vdev->dev = dev;
>> +     mutex_init(&node->vlock);
>> +     spin_lock_init(&params_vdev->config_lock);
>> +
>> +     strlcpy(vdev->name, "rkisp1-input-params", sizeof(vdev->name));
>> +
>> +     video_set_drvdata(vdev, params_vdev);
>> +     vdev->ioctl_ops = &rkisp1_params_ioctl;
>> +     vdev->fops = &rkisp1_params_fops;
>> +     vdev->release = video_device_release_empty;
>> +     /*
>> +      * Provide a mutex to v4l2 core. It will be used
>> +      * to protect all fops and v4l2 ioctls.
>> +      */
>> +     vdev->lock = &node->vlock;
>> +     vdev->v4l2_dev = v4l2_dev;
>> +     vdev->queue = &node->buf_queue;
>> +     vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT;
>> +     vdev->vfl_dir = VFL_DIR_TX;
>> +     rkisp1_params_init_vb2_queue(vdev->queue, params_vdev);
>> +     rkisp1_init_params_vdev(params_vdev);
>> +     video_set_drvdata(vdev, params_vdev);
>> +
>> +     node->pad.flags = MEDIA_PAD_FL_SOURCE;
>> +     vdev->entity.function = MEDIA_ENT_F_IO_V4L;
>> +     ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
>> +     if (ret < 0)
>> +             goto err_release_queue;
>> +     ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
>> +     if (ret < 0) {
>> +             dev_err(&vdev->dev,
>> +                     "could not register Video for Linux device\n");
>> +             goto err_cleanup_media_entity;
>> +     }
>> +     return 0;
>> +err_cleanup_media_entity:
>> +     media_entity_cleanup(&vdev->entity);
>> +err_release_queue:
>> +     vb2_queue_release(vdev->queue);
>> +     return ret;
>> +}
>> +
>> +void rkisp1_unregister_params_vdev(struct rkisp1_isp_params_vdev *params_vdev)
>> +{
>> +     struct rkisp1_vdev_node *node = &params_vdev->vnode;
>> +     struct video_device *vdev = &node->vdev;
>> +
>> +     video_unregister_device(vdev);
>> +     media_entity_cleanup(&vdev->entity);
>> +     vb2_queue_release(vdev->queue);
>> +}
>> diff --git a/drivers/media/platform/rockchip/isp1/isp_params.h b/drivers/media/platform/rockchip/isp1/isp_params.h
>> new file mode 100644
>> index 000000000000..0d6a2f2a151f
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/isp_params.h
>> @@ -0,0 +1,76 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef _RKISP1_ISP_H
>> +#define _RKISP1_ISP_H
>> +
>> +#include <linux/rkisp1-config.h>
>> +#include "common.h"
>> +
>> +/*
>> + * struct rkisp1_isp_subdev - ISP input parameters device
>> + *
>> + * @cur_params: Current ISP parameters
>> + * @first_params: the first params should take effect immediately
>> + */
>> +struct rkisp1_isp_params_vdev {
>> +     struct rkisp1_vdev_node vnode;
>> +     struct rkisp1_device *dev;
>> +
>> +     spinlock_t config_lock;
>> +     struct list_head params;
>> +     struct rkisp1_isp_params_cfg cur_params;
>> +     struct v4l2_format vdev_fmt;
>> +     bool streamon;
>> +     bool first_params;
>> +
>> +     enum v4l2_quantization quantization;
>> +     enum rkisp1_fmt_raw_pat_type raw_type;
>> +};
>> +
>> +/* config params before ISP streaming */
>> +void rkisp1_configure_isp(struct rkisp1_isp_params_vdev *params_vdev,
>> +                       struct ispsd_in_fmt *in_fmt,
>> +                       enum v4l2_quantization quantization);
>> +void rkisp1_disable_isp(struct rkisp1_isp_params_vdev *params_vdev);
>> +
>> +int rkisp1_register_params_vdev(struct rkisp1_isp_params_vdev *params_vdev,
>> +                             struct v4l2_device *v4l2_dev,
>> +                             struct rkisp1_device *dev);
>> +
>> +void rkisp1_unregister_params_vdev(struct rkisp1_isp_params_vdev *params_vdev);
>> +
>> +void rkisp1_params_isr(struct rkisp1_isp_params_vdev *params_vdev, u32 isp_mis);
>> +
>> +#endif /* _RKISP1_ISP_H */
>> diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.c b/drivers/media/platform/rockchip/isp1/isp_stats.c
>> new file mode 100644
>> index 000000000000..bb25c6384498
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/isp_stats.c
>> @@ -0,0 +1,521 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#include <media/v4l2-common.h>
>> +#include <media/v4l2-ioctl.h>
>> +#include <media/videobuf2-core.h>
>> +#include <media/videobuf2-vmalloc.h> /* for ISP statistics */
>> +#include "dev.h"
>> +#include "regs.h"
>> +
>> +#define RKISP1_ISP_STATS_REQ_BUFS_MIN 2
>> +#define RKISP1_ISP_STATS_REQ_BUFS_MAX 8
>> +
>> +static int rkisp1_stats_enum_fmt_meta_cap(struct file *file, void *priv,
>> +                                       struct v4l2_fmtdesc *f)
>> +{
>> +     struct video_device *video = video_devdata(file);
>> +     struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
>> +
>> +     if (f->index > 0 || f->type != video->queue->type)
>> +             return -EINVAL;
>> +
>> +     f->pixelformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_stats_g_fmt_meta_cap(struct file *file, void *priv,
>> +                                    struct v4l2_format *f)
>> +{
>> +     struct video_device *video = video_devdata(file);
>> +     struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
>> +     struct v4l2_meta_format *meta = &f->fmt.meta;
>> +
>> +     if (f->type != video->queue->type)
>> +             return -EINVAL;
>> +
>> +     memset(meta, 0, sizeof(*meta));
>> +     meta->dataformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
>> +     meta->buffersize = stats_vdev->vdev_fmt.fmt.meta.buffersize;
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_stats_querycap(struct file *file,
>> +                              void *priv, struct v4l2_capability *cap)
>> +{
>> +     struct video_device *vdev = video_devdata(file);
>> +
>> +     strcpy(cap->driver, DRIVER_NAME);
>> +     strlcpy(cap->card, vdev->name, sizeof(cap->card));
>> +     strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
>> +
>> +     return 0;
>> +}
>> +
>> +/* ISP video device IOCTLs */
>> +static const struct v4l2_ioctl_ops rkisp1_stats_ioctl = {
>> +     .vidioc_reqbufs = vb2_ioctl_reqbufs,
>> +     .vidioc_querybuf = vb2_ioctl_querybuf,
>> +     .vidioc_create_bufs = vb2_ioctl_create_bufs,
>> +     .vidioc_qbuf = vb2_ioctl_qbuf,
>> +     .vidioc_dqbuf = vb2_ioctl_dqbuf,
>> +     .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
>> +     .vidioc_expbuf = vb2_ioctl_expbuf,
>> +     .vidioc_streamon = vb2_ioctl_streamon,
>> +     .vidioc_streamoff = vb2_ioctl_streamoff,
>> +     .vidioc_enum_fmt_meta_cap = rkisp1_stats_enum_fmt_meta_cap,
>> +     .vidioc_g_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
>> +     .vidioc_s_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
>> +     .vidioc_try_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
>> +     .vidioc_querycap = rkisp1_stats_querycap
>> +};
>> +
>> +struct v4l2_file_operations rkisp1_stats_fops = {
>> +     .mmap = vb2_fop_mmap,
>> +     .unlocked_ioctl = video_ioctl2,
>> +     .poll = vb2_fop_poll,
>> +     .open = v4l2_fh_open,
>> +     .release = vb2_fop_release
>> +};
>> +
>> +static int rkisp1_stats_vb2_queue_setup(struct vb2_queue *vq,
>> +                                     unsigned int *num_buffers,
>> +                                     unsigned int *num_planes,
>> +                                     unsigned int sizes[],
>> +                                     struct device *alloc_devs[])
>> +{
>> +     struct rkisp1_isp_stats_vdev *stats_vdev = vq->drv_priv;
>> +
>> +     *num_planes = 1;
>> +
>> +     *num_buffers = clamp_t(u32, *num_buffers, RKISP1_ISP_STATS_REQ_BUFS_MIN,
>> +                            RKISP1_ISP_STATS_REQ_BUFS_MAX);
>> +
>> +     sizes[0] = sizeof(struct rkisp1_stat_buffer);
>> +
>> +     INIT_LIST_HEAD(&stats_vdev->stat);
>> +
>> +     return 0;
>> +}
>> +
>> +static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb)
>> +{
>> +     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +     struct rkisp1_buffer *stats_buf = to_rkisp1_buffer(vbuf);
>> +     struct vb2_queue *vq = vb->vb2_queue;
>> +     struct rkisp1_isp_stats_vdev *stats_dev = vq->drv_priv;
>> +     unsigned long flags;
>> +
>> +     stats_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
>> +     spin_lock_irqsave(&stats_dev->irq_lock, flags);
>> +     list_add_tail(&stats_buf->queue, &stats_dev->stat);
>> +     spin_unlock_irqrestore(&stats_dev->irq_lock, flags);
>> +}
>> +
>> +static void rkisp1_stats_vb2_stop_streaming(struct vb2_queue *vq)
>> +{
>> +     struct rkisp1_isp_stats_vdev *stats_vdev = vq->drv_priv;
>> +     struct rkisp1_buffer *buf;
>> +     unsigned long flags;
>> +     int i;
>> +
>> +     /* stop stats received firstly */
>> +     spin_lock_irqsave(&stats_vdev->irq_lock, flags);
>> +     stats_vdev->streamon = false;
>> +     spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
>> +
>> +     drain_workqueue(stats_vdev->readout_wq);
>> +
>> +     for (i = 0; i < RKISP1_ISP_STATS_REQ_BUFS_MAX; i++) {
>> +             spin_lock_irqsave(&stats_vdev->irq_lock, flags);
>> +             if (!list_empty(&stats_vdev->stat)) {
>> +                     buf = list_first_entry(&stats_vdev->stat,
>> +                                            struct rkisp1_buffer, queue);
>> +                     list_del(&buf->queue);
>> +                     spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
>> +             } else {
>> +                     spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
>> +                     break;
>> +             }
>> +
>> +             if (buf)
>> +                     vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
>> +             buf = NULL;
>> +     }
>> +}
>> +
>> +static int
>> +rkisp1_stats_vb2_start_streaming(struct vb2_queue *queue,
>> +                              unsigned int count)
>> +{
>> +     struct rkisp1_isp_stats_vdev *stats_vdev = queue->drv_priv;
>> +     unsigned long flags;
>> +
>> +     spin_lock_irqsave(&stats_vdev->irq_lock, flags);
>> +     stats_vdev->streamon = true;
>> +     spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
>> +
>> +     return 0;
>> +}
>> +
>> +static struct vb2_ops rkisp1_stats_vb2_ops = {
>> +     .queue_setup = rkisp1_stats_vb2_queue_setup,
>> +     .buf_queue = rkisp1_stats_vb2_buf_queue,
>> +     .wait_prepare = vb2_ops_wait_prepare,
>> +     .wait_finish = vb2_ops_wait_finish,
>> +     .stop_streaming = rkisp1_stats_vb2_stop_streaming,
>> +     .start_streaming = rkisp1_stats_vb2_start_streaming,
>> +};
>> +
>> +static int rkisp1_stats_init_vb2_queue(struct vb2_queue *q,
>> +                                    struct rkisp1_isp_stats_vdev *stats_vdev)
>> +{
>> +     struct rkisp1_vdev_node *node;
>> +
>> +     node = queue_to_node(q);
>> +
>> +     q->type = V4L2_BUF_TYPE_META_CAPTURE;
>> +     q->io_modes = VB2_MMAP | VB2_USERPTR;
>
> Either add VB2_DMABUF or drop expbuf from rkisp1_stats_ioctl.
>
>> +     q->drv_priv = stats_vdev;
>> +     q->ops = &rkisp1_stats_vb2_ops;
>> +     q->mem_ops = &vb2_vmalloc_memops;
>> +     q->buf_struct_size = sizeof(struct rkisp1_buffer);
>> +     q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
>> +     q->lock = &node->vlock;
>> +
>> +     return vb2_queue_init(q);
>> +}
>> +
>> +static void rkisp1_stats_get_awb_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
>> +                                   struct rkisp1_stat_buffer *pbuf)
>> +{
>> +     /* Protect against concurrent access from ISR? */
>> +     u32 reg_val;
>> +
>> +     pbuf->meas_type |= CIFISP_STAT_AWB;
>> +     reg_val = readl(stats_vdev->dev->base_addr + CIF_ISP_AWB_WHITE_CNT);
>> +     pbuf->params.awb.awb_mean[0].cnt = CIF_ISP_AWB_GET_PIXEL_CNT(reg_val);
>> +     reg_val = readl(stats_vdev->dev->base_addr + CIF_ISP_AWB_MEAN);
>> +
>> +     pbuf->params.awb.awb_mean[0].mean_cr_or_r =
>> +             CIF_ISP_AWB_GET_MEAN_CR_R(reg_val);
>> +     pbuf->params.awb.awb_mean[0].mean_cb_or_b =
>> +             CIF_ISP_AWB_GET_MEAN_CB_B(reg_val);
>> +     pbuf->params.awb.awb_mean[0].mean_y_or_g =
>> +             CIF_ISP_AWB_GET_MEAN_Y_G(reg_val);
>> +}
>> +
>> +static void rkisp1_stats_get_aec_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
>> +                                   struct rkisp1_stat_buffer *pbuf)
>> +{
>> +     unsigned int i;
>> +     void __iomem *addr = stats_vdev->dev->base_addr + CIF_ISP_EXP_MEAN_00;
>> +
>> +     pbuf->meas_type |= CIFISP_STAT_AUTOEXP;
>> +     for (i = 0; i < CIFISP_AE_MEAN_MAX; i++)
>> +             pbuf->params.ae.exp_mean[i] = (u8)readl(addr + i * 4);
>> +}
>> +
>> +static void rkisp1_stats_get_afc_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
>> +                                   struct rkisp1_stat_buffer *pbuf)
>> +{
>> +     void __iomem *base_addr;
>> +     struct cifisp_af_stat *af;
>> +
>> +     pbuf->meas_type = CIFISP_STAT_AFM_FIN;
>> +
>> +     af = &pbuf->params.af;
>> +     base_addr = stats_vdev->dev->base_addr;
>> +     af->window[0].sum = readl(base_addr + CIF_ISP_AFM_SUM_A);
>> +     af->window[0].lum = readl(base_addr + CIF_ISP_AFM_LUM_A);
>> +     af->window[1].sum = readl(base_addr + CIF_ISP_AFM_SUM_B);
>> +     af->window[1].lum = readl(base_addr + CIF_ISP_AFM_LUM_B);
>> +     af->window[2].sum = readl(base_addr + CIF_ISP_AFM_SUM_C);
>> +     af->window[2].lum = readl(base_addr + CIF_ISP_AFM_LUM_C);
>> +}
>> +
>> +static void rkisp1_stats_get_hst_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
>> +                                   struct rkisp1_stat_buffer *pbuf)
>> +{
>> +     int i;
>> +     void __iomem *addr = stats_vdev->dev->base_addr + CIF_ISP_HIST_BIN_0;
>> +
>> +     pbuf->meas_type |= CIFISP_STAT_HIST;
>> +     for (i = 0; i < CIFISP_HIST_BIN_N_MAX; i++)
>> +             pbuf->params.hist.hist_bins[i] = readl(addr + (i * 4));
>> +}
>> +
>> +static void rkisp1_stats_get_bls_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
>> +                                   struct rkisp1_stat_buffer *pbuf)
>> +{
>> +     struct rkisp1_device *dev = stats_vdev->dev;
>> +     const struct ispsd_in_fmt *in_fmt =
>> +                     rkisp1_get_ispsd_in_fmt(&dev->isp_sdev);
>> +     void __iomem *base = stats_vdev->dev->base_addr;
>> +     struct cifisp_bls_meas_val *bls_val;
>> +
>> +     bls_val = &pbuf->params.ae.bls_val;
>> +     if (in_fmt->bayer_pat == RAW_BGGR) {
>> +             bls_val->meas_b = readl(base + CIF_ISP_BLS_A_MEASURED);
>> +             bls_val->meas_gb = readl(base + CIF_ISP_BLS_B_MEASURED);
>> +             bls_val->meas_gr = readl(base + CIF_ISP_BLS_C_MEASURED);
>> +             bls_val->meas_r = readl(base + CIF_ISP_BLS_D_MEASURED);
>> +     } else if (in_fmt->bayer_pat == RAW_GBRG) {
>> +             bls_val->meas_gb = readl(base + CIF_ISP_BLS_A_MEASURED);
>> +             bls_val->meas_b = readl(base + CIF_ISP_BLS_B_MEASURED);
>> +             bls_val->meas_r = readl(base + CIF_ISP_BLS_C_MEASURED);
>> +             bls_val->meas_gr = readl(base + CIF_ISP_BLS_D_MEASURED);
>> +     } else if (in_fmt->bayer_pat == RAW_GRBG) {
>> +             bls_val->meas_gr = readl(base + CIF_ISP_BLS_A_MEASURED);
>> +             bls_val->meas_r = readl(base + CIF_ISP_BLS_B_MEASURED);
>> +             bls_val->meas_b = readl(base + CIF_ISP_BLS_C_MEASURED);
>> +             bls_val->meas_gb = readl(base + CIF_ISP_BLS_D_MEASURED);
>> +     } else if (in_fmt->bayer_pat == RAW_RGGB) {
>> +             bls_val->meas_r = readl(base + CIF_ISP_BLS_A_MEASURED);
>> +             bls_val->meas_gr = readl(base + CIF_ISP_BLS_B_MEASURED);
>> +             bls_val->meas_gb = readl(base + CIF_ISP_BLS_C_MEASURED);
>> +             bls_val->meas_b = readl(base + CIF_ISP_BLS_D_MEASURED);
>> +     }
>> +}
>> +
>> +static void
>> +rkisp1_stats_send_measurement(struct rkisp1_isp_stats_vdev *stats_vdev,
>> +                           struct rkisp1_isp_readout_work *meas_work)
>> +{
>> +     unsigned long lock_flags = 0;
>> +     unsigned int cur_frame_id = -1;
>> +     struct rkisp1_stat_buffer *cur_stat_buf;
>> +     struct rkisp1_buffer *cur_buf = NULL;
>> +
>> +     spin_lock_irqsave(&stats_vdev->irq_lock, lock_flags);
>> +     cur_frame_id = atomic_read(&stats_vdev->dev->isp_sdev.frm_sync_seq) - 1;
>> +     if (cur_frame_id != meas_work->frame_id) {
>> +             v4l2_warn(stats_vdev->vnode.vdev.v4l2_dev,
>> +                       "Measurement late(%d, %d)\n",
>> +                       cur_frame_id, meas_work->frame_id);
>> +     }
>> +     /* get one empty buffer */
>> +     if (!list_empty(&stats_vdev->stat)) {
>> +             cur_buf = list_first_entry(&stats_vdev->stat,
>> +                                        struct rkisp1_buffer, queue);
>> +             list_del(&cur_buf->queue);
>> +     }
>> +     spin_unlock_irqrestore(&stats_vdev->irq_lock, lock_flags);
>> +
>> +     if (!cur_buf)
>> +             return;
>> +
>> +     cur_stat_buf =
>> +             (struct rkisp1_stat_buffer *)(cur_buf->vaddr[0]);
>> +
>> +     if (meas_work->isp_ris & CIF_ISP_AWB_DONE) {
>> +             rkisp1_stats_get_awb_meas(stats_vdev, cur_stat_buf);
>> +             cur_stat_buf->meas_type |= CIFISP_STAT_AWB;
>> +     }
>> +
>> +     if (meas_work->isp_ris & CIF_ISP_AFM_FIN) {
>> +             rkisp1_stats_get_afc_meas(stats_vdev, cur_stat_buf);
>> +             cur_stat_buf->meas_type |= CIFISP_STAT_AFM_FIN;
>> +     }
>> +
>> +     if (meas_work->isp_ris & CIF_ISP_EXP_END) {
>> +             rkisp1_stats_get_aec_meas(stats_vdev, cur_stat_buf);
>> +             rkisp1_stats_get_bls_meas(stats_vdev, cur_stat_buf);
>> +             cur_stat_buf->meas_type |= CIFISP_STAT_AUTOEXP;
>> +     }
>> +
>> +     if (meas_work->isp_ris & CIF_ISP_HIST_MEASURE_RDY) {
>> +             rkisp1_stats_get_hst_meas(stats_vdev, cur_stat_buf);
>> +             cur_stat_buf->meas_type |= CIFISP_STAT_HIST;
>> +     }
>> +
>> +     vb2_set_plane_payload(&cur_buf->vb.vb2_buf, 0,
>> +                           sizeof(struct rkisp1_stat_buffer));
>> +     cur_buf->vb.sequence = cur_frame_id;
>> +     cur_buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> +     vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
>> +}
>> +
>> +static void rkisp1_stats_readout_work(struct work_struct *work)
>> +{
>> +     struct rkisp1_isp_readout_work *readout_work = container_of(work,
>> +                                             struct rkisp1_isp_readout_work,
>> +                                             work);
>> +     struct rkisp1_isp_stats_vdev *stats_vdev = readout_work->stats_vdev;
>> +
>> +     if (readout_work->readout == RKISP1_ISP_READOUT_MEAS)
>> +             rkisp1_stats_send_measurement(stats_vdev, readout_work);
>> +
>> +     kfree(readout_work);
>> +}
>> +
>> +int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris)
>> +{
>> +     unsigned int isp_mis_tmp = 0;
>> +     struct rkisp1_isp_readout_work *work;
>> +     unsigned int cur_frame_id =
>> +             atomic_read(&stats_vdev->dev->isp_sdev.frm_sync_seq) - 1;
>> +#ifdef LOG_ISR_EXE_TIME
>> +     ktime_t in_t = ktime_get();
>> +#endif
>> +
>> +     writel((CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN | CIF_ISP_EXP_END |
>> +             CIF_ISP_HIST_MEASURE_RDY),
>> +             stats_vdev->dev->base_addr + CIF_ISP_ICR);
>> +
>> +     isp_mis_tmp = readl(stats_vdev->dev->base_addr + CIF_ISP_MIS);
>> +     if (isp_mis_tmp &
>> +             (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
>> +              CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
>> +             v4l2_err(stats_vdev->vnode.vdev.v4l2_dev,
>> +                      "isp icr 3A info err: 0x%x\n",
>> +                      isp_mis_tmp);
>> +
>> +     if (isp_ris & (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN | CIF_ISP_EXP_END |
>> +             CIF_ISP_HIST_MEASURE_RDY)) {
>> +             work = (struct rkisp1_isp_readout_work *)
>> +                     kzalloc(sizeof(struct rkisp1_isp_readout_work),
>> +                             GFP_ATOMIC);
>> +             if (work) {
>> +                     INIT_WORK(&work->work,
>> +                               rkisp1_stats_readout_work);
>> +                     work->readout = RKISP1_ISP_READOUT_MEAS;
>> +                     work->stats_vdev = stats_vdev;
>> +                     work->frame_id = cur_frame_id;
>> +                     work->isp_ris = isp_ris;
>> +                     if (!queue_work(stats_vdev->readout_wq,
>> +                                     &work->work))
>> +                             kfree(work);
>> +             } else {
>> +                     v4l2_err(stats_vdev->vnode.vdev.v4l2_dev,
>> +                              "Could not allocate work\n");
>> +             }
>> +     }
>> +
>> +#ifdef LOG_ISR_EXE_TIME
>> +     if (isp_ris & (CIF_ISP_EXP_END | CIF_ISP_AWB_DONE |
>> +                    CIF_ISP_FRAME | CIF_ISP_HIST_MEASURE_RDY)) {
>> +             unsigned int diff_us =
>> +                 ktime_to_us(ktime_sub(ktime_get(), in_t));
>> +
>> +             if (diff_us > g_longest_isr_time)
>> +                     g_longest_isr_time = diff_us;
>> +
>> +             v4l2_info(stats_vdev->vnode.vdev.v4l2_dev,
>> +                       "isp_isr time %d %d\n", diff_us, g_longest_isr_time);
>> +     }
>> +#endif
>> +
>> +     return 0;
>> +}
>> +
>> +static void rkisp1_init_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev)
>> +{
>> +     stats_vdev->vdev_fmt.fmt.meta.dataformat =
>> +             V4L2_META_FMT_RK_ISP1_STAT_3A;
>> +     stats_vdev->vdev_fmt.fmt.meta.buffersize =
>> +             sizeof(struct rkisp1_stat_buffer);
>> +}
>> +
>> +int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev,
>> +                            struct v4l2_device *v4l2_dev,
>> +                            struct rkisp1_device *dev)
>> +{
>> +     int ret;
>> +     struct rkisp1_vdev_node *node = &stats_vdev->vnode;
>> +     struct video_device *vdev = &node->vdev;
>> +
>> +     stats_vdev->dev = dev;
>> +     mutex_init(&node->vlock);
>> +     INIT_LIST_HEAD(&stats_vdev->stat);
>> +     spin_lock_init(&stats_vdev->irq_lock);
>> +
>> +     strlcpy(vdev->name, "rkisp1-statistics", sizeof(vdev->name));
>> +
>> +     video_set_drvdata(vdev, stats_vdev);
>> +     vdev->ioctl_ops = &rkisp1_stats_ioctl;
>> +     vdev->fops = &rkisp1_stats_fops;
>> +     vdev->release = video_device_release_empty;
>> +     vdev->lock = &node->vlock;
>> +     vdev->v4l2_dev = v4l2_dev;
>> +     vdev->queue = &node->buf_queue;
>> +     vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING;
>> +     vdev->vfl_dir =  VFL_DIR_RX;
>> +     rkisp1_stats_init_vb2_queue(vdev->queue, stats_vdev);
>> +     rkisp1_init_stats_vdev(stats_vdev);
>> +     video_set_drvdata(vdev, stats_vdev);
>> +
>> +     node->pad.flags = MEDIA_PAD_FL_SINK;
>> +     vdev->entity.function = MEDIA_ENT_F_IO_V4L;
>> +     ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
>> +     if (ret < 0)
>> +             goto err_release_queue;
>> +
>> +     ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
>> +     if (ret < 0) {
>> +             dev_err(&vdev->dev,
>> +                     "could not register Video for Linux device\n");
>> +             goto err_cleanup_media_entity;
>> +     }
>> +
>> +     stats_vdev->readout_wq =
>> +         alloc_workqueue("measurement_queue",
>> +                         WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
>> +
>> +     if (!stats_vdev->readout_wq) {
>> +             ret = -ENOMEM;
>> +                     goto err_unreg_vdev;
>> +     }
>> +
>> +     return 0;
>> +err_unreg_vdev:
>> +     video_unregister_device(vdev);
>> +err_cleanup_media_entity:
>> +     media_entity_cleanup(&vdev->entity);
>> +err_release_queue:
>> +     vb2_queue_release(vdev->queue);
>> +     return ret;
>> +}
>> +
>> +void rkisp1_unregister_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev)
>> +{
>> +     struct rkisp1_vdev_node *node = &stats_vdev->vnode;
>> +     struct video_device *vdev = &node->vdev;
>> +
>> +     destroy_workqueue(stats_vdev->readout_wq);
>> +     video_unregister_device(vdev);
>> +     media_entity_cleanup(&vdev->entity);
>> +     vb2_queue_release(vdev->queue);
>> +}
>> diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.h b/drivers/media/platform/rockchip/isp1/isp_stats.h
>> new file mode 100644
>> index 000000000000..71fd4e447fd9
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/isp_stats.h
>> @@ -0,0 +1,85 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef _RKISP1_ISP_STATS_H
>> +#define _RKISP1_ISP_STATS_H
>> +
>> +#include <linux/rkisp1-config.h>
>> +#include "common.h"
>> +
>> +struct rkisp1_isp_stats_vdev;
>> +
>> +enum rkisp1_isp_readout_cmd {
>> +     RKISP1_ISP_READOUT_MEAS,
>> +     RKISP1_ISP_READOUT_META,
>> +};
>> +
>> +struct rkisp1_isp_readout_work {
>> +     struct work_struct work;
>> +     struct rkisp1_isp_stats_vdev *stats_vdev;
>> +
>> +     unsigned int frame_id;
>> +     unsigned int isp_ris;
>> +     enum rkisp1_isp_readout_cmd readout;
>> +     struct vb2_buffer *vb;
>> +};
>> +
>> +/*
>> + * struct rkisp1_isp_stats_vdev - ISP Statistics device
>> + *
>> + * @irq_lock: buffer queue lock
>> + * @stat: stats buffer list
>> + * @readout_wq: workqueue for statistics information read
>> + */
>> +struct rkisp1_isp_stats_vdev {
>> +     struct rkisp1_vdev_node vnode;
>> +     struct rkisp1_device *dev;
>> +
>> +     spinlock_t irq_lock;
>> +     struct list_head stat;
>> +     struct v4l2_format vdev_fmt;
>> +     bool streamon;
>> +
>> +     struct workqueue_struct *readout_wq;
>> +};
>> +
>> +int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris);
>> +
>> +int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev,
>> +                            struct v4l2_device *v4l2_dev,
>> +                            struct rkisp1_device *dev);
>> +
>> +void rkisp1_unregister_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev);
>> +
>> +#endif /* _RKISP1_ISP_STATS_H */
>> diff --git a/drivers/media/platform/rockchip/isp1/regs.c b/drivers/media/platform/rockchip/isp1/regs.c
>> new file mode 100644
>> index 000000000000..46b9898044d4
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/regs.c
>> @@ -0,0 +1,264 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#include <media/v4l2-common.h>
>> +#include "regs.h"
>> +
>> +void disable_dcrop(struct rkisp1_stream *stream, bool async)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +     void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
>> +     u32 dc_ctrl = readl(dc_ctrl_addr);
>> +     u32 mask = ~(stream->config->dual_crop.yuvmode_mask |
>> +                     stream->config->dual_crop.rawmode_mask);
>> +     u32 val = dc_ctrl & mask;
>> +
>> +     if (async)
>> +             val |= CIF_DUAL_CROP_GEN_CFG_UPD;
>> +     else
>> +             val |= CIF_DUAL_CROP_CFG_UPD;
>> +     writel(val, dc_ctrl_addr);
>> +}
>> +
>> +void config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect, bool async)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +     void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
>> +     u32 dc_ctrl = readl(dc_ctrl_addr);
>> +
>> +     writel(rect->left, base + stream->config->dual_crop.h_offset);
>> +     writel(rect->top, base + stream->config->dual_crop.v_offset);
>> +     writel(rect->width, base + stream->config->dual_crop.h_size);
>> +     writel(rect->height, base + stream->config->dual_crop.v_size);
>> +     dc_ctrl |= stream->config->dual_crop.yuvmode_mask;
>> +     if (async)
>> +             dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
>> +     else
>> +             dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
>> +     writel(dc_ctrl, dc_ctrl_addr);
>> +}
>> +
>> +void dump_rsz_regs(struct rkisp1_stream *stream)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     pr_info("RSZ_CTRL 0x%08x/0x%08x\n"
>> +                     "RSZ_SCALE_HY %d/%d\n"
>> +                     "RSZ_SCALE_HCB %d/%d\n"
>> +                     "RSZ_SCALE_HCR %d/%d\n"
>> +                     "RSZ_SCALE_VY %d/%d\n"
>> +                     "RSZ_SCALE_VC %d/%d\n"
>> +                     "RSZ_PHASE_HY %d/%d\n"
>> +                     "RSZ_PHASE_HC %d/%d\n"
>> +                     "RSZ_PHASE_VY %d/%d\n"
>> +                     "RSZ_PHASE_VC %d/%d\n",
>> +                     readl(base + stream->config->rsz.ctrl),
>> +                     readl(base + stream->config->rsz.ctrl_shd),
>> +                     readl(base + stream->config->rsz.scale_hy),
>> +                     readl(base + stream->config->rsz.scale_hy_shd),
>> +                     readl(base + stream->config->rsz.scale_hcb),
>> +                     readl(base + stream->config->rsz.scale_hcb_shd),
>> +                     readl(base + stream->config->rsz.scale_hcr),
>> +                     readl(base + stream->config->rsz.scale_hcr_shd),
>> +                     readl(base + stream->config->rsz.scale_vy),
>> +                     readl(base + stream->config->rsz.scale_vy_shd),
>> +                     readl(base + stream->config->rsz.scale_vc),
>> +                     readl(base + stream->config->rsz.scale_vc_shd),
>> +                     readl(base + stream->config->rsz.phase_hy),
>> +                     readl(base + stream->config->rsz.phase_hy_shd),
>> +                     readl(base + stream->config->rsz.phase_hc),
>> +                     readl(base + stream->config->rsz.phase_hc_shd),
>> +                     readl(base + stream->config->rsz.phase_vy),
>> +                     readl(base + stream->config->rsz.phase_vy_shd),
>> +                     readl(base + stream->config->rsz.phase_vc),
>> +                     readl(base + stream->config->rsz.phase_vc_shd));
>> +}
>> +
>> +static void update_rsz_shadow(struct rkisp1_stream *stream)
>> +{
>> +     void *addr = stream->ispdev->base_addr + stream->config->rsz.ctrl;
>> +     u32 ctrl_cfg = readl(addr);
>> +
>> +     writel(CIF_RSZ_CTRL_CFG_UPD | ctrl_cfg, addr);
>> +}
>> +
>> +static void set_scale(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
>> +             struct v4l2_rect *in_c, struct v4l2_rect *out_y,
>> +             struct v4l2_rect *out_c)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +     void __iomem *scale_hy_addr = base + stream->config->rsz.scale_hy;
>> +     void __iomem *scale_hcr_addr = base + stream->config->rsz.scale_hcr;
>> +     void __iomem *scale_hcb_addr = base + stream->config->rsz.scale_hcb;
>> +     void __iomem *scale_vy_addr = base + stream->config->rsz.scale_vy;
>> +     void __iomem *scale_vc_addr = base + stream->config->rsz.scale_vc;
>> +     void __iomem *rsz_ctrl_addr = base + stream->config->rsz.ctrl;
>> +     u32 scale_hy, scale_hc, scale_vy, scale_vc, rsz_ctrl = 0;
>> +
>> +     if (in_y->width < out_y->width) {
>> +             rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE |
>> +                             CIF_RSZ_CTRL_SCALE_HY_UP;
>> +             scale_hy = ((in_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +                             (out_y->width - 1);
>> +             writel(scale_hy, scale_hy_addr);
>> +     } else if (in_y->width > out_y->width) {
>> +             rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE;
>> +             scale_hy = ((out_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +                             (in_y->width - 1) + 1;
>> +             writel(scale_hy, scale_hy_addr);
>> +     }
>> +     if (in_c->width < out_c->width) {
>> +             rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE |
>> +                             CIF_RSZ_CTRL_SCALE_HC_UP;
>> +             scale_hc = ((in_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +                             (out_c->width - 1);
>> +             writel(scale_hc, scale_hcb_addr);
>> +             writel(scale_hc, scale_hcr_addr);
>> +     } else if (in_c->width > out_c->width) {
>> +             rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE;
>> +             scale_hc = ((out_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +                             (in_c->width - 1) + 1;
>> +             writel(scale_hc, scale_hcb_addr);
>> +             writel(scale_hc, scale_hcr_addr);
>> +     }
>> +
>> +     if (in_y->height < out_y->height) {
>> +             rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE |
>> +                             CIF_RSZ_CTRL_SCALE_VY_UP;
>> +             scale_vy = ((in_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +                             (out_y->height - 1);
>> +             writel(scale_vy, scale_vy_addr);
>> +     } else if (in_y->height > out_y->height) {
>> +             rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE;
>> +             scale_vy = ((out_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +                             (in_y->height - 1) + 1;
>> +             writel(scale_vy, scale_vy_addr);
>> +     }
>> +
>> +     if (in_c->height < out_c->height) {
>> +             rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE |
>> +                             CIF_RSZ_CTRL_SCALE_VC_UP;
>> +             scale_vc = ((in_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +                             (out_c->height - 1);
>> +             writel(scale_vc, scale_vc_addr);
>> +     } else if (in_c->height > out_c->height) {
>> +             rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE;
>> +             scale_vc = ((out_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +                             (in_c->height - 1) + 1;
>> +             writel(scale_vc, scale_vc_addr);
>> +     }
>> +
>> +     writel(rsz_ctrl, rsz_ctrl_addr);
>> +}
>> +
>> +void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
>> +     struct v4l2_rect *in_c, struct v4l2_rect *out_y,
>> +     struct v4l2_rect *out_c, bool async)
>> +{
>> +     int i = 0;
>> +
>> +     /* No phase offset */
>> +     writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_hy);
>> +     writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_hc);
>> +     writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_vy);
>> +     writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_vc);
>> +
>> +     /* Linear interpolation */
>> +     for (i = 0; i < 64; i++) {
>> +             writel(i, stream->ispdev->base_addr + stream->config->rsz.scale_lut_addr);
>> +             writel(i, stream->ispdev->base_addr + stream->config->rsz.scale_lut);
>> +     }
>> +
>> +     set_scale(stream, in_y, in_c, out_y, out_c);
>> +
>> +     if (!async)
>> +             update_rsz_shadow(stream);
>> +}
>> +
>> +void disable_rsz(struct rkisp1_stream *stream, bool async)
>> +{
>> +     writel(0, stream->ispdev->base_addr + stream->config->rsz.ctrl);
>> +
>> +     if (!async)
>> +             update_rsz_shadow(stream);
>> +}
>> +
>> +void config_mi_ctrl(struct rkisp1_stream *stream)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +     u32 reg;
>> +
>> +     reg = readl(addr) & ~GENMASK(17, 16);
>> +     writel(reg | CIF_MI_CTRL_BURST_LEN_LUM_64, addr);
>> +     reg = readl(addr) & ~GENMASK(19, 18);
>> +     writel(reg | CIF_MI_CTRL_BURST_LEN_CHROM_64, addr);
>> +     reg = readl(addr);
>> +     writel(reg | CIF_MI_CTRL_INIT_BASE_EN, addr);
>> +     reg = readl(addr);
>> +     writel(reg | CIF_MI_CTRL_INIT_OFFSET_EN, addr);
>> +}
>> +
>> +void mp_clr_frame_end_int(void __iomem *base)
>> +{
>> +     writel(CIF_MI_MP_FRAME, base + CIF_MI_ICR);
>> +}
>> +
>> +void sp_clr_frame_end_int(void __iomem *base)
>> +{
>> +     writel(CIF_MI_SP_FRAME, base + CIF_MI_ICR);
>> +}
>> +
>> +bool mp_is_frame_end_int_masked(void __iomem *base)
>> +{
>> +     return (mi_get_masked_int_status(base) & CIF_MI_MP_FRAME);
>> +}
>> +
>> +bool sp_is_frame_end_int_masked(void __iomem *base)
>> +{
>> +     return (mi_get_masked_int_status(base) & CIF_MI_SP_FRAME);
>> +}
>> +
>> +bool mp_is_stream_stopped(void __iomem *base)
>> +{
>> +     int en;
>> +
>> +     en = CIF_MI_CTRL_SHD_MP_IN_ENABLED | CIF_MI_CTRL_SHD_RAW_OUT_ENABLED;
>> +     return !(readl(base + CIF_MI_CTRL_SHD) & en);
>> +}
>> +
>> +bool sp_is_stream_stopped(void __iomem *base)
>> +{
>> +     return !(readl(base + CIF_MI_CTRL_SHD) & CIF_MI_CTRL_SHD_SP_IN_ENABLED);
>> +}
>> diff --git a/drivers/media/platform/rockchip/isp1/regs.h b/drivers/media/platform/rockchip/isp1/regs.h
>> new file mode 100644
>> index 000000000000..e8709b639bc2
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/regs.h
>> @@ -0,0 +1,1582 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef _RKISP1_REGS_H
>> +#define _RKISP1_REGS_H
>> +#include "dev.h"
>> +
>> +/* ISP_CTRL */
>> +#define CIF_ISP_CTRL_ISP_ENABLE                      BIT(0)
>> +#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT               (0 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_ITU656         (1 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_ITU601         (2 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601   (3 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_DATA_MODE              (4 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656   (5 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656        (6 << 1)
>> +#define CIF_ISP_CTRL_ISP_INFORM_ENABLE               BIT(4)
>> +#define CIF_ISP_CTRL_ISP_GAMMA_IN_ENA                BIT(6)
>> +#define CIF_ISP_CTRL_ISP_AWB_ENA             BIT(7)
>> +#define CIF_ISP_CTRL_ISP_CFG_UPD_PERMANENT   BIT(8)
>> +#define CIF_ISP_CTRL_ISP_CFG_UPD             BIT(9)
>> +#define CIF_ISP_CTRL_ISP_GEN_CFG_UPD         BIT(10)
>> +#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA               BIT(11)
>> +#define CIF_ISP_CTRL_ISP_FLASH_MODE_ENA              BIT(12)
>> +#define CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA              BIT(13)
>> +#define CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA              BIT(14)
>> +
>> +/* ISP_ACQ_PROP */
>> +#define CIF_ISP_ACQ_PROP_POS_EDGE            BIT(0)
>> +#define CIF_ISP_ACQ_PROP_HSYNC_LOW           BIT(1)
>> +#define CIF_ISP_ACQ_PROP_VSYNC_LOW           BIT(2)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB              (0 << 3)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG              (1 << 3)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG              (2 << 3)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR              (3 << 3)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT(pat)              ((pat) << 3)
>> +#define CIF_ISP_ACQ_PROP_YCBYCR                      (0 << 7)
>> +#define CIF_ISP_ACQ_PROP_YCRYCB                      (1 << 7)
>> +#define CIF_ISP_ACQ_PROP_CBYCRY                      (2 << 7)
>> +#define CIF_ISP_ACQ_PROP_CRYCBY                      (3 << 7)
>> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_ALL               (0 << 9)
>> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_EVEN              (1 << 9)
>> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_ODD               (2 << 9)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_12B          (0 << 12)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO     (1 << 12)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB              (2 << 12)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO              (3 << 12)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB               (4 << 12)
>> +
>> +/* VI_DPCL */
>> +#define CIF_VI_DPCL_DMA_JPEG                 (0 << 0)
>> +#define CIF_VI_DPCL_MP_MUX_MRSZ_MI           (1 << 0)
>> +#define CIF_VI_DPCL_MP_MUX_MRSZ_JPEG         (2 << 0)
>> +#define CIF_VI_DPCL_CHAN_MODE_MP             (1 << 2)
>> +#define CIF_VI_DPCL_CHAN_MODE_SP             (2 << 2)
>> +#define CIF_VI_DPCL_CHAN_MODE_MPSP           (3 << 2)
>> +#define CIF_VI_DPCL_DMA_SW_SPMUX             (0 << 4)
>> +#define CIF_VI_DPCL_DMA_SW_SI                        (1 << 4)
>> +#define CIF_VI_DPCL_DMA_SW_IE                        (2 << 4)
>> +#define CIF_VI_DPCL_DMA_SW_JPEG                      (3 << 4)
>> +#define CIF_VI_DPCL_DMA_SW_ISP                       (4 << 4)
>> +#define CIF_VI_DPCL_IF_SEL_PARALLEL          (0 << 8)
>> +#define CIF_VI_DPCL_IF_SEL_SMIA                      (1 << 8)
>> +#define CIF_VI_DPCL_IF_SEL_MIPI                      (2 << 8)
>> +#define CIF_VI_DPCL_DMA_IE_MUX_DMA           BIT(10)
>> +#define CIF_VI_DPCL_DMA_SP_MUX_DMA           BIT(11)
>> +
>> +/* ISP_IMSC - ISP_MIS - ISP_RIS - ISP_ICR - ISP_ISR */
>> +#define CIF_ISP_OFF                          BIT(0)
>> +#define CIF_ISP_FRAME                                BIT(1)
>> +#define CIF_ISP_DATA_LOSS                    BIT(2)
>> +#define CIF_ISP_PIC_SIZE_ERROR                       BIT(3)
>> +#define CIF_ISP_AWB_DONE                     BIT(4)
>> +#define CIF_ISP_FRAME_IN                     BIT(5)
>> +#define CIF_ISP_V_START                              BIT(6)
>> +#define CIF_ISP_H_START                              BIT(7)
>> +#define CIF_ISP_FLASH_ON                     BIT(8)
>> +#define CIF_ISP_FLASH_OFF                    BIT(9)
>> +#define CIF_ISP_SHUTTER_ON                   BIT(10)
>> +#define CIF_ISP_SHUTTER_OFF                  BIT(11)
>> +#define CIF_ISP_AFM_SUM_OF                   BIT(12)
>> +#define CIF_ISP_AFM_LUM_OF                   BIT(13)
>> +#define CIF_ISP_AFM_FIN                              BIT(14)
>> +#define CIF_ISP_HIST_MEASURE_RDY             BIT(15)
>> +#define CIF_ISP_FLASH_CAP                    BIT(17)
>> +#define CIF_ISP_EXP_END                              BIT(18)
>> +#define CIF_ISP_VSM_END                              BIT(19)
>> +
>> +/* ISP_ERR */
>> +#define CIF_ISP_ERR_INFORM_SIZE                      BIT(0)
>> +#define CIF_ISP_ERR_IS_SIZE                  BIT(1)
>> +#define CIF_ISP_ERR_OUTFORM_SIZE             BIT(2)
>> +
>> +/* MI_CTRL */
>> +#define CIF_MI_CTRL_MP_ENABLE                        (1 << 0)
>> +#define CIF_MI_CTRL_SP_ENABLE                        (2 << 0)
>> +#define CIF_MI_CTRL_JPEG_ENABLE                      (4 << 0)
>> +#define CIF_MI_CTRL_RAW_ENABLE                       (8 << 0)
>> +#define CIF_MI_CTRL_HFLIP                    BIT(4)
>> +#define CIF_MI_CTRL_VFLIP                    BIT(5)
>> +#define CIF_MI_CTRL_ROT                              BIT(6)
>> +#define CIF_MI_BYTE_SWAP                     BIT(7)
>> +#define CIF_MI_SP_Y_FULL_YUV2RGB             BIT(8)
>> +#define CIF_MI_SP_CBCR_FULL_YUV2RGB          BIT(9)
>> +#define CIF_MI_SP_422NONCOSITEED             BIT(10)
>> +#define CIF_MI_MP_PINGPONG_ENABEL            BIT(11)
>> +#define CIF_MI_SP_PINGPONG_ENABEL            BIT(12)
>> +#define CIF_MI_MP_AUTOUPDATE_ENABLE          BIT(13)
>> +#define CIF_MI_SP_AUTOUPDATE_ENABLE          BIT(14)
>> +#define CIF_MI_LAST_PIXEL_SIG_ENABLE         BIT(15)
>> +#define CIF_MI_CTRL_BURST_LEN_LUM_16         (0 << 16)
>> +#define CIF_MI_CTRL_BURST_LEN_LUM_32         (1 << 16)
>> +#define CIF_MI_CTRL_BURST_LEN_LUM_64         (2 << 16)
>> +#define CIF_MI_CTRL_BURST_LEN_CHROM_16               (0 << 18)
>> +#define CIF_MI_CTRL_BURST_LEN_CHROM_32               (1 << 18)
>> +#define CIF_MI_CTRL_BURST_LEN_CHROM_64               (2 << 18)
>> +#define CIF_MI_CTRL_INIT_BASE_EN             BIT(20)
>> +#define CIF_MI_CTRL_INIT_OFFSET_EN           BIT(21)
>> +#define MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8     (0 << 22)
>> +#define MI_CTRL_MP_WRITE_YUV_SPLA            (1 << 22)
>> +#define MI_CTRL_MP_WRITE_YUVINT                      (2 << 22)
>> +#define MI_CTRL_MP_WRITE_RAW12                       (2 << 22)
>> +#define MI_CTRL_SP_WRITE_PLA                 (0 << 24)
>> +#define MI_CTRL_SP_WRITE_SPLA                        (1 << 24)
>> +#define MI_CTRL_SP_WRITE_INT                 (2 << 24)
>> +#define MI_CTRL_SP_INPUT_YUV400                      (0 << 26)
>> +#define MI_CTRL_SP_INPUT_YUV420                      (1 << 26)
>> +#define MI_CTRL_SP_INPUT_YUV422                      (2 << 26)
>> +#define MI_CTRL_SP_INPUT_YUV444                      (3 << 26)
>> +#define MI_CTRL_SP_OUTPUT_YUV400             (0 << 28)
>> +#define MI_CTRL_SP_OUTPUT_YUV420             (1 << 28)
>> +#define MI_CTRL_SP_OUTPUT_YUV422             (2 << 28)
>> +#define MI_CTRL_SP_OUTPUT_YUV444             (3 << 28)
>> +#define MI_CTRL_SP_OUTPUT_RGB565             (4 << 28)
>> +#define MI_CTRL_SP_OUTPUT_RGB666             (5 << 28)
>> +#define MI_CTRL_SP_OUTPUT_RGB888             (6 << 28)
>> +
>> +#define MI_CTRL_MP_FMT_MASK                  GENMASK(23, 22)
>> +#define MI_CTRL_SP_FMT_MASK                  GENMASK(30, 24)
>> +
>> +/* MI_INIT */
>> +#define CIF_MI_INIT_SKIP                     BIT(2)
>> +#define CIF_MI_INIT_SOFT_UPD                 BIT(4)
>> +
>> +/* MI_CTRL_SHD */
>> +#define CIF_MI_CTRL_SHD_MP_IN_ENABLED                BIT(0)
>> +#define CIF_MI_CTRL_SHD_SP_IN_ENABLED                BIT(1)
>> +#define CIF_MI_CTRL_SHD_JPEG_IN_ENABLED              BIT(2)
>> +#define CIF_MI_CTRL_SHD_RAW_IN_ENABLED               BIT(3)
>> +#define CIF_MI_CTRL_SHD_MP_OUT_ENABLED               BIT(16)
>> +#define CIF_MI_CTRL_SHD_SP_OUT_ENABLED               BIT(17)
>> +#define CIF_MI_CTRL_SHD_JPEG_OUT_ENABLED     BIT(18)
>> +#define CIF_MI_CTRL_SHD_RAW_OUT_ENABLED              BIT(19)
>> +
>> +/* RSZ_CTRL */
>> +#define CIF_RSZ_CTRL_SCALE_HY_ENABLE         BIT(0)
>> +#define CIF_RSZ_CTRL_SCALE_HC_ENABLE         BIT(1)
>> +#define CIF_RSZ_CTRL_SCALE_VY_ENABLE         BIT(2)
>> +#define CIF_RSZ_CTRL_SCALE_VC_ENABLE         BIT(3)
>> +#define CIF_RSZ_CTRL_SCALE_HY_UP             BIT(4)
>> +#define CIF_RSZ_CTRL_SCALE_HC_UP             BIT(5)
>> +#define CIF_RSZ_CTRL_SCALE_VY_UP             BIT(6)
>> +#define CIF_RSZ_CTRL_SCALE_VC_UP             BIT(7)
>> +#define CIF_RSZ_CTRL_CFG_UPD                 BIT(8)
>> +#define CIF_RSZ_CTRL_CFG_UPD_AUTO            BIT(9)
>> +#define CIF_RSZ_SCALER_FACTOR                        BIT(16)
>> +
>> +/* MI_IMSC - MI_MIS - MI_RIS - MI_ICR - MI_ISR */
>> +#define CIF_MI_MP_FRAME                              BIT(0)
>> +#define CIF_MI_SP_FRAME                              BIT(1)
>> +#define CIF_MI_MBLK_LINE                     BIT(2)
>> +#define CIF_MI_FILL_MP_Y                     BIT(3)
>> +#define CIF_MI_WRAP_MP_Y                     BIT(4)
>> +#define CIF_MI_WRAP_MP_CB                    BIT(5)
>> +#define CIF_MI_WRAP_MP_CR                    BIT(6)
>> +#define CIF_MI_WRAP_SP_Y                     BIT(7)
>> +#define CIF_MI_WRAP_SP_CB                    BIT(8)
>> +#define CIF_MI_WRAP_SP_CR                    BIT(9)
>> +#define CIF_MI_DMA_READY                     BIT(11)
>> +
>> +/* MI_STATUS */
>> +#define CIF_MI_STATUS_MP_Y_FIFO_FULL         BIT(0)
>> +#define CIF_MI_STATUS_SP_Y_FIFO_FULL         BIT(4)
>> +
>> +/* MI_DMA_CTRL */
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_16     (0 << 0)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_32     (1 << 0)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_64     (2 << 0)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_16   (0 << 2)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_32   (1 << 2)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64   (2 << 2)
>> +#define CIF_MI_DMA_CTRL_READ_FMT_PLANAR              (0 << 4)
>> +#define CIF_MI_DMA_CTRL_READ_FMT_SPLANAR     (1 << 4)
>> +#define CIF_MI_DMA_CTRL_FMT_YUV400           (0 << 6)
>> +#define CIF_MI_DMA_CTRL_FMT_YUV420           (1 << 6)
>> +#define CIF_MI_DMA_CTRL_READ_FMT_PACKED              (2 << 4)
>> +#define CIF_MI_DMA_CTRL_FMT_YUV422           (2 << 6)
>> +#define CIF_MI_DMA_CTRL_FMT_YUV444           (3 << 6)
>> +#define CIF_MI_DMA_CTRL_BYTE_SWAP            BIT(8)
>> +#define CIF_MI_DMA_CTRL_CONTINUOUS_ENA               BIT(9)
>> +#define CIF_MI_DMA_CTRL_RGB_BAYER_NO         (0 << 12)
>> +#define CIF_MI_DMA_CTRL_RGB_BAYER_8BIT               (1 << 12)
>> +#define CIF_MI_DMA_CTRL_RGB_BAYER_16BIT              (2 << 12)
>> +/* MI_DMA_START */
>> +#define CIF_MI_DMA_START_ENABLE                      BIT(0)
>> +/* MI_XTD_FORMAT_CTRL  */
>> +#define CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP    BIT(0)
>> +#define CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP    BIT(1)
>> +#define CIF_MI_XTD_FMT_CTRL_DMA_CB_CR_SWAP   BIT(2)
>> +
>> +/* CCL */
>> +#define CIF_CCL_CIF_CLK_DIS                  BIT(2)
>> +/* ICCL */
>> +#define CIF_ICCL_ISP_CLK                     BIT(0)
>> +#define CIF_ICCL_CP_CLK                              BIT(1)
>> +#define CIF_ICCL_RES_2                               BIT(2)
>> +#define CIF_ICCL_MRSZ_CLK                    BIT(3)
>> +#define CIF_ICCL_SRSZ_CLK                    BIT(4)
>> +#define CIF_ICCL_JPEG_CLK                    BIT(5)
>> +#define CIF_ICCL_MI_CLK                              BIT(6)
>> +#define CIF_ICCL_RES_7                               BIT(7)
>> +#define CIF_ICCL_IE_CLK                              BIT(8)
>> +#define CIF_ICCL_SIMP_CLK                    BIT(9)
>> +#define CIF_ICCL_SMIA_CLK                    BIT(10)
>> +#define CIF_ICCL_MIPI_CLK                    BIT(11)
>> +#define CIF_ICCL_DCROP_CLK                   BIT(12)
>> +/* IRCL */
>> +#define CIF_IRCL_ISP_SW_RST                  BIT(0)
>> +#define CIF_IRCL_CP_SW_RST                   BIT(1)
>> +#define CIF_IRCL_YCS_SW_RST                  BIT(2)
>> +#define CIF_IRCL_MRSZ_SW_RST                 BIT(3)
>> +#define CIF_IRCL_SRSZ_SW_RST                 BIT(4)
>> +#define CIF_IRCL_JPEG_SW_RST                 BIT(5)
>> +#define CIF_IRCL_MI_SW_RST                   BIT(6)
>> +#define CIF_IRCL_CIF_SW_RST                  BIT(7)
>> +#define CIF_IRCL_IE_SW_RST                   BIT(8)
>> +#define CIF_IRCL_SI_SW_RST                   BIT(9)
>> +#define CIF_IRCL_MIPI_SW_RST                 BIT(11)
>> +
>> +/* C_PROC_CTR */
>> +#define CIF_C_PROC_CTR_ENABLE                        BIT(0)
>> +#define CIF_C_PROC_YOUT_FULL                 BIT(1)
>> +#define CIF_C_PROC_YIN_FULL                  BIT(2)
>> +#define CIF_C_PROC_COUT_FULL                 BIT(3)
>> +#define CIF_C_PROC_CTRL_RESERVED             0xFFFFFFFE
>> +#define CIF_C_PROC_CONTRAST_RESERVED         0xFFFFFF00
>> +#define CIF_C_PROC_BRIGHTNESS_RESERVED               0xFFFFFF00
>> +#define CIF_C_PROC_HUE_RESERVED                      0xFFFFFF00
>> +#define CIF_C_PROC_SATURATION_RESERVED               0xFFFFFF00
>> +#define CIF_C_PROC_MACC_RESERVED             0xE000E000
>> +#define CIF_C_PROC_TONE_RESERVED             0xF000
>> +/* DUAL_CROP_CTRL */
>> +#define CIF_DUAL_CROP_MP_MODE_BYPASS         (0 << 0)
>> +#define CIF_DUAL_CROP_MP_MODE_YUV            (1 << 0)
>> +#define CIF_DUAL_CROP_MP_MODE_RAW            (2 << 0)
>> +#define CIF_DUAL_CROP_SP_MODE_BYPASS         (0 << 2)
>> +#define CIF_DUAL_CROP_SP_MODE_YUV            (1 << 2)
>> +#define CIF_DUAL_CROP_SP_MODE_RAW            (2 << 2)
>> +#define CIF_DUAL_CROP_CFG_UPD_PERMANENT              BIT(4)
>> +#define CIF_DUAL_CROP_CFG_UPD                        BIT(5)
>> +#define CIF_DUAL_CROP_GEN_CFG_UPD            BIT(6)
>> +
>> +/* IMG_EFF_CTRL */
>> +#define CIF_IMG_EFF_CTRL_ENABLE                      BIT(0)
>> +#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE     (0 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE               (1 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_SEPIA          (2 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL              (3 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_EMBOSS         (4 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_SKETCH         (5 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_SHARPEN                (6 << 1)
>> +#define CIF_IMG_EFF_CTRL_CFG_UPD             BIT(4)
>> +#define CIF_IMG_EFF_CTRL_YCBCR_FULL          BIT(5)
>> +
>> +#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE_SHIFT       0
>> +#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE_SHIFT 1
>> +#define CIF_IMG_EFF_CTRL_MODE_SEPIA_SHIFT    2
>> +#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL_SHIFT        3
>> +#define CIF_IMG_EFF_CTRL_MODE_EMBOSS_SHIFT   4
>> +#define CIF_IMG_EFF_CTRL_MODE_SKETCH_SHIFT   5
>> +#define CIF_IMG_EFF_CTRL_MODE_SHARPEN_SHIFT  6
>> +#define CIF_IMG_EFF_CTRL_MODE_MASK           0xE
>> +
>> +/* IMG_EFF_COLOR_SEL */
>> +#define CIF_IMG_EFF_COLOR_RGB                        0
>> +#define CIF_IMG_EFF_COLOR_B                  (1 << 0)
>> +#define CIF_IMG_EFF_COLOR_G                  (2 << 0)
>> +#define CIF_IMG_EFF_COLOR_GB                 (3 << 0)
>> +#define CIF_IMG_EFF_COLOR_R                  (4 << 0)
>> +#define CIF_IMG_EFF_COLOR_RB                 (5 << 0)
>> +#define CIF_IMG_EFF_COLOR_RG                 (6 << 0)
>> +#define CIF_IMG_EFF_COLOR_RGB2                       (7 << 0)
>> +
>> +/* MIPI_CTRL */
>> +#define CIF_MIPI_CTRL_OUTPUT_ENA             BIT(0)
>> +#define CIF_MIPI_CTRL_SHUTDOWNLANES(a)               (((a) & 0xF) << 8)
>> +#define CIF_MIPI_CTRL_NUM_LANES(a)           (((a) & 0x3) << 12)
>> +#define CIF_MIPI_CTRL_ERR_SOT_HS_SKIP                BIT(16)
>> +#define CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP   BIT(17)
>> +#define CIF_MIPI_CTRL_CLOCKLANE_ENA          BIT(18)
>> +
>> +/* MIPI_DATA_SEL */
>> +#define CIF_MIPI_DATA_SEL_VC(a)                      (((a) & 0x3) << 6)
>> +#define CIF_MIPI_DATA_SEL_DT(a)                      (((a) & 0x3F) << 0)
>> +/* MIPI DATA_TYPE */
>> +#define CIF_CSI2_DT_YUV420_8b                        0x18
>> +#define CIF_CSI2_DT_YUV420_10b                       0x19
>> +#define CIF_CSI2_DT_YUV422_8b                        0x1E
>> +#define CIF_CSI2_DT_YUV422_10b                       0x1F
>> +#define CIF_CSI2_DT_RGB565                   0x22
>> +#define CIF_CSI2_DT_RGB666                   0x23
>> +#define CIF_CSI2_DT_RGB888                   0x24
>> +#define CIF_CSI2_DT_RAW8                     0x2A
>> +#define CIF_CSI2_DT_RAW10                    0x2B
>> +#define CIF_CSI2_DT_RAW12                    0x2C
>> +
>> +/* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */
>> +#define CIF_MIPI_SYNC_FIFO_OVFLW(a)          (((a) & 0xF) << 0)
>> +#define CIF_MIPI_ERR_SOT(a)                  (((a) & 0xF) << 4)
>> +#define CIF_MIPI_ERR_SOT_SYNC(a)             (((a) & 0xF) << 8)
>> +#define CIF_MIPI_ERR_EOT_SYNC(a)             (((a) & 0xF) << 12)
>> +#define CIF_MIPI_ERR_CTRL(a)                 (((a) & 0xF) << 16)
>> +#define CIF_MIPI_ERR_PROTOCOL                        BIT(20)
>> +#define CIF_MIPI_ERR_ECC1                    BIT(21)
>> +#define CIF_MIPI_ERR_ECC2                    BIT(22)
>> +#define CIF_MIPI_ERR_CS                              BIT(23)
>> +#define CIF_MIPI_FRAME_END                   BIT(24)
>> +#define CIF_MIPI_ADD_DATA_OVFLW                      BIT(25)
>> +#define CIF_MIPI_ADD_DATA_WATER_MARK         BIT(26)
>> +
>> +#define CIF_MIPI_ERR_CSI  (CIF_MIPI_ERR_PROTOCOL | \
>> +     CIF_MIPI_ERR_ECC1 | \
>> +     CIF_MIPI_ERR_ECC2 | \
>> +     CIF_MIPI_ERR_CS)
>> +
>> +#define CIF_MIPI_ERR_DPHY  (CIF_MIPI_ERR_SOT(3) | \
>> +     CIF_MIPI_ERR_SOT_SYNC(3) | \
>> +     CIF_MIPI_ERR_EOT_SYNC(3) | \
>> +     CIF_MIPI_ERR_CTRL(3))
>> +
>> +/* SUPER_IMPOSE */
>> +#define CIF_SUPER_IMP_CTRL_NORMAL_MODE               BIT(0)
>> +#define CIF_SUPER_IMP_CTRL_REF_IMG_MEM               BIT(1)
>> +#define CIF_SUPER_IMP_CTRL_TRANSP_DIS                BIT(2)
>> +
>> +/* ISP HISTOGRAM CALCULATION : ISP_HIST_PROP */
>> +#define CIF_ISP_HIST_PROP_MODE_DIS           (0 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_RGB           (1 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_RED           (2 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_GREEN         (3 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_BLUE          (4 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_LUM           (5 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_MASK          0x7
>> +#define CIF_ISP_HIST_PREDIV_SET(x)           (((x) & 0x7F) << 3)
>> +#define CIF_ISP_HIST_WEIGHT_SET(v0, v1, v2, v3)      \
>> +                                  (((v0) & 0x1F) | (((v1) & 0x1F) << 8)  |\
>> +                                  (((v2) & 0x1F) << 16) | \
>> +                                  (((v3) & 0x1F) << 24))
>> +
>> +#define CIF_ISP_HIST_WINDOW_OFFSET_RESERVED  0xFFFFF000
>> +#define CIF_ISP_HIST_WINDOW_SIZE_RESERVED    0xFFFFF800
>> +#define CIF_ISP_HIST_WEIGHT_RESERVED         0xE0E0E0E0
>> +#define CIF_ISP_MAX_HIST_PREDIVIDER          0x0000007F
>> +#define CIF_ISP_HIST_ROW_NUM                 5
>> +#define CIF_ISP_HIST_COLUMN_NUM                      5
>> +
>> +/* AUTO FOCUS MEASUREMENT:  ISP_AFM_CTRL */
>> +#define ISP_AFM_CTRL_ENABLE                  BIT(0)
>> +
>> +/* SHUTTER CONTROL */
>> +#define CIF_ISP_SH_CTRL_SH_ENA                       BIT(0)
>> +#define CIF_ISP_SH_CTRL_REP_EN                       BIT(1)
>> +#define CIF_ISP_SH_CTRL_SRC_SH_TRIG          BIT(2)
>> +#define CIF_ISP_SH_CTRL_EDGE_POS             BIT(3)
>> +#define CIF_ISP_SH_CTRL_POL_LOW                      BIT(4)
>> +
>> +/* FLASH MODULE */
>> +/* ISP_FLASH_CMD */
>> +#define CIF_FLASH_CMD_PRELIGHT_ON            BIT(0)
>> +#define CIF_FLASH_CMD_FLASH_ON                       BIT(1)
>> +#define CIF_FLASH_CMD_PRE_FLASH_ON           BIT(2)
>> +/* ISP_FLASH_CONFIG */
>> +#define CIF_FLASH_CONFIG_PRELIGHT_END                BIT(0)
>> +#define CIF_FLASH_CONFIG_VSYNC_POS           BIT(1)
>> +#define CIF_FLASH_CONFIG_PRELIGHT_LOW                BIT(2)
>> +#define CIF_FLASH_CONFIG_SRC_FL_TRIG         BIT(3)
>> +#define CIF_FLASH_CONFIG_DELAY(a)            (((a) & 0xF) << 4)
>> +
>> +/* Demosaic:  ISP_DEMOSAIC */
>> +#define CIF_ISP_DEMOSAIC_BYPASS                      BIT(10)
>> +#define CIF_ISP_DEMOSAIC_TH(x)                       ((x) & 0xFF)
>> +
>> +/* AWB */
>> +/* ISP_AWB_PROP */
>> +#define CIF_ISP_AWB_YMAX_CMP_EN                      BIT(2)
>> +#define CIFISP_AWB_YMAX_READ(x)                      (((x) >> 2) & 1)
>> +#define CIF_ISP_AWB_MODE_RGB_EN                      ((1 << 31) | (0x2 << 0))
>> +#define CIF_ISP_AWB_MODE_YCBCR_EN            ((0 << 31) | (0x2 << 0))
>> +#define CIF_ISP_AWB_MODE_YCBCR_EN            ((0 << 31) | (0x2 << 0))
>> +#define CIF_ISP_AWB_MODE_MASK_NONE           0xFFFFFFFC
>> +#define CIF_ISP_AWB_MODE_READ(x)             ((x) & 3)
>> +/* ISP_AWB_GAIN_RB, ISP_AWB_GAIN_G  */
>> +#define CIF_ISP_AWB_GAIN_R_SET(x)            (((x) & 0x3FF) << 16)
>> +#define CIF_ISP_AWB_GAIN_R_READ(x)           (((x) >> 16) & 0x3FF)
>> +#define CIF_ISP_AWB_GAIN_B_SET(x)            ((x) & 0x3FFF)
>> +#define CIF_ISP_AWB_GAIN_B_READ(x)           ((x) & 0x3FFF)
>> +/* ISP_AWB_REF */
>> +#define CIF_ISP_AWB_REF_CR_SET(x)            (((x) & 0xFF) << 8)
>> +#define CIF_ISP_AWB_REF_CR_READ(x)           (((x) >> 8) & 0xFF)
>> +#define CIF_ISP_AWB_REF_CB_READ(x)           ((x) & 0xFF)
>> +/* ISP_AWB_THRESH */
>> +#define CIF_ISP_AWB_MAX_CS_SET(x)            (((x) & 0xFF) << 8)
>> +#define CIF_ISP_AWB_MAX_CS_READ(x)           (((x) >> 8) & 0xFF)
>> +#define CIF_ISP_AWB_MIN_C_READ(x)            ((x) & 0xFF)
>> +#define CIF_ISP_AWB_MIN_Y_SET(x)             (((x) & 0xFF) << 16)
>> +#define CIF_ISP_AWB_MIN_Y_READ(x)            (((x) >> 16) & 0xFF)
>> +#define CIF_ISP_AWB_MAX_Y_SET(x)             (((x) & 0xFF) << 24)
>> +#define CIF_ISP_AWB_MAX_Y_READ(x)            (((x) >> 24) & 0xFF)
>> +/* ISP_AWB_MEAN */
>> +#define CIF_ISP_AWB_GET_MEAN_CR_R(x)         ((x) & 0xFF)
>> +#define CIF_ISP_AWB_GET_MEAN_CB_B(x)         (((x) >> 8) & 0xFF)
>> +#define CIF_ISP_AWB_GET_MEAN_Y_G(x)          (((x) >> 16) & 0xFF)
>> +/* ISP_AWB_WHITE_CNT */
>> +#define CIF_ISP_AWB_GET_PIXEL_CNT(x)         ((x) & 0x3FFFFFF)
>> +
>> +#define CIF_ISP_AWB_GAINS_MAX_VAL            0x000003FF
>> +#define CIF_ISP_AWB_WINDOW_OFFSET_MAX                0x00000FFF
>> +#define CIF_ISP_AWB_WINDOW_MAX_SIZE          0x00001FFF
>> +#define CIF_ISP_AWB_CBCR_MAX_REF             0x000000FF
>> +#define CIF_ISP_AWB_THRES_MAX_YC             0x000000FF
>> +
>> +/* AE */
>> +/* ISP_EXP_CTRL */
>> +#define CIF_ISP_EXP_ENA                              BIT(0)
>> +#define CIF_ISP_EXP_CTRL_AUTOSTOP            BIT(1)
>> +/*
>> + *'1' luminance calculation according to  Y=(R+G+B) x 0.332 (85/256)
>> + *'0' luminance calculation according to Y=16+0.25R+0.5G+0.1094B
>> + */
>> +#define CIF_ISP_EXP_CTRL_MEASMODE_1          BIT(31)
>> +
>> +/* ISP_EXP_H_SIZE */
>> +#define CIF_ISP_EXP_H_SIZE_SET(x)            ((x) & 0x7FF)
>> +#define CIF_ISP_EXP_HEIGHT_MASK                      0x000007FF
>> +/* ISP_EXP_V_SIZE : vertical size must be a multiple of 2). */
>> +#define CIF_ISP_EXP_V_SIZE_SET(x)            ((x) & 0x7FE)
>> +
>> +/* ISP_EXP_H_OFFSET */
>> +#define CIF_ISP_EXP_H_OFFSET_SET(x)          ((x) & 0x1FFF)
>> +#define CIF_ISP_EXP_MAX_HOFFS                        2424
>> +/* ISP_EXP_V_OFFSET */
>> +#define CIF_ISP_EXP_V_OFFSET_SET(x)          ((x) & 0x1FFF)
>> +#define CIF_ISP_EXP_MAX_VOFFS                        1806
>> +
>> +#define CIF_ISP_EXP_ROW_NUM                  5
>> +#define CIF_ISP_EXP_COLUMN_NUM                       5
>> +#define CIF_ISP_EXP_NUM_LUMA_REGS \
>> +     (CIF_ISP_EXP_ROW_NUM * CIF_ISP_EXP_COLUMN_NUM)
>> +#define CIF_ISP_EXP_BLOCK_MAX_HSIZE          516
>> +#define CIF_ISP_EXP_BLOCK_MIN_HSIZE          35
>> +#define CIF_ISP_EXP_BLOCK_MAX_VSIZE          390
>> +#define CIF_ISP_EXP_BLOCK_MIN_VSIZE          28
>> +#define CIF_ISP_EXP_MAX_HSIZE        \
>> +     (CIF_ISP_EXP_BLOCK_MAX_HSIZE * CIF_ISP_EXP_COLUMN_NUM + 1)
>> +#define CIF_ISP_EXP_MIN_HSIZE        \
>> +     (CIF_ISP_EXP_BLOCK_MIN_HSIZE * CIF_ISP_EXP_COLUMN_NUM + 1)
>> +#define CIF_ISP_EXP_MAX_VSIZE        \
>> +     (CIF_ISP_EXP_BLOCK_MAX_VSIZE * CIF_ISP_EXP_ROW_NUM + 1)
>> +#define CIF_ISP_EXP_MIN_VSIZE        \
>> +     (CIF_ISP_EXP_BLOCK_MIN_VSIZE * CIF_ISP_EXP_ROW_NUM + 1)
>> +
>> +/* LSC: ISP_LSC_CTRL */
>> +#define CIF_ISP_LSC_CTRL_ENA                 BIT(0)
>> +#define CIF_ISP_LSC_SECT_SIZE_RESERVED               0xFC00FC00
>> +#define CIF_ISP_LSC_GRAD_RESERVED            0xF000F000
>> +#define CIF_ISP_LSC_SAMPLE_RESERVED          0xF000F000
>> +#define CIF_ISP_LSC_SECTORS_MAX                      16
>> +#define CIF_ISP_LSC_TABLE_DATA(v0, v1)     \
>> +     (((v0) & 0xFFF) | (((v1) & 0xFFF) << 12))
>> +#define CIF_ISP_LSC_SECT_SIZE(v0, v1)      \
>> +     (((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
>> +#define CIF_ISP_LSC_GRAD_SIZE(v0, v1)      \
>> +     (((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
>> +
>> +/* LSC: ISP_LSC_TABLE_SEL */
>> +#define CIF_ISP_LSC_TABLE_0                  0
>> +#define CIF_ISP_LSC_TABLE_1                  1
>> +
>> +/* LSC: ISP_LSC_STATUS */
>> +#define CIF_ISP_LSC_ACTIVE_TABLE             BIT(1)
>> +#define CIF_ISP_LSC_TABLE_ADDRESS_0          0
>> +#define CIF_ISP_LSC_TABLE_ADDRESS_153                153
>> +
>> +/* FLT */
>> +/* ISP_FILT_MODE */
>> +#define CIF_ISP_FLT_ENA                              BIT(0)
>> +
>> +/*
>> + * 0: green filter static mode (active filter factor = FILT_FAC_MID)
>> + * 1: dynamic noise reduction/sharpen Default
>> + */
>> +#define CIF_ISP_FLT_MODE_DNR                 BIT(1)
>> +#define CIF_ISP_FLT_MODE_MAX                 1
>> +#define CIF_ISP_FLT_CHROMA_V_MODE(x)         (((x) & 0x3) << 4)
>> +#define CIF_ISP_FLT_CHROMA_H_MODE(x)         (((x) & 0x3) << 6)
>> +#define CIF_ISP_FLT_CHROMA_MODE_MAX          3
>> +#define CIF_ISP_FLT_GREEN_STAGE1(x)          (((x) & 0xF) << 8)
>> +#define CIF_ISP_FLT_GREEN_STAGE1_MAX         8
>> +#define CIF_ISP_FLT_THREAD_RESERVED          0xFFFFFC00
>> +#define CIF_ISP_FLT_FAC_RESERVED             0xFFFFFFC0
>> +#define CIF_ISP_FLT_LUM_WEIGHT_RESERVED              0xFFF80000
>> +
>> +#define CIF_ISP_CTK_COEFF_RESERVED           0xFFFFF800
>> +#define CIF_ISP_XTALK_OFFSET_RESERVED                0xFFFFF000
>> +
>> +/* GOC */
>> +#define CIF_ISP_GAMMA_OUT_MODE_EQU           BIT(0)
>> +#define CIF_ISP_GOC_MODE_MAX                 1
>> +#define CIF_ISP_GOC_RESERVED                 0xFFFFF800
>> +/* ISP_CTRL BIT 11*/
>> +#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA_READ(x)       (((x) >> 11) & 1)
>> +
>> +/* DPCC */
>> +/* ISP_DPCC_MODE */
>> +#define CIF_ISP_DPCC_ENA                     BIT(0)
>> +#define CIF_ISP_DPCC_MODE_MAX                        0x07
>> +#define CIF_ISP_DPCC_OUTPUTMODE_MAX          0x0F
>> +#define CIF_ISP_DPCC_SETUSE_MAX                      0x0F
>> +#define CIF_ISP_DPCC_METHODS_SET_RESERVED    0xFFFFE000
>> +#define CIF_ISP_DPCC_LINE_THRESH_RESERVED    0xFFFF0000
>> +#define CIF_ISP_DPCC_LINE_MAD_FAC_RESERVED   0xFFFFC0C0
>> +#define CIF_ISP_DPCC_PG_FAC_RESERVED         0xFFFFC0C0
>> +#define CIF_ISP_DPCC_RND_THRESH_RESERVED     0xFFFF0000
>> +#define CIF_ISP_DPCC_RG_FAC_RESERVED         0xFFFFC0C0
>> +#define CIF_ISP_DPCC_RO_LIMIT_RESERVED               0xFFFFF000
>> +#define CIF_ISP_DPCC_RND_OFFS_RESERVED               0xFFFFF000
>> +
>> +/* BLS */
>> +/* ISP_BLS_CTRL */
>> +#define CIF_ISP_BLS_ENA                              BIT(0)
>> +#define CIF_ISP_BLS_MODE_MEASURED            BIT(1)
>> +#define CIF_ISP_BLS_MODE_FIXED                       0
>> +#define CIF_ISP_BLS_WINDOW_1                 (1 << 2)
>> +#define CIF_ISP_BLS_WINDOW_2                 (2 << 2)
>> +
>> +/* GAMMA-IN */
>> +#define CIFISP_DEGAMMA_X_RESERVED    \
>> +     ((1 << 31) | (1 << 27) | (1 << 23) | (1 << 19) |\
>> +     (1 << 15) | (1 << 11) | (1 << 7) | (1 << 3))
>> +#define CIFISP_DEGAMMA_Y_RESERVED               0xFFFFF000
>> +
>> +/* AFM */
>> +#define CIF_ISP_AFM_ENA                              BIT(0)
>> +#define CIF_ISP_AFM_THRES_RESERVED           0xFFFF0000
>> +#define CIF_ISP_AFM_VAR_SHIFT_RESERVED               0xFFF8FFF8
>> +#define CIF_ISP_AFM_WINDOW_X_RESERVED                0xE000
>> +#define CIF_ISP_AFM_WINDOW_Y_RESERVED                0xF000
>> +#define CIF_ISP_AFM_WINDOW_X_MIN             0x5
>> +#define CIF_ISP_AFM_WINDOW_Y_MIN             0x2
>> +#define CIF_ISP_AFM_WINDOW_X(x)                      (((x) & 0x1FFF) << 16)
>> +#define CIF_ISP_AFM_WINDOW_Y(x)                      ((x) & 0x1FFF)
>> +
>> +/* DPF */
>> +#define CIF_ISP_DPF_MODE_EN                  BIT(0)
>> +#define CIF_ISP_DPF_MODE_B_FLT_DIS           BIT(1)
>> +#define CIF_ISP_DPF_MODE_GB_FLT_DIS          BIT(2)
>> +#define CIF_ISP_DPF_MODE_GR_FLT_DIS          BIT(3)
>> +#define CIF_ISP_DPF_MODE_R_FLT_DIS           BIT(4)
>> +#define CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9              BIT(5)
>> +#define CIF_ISP_DPF_MODE_NLL_SEGMENTATION    BIT(6)
>> +#define CIF_ISP_DPF_MODE_AWB_GAIN_COMP               BIT(7)
>> +#define CIF_ISP_DPF_MODE_LSC_GAIN_COMP               BIT(8)
>> +#define CIF_ISP_DPF_MODE_USE_NF_GAIN         BIT(9)
>> +#define CIF_ISP_DPF_NF_GAIN_RESERVED         0xFFFFF000
>> +#define CIF_ISP_DPF_SPATIAL_COEFF_MAX                0x1F
>> +#define CIF_ISP_DPF_NLL_COEFF_N_MAX          0x3FF
>> +
>> +/* =================================================================== */
>> +/*                            CIF Registers                            */
>> +/* =================================================================== */
>> +#define CIF_CTRL_BASE                        0x00000000
>> +#define CIF_CCL                              (CIF_CTRL_BASE + 0x00000000)
>> +#define CIF_VI_ID                    (CIF_CTRL_BASE + 0x00000008)
>> +#define CIF_ICCL                     (CIF_CTRL_BASE + 0x00000010)
>> +#define CIF_IRCL                     (CIF_CTRL_BASE + 0x00000014)
>> +#define CIF_VI_DPCL                  (CIF_CTRL_BASE + 0x00000018)
>> +
>> +#define CIF_IMG_EFF_BASE             0x00000200
>> +#define CIF_IMG_EFF_CTRL             (CIF_IMG_EFF_BASE + 0x00000000)
>> +#define CIF_IMG_EFF_COLOR_SEL                (CIF_IMG_EFF_BASE + 0x00000004)
>> +#define CIF_IMG_EFF_MAT_1            (CIF_IMG_EFF_BASE + 0x00000008)
>> +#define CIF_IMG_EFF_MAT_2            (CIF_IMG_EFF_BASE + 0x0000000C)
>> +#define CIF_IMG_EFF_MAT_3            (CIF_IMG_EFF_BASE + 0x00000010)
>> +#define CIF_IMG_EFF_MAT_4            (CIF_IMG_EFF_BASE + 0x00000014)
>> +#define CIF_IMG_EFF_MAT_5            (CIF_IMG_EFF_BASE + 0x00000018)
>> +#define CIF_IMG_EFF_TINT             (CIF_IMG_EFF_BASE + 0x0000001C)
>> +#define CIF_IMG_EFF_CTRL_SHD         (CIF_IMG_EFF_BASE + 0x00000020)
>> +#define CIF_IMG_EFF_SHARPEN          (CIF_IMG_EFF_BASE + 0x00000024)
>> +
>> +#define CIF_SUPER_IMP_BASE           0x00000300
>> +#define CIF_SUPER_IMP_CTRL           (CIF_SUPER_IMP_BASE + 0x00000000)
>> +#define CIF_SUPER_IMP_OFFSET_X               (CIF_SUPER_IMP_BASE + 0x00000004)
>> +#define CIF_SUPER_IMP_OFFSET_Y               (CIF_SUPER_IMP_BASE + 0x00000008)
>> +#define CIF_SUPER_IMP_COLOR_Y                (CIF_SUPER_IMP_BASE + 0x0000000C)
>> +#define CIF_SUPER_IMP_COLOR_CB               (CIF_SUPER_IMP_BASE + 0x00000010)
>> +#define CIF_SUPER_IMP_COLOR_CR               (CIF_SUPER_IMP_BASE + 0x00000014)
>> +
>> +#define CIF_ISP_BASE                 0x00000400
>> +#define CIF_ISP_CTRL                 (CIF_ISP_BASE + 0x00000000)
>> +#define CIF_ISP_ACQ_PROP             (CIF_ISP_BASE + 0x00000004)
>> +#define CIF_ISP_ACQ_H_OFFS           (CIF_ISP_BASE + 0x00000008)
>> +#define CIF_ISP_ACQ_V_OFFS           (CIF_ISP_BASE + 0x0000000C)
>> +#define CIF_ISP_ACQ_H_SIZE           (CIF_ISP_BASE + 0x00000010)
>> +#define CIF_ISP_ACQ_V_SIZE           (CIF_ISP_BASE + 0x00000014)
>> +#define CIF_ISP_ACQ_NR_FRAMES                (CIF_ISP_BASE + 0x00000018)
>> +#define CIF_ISP_GAMMA_DX_LO          (CIF_ISP_BASE + 0x0000001C)
>> +#define CIF_ISP_GAMMA_DX_HI          (CIF_ISP_BASE + 0x00000020)
>> +#define CIF_ISP_GAMMA_R_Y0           (CIF_ISP_BASE + 0x00000024)
>> +#define CIF_ISP_GAMMA_R_Y1           (CIF_ISP_BASE + 0x00000028)
>> +#define CIF_ISP_GAMMA_R_Y2           (CIF_ISP_BASE + 0x0000002C)
>> +#define CIF_ISP_GAMMA_R_Y3           (CIF_ISP_BASE + 0x00000030)
>> +#define CIF_ISP_GAMMA_R_Y4           (CIF_ISP_BASE + 0x00000034)
>> +#define CIF_ISP_GAMMA_R_Y5           (CIF_ISP_BASE + 0x00000038)
>> +#define CIF_ISP_GAMMA_R_Y6           (CIF_ISP_BASE + 0x0000003C)
>> +#define CIF_ISP_GAMMA_R_Y7           (CIF_ISP_BASE + 0x00000040)
>> +#define CIF_ISP_GAMMA_R_Y8           (CIF_ISP_BASE + 0x00000044)
>> +#define CIF_ISP_GAMMA_R_Y9           (CIF_ISP_BASE + 0x00000048)
>> +#define CIF_ISP_GAMMA_R_Y10          (CIF_ISP_BASE + 0x0000004C)
>> +#define CIF_ISP_GAMMA_R_Y11          (CIF_ISP_BASE + 0x00000050)
>> +#define CIF_ISP_GAMMA_R_Y12          (CIF_ISP_BASE + 0x00000054)
>> +#define CIF_ISP_GAMMA_R_Y13          (CIF_ISP_BASE + 0x00000058)
>> +#define CIF_ISP_GAMMA_R_Y14          (CIF_ISP_BASE + 0x0000005C)
>> +#define CIF_ISP_GAMMA_R_Y15          (CIF_ISP_BASE + 0x00000060)
>> +#define CIF_ISP_GAMMA_R_Y16          (CIF_ISP_BASE + 0x00000064)
>> +#define CIF_ISP_GAMMA_G_Y0           (CIF_ISP_BASE + 0x00000068)
>> +#define CIF_ISP_GAMMA_G_Y1           (CIF_ISP_BASE + 0x0000006C)
>> +#define CIF_ISP_GAMMA_G_Y2           (CIF_ISP_BASE + 0x00000070)
>> +#define CIF_ISP_GAMMA_G_Y3           (CIF_ISP_BASE + 0x00000074)
>> +#define CIF_ISP_GAMMA_G_Y4           (CIF_ISP_BASE + 0x00000078)
>> +#define CIF_ISP_GAMMA_G_Y5           (CIF_ISP_BASE + 0x0000007C)
>> +#define CIF_ISP_GAMMA_G_Y6           (CIF_ISP_BASE + 0x00000080)
>> +#define CIF_ISP_GAMMA_G_Y7           (CIF_ISP_BASE + 0x00000084)
>> +#define CIF_ISP_GAMMA_G_Y8           (CIF_ISP_BASE + 0x00000088)
>> +#define CIF_ISP_GAMMA_G_Y9           (CIF_ISP_BASE + 0x0000008C)
>> +#define CIF_ISP_GAMMA_G_Y10          (CIF_ISP_BASE + 0x00000090)
>> +#define CIF_ISP_GAMMA_G_Y11          (CIF_ISP_BASE + 0x00000094)
>> +#define CIF_ISP_GAMMA_G_Y12          (CIF_ISP_BASE + 0x00000098)
>> +#define CIF_ISP_GAMMA_G_Y13          (CIF_ISP_BASE + 0x0000009C)
>> +#define CIF_ISP_GAMMA_G_Y14          (CIF_ISP_BASE + 0x000000A0)
>> +#define CIF_ISP_GAMMA_G_Y15          (CIF_ISP_BASE + 0x000000A4)
>> +#define CIF_ISP_GAMMA_G_Y16          (CIF_ISP_BASE + 0x000000A8)
>> +#define CIF_ISP_GAMMA_B_Y0           (CIF_ISP_BASE + 0x000000AC)
>> +#define CIF_ISP_GAMMA_B_Y1           (CIF_ISP_BASE + 0x000000B0)
>> +#define CIF_ISP_GAMMA_B_Y2           (CIF_ISP_BASE + 0x000000B4)
>> +#define CIF_ISP_GAMMA_B_Y3           (CIF_ISP_BASE + 0x000000B8)
>> +#define CIF_ISP_GAMMA_B_Y4           (CIF_ISP_BASE + 0x000000BC)
>> +#define CIF_ISP_GAMMA_B_Y5           (CIF_ISP_BASE + 0x000000C0)
>> +#define CIF_ISP_GAMMA_B_Y6           (CIF_ISP_BASE + 0x000000C4)
>> +#define CIF_ISP_GAMMA_B_Y7           (CIF_ISP_BASE + 0x000000C8)
>> +#define CIF_ISP_GAMMA_B_Y8           (CIF_ISP_BASE + 0x000000CC)
>> +#define CIF_ISP_GAMMA_B_Y9           (CIF_ISP_BASE + 0x000000D0)
>> +#define CIF_ISP_GAMMA_B_Y10          (CIF_ISP_BASE + 0x000000D4)
>> +#define CIF_ISP_GAMMA_B_Y11          (CIF_ISP_BASE + 0x000000D8)
>> +#define CIF_ISP_GAMMA_B_Y12          (CIF_ISP_BASE + 0x000000DC)
>> +#define CIF_ISP_GAMMA_B_Y13          (CIF_ISP_BASE + 0x000000E0)
>> +#define CIF_ISP_GAMMA_B_Y14          (CIF_ISP_BASE + 0x000000E4)
>> +#define CIF_ISP_GAMMA_B_Y15          (CIF_ISP_BASE + 0x000000E8)
>> +#define CIF_ISP_GAMMA_B_Y16          (CIF_ISP_BASE + 0x000000EC)
>> +#define CIF_ISP_AWB_PROP             (CIF_ISP_BASE + 0x00000110)
>> +#define CIF_ISP_AWB_WND_H_OFFS               (CIF_ISP_BASE + 0x00000114)
>> +#define CIF_ISP_AWB_WND_V_OFFS               (CIF_ISP_BASE + 0x00000118)
>> +#define CIF_ISP_AWB_WND_H_SIZE               (CIF_ISP_BASE + 0x0000011C)
>> +#define CIF_ISP_AWB_WND_V_SIZE               (CIF_ISP_BASE + 0x00000120)
>> +#define CIF_ISP_AWB_FRAMES           (CIF_ISP_BASE + 0x00000124)
>> +#define CIF_ISP_AWB_REF                      (CIF_ISP_BASE + 0x00000128)
>> +#define CIF_ISP_AWB_THRESH           (CIF_ISP_BASE + 0x0000012C)
>> +#define CIF_ISP_AWB_GAIN_G           (CIF_ISP_BASE + 0x00000138)
>> +#define CIF_ISP_AWB_GAIN_RB          (CIF_ISP_BASE + 0x0000013C)
>> +#define CIF_ISP_AWB_WHITE_CNT                (CIF_ISP_BASE + 0x00000140)
>> +#define CIF_ISP_AWB_MEAN             (CIF_ISP_BASE + 0x00000144)
>> +#define CIF_ISP_CC_COEFF_0           (CIF_ISP_BASE + 0x00000170)
>> +#define CIF_ISP_CC_COEFF_1           (CIF_ISP_BASE + 0x00000174)
>> +#define CIF_ISP_CC_COEFF_2           (CIF_ISP_BASE + 0x00000178)
>> +#define CIF_ISP_CC_COEFF_3           (CIF_ISP_BASE + 0x0000017C)
>> +#define CIF_ISP_CC_COEFF_4           (CIF_ISP_BASE + 0x00000180)
>> +#define CIF_ISP_CC_COEFF_5           (CIF_ISP_BASE + 0x00000184)
>> +#define CIF_ISP_CC_COEFF_6           (CIF_ISP_BASE + 0x00000188)
>> +#define CIF_ISP_CC_COEFF_7           (CIF_ISP_BASE + 0x0000018C)
>> +#define CIF_ISP_CC_COEFF_8           (CIF_ISP_BASE + 0x00000190)
>> +#define CIF_ISP_OUT_H_OFFS           (CIF_ISP_BASE + 0x00000194)
>> +#define CIF_ISP_OUT_V_OFFS           (CIF_ISP_BASE + 0x00000198)
>> +#define CIF_ISP_OUT_H_SIZE           (CIF_ISP_BASE + 0x0000019C)
>> +#define CIF_ISP_OUT_V_SIZE           (CIF_ISP_BASE + 0x000001A0)
>> +#define CIF_ISP_DEMOSAIC             (CIF_ISP_BASE + 0x000001A4)
>> +#define CIF_ISP_FLAGS_SHD            (CIF_ISP_BASE + 0x000001A8)
>> +#define CIF_ISP_OUT_H_OFFS_SHD               (CIF_ISP_BASE + 0x000001AC)
>> +#define CIF_ISP_OUT_V_OFFS_SHD               (CIF_ISP_BASE + 0x000001B0)
>> +#define CIF_ISP_OUT_H_SIZE_SHD               (CIF_ISP_BASE + 0x000001B4)
>> +#define CIF_ISP_OUT_V_SIZE_SHD               (CIF_ISP_BASE + 0x000001B8)
>> +#define CIF_ISP_IMSC                 (CIF_ISP_BASE + 0x000001BC)
>> +#define CIF_ISP_RIS                  (CIF_ISP_BASE + 0x000001C0)
>> +#define CIF_ISP_MIS                  (CIF_ISP_BASE + 0x000001C4)
>> +#define CIF_ISP_ICR                  (CIF_ISP_BASE + 0x000001C8)
>> +#define CIF_ISP_ISR                  (CIF_ISP_BASE + 0x000001CC)
>> +#define CIF_ISP_CT_COEFF_0           (CIF_ISP_BASE + 0x000001D0)
>> +#define CIF_ISP_CT_COEFF_1           (CIF_ISP_BASE + 0x000001D4)
>> +#define CIF_ISP_CT_COEFF_2           (CIF_ISP_BASE + 0x000001D8)
>> +#define CIF_ISP_CT_COEFF_3           (CIF_ISP_BASE + 0x000001DC)
>> +#define CIF_ISP_CT_COEFF_4           (CIF_ISP_BASE + 0x000001E0)
>> +#define CIF_ISP_CT_COEFF_5           (CIF_ISP_BASE + 0x000001E4)
>> +#define CIF_ISP_CT_COEFF_6           (CIF_ISP_BASE + 0x000001E8)
>> +#define CIF_ISP_CT_COEFF_7           (CIF_ISP_BASE + 0x000001EC)
>> +#define CIF_ISP_CT_COEFF_8           (CIF_ISP_BASE + 0x000001F0)
>> +#define CIF_ISP_GAMMA_OUT_MODE               (CIF_ISP_BASE + 0x000001F4)
>> +#define CIF_ISP_GAMMA_OUT_Y_0                (CIF_ISP_BASE + 0x000001F8)
>> +#define CIF_ISP_GAMMA_OUT_Y_1                (CIF_ISP_BASE + 0x000001FC)
>> +#define CIF_ISP_GAMMA_OUT_Y_2                (CIF_ISP_BASE + 0x00000200)
>> +#define CIF_ISP_GAMMA_OUT_Y_3                (CIF_ISP_BASE + 0x00000204)
>> +#define CIF_ISP_GAMMA_OUT_Y_4                (CIF_ISP_BASE + 0x00000208)
>> +#define CIF_ISP_GAMMA_OUT_Y_5                (CIF_ISP_BASE + 0x0000020C)
>> +#define CIF_ISP_GAMMA_OUT_Y_6                (CIF_ISP_BASE + 0x00000210)
>> +#define CIF_ISP_GAMMA_OUT_Y_7                (CIF_ISP_BASE + 0x00000214)
>> +#define CIF_ISP_GAMMA_OUT_Y_8                (CIF_ISP_BASE + 0x00000218)
>> +#define CIF_ISP_GAMMA_OUT_Y_9                (CIF_ISP_BASE + 0x0000021C)
>> +#define CIF_ISP_GAMMA_OUT_Y_10               (CIF_ISP_BASE + 0x00000220)
>> +#define CIF_ISP_GAMMA_OUT_Y_11               (CIF_ISP_BASE + 0x00000224)
>> +#define CIF_ISP_GAMMA_OUT_Y_12               (CIF_ISP_BASE + 0x00000228)
>> +#define CIF_ISP_GAMMA_OUT_Y_13               (CIF_ISP_BASE + 0x0000022C)
>> +#define CIF_ISP_GAMMA_OUT_Y_14               (CIF_ISP_BASE + 0x00000230)
>> +#define CIF_ISP_GAMMA_OUT_Y_15               (CIF_ISP_BASE + 0x00000234)
>> +#define CIF_ISP_GAMMA_OUT_Y_16               (CIF_ISP_BASE + 0x00000238)
>> +#define CIF_ISP_ERR                  (CIF_ISP_BASE + 0x0000023C)
>> +#define CIF_ISP_ERR_CLR                      (CIF_ISP_BASE + 0x00000240)
>> +#define CIF_ISP_FRAME_COUNT          (CIF_ISP_BASE + 0x00000244)
>> +#define CIF_ISP_CT_OFFSET_R          (CIF_ISP_BASE + 0x00000248)
>> +#define CIF_ISP_CT_OFFSET_G          (CIF_ISP_BASE + 0x0000024C)
>> +#define CIF_ISP_CT_OFFSET_B          (CIF_ISP_BASE + 0x00000250)
>> +
>> +#define CIF_ISP_FLASH_BASE           0x00000660
>> +#define CIF_ISP_FLASH_CMD            (CIF_ISP_FLASH_BASE + 0x00000000)
>> +#define CIF_ISP_FLASH_CONFIG         (CIF_ISP_FLASH_BASE + 0x00000004)
>> +#define CIF_ISP_FLASH_PREDIV         (CIF_ISP_FLASH_BASE + 0x00000008)
>> +#define CIF_ISP_FLASH_DELAY          (CIF_ISP_FLASH_BASE + 0x0000000C)
>> +#define CIF_ISP_FLASH_TIME           (CIF_ISP_FLASH_BASE + 0x00000010)
>> +#define CIF_ISP_FLASH_MAXP           (CIF_ISP_FLASH_BASE + 0x00000014)
>> +
>> +#define CIF_ISP_SH_BASE                      0x00000680
>> +#define CIF_ISP_SH_CTRL                      (CIF_ISP_SH_BASE + 0x00000000)
>> +#define CIF_ISP_SH_PREDIV            (CIF_ISP_SH_BASE + 0x00000004)
>> +#define CIF_ISP_SH_DELAY             (CIF_ISP_SH_BASE + 0x00000008)
>> +#define CIF_ISP_SH_TIME                      (CIF_ISP_SH_BASE + 0x0000000C)
>> +
>> +#define CIF_C_PROC_BASE                      0x00000800
>> +#define CIF_C_PROC_CTRL                      (CIF_C_PROC_BASE + 0x00000000)
>> +#define CIF_C_PROC_CONTRAST          (CIF_C_PROC_BASE + 0x00000004)
>> +#define CIF_C_PROC_BRIGHTNESS                (CIF_C_PROC_BASE + 0x00000008)
>> +#define CIF_C_PROC_SATURATION                (CIF_C_PROC_BASE + 0x0000000C)
>> +#define CIF_C_PROC_HUE                       (CIF_C_PROC_BASE + 0x00000010)
>> +
>> +#define CIF_DUAL_CROP_BASE           0x00000880
>> +#define CIF_DUAL_CROP_CTRL           (CIF_DUAL_CROP_BASE + 0x00000000)
>> +#define CIF_DUAL_CROP_M_H_OFFS               (CIF_DUAL_CROP_BASE + 0x00000004)
>> +#define CIF_DUAL_CROP_M_V_OFFS               (CIF_DUAL_CROP_BASE + 0x00000008)
>> +#define CIF_DUAL_CROP_M_H_SIZE               (CIF_DUAL_CROP_BASE + 0x0000000C)
>> +#define CIF_DUAL_CROP_M_V_SIZE               (CIF_DUAL_CROP_BASE + 0x00000010)
>> +#define CIF_DUAL_CROP_S_H_OFFS               (CIF_DUAL_CROP_BASE + 0x00000014)
>> +#define CIF_DUAL_CROP_S_V_OFFS               (CIF_DUAL_CROP_BASE + 0x00000018)
>> +#define CIF_DUAL_CROP_S_H_SIZE               (CIF_DUAL_CROP_BASE + 0x0000001C)
>> +#define CIF_DUAL_CROP_S_V_SIZE               (CIF_DUAL_CROP_BASE + 0x00000020)
>> +#define CIF_DUAL_CROP_M_H_OFFS_SHD   (CIF_DUAL_CROP_BASE + 0x00000024)
>> +#define CIF_DUAL_CROP_M_V_OFFS_SHD   (CIF_DUAL_CROP_BASE + 0x00000028)
>> +#define CIF_DUAL_CROP_M_H_SIZE_SHD   (CIF_DUAL_CROP_BASE + 0x0000002C)
>> +#define CIF_DUAL_CROP_M_V_SIZE_SHD   (CIF_DUAL_CROP_BASE + 0x00000030)
>> +#define CIF_DUAL_CROP_S_H_OFFS_SHD   (CIF_DUAL_CROP_BASE + 0x00000034)
>> +#define CIF_DUAL_CROP_S_V_OFFS_SHD   (CIF_DUAL_CROP_BASE + 0x00000038)
>> +#define CIF_DUAL_CROP_S_H_SIZE_SHD   (CIF_DUAL_CROP_BASE + 0x0000003C)
>> +#define CIF_DUAL_CROP_S_V_SIZE_SHD   (CIF_DUAL_CROP_BASE + 0x00000040)
>> +
>> +#define CIF_MRSZ_BASE                        0x00000C00
>> +#define CIF_MRSZ_CTRL                        (CIF_MRSZ_BASE + 0x00000000)
>> +#define CIF_MRSZ_SCALE_HY            (CIF_MRSZ_BASE + 0x00000004)
>> +#define CIF_MRSZ_SCALE_HCB           (CIF_MRSZ_BASE + 0x00000008)
>> +#define CIF_MRSZ_SCALE_HCR           (CIF_MRSZ_BASE + 0x0000000C)
>> +#define CIF_MRSZ_SCALE_VY            (CIF_MRSZ_BASE + 0x00000010)
>> +#define CIF_MRSZ_SCALE_VC            (CIF_MRSZ_BASE + 0x00000014)
>> +#define CIF_MRSZ_PHASE_HY            (CIF_MRSZ_BASE + 0x00000018)
>> +#define CIF_MRSZ_PHASE_HC            (CIF_MRSZ_BASE + 0x0000001C)
>> +#define CIF_MRSZ_PHASE_VY            (CIF_MRSZ_BASE + 0x00000020)
>> +#define CIF_MRSZ_PHASE_VC            (CIF_MRSZ_BASE + 0x00000024)
>> +#define CIF_MRSZ_SCALE_LUT_ADDR              (CIF_MRSZ_BASE + 0x00000028)
>> +#define CIF_MRSZ_SCALE_LUT           (CIF_MRSZ_BASE + 0x0000002C)
>> +#define CIF_MRSZ_CTRL_SHD            (CIF_MRSZ_BASE + 0x00000030)
>> +#define CIF_MRSZ_SCALE_HY_SHD                (CIF_MRSZ_BASE + 0x00000034)
>> +#define CIF_MRSZ_SCALE_HCB_SHD               (CIF_MRSZ_BASE + 0x00000038)
>> +#define CIF_MRSZ_SCALE_HCR_SHD               (CIF_MRSZ_BASE + 0x0000003C)
>> +#define CIF_MRSZ_SCALE_VY_SHD                (CIF_MRSZ_BASE + 0x00000040)
>> +#define CIF_MRSZ_SCALE_VC_SHD                (CIF_MRSZ_BASE + 0x00000044)
>> +#define CIF_MRSZ_PHASE_HY_SHD                (CIF_MRSZ_BASE + 0x00000048)
>> +#define CIF_MRSZ_PHASE_HC_SHD                (CIF_MRSZ_BASE + 0x0000004C)
>> +#define CIF_MRSZ_PHASE_VY_SHD                (CIF_MRSZ_BASE + 0x00000050)
>> +#define CIF_MRSZ_PHASE_VC_SHD                (CIF_MRSZ_BASE + 0x00000054)
>> +
>> +#define CIF_SRSZ_BASE                        0x00001000
>> +#define CIF_SRSZ_CTRL                        (CIF_SRSZ_BASE + 0x00000000)
>> +#define CIF_SRSZ_SCALE_HY            (CIF_SRSZ_BASE + 0x00000004)
>> +#define CIF_SRSZ_SCALE_HCB           (CIF_SRSZ_BASE + 0x00000008)
>> +#define CIF_SRSZ_SCALE_HCR           (CIF_SRSZ_BASE + 0x0000000C)
>> +#define CIF_SRSZ_SCALE_VY            (CIF_SRSZ_BASE + 0x00000010)
>> +#define CIF_SRSZ_SCALE_VC            (CIF_SRSZ_BASE + 0x00000014)
>> +#define CIF_SRSZ_PHASE_HY            (CIF_SRSZ_BASE + 0x00000018)
>> +#define CIF_SRSZ_PHASE_HC            (CIF_SRSZ_BASE + 0x0000001C)
>> +#define CIF_SRSZ_PHASE_VY            (CIF_SRSZ_BASE + 0x00000020)
>> +#define CIF_SRSZ_PHASE_VC            (CIF_SRSZ_BASE + 0x00000024)
>> +#define CIF_SRSZ_SCALE_LUT_ADDR              (CIF_SRSZ_BASE + 0x00000028)
>> +#define CIF_SRSZ_SCALE_LUT           (CIF_SRSZ_BASE + 0x0000002C)
>> +#define CIF_SRSZ_CTRL_SHD            (CIF_SRSZ_BASE + 0x00000030)
>> +#define CIF_SRSZ_SCALE_HY_SHD                (CIF_SRSZ_BASE + 0x00000034)
>> +#define CIF_SRSZ_SCALE_HCB_SHD               (CIF_SRSZ_BASE + 0x00000038)
>> +#define CIF_SRSZ_SCALE_HCR_SHD               (CIF_SRSZ_BASE + 0x0000003C)
>> +#define CIF_SRSZ_SCALE_VY_SHD                (CIF_SRSZ_BASE + 0x00000040)
>> +#define CIF_SRSZ_SCALE_VC_SHD                (CIF_SRSZ_BASE + 0x00000044)
>> +#define CIF_SRSZ_PHASE_HY_SHD                (CIF_SRSZ_BASE + 0x00000048)
>> +#define CIF_SRSZ_PHASE_HC_SHD                (CIF_SRSZ_BASE + 0x0000004C)
>> +#define CIF_SRSZ_PHASE_VY_SHD                (CIF_SRSZ_BASE + 0x00000050)
>> +#define CIF_SRSZ_PHASE_VC_SHD                (CIF_SRSZ_BASE + 0x00000054)
>> +
>> +#define CIF_MI_BASE                  0x00001400
>> +#define CIF_MI_CTRL                  (CIF_MI_BASE + 0x00000000)
>> +#define CIF_MI_INIT                  (CIF_MI_BASE + 0x00000004)
>> +#define CIF_MI_MP_Y_BASE_AD_INIT     (CIF_MI_BASE + 0x00000008)
>> +#define CIF_MI_MP_Y_SIZE_INIT                (CIF_MI_BASE + 0x0000000C)
>> +#define CIF_MI_MP_Y_OFFS_CNT_INIT    (CIF_MI_BASE + 0x00000010)
>> +#define CIF_MI_MP_Y_OFFS_CNT_START   (CIF_MI_BASE + 0x00000014)
>> +#define CIF_MI_MP_Y_IRQ_OFFS_INIT    (CIF_MI_BASE + 0x00000018)
>> +#define CIF_MI_MP_CB_BASE_AD_INIT    (CIF_MI_BASE + 0x0000001C)
>> +#define CIF_MI_MP_CB_SIZE_INIT               (CIF_MI_BASE + 0x00000020)
>> +#define CIF_MI_MP_CB_OFFS_CNT_INIT   (CIF_MI_BASE + 0x00000024)
>> +#define CIF_MI_MP_CB_OFFS_CNT_START  (CIF_MI_BASE + 0x00000028)
>> +#define CIF_MI_MP_CR_BASE_AD_INIT    (CIF_MI_BASE + 0x0000002C)
>> +#define CIF_MI_MP_CR_SIZE_INIT               (CIF_MI_BASE + 0x00000030)
>> +#define CIF_MI_MP_CR_OFFS_CNT_INIT   (CIF_MI_BASE + 0x00000034)
>> +#define CIF_MI_MP_CR_OFFS_CNT_START  (CIF_MI_BASE + 0x00000038)
>> +#define CIF_MI_SP_Y_BASE_AD_INIT     (CIF_MI_BASE + 0x0000003C)
>> +#define CIF_MI_SP_Y_SIZE_INIT                (CIF_MI_BASE + 0x00000040)
>> +#define CIF_MI_SP_Y_OFFS_CNT_INIT    (CIF_MI_BASE + 0x00000044)
>> +#define CIF_MI_SP_Y_OFFS_CNT_START   (CIF_MI_BASE + 0x00000048)
>> +#define CIF_MI_SP_Y_LLENGTH          (CIF_MI_BASE + 0x0000004C)
>> +#define CIF_MI_SP_CB_BASE_AD_INIT    (CIF_MI_BASE + 0x00000050)
>> +#define CIF_MI_SP_CB_SIZE_INIT               (CIF_MI_BASE + 0x00000054)
>> +#define CIF_MI_SP_CB_OFFS_CNT_INIT   (CIF_MI_BASE + 0x00000058)
>> +#define CIF_MI_SP_CB_OFFS_CNT_START  (CIF_MI_BASE + 0x0000005C)
>> +#define CIF_MI_SP_CR_BASE_AD_INIT    (CIF_MI_BASE + 0x00000060)
>> +#define CIF_MI_SP_CR_SIZE_INIT               (CIF_MI_BASE + 0x00000064)
>> +#define CIF_MI_SP_CR_OFFS_CNT_INIT   (CIF_MI_BASE + 0x00000068)
>> +#define CIF_MI_SP_CR_OFFS_CNT_START  (CIF_MI_BASE + 0x0000006C)
>> +#define CIF_MI_BYTE_CNT                      (CIF_MI_BASE + 0x00000070)
>> +#define CIF_MI_CTRL_SHD                      (CIF_MI_BASE + 0x00000074)
>> +#define CIF_MI_MP_Y_BASE_AD_SHD              (CIF_MI_BASE + 0x00000078)
>> +#define CIF_MI_MP_Y_SIZE_SHD         (CIF_MI_BASE + 0x0000007C)
>> +#define CIF_MI_MP_Y_OFFS_CNT_SHD     (CIF_MI_BASE + 0x00000080)
>> +#define CIF_MI_MP_Y_IRQ_OFFS_SHD     (CIF_MI_BASE + 0x00000084)
>> +#define CIF_MI_MP_CB_BASE_AD_SHD     (CIF_MI_BASE + 0x00000088)
>> +#define CIF_MI_MP_CB_SIZE_SHD                (CIF_MI_BASE + 0x0000008C)
>> +#define CIF_MI_MP_CB_OFFS_CNT_SHD    (CIF_MI_BASE + 0x00000090)
>> +#define CIF_MI_MP_CR_BASE_AD_SHD     (CIF_MI_BASE + 0x00000094)
>> +#define CIF_MI_MP_CR_SIZE_SHD                (CIF_MI_BASE + 0x00000098)
>> +#define CIF_MI_MP_CR_OFFS_CNT_SHD    (CIF_MI_BASE + 0x0000009C)
>> +#define CIF_MI_SP_Y_BASE_AD_SHD              (CIF_MI_BASE + 0x000000A0)
>> +#define CIF_MI_SP_Y_SIZE_SHD         (CIF_MI_BASE + 0x000000A4)
>> +#define CIF_MI_SP_Y_OFFS_CNT_SHD     (CIF_MI_BASE + 0x000000A8)
>> +#define CIF_MI_SP_CB_BASE_AD_SHD     (CIF_MI_BASE + 0x000000B0)
>> +#define CIF_MI_SP_CB_SIZE_SHD                (CIF_MI_BASE + 0x000000B4)
>> +#define CIF_MI_SP_CB_OFFS_CNT_SHD    (CIF_MI_BASE + 0x000000B8)
>> +#define CIF_MI_SP_CR_BASE_AD_SHD     (CIF_MI_BASE + 0x000000BC)
>> +#define CIF_MI_SP_CR_SIZE_SHD                (CIF_MI_BASE + 0x000000C0)
>> +#define CIF_MI_SP_CR_OFFS_CNT_SHD    (CIF_MI_BASE + 0x000000C4)
>> +#define CIF_MI_DMA_Y_PIC_START_AD    (CIF_MI_BASE + 0x000000C8)
>> +#define CIF_MI_DMA_Y_PIC_WIDTH               (CIF_MI_BASE + 0x000000CC)
>> +#define CIF_MI_DMA_Y_LLENGTH         (CIF_MI_BASE + 0x000000D0)
>> +#define CIF_MI_DMA_Y_PIC_SIZE                (CIF_MI_BASE + 0x000000D4)
>> +#define CIF_MI_DMA_CB_PIC_START_AD   (CIF_MI_BASE + 0x000000D8)
>> +#define CIF_MI_DMA_CR_PIC_START_AD   (CIF_MI_BASE + 0x000000E8)
>> +#define CIF_MI_IMSC                  (CIF_MI_BASE + 0x000000F8)
>> +#define CIF_MI_RIS                   (CIF_MI_BASE + 0x000000FC)
>> +#define CIF_MI_MIS                   (CIF_MI_BASE + 0x00000100)
>> +#define CIF_MI_ICR                   (CIF_MI_BASE + 0x00000104)
>> +#define CIF_MI_ISR                   (CIF_MI_BASE + 0x00000108)
>> +#define CIF_MI_STATUS                        (CIF_MI_BASE + 0x0000010C)
>> +#define CIF_MI_STATUS_CLR            (CIF_MI_BASE + 0x00000110)
>> +#define CIF_MI_SP_Y_PIC_WIDTH                (CIF_MI_BASE + 0x00000114)
>> +#define CIF_MI_SP_Y_PIC_HEIGHT               (CIF_MI_BASE + 0x00000118)
>> +#define CIF_MI_SP_Y_PIC_SIZE         (CIF_MI_BASE + 0x0000011C)
>> +#define CIF_MI_DMA_CTRL                      (CIF_MI_BASE + 0x00000120)
>> +#define CIF_MI_DMA_START             (CIF_MI_BASE + 0x00000124)
>> +#define CIF_MI_DMA_STATUS            (CIF_MI_BASE + 0x00000128)
>> +#define CIF_MI_PIXEL_COUNT           (CIF_MI_BASE + 0x0000012C)
>> +#define CIF_MI_MP_Y_BASE_AD_INIT2    (CIF_MI_BASE + 0x00000130)
>> +#define CIF_MI_MP_CB_BASE_AD_INIT2   (CIF_MI_BASE + 0x00000134)
>> +#define CIF_MI_MP_CR_BASE_AD_INIT2   (CIF_MI_BASE + 0x00000138)
>> +#define CIF_MI_SP_Y_BASE_AD_INIT2    (CIF_MI_BASE + 0x0000013C)
>> +#define CIF_MI_SP_CB_BASE_AD_INIT2   (CIF_MI_BASE + 0x00000140)
>> +#define CIF_MI_SP_CR_BASE_AD_INIT2   (CIF_MI_BASE + 0x00000144)
>> +#define CIF_MI_XTD_FORMAT_CTRL               (CIF_MI_BASE + 0x00000148)
>> +
>> +#define CIF_SMIA_BASE                        0x00001A00
>> +#define CIF_SMIA_CTRL                        (CIF_SMIA_BASE + 0x00000000)
>> +#define CIF_SMIA_STATUS                      (CIF_SMIA_BASE + 0x00000004)
>> +#define CIF_SMIA_IMSC                        (CIF_SMIA_BASE + 0x00000008)
>> +#define CIF_SMIA_RIS                 (CIF_SMIA_BASE + 0x0000000C)
>> +#define CIF_SMIA_MIS                 (CIF_SMIA_BASE + 0x00000010)
>> +#define CIF_SMIA_ICR                 (CIF_SMIA_BASE + 0x00000014)
>> +#define CIF_SMIA_ISR                 (CIF_SMIA_BASE + 0x00000018)
>> +#define CIF_SMIA_DATA_FORMAT_SEL     (CIF_SMIA_BASE + 0x0000001C)
>> +#define CIF_SMIA_SOF_EMB_DATA_LINES  (CIF_SMIA_BASE + 0x00000020)
>> +#define CIF_SMIA_EMB_HSTART          (CIF_SMIA_BASE + 0x00000024)
>> +#define CIF_SMIA_EMB_HSIZE           (CIF_SMIA_BASE + 0x00000028)
>> +#define CIF_SMIA_EMB_VSTART          (CIF_SMIA_BASE + 0x0000002c)
>> +#define CIF_SMIA_NUM_LINES           (CIF_SMIA_BASE + 0x00000030)
>> +#define CIF_SMIA_EMB_DATA_FIFO               (CIF_SMIA_BASE + 0x00000034)
>> +#define CIF_SMIA_EMB_DATA_WATERMARK  (CIF_SMIA_BASE + 0x00000038)
>> +
>> +#define CIF_MIPI_BASE                        0x00001C00
>> +#define CIF_MIPI_CTRL                        (CIF_MIPI_BASE + 0x00000000)
>> +#define CIF_MIPI_STATUS                      (CIF_MIPI_BASE + 0x00000004)
>> +#define CIF_MIPI_IMSC                        (CIF_MIPI_BASE + 0x00000008)
>> +#define CIF_MIPI_RIS                 (CIF_MIPI_BASE + 0x0000000C)
>> +#define CIF_MIPI_MIS                 (CIF_MIPI_BASE + 0x00000010)
>> +#define CIF_MIPI_ICR                 (CIF_MIPI_BASE + 0x00000014)
>> +#define CIF_MIPI_ISR                 (CIF_MIPI_BASE + 0x00000018)
>> +#define CIF_MIPI_CUR_DATA_ID         (CIF_MIPI_BASE + 0x0000001C)
>> +#define CIF_MIPI_IMG_DATA_SEL                (CIF_MIPI_BASE + 0x00000020)
>> +#define CIF_MIPI_ADD_DATA_SEL_1              (CIF_MIPI_BASE + 0x00000024)
>> +#define CIF_MIPI_ADD_DATA_SEL_2              (CIF_MIPI_BASE + 0x00000028)
>> +#define CIF_MIPI_ADD_DATA_SEL_3              (CIF_MIPI_BASE + 0x0000002C)
>> +#define CIF_MIPI_ADD_DATA_SEL_4              (CIF_MIPI_BASE + 0x00000030)
>> +#define CIF_MIPI_ADD_DATA_FIFO               (CIF_MIPI_BASE + 0x00000034)
>> +#define CIF_MIPI_FIFO_FILL_LEVEL     (CIF_MIPI_BASE + 0x00000038)
>> +#define CIF_MIPI_COMPRESSED_MODE     (CIF_MIPI_BASE + 0x0000003C)
>> +#define CIF_MIPI_FRAME                       (CIF_MIPI_BASE + 0x00000040)
>> +#define CIF_MIPI_GEN_SHORT_DT                (CIF_MIPI_BASE + 0x00000044)
>> +#define CIF_MIPI_GEN_SHORT_8_9               (CIF_MIPI_BASE + 0x00000048)
>> +#define CIF_MIPI_GEN_SHORT_A_B               (CIF_MIPI_BASE + 0x0000004C)
>> +#define CIF_MIPI_GEN_SHORT_C_D               (CIF_MIPI_BASE + 0x00000050)
>> +#define CIF_MIPI_GEN_SHORT_E_F               (CIF_MIPI_BASE + 0x00000054)
>> +
>> +#define CIF_ISP_AFM_BASE             0x00002000
>> +#define CIF_ISP_AFM_CTRL             (CIF_ISP_AFM_BASE + 0x00000000)
>> +#define CIF_ISP_AFM_LT_A             (CIF_ISP_AFM_BASE + 0x00000004)
>> +#define CIF_ISP_AFM_RB_A             (CIF_ISP_AFM_BASE + 0x00000008)
>> +#define CIF_ISP_AFM_LT_B             (CIF_ISP_AFM_BASE + 0x0000000C)
>> +#define CIF_ISP_AFM_RB_B             (CIF_ISP_AFM_BASE + 0x00000010)
>> +#define CIF_ISP_AFM_LT_C             (CIF_ISP_AFM_BASE + 0x00000014)
>> +#define CIF_ISP_AFM_RB_C             (CIF_ISP_AFM_BASE + 0x00000018)
>> +#define CIF_ISP_AFM_THRES            (CIF_ISP_AFM_BASE + 0x0000001C)
>> +#define CIF_ISP_AFM_VAR_SHIFT                (CIF_ISP_AFM_BASE + 0x00000020)
>> +#define CIF_ISP_AFM_SUM_A            (CIF_ISP_AFM_BASE + 0x00000024)
>> +#define CIF_ISP_AFM_SUM_B            (CIF_ISP_AFM_BASE + 0x00000028)
>> +#define CIF_ISP_AFM_SUM_C            (CIF_ISP_AFM_BASE + 0x0000002C)
>> +#define CIF_ISP_AFM_LUM_A            (CIF_ISP_AFM_BASE + 0x00000030)
>> +#define CIF_ISP_AFM_LUM_B            (CIF_ISP_AFM_BASE + 0x00000034)
>> +#define CIF_ISP_AFM_LUM_C            (CIF_ISP_AFM_BASE + 0x00000038)
>> +
>> +#define CIF_ISP_LSC_BASE             0x00002200
>> +#define CIF_ISP_LSC_CTRL             (CIF_ISP_LSC_BASE + 0x00000000)
>> +#define CIF_ISP_LSC_R_TABLE_ADDR     (CIF_ISP_LSC_BASE + 0x00000004)
>> +#define CIF_ISP_LSC_GR_TABLE_ADDR    (CIF_ISP_LSC_BASE + 0x00000008)
>> +#define CIF_ISP_LSC_B_TABLE_ADDR     (CIF_ISP_LSC_BASE + 0x0000000C)
>> +#define CIF_ISP_LSC_GB_TABLE_ADDR    (CIF_ISP_LSC_BASE + 0x00000010)
>> +#define CIF_ISP_LSC_R_TABLE_DATA     (CIF_ISP_LSC_BASE + 0x00000014)
>> +#define CIF_ISP_LSC_GR_TABLE_DATA    (CIF_ISP_LSC_BASE + 0x00000018)
>> +#define CIF_ISP_LSC_B_TABLE_DATA     (CIF_ISP_LSC_BASE + 0x0000001C)
>> +#define CIF_ISP_LSC_GB_TABLE_DATA    (CIF_ISP_LSC_BASE + 0x00000020)
>> +#define CIF_ISP_LSC_XGRAD_01         (CIF_ISP_LSC_BASE + 0x00000024)
>> +#define CIF_ISP_LSC_XGRAD_23         (CIF_ISP_LSC_BASE + 0x00000028)
>> +#define CIF_ISP_LSC_XGRAD_45         (CIF_ISP_LSC_BASE + 0x0000002C)
>> +#define CIF_ISP_LSC_XGRAD_67         (CIF_ISP_LSC_BASE + 0x00000030)
>> +#define CIF_ISP_LSC_YGRAD_01         (CIF_ISP_LSC_BASE + 0x00000034)
>> +#define CIF_ISP_LSC_YGRAD_23         (CIF_ISP_LSC_BASE + 0x00000038)
>> +#define CIF_ISP_LSC_YGRAD_45         (CIF_ISP_LSC_BASE + 0x0000003C)
>> +#define CIF_ISP_LSC_YGRAD_67         (CIF_ISP_LSC_BASE + 0x00000040)
>> +#define CIF_ISP_LSC_XSIZE_01         (CIF_ISP_LSC_BASE + 0x00000044)
>> +#define CIF_ISP_LSC_XSIZE_23         (CIF_ISP_LSC_BASE + 0x00000048)
>> +#define CIF_ISP_LSC_XSIZE_45         (CIF_ISP_LSC_BASE + 0x0000004C)
>> +#define CIF_ISP_LSC_XSIZE_67         (CIF_ISP_LSC_BASE + 0x00000050)
>> +#define CIF_ISP_LSC_YSIZE_01         (CIF_ISP_LSC_BASE + 0x00000054)
>> +#define CIF_ISP_LSC_YSIZE_23         (CIF_ISP_LSC_BASE + 0x00000058)
>> +#define CIF_ISP_LSC_YSIZE_45         (CIF_ISP_LSC_BASE + 0x0000005C)
>> +#define CIF_ISP_LSC_YSIZE_67         (CIF_ISP_LSC_BASE + 0x00000060)
>> +#define CIF_ISP_LSC_TABLE_SEL                (CIF_ISP_LSC_BASE + 0x00000064)
>> +#define CIF_ISP_LSC_STATUS           (CIF_ISP_LSC_BASE + 0x00000068)
>> +
>> +#define CIF_ISP_IS_BASE                      0x00002300
>> +#define CIF_ISP_IS_CTRL                      (CIF_ISP_IS_BASE + 0x00000000)
>> +#define CIF_ISP_IS_RECENTER          (CIF_ISP_IS_BASE + 0x00000004)
>> +#define CIF_ISP_IS_H_OFFS            (CIF_ISP_IS_BASE + 0x00000008)
>> +#define CIF_ISP_IS_V_OFFS            (CIF_ISP_IS_BASE + 0x0000000C)
>> +#define CIF_ISP_IS_H_SIZE            (CIF_ISP_IS_BASE + 0x00000010)
>> +#define CIF_ISP_IS_V_SIZE            (CIF_ISP_IS_BASE + 0x00000014)
>> +#define CIF_ISP_IS_MAX_DX            (CIF_ISP_IS_BASE + 0x00000018)
>> +#define CIF_ISP_IS_MAX_DY            (CIF_ISP_IS_BASE + 0x0000001C)
>> +#define CIF_ISP_IS_DISPLACE          (CIF_ISP_IS_BASE + 0x00000020)
>> +#define CIF_ISP_IS_H_OFFS_SHD                (CIF_ISP_IS_BASE + 0x00000024)
>> +#define CIF_ISP_IS_V_OFFS_SHD                (CIF_ISP_IS_BASE + 0x00000028)
>> +#define CIF_ISP_IS_H_SIZE_SHD                (CIF_ISP_IS_BASE + 0x0000002C)
>> +#define CIF_ISP_IS_V_SIZE_SHD                (CIF_ISP_IS_BASE + 0x00000030)
>> +
>> +#define CIF_ISP_HIST_BASE            0x00002400
>> +
>> +#define CIF_ISP_HIST_PROP            (CIF_ISP_HIST_BASE + 0x00000000)
>> +#define CIF_ISP_HIST_H_OFFS          (CIF_ISP_HIST_BASE + 0x00000004)
>> +#define CIF_ISP_HIST_V_OFFS          (CIF_ISP_HIST_BASE + 0x00000008)
>> +#define CIF_ISP_HIST_H_SIZE          (CIF_ISP_HIST_BASE + 0x0000000C)
>> +#define CIF_ISP_HIST_V_SIZE          (CIF_ISP_HIST_BASE + 0x00000010)
>> +#define CIF_ISP_HIST_BIN_0           (CIF_ISP_HIST_BASE + 0x00000014)
>> +#define CIF_ISP_HIST_BIN_1           (CIF_ISP_HIST_BASE + 0x00000018)
>> +#define CIF_ISP_HIST_BIN_2           (CIF_ISP_HIST_BASE + 0x0000001C)
>> +#define CIF_ISP_HIST_BIN_3           (CIF_ISP_HIST_BASE + 0x00000020)
>> +#define CIF_ISP_HIST_BIN_4           (CIF_ISP_HIST_BASE + 0x00000024)
>> +#define CIF_ISP_HIST_BIN_5           (CIF_ISP_HIST_BASE + 0x00000028)
>> +#define CIF_ISP_HIST_BIN_6           (CIF_ISP_HIST_BASE + 0x0000002C)
>> +#define CIF_ISP_HIST_BIN_7           (CIF_ISP_HIST_BASE + 0x00000030)
>> +#define CIF_ISP_HIST_BIN_8           (CIF_ISP_HIST_BASE + 0x00000034)
>> +#define CIF_ISP_HIST_BIN_9           (CIF_ISP_HIST_BASE + 0x00000038)
>> +#define CIF_ISP_HIST_BIN_10          (CIF_ISP_HIST_BASE + 0x0000003C)
>> +#define CIF_ISP_HIST_BIN_11          (CIF_ISP_HIST_BASE + 0x00000040)
>> +#define CIF_ISP_HIST_BIN_12          (CIF_ISP_HIST_BASE + 0x00000044)
>> +#define CIF_ISP_HIST_BIN_13          (CIF_ISP_HIST_BASE + 0x00000048)
>> +#define CIF_ISP_HIST_BIN_14          (CIF_ISP_HIST_BASE + 0x0000004C)
>> +#define CIF_ISP_HIST_BIN_15          (CIF_ISP_HIST_BASE + 0x00000050)
>> +#define CIF_ISP_HIST_WEIGHT_00TO30   (CIF_ISP_HIST_BASE + 0x00000054)
>> +#define CIF_ISP_HIST_WEIGHT_40TO21   (CIF_ISP_HIST_BASE + 0x00000058)
>> +#define CIF_ISP_HIST_WEIGHT_31TO12   (CIF_ISP_HIST_BASE + 0x0000005C)
>> +#define CIF_ISP_HIST_WEIGHT_22TO03   (CIF_ISP_HIST_BASE + 0x00000060)
>> +#define CIF_ISP_HIST_WEIGHT_13TO43   (CIF_ISP_HIST_BASE + 0x00000064)
>> +#define CIF_ISP_HIST_WEIGHT_04TO34   (CIF_ISP_HIST_BASE + 0x00000068)
>> +#define CIF_ISP_HIST_WEIGHT_44               (CIF_ISP_HIST_BASE + 0x0000006C)
>> +
>> +#define CIF_ISP_FILT_BASE            0x00002500
>> +#define CIF_ISP_FILT_MODE            (CIF_ISP_FILT_BASE + 0x00000000)
>> +#define CIF_ISP_FILT_THRESH_BL0              (CIF_ISP_FILT_BASE + 0x00000028)
>> +#define CIF_ISP_FILT_THRESH_BL1              (CIF_ISP_FILT_BASE + 0x0000002c)
>> +#define CIF_ISP_FILT_THRESH_SH0              (CIF_ISP_FILT_BASE + 0x00000030)
>> +#define CIF_ISP_FILT_THRESH_SH1              (CIF_ISP_FILT_BASE + 0x00000034)
>> +#define CIF_ISP_FILT_LUM_WEIGHT              (CIF_ISP_FILT_BASE + 0x00000038)
>> +#define CIF_ISP_FILT_FAC_SH1         (CIF_ISP_FILT_BASE + 0x0000003c)
>> +#define CIF_ISP_FILT_FAC_SH0         (CIF_ISP_FILT_BASE + 0x00000040)
>> +#define CIF_ISP_FILT_FAC_MID         (CIF_ISP_FILT_BASE + 0x00000044)
>> +#define CIF_ISP_FILT_FAC_BL0         (CIF_ISP_FILT_BASE + 0x00000048)
>> +#define CIF_ISP_FILT_FAC_BL1         (CIF_ISP_FILT_BASE + 0x0000004C)
>> +
>> +#define CIF_ISP_CAC_BASE             0x00002580
>> +#define CIF_ISP_CAC_CTRL             (CIF_ISP_CAC_BASE + 0x00000000)
>> +#define CIF_ISP_CAC_COUNT_START              (CIF_ISP_CAC_BASE + 0x00000004)
>> +#define CIF_ISP_CAC_A                        (CIF_ISP_CAC_BASE + 0x00000008)
>> +#define CIF_ISP_CAC_B                        (CIF_ISP_CAC_BASE + 0x0000000C)
>> +#define CIF_ISP_CAC_C                        (CIF_ISP_CAC_BASE + 0x00000010)
>> +#define CIF_ISP_X_NORM                       (CIF_ISP_CAC_BASE + 0x00000014)
>> +#define CIF_ISP_Y_NORM                       (CIF_ISP_CAC_BASE + 0x00000018)
>> +
>> +#define CIF_ISP_EXP_BASE             0x00002600
>> +#define CIF_ISP_EXP_CTRL             (CIF_ISP_EXP_BASE + 0x00000000)
>> +#define CIF_ISP_EXP_H_OFFSET         (CIF_ISP_EXP_BASE + 0x00000004)
>> +#define CIF_ISP_EXP_V_OFFSET         (CIF_ISP_EXP_BASE + 0x00000008)
>> +#define CIF_ISP_EXP_H_SIZE           (CIF_ISP_EXP_BASE + 0x0000000C)
>> +#define CIF_ISP_EXP_V_SIZE           (CIF_ISP_EXP_BASE + 0x00000010)
>> +#define CIF_ISP_EXP_MEAN_00          (CIF_ISP_EXP_BASE + 0x00000014)
>> +#define CIF_ISP_EXP_MEAN_10          (CIF_ISP_EXP_BASE + 0x00000018)
>> +#define CIF_ISP_EXP_MEAN_20          (CIF_ISP_EXP_BASE + 0x0000001c)
>> +#define CIF_ISP_EXP_MEAN_30          (CIF_ISP_EXP_BASE + 0x00000020)
>> +#define CIF_ISP_EXP_MEAN_40          (CIF_ISP_EXP_BASE + 0x00000024)
>> +#define CIF_ISP_EXP_MEAN_01          (CIF_ISP_EXP_BASE + 0x00000028)
>> +#define CIF_ISP_EXP_MEAN_11          (CIF_ISP_EXP_BASE + 0x0000002c)
>> +#define CIF_ISP_EXP_MEAN_21          (CIF_ISP_EXP_BASE + 0x00000030)
>> +#define CIF_ISP_EXP_MEAN_31          (CIF_ISP_EXP_BASE + 0x00000034)
>> +#define CIF_ISP_EXP_MEAN_41          (CIF_ISP_EXP_BASE + 0x00000038)
>> +#define CIF_ISP_EXP_MEAN_02          (CIF_ISP_EXP_BASE + 0x0000003c)
>> +#define CIF_ISP_EXP_MEAN_12          (CIF_ISP_EXP_BASE + 0x00000040)
>> +#define CIF_ISP_EXP_MEAN_22          (CIF_ISP_EXP_BASE + 0x00000044)
>> +#define CIF_ISP_EXP_MEAN_32          (CIF_ISP_EXP_BASE + 0x00000048)
>> +#define CIF_ISP_EXP_MEAN_42          (CIF_ISP_EXP_BASE + 0x0000004c)
>> +#define CIF_ISP_EXP_MEAN_03          (CIF_ISP_EXP_BASE + 0x00000050)
>> +#define CIF_ISP_EXP_MEAN_13          (CIF_ISP_EXP_BASE + 0x00000054)
>> +#define CIF_ISP_EXP_MEAN_23          (CIF_ISP_EXP_BASE + 0x00000058)
>> +#define CIF_ISP_EXP_MEAN_33          (CIF_ISP_EXP_BASE + 0x0000005c)
>> +#define CIF_ISP_EXP_MEAN_43          (CIF_ISP_EXP_BASE + 0x00000060)
>> +#define CIF_ISP_EXP_MEAN_04          (CIF_ISP_EXP_BASE + 0x00000064)
>> +#define CIF_ISP_EXP_MEAN_14          (CIF_ISP_EXP_BASE + 0x00000068)
>> +#define CIF_ISP_EXP_MEAN_24          (CIF_ISP_EXP_BASE + 0x0000006c)
>> +#define CIF_ISP_EXP_MEAN_34          (CIF_ISP_EXP_BASE + 0x00000070)
>> +#define CIF_ISP_EXP_MEAN_44          (CIF_ISP_EXP_BASE + 0x00000074)
>> +
>> +#define CIF_ISP_BLS_BASE             0x00002700
>> +#define CIF_ISP_BLS_CTRL             (CIF_ISP_BLS_BASE + 0x00000000)
>> +#define CIF_ISP_BLS_SAMPLES          (CIF_ISP_BLS_BASE + 0x00000004)
>> +#define CIF_ISP_BLS_H1_START         (CIF_ISP_BLS_BASE + 0x00000008)
>> +#define CIF_ISP_BLS_H1_STOP          (CIF_ISP_BLS_BASE + 0x0000000c)
>> +#define CIF_ISP_BLS_V1_START         (CIF_ISP_BLS_BASE + 0x00000010)
>> +#define CIF_ISP_BLS_V1_STOP          (CIF_ISP_BLS_BASE + 0x00000014)
>> +#define CIF_ISP_BLS_H2_START         (CIF_ISP_BLS_BASE + 0x00000018)
>> +#define CIF_ISP_BLS_H2_STOP          (CIF_ISP_BLS_BASE + 0x0000001c)
>> +#define CIF_ISP_BLS_V2_START         (CIF_ISP_BLS_BASE + 0x00000020)
>> +#define CIF_ISP_BLS_V2_STOP          (CIF_ISP_BLS_BASE + 0x00000024)
>> +#define CIF_ISP_BLS_A_FIXED          (CIF_ISP_BLS_BASE + 0x00000028)
>> +#define CIF_ISP_BLS_B_FIXED          (CIF_ISP_BLS_BASE + 0x0000002c)
>> +#define CIF_ISP_BLS_C_FIXED          (CIF_ISP_BLS_BASE + 0x00000030)
>> +#define CIF_ISP_BLS_D_FIXED          (CIF_ISP_BLS_BASE + 0x00000034)
>> +#define CIF_ISP_BLS_A_MEASURED               (CIF_ISP_BLS_BASE + 0x00000038)
>> +#define CIF_ISP_BLS_B_MEASURED               (CIF_ISP_BLS_BASE + 0x0000003c)
>> +#define CIF_ISP_BLS_C_MEASURED               (CIF_ISP_BLS_BASE + 0x00000040)
>> +#define CIF_ISP_BLS_D_MEASURED               (CIF_ISP_BLS_BASE + 0x00000044)
>> +
>> +#define CIF_ISP_DPF_BASE             0x00002800
>> +#define CIF_ISP_DPF_MODE             (CIF_ISP_DPF_BASE + 0x00000000)
>> +#define CIF_ISP_DPF_STRENGTH_R               (CIF_ISP_DPF_BASE + 0x00000004)
>> +#define CIF_ISP_DPF_STRENGTH_G               (CIF_ISP_DPF_BASE + 0x00000008)
>> +#define CIF_ISP_DPF_STRENGTH_B               (CIF_ISP_DPF_BASE + 0x0000000C)
>> +#define CIF_ISP_DPF_S_WEIGHT_G_1_4   (CIF_ISP_DPF_BASE + 0x00000010)
>> +#define CIF_ISP_DPF_S_WEIGHT_G_5_6   (CIF_ISP_DPF_BASE + 0x00000014)
>> +#define CIF_ISP_DPF_S_WEIGHT_RB_1_4  (CIF_ISP_DPF_BASE + 0x00000018)
>> +#define CIF_ISP_DPF_S_WEIGHT_RB_5_6  (CIF_ISP_DPF_BASE + 0x0000001C)
>> +#define CIF_ISP_DPF_NULL_COEFF_0     (CIF_ISP_DPF_BASE + 0x00000020)
>> +#define CIF_ISP_DPF_NULL_COEFF_1     (CIF_ISP_DPF_BASE + 0x00000024)
>> +#define CIF_ISP_DPF_NULL_COEFF_2     (CIF_ISP_DPF_BASE + 0x00000028)
>> +#define CIF_ISP_DPF_NULL_COEFF_3     (CIF_ISP_DPF_BASE + 0x0000002C)
>> +#define CIF_ISP_DPF_NULL_COEFF_4     (CIF_ISP_DPF_BASE + 0x00000030)
>> +#define CIF_ISP_DPF_NULL_COEFF_5     (CIF_ISP_DPF_BASE + 0x00000034)
>> +#define CIF_ISP_DPF_NULL_COEFF_6     (CIF_ISP_DPF_BASE + 0x00000038)
>> +#define CIF_ISP_DPF_NULL_COEFF_7     (CIF_ISP_DPF_BASE + 0x0000003C)
>> +#define CIF_ISP_DPF_NULL_COEFF_8     (CIF_ISP_DPF_BASE + 0x00000040)
>> +#define CIF_ISP_DPF_NULL_COEFF_9     (CIF_ISP_DPF_BASE + 0x00000044)
>> +#define CIF_ISP_DPF_NULL_COEFF_10    (CIF_ISP_DPF_BASE + 0x00000048)
>> +#define CIF_ISP_DPF_NULL_COEFF_11    (CIF_ISP_DPF_BASE + 0x0000004C)
>> +#define CIF_ISP_DPF_NULL_COEFF_12    (CIF_ISP_DPF_BASE + 0x00000050)
>> +#define CIF_ISP_DPF_NULL_COEFF_13    (CIF_ISP_DPF_BASE + 0x00000054)
>> +#define CIF_ISP_DPF_NULL_COEFF_14    (CIF_ISP_DPF_BASE + 0x00000058)
>> +#define CIF_ISP_DPF_NULL_COEFF_15    (CIF_ISP_DPF_BASE + 0x0000005C)
>> +#define CIF_ISP_DPF_NULL_COEFF_16    (CIF_ISP_DPF_BASE + 0x00000060)
>> +#define CIF_ISP_DPF_NF_GAIN_R                (CIF_ISP_DPF_BASE + 0x00000064)
>> +#define CIF_ISP_DPF_NF_GAIN_GR               (CIF_ISP_DPF_BASE + 0x00000068)
>> +#define CIF_ISP_DPF_NF_GAIN_GB               (CIF_ISP_DPF_BASE + 0x0000006C)
>> +#define CIF_ISP_DPF_NF_GAIN_B                (CIF_ISP_DPF_BASE + 0x00000070)
>> +
>> +#define CIF_ISP_DPCC_BASE            0x00002900
>> +#define CIF_ISP_DPCC_MODE            (CIF_ISP_DPCC_BASE + 0x00000000)
>> +#define CIF_ISP_DPCC_OUTPUT_MODE     (CIF_ISP_DPCC_BASE + 0x00000004)
>> +#define CIF_ISP_DPCC_SET_USE         (CIF_ISP_DPCC_BASE + 0x00000008)
>> +#define CIF_ISP_DPCC_METHODS_SET_1   (CIF_ISP_DPCC_BASE + 0x0000000C)
>> +#define CIF_ISP_DPCC_METHODS_SET_2   (CIF_ISP_DPCC_BASE + 0x00000010)
>> +#define CIF_ISP_DPCC_METHODS_SET_3   (CIF_ISP_DPCC_BASE + 0x00000014)
>> +#define CIF_ISP_DPCC_LINE_THRESH_1   (CIF_ISP_DPCC_BASE + 0x00000018)
>> +#define CIF_ISP_DPCC_LINE_MAD_FAC_1  (CIF_ISP_DPCC_BASE + 0x0000001C)
>> +#define CIF_ISP_DPCC_PG_FAC_1                (CIF_ISP_DPCC_BASE + 0x00000020)
>> +#define CIF_ISP_DPCC_RND_THRESH_1    (CIF_ISP_DPCC_BASE + 0x00000024)
>> +#define CIF_ISP_DPCC_RG_FAC_1                (CIF_ISP_DPCC_BASE + 0x00000028)
>> +#define CIF_ISP_DPCC_LINE_THRESH_2   (CIF_ISP_DPCC_BASE + 0x0000002C)
>> +#define CIF_ISP_DPCC_LINE_MAD_FAC_2  (CIF_ISP_DPCC_BASE + 0x00000030)
>> +#define CIF_ISP_DPCC_PG_FAC_2                (CIF_ISP_DPCC_BASE + 0x00000034)
>> +#define CIF_ISP_DPCC_RND_THRESH_2    (CIF_ISP_DPCC_BASE + 0x00000038)
>> +#define CIF_ISP_DPCC_RG_FAC_2                (CIF_ISP_DPCC_BASE + 0x0000003C)
>> +#define CIF_ISP_DPCC_LINE_THRESH_3   (CIF_ISP_DPCC_BASE + 0x00000040)
>> +#define CIF_ISP_DPCC_LINE_MAD_FAC_3  (CIF_ISP_DPCC_BASE + 0x00000044)
>> +#define CIF_ISP_DPCC_PG_FAC_3                (CIF_ISP_DPCC_BASE + 0x00000048)
>> +#define CIF_ISP_DPCC_RND_THRESH_3    (CIF_ISP_DPCC_BASE + 0x0000004C)
>> +#define CIF_ISP_DPCC_RG_FAC_3                (CIF_ISP_DPCC_BASE + 0x00000050)
>> +#define CIF_ISP_DPCC_RO_LIMITS               (CIF_ISP_DPCC_BASE + 0x00000054)
>> +#define CIF_ISP_DPCC_RND_OFFS                (CIF_ISP_DPCC_BASE + 0x00000058)
>> +#define CIF_ISP_DPCC_BPT_CTRL                (CIF_ISP_DPCC_BASE + 0x0000005C)
>> +#define CIF_ISP_DPCC_BPT_NUMBER              (CIF_ISP_DPCC_BASE + 0x00000060)
>> +#define CIF_ISP_DPCC_BPT_ADDR                (CIF_ISP_DPCC_BASE + 0x00000064)
>> +#define CIF_ISP_DPCC_BPT_DATA                (CIF_ISP_DPCC_BASE + 0x00000068)
>> +
>> +#define CIF_ISP_WDR_BASE             0x00002A00
>> +#define CIF_ISP_WDR_CTRL             (CIF_ISP_WDR_BASE + 0x00000000)
>> +#define CIF_ISP_WDR_TONECURVE_1              (CIF_ISP_WDR_BASE + 0x00000004)
>> +#define CIF_ISP_WDR_TONECURVE_2              (CIF_ISP_WDR_BASE + 0x00000008)
>> +#define CIF_ISP_WDR_TONECURVE_3              (CIF_ISP_WDR_BASE + 0x0000000C)
>> +#define CIF_ISP_WDR_TONECURVE_4              (CIF_ISP_WDR_BASE + 0x00000010)
>> +#define CIF_ISP_WDR_TONECURVE_YM_0   (CIF_ISP_WDR_BASE + 0x00000014)
>> +#define CIF_ISP_WDR_TONECURVE_YM_1   (CIF_ISP_WDR_BASE + 0x00000018)
>> +#define CIF_ISP_WDR_TONECURVE_YM_2   (CIF_ISP_WDR_BASE + 0x0000001C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_3   (CIF_ISP_WDR_BASE + 0x00000020)
>> +#define CIF_ISP_WDR_TONECURVE_YM_4   (CIF_ISP_WDR_BASE + 0x00000024)
>> +#define CIF_ISP_WDR_TONECURVE_YM_5   (CIF_ISP_WDR_BASE + 0x00000028)
>> +#define CIF_ISP_WDR_TONECURVE_YM_6   (CIF_ISP_WDR_BASE + 0x0000002C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_7   (CIF_ISP_WDR_BASE + 0x00000030)
>> +#define CIF_ISP_WDR_TONECURVE_YM_8   (CIF_ISP_WDR_BASE + 0x00000034)
>> +#define CIF_ISP_WDR_TONECURVE_YM_9   (CIF_ISP_WDR_BASE + 0x00000038)
>> +#define CIF_ISP_WDR_TONECURVE_YM_10  (CIF_ISP_WDR_BASE + 0x0000003C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_11  (CIF_ISP_WDR_BASE + 0x00000040)
>> +#define CIF_ISP_WDR_TONECURVE_YM_12  (CIF_ISP_WDR_BASE + 0x00000044)
>> +#define CIF_ISP_WDR_TONECURVE_YM_13  (CIF_ISP_WDR_BASE + 0x00000048)
>> +#define CIF_ISP_WDR_TONECURVE_YM_14  (CIF_ISP_WDR_BASE + 0x0000004C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_15  (CIF_ISP_WDR_BASE + 0x00000050)
>> +#define CIF_ISP_WDR_TONECURVE_YM_16  (CIF_ISP_WDR_BASE + 0x00000054)
>> +#define CIF_ISP_WDR_TONECURVE_YM_17  (CIF_ISP_WDR_BASE + 0x00000058)
>> +#define CIF_ISP_WDR_TONECURVE_YM_18  (CIF_ISP_WDR_BASE + 0x0000005C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_19  (CIF_ISP_WDR_BASE + 0x00000060)
>> +#define CIF_ISP_WDR_TONECURVE_YM_20  (CIF_ISP_WDR_BASE + 0x00000064)
>> +#define CIF_ISP_WDR_TONECURVE_YM_21  (CIF_ISP_WDR_BASE + 0x00000068)
>> +#define CIF_ISP_WDR_TONECURVE_YM_22  (CIF_ISP_WDR_BASE + 0x0000006C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_23  (CIF_ISP_WDR_BASE + 0x00000070)
>> +#define CIF_ISP_WDR_TONECURVE_YM_24  (CIF_ISP_WDR_BASE + 0x00000074)
>> +#define CIF_ISP_WDR_TONECURVE_YM_25  (CIF_ISP_WDR_BASE + 0x00000078)
>> +#define CIF_ISP_WDR_TONECURVE_YM_26  (CIF_ISP_WDR_BASE + 0x0000007C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_27  (CIF_ISP_WDR_BASE + 0x00000080)
>> +#define CIF_ISP_WDR_TONECURVE_YM_28  (CIF_ISP_WDR_BASE + 0x00000084)
>> +#define CIF_ISP_WDR_TONECURVE_YM_29  (CIF_ISP_WDR_BASE + 0x00000088)
>> +#define CIF_ISP_WDR_TONECURVE_YM_30  (CIF_ISP_WDR_BASE + 0x0000008C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_31  (CIF_ISP_WDR_BASE + 0x00000090)
>> +#define CIF_ISP_WDR_TONECURVE_YM_32  (CIF_ISP_WDR_BASE + 0x00000094)
>> +#define CIF_ISP_WDR_OFFSET           (CIF_ISP_WDR_BASE + 0x00000098)
>> +#define CIF_ISP_WDR_DELTAMIN         (CIF_ISP_WDR_BASE + 0x0000009C)
>> +#define CIF_ISP_WDR_TONECURVE_1_SHD  (CIF_ISP_WDR_BASE + 0x000000A0)
>> +#define CIF_ISP_WDR_TONECURVE_2_SHD  (CIF_ISP_WDR_BASE + 0x000000A4)
>> +#define CIF_ISP_WDR_TONECURVE_3_SHD  (CIF_ISP_WDR_BASE + 0x000000A8)
>> +#define CIF_ISP_WDR_TONECURVE_4_SHD  (CIF_ISP_WDR_BASE + 0x000000AC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_0_SHD       (CIF_ISP_WDR_BASE + 0x000000B0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_1_SHD       (CIF_ISP_WDR_BASE + 0x000000B4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_2_SHD       (CIF_ISP_WDR_BASE + 0x000000B8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_3_SHD       (CIF_ISP_WDR_BASE + 0x000000BC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_4_SHD       (CIF_ISP_WDR_BASE + 0x000000C0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_5_SHD       (CIF_ISP_WDR_BASE + 0x000000C4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_6_SHD       (CIF_ISP_WDR_BASE + 0x000000C8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_7_SHD       (CIF_ISP_WDR_BASE + 0x000000CC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_8_SHD       (CIF_ISP_WDR_BASE + 0x000000D0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_9_SHD       (CIF_ISP_WDR_BASE + 0x000000D4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_10_SHD      (CIF_ISP_WDR_BASE + 0x000000D8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_11_SHD      (CIF_ISP_WDR_BASE + 0x000000DC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_12_SHD      (CIF_ISP_WDR_BASE + 0x000000E0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_13_SHD      (CIF_ISP_WDR_BASE + 0x000000E4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_14_SHD      (CIF_ISP_WDR_BASE + 0x000000E8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_15_SHD      (CIF_ISP_WDR_BASE + 0x000000EC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_16_SHD      (CIF_ISP_WDR_BASE + 0x000000F0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_17_SHD      (CIF_ISP_WDR_BASE + 0x000000F4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_18_SHD      (CIF_ISP_WDR_BASE + 0x000000F8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_19_SHD      (CIF_ISP_WDR_BASE + 0x000000FC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_20_SHD      (CIF_ISP_WDR_BASE + 0x00000100)
>> +#define CIF_ISP_WDR_TONECURVE_YM_21_SHD      (CIF_ISP_WDR_BASE + 0x00000104)
>> +#define CIF_ISP_WDR_TONECURVE_YM_22_SHD      (CIF_ISP_WDR_BASE + 0x00000108)
>> +#define CIF_ISP_WDR_TONECURVE_YM_23_SHD      (CIF_ISP_WDR_BASE + 0x0000010C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_24_SHD      (CIF_ISP_WDR_BASE + 0x00000110)
>> +#define CIF_ISP_WDR_TONECURVE_YM_25_SHD      (CIF_ISP_WDR_BASE + 0x00000114)
>> +#define CIF_ISP_WDR_TONECURVE_YM_26_SHD      (CIF_ISP_WDR_BASE + 0x00000118)
>> +#define CIF_ISP_WDR_TONECURVE_YM_27_SHD      (CIF_ISP_WDR_BASE + 0x0000011C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_28_SHD      (CIF_ISP_WDR_BASE + 0x00000120)
>> +#define CIF_ISP_WDR_TONECURVE_YM_29_SHD      (CIF_ISP_WDR_BASE + 0x00000124)
>> +#define CIF_ISP_WDR_TONECURVE_YM_30_SHD      (CIF_ISP_WDR_BASE + 0x00000128)
>> +#define CIF_ISP_WDR_TONECURVE_YM_31_SHD      (CIF_ISP_WDR_BASE + 0x0000012C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_32_SHD      (CIF_ISP_WDR_BASE + 0x00000130)
>> +
>> +#define CIF_ISP_VSM_BASE             0x00002F00
>> +#define CIF_ISP_VSM_MODE             (CIF_ISP_VSM_BASE + 0x00000000)
>> +#define CIF_ISP_VSM_H_OFFS           (CIF_ISP_VSM_BASE + 0x00000004)
>> +#define CIF_ISP_VSM_V_OFFS           (CIF_ISP_VSM_BASE + 0x00000008)
>> +#define CIF_ISP_VSM_H_SIZE           (CIF_ISP_VSM_BASE + 0x0000000C)
>> +#define CIF_ISP_VSM_V_SIZE           (CIF_ISP_VSM_BASE + 0x00000010)
>> +#define CIF_ISP_VSM_H_SEGMENTS               (CIF_ISP_VSM_BASE + 0x00000014)
>> +#define CIF_ISP_VSM_V_SEGMENTS               (CIF_ISP_VSM_BASE + 0x00000018)
>> +#define CIF_ISP_VSM_DELTA_H          (CIF_ISP_VSM_BASE + 0x0000001C)
>> +#define CIF_ISP_VSM_DELTA_V          (CIF_ISP_VSM_BASE + 0x00000020)
>> +
>> +void disable_dcrop(struct rkisp1_stream *stream, bool async);
>> +void config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect,
>> +               bool async);
>> +
>> +void dump_rsz_regs(struct rkisp1_stream *stream);
>> +void disable_rsz(struct rkisp1_stream *stream, bool async);
>> +void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
>> +             struct v4l2_rect *in_c, struct v4l2_rect *out_y,
>> +             struct v4l2_rect *out_c, bool async);
>> +
>> +void config_mi_ctrl(struct rkisp1_stream *stream);
>> +
>> +void mp_clr_frame_end_int(void __iomem *base);
>> +void sp_clr_frame_end_int(void __iomem *base);
>> +
>> +bool mp_is_frame_end_int_masked(void __iomem *base);
>> +bool sp_is_frame_end_int_masked(void __iomem *base);
>> +bool mp_is_stream_stopped(void __iomem *base);
>> +bool sp_is_stream_stopped(void __iomem *base);
>> +
>> +static inline void mi_set_y_size(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.y_size_init);
>> +}
>> +
>> +static inline void mi_set_cb_size(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.cb_size_init);
>> +}
>> +
>> +static inline void mi_set_cr_size(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.cr_size_init);
>> +}
>> +
>> +static inline void mi_set_y_addr(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.y_base_ad_init);
>> +}
>> +
>> +static inline void mi_set_cb_addr(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.cb_base_ad_init);
>> +}
>> +
>> +static inline void mi_set_cr_addr(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.cr_base_ad_init);
>> +}
>> +
>> +static inline void mi_set_y_offset(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.y_offs_cnt_init);
>> +}
>> +
>> +static inline void mi_set_cb_offset(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.cb_offs_cnt_init);
>> +}
>> +
>> +static inline void mi_set_cr_offset(struct rkisp1_stream *stream, int val)
>> +{
>> +     void __iomem *base = stream->ispdev->base_addr;
>> +
>> +     writel(val, base + stream->config->mi.cr_offs_cnt_init);
>> +}
>> +
>> +static inline void mp_set_chain_mode(void __iomem *base)
>> +{
>> +     u32 dpcl = readl(base + CIF_VI_DPCL);
>> +
>> +     dpcl |= CIF_VI_DPCL_CHAN_MODE_MP;
>> +     writel(dpcl, base + CIF_VI_DPCL);
>> +}
>> +
>> +static inline void sp_set_chain_mode(void __iomem *base)
>> +{
>> +     u32 dpcl = readl(base + CIF_VI_DPCL);
>> +
>> +     dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
>> +     writel(dpcl, base + CIF_VI_DPCL);
>> +}
>> +
>> +static inline void mp_set_data_path(void __iomem *base)
>> +{
>> +     u32 dpcl = readl(base + CIF_VI_DPCL);
>> +
>> +     dpcl = dpcl | CIF_VI_DPCL_CHAN_MODE_MP | CIF_VI_DPCL_MP_MUX_MRSZ_MI;
>> +     writel(dpcl, base + CIF_VI_DPCL);
>> +}
>> +
>> +static inline void sp_set_data_path(void __iomem *base)
>> +{
>> +     u32 dpcl = readl(base + CIF_VI_DPCL);
>> +
>> +     dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
>> +     writel(dpcl, base + CIF_VI_DPCL);
>> +}
>> +
>> +static inline void mp_frame_end_int_enable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_IMSC;
>> +
>> +     writel(CIF_MI_MP_FRAME | readl(addr), addr);
>> +}
>> +
>> +static inline void sp_frame_end_int_enable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_IMSC;
>> +
>> +     writel(CIF_MI_SP_FRAME | readl(addr), addr);
>> +}
>> +
>> +static inline void mp_frame_end_int_disable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_IMSC;
>> +
>> +     writel(~CIF_MI_MP_FRAME & readl(addr), addr);
>> +}
>> +
>> +static inline void sp_frame_end_int_disable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_IMSC;
>> +
>> +     writel(~CIF_MI_SP_FRAME & readl(addr), addr);
>> +}
>> +
>> +static inline void clr_mpsp_frame_end_int(void __iomem *base)
>> +{
>> +     writel(CIF_MI_SP_FRAME | CIF_MI_MP_FRAME, base + CIF_MI_ICR);
>> +}
>> +
>> +static inline void clr_mp_crop_rsz_int(void __iomem *base)
>> +{
>> +     writel(~CIF_MI_MP_FRAME, base + CIF_MI_ICR);
>> +}
>> +
>> +static inline void clr_sp_crop_rsz_int(void __iomem *base)
>> +{
>> +     writel(~CIF_MI_SP_FRAME, base + CIF_MI_ICR);
>> +}
>> +
>> +static inline void clr_all_int(void __iomem *base)
>> +{
>> +     writel(~0, base + CIF_MI_ICR);
>> +}
>> +
>> +static inline void mp_set_uv_swap(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_XTD_FORMAT_CTRL;
>> +     u32 reg = readl(addr) & ~BIT(0);
>> +
>> +     writel(reg | CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP, addr);
>> +}
>> +
>> +static inline void sp_set_uv_swap(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_XTD_FORMAT_CTRL;
>> +     u32 reg = readl(addr) & ~BIT(1);
>> +
>> +     writel(reg | CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP, addr);
>> +}
>> +
>> +static inline void sp_set_y_width(void __iomem *base, u32 val)
>> +{
>> +     writel(val, base + CIF_MI_SP_Y_PIC_WIDTH);
>> +}
>> +
>> +static inline void sp_set_y_height(void __iomem *base, u32 val)
>> +{
>> +     writel(val, base + CIF_MI_SP_Y_PIC_HEIGHT);
>> +}
>> +
>> +static inline void sp_set_y_line_length(void __iomem *base, u32 val)
>> +{
>> +     writel(val, base + CIF_MI_SP_Y_LLENGTH);
>> +}
>> +
>> +static inline void mp_mi_ctrl_set_format(void __iomem *base, u32 val)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +     u32 reg = readl(addr) & ~MI_CTRL_MP_FMT_MASK;
>> +
>> +     writel(reg | val, addr);
>> +}
>> +
>> +static inline void sp_mi_ctrl_set_format(void __iomem *base, u32 val)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +     u32 reg = readl(addr) & ~MI_CTRL_SP_FMT_MASK;
>> +
>> +     writel(reg | val, addr);
>> +}
>> +
>> +static inline void mi_ctrl_mpyuv_enable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(CIF_MI_CTRL_MP_ENABLE | readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_mpyuv_disable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(~CIF_MI_CTRL_MP_ENABLE & readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_mp_disable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(~(CIF_MI_CTRL_MP_ENABLE | CIF_MI_CTRL_RAW_ENABLE) & readl(addr),
>> +            addr);
>> +}
>> +
>> +static inline void mi_ctrl_spyuv_enable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(CIF_MI_CTRL_SP_ENABLE | readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_spyuv_disable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(~CIF_MI_CTRL_SP_ENABLE & readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_sp_disable(void __iomem *base)
>> +{
>> +     mi_ctrl_spyuv_disable(base);
>> +}
>> +
>> +static inline void mi_ctrl_mpraw_enable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(CIF_MI_CTRL_RAW_ENABLE | readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_mpraw_disable(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(~CIF_MI_CTRL_RAW_ENABLE & readl(addr), addr);
>> +}
>> +
>> +static inline void mp_mi_ctrl_autoupdate_en(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(readl(addr) | CIF_MI_MP_AUTOUPDATE_ENABLE, addr);
>> +}
>> +
>> +static inline void sp_mi_ctrl_autoupdate_en(void __iomem *base)
>> +{
>> +     void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +     writel(readl(addr) | CIF_MI_SP_AUTOUPDATE_ENABLE, addr);
>> +}
>> +
>> +static inline void force_cfg_update(void __iomem *base)
>> +{
>> +     writel(CIF_MI_INIT_SOFT_UPD, base + CIF_MI_INIT);
>> +}
>> +
>> +static inline u32 mi_get_masked_int_status(void __iomem *base)
>> +{
>> +     return readl(base + CIF_MI_MIS);
>> +}
>> +
>> +#endif /* _RKISP1_REGS_H */
>> diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.c b/drivers/media/platform/rockchip/isp1/rkisp1.c
>> new file mode 100644
>> index 000000000000..7ce98b80f447
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/rkisp1.c
>> @@ -0,0 +1,1201 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#include <linux/iopoll.h>
>> +#include <linux/pm_runtime.h>
>> +#include <linux/videodev2.h>
>> +#include <linux/vmalloc.h>
>> +#include <media/v4l2-event.h>
>> +
>> +#include "common.h"
>> +#include "regs.h"
>> +
>> +#define CIF_ISP_INPUT_W_MAX          4032
>> +#define CIF_ISP_INPUT_H_MAX          3024
>> +#define CIF_ISP_INPUT_W_MIN          32
>> +#define CIF_ISP_INPUT_H_MIN          32
>> +#define CIF_ISP_OUTPUT_W_MAX         CIF_ISP_INPUT_W_MAX
>> +#define CIF_ISP_OUTPUT_H_MAX         CIF_ISP_INPUT_H_MAX
>> +#define CIF_ISP_OUTPUT_W_MIN         CIF_ISP_INPUT_W_MIN
>> +#define CIF_ISP_OUTPUT_H_MIN         CIF_ISP_INPUT_H_MIN
>> +
>> +/*
>> + * NOTE: MIPI controller and input MUX are also configured in this file,
>> + * because ISP Subdev is not only describe ISP submodule(input size,format, output size, format),
>> + * but also a virtual route device.
>> + */
>> +
>> +/*
>> + * There are many variables named with format/frame in below code,
>> + * please see here for their meaning.
>> + *
>> + * Cropping regions of ISP
>> + *
>> + * +---------------------------------------------------------+
>> + * | Sensor image                                            |
>> + * | +---------------------------------------------------+   |
>> + * | | ISP_ACQ (for black level)                         |   |
>> + * | | in_frm                                            |   |
>> + * | | +--------------------------------------------+    |   |
>> + * | | |    ISP_OUT                                 |    |   |
>> + * | | |    in_crop                                 |    |   |
>> + * | | |    +---------------------------------+     |    |   |
>> + * | | |    |   ISP_IS                        |     |    |   |
>> + * | | |    |   rkisp1_isp_subdev: out_crop   |     |    |   |
>> + * | | |    +---------------------------------+     |    |   |
>> + * | | +--------------------------------------------+    |   |
>> + * | +---------------------------------------------------+   |
>> + * +---------------------------------------------------------+
>> + */
>> +
>> +static inline struct rkisp1_device *sd_to_isp_dev(struct v4l2_subdev *sd)
>> +{
>> +     return container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev);
>> +}
>> +
>> +/* Get sensor by enabled media link */
>> +static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
>> +{
>> +     struct media_pad *local;
>> +     struct media_entity *sensor_me;
>> +
>> +     local = &sd->entity.pads[RKISP1_ISP_PAD_SINK];
>> +     sensor_me = media_entity_remote_pad(local)->entity;
>> +
>> +     return media_entity_to_v4l2_subdev(sensor_me);
>> +}
>> +
>> +static struct rkisp1_sensor_info *sd_to_sensor(struct rkisp1_device *dev,
>> +                                            struct v4l2_subdev *sd)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i < dev->num_sensors; ++i)
>> +             if (dev->sensors[i].sd == sd)
>> +                     return &dev->sensors[i];
>> +
>> +     return NULL;
>> +}
>> +
>> +/****************  register operations ****************/
>> +
>> +/*
>> + * Image Stabilization.
>> + * This should only be called when configuring CIF
>> + * or at the frame end interrupt
>> + */
>> +static void rkisp1_config_ism(struct rkisp1_device *dev)
>> +{
>> +     void __iomem *base = dev->base_addr;
>> +     struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop;
>> +     u32 val;
>> +
>> +     writel(0, base + CIF_ISP_IS_RECENTER);
>> +     writel(0, base + CIF_ISP_IS_MAX_DX);
>> +     writel(0, base + CIF_ISP_IS_MAX_DY);
>> +     writel(0, base + CIF_ISP_IS_DISPLACE);
>> +     writel(out_crop->left, base + CIF_ISP_IS_H_OFFS);
>> +     writel(out_crop->top, base + CIF_ISP_IS_V_OFFS);
>> +     writel(out_crop->width, base + CIF_ISP_IS_H_SIZE);
>> +     writel(out_crop->height, base + CIF_ISP_IS_V_SIZE);
>> +
>> +     /* IS(Image Stabilization) is always on, working as output crop */
>> +     writel(1, base + CIF_ISP_IS_CTRL);
>> +     val = readl(base + CIF_ISP_CTRL);
>> +     val |= CIF_ISP_CTRL_ISP_CFG_UPD;
>> +     writel(val, base + CIF_ISP_CTRL);
>> +}
>> +
>> +/*
>> + * configure isp blocks with input format, size......
>> + */
>> +static int rkisp1_config_isp(struct rkisp1_device *dev)
>> +{
>> +     struct ispsd_in_fmt *in_fmt;
>> +     struct ispsd_out_fmt *out_fmt;
>> +     struct v4l2_mbus_framefmt *in_frm;
>> +     struct v4l2_rect *out_crop, *in_crop;
>> +     struct rkisp1_sensor_info *sensor;
>> +     void __iomem *base = dev->base_addr;
>> +     u32 isp_ctrl = 0;
>> +     u32 irq_mask = 0;
>> +     u32 signal = 0;
>> +     u32 acq_mult = 0;
>> +     u32 val;
>> +
>> +     sensor = dev->active_sensor;
>> +     in_frm = &dev->isp_sdev.in_frm;
>> +     in_fmt = &dev->isp_sdev.in_fmt;
>> +     out_fmt = &dev->isp_sdev.out_fmt;
>> +     out_crop = &dev->isp_sdev.out_crop;
>> +     in_crop = &dev->isp_sdev.in_crop;
>> +     val = readl(base + CIF_ICCL);
>> +     writel(val | CIF_ICCL_ISP_CLK, base + CIF_ICCL);
>> +
>> +     if (in_fmt->fmt_type == FMT_BAYER) {
>> +             acq_mult = 1;
>> +             if (out_fmt->fmt_type == FMT_BAYER) {
>> +                     if (sensor->mbus.type == V4L2_MBUS_BT656)
>> +                             isp_ctrl =
>> +                                     CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656;
>> +                     else
>> +                             isp_ctrl =
>> +                                     CIF_ISP_CTRL_ISP_MODE_RAW_PICT;
>> +             } else {
>> +                     writel(CIF_ISP_DEMOSAIC_TH(0xc),
>> +                            base + CIF_ISP_DEMOSAIC);
>> +
>> +                     if (sensor->mbus.type == V4L2_MBUS_BT656)
>> +                             isp_ctrl = CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656;
>> +                     else
>> +                             isp_ctrl = CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601;
>> +             }
>> +     } else if (in_fmt->fmt_type == FMT_YUV) {
>> +             acq_mult = 2;
>> +             if (sensor->mbus.type == V4L2_MBUS_CSI2) {
>> +                     isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
>> +             } else {
>> +                     if (sensor->mbus.type == V4L2_MBUS_BT656)
>> +                             isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU656;
>> +                     else
>> +                             isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
>> +
>> +             }
>> +
>> +             irq_mask |= CIF_ISP_DATA_LOSS;
>> +     }
>> +
>> +     /* Set up input acquisition properties */
>> +     if (sensor->mbus.type == V4L2_MBUS_BT656 ||
>> +         sensor->mbus.type == V4L2_MBUS_PARALLEL) {
>> +             if (sensor->mbus.flags &
>> +                     V4L2_MBUS_PCLK_SAMPLE_RISING)
>> +                     signal = CIF_ISP_ACQ_PROP_POS_EDGE;
>> +     }
>> +
>> +     if (sensor->mbus.type == V4L2_MBUS_PARALLEL) {
>> +             if (sensor->mbus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
>> +                     signal |= CIF_ISP_ACQ_PROP_VSYNC_LOW;
>> +
>> +             if (sensor->mbus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
>> +                     signal |= CIF_ISP_ACQ_PROP_HSYNC_LOW;
>> +     }
>> +
>> +     writel(isp_ctrl, base + CIF_ISP_CTRL);
>> +     writel(signal | in_fmt->yuv_seq |
>> +            CIF_ISP_ACQ_PROP_BAYER_PAT(in_fmt->bayer_pat) |
>> +            CIF_ISP_ACQ_PROP_FIELD_SEL_ALL, base + CIF_ISP_ACQ_PROP);
>> +     writel(0, base + CIF_ISP_ACQ_NR_FRAMES);
>> +
>> +     /* Acquisition Size */
>> +     writel(0, base + CIF_ISP_ACQ_H_OFFS);
>> +     writel(0, base + CIF_ISP_ACQ_V_OFFS);
>> +     writel(acq_mult * in_frm->width, base + CIF_ISP_ACQ_H_SIZE);
>> +     writel(in_frm->height, base + CIF_ISP_ACQ_V_SIZE);
>> +
>> +     /* ISP Out Area */
>> +     writel(in_crop->left, base + CIF_ISP_OUT_H_OFFS);
>> +     writel(in_crop->top, base + CIF_ISP_OUT_V_OFFS);
>> +     writel(in_crop->width, base + CIF_ISP_OUT_H_SIZE);
>> +     writel(in_crop->height, base + CIF_ISP_OUT_V_SIZE);
>> +
>> +     /* interrupt mask */
>> +     irq_mask |= CIF_ISP_FRAME | CIF_ISP_V_START | CIF_ISP_PIC_SIZE_ERROR |
>> +                 CIF_ISP_FRAME_IN;
>> +     writel(irq_mask, base + CIF_ISP_IMSC);
>> +
>> +     if (out_fmt->fmt_type == FMT_BAYER)
>> +             rkisp1_disable_isp(&dev->params_vdev);
>> +     else
>> +             rkisp1_configure_isp(&dev->params_vdev, in_fmt, 0);
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_config_dvp(struct rkisp1_device *dev)
>> +{
>> +     struct ispsd_in_fmt *in_fmt = &dev->isp_sdev.in_fmt;
>> +     void __iomem *base = dev->base_addr;
>> +     u32 val, input_sel;
>> +
>> +     switch (in_fmt->bus_width) {
>> +     case 8:
>> +             input_sel = CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO;
>> +             break;
>> +     case 10:
>> +             input_sel = CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO;
>> +             break;
>> +     case 12:
>> +             input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
>> +             break;
>> +     default:
>> +             v4l2_err(&dev->v4l2_dev, "Invalid bus width\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     val = readl(base + CIF_ISP_ACQ_PROP);
>> +     writel(val | input_sel, base + CIF_ISP_ACQ_PROP);
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_config_mipi(struct rkisp1_device *dev)
>> +{
>> +     u32 mipi_ctrl, val;
>> +     void __iomem *base = dev->base_addr;
>> +     struct ispsd_in_fmt *in_fmt = &dev->isp_sdev.in_fmt;
>> +     struct rkisp1_sensor_info *sensor = dev->active_sensor;
>> +     int lanes;
>> +
>> +     /*
>> +      * sensor->mbus is set in isp or d-phy notifier_bound function
>> +      */
>> +     switch (sensor->mbus.flags & V4L2_MBUS_CSI2_LANES) {
>> +     case V4L2_MBUS_CSI2_4_LANE:
>> +             lanes = 4;
>> +             break;
>> +     case V4L2_MBUS_CSI2_3_LANE:
>> +             lanes = 3;
>> +             break;
>> +     case V4L2_MBUS_CSI2_2_LANE:
>> +             lanes = 2;
>> +             break;
>> +     case V4L2_MBUS_CSI2_1_LANE:
>> +             lanes = 1;
>> +             break;
>> +     default:
>> +             return -EINVAL;
>> +     }
>> +
>> +     val = readl(base + CIF_ICCL);
>> +     writel(val | CIF_ICCL_MIPI_CLK, base + CIF_ICCL);
>> +
>> +     mipi_ctrl = CIF_MIPI_CTRL_NUM_LANES(lanes - 1) |
>> +                 CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) |
>> +                 CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP |
>> +                 CIF_MIPI_CTRL_CLOCKLANE_ENA;
>> +
>> +     writel(mipi_ctrl, base + CIF_MIPI_CTRL);
>> +
>> +     /* Configure Data Type and Virtual Channel */
>> +     writel(CIF_MIPI_DATA_SEL_DT(in_fmt->mipi_dt) | CIF_MIPI_DATA_SEL_VC(0),
>> +            base + CIF_MIPI_IMG_DATA_SEL);
>> +
>> +     /* Clear MIPI interrupts */
>> +     writel(~0, base + CIF_MIPI_ICR);
>> +     /*
>> +      * Disable CIF_MIPI_ERR_DPHY interrupt here temporary for
>> +      * isp bus may be dead when switch isp.
>> +      */
>> +     writel(CIF_MIPI_FRAME_END | CIF_MIPI_ERR_CSI | CIF_MIPI_ERR_DPHY |
>> +            CIF_MIPI_SYNC_FIFO_OVFLW(0x03) | CIF_MIPI_ADD_DATA_OVFLW,
>> +            base + CIF_MIPI_IMSC);
>> +
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "\n  MIPI_CTRL 0x%08x\n"
>> +              "  MIPI_IMG_DATA_SEL 0x%08x\n"
>> +              "  MIPI_STATUS 0x%08x\n"
>> +              "  MIPI_IMSC 0x%08x\n",
>> +              readl(base + CIF_MIPI_CTRL),
>> +              readl(base + CIF_MIPI_IMG_DATA_SEL),
>> +              readl(base + CIF_MIPI_STATUS),
>> +              readl(base + CIF_MIPI_IMSC));
>> +
>> +     return 0;
>> +}
>> +
>> +/* Configure MUX */
>> +static int rkisp1_config_path(struct rkisp1_device *dev)
>> +{
>> +     int ret = 0;
>> +     struct rkisp1_sensor_info *sensor = dev->active_sensor;
>> +     u32 dpcl = readl(dev->base_addr + CIF_VI_DPCL);
>> +
>> +     if (sensor->mbus.type == V4L2_MBUS_BT656 ||
>> +         sensor->mbus.type == V4L2_MBUS_PARALLEL) {
>> +             ret = rkisp1_config_dvp(dev);
>> +             dpcl |= CIF_VI_DPCL_IF_SEL_PARALLEL;
>> +     } else if (sensor->mbus.type == V4L2_MBUS_CSI2) {
>> +             ret = rkisp1_config_mipi(dev);
>> +             dpcl |= CIF_VI_DPCL_IF_SEL_MIPI;
>> +     }
>> +
>> +     writel(dpcl, dev->base_addr + CIF_VI_DPCL);
>> +
>> +     return ret;
>> +}
>> +
>> +/* Hareware configure Entry */
>> +static int rkisp1_config_cif(struct rkisp1_device *dev)
>> +{
>> +     int ret = 0;
>> +     u32 cif_id;
>> +
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +              "SP state = %d, MP state = %d\n",
>> +              dev->stream[RKISP1_STREAM_SP].state,
>> +              dev->stream[RKISP1_STREAM_MP].state);
>> +
>> +     cif_id = readl(dev->base_addr + CIF_VI_ID);
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "CIF_ID 0x%08x\n", cif_id);
>> +
>> +     ret = rkisp1_config_isp(dev);
>> +     if (ret < 0)
>> +             return ret;
>> +     ret = rkisp1_config_path(dev);
>> +     if (ret < 0)
>> +             return ret;
>> +     rkisp1_config_ism(dev);
>> +
>> +     return 0;
>> +}
>> +
>> +/* Mess register operations to stop isp */
>> +static int rkisp1_isp_stop(struct rkisp1_device *dev)
>> +{
>> +     void __iomem *base = dev->base_addr;
>> +     u32 val;
>> +
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +              "SP state = %d, MP state = %d\n",
>> +              dev->stream[RKISP1_STREAM_SP].state,
>> +              dev->stream[RKISP1_STREAM_MP].state);
>> +
>> +     /*
>> +      * ISP(mi) stop in mi frame end -> Stop ISP(mipi) ->
>> +      * Stop ISP(isp) ->wait for ISP isp off
>> +      */
>> +     /* stop and clear MI, MIPI, and ISP interrupts */
>> +     writel(0, base + CIF_MIPI_IMSC);
>> +     writel(~0, base + CIF_MIPI_ICR);
>> +
>> +     writel(0, base + CIF_ISP_IMSC);
>> +     writel(~0, base + CIF_ISP_ICR);
>> +
>> +     writel(0, base + CIF_MI_IMSC);
>> +     writel(~0, base + CIF_MI_ICR);
>> +     val = readl(base + CIF_MIPI_CTRL);
>> +     writel(val & (~CIF_MIPI_CTRL_OUTPUT_ENA), base + CIF_MIPI_CTRL);
>> +     /* stop ISP */
>> +     val = readl(base + CIF_ISP_CTRL);
>> +     val &= ~(CIF_ISP_CTRL_ISP_INFORM_ENABLE | CIF_ISP_CTRL_ISP_ENABLE);
>> +     writel(val, base + CIF_ISP_CTRL);
>> +
>> +     val = readl(base + CIF_ISP_CTRL);
>> +     writel(val | CIF_ISP_CTRL_ISP_CFG_UPD, base + CIF_ISP_CTRL);
>> +
>> +     readx_poll_timeout(readl, base + CIF_ISP_RIS,
>> +                        val, val & CIF_ISP_OFF, 20, 100);
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +             "state(MP:%d, SP:%d), MI_CTRL:%x, ISP_CTRL:%x, MIPI_CTRL:%x\n",
>> +              dev->stream[RKISP1_STREAM_SP].state,
>> +              dev->stream[RKISP1_STREAM_MP].state,
>> +              readl(base + CIF_MI_CTRL),
>> +              readl(base + CIF_ISP_CTRL),
>> +              readl(base + CIF_MIPI_CTRL));
>> +
>> +     writel(CIF_IRCL_MIPI_SW_RST | CIF_IRCL_ISP_SW_RST, base + CIF_IRCL);
>> +     writel(0x0, base + CIF_IRCL);
>> +
>> +     return 0;
>> +}
>> +
>> +/* Mess register operations to start isp */
>> +static int rkisp1_isp_start(struct rkisp1_device *dev)
>> +{
>> +     struct rkisp1_sensor_info *sensor = dev->active_sensor;
>> +     void __iomem *base = dev->base_addr;
>> +     u32 val;
>> +
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +              "SP state = %d, MP state = %d\n",
>> +              dev->stream[RKISP1_STREAM_SP].state,
>> +              dev->stream[RKISP1_STREAM_MP].state);
>> +
>> +     /* Activate MIPI */
>> +     if (sensor->mbus.type == V4L2_MBUS_CSI2) {
>> +             val = readl(base + CIF_MIPI_CTRL);
>> +             writel(val | CIF_MIPI_CTRL_OUTPUT_ENA, base + CIF_MIPI_CTRL);
>> +     }
>> +     /* Activate ISP */
>> +     val = readl(base + CIF_ISP_CTRL);
>> +     val |= CIF_ISP_CTRL_ISP_CFG_UPD | CIF_ISP_CTRL_ISP_ENABLE |
>> +            CIF_ISP_CTRL_ISP_INFORM_ENABLE;
>> +     writel(val, base + CIF_ISP_CTRL);
>> +
>> +     /* XXX: Is the 1000us too long?
>> +      * CIF spec says to wait for sufficient time after enabling
>> +      * the MIPI interface and before starting the sensor output.
>> +      */
>> +     usleep_range(1000, 1200);
>> +
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +              "SP state = %d, MP state = %d MI_CTRL 0x%08x\n"
>> +              "  ISP_CTRL 0x%08x MIPI_CTRL 0x%08x\n",
>> +              dev->stream[RKISP1_STREAM_SP].state,
>> +              dev->stream[RKISP1_STREAM_MP].state,
>> +              readl(base + CIF_MI_CTRL),
>> +              readl(base + CIF_ISP_CTRL),
>> +              readl(base + CIF_MIPI_CTRL));
>> +
>> +     return 0;
>> +}
>> +
>> +static void rkisp1_config_clk(struct rkisp1_device *dev)
>> +{
>> +     u32 val = CIF_ICCL_ISP_CLK | CIF_ICCL_CP_CLK | CIF_ICCL_MRSZ_CLK |
>> +             CIF_ICCL_SRSZ_CLK | CIF_ICCL_JPEG_CLK | CIF_ICCL_MI_CLK |
>> +             CIF_ICCL_MIPI_CLK | CIF_ICCL_DCROP_CLK;
>> +
>> +     writel(val, dev->base_addr + CIF_ICCL);
>> +}
>> +
>> +/***************************** isp sub-devs *******************************/
>> +
>> +static const struct ispsd_in_fmt rkisp1_isp_input_formats[] = {
>> +     {
>> +             .mbus_code      = MEDIA_BUS_FMT_SBGGR10_1X10,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW10,
>> +             .bayer_pat      = RAW_BGGR,
>> +             .bus_width      = 10,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SRGGB10_1X10,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW10,
>> +             .bayer_pat      = RAW_RGGB,
>> +             .bus_width      = 10,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGBRG10_1X10,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW10,
>> +             .bayer_pat      = RAW_GBRG,
>> +             .bus_width      = 10,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGRBG10_1X10,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW10,
>> +             .bayer_pat      = RAW_GRBG,
>> +             .bus_width      = 10,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SRGGB12_1X12,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW12,
>> +             .bayer_pat      = RAW_RGGB,
>> +             .bus_width      = 12,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SBGGR12_1X12,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW12,
>> +             .bayer_pat      = RAW_BGGR,
>> +             .bus_width      = 12,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGBRG12_1X12,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW12,
>> +             .bayer_pat      = RAW_GBRG,
>> +             .bus_width      = 12,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGRBG12_1X12,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW12,
>> +             .bayer_pat      = RAW_GRBG,
>> +             .bus_width      = 12,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SRGGB8_1X8,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW8,
>> +             .bayer_pat      = RAW_RGGB,
>> +             .bus_width      = 8,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SBGGR8_1X8,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW8,
>> +             .bayer_pat      = RAW_BGGR,
>> +             .bus_width      = 8,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGBRG8_1X8,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW8,
>> +             .bayer_pat      = RAW_GBRG,
>> +             .bus_width      = 8,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGRBG8_1X8,
>> +             .fmt_type       = FMT_BAYER,
>> +             .mipi_dt        = CIF_CSI2_DT_RAW8,
>> +             .bayer_pat      = RAW_GRBG,
>> +             .bus_width      = 8,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_YUYV8_1X16,
>> +             .fmt_type       = FMT_YUV,
>> +             .mipi_dt        = CIF_CSI2_DT_YUV422_8b,
>> +             .yuv_seq        = CIF_ISP_ACQ_PROP_YCBYCR,
>> +             .bus_width      = 16,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_YVYU8_1X16,
>> +             .fmt_type       = FMT_YUV,
>> +             .mipi_dt        = CIF_CSI2_DT_YUV422_8b,
>> +             .yuv_seq        = CIF_ISP_ACQ_PROP_YCRYCB,
>> +             .bus_width      = 16,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_UYVY8_1X16,
>> +             .fmt_type       = FMT_YUV,
>> +             .mipi_dt        = CIF_CSI2_DT_YUV422_8b,
>> +             .yuv_seq        = CIF_ISP_ACQ_PROP_CBYCRY,
>> +             .bus_width      = 16,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_VYUY8_1X16,
>> +             .fmt_type       = FMT_YUV,
>> +             .mipi_dt        = CIF_CSI2_DT_YUV422_8b,
>> +             .yuv_seq        = CIF_ISP_ACQ_PROP_CRYCBY,
>> +             .bus_width      = 16,
>> +     },
>> +};
>> +
>> +static const struct ispsd_out_fmt rkisp1_isp_output_formats[] = {
>> +     {
>> +             .mbus_code      = MEDIA_BUS_FMT_YUYV8_2X8,
>> +             .fmt_type       = FMT_YUV,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SRGGB12_1X12,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SBGGR12_1X12,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGBRG12_1X12,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGRBG12_1X12,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SRGGB10_1X10,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SBGGR10_1X10,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGBRG10_1X10,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGRBG10_1X10,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SRGGB8_1X8,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SBGGR8_1X8,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGBRG8_1X8,
>> +             .fmt_type       = FMT_BAYER,
>> +     }, {
>> +             .mbus_code      = MEDIA_BUS_FMT_SGRBG8_1X8,
>> +             .fmt_type       = FMT_BAYER,
>> +     },
>> +};
>> +
>> +static const struct ispsd_in_fmt *find_in_fmt(u32 mbus_code)
>> +{
>> +     const struct ispsd_in_fmt *fmt;
>> +     int i, array_size = ARRAY_SIZE(rkisp1_isp_input_formats);
>> +
>> +     for (i = 0; i < array_size; i++) {
>> +             fmt = &rkisp1_isp_input_formats[i];
>> +             if (fmt->mbus_code == mbus_code)
>> +                     return fmt;
>> +     }
>> +
>> +     return NULL;
>> +}
>> +
>> +static const struct ispsd_out_fmt *find_out_fmt(u32 mbus_code)
>> +{
>> +     const struct ispsd_out_fmt *fmt;
>> +     int i, array_size = ARRAY_SIZE(rkisp1_isp_output_formats);
>> +
>> +     for (i = 0; i < array_size; i++) {
>> +             fmt = &rkisp1_isp_output_formats[i];
>> +             if (fmt->mbus_code == mbus_code)
>> +                     return fmt;
>> +     }
>> +
>> +     return NULL;
>> +}
>> +
>> +static int rkisp1_isp_sd_enum_mbus_code(struct v4l2_subdev *sd,
>> +                                     struct v4l2_subdev_pad_config *cfg,
>> +                                     struct v4l2_subdev_mbus_code_enum *code)
>> +{
>> +     int i = code->index;
>> +
>> +     if (code->pad == RKISP1_ISP_PAD_SINK) {
>> +             if (i >= ARRAY_SIZE(rkisp1_isp_input_formats))
>> +                     return -EINVAL;
>> +             code->code = rkisp1_isp_input_formats[i].mbus_code;
>> +     } else {
>> +             if (i >= ARRAY_SIZE(rkisp1_isp_output_formats))
>> +                     return -EINVAL;
>> +             code->code = rkisp1_isp_output_formats[i].mbus_code;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +#define sd_to_isp_sd(_sd) container_of(_sd, struct rkisp1_isp_subdev, sd)
>> +static int rkisp1_isp_sd_get_fmt(struct v4l2_subdev *sd,
>> +                              struct v4l2_subdev_pad_config *cfg,
>> +                              struct v4l2_subdev_format *fmt)
>> +{
>> +     struct v4l2_mbus_framefmt *mf = &fmt->format;
>> +     struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
>> +
>> +     if ((fmt->pad != RKISP1_ISP_PAD_SINK) &&
>> +         (fmt->pad != RKISP1_ISP_PAD_SOURCE_PATH))
>> +             return -EINVAL;
>> +
>> +     if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
>> +             mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
>> +             fmt->format = *mf;
>> +             return 0;
>> +     }
>> +
>> +     if (fmt->pad == RKISP1_ISP_PAD_SINK) {
>> +             *mf = isp_sd->in_frm;
>> +     } else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
>> +             /* format of source pad */
>> +             *mf = isp_sd->in_frm;
>> +             /* window size of source pad */
>> +             mf->width = isp_sd->out_crop.width;
>> +             mf->height = isp_sd->out_crop.height;
>> +     }
>> +     mf->field = V4L2_FIELD_NONE;
>> +
>> +     return 0;
>> +}
>> +
>> +static void rkisp1_isp_sd_try_fmt(struct v4l2_subdev *sd,
>> +                               unsigned int pad,
>> +                               struct v4l2_mbus_framefmt *fmt)
>> +{
>> +     struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
>> +     struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
>> +     const struct ispsd_in_fmt *in_fmt;
>> +     const struct ispsd_out_fmt *out_fmt;
>> +
>> +     switch (pad) {
>> +     case RKISP1_ISP_PAD_SINK:
>> +             in_fmt = find_in_fmt(fmt->code);
>> +             if (in_fmt)
>> +                     fmt->code = in_fmt->mbus_code;
>> +             else
>> +                     fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
>> +             fmt->width  = clamp_t(u32, fmt->width, CIF_ISP_INPUT_W_MIN,
>> +                                   CIF_ISP_INPUT_W_MAX);
>> +             fmt->height = clamp_t(u32, fmt->height, CIF_ISP_INPUT_H_MIN,
>> +                                   CIF_ISP_INPUT_H_MAX);
>> +             break;
>> +     case RKISP1_ISP_PAD_SOURCE_PATH:
>> +             out_fmt = find_out_fmt(fmt->code);
>> +             if (out_fmt)
>> +                     fmt->code = out_fmt->mbus_code;
>> +             else
>> +                     fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
>> +             /* window size is set in s_selection */
>> +             fmt->width  = isp_sd->out_crop.width;
>> +             fmt->height = isp_sd->out_crop.height;
>> +             break;
>> +     }
>> +
>> +     fmt->field = V4L2_FIELD_NONE;
>> +}
>> +
>> +static int rkisp1_isp_sd_set_fmt(struct v4l2_subdev *sd,
>> +                              struct v4l2_subdev_pad_config *cfg,
>> +                              struct v4l2_subdev_format *fmt)
>> +{
>> +     struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
>> +     struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
>> +     struct v4l2_mbus_framefmt *mf = &fmt->format;
>> +
>> +     if ((fmt->pad != RKISP1_ISP_PAD_SINK) &&
>> +         (fmt->pad != RKISP1_ISP_PAD_SOURCE_PATH))
>> +             return -EINVAL;
>> +
>> +     rkisp1_isp_sd_try_fmt(sd, fmt->pad, mf);
>> +
>> +     if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
>> +             struct v4l2_mbus_framefmt *try_mf;
>> +
>> +             mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
>> +             *try_mf = *mf;
>> +             return 0;
>> +     }
>> +
>> +     if (fmt->pad == RKISP1_ISP_PAD_SINK) {
>> +             const struct ispsd_in_fmt *in_fmt;
>> +
>> +             in_fmt = find_in_fmt(mf->code);
>> +             isp_sd->in_fmt = *in_fmt;
>> +             isp_sd->in_frm = *mf;
>> +     } else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
>> +             const struct ispsd_out_fmt *out_fmt;
>> +
>> +             /* Ignore width/height */
>> +             out_fmt = find_out_fmt(mf->code);
>> +             isp_sd->out_fmt = *out_fmt;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static void rkisp1_isp_sd_try_crop(struct v4l2_subdev *sd,
>> +                               struct v4l2_subdev_pad_config *cfg,
>> +                               struct v4l2_subdev_selection *sel)
>> +{
>> +     struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
>> +     struct v4l2_mbus_framefmt in_frm = isp_sd->in_frm;
>> +     struct v4l2_rect in_crop = isp_sd->in_crop;
>> +     struct v4l2_rect *input = &sel->r;
>> +
>> +     if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
>> +             in_frm = *v4l2_subdev_get_try_format(sd, cfg, RKISP1_ISP_PAD_SINK);
>> +             in_crop = *v4l2_subdev_get_try_crop(sd, cfg, RKISP1_ISP_PAD_SINK);
>> +     }
>> +
>> +     input->left = ALIGN(input->left, 2);
>> +     input->width = ALIGN(input->width, 2);
>> +
>> +     if (sel->pad == RKISP1_ISP_PAD_SINK) {
>> +             input->left = clamp_t(u32, input->left, 0, in_frm.width);
>> +             input->top = clamp_t(u32, input->top, 0, in_frm.height);
>> +             input->width = clamp_t(u32, input->width, CIF_ISP_INPUT_W_MIN,
>> +                             in_frm.width - input->left);
>> +             input->height = clamp_t(u32, input->height,
>> +                             CIF_ISP_INPUT_H_MIN,
>> +                             in_frm.height - input->top);
>> +     } else if (sel->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
>> +             input->left = clamp_t(u32, input->left, 0, in_crop.width);
>> +             input->top = clamp_t(u32, input->top, 0, in_crop.height);
>> +             input->width = clamp_t(u32, input->width, CIF_ISP_OUTPUT_W_MIN,
>> +                             in_crop.width - input->left);
>> +             input->height = clamp_t(u32, input->height, CIF_ISP_OUTPUT_H_MIN,
>> +                             in_crop.height - input->top);
>> +     }
>> +}
>> +
>> +static int rkisp1_isp_sd_get_selection(struct v4l2_subdev *sd,
>> +                                    struct v4l2_subdev_pad_config *cfg,
>> +                                    struct v4l2_subdev_selection *sel)
>> +{
>> +     struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
>> +
>> +     if (sel->pad != RKISP1_ISP_PAD_SOURCE_PATH &&
>> +         sel->pad != RKISP1_ISP_PAD_SINK)
>> +             return -EINVAL;
>> +
>> +     if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
>> +             struct v4l2_rect *try_sel;
>> +
>> +             try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
>> +             sel->r = *try_sel;
>> +             return 0;
>> +     }
>> +
>> +     switch (sel->target) {
>> +     case V4L2_SEL_TGT_CROP_BOUNDS:
>> +             if (sel->pad == RKISP1_ISP_PAD_SINK) {
>> +                     sel->r.height = isp_sd->in_frm.height;
>> +                     sel->r.width = isp_sd->in_frm.width;
>> +                     sel->r.left = 0;
>> +                     sel->r.top = 0;
>> +             } else {
>> +                     sel->r = isp_sd->in_crop;
>> +             }
>> +             break;
>> +     case V4L2_SEL_TGT_CROP:
>> +             if (sel->pad == RKISP1_ISP_PAD_SINK)
>> +                     sel->r = isp_sd->in_crop;
>> +             else
>> +                     sel->r = isp_sd->out_crop;
>> +             break;
>> +     default:
>> +             return -EINVAL;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_isp_sd_set_selection(struct v4l2_subdev *sd,
>> +                                    struct v4l2_subdev_pad_config *cfg,
>> +                                    struct v4l2_subdev_selection *sel)
>> +{
>> +     struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
>> +     struct rkisp1_device *dev = sd_to_isp_dev(sd);
>> +
>> +     if (sel->pad != RKISP1_ISP_PAD_SOURCE_PATH &&
>> +         sel->pad != RKISP1_ISP_PAD_SINK)
>> +             return -EINVAL;
>> +     if (sel->target != V4L2_SEL_TGT_CROP)
>> +             return -EINVAL;
>> +
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +              "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, sel->pad,
>> +              sel->r.left, sel->r.top, sel->r.width, sel->r.height);
>> +     rkisp1_isp_sd_try_crop(sd, cfg, sel);
>> +
>> +     if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
>> +             struct v4l2_rect *try_sel;
>> +
>> +             try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
>> +             *try_sel = sel->r;
>> +             return 0;
>> +     }
>> +
>> +     if (sel->pad == RKISP1_ISP_PAD_SINK)
>> +             isp_sd->in_crop = sel->r;
>> +     else
>> +             isp_sd->out_crop = sel->r;
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_isp_sd_s_stream(struct v4l2_subdev *sd, int on)
>> +{
>> +     struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
>> +     struct rkisp1_sensor_info *sensor;
>> +     struct v4l2_subdev *sensor_sd;
>> +     int ret = 0;
>> +
>> +     if (!on)
>> +             return rkisp1_isp_stop(isp_dev);
>> +
>> +     sensor_sd = get_remote_sensor(sd);
>> +     if (!sensor_sd)
>> +             return -ENODEV;
>> +
>> +     sensor = sd_to_sensor(isp_dev, sensor_sd);
>> +     /*
>> +      * Update sensor bus configuration. This is only effective
>> +      * for sensors chained off an external CSI2 PHY.
>> +      */
>> +     ret = v4l2_subdev_call(sensor->sd, video, g_mbus_config,
>> +                            &sensor->mbus);
>
> What do you use g_mbus_config for? Typically this information should
> come from the device tree. I want to remove this op in the not-too-distant
> future since it really makes no sense.
>
>> +     if (ret && ret != -ENOIOCTLCMD)
>> +             return ret;
>> +     isp_dev->active_sensor = sensor;
>> +
>> +     atomic_set(&isp_dev->isp_sdev.frm_sync_seq, 0);
>> +     ret = rkisp1_config_cif(isp_dev);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     return rkisp1_isp_start(isp_dev);
>> +}
>> +
>> +static int rkisp1_isp_sd_s_power(struct v4l2_subdev *sd, int on)
>> +{
>> +     struct rkisp1_device *dev = sd_to_isp_dev(sd);
>> +     int ret;
>> +
>> +     v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "s_power: %d\n", on);
>> +
>> +     if (on) {
>> +             ret = pm_runtime_get_sync(dev->dev);
>> +             if (ret < 0)
>> +                     return ret;
>> +
>> +             rkisp1_config_clk(dev);
>> +     } else {
>> +             ret = pm_runtime_put(dev->dev);
>> +             if (ret < 0)
>> +                     return ret;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int rkisp1_subdev_link_validate(struct media_link *link)
>> +{
>> +     if (link->source->index == RKISP1_ISP_PAD_SINK_PARAMS)
>> +             return 0;
>> +
>> +     return v4l2_subdev_link_validate(link);
>> +}
>> +
>> +static int rkisp1_subdev_fmt_link_validate(struct v4l2_subdev *sd,
>> +                          struct media_link *link,
>> +                          struct v4l2_subdev_format *source_fmt,
>> +                          struct v4l2_subdev_format *sink_fmt)
>> +{
>> +     if (source_fmt->format.code != sink_fmt->format.code)
>> +             return -EINVAL;
>> +
>> +     /* Crop is available */
>> +     if (source_fmt->format.width < sink_fmt->format.width ||
>> +             source_fmt->format.height < sink_fmt->format.height)
>> +             return -EINVAL;
>> +
>> +     return 0;
>> +}
>> +
>> +static void
>> +riksp1_isp_queue_event_sof(struct rkisp1_isp_subdev *isp)
>> +{
>> +     struct v4l2_event event = {
>> +             .type = V4L2_EVENT_FRAME_SYNC,
>> +             .u.frame_sync.frame_sequence =
>> +                     atomic_inc_return(&isp->frm_sync_seq) - 1,
>> +     };
>> +     v4l2_event_queue(isp->sd.devnode, &event);
>> +}
>> +
>> +static int rkisp1_isp_sd_subs_evt(struct v4l2_subdev *sd, struct v4l2_fh *fh,
>> +                               struct v4l2_event_subscription *sub)
>> +{
>> +     if (sub->type != V4L2_EVENT_FRAME_SYNC)
>> +             return -EINVAL;
>> +
>> +     /* Line number. For now only zero accepted. */
>> +     if (sub->id != 0)
>> +             return -EINVAL;
>> +
>> +     return v4l2_event_subscribe(fh, sub, 0, NULL);
>> +}
>> +
>> +static const struct v4l2_subdev_pad_ops rkisp1_isp_sd_pad_ops = {
>> +     .enum_mbus_code = rkisp1_isp_sd_enum_mbus_code,
>> +     .get_selection = rkisp1_isp_sd_get_selection,
>> +     .set_selection = rkisp1_isp_sd_set_selection,
>> +     .get_fmt = rkisp1_isp_sd_get_fmt,
>> +     .set_fmt = rkisp1_isp_sd_set_fmt,
>> +     .link_validate = rkisp1_subdev_fmt_link_validate,
>> +};
>> +
>> +static const struct media_entity_operations rkisp1_isp_sd_media_ops = {
>> +     .link_validate = rkisp1_subdev_link_validate,
>> +};
>> +
>> +static const struct v4l2_subdev_video_ops rkisp1_isp_sd_video_ops = {
>> +     .s_stream = rkisp1_isp_sd_s_stream,
>> +};
>> +
>> +static const struct v4l2_subdev_core_ops rkisp1_isp_core_ops = {
>> +     .subscribe_event = rkisp1_isp_sd_subs_evt,
>> +     .unsubscribe_event = v4l2_event_subdev_unsubscribe,
>> +     .s_power = rkisp1_isp_sd_s_power,
>> +};
>> +
>> +static struct v4l2_subdev_ops rkisp1_isp_sd_ops = {
>> +     .core = &rkisp1_isp_core_ops,
>> +     .video = &rkisp1_isp_sd_video_ops,
>> +     .pad = &rkisp1_isp_sd_pad_ops,
>> +};
>> +
>> +static void rkisp1_isp_sd_init_default_fmt(struct rkisp1_isp_subdev *isp_sd)
>> +{
>> +     struct v4l2_mbus_framefmt *in_frm = &isp_sd->in_frm;
>> +     struct v4l2_rect *in_crop = &isp_sd->in_crop;
>> +     struct v4l2_rect *out_crop = &isp_sd->out_crop;
>> +     struct ispsd_in_fmt *in_fmt = &isp_sd->in_fmt;
>> +     struct ispsd_out_fmt *out_fmt = &isp_sd->out_fmt;
>> +
>> +     *in_fmt = rkisp1_isp_input_formats[0];
>> +     in_frm->width = RKISP1_DEFAULT_WIDTH;
>> +     in_frm->height = RKISP1_DEFAULT_HEIGHT;
>> +     in_frm->code = in_fmt->mbus_code;
>> +
>> +     in_crop->width = in_frm->width;
>> +     in_crop->height = in_frm->height;
>> +     in_crop->left = 0;
>> +     in_crop->top = 0;
>> +
>> +     /* propagate to source */
>> +     *out_crop = *in_crop;
>> +     *out_fmt = rkisp1_isp_output_formats[0];
>> +}
>> +
>> +int rkisp1_register_isp_subdev(struct rkisp1_device *isp_dev,
>> +                            struct v4l2_device *v4l2_dev)
>> +{
>> +     struct rkisp1_isp_subdev *isp_sdev = &isp_dev->isp_sdev;
>> +     struct v4l2_subdev *sd = &isp_sdev->sd;
>> +     int ret;
>> +
>> +     v4l2_subdev_init(sd, &rkisp1_isp_sd_ops);
>> +     sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
>> +     sd->entity.ops = &rkisp1_isp_sd_media_ops;
>> +     snprintf(sd->name, sizeof(sd->name), "rkisp1-isp-subdev");
>> +
>> +     isp_sdev->pads[RKISP1_ISP_PAD_SINK].flags =
>> +             MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
>> +     isp_sdev->pads[RKISP1_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
>> +     isp_sdev->pads[RKISP1_ISP_PAD_SOURCE_PATH].flags = MEDIA_PAD_FL_SOURCE;
>> +     isp_sdev->pads[RKISP1_ISP_PAD_SOURCE_STATS].flags = MEDIA_PAD_FL_SOURCE;
>> +     sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
>> +     ret = media_entity_pads_init(&sd->entity, RKISP1_ISP_PAD_MAX,
>> +                                  isp_sdev->pads);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     sd->owner = THIS_MODULE;
>> +     v4l2_set_subdevdata(sd, isp_dev);
>> +
>> +     sd->grp_id = GRP_ID_ISP;
>> +     ret = v4l2_device_register_subdev(v4l2_dev, sd);
>> +     if (ret < 0) {
>> +             v4l2_err(sd, "Failed to register isp subdev\n");
>> +             goto err_cleanup_media_entity;
>> +     }
>> +
>> +     rkisp1_isp_sd_init_default_fmt(isp_sdev);
>> +
>> +     return 0;
>> +err_cleanup_media_entity:
>> +     media_entity_cleanup(&sd->entity);
>> +     return ret;
>> +}
>> +
>> +void rkisp1_unregister_isp_subdev(struct rkisp1_device *isp_dev)
>> +{
>> +     struct v4l2_subdev *sd = &isp_dev->isp_sdev.sd;
>> +
>> +     v4l2_device_unregister_subdev(sd);
>> +     media_entity_cleanup(&sd->entity);
>> +}
>> +
>> +/****************  Interrupter Handler ****************/
>> +
>> +void rkisp1_mipi_isr(unsigned int mis, struct rkisp1_device *dev)
>> +{
>> +     struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
>> +     void __iomem *base = dev->base_addr;
>> +     u32 val;
>> +
>> +     writel(~0, base + CIF_MIPI_ICR);
>> +
>> +     /*
>> +      * Disable DPHY errctrl interrupt, because this dphy
>> +      * erctrl signal is asserted until the next changes
>> +      * of line state. This time is may be too long and cpu
>> +      * is hold in this interrupt.
>> +      */
>> +     if (mis & CIF_MIPI_ERR_CTRL(0x0f)) {
>> +             val = readl(base + CIF_MIPI_IMSC);
>> +             writel(val & ~CIF_MIPI_ERR_CTRL(0x0f), base + CIF_MIPI_IMSC);
>> +             dev->isp_sdev.dphy_errctrl_disabled = true;
>> +     }
>> +
>> +     /*
>> +      * Enable DPHY errctrl interrupt again, if mipi have receive
>> +      * the whole frame without any error.
>> +      */
>> +     if (mis == CIF_MIPI_FRAME_END) {
>> +             /*
>> +              * Enable DPHY errctrl interrupt again, if mipi have receive
>> +              * the whole frame without any error.
>> +              */
>> +             if (dev->isp_sdev.dphy_errctrl_disabled) {
>> +                     val = readl(base + CIF_MIPI_IMSC);
>> +                     val |= CIF_MIPI_ERR_CTRL(0x0f);
>> +                     writel(val, base + CIF_MIPI_IMSC);
>> +                     dev->isp_sdev.dphy_errctrl_disabled = false;
>> +             }
>> +     } else {
>> +             v4l2_warn(v4l2_dev, "MIPI mis error: 0x%08x\n", mis);
>> +     }
>> +}
>> +
>> +void rkisp1_isp_isr(unsigned int isp_mis, struct rkisp1_device *dev)
>> +{
>> +     void __iomem *base = dev->base_addr;
>> +     unsigned int isp_mis_tmp = 0;
>> +     unsigned int isp_err = 0;
>> +
>> +     /* start edge of v_sync */
>> +     if (isp_mis & CIF_ISP_V_START) {
>> +             riksp1_isp_queue_event_sof(&dev->isp_sdev);
>> +
>> +             writel(CIF_ISP_V_START, base + CIF_ISP_ICR);
>> +             isp_mis_tmp = readl(base + CIF_ISP_MIS);
>> +             if (isp_mis_tmp & CIF_ISP_V_START)
>> +                     v4l2_err(&dev->v4l2_dev, "isp icr v_statr err: 0x%x\n",
>> +                              isp_mis_tmp);
>> +     }
>> +
>> +     if ((isp_mis & CIF_ISP_PIC_SIZE_ERROR)) {
>> +             /* Clear pic_size_error */
>> +             writel(CIF_ISP_PIC_SIZE_ERROR, base + CIF_ISP_ICR);
>> +             isp_err = readl(base + CIF_ISP_ERR);
>> +             v4l2_err(&dev->v4l2_dev,
>> +                             "CIF_ISP_PIC_SIZE_ERROR (0x%08x)", isp_err);
>> +             writel(isp_err, base + CIF_ISP_ERR_CLR);
>> +     } else if ((isp_mis & CIF_ISP_DATA_LOSS)) {
>> +             /* Clear data_loss */
>> +             writel(CIF_ISP_DATA_LOSS, base + CIF_ISP_ICR);
>> +             v4l2_err(&dev->v4l2_dev, "CIF_ISP_DATA_LOSS\n");
>> +             writel(CIF_ISP_DATA_LOSS, base + CIF_ISP_ICR);
>> +     }
>> +
>> +     /* sampled input frame is complete */
>> +     if (isp_mis & CIF_ISP_FRAME_IN) {
>> +             writel(CIF_ISP_FRAME_IN, base + CIF_ISP_ICR);
>> +             isp_mis_tmp = readl(base + CIF_ISP_MIS);
>> +             if (isp_mis_tmp & CIF_ISP_FRAME_IN)
>> +                     v4l2_err(&dev->v4l2_dev, "isp icr frame_in err: 0x%x\n",
>> +                              isp_mis_tmp);
>> +     }
>> +
>> +     /* frame was completely put out */
>> +     if (isp_mis & CIF_ISP_FRAME) {
>> +             u32 isp_ris = 0;
>> +             /* Clear Frame In (ISP) */
>> +             writel(CIF_ISP_FRAME, base + CIF_ISP_ICR);
>> +             isp_mis_tmp = readl(base + CIF_ISP_MIS);
>> +             if (isp_mis_tmp & CIF_ISP_FRAME)
>> +                     v4l2_err(&dev->v4l2_dev,
>> +                              "isp icr frame end err: 0x%x\n", isp_mis_tmp);
>> +
>> +             isp_ris = readl(base + CIF_ISP_RIS);
>> +             if (isp_ris & (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
>> +                             CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
>> +                     rkisp1_stats_isr(&dev->stats_vdev, isp_ris);
>> +     }
>> +
>> +     /*
>> +      * Then update changed configs. Some of them involve
>> +      * lot of register writes. Do those only one per frame.
>> +      * Do the updates in the order of the processing flow.
>> +      */
>> +     rkisp1_params_isr(&dev->params_vdev, isp_mis);
>> +}
>> diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.h b/drivers/media/platform/rockchip/isp1/rkisp1.h
>> new file mode 100644
>> index 000000000000..274cafbe2d4d
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/rkisp1.h
>> @@ -0,0 +1,131 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses.  You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + *     Redistribution and use in source and binary forms, with or
>> + *     without modification, are permitted provided that the following
>> + *     conditions are met:
>> + *
>> + *      - Redistributions of source code must retain the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer.
>> + *
>> + *      - Redistributions in binary form must reproduce the above
>> + *        copyright notice, this list of conditions and the following
>> + *        disclaimer in the documentation and/or other materials
>> + *        provided with the distribution.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef _RKISP1_H
>> +#define _RKISP1_H
>> +
>> +#include <linux/platform_device.h>
>> +#include <media/v4l2-fwnode.h>
>> +#include "common.h"
>> +
>> +struct rkisp1_stream;
>> +
>> +/*
>> + * struct ispsd_in_fmt - ISP intput-pad format
>> + *
>> + * Translate mbus_code to hardware format values
>> + *
>> + * @bus_width: used for parallel
>> + */
>> +struct ispsd_in_fmt {
>> +     u32 mbus_code;
>> +     u8 fmt_type;
>> +     u32 mipi_dt;
>> +     u32 yuv_seq;
>> +     enum rkisp1_fmt_raw_pat_type bayer_pat;
>> +     u8 bus_width;
>> +};
>> +
>> +struct ispsd_out_fmt {
>> +     u32 mbus_code;
>> +     u8 fmt_type;
>> +};
>> +
>> +struct rkisp1_ie_config {
>> +     unsigned int effect;
>> +};
>> +
>> +enum rkisp1_isp_pad {
>> +     RKISP1_ISP_PAD_SINK,
>> +     RKISP1_ISP_PAD_SINK_PARAMS,
>> +     RKISP1_ISP_PAD_SOURCE_PATH,
>> +     RKISP1_ISP_PAD_SOURCE_STATS,
>> +     RKISP1_ISP_PAD_MAX
>> +};
>> +
>> +/*
>> + * struct rkisp1_isp_subdev - ISP sub-device
>> + *
>> + * See Cropping regions of ISP in rkisp1.c for details
>> + * @in_frm: input size, don't have to be equal to sensor size
>> + * @in_fmt: intput format
>> + * @in_crop: crop for sink pad
>> + * @out_fmt: output format
>> + * @out_crop: output size
>> + *
>> + * @dphy_errctrl_disabled: if dphy errctrl is disabled(avoid endless interrupt)
>> + * @frm_sync_seq: frame sequence, to sync frame_id between video devices.
>> + */
>> +struct rkisp1_isp_subdev {
>> +     struct v4l2_subdev sd;
>> +     struct media_pad pads[RKISP1_ISP_PAD_MAX];
>> +     struct v4l2_ctrl_handler ctrl_handler;
>> +     struct v4l2_mbus_framefmt in_frm;
>> +     struct ispsd_in_fmt in_fmt;
>> +     struct v4l2_rect in_crop;
>> +     struct ispsd_out_fmt out_fmt;
>> +     struct v4l2_rect out_crop;
>> +     bool dphy_errctrl_disabled;
>> +     atomic_t frm_sync_seq;
>> +};
>> +
>> +int rkisp1_register_isp_subdev(struct rkisp1_device *isp_dev,
>> +                            struct v4l2_device *v4l2_dev);
>> +
>> +void rkisp1_unregister_isp_subdev(struct rkisp1_device *isp_dev);
>> +
>> +void rkisp1_mipi_isr(unsigned int mipi_mis, struct rkisp1_device *dev);
>> +
>> +void rkisp1_isp_isr(unsigned int isp_mis, struct rkisp1_device *dev);
>> +
>> +/* Avoid direct access to rkisp1_isp_subdev in capture.c */
>> +static inline
>> +struct ispsd_out_fmt *rkisp1_get_ispsd_out_fmt(struct rkisp1_isp_subdev *isp_sdev)
>> +{
>> +     return &isp_sdev->out_fmt;
>> +}
>> +
>> +static inline
>> +struct ispsd_in_fmt *rkisp1_get_ispsd_in_fmt(struct rkisp1_isp_subdev *isp_sdev)
>> +{
>> +     return &isp_sdev->in_fmt;
>> +}
>> +
>> +static inline
>> +struct v4l2_rect *rkisp1_get_isp_sd_win(struct rkisp1_isp_subdev *isp_sdev)
>> +{
>> +     return &isp_sdev->out_crop;
>> +}
>> +
>> +#endif /* _RKISP1_H */
>>
>
> Perhaps when you post v4 you can split up this patch in 2 or 3 smaller patches.
> Certainly regs.[ch] can easily be put in a separate patch. It's hard to review
> a single very large patch like this.

Done, have put them in a separate patch.

>
> Regards,
>
>         Hans
diff mbox

Patch

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index fd0c99859d6f..062fffc9ffb6 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -117,6 +117,16 @@  config VIDEO_QCOM_CAMSS
 	select VIDEOBUF2_DMA_SG
 	select V4L2_FWNODE
 
+config VIDEO_ROCKCHIP_ISP1
+	tristate "Rockchip Image Signal Processing v1 Unit driver"
+	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on ARCH_ROCKCHIP || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	select V4L2_FWNODE
+	default n
+	---help---
+	  Support for ISP1 on the rockchip SoC.
+
 config VIDEO_S3C_CAMIF
 	tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
 	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 003b0bb2cddf..d235908df63e 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -67,6 +67,7 @@  obj-$(CONFIG_VIDEO_RENESAS_FDP1)	+= rcar_fdp1.o
 obj-$(CONFIG_VIDEO_RENESAS_JPU) 	+= rcar_jpu.o
 obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1/
 
+obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1)	+= rockchip/isp1/
 obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)	+= rockchip/rga/
 
 obj-y	+= omap/
diff --git a/drivers/media/platform/rockchip/isp1/Makefile b/drivers/media/platform/rockchip/isp1/Makefile
new file mode 100644
index 000000000000..8f52f959398e
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/Makefile
@@ -0,0 +1,7 @@ 
+obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += 	video_rkisp1.o
+video_rkisp1-objs 	   += 	rkisp1.o \
+				dev.o \
+				regs.o \
+				isp_stats.o \
+				isp_params.o \
+				capture.o
diff --git a/drivers/media/platform/rockchip/isp1/capture.c b/drivers/media/platform/rockchip/isp1/capture.c
new file mode 100644
index 000000000000..5e43b5420a45
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/capture.c
@@ -0,0 +1,1684 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-dma-contig.h>
+#include "dev.h"
+#include "regs.h"
+
+/*
+ * NOTE:
+ * 1. There are two capture video devices in rkisp1, selfpath and mainpath
+ * 2. Two capture device have separated memory-interface/crop/scale units.
+ * 3. Besides describing stream hardware, this file also contain entries for pipeline operations.
+ * 4. The register read/write operations in this file are put into regs.c.
+ */
+
+/*
+ * differences between selfpatch and mainpath
+ * available mp sink input: isp
+ * available sp sink input : isp, dma(TODO)
+ * available mp sink pad fmts: yuv422, raw
+ * available sp sink pad fmts: yuv422, yuv420......
+ * available mp source fmts: yuv, raw, jpeg(TODO)
+ * available sp source fmts: yuv, rgb
+ */
+
+#define CIF_ISP_REQ_BUFS_MIN 1
+#define CIF_ISP_REQ_BUFS_MAX 8
+
+#define STREAM_PAD_SINK				0
+#define STREAM_PAD_SOURCE			1
+
+#define STREAM_MAX_MP_RSZ_OUTPUT_WIDTH		4416
+#define STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT		3312
+#define STREAM_MAX_SP_RSZ_OUTPUT_WIDTH		1920
+#define STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT		1080
+#define STREAM_MIN_RSZ_OUTPUT_WIDTH		32
+#define STREAM_MIN_RSZ_OUTPUT_HEIGHT		16
+
+#define STREAM_MAX_MP_SP_INPUT_WIDTH STREAM_MAX_MP_RSZ_OUTPUT_WIDTH
+#define STREAM_MAX_MP_SP_INPUT_HEIGHT STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT
+#define STREAM_MIN_MP_SP_INPUT_WIDTH		32
+#define STREAM_MIN_MP_SP_INPUT_HEIGHT		32
+
+/* Get xsubs and ysubs for fourcc formats
+ *
+ * @xsubs: horizontal color samples in a 4*4 matrix, for yuv
+ * @ysubs: vertical color samples in a 4*4 matrix, for yuv
+ */
+static int fcc_xysubs(u32 fcc, u32 *xsubs, u32 *ysubs)
+{
+	switch (fcc) {
+	case V4L2_PIX_FMT_GREY:
+	case V4L2_PIX_FMT_YUV444M:
+		*xsubs = 1;
+		*ysubs = 1;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_YVYU:
+	case V4L2_PIX_FMT_VYUY:
+	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV61:
+	case V4L2_PIX_FMT_YVU422M:
+		*xsubs = 2;
+		*ysubs = 1;
+		break;
+	case V4L2_PIX_FMT_NV21:
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21M:
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		*xsubs = 2;
+		*ysubs = 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mbus_code_xysubs(u32 code, u32 *xsubs, u32 *ysubs)
+{
+	switch (code) {
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_VYUY8_1X16:
+		*xsubs = 2;
+		*ysubs = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mbus_code_sp_in_fmt(u32 code, u32 *format)
+{
+	switch (code) {
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+		*format = MI_CTRL_SP_INPUT_YUV422;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct capture_fmt mp_fmts[] = {
+	/* yuv422 */
+	{
+		.fourcc = V4L2_PIX_FMT_YUYV,
+		.fmt_type = FMT_YUV,
+		.bpp = { 16 },
+		.cplanes = 1,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_MP_WRITE_YUVINT,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YVYU,
+		.fmt_type = FMT_YUV,
+		.bpp = { 16 },
+		.cplanes = 1,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUVINT,
+	}, {
+		.fourcc = V4L2_PIX_FMT_VYUY,
+		.fmt_type = FMT_YUV,
+		.bpp = { 16 },
+		.cplanes = 1,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUVINT,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YUV422P,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 4, 4 },
+		.cplanes = 3,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV16,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV61,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YVU422M,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 3,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	},
+	/* yuv420 */
+	{
+		.fourcc = V4L2_PIX_FMT_NV21,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 2,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 2,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YVU420,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	},
+	/* yuv444 */
+	{
+		.fourcc = V4L2_PIX_FMT_YUV444M,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 3,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	},
+	/* yuv400 */
+	{
+		.fourcc = V4L2_PIX_FMT_GREY,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8 },
+		.cplanes = 1,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_MP_WRITE_YUVINT,
+	},
+	/* raw */
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB8,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 8 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SGRBG8,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 8 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SGBRG8,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 8 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SBGGR8,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 8 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SRGGB8,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 10 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_RAW12,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SGRBG10,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 10 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_RAW12,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SGBRG10,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 10 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_RAW12,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SBGGR10,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 10 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_RAW12,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SRGGB12,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 12 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_RAW12,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SGRBG12,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 12 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_RAW12,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SGBRG12,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 12 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_RAW12,
+	}, {
+		.fourcc = V4L2_PIX_FMT_SBGGR12,
+		.fmt_type = FMT_BAYER,
+		.bpp = { 12 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_MP_WRITE_RAW12,
+	},
+};
+
+static const struct capture_fmt sp_fmts[] = {
+	/* yuv422 */
+	{
+		.fourcc = V4L2_PIX_FMT_YUYV,
+		.fmt_type = FMT_YUV,
+		.bpp = { 16 },
+		.cplanes = 1,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_SP_WRITE_INT,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YVYU,
+		.fmt_type = FMT_YUV,
+		.bpp = { 16 },
+		.cplanes = 1,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_SP_WRITE_INT,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
+	}, {
+		.fourcc = V4L2_PIX_FMT_VYUY,
+		.fmt_type = FMT_YUV,
+		.bpp = { 16 },
+		.cplanes = 1,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_SP_WRITE_INT,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YUV422P,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_SP_WRITE_PLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV16,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_SP_WRITE_SPLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV61,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_SP_WRITE_SPLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YVU422M,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 3,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_SP_WRITE_PLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
+	},
+	/* yuv420 */
+	{
+		.fourcc = V4L2_PIX_FMT_NV21,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_SP_WRITE_SPLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_SP_WRITE_SPLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 2,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_SP_WRITE_SPLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 16 },
+		.cplanes = 2,
+		.mplanes = 2,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_SP_WRITE_SPLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_SP_WRITE_PLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
+	}, {
+		.fourcc = V4L2_PIX_FMT_YVU420,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 1,
+		.uv_swap = 1,
+		.write_format = MI_CTRL_SP_WRITE_PLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
+	},
+	/* yuv444 */
+	{
+		.fourcc = V4L2_PIX_FMT_YUV444M,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8, 8, 8 },
+		.cplanes = 3,
+		.mplanes = 3,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_SP_WRITE_PLA,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV444,
+	},
+	/* yuv400 */
+	{
+		.fourcc = V4L2_PIX_FMT_GREY,
+		.fmt_type = FMT_YUV,
+		.bpp = { 8 },
+		.cplanes = 1,
+		.mplanes = 1,
+		.uv_swap = 0,
+		.write_format = MI_CTRL_SP_WRITE_INT,
+		.output_format = MI_CTRL_SP_OUTPUT_YUV400,
+	},
+	/* rgb */
+	{
+		.fourcc = V4L2_PIX_FMT_RGB24,
+		.fmt_type = FMT_RGB,
+		.bpp = { 24 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_SP_WRITE_PLA,
+		.output_format = MI_CTRL_SP_OUTPUT_RGB888,
+	}, {
+		.fourcc = V4L2_PIX_FMT_RGB565,
+		.fmt_type = FMT_RGB,
+		.bpp = { 16 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_SP_WRITE_PLA,
+		.output_format = MI_CTRL_SP_OUTPUT_RGB565,
+	}, {
+		.fourcc = V4L2_PIX_FMT_BGR666,
+		.fmt_type = FMT_RGB,
+		.bpp = { 18 },
+		.mplanes = 1,
+		.write_format = MI_CTRL_SP_WRITE_PLA,
+		.output_format = MI_CTRL_SP_OUTPUT_RGB666,
+	},
+};
+
+static struct stream_config rkisp1_mp_stream_config = {
+	.fmts = mp_fmts,
+	.fmt_size = ARRAY_SIZE(mp_fmts),
+	/* constraints */
+	.max_rsz_width = STREAM_MAX_MP_RSZ_OUTPUT_WIDTH,
+	.max_rsz_height = STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT,
+	.min_rsz_width = STREAM_MIN_RSZ_OUTPUT_WIDTH,
+	.min_rsz_height = STREAM_MIN_RSZ_OUTPUT_HEIGHT,
+	/* registers */
+	.rsz = {
+		.ctrl = CIF_MRSZ_CTRL,
+		.scale_hy = CIF_MRSZ_SCALE_HY,
+		.scale_hcr = CIF_MRSZ_SCALE_HCR,
+		.scale_hcb = CIF_MRSZ_SCALE_HCB,
+		.scale_vy = CIF_MRSZ_SCALE_VY,
+		.scale_vc = CIF_MRSZ_SCALE_VC,
+		.scale_lut = CIF_MRSZ_SCALE_LUT,
+		.scale_lut_addr = CIF_MRSZ_SCALE_LUT_ADDR,
+		.scale_hy_shd = CIF_MRSZ_SCALE_HY_SHD,
+		.scale_hcr_shd = CIF_MRSZ_SCALE_HCR_SHD,
+		.scale_hcb_shd = CIF_MRSZ_SCALE_HCB_SHD,
+		.scale_vy_shd = CIF_MRSZ_SCALE_VY_SHD,
+		.scale_vc_shd = CIF_MRSZ_SCALE_VC_SHD,
+		.phase_hy = CIF_MRSZ_PHASE_HY,
+		.phase_hc = CIF_MRSZ_PHASE_HC,
+		.phase_vy = CIF_MRSZ_PHASE_VY,
+		.phase_vc = CIF_MRSZ_PHASE_VC,
+		.ctrl_shd = CIF_MRSZ_CTRL_SHD,
+		.phase_hy_shd = CIF_MRSZ_PHASE_HY_SHD,
+		.phase_hc_shd = CIF_MRSZ_PHASE_HC_SHD,
+		.phase_vy_shd = CIF_MRSZ_PHASE_VY_SHD,
+		.phase_vc_shd = CIF_MRSZ_PHASE_VC_SHD,
+	},
+	.dual_crop = {
+		.ctrl = CIF_DUAL_CROP_CTRL,
+		.yuvmode_mask = CIF_DUAL_CROP_MP_MODE_YUV,
+		.rawmode_mask = CIF_DUAL_CROP_MP_MODE_RAW,
+		.h_offset = CIF_DUAL_CROP_M_H_OFFS,
+		.v_offset = CIF_DUAL_CROP_M_V_OFFS,
+		.h_size = CIF_DUAL_CROP_M_H_SIZE,
+		.v_size = CIF_DUAL_CROP_M_V_SIZE,
+	},
+	.mi = {
+		.y_size_init = CIF_MI_MP_Y_SIZE_INIT,
+		.cb_size_init = CIF_MI_MP_CB_SIZE_INIT,
+		.cr_size_init = CIF_MI_MP_CR_SIZE_INIT,
+		.y_base_ad_init = CIF_MI_MP_Y_BASE_AD_INIT,
+		.cb_base_ad_init = CIF_MI_MP_CB_BASE_AD_INIT,
+		.cr_base_ad_init = CIF_MI_MP_CR_BASE_AD_INIT,
+		.y_offs_cnt_init = CIF_MI_MP_Y_OFFS_CNT_INIT,
+		.cb_offs_cnt_init = CIF_MI_MP_CB_OFFS_CNT_INIT,
+		.cr_offs_cnt_init = CIF_MI_MP_CR_OFFS_CNT_INIT,
+	},
+};
+
+static struct stream_config rkisp1_sp_stream_config = {
+	.fmts = sp_fmts,
+	.fmt_size = ARRAY_SIZE(sp_fmts),
+	/* constraints */
+	.max_rsz_width = STREAM_MAX_SP_RSZ_OUTPUT_WIDTH,
+	.max_rsz_height = STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT,
+	.min_rsz_width = STREAM_MIN_RSZ_OUTPUT_WIDTH,
+	.min_rsz_height = STREAM_MIN_RSZ_OUTPUT_HEIGHT,
+	/* registers */
+	.rsz = {
+		.ctrl = CIF_SRSZ_CTRL,
+		.scale_hy = CIF_SRSZ_SCALE_HY,
+		.scale_hcr = CIF_SRSZ_SCALE_HCR,
+		.scale_hcb = CIF_SRSZ_SCALE_HCB,
+		.scale_vy = CIF_SRSZ_SCALE_VY,
+		.scale_vc = CIF_SRSZ_SCALE_VC,
+		.scale_lut = CIF_SRSZ_SCALE_LUT,
+		.scale_lut_addr = CIF_SRSZ_SCALE_LUT_ADDR,
+		.scale_hy_shd = CIF_SRSZ_SCALE_HY_SHD,
+		.scale_hcr_shd = CIF_SRSZ_SCALE_HCR_SHD,
+		.scale_hcb_shd = CIF_SRSZ_SCALE_HCB_SHD,
+		.scale_vy_shd = CIF_SRSZ_SCALE_VY_SHD,
+		.scale_vc_shd = CIF_SRSZ_SCALE_VC_SHD,
+		.phase_hy = CIF_SRSZ_PHASE_HY,
+		.phase_hc = CIF_SRSZ_PHASE_HC,
+		.phase_vy = CIF_SRSZ_PHASE_VY,
+		.phase_vc = CIF_SRSZ_PHASE_VC,
+		.ctrl_shd = CIF_SRSZ_CTRL_SHD,
+		.phase_hy_shd = CIF_SRSZ_PHASE_HY_SHD,
+		.phase_hc_shd = CIF_SRSZ_PHASE_HC_SHD,
+		.phase_vy_shd = CIF_SRSZ_PHASE_VY_SHD,
+		.phase_vc_shd = CIF_SRSZ_PHASE_VC_SHD,
+	},
+	.dual_crop = {
+		.ctrl = CIF_DUAL_CROP_CTRL,
+		.yuvmode_mask = CIF_DUAL_CROP_SP_MODE_YUV,
+		.rawmode_mask = CIF_DUAL_CROP_SP_MODE_RAW,
+		.h_offset = CIF_DUAL_CROP_S_H_OFFS,
+		.v_offset = CIF_DUAL_CROP_S_V_OFFS,
+		.h_size = CIF_DUAL_CROP_S_H_SIZE,
+		.v_size = CIF_DUAL_CROP_S_V_SIZE,
+	},
+	.mi = {
+		.y_size_init = CIF_MI_SP_Y_SIZE_INIT,
+		.cb_size_init = CIF_MI_SP_CB_SIZE_INIT,
+		.cr_size_init = CIF_MI_SP_CR_SIZE_INIT,
+		.y_base_ad_init = CIF_MI_SP_Y_BASE_AD_INIT,
+		.cb_base_ad_init = CIF_MI_SP_CB_BASE_AD_INIT,
+		.cr_base_ad_init = CIF_MI_SP_CR_BASE_AD_INIT,
+		.y_offs_cnt_init = CIF_MI_SP_Y_OFFS_CNT_INIT,
+		.cb_offs_cnt_init = CIF_MI_SP_CB_OFFS_CNT_INIT,
+		.cr_offs_cnt_init = CIF_MI_SP_CR_OFFS_CNT_INIT,
+	},
+};
+
+static const
+struct capture_fmt *find_fmt(struct rkisp1_stream *stream, const u32 pixelfmt)
+{
+	const struct capture_fmt *fmt;
+	int i;
+
+	for (i = 0; i < stream->config->fmt_size; i++) {
+		fmt = &stream->config->fmts[i];
+		if (fmt->fourcc == pixelfmt)
+			return fmt;
+	}
+	return NULL;
+}
+
+/* configure dual-crop unit */
+static int rkisp1_config_dcrop(struct rkisp1_stream *stream, bool async)
+{
+	struct rkisp1_device *dev = stream->ispdev;
+	struct v4l2_rect *dcrop = &stream->dcrop;
+	struct v4l2_rect *input_win;
+
+	/* dual-crop unit get data from isp */
+	input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
+
+	if (dcrop->width == input_win->width &&
+	    dcrop->height == input_win->height &&
+	    dcrop->left == 0 && dcrop->top == 0) {
+		disable_dcrop(stream, async);
+		v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+			 "stream %d crop disabled\n", stream->id);
+		return 0;
+	}
+
+	config_dcrop(stream, dcrop, async);
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		 "stream %d crop: %dx%d -> %dx%d\n", stream->id,
+		 input_win->width, input_win->height,
+		 dcrop->width, dcrop->height);
+
+	return 0;
+}
+
+/* configure scale unit */
+static int rkisp1_config_rsz(struct rkisp1_stream *stream, bool async)
+{
+	struct rkisp1_device *dev = stream->ispdev;
+	struct v4l2_pix_format_mplane output_fmt = stream->out_fmt;
+	struct capture_fmt *output_isp_fmt = &stream->out_isp_fmt;
+	struct ispsd_out_fmt *input_isp_fmt =
+			rkisp1_get_ispsd_out_fmt(&dev->isp_sdev);
+	struct v4l2_rect in_y, in_c, out_y, out_c;
+	u32 xsubs_in, ysubs_in, xsubs_out, ysubs_out;
+
+	if (input_isp_fmt->fmt_type == FMT_BAYER)
+		goto disable;
+
+	/* set input and output sizes for scale calculation */
+	in_y.width = stream->dcrop.width;
+	in_y.height = stream->dcrop.height;
+	out_y.width = output_fmt.width;
+	out_y.height = output_fmt.height;
+
+	/* The size of Cb,Cr are related to the format */
+	if (mbus_code_xysubs(input_isp_fmt->mbus_code, &xsubs_in, &ysubs_in)) {
+		v4l2_err(&dev->v4l2_dev, "Not xsubs/ysubs found\n");
+		return -EINVAL;
+	}
+	in_c.width = in_y.width / xsubs_in;
+	in_c.height = in_y.height / ysubs_in;
+
+	if (output_isp_fmt->fmt_type == FMT_YUV) {
+		fcc_xysubs(output_isp_fmt->fourcc, &xsubs_out, &ysubs_out);
+		out_c.width = out_y.width / xsubs_out;
+		out_c.height = out_y.height / ysubs_out;
+	} else {
+		out_c.width = out_y.width / xsubs_in;
+		out_c.height = out_y.height / ysubs_in;
+	}
+
+	if (in_c.width == out_c.width && in_c.height == out_c.height)
+		goto disable;
+
+	/* set RSZ input and output */
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		 "stream %d rsz/scale: %dx%d -> %dx%d\n",
+		 stream->id, stream->dcrop.width, stream->dcrop.height,
+		 output_fmt.width, output_fmt.height);
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		 "chroma scaling %dx%d -> %dx%d\n",
+		 in_c.width, in_c.height, out_c.width, out_c.height);
+
+	/* calculate and set scale */
+	config_rsz(stream, &in_y, &in_c, &out_y, &out_c, async);
+
+	if (rkisp1_debug)
+		dump_rsz_regs(stream);
+
+	return 0;
+
+disable:
+	disable_rsz(stream, async);
+
+	return 0;
+}
+
+/***************************** stream operations*******************************/
+
+/*
+ * configure memory interface for mainpath
+ * This should only be called when stream-on
+ */
+static int mp_config_mi(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+       /*
+	* NOTE: plane_fmt[0].sizeimage is total size of all planes for single
+	* memory plane formats, so calculate the size explicitly.
+	*/
+	mi_set_y_size(stream, stream->out_fmt.plane_fmt[0].bytesperline *
+			 stream->out_fmt.height);
+	mi_set_cb_size(stream, stream->out_fmt.plane_fmt[1].sizeimage);
+	mi_set_cr_size(stream, stream->out_fmt.plane_fmt[2].sizeimage);
+
+	mp_frame_end_int_enable(base);
+	if (stream->out_isp_fmt.uv_swap)
+		mp_set_uv_swap(base);
+
+	config_mi_ctrl(stream);
+	mp_mi_ctrl_set_format(base, stream->out_isp_fmt.write_format);
+	mp_mi_ctrl_autoupdate_en(base);
+
+	return 0;
+}
+
+/*
+ * configure memory interface for selfpath
+ * This should only be called when stream-on
+ */
+static int sp_config_mi(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+	struct rkisp1_device *dev = stream->ispdev;
+	struct capture_fmt *output_isp_fmt = &stream->out_isp_fmt;
+	struct ispsd_out_fmt *input_isp_fmt =
+			rkisp1_get_ispsd_out_fmt(&dev->isp_sdev);
+	u32 sp_in_fmt;
+
+	if (mbus_code_sp_in_fmt(input_isp_fmt->mbus_code, &sp_in_fmt)) {
+		v4l2_err(&dev->v4l2_dev, "Can't find the input format\n");
+		return -EINVAL;
+	}
+       /*
+	* NOTE: plane_fmt[0].sizeimage is total size of all planes for single
+	* memory plane formats, so calculate the size explicitly.
+	*/
+	mi_set_y_size(stream, stream->out_fmt.plane_fmt[0].bytesperline *
+		      stream->out_fmt.height);
+	mi_set_cb_size(stream, stream->out_fmt.plane_fmt[1].sizeimage);
+	mi_set_cr_size(stream, stream->out_fmt.plane_fmt[2].sizeimage);
+
+	sp_set_y_width(base, stream->out_fmt.width);
+	sp_set_y_height(base, stream->out_fmt.height);
+	sp_set_y_line_length(base, stream->u.sp.y_stride);
+
+	sp_frame_end_int_enable(base);
+	if (output_isp_fmt->uv_swap)
+		sp_set_uv_swap(base);
+
+	config_mi_ctrl(stream);
+	sp_mi_ctrl_set_format(base, stream->out_isp_fmt.write_format |
+			      sp_in_fmt | output_isp_fmt->output_format);
+
+	sp_mi_ctrl_autoupdate_en(base);
+
+	return 0;
+}
+
+static void mp_enable_mi(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+	struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
+
+	mi_ctrl_mp_disable(base);
+	if (isp_fmt->fmt_type == FMT_BAYER)
+		mi_ctrl_mpraw_enable(base);
+	else if (isp_fmt->fmt_type == FMT_YUV)
+		mi_ctrl_mpyuv_enable(base);
+}
+
+static void sp_enable_mi(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	mi_ctrl_spyuv_enable(base);
+}
+
+static void mp_disable_mi(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	mi_ctrl_mp_disable(base);
+}
+
+static void sp_disable_mi(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	mi_ctrl_spyuv_disable(base);
+}
+
+/* Update buffer info to memory interface, it's called in interrupt */
+static void update_mi(struct rkisp1_stream *stream)
+{
+	struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
+
+	/* The dummy space allocated by dma_alloc_coherent is used, we can
+	 * throw data to it if there is no available buffer.
+	 */
+	if (stream->next_buf) {
+		mi_set_y_addr(stream,
+			stream->next_buf->buff_addr[RKISP1_PLANE_Y]);
+		mi_set_cb_addr(stream,
+			stream->next_buf->buff_addr[RKISP1_PLANE_CB]);
+		mi_set_cr_addr(stream,
+			stream->next_buf->buff_addr[RKISP1_PLANE_CR]);
+	} else {
+		v4l2_dbg(1, rkisp1_debug, &stream->ispdev->v4l2_dev,
+			 "stream %d: to dummy buf\n", stream->id);
+		mi_set_y_addr(stream, dummy_buf->dma_addr);
+		mi_set_cb_addr(stream, dummy_buf->dma_addr);
+		mi_set_cr_addr(stream, dummy_buf->dma_addr);
+	}
+
+	mi_set_y_offset(stream, 0);
+	mi_set_cb_offset(stream, 0);
+	mi_set_cr_offset(stream, 0);
+}
+
+static void mp_stop_mi(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	if (stream->state != RKISP1_STATE_STREAMING)
+		return;
+	stream->ops->clr_frame_end_int(base);
+	stream->ops->disable_mi(stream);
+}
+
+static void sp_stop_mi(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	if (stream->state != RKISP1_STATE_STREAMING)
+		return;
+	stream->ops->clr_frame_end_int(base);
+	stream->ops->disable_mi(stream);
+}
+
+static struct streams_ops rkisp1_mp_streams_ops = {
+	.config_mi = mp_config_mi,
+	.enable_mi = mp_enable_mi,
+	.disable_mi = mp_disable_mi,
+	.stop_mi = mp_stop_mi,
+	.set_data_path = mp_set_data_path,
+	.clr_frame_end_int = mp_clr_frame_end_int,
+	.is_frame_end_int_masked = mp_is_frame_end_int_masked,
+	.is_stream_stopped = mp_is_stream_stopped,
+};
+
+static struct streams_ops rkisp1_sp_streams_ops = {
+	.config_mi = sp_config_mi,
+	.enable_mi = sp_enable_mi,
+	.disable_mi = sp_disable_mi,
+	.stop_mi = sp_stop_mi,
+	.set_data_path = sp_set_data_path,
+	.clr_frame_end_int = sp_clr_frame_end_int,
+	.is_frame_end_int_masked = sp_is_frame_end_int_masked,
+	.is_stream_stopped = sp_is_stream_stopped,
+};
+
+/*
+ * This function is called when a frame end come. The next frame
+ * is processing and we should set up buffer for next-next frame,
+ * otherwise it will overflow.
+ */
+static int mi_frame_end(struct rkisp1_stream *stream)
+{
+	struct rkisp1_device *isp_dev = stream->ispdev;
+	struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
+	struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
+	unsigned long lock_flags = 0;
+	int i = 0;
+
+	if (stream->curr_buf) {
+		/* Dequeue a filled buffer */
+		for (i = 0; i < isp_fmt->mplanes; i++) {
+			u32 payload_size =
+				stream->out_fmt.plane_fmt[i].sizeimage;
+			vb2_set_plane_payload(
+				&stream->curr_buf->vb.vb2_buf, i,
+				payload_size);
+		}
+		stream->curr_buf->vb.sequence =
+				atomic_read(&isp_sd->frm_sync_seq) - 1;
+		stream->curr_buf->vb.vb2_buf.timestamp = ktime_get_ns();
+		vb2_buffer_done(&stream->curr_buf->vb.vb2_buf,
+				VB2_BUF_STATE_DONE);
+	}
+
+	/* Next frame is writing to it */
+	stream->curr_buf = stream->next_buf;
+	stream->next_buf = NULL;
+
+	/* Set up an empty buffer for the next-next frame */
+	spin_lock_irqsave(&stream->vbq_lock, lock_flags);
+	if (!list_empty(&stream->buf_queue)) {
+		stream->next_buf = list_first_entry(&stream->buf_queue,
+					struct rkisp1_buffer, queue);
+		list_del(&stream->next_buf->queue);
+	}
+
+	spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
+
+	update_mi(stream);
+
+	return 0;
+}
+
+/***************************** vb2 operations*******************************/
+
+/*
+ * Set flags and wait, it should stop in interrupt.
+ * If it didn't, stop it by force.
+ */
+static void rkisp1_stream_stop(struct rkisp1_stream *stream)
+{
+	struct rkisp1_device *dev = stream->ispdev;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	int ret = 0;
+
+	stream->stopping = true;
+	ret = wait_event_timeout(stream->done,
+				 stream->state != RKISP1_STATE_STREAMING,
+				 msecs_to_jiffies(1000));
+	if (!ret) {
+		v4l2_warn(v4l2_dev, "waiting on event return error %d\n", ret);
+		stream->ops->stop_mi(stream);
+		stream->stopping = false;
+		stream->state = RKISP1_STATE_READY;
+	}
+	disable_dcrop(stream, true);
+	disable_rsz(stream, true);
+}
+
+static int rkisp1_start(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+	int ret;
+
+	stream->ops->set_data_path(base);
+	ret = stream->ops->config_mi(stream);
+	if (ret)
+		return ret;
+
+	/* Set up an buffer for the next frame */
+	mi_frame_end(stream);
+	stream->ops->enable_mi(stream);
+	stream->state = RKISP1_STATE_STREAMING;
+
+	return 0;
+}
+
+static int rkisp1_queue_setup(struct vb2_queue *queue,
+			      unsigned int *num_buffers,
+			      unsigned int *num_planes,
+			      unsigned int sizes[],
+			      struct device *alloc_devs[])
+{
+	struct rkisp1_stream *stream = queue->drv_priv;
+	struct rkisp1_device *dev = stream->ispdev;
+	const struct v4l2_pix_format_mplane *pixm = &stream->out_fmt;
+	const struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
+	u32 i;
+
+	*num_planes = isp_fmt->mplanes;
+
+	for (i = 0; i < isp_fmt->mplanes; i++) {
+		const struct v4l2_plane_pix_format *plane_fmt;
+
+		plane_fmt = &pixm->plane_fmt[i];
+		sizes[i] = plane_fmt->sizeimage;
+	}
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "%s count %d, size %d\n",
+		 v4l2_type_names[queue->type], *num_buffers, sizes[0]);
+
+	return 0;
+}
+
+/*
+ * The vb2_buffer are stored in rkisp1_buffer, in order to unify
+ * mplane buffer and none-mplane buffer.
+ */
+static void rkisp1_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct rkisp1_buffer *ispbuf = to_rkisp1_buffer(vbuf);
+	struct vb2_queue *queue = vb->vb2_queue;
+	struct rkisp1_stream *stream = queue->drv_priv;
+	unsigned long lock_flags = 0;
+	struct v4l2_pix_format_mplane *pixm = &stream->out_fmt;
+	struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
+	int i;
+
+	memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr));
+	for (i = 0; i < isp_fmt->mplanes; i++)
+		ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
+
+	if (isp_fmt->mplanes == 1) {
+		for (i = 0; i < isp_fmt->cplanes - 1; i++) {
+			ispbuf->buff_addr[i + 1] =
+				ispbuf->buff_addr[i] +
+				pixm->plane_fmt[i].bytesperline *
+				pixm->height;
+		}
+	}
+
+	spin_lock_irqsave(&stream->vbq_lock, lock_flags);
+	list_add_tail(&ispbuf->queue, &stream->buf_queue);
+	spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
+}
+
+static int rkisp1_create_dummy_buf(struct rkisp1_stream *stream)
+{
+	struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
+	struct rkisp1_device *dev = stream->ispdev;
+
+	/* get a maximum size */
+	dummy_buf->size = max3(stream->out_fmt.plane_fmt[0].bytesperline *
+		stream->out_fmt.height,
+		stream->out_fmt.plane_fmt[1].sizeimage,
+		stream->out_fmt.plane_fmt[2].sizeimage);
+
+	dummy_buf->vaddr = dma_alloc_coherent(dev->dev, dummy_buf->size,
+					      &dummy_buf->dma_addr,
+					      GFP_KERNEL);
+	if (!dummy_buf->vaddr) {
+		v4l2_err(&dev->v4l2_dev,
+			 "Failed to allocate the memory for dummy buffer\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void rkisp1_destroy_dummy_buf(struct rkisp1_stream *stream)
+{
+	struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
+	struct rkisp1_device *dev = stream->ispdev;
+
+	dma_free_coherent(dev->dev, dummy_buf->size,
+			  dummy_buf->vaddr, dummy_buf->dma_addr);
+}
+
+static void rkisp1_stop_streaming(struct vb2_queue *queue)
+{
+	struct rkisp1_stream *stream = queue->drv_priv;
+	struct rkisp1_vdev_node *node = &stream->vnode;
+	struct rkisp1_device *dev = stream->ispdev;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	struct rkisp1_buffer *buf;
+	unsigned long lock_flags = 0;
+	int ret;
+
+	rkisp1_stream_stop(stream);
+	/* call to the other devices */
+	media_pipeline_stop(&node->vdev.entity);
+	ret = dev->pipe.set_stream(&dev->pipe, false);
+	if (ret < 0)
+		return;
+
+	/* release buffers */
+	spin_lock_irqsave(&stream->vbq_lock, lock_flags);
+	if (stream->curr_buf) {
+		list_add_tail(&stream->curr_buf->queue, &stream->buf_queue);
+		stream->curr_buf = NULL;
+	}
+	if (stream->next_buf) {
+		list_add_tail(&stream->next_buf->queue, &stream->buf_queue);
+		stream->next_buf = NULL;
+	}
+	while (!list_empty(&stream->buf_queue)) {
+		buf = list_first_entry(&stream->buf_queue,
+				       struct rkisp1_buffer, queue);
+		list_del(&buf->queue);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+	}
+	spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
+
+	ret = dev->pipe.close(&dev->pipe);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret);
+		return;
+	}
+
+	rkisp1_destroy_dummy_buf(stream);
+}
+
+static int rkisp1_stream_start(struct rkisp1_stream *stream)
+{
+	struct v4l2_device *v4l2_dev = &stream->ispdev->v4l2_dev;
+	int ret;
+
+	ret = rkisp1_config_rsz(stream, false);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "config rsz failed with error %d\n", ret);
+		return ret;
+	}
+
+	ret = rkisp1_config_dcrop(stream, false);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "config dcrop failed with error %d\n", ret);
+		return ret;
+	}
+
+	return rkisp1_start(stream);
+}
+
+static int
+rkisp1_start_streaming(struct vb2_queue *queue, unsigned int count)
+{
+	struct rkisp1_stream *stream = queue->drv_priv;
+	struct rkisp1_vdev_node *node = &stream->vnode;
+	struct rkisp1_device *dev = stream->ispdev;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	int ret;
+
+	if (stream->state != RKISP1_STATE_READY) {
+		v4l2_err(v4l2_dev, "stream %d in bad state(%d) for streaming\n",
+			 stream->id, stream->state);
+		return -EBUSY;
+	}
+
+	ret = rkisp1_create_dummy_buf(stream);
+	if (ret < 0)
+		return ret;
+
+	/* enable clocks/power-domains */
+	ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "open cif pipeline failed %d\n", ret);
+		goto destroy_dummy_buf;
+	}
+
+	/* configure stream hardware to start */
+	ret = rkisp1_stream_start(stream);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "start streaming failed\n");
+		goto close_pipe;
+	}
+
+	/* start sub-devices */
+	ret = dev->pipe.set_stream(&dev->pipe, true);
+	if (ret < 0)
+		goto stop_stream;
+
+	ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "start pipeline failed %d\n", ret);
+		goto pipe_stream_off;
+	}
+
+	return 0;
+
+pipe_stream_off:
+	dev->pipe.set_stream(&dev->pipe, false);
+stop_stream:
+	rkisp1_stream_stop(stream);
+close_pipe:
+	dev->pipe.close(&dev->pipe);
+destroy_dummy_buf:
+	rkisp1_destroy_dummy_buf(stream);
+
+	return ret;
+}
+
+static struct vb2_ops rkisp1_vb2_ops = {
+	.queue_setup = rkisp1_queue_setup,
+	.buf_queue = rkisp1_buf_queue,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.stop_streaming = rkisp1_stop_streaming,
+	.start_streaming = rkisp1_start_streaming,
+};
+
+static int rkisp_init_vb2_queue(struct vb2_queue *q,
+				struct rkisp1_stream *stream,
+				enum v4l2_buf_type buf_type)
+{
+	struct rkisp1_vdev_node *node;
+
+	node = queue_to_node(q);
+
+	q->type = buf_type;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
+	q->drv_priv = stream;
+	q->ops = &rkisp1_vb2_ops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct rkisp1_buffer);
+	q->min_buffers_needed = CIF_ISP_REQ_BUFS_MIN;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &node->vlock;
+	q->dev = stream->ispdev->dev;
+
+	return vb2_queue_init(q);
+}
+
+static void rkisp1_set_fmt(struct rkisp1_stream *stream,
+			   struct v4l2_pix_format_mplane *pixm,
+			   bool try)
+{
+	const struct capture_fmt *fmt;
+	const struct stream_config *config = stream->config;
+	struct rkisp1_stream *other_stream =
+			&stream->ispdev->stream[!stream->id];
+	unsigned int imagsize = 0;
+	unsigned int planes;
+	u32 xsubs = 1, ysubs = 1;
+	int i;
+
+	fmt = find_fmt(stream, pixm->pixelformat);
+	if (!fmt)
+		fmt = config->fmts;
+
+	/* do checks on resolution */
+	pixm->width = clamp_t(u32, pixm->width, config->min_rsz_width,
+			      config->max_rsz_width);
+	pixm->height = clamp_t(u32, pixm->height, config->min_rsz_height,
+			      config->max_rsz_height);
+	pixm->num_planes = fmt->mplanes;
+	pixm->field = V4L2_FIELD_NONE;
+
+	/* output full range by default, take effect in isp_params */
+	if (!pixm->quantization)
+		pixm->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+	/* can not change quantization when stream-on */
+	if (other_stream->state == RKISP1_STATE_STREAMING)
+		pixm->quantization = other_stream->out_fmt.quantization;
+
+	/* calculate size */
+	fcc_xysubs(fmt->fourcc, &xsubs, &ysubs);
+	planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes;
+	for (i = 0; i < planes; i++) {
+		struct v4l2_plane_pix_format *plane_fmt;
+		int width, height, bytesperline;
+
+		plane_fmt = pixm->plane_fmt + i;
+
+		if (i == 0) {
+			width = pixm->width;
+			height = pixm->height;
+		} else {
+			width = pixm->width / xsubs;
+			height = pixm->height / ysubs;
+		}
+
+		bytesperline = width * DIV_ROUND_UP(fmt->bpp[i], 8);
+		/* stride is only available for sp stream and y plane */
+		if (stream->id != RKISP1_STREAM_SP || i != 0 ||
+		    plane_fmt->bytesperline < bytesperline)
+			plane_fmt->bytesperline = bytesperline;
+
+		plane_fmt->sizeimage = plane_fmt->bytesperline * height;
+
+		imagsize += plane_fmt->sizeimage;
+	}
+
+	/* convert to non-MPLANE format.
+	 * it's important since we want to unify none-MPLANE
+	 * and MPLANE.
+	 */
+	if (fmt->mplanes == 1)
+		pixm->plane_fmt[0].sizeimage = imagsize;
+
+	if (!try) {
+		stream->out_isp_fmt = *fmt;
+		stream->out_fmt = *pixm;
+
+		if (stream->id == RKISP1_STREAM_SP) {
+			stream->u.sp.y_stride =
+				pixm->plane_fmt[0].bytesperline /
+				DIV_ROUND_UP(fmt->bpp[0], 8);
+		} else {
+			stream->u.mp.raw_enable = (fmt->fmt_type == FMT_BAYER);
+		}
+		v4l2_dbg(1, rkisp1_debug, &stream->ispdev->v4l2_dev,
+			 "%s: stream: %d req(%d, %d) out(%d, %d)\n", __func__,
+			 stream->id, pixm->width, pixm->height,
+			 stream->out_fmt.width, stream->out_fmt.height);
+
+		/* set quantization to isp_params */
+		rkisp1_configure_isp(NULL, NULL, pixm->quantization);
+	}
+}
+
+/************************* v4l2_file_operations***************************/
+void rkisp1_stream_init(struct rkisp1_device *dev, u32 id)
+{
+	struct rkisp1_stream *stream = &dev->stream[id];
+	struct v4l2_pix_format_mplane pixm;
+
+	memset(stream, 0, sizeof(*stream));
+	stream->id = id;
+	stream->ispdev = dev;
+
+	INIT_LIST_HEAD(&stream->buf_queue);
+	init_waitqueue_head(&stream->done);
+	spin_lock_init(&stream->vbq_lock);
+	if (stream->id == RKISP1_STREAM_SP) {
+		stream->ops = &rkisp1_sp_streams_ops;
+		stream->config = &rkisp1_sp_stream_config;
+	} else {
+		stream->ops = &rkisp1_mp_streams_ops;
+		stream->config = &rkisp1_mp_stream_config;
+	}
+
+	stream->state = RKISP1_STATE_READY;
+
+	memset(&pixm, 0, sizeof(pixm));
+	pixm.pixelformat = V4L2_PIX_FMT_YUYV;
+	pixm.width = RKISP1_DEFAULT_WIDTH;
+	pixm.height = RKISP1_DEFAULT_HEIGHT;
+	rkisp1_set_fmt(stream, &pixm, false);
+
+	stream->dcrop.left = 0;
+	stream->dcrop.top = 0;
+	stream->dcrop.width = RKISP1_DEFAULT_WIDTH;
+	stream->dcrop.height = RKISP1_DEFAULT_HEIGHT;
+}
+
+static const struct v4l2_file_operations rkisp1_fops = {
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.unlocked_ioctl = video_ioctl2,
+	.poll = vb2_fop_poll,
+	.mmap = vb2_fop_mmap,
+};
+
+/*
+ * mp and sp v4l2_ioctl_ops
+ */
+
+/* keep for compatibility */
+static int rkisp1_enum_input(struct file *file, void *priv,
+			     struct v4l2_input *input)
+{
+	if (input->index > 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rkisp1_try_fmt_vid_cap_mplane(struct file *file, void *fh,
+					 struct v4l2_format *f)
+{
+	struct rkisp1_stream *stream = video_drvdata(file);
+
+	rkisp1_set_fmt(stream, &f->fmt.pix_mp, true);
+
+	return 0;
+}
+
+static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
+					  struct v4l2_fmtdesc *f)
+{
+	struct rkisp1_stream *stream = video_drvdata(file);
+	const struct capture_fmt *fmt = NULL;
+
+	if (f->index >= stream->config->fmt_size)
+		return -EINVAL;
+
+	fmt = &stream->config->fmts[f->index];
+	f->pixelformat = fmt->fourcc;
+
+	return 0;
+}
+
+static int rkisp1_s_fmt_vid_cap_mplane(struct file *file,
+				       void *priv, struct v4l2_format *f)
+{
+	struct rkisp1_stream *stream = video_drvdata(file);
+	struct video_device *vdev = &stream->vnode.vdev;
+	struct rkisp1_vdev_node *node = vdev_to_node(vdev);
+	struct rkisp1_device *dev = stream->ispdev;
+
+	if (vb2_is_busy(&node->buf_queue)) {
+		v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
+		return -EBUSY;
+	}
+
+	rkisp1_set_fmt(stream, &f->fmt.pix_mp, false);
+
+	return 0;
+}
+
+static int rkisp1_g_fmt_vid_cap_mplane(struct file *file, void *fh,
+				       struct v4l2_format *f)
+{
+	struct rkisp1_stream *stream = video_drvdata(file);
+
+	f->fmt.pix_mp = stream->out_fmt;
+
+	return 0;
+}
+
+static int rkisp1_g_selection(struct file *file, void *prv,
+			      struct v4l2_selection *sel)
+{
+	struct rkisp1_stream *stream = video_drvdata(file);
+	struct rkisp1_device *dev = stream->ispdev;
+	struct v4l2_rect *dcrop = &stream->dcrop;
+	struct v4l2_rect *input_win;
+
+	input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		sel->r.width = input_win->width;
+		sel->r.height = input_win->height;
+		sel->r.left = 0;
+		sel->r.top = 0;
+		break;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = *dcrop;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct v4l2_rect *rkisp1_update_crop(struct rkisp1_stream *stream,
+					    struct v4l2_rect *sel,
+					    const struct v4l2_rect *in)
+{
+	/* Not crop for MP bayer raw data */
+	if (stream->id == RKISP1_STREAM_MP &&
+	    stream->out_isp_fmt.fmt_type == FMT_BAYER) {
+		sel->left = 0;
+		sel->top = 0;
+		sel->width = in->width;
+		sel->height = in->height;
+		return sel;
+	}
+
+	sel->left = ALIGN(sel->left, 2);
+	sel->width = ALIGN(sel->width, 2);
+	sel->left = clamp_t(u32, sel->left, 0,
+			    in->width - STREAM_MIN_MP_SP_INPUT_WIDTH);
+	sel->top = clamp_t(u32, sel->top, 0,
+			   in->height - STREAM_MIN_MP_SP_INPUT_HEIGHT);
+	sel->width = clamp_t(u32, sel->width, STREAM_MIN_MP_SP_INPUT_WIDTH,
+			     in->width - sel->left);
+	sel->height = clamp_t(u32, sel->height, STREAM_MIN_MP_SP_INPUT_HEIGHT,
+			      in->height - sel->top);
+	return sel;
+}
+
+static int rkisp1_s_selection(struct file *file, void *prv,
+			      struct v4l2_selection *sel)
+{
+	struct rkisp1_stream *stream = video_drvdata(file);
+	struct rkisp1_device *dev = stream->ispdev;
+	struct v4l2_rect *dcrop = &stream->dcrop;
+	const struct v4l2_rect *input_win;
+
+	input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
+
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	if (sel->flags != 0)
+		return -EINVAL;
+
+	if (sel->target == V4L2_SEL_TGT_CROP) {
+		*dcrop = *rkisp1_update_crop(stream, &sel->r, input_win);
+		v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+			 "stream %d crop(%d,%d)/%dx%d\n", stream->id,
+			 dcrop->left, dcrop->top, dcrop->width, dcrop->height);
+	}
+
+	return 0;
+}
+
+static int rkisp1_querycap(struct file *file, void *priv,
+			   struct v4l2_capability *cap)
+{
+	struct rkisp1_stream *stream = video_drvdata(file);
+	struct device *dev = stream->ispdev->dev;
+
+	strlcpy(cap->driver, dev->driver->name, sizeof(cap->driver));
+	strlcpy(cap->card, dev->driver->name, sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "platform:%s", dev_name(dev));
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops rkisp1_v4l2_ioctl_ops = {
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_qbuf = vb2_ioctl_qbuf,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+	.vidioc_enum_input = rkisp1_enum_input,
+	.vidioc_try_fmt_vid_cap_mplane = rkisp1_try_fmt_vid_cap_mplane,
+	.vidioc_enum_fmt_vid_cap_mplane = rkisp1_enum_fmt_vid_cap_mplane,
+	.vidioc_s_fmt_vid_cap_mplane = rkisp1_s_fmt_vid_cap_mplane,
+	.vidioc_g_fmt_vid_cap_mplane = rkisp1_g_fmt_vid_cap_mplane,
+	.vidioc_s_selection = rkisp1_s_selection,
+	.vidioc_g_selection = rkisp1_g_selection,
+	.vidioc_querycap = rkisp1_querycap,
+};
+
+static void rkisp1_unregister_stream_vdev(struct rkisp1_stream *stream)
+{
+	media_entity_cleanup(&stream->vnode.vdev.entity);
+	video_unregister_device(&stream->vnode.vdev);
+}
+
+void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev)
+{
+	struct rkisp1_stream *mp_stream = &dev->stream[RKISP1_STREAM_MP];
+	struct rkisp1_stream *sp_stream = &dev->stream[RKISP1_STREAM_SP];
+
+	rkisp1_unregister_stream_vdev(mp_stream);
+	rkisp1_unregister_stream_vdev(sp_stream);
+}
+
+static int rkisp1_register_stream_vdev(struct rkisp1_stream *stream)
+{
+	struct rkisp1_device *dev = stream->ispdev;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	struct video_device *vdev = &stream->vnode.vdev;
+	struct rkisp1_vdev_node *node;
+	int ret;
+
+	strlcpy(vdev->name,
+		stream->id == RKISP1_STREAM_SP ? SP_VDEV_NAME : MP_VDEV_NAME,
+		sizeof(vdev->name));
+	node = vdev_to_node(vdev);
+	mutex_init(&node->vlock);
+
+	vdev->ioctl_ops = &rkisp1_v4l2_ioctl_ops;
+	vdev->release = video_device_release_empty;
+	vdev->fops = &rkisp1_fops;
+	vdev->minor = -1;
+	vdev->v4l2_dev = v4l2_dev;
+	vdev->lock = &node->vlock;
+	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+				V4L2_CAP_STREAMING;
+	video_set_drvdata(vdev, stream);
+	vdev->vfl_dir = VFL_DIR_RX;
+	node->pad.flags = MEDIA_PAD_FL_SINK;
+
+	rkisp_init_vb2_queue(&node->buf_queue, stream,
+			     V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+	vdev->queue = &node->buf_queue;
+
+	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev,
+			 "video_register_device failed with error %d\n", ret);
+		return ret;
+	}
+
+	vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
+	if (ret < 0)
+		goto unreg;
+
+	return 0;
+unreg:
+	video_unregister_device(vdev);
+	return ret;
+}
+
+int rkisp1_register_stream_vdevs(struct rkisp1_device *dev)
+{
+	struct rkisp1_stream *stream;
+	int i, j, ret;
+
+	for (i = 0; i < RKISP1_MAX_STREAM; i++) {
+		stream = &dev->stream[i];
+		stream->ispdev = dev;
+		ret = rkisp1_register_stream_vdev(stream);
+		if (ret < 0)
+			goto err;
+	}
+
+	return 0;
+err:
+	for (j = 0; j < i; j++) {
+		stream = &dev->stream[j];
+		rkisp1_unregister_stream_vdev(stream);
+	}
+
+	return ret;
+}
+
+/****************  Interrupter Handler ****************/
+
+void rkisp1_mi_isr(struct rkisp1_stream *stream)
+{
+	struct rkisp1_device *dev = stream->ispdev;
+	void __iomem *base = stream->ispdev->base_addr;
+	u32 val;
+
+	stream->ops->clr_frame_end_int(base);
+	if (stream->ops->is_frame_end_int_masked(base)) {
+		val = mi_get_masked_int_status(base);
+		v4l2_err(&dev->v4l2_dev, "icr err: 0x%x\n", val);
+	}
+
+	if (stream->stopping) {
+		/* Make sure stream is actually stopped, whose state
+		 * can be read from the shadow register, before wake_up()
+		 * thread which would immediately free all frame buffers.
+		 * stop_mi() takes effect at the next frame end
+		 * that sync the configurations to shadow regs.
+		 */
+		if (stream->ops->is_stream_stopped(dev->base_addr)) {
+			stream->stopping = false;
+			stream->state = RKISP1_STATE_READY;
+			wake_up(&stream->done);
+		} else {
+			stream->ops->stop_mi(stream);
+		}
+	} else {
+		mi_frame_end(stream);
+	}
+}
diff --git a/drivers/media/platform/rockchip/isp1/capture.h b/drivers/media/platform/rockchip/isp1/capture.h
new file mode 100644
index 000000000000..f0989103daa1
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/capture.h
@@ -0,0 +1,194 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_PATH_VIDEO_H
+#define _RKISP1_PATH_VIDEO_H
+
+#include "common.h"
+
+struct rkisp1_stream;
+
+/*
+ * @fourcc: pixel format
+ * @mbus_code: pixel format over bus
+ * @fmt_type: helper filed for pixel format
+ * @bpp: bits per pixel
+ * @bayer_pat: bayer patten type
+ * @cplanes: number of colour planes
+ * @mplanes: number of stored memory planes
+ * @uv_swap: if cb cr swaped, for yuv
+ * @write_format: defines how YCbCr self picture data is written to memory
+ * @input_format: defines sp input format
+ * @output_format: defines sp output format
+ */
+struct capture_fmt {
+	u32 fourcc;
+	u32 mbus_code;
+	u8 fmt_type;
+	u8 cplanes;
+	u8 mplanes;
+	u8 uv_swap;
+	u32 write_format;
+	u32 output_format;
+	u8 bpp[VIDEO_MAX_PLANES];
+};
+
+enum rkisp1_sp_inp {
+	RKISP1_SP_INP_ISP,
+	RKISP1_SP_INP_DMA_SP,
+	RKISP1_SP_INP_MAX
+};
+
+struct rkisp1_stream_sp {
+	int y_stride;
+	enum rkisp1_sp_inp input_sel;
+};
+
+struct rkisp1_stream_mp {
+	bool raw_enable;
+};
+
+/* Different config between selfpath and mainpath */
+struct stream_config {
+	const struct capture_fmt *fmts;
+	int fmt_size;
+	/* constrains */
+	const int max_rsz_width;
+	const int max_rsz_height;
+	const int min_rsz_width;
+	const int min_rsz_height;
+	/* registers */
+	struct {
+		u32 ctrl;
+		u32 ctrl_shd;
+		u32 scale_hy;
+		u32 scale_hcr;
+		u32 scale_hcb;
+		u32 scale_vy;
+		u32 scale_vc;
+		u32 scale_lut;
+		u32 scale_lut_addr;
+		u32 scale_hy_shd;
+		u32 scale_hcr_shd;
+		u32 scale_hcb_shd;
+		u32 scale_vy_shd;
+		u32 scale_vc_shd;
+		u32 phase_hy;
+		u32 phase_hc;
+		u32 phase_vy;
+		u32 phase_vc;
+		u32 phase_hy_shd;
+		u32 phase_hc_shd;
+		u32 phase_vy_shd;
+		u32 phase_vc_shd;
+	} rsz;
+	struct {
+		u32 ctrl;
+		u32 yuvmode_mask;
+		u32 rawmode_mask;
+		u32 h_offset;
+		u32 v_offset;
+		u32 h_size;
+		u32 v_size;
+	} dual_crop;
+	struct {
+		u32 y_size_init;
+		u32 cb_size_init;
+		u32 cr_size_init;
+		u32 y_base_ad_init;
+		u32 cb_base_ad_init;
+		u32 cr_base_ad_init;
+		u32 y_offs_cnt_init;
+		u32 cb_offs_cnt_init;
+		u32 cr_offs_cnt_init;
+	} mi;
+};
+
+/* Different reg ops between selfpath and mainpath */
+struct streams_ops {
+	int (*config_mi)(struct rkisp1_stream *stream);
+	void (*stop_mi)(struct rkisp1_stream *stream);
+	void (*enable_mi)(struct rkisp1_stream *stream);
+	void (*disable_mi)(struct rkisp1_stream *stream);
+	void (*set_data_path)(void __iomem *base);
+	void (*clr_frame_end_int)(void __iomem *base);
+	bool (*is_frame_end_int_masked)(void __iomem *base);
+	bool (*is_stream_stopped)(void __iomem *base);
+};
+
+/*
+ * struct rkisp1_stream - ISP capture video device
+ *
+ * @out_isp_fmt: output isp format
+ * @out_fmt: output buffer size
+ * @dcrop: coordinates of dual-crop
+ *
+ * @vbq_lock: lock to protect buf_queue
+ * @buf_queue: queued buffer list
+ * @dummy_buf: dummy space to store dropped data
+ *
+ * rkisp1 use shadowsock registers, so it need two buffer at a time
+ * @curr_buf: the buffer used for current frame
+ * @next_buf: the buffer used for next frame
+ */
+struct rkisp1_stream {
+	u32 id;
+	struct rkisp1_device *ispdev;
+	struct rkisp1_vdev_node vnode;
+	enum rkisp1_state state;
+	enum rkisp1_state saved_state;
+	struct capture_fmt out_isp_fmt;
+	struct v4l2_pix_format_mplane out_fmt;
+	struct v4l2_rect dcrop;
+	struct streams_ops *ops;
+	struct stream_config *config;
+	spinlock_t vbq_lock;
+	struct list_head buf_queue;
+	struct rkisp1_dummy_buffer dummy_buf;
+	struct rkisp1_buffer *curr_buf;
+	struct rkisp1_buffer *next_buf;
+	bool stopping;
+	wait_queue_head_t done;
+	union {
+		struct rkisp1_stream_sp sp;
+		struct rkisp1_stream_mp mp;
+	} u;
+};
+
+void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev);
+int rkisp1_register_stream_vdevs(struct rkisp1_device *dev);
+void rkisp1_mi_isr(struct rkisp1_stream *stream);
+void rkisp1_stream_init(struct rkisp1_device *dev, u32 id);
+
+#endif /* _RKISP1_PATH_VIDEO_H */
diff --git a/drivers/media/platform/rockchip/isp1/common.h b/drivers/media/platform/rockchip/isp1/common.h
new file mode 100644
index 000000000000..1adfb9039b60
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/common.h
@@ -0,0 +1,137 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_COMMON_H
+#define _RKISP1_COMMON_H
+
+#include <linux/mutex.h>
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf2-v4l2.h>
+
+#define RKISP1_DEFAULT_WIDTH		800
+#define RKISP1_DEFAULT_HEIGHT		600
+
+#define RKISP1_MAX_STREAM		2
+#define RKISP1_STREAM_SP		0
+#define RKISP1_STREAM_MP		1
+
+#define RKISP1_PLANE_Y			0
+#define RKISP1_PLANE_CB			1
+#define RKISP1_PLANE_CR			2
+
+enum rkisp1_sd_type {
+	RKISP1_SD_SENSOR,
+	RKISP1_SD_PHY_CSI,
+	RKISP1_SD_VCM,
+	RKISP1_SD_FLASH,
+	RKISP1_SD_MAX,
+};
+
+/* One structure per video node */
+struct rkisp1_vdev_node {
+	struct vb2_queue buf_queue;
+	/* vfd lock */
+	struct mutex vlock;
+	struct video_device vdev;
+	struct media_pad pad;
+};
+
+enum rkisp1_fmt_pix_type {
+	FMT_YUV,
+	FMT_RGB,
+	FMT_BAYER,
+	FMT_JPEG,
+	FMT_MAX
+};
+
+enum rkisp1_fmt_raw_pat_type {
+	RAW_RGGB = 0,
+	RAW_GRBG,
+	RAW_GBRG,
+	RAW_BGGR,
+};
+
+enum rkisp1_state {
+	/* path not yet opened: */
+	RKISP1_STATE_DISABLED,
+	/* path opened and configured, ready for streaming: */
+	RKISP1_STATE_READY,
+	/* path is streaming: */
+	RKISP1_STATE_STREAMING
+};
+
+struct rkisp1_buffer {
+	struct vb2_v4l2_buffer vb;
+	struct list_head queue;
+	union {
+		u32 buff_addr[VIDEO_MAX_PLANES];
+		void *vaddr[VIDEO_MAX_PLANES];
+	};
+};
+
+struct rkisp1_dummy_buffer {
+	void *vaddr;
+	dma_addr_t dma_addr;
+	u32 size;
+};
+
+extern int rkisp1_debug;
+
+static inline
+struct rkisp1_vdev_node *vdev_to_node(struct video_device *vdev)
+{
+	return container_of(vdev, struct rkisp1_vdev_node, vdev);
+}
+
+static inline struct rkisp1_vdev_node *queue_to_node(struct vb2_queue *q)
+{
+	return container_of(q, struct rkisp1_vdev_node, buf_queue);
+}
+
+static inline struct rkisp1_buffer *to_rkisp1_buffer(struct vb2_v4l2_buffer *vb)
+{
+	return container_of(vb, struct rkisp1_buffer, vb);
+}
+
+static inline struct vb2_queue *to_vb2_queue(struct file *file)
+{
+	struct rkisp1_vdev_node *vnode = video_drvdata(file);
+
+	return &vnode->buf_queue;
+}
+
+#endif /* _RKISP1_COMMON_H */
diff --git a/drivers/media/platform/rockchip/isp1/dev.c b/drivers/media/platform/rockchip/isp1/dev.c
new file mode 100644
index 000000000000..025aa3a019a8
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/dev.c
@@ -0,0 +1,655 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
+#include "common.h"
+#include "regs.h"
+
+struct isp_match_data {
+	const char * const *clks;
+	int size;
+};
+
+int rkisp1_debug;
+module_param_named(debug, rkisp1_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/***************************** pipeline operations*******************************/
+
+static int __isp_pipeline_prepare(struct rkisp1_pipeline *p,
+				  struct media_entity *me)
+{
+	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
+	struct v4l2_subdev *sd;
+	int i;
+
+	p->num_subdevs = 0;
+	memset(p->subdevs, 0, sizeof(p->subdevs));
+
+	while (1) {
+		struct media_pad *pad = NULL;
+
+		/* Find remote source pad */
+		for (i = 0; i < me->num_pads; i++) {
+			struct media_pad *spad = &me->pads[i];
+
+			if (!(spad->flags & MEDIA_PAD_FL_SINK))
+				continue;
+			pad = media_entity_remote_pad(spad);
+			if (pad)
+				break;
+		}
+
+		if (!pad)
+			break;
+
+		sd = media_entity_to_v4l2_subdev(pad->entity);
+		if (sd != &dev->isp_sdev.sd)
+			p->subdevs[p->num_subdevs++] = sd;
+
+		me = &sd->entity;
+		if (me->num_pads == 1)
+			break;
+	}
+	return 0;
+}
+
+static int __subdev_set_power(struct v4l2_subdev *sd, int on)
+{
+	int ret;
+
+	if (!sd)
+		return -ENXIO;
+
+	ret = v4l2_subdev_call(sd, core, s_power, on);
+
+	return ret != -ENOIOCTLCMD ? ret : 0;
+}
+
+static int __isp_pipeline_s_power(struct rkisp1_pipeline *p, bool on)
+{
+	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
+	int i, ret;
+
+	if (on) {
+		__subdev_set_power(&dev->isp_sdev.sd, true);
+
+		for (i = p->num_subdevs - 1; i >= 0; --i) {
+			ret = __subdev_set_power(p->subdevs[i], true);
+			if (ret < 0 && ret != -ENXIO)
+				goto err_power_off;
+		}
+	} else {
+		for (i = 0; i < p->num_subdevs; ++i)
+			__subdev_set_power(p->subdevs[i], false);
+
+		__subdev_set_power(&dev->isp_sdev.sd, false);
+	}
+
+	return 0;
+
+err_power_off:
+	for (++i; i < p->num_subdevs; ++i)
+		__subdev_set_power(p->subdevs[i], false);
+	__subdev_set_power(&dev->isp_sdev.sd, true);
+	return ret;
+}
+
+static int rkisp1_pipeline_open(struct rkisp1_pipeline *p,
+				struct media_entity *me,
+				bool prepare)
+{
+	int ret;
+
+	if (WARN_ON(!p || !me))
+		return -EINVAL;
+	if (atomic_inc_return(&p->power_cnt) > 1)
+		return 0;
+
+	/* go through media graphic and get subdevs */
+	if (prepare)
+		__isp_pipeline_prepare(p, me);
+
+	if (!p->num_subdevs)
+		return -EINVAL;
+
+	ret = __isp_pipeline_s_power(p, 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int rkisp1_pipeline_close(struct rkisp1_pipeline *p)
+{
+	int ret;
+
+	if (atomic_dec_return(&p->power_cnt) > 0)
+		return 0;
+	ret = __isp_pipeline_s_power(p, 0);
+
+	return ret == -ENXIO ? 0 : ret;
+}
+
+/*
+ * stream-on order: isp_subdev, mipi dphy, sensor
+ * stream-off order: mipi dphy, sensor, isp_subdev
+ */
+static int rkisp1_pipeline_set_stream(struct rkisp1_pipeline *p, bool on)
+{
+	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
+	int i, ret;
+
+	if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
+	    (!on && atomic_dec_return(&p->stream_cnt) > 0))
+		return 0;
+
+	if (on)
+		v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, true);
+
+	/* phy -> sensor */
+	for (i = 0; i < p->num_subdevs; ++i) {
+		ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
+		if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+			goto err_stream_off;
+	}
+
+	if (!on)
+		v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
+
+	return 0;
+
+err_stream_off:
+	for (--i; i >= 0; --i)
+		v4l2_subdev_call(p->subdevs[i], video, s_stream, false);
+	v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
+	return ret;
+}
+
+/***************************** media controller *******************************/
+/* See http://opensource.rock-chips.com/wiki_Rockchip-isp1 for Topology */
+
+static int rkisp1_create_links(struct rkisp1_device *dev)
+{
+	struct media_entity *source, *sink;
+	unsigned int flags, s, pad;
+	int ret;
+
+	/* sensor links(or mipi-phy) */
+	for (s = 0; s < dev->num_sensors; ++s) {
+		struct rkisp1_sensor_info *sensor = &dev->sensors[s];
+
+		for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
+			if (sensor->sd->entity.pads[pad].flags &
+				MEDIA_PAD_FL_SOURCE)
+				break;
+
+		if (pad == sensor->sd->entity.num_pads) {
+			dev_err(dev->dev,
+				"failed to find src pad for %s\n",
+				sensor->sd->name);
+
+			return -ENXIO;
+		}
+
+		ret = media_create_pad_link(
+				&sensor->sd->entity, pad,
+				&dev->isp_sdev.sd.entity,
+				RKISP1_ISP_PAD_SINK + s,
+				s ? 0 : MEDIA_LNK_FL_ENABLED);
+		if (ret) {
+			dev_err(dev->dev,
+				"failed to create link for %s\n",
+				sensor->sd->name);
+			return ret;
+		}
+	}
+
+	/* params links */
+	source = &dev->params_vdev.vnode.vdev.entity;
+	sink = &dev->isp_sdev.sd.entity;
+	flags = MEDIA_LNK_FL_ENABLED;
+	ret = media_create_pad_link(source, 0, sink,
+				       RKISP1_ISP_PAD_SINK_PARAMS, flags);
+	if (ret < 0)
+		return ret;
+
+	/* create isp internal links */
+	/* SP links */
+	source = &dev->isp_sdev.sd.entity;
+	sink = &dev->stream[RKISP1_STREAM_SP].vnode.vdev.entity;
+	ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
+				       sink, 0, flags);
+	if (ret < 0)
+		return ret;
+
+	/* MP links */
+	source = &dev->isp_sdev.sd.entity;
+	sink = &dev->stream[RKISP1_STREAM_MP].vnode.vdev.entity;
+	ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
+				       sink, 0, flags);
+	if (ret < 0)
+		return ret;
+
+	/* 3A stats links */
+	source = &dev->isp_sdev.sd.entity;
+	sink = &dev->stats_vdev.vnode.vdev.entity;
+	return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS,
+					sink, 0, flags);
+}
+
+static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+	struct rkisp1_device *dev;
+	int ret;
+
+	dev = container_of(notifier, struct rkisp1_device, notifier);
+
+	mutex_lock(&dev->media_dev.graph_mutex);
+	ret = rkisp1_create_links(dev);
+	if (ret < 0)
+		goto unlock;
+	ret = v4l2_device_register_subdev_nodes(&dev->v4l2_dev);
+	if (ret < 0)
+		goto unlock;
+
+	v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n");
+
+unlock:
+	mutex_unlock(&dev->media_dev.graph_mutex);
+	return ret;
+}
+
+struct rkisp1_async_subdev {
+	struct v4l2_async_subdev asd;
+	struct v4l2_mbus_config mbus;
+};
+
+static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
+				 struct v4l2_subdev *subdev,
+				 struct v4l2_async_subdev *asd)
+{
+	struct rkisp1_device *isp_dev = container_of(notifier,
+					struct rkisp1_device, notifier);
+	struct rkisp1_async_subdev *s_asd = container_of(asd,
+					struct rkisp1_async_subdev, asd);
+
+	if (isp_dev->num_sensors == ARRAY_SIZE(isp_dev->sensors))
+		return -EBUSY;
+
+	isp_dev->sensors[isp_dev->num_sensors].mbus = s_asd->mbus;
+	isp_dev->sensors[isp_dev->num_sensors].sd = subdev;
+	++isp_dev->num_sensors;
+
+	v4l2_dbg(1, rkisp1_debug, subdev, "Async registered subdev\n");
+
+	return 0;
+}
+
+static int rkisp1_fwnode_parse(struct device *dev,
+			       struct v4l2_fwnode_endpoint *vep,
+			       struct v4l2_async_subdev *asd)
+{
+	struct rkisp1_async_subdev *rk_asd =
+			container_of(asd, struct rkisp1_async_subdev, asd);
+	struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel;
+
+	/*
+	 * MIPI sensor is linked with a mipi dphy and its media bus config can
+	 * not be get in here
+	 */
+	if (vep->bus_type != V4L2_MBUS_BT656 &&
+		vep->bus_type != V4L2_MBUS_PARALLEL)
+		return 0;
+
+	rk_asd->mbus.flags = bus->flags;
+	rk_asd->mbus.type = vep->bus_type;
+
+	return 0;
+}
+
+static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
+	.bound = subdev_notifier_bound,
+	.complete = subdev_notifier_complete,
+};
+
+static int isp_subdev_notifier(struct rkisp1_device *isp_dev)
+{
+	struct v4l2_async_notifier *ntf = &isp_dev->notifier;
+	struct device *dev = isp_dev->dev;
+	int ret;
+
+	ret = v4l2_async_notifier_parse_fwnode_endpoints(
+		dev, ntf, sizeof(struct rkisp1_async_subdev),
+		rkisp1_fwnode_parse);
+	if (ret < 0)
+		return ret;
+
+	if (!ntf->num_subdevs)
+		return -ENODEV;	/* no endpoint */
+
+	ntf->ops = &subdev_notifier_ops;
+
+	return v4l2_async_notifier_register(&isp_dev->v4l2_dev, ntf);
+}
+
+/***************************** platform deive *******************************/
+
+static int rkisp1_register_platform_subdevs(struct rkisp1_device *dev)
+{
+	int ret;
+
+	ret = rkisp1_register_isp_subdev(dev, &dev->v4l2_dev);
+	if (ret < 0)
+		return ret;
+
+	ret = rkisp1_register_stream_vdevs(dev);
+	if (ret < 0)
+		goto err_unreg_isp_subdev;
+
+	ret = rkisp1_register_stats_vdev(&dev->stats_vdev, &dev->v4l2_dev, dev);
+	if (ret < 0)
+		goto err_unreg_stream_vdev;
+
+	ret = rkisp1_register_params_vdev(&dev->params_vdev, &dev->v4l2_dev,
+					  dev);
+	if (ret < 0)
+		goto err_unreg_stats_vdev;
+
+	ret = isp_subdev_notifier(dev);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev,
+			 "Failed to register subdev notifier(%d)\n", ret);
+		goto err_unreg_params_vdev;
+	}
+
+	return 0;
+err_unreg_params_vdev:
+	rkisp1_unregister_params_vdev(&dev->params_vdev);
+err_unreg_stats_vdev:
+	rkisp1_unregister_stats_vdev(&dev->stats_vdev);
+err_unreg_stream_vdev:
+	rkisp1_unregister_stream_vdevs(dev);
+err_unreg_isp_subdev:
+	rkisp1_unregister_isp_subdev(dev);
+	return ret;
+}
+
+static const char * const rk3399_isp_clks[] = {
+	"clk_isp",
+	"aclk_isp",
+	"hclk_isp",
+	"aclk_isp_wrap",
+	"hclk_isp_wrap",
+};
+
+static const char * const rk3288_isp_clks[] = {
+	"clk_isp",
+	"aclk_isp",
+	"hclk_isp",
+	"pclk_isp_in",
+	"sclk_isp_jpe",
+};
+
+static const struct isp_match_data rk3288_isp_clk_data = {
+	.clks = rk3288_isp_clks,
+	.size = ARRAY_SIZE(rk3288_isp_clks),
+};
+
+static const struct isp_match_data rk3399_isp_clk_data = {
+	.clks = rk3399_isp_clks,
+	.size = ARRAY_SIZE(rk3399_isp_clks),
+};
+
+static const struct of_device_id rkisp1_plat_of_match[] = {
+	{
+		.compatible = "rockchip,rk3288-cif-isp",
+		.data = &rk3288_isp_clk_data,
+	}, {
+		.compatible = "rockchip,rk3399-cif-isp",
+		.data = &rk3399_isp_clk_data,
+	},
+	{},
+};
+
+static irqreturn_t rkisp1_irq_handler(int irq, void *cntxt)
+{
+	struct device *dev = cntxt;
+	struct rkisp1_device *rkisp1_dev = dev_get_drvdata(dev);
+	void __iomem *base = rkisp1_dev->base_addr;
+	unsigned int mis_val, i;
+
+	mis_val = readl(rkisp1_dev->base_addr + CIF_ISP_MIS);
+	if (mis_val)
+		rkisp1_isp_isr(mis_val, rkisp1_dev);
+
+	mis_val = readl(rkisp1_dev->base_addr + CIF_MIPI_MIS);
+	if (mis_val)
+		rkisp1_mipi_isr(mis_val, rkisp1_dev);
+
+	for (i = 0; i < RKISP1_MAX_STREAM; ++i) {
+		struct rkisp1_stream *stream = &rkisp1_dev->stream[i];
+
+		if (stream->ops->is_frame_end_int_masked(base))
+			rkisp1_mi_isr(stream);
+	}
+
+	clr_all_int(base);
+
+	return IRQ_HANDLED;
+}
+
+static void rkisp1_disable_sys_clk(struct rkisp1_device *rkisp1_dev)
+{
+	int i;
+
+	for (i = rkisp1_dev->clk_size - 1; i >= 0; i--)
+		clk_disable_unprepare(rkisp1_dev->clks[i]);
+}
+
+static int rkisp1_enable_sys_clk(struct rkisp1_device *rkisp1_dev)
+{
+	int i, ret = -EINVAL;
+
+	for (i = 0; i < rkisp1_dev->clk_size; i++) {
+		ret = clk_prepare_enable(rkisp1_dev->clks[i]);
+		if (ret < 0)
+			goto err;
+	}
+	return 0;
+err:
+	for (--i; i >= 0; --i)
+		clk_disable_unprepare(rkisp1_dev->clks[i]);
+	return ret;
+}
+
+static int rkisp1_plat_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct device_node *node = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	struct v4l2_device *v4l2_dev;
+	struct rkisp1_device *isp_dev;
+	const struct isp_match_data *clk_data;
+
+	struct resource *res;
+	int i, ret, irq;
+
+	match = of_match_node(rkisp1_plat_of_match, node);
+	isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
+	if (!isp_dev)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, isp_dev);
+	isp_dev->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	isp_dev->base_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(isp_dev->base_addr))
+		return PTR_ERR(isp_dev->base_addr);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_irq(dev, irq, rkisp1_irq_handler, IRQF_SHARED,
+			       dev_driver_string(dev), dev);
+	if (ret < 0) {
+		dev_err(dev, "request irq failed: %d\n", ret);
+		return ret;
+	}
+
+	isp_dev->irq = irq;
+	clk_data = match->data;
+	for (i = 0; i < clk_data->size; i++) {
+		struct clk *clk = devm_clk_get(dev, clk_data->clks[i]);
+
+		if (IS_ERR(clk)) {
+			dev_err(dev, "failed to get %s\n", clk_data->clks[i]);
+			return PTR_ERR(clk);
+		}
+		isp_dev->clks[i] = clk;
+	}
+	isp_dev->clk_size = clk_data->size;
+
+	atomic_set(&isp_dev->pipe.power_cnt, 0);
+	atomic_set(&isp_dev->pipe.stream_cnt, 0);
+	isp_dev->pipe.open = rkisp1_pipeline_open;
+	isp_dev->pipe.close = rkisp1_pipeline_close;
+	isp_dev->pipe.set_stream = rkisp1_pipeline_set_stream;
+
+	rkisp1_stream_init(isp_dev, RKISP1_STREAM_SP);
+	rkisp1_stream_init(isp_dev, RKISP1_STREAM_MP);
+
+	strlcpy(isp_dev->media_dev.model, "rkisp1",
+		sizeof(isp_dev->media_dev.model));
+	isp_dev->media_dev.dev = &pdev->dev;
+	media_device_init(&isp_dev->media_dev);
+
+	v4l2_dev = &isp_dev->v4l2_dev;
+	v4l2_dev->mdev = &isp_dev->media_dev;
+	strlcpy(v4l2_dev->name, "rkisp1", sizeof(v4l2_dev->name));
+	v4l2_ctrl_handler_init(&isp_dev->ctrl_handler, 5);
+	v4l2_dev->ctrl_handler = &isp_dev->ctrl_handler;
+
+	ret = v4l2_device_register(isp_dev->dev, &isp_dev->v4l2_dev);
+	if (ret < 0)
+		return ret;
+
+	ret = media_device_register(&isp_dev->media_dev);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "Failed to register media device: %d\n",
+			 ret);
+		goto err_unreg_v4l2_dev;
+	}
+
+	/* create & register platefom subdev (from of_node) */
+	ret = rkisp1_register_platform_subdevs(isp_dev);
+	if (ret < 0)
+		goto err_unreg_media_dev;
+
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+
+err_unreg_media_dev:
+	media_device_unregister(&isp_dev->media_dev);
+err_unreg_v4l2_dev:
+	v4l2_device_unregister(&isp_dev->v4l2_dev);
+	return ret;
+}
+
+static int rkisp1_plat_remove(struct platform_device *pdev)
+{
+	struct rkisp1_device *isp_dev = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+	media_device_unregister(&isp_dev->media_dev);
+	v4l2_device_unregister(&isp_dev->v4l2_dev);
+	rkisp1_unregister_params_vdev(&isp_dev->params_vdev);
+	rkisp1_unregister_stats_vdev(&isp_dev->stats_vdev);
+	rkisp1_unregister_stream_vdevs(isp_dev);
+	rkisp1_unregister_isp_subdev(isp_dev);
+
+	return 0;
+}
+
+static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
+{
+	struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
+
+	rkisp1_disable_sys_clk(isp_dev);
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
+{
+	struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pinctrl_pm_select_default_state(dev);
+	if (ret < 0)
+		return ret;
+	rkisp1_enable_sys_clk(isp_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops rkisp1_plat_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL)
+};
+
+static struct platform_driver rkisp1_plat_drv = {
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .of_match_table = of_match_ptr(rkisp1_plat_of_match),
+		   .pm = &rkisp1_plat_pm_ops,
+	},
+	.probe = rkisp1_plat_probe,
+	.remove = rkisp1_plat_remove,
+};
+
+module_platform_driver(rkisp1_plat_drv);
+MODULE_AUTHOR("Rockchip Camera/ISP team");
+MODULE_DESCRIPTION("Rockchip ISP1 platform driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/media/platform/rockchip/isp1/dev.h b/drivers/media/platform/rockchip/isp1/dev.h
new file mode 100644
index 000000000000..f28cde364b8d
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/dev.h
@@ -0,0 +1,120 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_DEV_H
+#define _RKISP1_DEV_H
+
+#include "capture.h"
+#include "rkisp1.h"
+#include "isp_params.h"
+#include "isp_stats.h"
+
+#define DRIVER_NAME "rkisp1"
+#define ISP_VDEV_NAME DRIVER_NAME  "_ispdev"
+#define SP_VDEV_NAME DRIVER_NAME   "_selfpath"
+#define MP_VDEV_NAME DRIVER_NAME   "_mainpath"
+#define DMA_VDEV_NAME DRIVER_NAME  "_dmapath"
+
+#define GRP_ID_SENSOR			BIT(0)
+#define GRP_ID_MIPIPHY			BIT(1)
+#define GRP_ID_ISP			BIT(2)
+#define GRP_ID_ISP_MP			BIT(3)
+#define GRP_ID_ISP_SP			BIT(4)
+
+#define RKISP1_MAX_BUS_CLK	8
+#define RKISP1_MAX_SENSOR	2
+#define RKISP1_MAX_PIPELINE	4
+
+/*
+ * struct rkisp1_pipeline - An ISP hardware pipeline
+ *
+ * Capture device call other devices via pipeline
+ *
+ * @num_subdevs: number of linked subdevs
+ * @power_cnt: pipeline power count
+ * @stream_cnt: stream power count
+ */
+struct rkisp1_pipeline {
+	struct media_pipeline pipe;
+	int num_subdevs;
+	atomic_t power_cnt;
+	atomic_t stream_cnt;
+	struct v4l2_subdev *subdevs[RKISP1_MAX_PIPELINE];
+	int (*open)(struct rkisp1_pipeline *p,
+		    struct media_entity *me, bool prepare);
+	int (*close)(struct rkisp1_pipeline *p);
+	int (*set_stream)(struct rkisp1_pipeline *p, bool on);
+};
+
+/*
+ * struct rkisp1_sensor_info - Sensor infomations
+ * @mbus: media bus configuration
+ */
+struct rkisp1_sensor_info {
+	struct v4l2_subdev *sd;
+	struct v4l2_mbus_config mbus;
+};
+
+/*
+ * struct rkisp1_device - ISP platform device
+ * @base_addr: base register address
+ * @active_sensor: sensor in-use, set when streaming on
+ * @isp_sdev: ISP sub-device
+ * @rkisp1_stream: capture video device
+ * @stats_vdev: ISP statistics output device
+ * @params_vdev: ISP input parameters device
+ */
+struct rkisp1_device {
+	void __iomem *base_addr;
+	int irq;
+	struct device *dev;
+	struct clk *clks[RKISP1_MAX_BUS_CLK];
+	int clk_size;
+	struct v4l2_device v4l2_dev;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct media_device media_dev;
+	struct v4l2_async_notifier notifier;
+	struct v4l2_subdev *subdevs[RKISP1_SD_MAX];
+	struct rkisp1_sensor_info *active_sensor;
+	struct rkisp1_sensor_info sensors[RKISP1_MAX_SENSOR];
+	int num_sensors;
+	struct rkisp1_isp_subdev isp_sdev;
+	struct rkisp1_stream stream[RKISP1_MAX_STREAM];
+	struct rkisp1_isp_stats_vdev stats_vdev;
+	struct rkisp1_isp_params_vdev params_vdev;
+	struct rkisp1_pipeline pipe;
+	struct vb2_alloc_ctx *alloc_ctx;
+};
+
+#endif
diff --git a/drivers/media/platform/rockchip/isp1/isp_params.c b/drivers/media/platform/rockchip/isp1/isp_params.c
new file mode 100644
index 000000000000..5a145b0a704e
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/isp_params.c
@@ -0,0 +1,1543 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-vmalloc.h>	/* for ISP params */
+#include "dev.h"
+#include "regs.h"
+
+#define RKISP1_ISP_PARAMS_REQ_BUFS_MIN	2
+#define RKISP1_ISP_PARAMS_REQ_BUFS_MAX	8
+
+#define BLS_START_H_MAX_IS_VALID(val)	((val) < CIFISP_BLS_START_H_MAX)
+#define BLS_STOP_H_MAX_IS_VALID(val)	((val) < CIFISP_BLS_STOP_H_MAX)
+
+#define BLS_START_V_MAX_IS_VALID(val)	((val) < CIFISP_BLS_START_V_MAX)
+#define BLS_STOP_V_MAX_IS_VALID(val)	((val) < CIFISP_BLS_STOP_V_MAX)
+
+#define BLS_SAMPLE_MAX_IS_VALID(val)	((val) < CIFISP_BLS_SAMPLES_MAX)
+
+#define BLS_FIX_SUB_IS_VALID(val)	\
+	((val) > (s16) CIFISP_BLS_FIX_SUB_MIN && (val) < CIFISP_BLS_FIX_SUB_MAX)
+
+#define RKISP1_ISP_DPCC_LINE_THRESH(n)	(CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * (n))
+#define RKISP1_ISP_DPCC_LINE_MAD_FAC(n) (CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * (n))
+#define RKISP1_ISP_DPCC_PG_FAC(n)	(CIF_ISP_DPCC_PG_FAC_1 + 0x14 * (n))
+#define RKISP1_ISP_DPCC_RND_THRESH(n)	(CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * (n))
+#define RKISP1_ISP_DPCC_RG_FAC(n)	(CIF_ISP_DPCC_RG_FAC_1 + 0x14 * (n))
+#define RKISP1_ISP_CC_COEFF(n)		(CIF_ISP_CC_COEFF_0 + (n) * 4)
+
+static inline void rkisp1_iowrite32(struct rkisp1_isp_params_vdev *params_vdev,
+				    u32 value, u32 addr)
+{
+	iowrite32(value, params_vdev->dev->base_addr + addr);
+}
+
+static inline u32 rkisp1_ioread32(struct rkisp1_isp_params_vdev *params_vdev,
+				  u32 addr)
+{
+	return ioread32(params_vdev->dev->base_addr + addr);
+}
+
+static inline void isp_param_set_bits(struct rkisp1_isp_params_vdev
+					     *params_vdev,
+				      u32 reg, u32 bit_mask)
+{
+	u32 val;
+
+	val = rkisp1_ioread32(params_vdev, reg);
+	rkisp1_iowrite32(params_vdev, val | bit_mask, reg);
+}
+
+static inline void isp_param_clear_bits(struct rkisp1_isp_params_vdev
+					       *params_vdev,
+					u32 reg, u32 bit_mask)
+{
+	u32 val;
+
+	val = rkisp1_ioread32(params_vdev, reg);
+	rkisp1_iowrite32(params_vdev, val & ~bit_mask, reg);
+}
+
+/* ISP BP interface function */
+static void dpcc_config(struct rkisp1_isp_params_vdev *params_vdev,
+			const struct cifisp_dpcc_config *arg)
+{
+	unsigned int i;
+
+	rkisp1_iowrite32(params_vdev, arg->mode, CIF_ISP_DPCC_MODE);
+	rkisp1_iowrite32(params_vdev, arg->output_mode,
+			 CIF_ISP_DPCC_OUTPUT_MODE);
+	rkisp1_iowrite32(params_vdev, arg->set_use, CIF_ISP_DPCC_SET_USE);
+
+	rkisp1_iowrite32(params_vdev, arg->methods[0].method,
+			 CIF_ISP_DPCC_METHODS_SET_1);
+	rkisp1_iowrite32(params_vdev, arg->methods[1].method,
+			 CIF_ISP_DPCC_METHODS_SET_2);
+	rkisp1_iowrite32(params_vdev, arg->methods[2].method,
+			 CIF_ISP_DPCC_METHODS_SET_3);
+	for (i = 0; i < CIFISP_DPCC_METHODS_MAX; i++) {
+		rkisp1_iowrite32(params_vdev, arg->methods[i].line_thresh,
+				 RKISP1_ISP_DPCC_LINE_THRESH(i));
+		rkisp1_iowrite32(params_vdev, arg->methods[i].line_mad_fac,
+				 RKISP1_ISP_DPCC_LINE_MAD_FAC(i));
+		rkisp1_iowrite32(params_vdev, arg->methods[i].pg_fac,
+				 RKISP1_ISP_DPCC_PG_FAC(i));
+		rkisp1_iowrite32(params_vdev, arg->methods[i].rnd_thresh,
+				 RKISP1_ISP_DPCC_RND_THRESH(i));
+		rkisp1_iowrite32(params_vdev, arg->methods[i].rg_fac,
+				 RKISP1_ISP_DPCC_RG_FAC(i));
+	}
+
+	rkisp1_iowrite32(params_vdev, arg->rnd_offs, CIF_ISP_DPCC_RND_OFFS);
+	rkisp1_iowrite32(params_vdev, arg->ro_limits, CIF_ISP_DPCC_RO_LIMITS);
+}
+
+/* ISP black level subtraction interface function */
+static void bls_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_bls_config *arg)
+{
+	u32 new_control = 0;
+
+	/* fixed subtraction values */
+	if (!arg->enable_auto) {
+		const struct cifisp_bls_fixed_val *pval = &arg->fixed_val;
+
+		switch (params_vdev->raw_type) {
+		case RAW_BGGR:
+			rkisp1_iowrite32(params_vdev,
+					 pval->r, CIF_ISP_BLS_D_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->gr, CIF_ISP_BLS_C_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->gb, CIF_ISP_BLS_B_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->b, CIF_ISP_BLS_A_FIXED);
+			break;
+		case RAW_GBRG:
+			rkisp1_iowrite32(params_vdev,
+					 pval->r, CIF_ISP_BLS_C_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->gr, CIF_ISP_BLS_D_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->gb, CIF_ISP_BLS_A_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->b, CIF_ISP_BLS_B_FIXED);
+			break;
+		case RAW_GRBG:
+			rkisp1_iowrite32(params_vdev,
+					 pval->r, CIF_ISP_BLS_B_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->gr, CIF_ISP_BLS_A_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->gb, CIF_ISP_BLS_D_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->b, CIF_ISP_BLS_C_FIXED);
+			break;
+		case RAW_RGGB:
+			rkisp1_iowrite32(params_vdev,
+					 pval->r, CIF_ISP_BLS_A_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->gr, CIF_ISP_BLS_B_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->gb, CIF_ISP_BLS_C_FIXED);
+			rkisp1_iowrite32(params_vdev,
+					 pval->b, CIF_ISP_BLS_D_FIXED);
+			break;
+		default:
+			break;
+		}
+
+		new_control = CIF_ISP_BLS_MODE_FIXED;
+	} else {
+		if (arg->en_windows & BIT(1)) {
+			rkisp1_iowrite32(params_vdev, arg->bls_window2.h_offs,
+					 CIF_ISP_BLS_H2_START);
+			rkisp1_iowrite32(params_vdev, arg->bls_window2.h_size,
+					 CIF_ISP_BLS_H2_STOP);
+			rkisp1_iowrite32(params_vdev, arg->bls_window2.v_offs,
+					 CIF_ISP_BLS_V2_START);
+			rkisp1_iowrite32(params_vdev, arg->bls_window2.v_size,
+					 CIF_ISP_BLS_V2_STOP);
+			new_control |= CIF_ISP_BLS_WINDOW_2;
+		}
+
+		if (arg->en_windows & BIT(0)) {
+			rkisp1_iowrite32(params_vdev, arg->bls_window1.h_offs,
+					 CIF_ISP_BLS_H1_START);
+			rkisp1_iowrite32(params_vdev, arg->bls_window1.h_size,
+					 CIF_ISP_BLS_H1_STOP);
+			rkisp1_iowrite32(params_vdev, arg->bls_window1.v_offs,
+					 CIF_ISP_BLS_V1_START);
+			rkisp1_iowrite32(params_vdev, arg->bls_window1.v_size,
+					 CIF_ISP_BLS_V1_STOP);
+			new_control |= CIF_ISP_BLS_WINDOW_1;
+		}
+
+		rkisp1_iowrite32(params_vdev, arg->bls_samples,
+				 CIF_ISP_BLS_SAMPLES);
+
+		new_control |= CIF_ISP_BLS_MODE_MEASURED;
+	}
+	rkisp1_iowrite32(params_vdev, new_control, CIF_ISP_BLS_CTRL);
+}
+
+/* ISP LS correction interface function */
+static void
+__lsc_correct_matrix_config(struct rkisp1_isp_params_vdev *params_vdev,
+			    const struct cifisp_lsc_config *pconfig)
+{
+	int i, j;
+	unsigned int isp_lsc_status, sram_addr, isp_lsc_table_sel;
+	unsigned int data;
+
+	isp_lsc_status = rkisp1_ioread32(params_vdev, CIF_ISP_LSC_STATUS);
+
+	/* CIF_ISP_LSC_TABLE_ADDRESS_153 = ( 17 * 18 ) >> 1 */
+	sram_addr = (isp_lsc_status & CIF_ISP_LSC_ACTIVE_TABLE) ?
+		     CIF_ISP_LSC_TABLE_ADDRESS_0 :
+		     CIF_ISP_LSC_TABLE_ADDRESS_153;
+	rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_R_TABLE_ADDR);
+	rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_GR_TABLE_ADDR);
+	rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_GB_TABLE_ADDR);
+	rkisp1_iowrite32(params_vdev, sram_addr, CIF_ISP_LSC_B_TABLE_ADDR);
+
+	/* program data tables (table size is 9 * 17 = 153) */
+	for (i = 0; i < ((CIF_ISP_LSC_SECTORS_MAX + 1) *
+	     (CIF_ISP_LSC_SECTORS_MAX + 1));
+	     i += CIF_ISP_LSC_SECTORS_MAX + 1) {
+		/*
+		 * 17 sectors with 2 values in one DWORD = 9
+		 * DWORDs (2nd value of last DWORD unused)
+		 */
+		for (j = 0; j < (CIF_ISP_LSC_SECTORS_MAX + 1); j += 2) {
+			data = CIF_ISP_LSC_TABLE_DATA(
+					pconfig->r_data_tbl[i + j],
+					pconfig->r_data_tbl[i + j + 1]);
+			rkisp1_iowrite32(params_vdev, data,
+					 CIF_ISP_LSC_R_TABLE_DATA);
+
+			data = CIF_ISP_LSC_TABLE_DATA(
+					pconfig->gr_data_tbl[i + j],
+					pconfig->gr_data_tbl[i + j + 1]);
+			rkisp1_iowrite32(params_vdev, data,
+					 CIF_ISP_LSC_GR_TABLE_DATA);
+
+			data = CIF_ISP_LSC_TABLE_DATA(
+					pconfig->gb_data_tbl[i + j],
+					pconfig->gb_data_tbl[i + j + 1]);
+			rkisp1_iowrite32(params_vdev, data,
+					 CIF_ISP_LSC_GB_TABLE_DATA);
+
+			data = CIF_ISP_LSC_TABLE_DATA(
+					pconfig->b_data_tbl[i + j],
+					pconfig->b_data_tbl[i + j + 1]);
+			rkisp1_iowrite32(params_vdev, data,
+					 CIF_ISP_LSC_B_TABLE_DATA);
+		}
+	}
+
+	isp_lsc_table_sel = (isp_lsc_status & CIF_ISP_LSC_ACTIVE_TABLE) ?
+				CIF_ISP_LSC_TABLE_0 : CIF_ISP_LSC_TABLE_1;
+	rkisp1_iowrite32(params_vdev, isp_lsc_table_sel, CIF_ISP_LSC_TABLE_SEL);
+}
+
+static void lsc_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_lsc_config *arg)
+{
+	int i;
+	u32 lsc_ctrl;
+	unsigned int data;
+
+	/* To config must be off , store the current status firstly */
+	lsc_ctrl = rkisp1_ioread32(params_vdev, CIF_ISP_LSC_CTRL);
+	isp_param_clear_bits(params_vdev, CIF_ISP_LSC_CTRL,
+			     CIF_ISP_LSC_CTRL_ENA);
+	__lsc_correct_matrix_config(params_vdev, arg);
+
+	for (i = 0; i < 4; i++) {
+		/* program x size tables */
+		data = CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2],
+					arg->x_size_tbl[i * 2 + 1]);
+		rkisp1_iowrite32(params_vdev, data,
+				 CIF_ISP_LSC_XSIZE_01 + i * 4);
+
+		/* program x grad tables */
+		data = CIF_ISP_LSC_SECT_SIZE(arg->x_grad_tbl[i * 2],
+					arg->x_grad_tbl[i * 2 + 1]);
+		rkisp1_iowrite32(params_vdev, data,
+				 CIF_ISP_LSC_XGRAD_01 + i * 4);
+
+		/* program y size tables */
+		data = CIF_ISP_LSC_SECT_SIZE(arg->y_size_tbl[i * 2],
+					arg->y_size_tbl[i * 2 + 1]);
+		rkisp1_iowrite32(params_vdev, data,
+				 CIF_ISP_LSC_YSIZE_01 + i * 4);
+
+		/* program y grad tables */
+		data = CIF_ISP_LSC_SECT_SIZE(arg->y_grad_tbl[i * 2],
+					arg->y_grad_tbl[i * 2 + 1]);
+		rkisp1_iowrite32(params_vdev, data,
+				 CIF_ISP_LSC_YGRAD_01 + i * 4);
+	}
+
+	/* restore the bls ctrl status */
+	if (lsc_ctrl & CIF_ISP_LSC_CTRL_ENA) {
+		isp_param_set_bits(params_vdev,
+				   CIF_ISP_LSC_CTRL,
+				   CIF_ISP_LSC_CTRL_ENA);
+	} else {
+		isp_param_clear_bits(params_vdev,
+				     CIF_ISP_LSC_CTRL,
+				     CIF_ISP_LSC_CTRL_ENA);
+	}
+}
+
+/* ISP Filtering function */
+static void flt_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_flt_config *arg)
+{
+	rkisp1_iowrite32(params_vdev, arg->thresh_bl0, CIF_ISP_FILT_THRESH_BL0);
+	rkisp1_iowrite32(params_vdev, arg->thresh_bl1, CIF_ISP_FILT_THRESH_BL1);
+	rkisp1_iowrite32(params_vdev, arg->thresh_sh0, CIF_ISP_FILT_THRESH_SH0);
+	rkisp1_iowrite32(params_vdev, arg->thresh_sh1, CIF_ISP_FILT_THRESH_SH1);
+	rkisp1_iowrite32(params_vdev, arg->fac_bl0, CIF_ISP_FILT_FAC_BL0);
+	rkisp1_iowrite32(params_vdev, arg->fac_bl1, CIF_ISP_FILT_FAC_BL1);
+	rkisp1_iowrite32(params_vdev, arg->fac_mid, CIF_ISP_FILT_FAC_MID);
+	rkisp1_iowrite32(params_vdev, arg->fac_sh0, CIF_ISP_FILT_FAC_SH0);
+	rkisp1_iowrite32(params_vdev, arg->fac_sh1, CIF_ISP_FILT_FAC_SH1);
+	rkisp1_iowrite32(params_vdev, arg->lum_weight, CIF_ISP_FILT_LUM_WEIGHT);
+
+	rkisp1_iowrite32(params_vdev, (arg->mode ? CIF_ISP_FLT_MODE_DNR : 0) |
+			 CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) |
+			 CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) |
+			 CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1),
+			 CIF_ISP_FILT_MODE);
+}
+
+/* ISP demosaic interface function */
+static int bdm_config(struct rkisp1_isp_params_vdev *params_vdev,
+		      const struct cifisp_bdm_config *arg)
+{
+	/* set demosaic threshold */
+	rkisp1_iowrite32(params_vdev, arg->demosaic_th, CIF_ISP_DEMOSAIC);
+	return 0;
+}
+
+/* ISP GAMMA correction interface function */
+static void sdg_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_sdg_config *arg)
+{
+	int i;
+
+	rkisp1_iowrite32(params_vdev,
+			 arg->xa_pnts.gamma_dx0, CIF_ISP_GAMMA_DX_LO);
+	rkisp1_iowrite32(params_vdev,
+			 arg->xa_pnts.gamma_dx1, CIF_ISP_GAMMA_DX_HI);
+
+	for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+		rkisp1_iowrite32(params_vdev, arg->curve_r.gamma_y[i],
+				 CIF_ISP_GAMMA_R_Y0 + i * 4);
+		rkisp1_iowrite32(params_vdev, arg->curve_g.gamma_y[i],
+				 CIF_ISP_GAMMA_G_Y0 + i * 4);
+		rkisp1_iowrite32(params_vdev, arg->curve_b.gamma_y[i],
+				 CIF_ISP_GAMMA_B_Y0 + i * 4);
+	}
+}
+
+/* ISP GAMMA correction interface function */
+static void goc_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_goc_config *arg)
+{
+	int i;
+
+	isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
+			     CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
+	rkisp1_iowrite32(params_vdev, arg->mode, CIF_ISP_GAMMA_OUT_MODE);
+
+	for (i = 0; i < CIFISP_GAMMA_OUT_MAX_SAMPLES; i++)
+		rkisp1_iowrite32(params_vdev, arg->gamma_y[i],
+				 CIF_ISP_GAMMA_OUT_Y_0 + i * 4);
+}
+
+/* ISP Cross Talk */
+static void ctk_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_ctk_config *arg)
+{
+	rkisp1_iowrite32(params_vdev, arg->coeff0, CIF_ISP_CT_COEFF_0);
+	rkisp1_iowrite32(params_vdev, arg->coeff1, CIF_ISP_CT_COEFF_1);
+	rkisp1_iowrite32(params_vdev, arg->coeff2, CIF_ISP_CT_COEFF_2);
+	rkisp1_iowrite32(params_vdev, arg->coeff3, CIF_ISP_CT_COEFF_3);
+	rkisp1_iowrite32(params_vdev, arg->coeff4, CIF_ISP_CT_COEFF_4);
+	rkisp1_iowrite32(params_vdev, arg->coeff5, CIF_ISP_CT_COEFF_5);
+	rkisp1_iowrite32(params_vdev, arg->coeff6, CIF_ISP_CT_COEFF_6);
+	rkisp1_iowrite32(params_vdev, arg->coeff7, CIF_ISP_CT_COEFF_7);
+	rkisp1_iowrite32(params_vdev, arg->coeff8, CIF_ISP_CT_COEFF_8);
+	rkisp1_iowrite32(params_vdev, arg->ct_offset_r, CIF_ISP_CT_OFFSET_R);
+	rkisp1_iowrite32(params_vdev, arg->ct_offset_g, CIF_ISP_CT_OFFSET_G);
+	rkisp1_iowrite32(params_vdev, arg->ct_offset_b, CIF_ISP_CT_OFFSET_B);
+}
+
+static void ctk_enable(struct rkisp1_isp_params_vdev *params_vdev, bool en)
+{
+	if (en)
+		return;
+
+	/* Write back the default values. */
+	rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_0);
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_1);
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_2);
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_3);
+	rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_4);
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_5);
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_6);
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_COEFF_7);
+	rkisp1_iowrite32(params_vdev, 0x80, CIF_ISP_CT_COEFF_8);
+
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_R);
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_G);
+	rkisp1_iowrite32(params_vdev, 0, CIF_ISP_CT_OFFSET_B);
+}
+
+/* ISP White Balance Mode */
+static void awb_meas_config(struct rkisp1_isp_params_vdev *params_vdev,
+			    const struct cifisp_awb_meas_config *arg)
+{
+	/* based on the mode,configure the awb module */
+	if (arg->awb_mode == CIFISP_AWB_MODE_YCBCR) {
+		/* Reference Cb and Cr */
+		rkisp1_iowrite32(params_vdev,
+				 CIF_ISP_AWB_REF_CR_SET(arg->awb_ref_cr) |
+				 arg->awb_ref_cb, CIF_ISP_AWB_REF);
+		/* Yc Threshold */
+		rkisp1_iowrite32(params_vdev,
+				 CIF_ISP_AWB_MAX_Y_SET(arg->max_y) |
+				 CIF_ISP_AWB_MIN_Y_SET(arg->min_y) |
+				 CIF_ISP_AWB_MAX_CS_SET(arg->max_csum) |
+				 arg->min_c, CIF_ISP_AWB_THRESH);
+	}
+
+	/* window offset */
+	rkisp1_iowrite32(params_vdev,
+			 arg->awb_wnd.v_offs, CIF_ISP_AWB_WND_V_OFFS);
+	rkisp1_iowrite32(params_vdev,
+			 arg->awb_wnd.h_offs, CIF_ISP_AWB_WND_H_OFFS);
+	/* AWB window size */
+	rkisp1_iowrite32(params_vdev,
+			 arg->awb_wnd.v_size, CIF_ISP_AWB_WND_V_SIZE);
+	rkisp1_iowrite32(params_vdev,
+			 arg->awb_wnd.h_size, CIF_ISP_AWB_WND_H_SIZE);
+	/* Number of frames */
+	rkisp1_iowrite32(params_vdev,
+			 arg->frames, CIF_ISP_AWB_FRAMES);
+}
+
+static void awb_meas_enable(struct rkisp1_isp_params_vdev *params_vdev,
+			    const struct cifisp_awb_meas_config *arg, bool en)
+{
+	u32 reg_val = rkisp1_ioread32(params_vdev, CIF_ISP_AWB_PROP);
+
+	/* switch off */
+	reg_val &= CIF_ISP_AWB_MODE_MASK_NONE;
+
+	if (en) {
+		if (arg->awb_mode == CIFISP_AWB_MODE_RGB)
+			reg_val |= CIF_ISP_AWB_MODE_RGB_EN;
+		else
+			reg_val |= CIF_ISP_AWB_MODE_YCBCR_EN;
+
+		rkisp1_iowrite32(params_vdev, reg_val, CIF_ISP_AWB_PROP);
+
+		/* Measurements require AWB block be active. */
+		/* TODO: need to enable here ? awb_gain_enable has done this */
+		isp_param_set_bits(params_vdev, CIF_ISP_CTRL,
+				   CIF_ISP_CTRL_ISP_AWB_ENA);
+	} else {
+		rkisp1_iowrite32(params_vdev,
+				 reg_val, CIF_ISP_AWB_PROP);
+		isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
+				     CIF_ISP_CTRL_ISP_AWB_ENA);
+	}
+}
+
+static void awb_gain_config(struct rkisp1_isp_params_vdev *params_vdev,
+			    const struct cifisp_awb_gain_config *arg)
+{
+	rkisp1_iowrite32(params_vdev,
+			 CIF_ISP_AWB_GAIN_R_SET(arg->gain_green_r) |
+			 arg->gain_green_b, CIF_ISP_AWB_GAIN_G);
+
+	rkisp1_iowrite32(params_vdev, CIF_ISP_AWB_GAIN_R_SET(arg->gain_red) |
+			 arg->gain_blue, CIF_ISP_AWB_GAIN_RB);
+}
+
+static void aec_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_aec_config *arg)
+{
+	unsigned int block_hsize, block_vsize;
+
+	rkisp1_iowrite32(params_vdev,
+			 ((arg->autostop) ? CIF_ISP_EXP_CTRL_AUTOSTOP : 0) |
+			 ((arg->mode == CIFISP_EXP_MEASURING_MODE_1) ?
+			 CIF_ISP_EXP_CTRL_MEASMODE_1 : 0), CIF_ISP_EXP_CTRL);
+
+	rkisp1_iowrite32(params_vdev,
+			 arg->meas_window.h_offs, CIF_ISP_EXP_H_OFFSET);
+	rkisp1_iowrite32(params_vdev,
+			 arg->meas_window.v_offs, CIF_ISP_EXP_V_OFFSET);
+
+	block_hsize = arg->meas_window.h_size / CIF_ISP_EXP_COLUMN_NUM - 1;
+	block_vsize = arg->meas_window.v_size / CIF_ISP_EXP_ROW_NUM - 1;
+
+	rkisp1_iowrite32(params_vdev, CIF_ISP_EXP_H_SIZE_SET(block_hsize),
+			 CIF_ISP_EXP_H_SIZE);
+	rkisp1_iowrite32(params_vdev, CIF_ISP_EXP_V_SIZE_SET(block_vsize),
+			 CIF_ISP_EXP_V_SIZE);
+}
+
+static void cproc_config(struct rkisp1_isp_params_vdev *params_vdev,
+			 const struct cifisp_cproc_config *arg)
+{
+	struct cifisp_isp_other_cfg *cur_other_cfg = &params_vdev->cur_params.others;
+	struct cifisp_ie_config *cur_ie_config = &cur_other_cfg->ie_config;
+	u32 effect = cur_ie_config->effect;
+	u32 quantization = params_vdev->quantization;
+
+	rkisp1_iowrite32(params_vdev, arg->contrast, CIF_C_PROC_CONTRAST);
+	rkisp1_iowrite32(params_vdev, arg->hue, CIF_C_PROC_HUE);
+	rkisp1_iowrite32(params_vdev, arg->sat, CIF_C_PROC_SATURATION);
+	rkisp1_iowrite32(params_vdev, arg->brightness, CIF_C_PROC_BRIGHTNESS);
+
+	if (quantization != V4L2_QUANTIZATION_FULL_RANGE ||
+	    effect != V4L2_COLORFX_NONE) {
+		isp_param_clear_bits(params_vdev, CIF_C_PROC_CTRL,
+				     CIF_C_PROC_YOUT_FULL |
+				     CIF_C_PROC_YIN_FULL |
+				     CIF_C_PROC_COUT_FULL);
+	} else {
+		isp_param_set_bits(params_vdev, CIF_C_PROC_CTRL,
+				   CIF_C_PROC_YOUT_FULL |
+				   CIF_C_PROC_YIN_FULL |
+				   CIF_C_PROC_COUT_FULL);
+	}
+}
+
+static void hst_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_hst_config *arg)
+{
+	unsigned int block_hsize, block_vsize;
+	static const u32 hist_weight_regs[] = {
+		CIF_ISP_HIST_WEIGHT_00TO30, CIF_ISP_HIST_WEIGHT_40TO21,
+		CIF_ISP_HIST_WEIGHT_31TO12, CIF_ISP_HIST_WEIGHT_22TO03,
+		CIF_ISP_HIST_WEIGHT_13TO43, CIF_ISP_HIST_WEIGHT_04TO34,
+		CIF_ISP_HIST_WEIGHT_44,
+	};
+	int i;
+	const u8 *weight;
+
+	rkisp1_iowrite32(params_vdev,
+			 CIF_ISP_HIST_PREDIV_SET(arg->histogram_predivider),
+			 CIF_ISP_HIST_PROP);
+	rkisp1_iowrite32(params_vdev,
+			arg->meas_window.h_offs,
+			CIF_ISP_HIST_H_OFFS);
+	rkisp1_iowrite32(params_vdev,
+			arg->meas_window.v_offs,
+			CIF_ISP_HIST_V_OFFS);
+
+	block_hsize = arg->meas_window.h_size / CIF_ISP_HIST_COLUMN_NUM - 1;
+	block_vsize = arg->meas_window.v_size / CIF_ISP_HIST_ROW_NUM - 1;
+
+	rkisp1_iowrite32(params_vdev, block_hsize, CIF_ISP_HIST_H_SIZE);
+	rkisp1_iowrite32(params_vdev, block_vsize, CIF_ISP_HIST_V_SIZE);
+
+	weight = arg->hist_weight;
+	for (i = 0; i < ARRAY_SIZE(hist_weight_regs); ++i, weight += 4)
+		rkisp1_iowrite32(params_vdev, CIF_ISP_HIST_WEIGHT_SET(
+				 weight[0], weight[1], weight[2], weight[3]),
+				 hist_weight_regs[i]);
+}
+
+static void hst_enable(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_hst_config *arg, bool en)
+{
+	if (en)	{
+		u32 hist_prop = rkisp1_ioread32(params_vdev, CIF_ISP_HIST_PROP);
+
+		hist_prop &= ~CIF_ISP_HIST_PROP_MODE_MASK;
+		hist_prop |= arg->mode;
+		isp_param_set_bits(params_vdev, CIF_ISP_HIST_PROP, hist_prop);
+	} else {
+		isp_param_clear_bits(params_vdev, CIF_ISP_HIST_PROP,
+				CIF_ISP_HIST_PROP_MODE_MASK);
+	}
+}
+
+static void afm_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_afc_config *arg)
+{
+	int i;
+	size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->afm_win),
+				  arg->num_afm_win);
+
+	/* Switch off to configure. Enabled during normal flow in frame isr. */
+	isp_param_clear_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
+
+	for (i = 0; i < num_of_win; i++) {
+		rkisp1_iowrite32(params_vdev,
+				 CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_offs) |
+				 CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_offs),
+				 CIF_ISP_AFM_LT_A + i * 8);
+		rkisp1_iowrite32(params_vdev,
+				 CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_size +
+						      arg->afm_win[i].h_offs) |
+				 CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_size +
+						      arg->afm_win[i].v_offs),
+				 CIF_ISP_AFM_RB_A + i * 8);
+	}
+	rkisp1_iowrite32(params_vdev, arg->thres, CIF_ISP_AFM_THRES);
+	rkisp1_iowrite32(params_vdev, arg->var_shift, CIF_ISP_AFM_VAR_SHIFT);
+}
+
+static void ie_config(struct rkisp1_isp_params_vdev *params_vdev,
+		      const struct cifisp_ie_config *arg)
+{
+	u32 eff_ctrl;
+
+	eff_ctrl = rkisp1_ioread32(params_vdev, CIF_IMG_EFF_CTRL);
+	eff_ctrl &= ~CIF_IMG_EFF_CTRL_MODE_MASK;
+
+	if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE)
+		eff_ctrl |= CIF_IMG_EFF_CTRL_YCBCR_FULL;
+
+	switch (arg->effect) {
+	case V4L2_COLORFX_SEPIA:
+		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SEPIA;
+		break;
+	case V4L2_COLORFX_SET_CBCR:
+		rkisp1_iowrite32(params_vdev, arg->eff_tint, CIF_IMG_EFF_TINT);
+		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SEPIA;
+		break;
+		/*
+		 * Color selection is similar to water color(AQUA):
+		 * grayscale + selected color w threshold
+		 */
+	case V4L2_COLORFX_AQUA:
+		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_COLOR_SEL;
+		rkisp1_iowrite32(params_vdev, arg->color_sel,
+				 CIF_IMG_EFF_COLOR_SEL);
+		break;
+	case V4L2_COLORFX_EMBOSS:
+		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_EMBOSS;
+		rkisp1_iowrite32(params_vdev, arg->eff_mat_1,
+				 CIF_IMG_EFF_MAT_1);
+		rkisp1_iowrite32(params_vdev, arg->eff_mat_2,
+				 CIF_IMG_EFF_MAT_2);
+		rkisp1_iowrite32(params_vdev, arg->eff_mat_3,
+				 CIF_IMG_EFF_MAT_3);
+		break;
+	case V4L2_COLORFX_SKETCH:
+		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_SKETCH;
+		rkisp1_iowrite32(params_vdev, arg->eff_mat_3,
+				 CIF_IMG_EFF_MAT_3);
+		rkisp1_iowrite32(params_vdev, arg->eff_mat_4,
+				 CIF_IMG_EFF_MAT_4);
+		rkisp1_iowrite32(params_vdev, arg->eff_mat_5,
+				 CIF_IMG_EFF_MAT_5);
+		break;
+	case V4L2_COLORFX_BW:
+		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_BLACKWHITE;
+		break;
+	case V4L2_COLORFX_NEGATIVE:
+		eff_ctrl |= CIF_IMG_EFF_CTRL_MODE_NEGATIVE;
+		break;
+	default:
+		break;
+	}
+
+	rkisp1_iowrite32(params_vdev, eff_ctrl, CIF_IMG_EFF_CTRL);
+}
+
+static void ie_enable(struct rkisp1_isp_params_vdev *params_vdev, bool en)
+{
+	if (en) {
+		isp_param_set_bits(params_vdev, CIF_ICCL, CIF_ICCL_IE_CLK);
+		rkisp1_iowrite32(params_vdev, CIF_IMG_EFF_CTRL_ENABLE,
+				 CIF_IMG_EFF_CTRL);
+		isp_param_set_bits(params_vdev, CIF_IMG_EFF_CTRL,
+				   CIF_IMG_EFF_CTRL_CFG_UPD);
+	} else {
+		/* Disable measurement */
+		isp_param_clear_bits(params_vdev, CIF_IMG_EFF_CTRL,
+				     CIF_IMG_EFF_CTRL_ENABLE);
+		isp_param_clear_bits(params_vdev, CIF_ICCL, CIF_ICCL_IE_CLK);
+	}
+}
+
+static void csm_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       bool full_range)
+{
+	static const u16 full_range_coeff[] = {
+		0x0026, 0x004b, 0x000f,
+		0x01ea, 0x01d6, 0x0040,
+		0x0040, 0x01ca, 0x01f6
+	};
+	static const u16 limited_range_coeff[] = {
+		0x0021, 0x0040, 0x000d,
+		0x01ed, 0x01db, 0x0038,
+		0x0038, 0x01d1, 0x01f7,
+	};
+	int i;
+
+	if (full_range) {
+		for (i = 0; i < ARRAY_SIZE(full_range_coeff); i++)
+			rkisp1_iowrite32(params_vdev, full_range_coeff[i],
+					 CIF_ISP_CC_COEFF_0 + i * 4);
+
+		isp_param_set_bits(params_vdev, CIF_ISP_CTRL,
+				   CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
+				   CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA);
+	} else {
+		for (i = 0; i < ARRAY_SIZE(limited_range_coeff); i++)
+			rkisp1_iowrite32(params_vdev, limited_range_coeff[i],
+					 CIF_ISP_CC_COEFF_0 + i * 4);
+
+		isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
+				     CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
+				     CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA);
+	}
+}
+
+/* ISP De-noise Pre-Filter(DPF) function */
+static void dpf_config(struct rkisp1_isp_params_vdev *params_vdev,
+		       const struct cifisp_dpf_config *arg)
+{
+	unsigned int isp_dpf_mode;
+	unsigned int spatial_coeff;
+	unsigned int i;
+
+	switch (arg->gain.mode) {
+	case CIFISP_DPF_GAIN_USAGE_NF_GAINS:
+		isp_dpf_mode = CIF_ISP_DPF_MODE_USE_NF_GAIN |
+				CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
+		break;
+	case CIFISP_DPF_GAIN_USAGE_LSC_GAINS:
+		isp_dpf_mode = CIF_ISP_DPF_MODE_LSC_GAIN_COMP;
+		break;
+	case CIFISP_DPF_GAIN_USAGE_NF_LSC_GAINS:
+		isp_dpf_mode = CIF_ISP_DPF_MODE_USE_NF_GAIN |
+				CIF_ISP_DPF_MODE_AWB_GAIN_COMP |
+				CIF_ISP_DPF_MODE_LSC_GAIN_COMP;
+		break;
+	case CIFISP_DPF_GAIN_USAGE_AWB_GAINS:
+		isp_dpf_mode = CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
+		break;
+	case CIFISP_DPF_GAIN_USAGE_AWB_LSC_GAINS:
+		isp_dpf_mode = CIF_ISP_DPF_MODE_LSC_GAIN_COMP |
+				CIF_ISP_DPF_MODE_AWB_GAIN_COMP;
+		break;
+	case CIFISP_DPF_GAIN_USAGE_DISABLED:
+	default:
+		isp_dpf_mode = 0;
+		break;
+	}
+
+	if (arg->nll.scale_mode == CIFISP_NLL_SCALE_LOGARITHMIC)
+		isp_dpf_mode |= CIF_ISP_DPF_MODE_NLL_SEGMENTATION;
+	if (arg->rb_flt.fltsize == CIFISP_DPF_RB_FILTERSIZE_9x9)
+		isp_dpf_mode |= CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9;
+	if (!arg->rb_flt.r_enable)
+		isp_dpf_mode |= CIF_ISP_DPF_MODE_R_FLT_DIS;
+	if (!arg->rb_flt.b_enable)
+		isp_dpf_mode |= CIF_ISP_DPF_MODE_B_FLT_DIS;
+	if (!arg->g_flt.gb_enable)
+		isp_dpf_mode |= CIF_ISP_DPF_MODE_GB_FLT_DIS;
+	if (!arg->g_flt.gr_enable)
+		isp_dpf_mode |= CIF_ISP_DPF_MODE_GR_FLT_DIS;
+
+	isp_param_set_bits(params_vdev, CIF_ISP_DPF_MODE, isp_dpf_mode);
+	rkisp1_iowrite32(params_vdev, arg->gain.nf_b_gain,
+			 CIF_ISP_DPF_NF_GAIN_B);
+	rkisp1_iowrite32(params_vdev, arg->gain.nf_r_gain,
+			 CIF_ISP_DPF_NF_GAIN_R);
+	rkisp1_iowrite32(params_vdev, arg->gain.nf_gb_gain,
+			 CIF_ISP_DPF_NF_GAIN_GB);
+	rkisp1_iowrite32(params_vdev, arg->gain.nf_gr_gain,
+			 CIF_ISP_DPF_NF_GAIN_GR);
+
+	for (i = 0; i < CIFISP_DPF_MAX_NLF_COEFFS; i++) {
+		rkisp1_iowrite32(params_vdev, arg->nll.coeff[i],
+				 CIF_ISP_DPF_NULL_COEFF_0 + i * 4);
+	}
+
+	spatial_coeff = arg->g_flt.spatial_coeff[0] |
+			(arg->g_flt.spatial_coeff[1] << 8) |
+			(arg->g_flt.spatial_coeff[2] << 16) |
+			(arg->g_flt.spatial_coeff[3] << 24);
+	rkisp1_iowrite32(params_vdev, spatial_coeff,
+			 CIF_ISP_DPF_S_WEIGHT_G_1_4);
+
+	spatial_coeff = arg->g_flt.spatial_coeff[4] |
+			(arg->g_flt.spatial_coeff[5] << 8);
+	rkisp1_iowrite32(params_vdev, spatial_coeff,
+			 CIF_ISP_DPF_S_WEIGHT_G_5_6);
+
+	spatial_coeff = arg->rb_flt.spatial_coeff[0] |
+			(arg->rb_flt.spatial_coeff[1] << 8) |
+			(arg->rb_flt.spatial_coeff[2] << 16) |
+			(arg->rb_flt.spatial_coeff[3] << 24);
+	rkisp1_iowrite32(params_vdev, spatial_coeff,
+			 CIF_ISP_DPF_S_WEIGHT_RB_1_4);
+
+	spatial_coeff = arg->rb_flt.spatial_coeff[4] |
+			(arg->rb_flt.spatial_coeff[5] << 8);
+	rkisp1_iowrite32(params_vdev, spatial_coeff,
+			CIF_ISP_DPF_S_WEIGHT_RB_5_6);
+}
+
+static void dpf_strength_config(struct rkisp1_isp_params_vdev *params_vdev,
+				const struct cifisp_dpf_strength_config *arg)
+{
+	rkisp1_iowrite32(params_vdev, arg->b, CIF_ISP_DPF_STRENGTH_B);
+	rkisp1_iowrite32(params_vdev, arg->g, CIF_ISP_DPF_STRENGTH_G);
+	rkisp1_iowrite32(params_vdev, arg->r, CIF_ISP_DPF_STRENGTH_R);
+}
+
+static __maybe_unused
+void __isp_isr_other_config(struct rkisp1_isp_params_vdev *params_vdev,
+			    const struct rkisp1_isp_params_cfg *new_params)
+{
+	unsigned int module_en_update, module_cfg_update, module_ens;
+
+	module_en_update = new_params->module_en_update;
+	module_cfg_update = new_params->module_cfg_update;
+	module_ens = new_params->module_ens;
+
+	if ((module_en_update & CIFISP_MODULE_DPCC) ||
+	    (module_cfg_update & CIFISP_MODULE_DPCC)) {
+		/*update dpc config */
+		if ((module_cfg_update & CIFISP_MODULE_DPCC))
+			dpcc_config(params_vdev,
+					&new_params->others.dpcc_config);
+
+		if (module_en_update & CIFISP_MODULE_DPCC) {
+			if (!!(module_ens & CIFISP_MODULE_DPCC))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_DPCC_MODE,
+						   CIF_ISP_DPCC_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_DPCC_MODE,
+						     CIF_ISP_DPCC_ENA);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_BLS) ||
+	    (module_cfg_update & CIFISP_MODULE_BLS)) {
+		/* update bls config */
+		if ((module_cfg_update & CIFISP_MODULE_BLS))
+			bls_config(params_vdev, &new_params->others.bls_config);
+
+		if (module_en_update & CIFISP_MODULE_BLS) {
+			if (!!(module_ens & CIFISP_MODULE_BLS))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_BLS_CTRL,
+						   CIF_ISP_BLS_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_BLS_CTRL,
+						     CIF_ISP_BLS_ENA);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_SDG) ||
+	    (module_cfg_update & CIFISP_MODULE_SDG)) {
+		/* update sdg config */
+		if ((module_cfg_update & CIFISP_MODULE_SDG))
+			sdg_config(params_vdev, &new_params->others.sdg_config);
+
+		if (module_en_update & CIFISP_MODULE_SDG) {
+			if (!!(module_ens & CIFISP_MODULE_SDG))
+				isp_param_set_bits(params_vdev,
+						CIF_ISP_CTRL,
+						CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						CIF_ISP_CTRL,
+						CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_LSC) ||
+	    (module_cfg_update & CIFISP_MODULE_LSC)) {
+		/* update lsc config */
+		if ((module_cfg_update & CIFISP_MODULE_LSC))
+			lsc_config(params_vdev, &new_params->others.lsc_config);
+
+		if (module_en_update & CIFISP_MODULE_LSC) {
+			if (!!(module_ens & CIFISP_MODULE_LSC))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_LSC_CTRL,
+						   CIF_ISP_LSC_CTRL_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_LSC_CTRL,
+						     CIF_ISP_LSC_CTRL_ENA);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_AWB_GAIN) ||
+	    (module_cfg_update & CIFISP_MODULE_AWB_GAIN)) {
+		/* update awb gains */
+		if ((module_cfg_update & CIFISP_MODULE_AWB_GAIN))
+			awb_gain_config(params_vdev,
+					&new_params->others.awb_gain_config);
+
+		if (module_en_update & CIFISP_MODULE_AWB_GAIN) {
+			if (!!(module_ens & CIFISP_MODULE_AWB_GAIN))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_CTRL,
+						   CIF_ISP_CTRL_ISP_AWB_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_CTRL,
+						     CIF_ISP_CTRL_ISP_AWB_ENA);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_BDM) ||
+	    (module_cfg_update & CIFISP_MODULE_BDM)) {
+		/* update bdm config */
+		if ((module_cfg_update & CIFISP_MODULE_BDM))
+			bdm_config(params_vdev, &new_params->others.bdm_config);
+
+		if (module_en_update & CIFISP_MODULE_BDM) {
+			if (!!(module_ens & CIFISP_MODULE_BDM))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_DEMOSAIC,
+						   CIF_ISP_DEMOSAIC_BYPASS);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_DEMOSAIC,
+						     CIF_ISP_DEMOSAIC_BYPASS);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_FLT) ||
+	    (module_cfg_update & CIFISP_MODULE_FLT)) {
+		/* update filter config */
+		if ((module_cfg_update & CIFISP_MODULE_FLT))
+			flt_config(params_vdev, &new_params->others.flt_config);
+
+		if (module_en_update & CIFISP_MODULE_FLT) {
+			if (!!(module_ens & CIFISP_MODULE_FLT))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_FILT_MODE,
+						   CIF_ISP_FLT_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_FILT_MODE,
+						     CIF_ISP_FLT_ENA);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_CTK) ||
+	    (module_cfg_update & CIFISP_MODULE_CTK)) {
+		/* update ctk config */
+		if ((module_cfg_update & CIFISP_MODULE_CTK))
+			ctk_config(params_vdev, &new_params->others.ctk_config);
+
+		if (module_en_update & CIFISP_MODULE_CTK)
+			ctk_enable(params_vdev,
+				   !!(module_ens & CIFISP_MODULE_CTK));
+	}
+
+	if ((module_en_update & CIFISP_MODULE_GOC) ||
+	    (module_cfg_update & CIFISP_MODULE_GOC)) {
+		/* update goc config */
+		if ((module_cfg_update & CIFISP_MODULE_GOC))
+			goc_config(params_vdev, &new_params->others.goc_config);
+
+		if (module_en_update & CIFISP_MODULE_GOC) {
+			if (!!(module_ens & CIFISP_MODULE_GOC))
+				isp_param_set_bits(params_vdev,
+						CIF_ISP_CTRL,
+						CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						CIF_ISP_CTRL,
+						CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_CPROC) ||
+	    (module_cfg_update & CIFISP_MODULE_CPROC)) {
+		/* update cproc config */
+		if ((module_cfg_update & CIFISP_MODULE_CPROC)) {
+			cproc_config(params_vdev,
+				     &new_params->others.cproc_config);
+
+		}
+
+		if (module_en_update & CIFISP_MODULE_CPROC) {
+			if (!!(module_ens & CIFISP_MODULE_CPROC))
+				isp_param_set_bits(params_vdev,
+						   CIF_C_PROC_CTRL,
+						   CIF_C_PROC_CTR_ENABLE);
+			else
+				isp_param_clear_bits(params_vdev,
+						   CIF_C_PROC_CTRL,
+						   CIF_C_PROC_CTR_ENABLE);
+		}
+	}
+
+
+	if ((module_en_update & CIFISP_MODULE_IE) ||
+	    (module_cfg_update & CIFISP_MODULE_IE)) {
+		/* update ie config */
+		if ((module_cfg_update & CIFISP_MODULE_IE))
+			ie_config(params_vdev, &new_params->others.ie_config);
+
+		if (module_en_update & CIFISP_MODULE_IE)
+			ie_enable(params_vdev,
+				   !!(module_ens & CIFISP_MODULE_IE));
+	}
+
+	if ((module_en_update & CIFISP_MODULE_DPF) ||
+	    (module_cfg_update & CIFISP_MODULE_DPF)) {
+		/* update dpf  config */
+		if ((module_cfg_update & CIFISP_MODULE_DPF))
+			dpf_config(params_vdev, &new_params->others.dpf_config);
+
+		if (module_en_update & CIFISP_MODULE_DPF) {
+			if (!!(module_ens & CIFISP_MODULE_DPF))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_DPF_MODE,
+						   CIF_ISP_DPF_MODE_EN);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_DPF_MODE,
+						     CIF_ISP_DPF_MODE_EN);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_DPF_STRENGTH) ||
+	    (module_cfg_update & CIFISP_MODULE_DPF_STRENGTH)) {
+		/* update dpf strength config */
+		dpf_strength_config(params_vdev,
+				    &new_params->others.dpf_strength_config);
+	}
+}
+
+static __maybe_unused
+void __isp_isr_meas_config(struct rkisp1_isp_params_vdev *params_vdev,
+			   struct  rkisp1_isp_params_cfg *new_params)
+{
+	unsigned int module_en_update, module_cfg_update, module_ens;
+
+	module_en_update = new_params->module_en_update;
+	module_cfg_update = new_params->module_cfg_update;
+	module_ens = new_params->module_ens;
+
+	if ((module_en_update & CIFISP_MODULE_AWB) ||
+	    (module_cfg_update & CIFISP_MODULE_AWB)) {
+		/* update awb config */
+		if ((module_cfg_update & CIFISP_MODULE_AWB))
+			awb_meas_config(params_vdev,
+					&new_params->meas.awb_meas_config);
+
+		if (module_en_update & CIFISP_MODULE_AWB)
+			awb_meas_enable(params_vdev,
+					&new_params->meas.awb_meas_config,
+					!!(module_ens & CIFISP_MODULE_AWB));
+	}
+
+	if ((module_en_update & CIFISP_MODULE_AFC) ||
+	    (module_cfg_update & CIFISP_MODULE_AFC)) {
+		/* update afc config */
+		if ((module_cfg_update & CIFISP_MODULE_AFC))
+			afm_config(params_vdev, &new_params->meas.afc_config);
+
+		if (module_en_update & CIFISP_MODULE_AFC) {
+			if (!!(module_ens & CIFISP_MODULE_AFC))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_AFM_CTRL,
+						   CIF_ISP_AFM_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_AFM_CTRL,
+						     CIF_ISP_AFM_ENA);
+		}
+	}
+
+	if ((module_en_update & CIFISP_MODULE_HST) ||
+	    (module_cfg_update & CIFISP_MODULE_HST)) {
+		/* update hst config */
+		if ((module_cfg_update & CIFISP_MODULE_HST))
+			hst_config(params_vdev, &new_params->meas.hst_config);
+
+		if (module_en_update & CIFISP_MODULE_HST)
+			hst_enable(params_vdev,
+				   &new_params->meas.hst_config,
+				   !!(module_ens & CIFISP_MODULE_HST));
+	}
+
+	if ((module_en_update & CIFISP_MODULE_AEC) ||
+	    (module_cfg_update & CIFISP_MODULE_AEC)) {
+		/* update aec config */
+		if ((module_cfg_update & CIFISP_MODULE_AEC))
+			aec_config(params_vdev, &new_params->meas.aec_config);
+
+		if (module_en_update & CIFISP_MODULE_AEC) {
+			if (!!(module_ens & CIFISP_MODULE_AEC))
+				isp_param_set_bits(params_vdev,
+						   CIF_ISP_EXP_CTRL,
+						   CIF_ISP_EXP_ENA);
+			else
+				isp_param_clear_bits(params_vdev,
+						     CIF_ISP_EXP_CTRL,
+						     CIF_ISP_EXP_ENA);
+		}
+	}
+}
+
+void rkisp1_params_isr(struct rkisp1_isp_params_vdev *params_vdev, u32 isp_mis)
+{
+	struct rkisp1_isp_params_cfg *new_params;
+	struct rkisp1_buffer *cur_buf = NULL;
+
+	spin_lock(&params_vdev->config_lock);
+	if (!params_vdev->streamon) {
+		spin_unlock(&params_vdev->config_lock);
+		return;
+	}
+
+	/* get one empty buffer */
+	if (!list_empty(&params_vdev->params))
+		cur_buf = list_first_entry(&params_vdev->params,
+					   struct rkisp1_buffer, queue);
+	spin_unlock(&params_vdev->config_lock);
+
+	if (!cur_buf)
+		return;
+
+	new_params = (struct rkisp1_isp_params_cfg *)(cur_buf->vaddr[0]);
+
+	if (isp_mis & CIF_ISP_FRAME) {
+		__isp_isr_other_config(params_vdev, new_params);
+		__isp_isr_meas_config(params_vdev, new_params);
+		spin_lock(&params_vdev->config_lock);
+		list_del(&cur_buf->queue);
+		spin_unlock(&params_vdev->config_lock);
+		vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+	}
+}
+
+static const struct cifisp_awb_meas_config awb_params_default_config = {
+	{
+		0, 0, RKISP1_DEFAULT_WIDTH, RKISP1_DEFAULT_HEIGHT
+	},
+	CIFISP_AWB_MODE_YCBCR, 200, 30, 20, 20, 0, 128, 128
+};
+
+static const struct cifisp_aec_config aec_params_default_config = {
+	CIFISP_EXP_MEASURING_MODE_0,
+	CIFISP_EXP_CTRL_AUTOSTOP_0,
+	{
+		RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2,
+		RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1
+	}
+};
+
+static const struct cifisp_hst_config hst_params_default_config = {
+	CIFISP_HISTOGRAM_MODE_RGB_COMBINED,
+	3,
+	{
+		RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2,
+		RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1
+	},
+	{
+		0, /* To be filled in with 0x01 at runtime. */
+	}
+};
+
+static const struct cifisp_afc_config afc_params_default_config = {
+	1,
+	{
+		{
+			300, 225, 200, 150
+		}
+	},
+	4,
+	14
+};
+
+static
+void rkisp1_params_config_parameter(struct rkisp1_isp_params_vdev *params_vdev)
+{
+	struct cifisp_hst_config hst = hst_params_default_config;
+
+	spin_lock(&params_vdev->config_lock);
+
+	awb_meas_config(params_vdev, &awb_params_default_config);
+	awb_meas_enable(params_vdev, &awb_params_default_config, true);
+
+	aec_config(params_vdev, &aec_params_default_config);
+	isp_param_set_bits(params_vdev, CIF_ISP_EXP_CTRL, CIF_ISP_EXP_ENA);
+
+	afm_config(params_vdev, &afc_params_default_config);
+	isp_param_set_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
+
+	memset(hst.hist_weight, 0x01, sizeof(hst.hist_weight));
+	hst_config(params_vdev, &hst);
+	isp_param_set_bits(params_vdev, CIF_ISP_HIST_PROP,
+			   ~CIF_ISP_HIST_PROP_MODE_MASK |
+			   hst_params_default_config.mode);
+
+	/* set the  range */
+	if (params_vdev->quantization == V4L2_QUANTIZATION_FULL_RANGE)
+		csm_config(params_vdev, true);
+	else
+		csm_config(params_vdev, false);
+
+	/* override the default things */
+	__isp_isr_other_config(params_vdev, &params_vdev->cur_params);
+	__isp_isr_meas_config(params_vdev, &params_vdev->cur_params);
+
+	spin_unlock(&params_vdev->config_lock);
+}
+
+/* Not called when the camera active, thus not isr protection. */
+void rkisp1_configure_isp(struct rkisp1_isp_params_vdev *params_vdev,
+			  struct ispsd_in_fmt *in_fmt,
+			  enum v4l2_quantization quantization)
+{
+	if (!params_vdev)
+		return;
+
+	if (quantization)
+		params_vdev->quantization = quantization;
+	if (in_fmt)
+		params_vdev->raw_type = in_fmt->bayer_pat;
+	if (params_vdev)
+		rkisp1_params_config_parameter(params_vdev);
+}
+
+/* Not called when the camera active, thus not isr protection. */
+void rkisp1_disable_isp(struct rkisp1_isp_params_vdev *params_vdev)
+{
+	isp_param_clear_bits(params_vdev, CIF_ISP_DPCC_MODE, CIF_ISP_DPCC_ENA);
+	isp_param_clear_bits(params_vdev, CIF_ISP_LSC_CTRL,
+			     CIF_ISP_LSC_CTRL_ENA);
+	isp_param_clear_bits(params_vdev, CIF_ISP_BLS_CTRL, CIF_ISP_BLS_ENA);
+	isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
+			     CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
+	isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
+			     CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
+	isp_param_clear_bits(params_vdev, CIF_ISP_DEMOSAIC,
+			     CIF_ISP_DEMOSAIC_BYPASS);
+	isp_param_clear_bits(params_vdev, CIF_ISP_FILT_MODE, CIF_ISP_FLT_ENA);
+	awb_meas_enable(params_vdev, NULL, false);
+	isp_param_clear_bits(params_vdev, CIF_ISP_CTRL,
+			     CIF_ISP_CTRL_ISP_AWB_ENA);
+	isp_param_clear_bits(params_vdev, CIF_ISP_EXP_CTRL, CIF_ISP_EXP_ENA);
+	ctk_enable(params_vdev, false);
+	isp_param_clear_bits(params_vdev, CIF_C_PROC_CTRL,
+			     CIF_C_PROC_CTR_ENABLE);
+	hst_enable(params_vdev, NULL, false);
+	isp_param_clear_bits(params_vdev, CIF_ISP_AFM_CTRL, CIF_ISP_AFM_ENA);
+	ie_enable(params_vdev, false);
+	isp_param_clear_bits(params_vdev, CIF_ISP_DPF_MODE,
+			     CIF_ISP_DPF_MODE_EN);
+}
+
+static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv,
+					   struct v4l2_fmtdesc *f)
+{
+	struct video_device *video = video_devdata(file);
+	struct rkisp1_isp_params_vdev *params_vdev = video_get_drvdata(video);
+
+	if (f->index > 0 || f->type != video->queue->type)
+		return -EINVAL;
+
+	f->pixelformat = params_vdev->vdev_fmt.fmt.meta.dataformat;
+
+	return 0;
+}
+
+static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh,
+					struct v4l2_format *f)
+{
+	struct video_device *video = video_devdata(file);
+	struct rkisp1_isp_params_vdev *params_vdev = video_get_drvdata(video);
+	struct v4l2_meta_format *meta = &f->fmt.meta;
+
+	if (f->type != video->queue->type)
+		return -EINVAL;
+
+	memset(meta, 0, sizeof(*meta));
+	meta->dataformat = params_vdev->vdev_fmt.fmt.meta.dataformat;
+	meta->buffersize = params_vdev->vdev_fmt.fmt.meta.buffersize;
+
+	return 0;
+}
+
+static int rkisp1_params_querycap(struct file *file,
+				  void *priv, struct v4l2_capability *cap)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	strcpy(cap->driver, DRIVER_NAME);
+	strlcpy(cap->card, vdev->name, sizeof(cap->card));
+	strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
+
+	return 0;
+}
+
+/* ISP params video device IOCTLs */
+static const struct v4l2_ioctl_ops rkisp1_params_ioctl = {
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_qbuf = vb2_ioctl_qbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+	.vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out,
+	.vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
+	.vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
+	.vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
+	.vidioc_querycap = rkisp1_params_querycap
+};
+
+static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
+					 unsigned int *num_buffers,
+					 unsigned int *num_planes,
+					 unsigned int sizes[],
+					 struct device *alloc_devs[])
+{
+	struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
+
+	*num_buffers = clamp_t(u32, *num_buffers,
+			       RKISP1_ISP_PARAMS_REQ_BUFS_MIN,
+			       RKISP1_ISP_PARAMS_REQ_BUFS_MAX);
+
+	*num_planes = 1;
+
+	sizes[0] = sizeof(struct rkisp1_isp_params_cfg);
+
+	INIT_LIST_HEAD(&params_vdev->params);
+	params_vdev->first_params = true;
+
+	return 0;
+}
+
+static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct rkisp1_buffer *params_buf = to_rkisp1_buffer(vbuf);
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
+	struct rkisp1_isp_params_cfg *new_params;
+	unsigned long flags;
+
+	if (params_vdev->first_params) {
+		new_params = (struct rkisp1_isp_params_cfg *)
+			(vb2_plane_vaddr(vb, 0));
+		vb2_buffer_done(&params_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+		params_vdev->first_params = false;
+		params_vdev->cur_params = *new_params;
+		return;
+	}
+
+	params_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
+	spin_lock_irqsave(&params_vdev->config_lock, flags);
+	list_add_tail(&params_buf->queue, &params_vdev->params);
+	spin_unlock_irqrestore(&params_vdev->config_lock, flags);
+}
+
+static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
+{
+	struct rkisp1_isp_params_vdev *params_vdev = vq->drv_priv;
+	struct rkisp1_buffer *buf;
+	unsigned long flags;
+	int i;
+
+	/* stop params input firstly */
+	spin_lock_irqsave(&params_vdev->config_lock, flags);
+	params_vdev->streamon = false;
+	spin_unlock_irqrestore(&params_vdev->config_lock, flags);
+
+	for (i = 0; i < RKISP1_ISP_PARAMS_REQ_BUFS_MAX; i++) {
+		spin_lock_irqsave(&params_vdev->config_lock, flags);
+		if (!list_empty(&params_vdev->params)) {
+			buf = list_first_entry(&params_vdev->params,
+					       struct rkisp1_buffer, queue);
+			list_del(&buf->queue);
+			spin_unlock_irqrestore(&params_vdev->config_lock,
+					       flags);
+		} else {
+			spin_unlock_irqrestore(&params_vdev->config_lock,
+					       flags);
+			break;
+		}
+
+		if (buf)
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		buf = NULL;
+	}
+}
+
+static int
+rkisp1_params_vb2_start_streaming(struct vb2_queue *queue, unsigned int count)
+{
+	struct rkisp1_isp_params_vdev *params_vdev = queue->drv_priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&params_vdev->config_lock, flags);
+	params_vdev->streamon = true;
+	spin_unlock_irqrestore(&params_vdev->config_lock, flags);
+
+	return 0;
+}
+
+static struct vb2_ops rkisp1_params_vb2_ops = {
+	.queue_setup = rkisp1_params_vb2_queue_setup,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.buf_queue = rkisp1_params_vb2_buf_queue,
+	.start_streaming = rkisp1_params_vb2_start_streaming,
+	.stop_streaming = rkisp1_params_vb2_stop_streaming,
+
+};
+
+struct v4l2_file_operations rkisp1_params_fops = {
+	.mmap = vb2_fop_mmap,
+	.unlocked_ioctl = video_ioctl2,
+	.poll = vb2_fop_poll,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release
+};
+
+static int
+rkisp1_params_init_vb2_queue(struct vb2_queue *q,
+			     struct rkisp1_isp_params_vdev *params_vdev)
+{
+	struct rkisp1_vdev_node *node;
+
+	node = queue_to_node(q);
+
+	q->type = V4L2_BUF_TYPE_META_OUTPUT;
+	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->drv_priv = params_vdev;
+	q->ops = &rkisp1_params_vb2_ops;
+	q->mem_ops = &vb2_vmalloc_memops;
+	q->buf_struct_size = sizeof(struct rkisp1_buffer);
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &node->vlock;
+
+	return vb2_queue_init(q);
+}
+
+static void rkisp1_init_params_vdev(struct rkisp1_isp_params_vdev *params_vdev)
+{
+	params_vdev->vdev_fmt.fmt.meta.dataformat =
+		V4L2_META_FMT_RK_ISP1_PARAMS;
+	params_vdev->vdev_fmt.fmt.meta.buffersize =
+		sizeof(struct rkisp1_isp_params_cfg);
+}
+
+int rkisp1_register_params_vdev(struct rkisp1_isp_params_vdev *params_vdev,
+				struct v4l2_device *v4l2_dev,
+				struct rkisp1_device *dev)
+{
+	int ret;
+	struct rkisp1_vdev_node *node = &params_vdev->vnode;
+	struct video_device *vdev = &node->vdev;
+
+	params_vdev->dev = dev;
+	mutex_init(&node->vlock);
+	spin_lock_init(&params_vdev->config_lock);
+
+	strlcpy(vdev->name, "rkisp1-input-params", sizeof(vdev->name));
+
+	video_set_drvdata(vdev, params_vdev);
+	vdev->ioctl_ops = &rkisp1_params_ioctl;
+	vdev->fops = &rkisp1_params_fops;
+	vdev->release = video_device_release_empty;
+	/*
+	 * Provide a mutex to v4l2 core. It will be used
+	 * to protect all fops and v4l2 ioctls.
+	 */
+	vdev->lock = &node->vlock;
+	vdev->v4l2_dev = v4l2_dev;
+	vdev->queue = &node->buf_queue;
+	vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT;
+	vdev->vfl_dir = VFL_DIR_TX;
+	rkisp1_params_init_vb2_queue(vdev->queue, params_vdev);
+	rkisp1_init_params_vdev(params_vdev);
+	video_set_drvdata(vdev, params_vdev);
+
+	node->pad.flags = MEDIA_PAD_FL_SOURCE;
+	vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
+	if (ret < 0)
+		goto err_release_queue;
+	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		dev_err(&vdev->dev,
+			"could not register Video for Linux device\n");
+		goto err_cleanup_media_entity;
+	}
+	return 0;
+err_cleanup_media_entity:
+	media_entity_cleanup(&vdev->entity);
+err_release_queue:
+	vb2_queue_release(vdev->queue);
+	return ret;
+}
+
+void rkisp1_unregister_params_vdev(struct rkisp1_isp_params_vdev *params_vdev)
+{
+	struct rkisp1_vdev_node *node = &params_vdev->vnode;
+	struct video_device *vdev = &node->vdev;
+
+	video_unregister_device(vdev);
+	media_entity_cleanup(&vdev->entity);
+	vb2_queue_release(vdev->queue);
+}
diff --git a/drivers/media/platform/rockchip/isp1/isp_params.h b/drivers/media/platform/rockchip/isp1/isp_params.h
new file mode 100644
index 000000000000..0d6a2f2a151f
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/isp_params.h
@@ -0,0 +1,76 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_ISP_H
+#define _RKISP1_ISP_H
+
+#include <linux/rkisp1-config.h>
+#include "common.h"
+
+/*
+ * struct rkisp1_isp_subdev - ISP input parameters device
+ *
+ * @cur_params: Current ISP parameters
+ * @first_params: the first params should take effect immediately
+ */
+struct rkisp1_isp_params_vdev {
+	struct rkisp1_vdev_node vnode;
+	struct rkisp1_device *dev;
+
+	spinlock_t config_lock;
+	struct list_head params;
+	struct rkisp1_isp_params_cfg cur_params;
+	struct v4l2_format vdev_fmt;
+	bool streamon;
+	bool first_params;
+
+	enum v4l2_quantization quantization;
+	enum rkisp1_fmt_raw_pat_type raw_type;
+};
+
+/* config params before ISP streaming */
+void rkisp1_configure_isp(struct rkisp1_isp_params_vdev *params_vdev,
+			  struct ispsd_in_fmt *in_fmt,
+			  enum v4l2_quantization quantization);
+void rkisp1_disable_isp(struct rkisp1_isp_params_vdev *params_vdev);
+
+int rkisp1_register_params_vdev(struct rkisp1_isp_params_vdev *params_vdev,
+				struct v4l2_device *v4l2_dev,
+				struct rkisp1_device *dev);
+
+void rkisp1_unregister_params_vdev(struct rkisp1_isp_params_vdev *params_vdev);
+
+void rkisp1_params_isr(struct rkisp1_isp_params_vdev *params_vdev, u32 isp_mis);
+
+#endif /* _RKISP1_ISP_H */
diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.c b/drivers/media/platform/rockchip/isp1/isp_stats.c
new file mode 100644
index 000000000000..bb25c6384498
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/isp_stats.c
@@ -0,0 +1,521 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-vmalloc.h>	/* for ISP statistics */
+#include "dev.h"
+#include "regs.h"
+
+#define RKISP1_ISP_STATS_REQ_BUFS_MIN 2
+#define RKISP1_ISP_STATS_REQ_BUFS_MAX 8
+
+static int rkisp1_stats_enum_fmt_meta_cap(struct file *file, void *priv,
+					  struct v4l2_fmtdesc *f)
+{
+	struct video_device *video = video_devdata(file);
+	struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
+
+	if (f->index > 0 || f->type != video->queue->type)
+		return -EINVAL;
+
+	f->pixelformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
+	return 0;
+}
+
+static int rkisp1_stats_g_fmt_meta_cap(struct file *file, void *priv,
+				       struct v4l2_format *f)
+{
+	struct video_device *video = video_devdata(file);
+	struct rkisp1_isp_stats_vdev *stats_vdev = video_get_drvdata(video);
+	struct v4l2_meta_format *meta = &f->fmt.meta;
+
+	if (f->type != video->queue->type)
+		return -EINVAL;
+
+	memset(meta, 0, sizeof(*meta));
+	meta->dataformat = stats_vdev->vdev_fmt.fmt.meta.dataformat;
+	meta->buffersize = stats_vdev->vdev_fmt.fmt.meta.buffersize;
+
+	return 0;
+}
+
+static int rkisp1_stats_querycap(struct file *file,
+				 void *priv, struct v4l2_capability *cap)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	strcpy(cap->driver, DRIVER_NAME);
+	strlcpy(cap->card, vdev->name, sizeof(cap->card));
+	strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
+
+	return 0;
+}
+
+/* ISP video device IOCTLs */
+static const struct v4l2_ioctl_ops rkisp1_stats_ioctl = {
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_qbuf = vb2_ioctl_qbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+	.vidioc_enum_fmt_meta_cap = rkisp1_stats_enum_fmt_meta_cap,
+	.vidioc_g_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
+	.vidioc_s_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
+	.vidioc_try_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap,
+	.vidioc_querycap = rkisp1_stats_querycap
+};
+
+struct v4l2_file_operations rkisp1_stats_fops = {
+	.mmap = vb2_fop_mmap,
+	.unlocked_ioctl = video_ioctl2,
+	.poll = vb2_fop_poll,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release
+};
+
+static int rkisp1_stats_vb2_queue_setup(struct vb2_queue *vq,
+					unsigned int *num_buffers,
+					unsigned int *num_planes,
+					unsigned int sizes[],
+					struct device *alloc_devs[])
+{
+	struct rkisp1_isp_stats_vdev *stats_vdev = vq->drv_priv;
+
+	*num_planes = 1;
+
+	*num_buffers = clamp_t(u32, *num_buffers, RKISP1_ISP_STATS_REQ_BUFS_MIN,
+			       RKISP1_ISP_STATS_REQ_BUFS_MAX);
+
+	sizes[0] = sizeof(struct rkisp1_stat_buffer);
+
+	INIT_LIST_HEAD(&stats_vdev->stat);
+
+	return 0;
+}
+
+static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct rkisp1_buffer *stats_buf = to_rkisp1_buffer(vbuf);
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct rkisp1_isp_stats_vdev *stats_dev = vq->drv_priv;
+	unsigned long flags;
+
+	stats_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
+	spin_lock_irqsave(&stats_dev->irq_lock, flags);
+	list_add_tail(&stats_buf->queue, &stats_dev->stat);
+	spin_unlock_irqrestore(&stats_dev->irq_lock, flags);
+}
+
+static void rkisp1_stats_vb2_stop_streaming(struct vb2_queue *vq)
+{
+	struct rkisp1_isp_stats_vdev *stats_vdev = vq->drv_priv;
+	struct rkisp1_buffer *buf;
+	unsigned long flags;
+	int i;
+
+	/* stop stats received firstly */
+	spin_lock_irqsave(&stats_vdev->irq_lock, flags);
+	stats_vdev->streamon = false;
+	spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
+
+	drain_workqueue(stats_vdev->readout_wq);
+
+	for (i = 0; i < RKISP1_ISP_STATS_REQ_BUFS_MAX; i++) {
+		spin_lock_irqsave(&stats_vdev->irq_lock, flags);
+		if (!list_empty(&stats_vdev->stat)) {
+			buf = list_first_entry(&stats_vdev->stat,
+					       struct rkisp1_buffer, queue);
+			list_del(&buf->queue);
+			spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
+		} else {
+			spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
+			break;
+		}
+
+		if (buf)
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		buf = NULL;
+	}
+}
+
+static int
+rkisp1_stats_vb2_start_streaming(struct vb2_queue *queue,
+				 unsigned int count)
+{
+	struct rkisp1_isp_stats_vdev *stats_vdev = queue->drv_priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&stats_vdev->irq_lock, flags);
+	stats_vdev->streamon = true;
+	spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
+
+	return 0;
+}
+
+static struct vb2_ops rkisp1_stats_vb2_ops = {
+	.queue_setup = rkisp1_stats_vb2_queue_setup,
+	.buf_queue = rkisp1_stats_vb2_buf_queue,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.stop_streaming = rkisp1_stats_vb2_stop_streaming,
+	.start_streaming = rkisp1_stats_vb2_start_streaming,
+};
+
+static int rkisp1_stats_init_vb2_queue(struct vb2_queue *q,
+				       struct rkisp1_isp_stats_vdev *stats_vdev)
+{
+	struct rkisp1_vdev_node *node;
+
+	node = queue_to_node(q);
+
+	q->type = V4L2_BUF_TYPE_META_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->drv_priv = stats_vdev;
+	q->ops = &rkisp1_stats_vb2_ops;
+	q->mem_ops = &vb2_vmalloc_memops;
+	q->buf_struct_size = sizeof(struct rkisp1_buffer);
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &node->vlock;
+
+	return vb2_queue_init(q);
+}
+
+static void rkisp1_stats_get_awb_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
+				      struct rkisp1_stat_buffer *pbuf)
+{
+	/* Protect against concurrent access from ISR? */
+	u32 reg_val;
+
+	pbuf->meas_type |= CIFISP_STAT_AWB;
+	reg_val = readl(stats_vdev->dev->base_addr + CIF_ISP_AWB_WHITE_CNT);
+	pbuf->params.awb.awb_mean[0].cnt = CIF_ISP_AWB_GET_PIXEL_CNT(reg_val);
+	reg_val = readl(stats_vdev->dev->base_addr + CIF_ISP_AWB_MEAN);
+
+	pbuf->params.awb.awb_mean[0].mean_cr_or_r =
+		CIF_ISP_AWB_GET_MEAN_CR_R(reg_val);
+	pbuf->params.awb.awb_mean[0].mean_cb_or_b =
+		CIF_ISP_AWB_GET_MEAN_CB_B(reg_val);
+	pbuf->params.awb.awb_mean[0].mean_y_or_g =
+		CIF_ISP_AWB_GET_MEAN_Y_G(reg_val);
+}
+
+static void rkisp1_stats_get_aec_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
+				      struct rkisp1_stat_buffer *pbuf)
+{
+	unsigned int i;
+	void __iomem *addr = stats_vdev->dev->base_addr + CIF_ISP_EXP_MEAN_00;
+
+	pbuf->meas_type |= CIFISP_STAT_AUTOEXP;
+	for (i = 0; i < CIFISP_AE_MEAN_MAX; i++)
+		pbuf->params.ae.exp_mean[i] = (u8)readl(addr + i * 4);
+}
+
+static void rkisp1_stats_get_afc_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
+				      struct rkisp1_stat_buffer *pbuf)
+{
+	void __iomem *base_addr;
+	struct cifisp_af_stat *af;
+
+	pbuf->meas_type = CIFISP_STAT_AFM_FIN;
+
+	af = &pbuf->params.af;
+	base_addr = stats_vdev->dev->base_addr;
+	af->window[0].sum = readl(base_addr + CIF_ISP_AFM_SUM_A);
+	af->window[0].lum = readl(base_addr + CIF_ISP_AFM_LUM_A);
+	af->window[1].sum = readl(base_addr + CIF_ISP_AFM_SUM_B);
+	af->window[1].lum = readl(base_addr + CIF_ISP_AFM_LUM_B);
+	af->window[2].sum = readl(base_addr + CIF_ISP_AFM_SUM_C);
+	af->window[2].lum = readl(base_addr + CIF_ISP_AFM_LUM_C);
+}
+
+static void rkisp1_stats_get_hst_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
+				      struct rkisp1_stat_buffer *pbuf)
+{
+	int i;
+	void __iomem *addr = stats_vdev->dev->base_addr + CIF_ISP_HIST_BIN_0;
+
+	pbuf->meas_type |= CIFISP_STAT_HIST;
+	for (i = 0; i < CIFISP_HIST_BIN_N_MAX; i++)
+		pbuf->params.hist.hist_bins[i] = readl(addr + (i * 4));
+}
+
+static void rkisp1_stats_get_bls_meas(struct rkisp1_isp_stats_vdev *stats_vdev,
+				      struct rkisp1_stat_buffer *pbuf)
+{
+	struct rkisp1_device *dev = stats_vdev->dev;
+	const struct ispsd_in_fmt *in_fmt =
+			rkisp1_get_ispsd_in_fmt(&dev->isp_sdev);
+	void __iomem *base = stats_vdev->dev->base_addr;
+	struct cifisp_bls_meas_val *bls_val;
+
+	bls_val = &pbuf->params.ae.bls_val;
+	if (in_fmt->bayer_pat == RAW_BGGR) {
+		bls_val->meas_b = readl(base + CIF_ISP_BLS_A_MEASURED);
+		bls_val->meas_gb = readl(base + CIF_ISP_BLS_B_MEASURED);
+		bls_val->meas_gr = readl(base + CIF_ISP_BLS_C_MEASURED);
+		bls_val->meas_r = readl(base + CIF_ISP_BLS_D_MEASURED);
+	} else if (in_fmt->bayer_pat == RAW_GBRG) {
+		bls_val->meas_gb = readl(base + CIF_ISP_BLS_A_MEASURED);
+		bls_val->meas_b = readl(base + CIF_ISP_BLS_B_MEASURED);
+		bls_val->meas_r = readl(base + CIF_ISP_BLS_C_MEASURED);
+		bls_val->meas_gr = readl(base + CIF_ISP_BLS_D_MEASURED);
+	} else if (in_fmt->bayer_pat == RAW_GRBG) {
+		bls_val->meas_gr = readl(base + CIF_ISP_BLS_A_MEASURED);
+		bls_val->meas_r = readl(base + CIF_ISP_BLS_B_MEASURED);
+		bls_val->meas_b = readl(base + CIF_ISP_BLS_C_MEASURED);
+		bls_val->meas_gb = readl(base + CIF_ISP_BLS_D_MEASURED);
+	} else if (in_fmt->bayer_pat == RAW_RGGB) {
+		bls_val->meas_r = readl(base + CIF_ISP_BLS_A_MEASURED);
+		bls_val->meas_gr = readl(base + CIF_ISP_BLS_B_MEASURED);
+		bls_val->meas_gb = readl(base + CIF_ISP_BLS_C_MEASURED);
+		bls_val->meas_b = readl(base + CIF_ISP_BLS_D_MEASURED);
+	}
+}
+
+static void
+rkisp1_stats_send_measurement(struct rkisp1_isp_stats_vdev *stats_vdev,
+			      struct rkisp1_isp_readout_work *meas_work)
+{
+	unsigned long lock_flags = 0;
+	unsigned int cur_frame_id = -1;
+	struct rkisp1_stat_buffer *cur_stat_buf;
+	struct rkisp1_buffer *cur_buf = NULL;
+
+	spin_lock_irqsave(&stats_vdev->irq_lock, lock_flags);
+	cur_frame_id = atomic_read(&stats_vdev->dev->isp_sdev.frm_sync_seq) - 1;
+	if (cur_frame_id != meas_work->frame_id) {
+		v4l2_warn(stats_vdev->vnode.vdev.v4l2_dev,
+			  "Measurement late(%d, %d)\n",
+			  cur_frame_id, meas_work->frame_id);
+	}
+	/* get one empty buffer */
+	if (!list_empty(&stats_vdev->stat)) {
+		cur_buf = list_first_entry(&stats_vdev->stat,
+					   struct rkisp1_buffer, queue);
+		list_del(&cur_buf->queue);
+	}
+	spin_unlock_irqrestore(&stats_vdev->irq_lock, lock_flags);
+
+	if (!cur_buf)
+		return;
+
+	cur_stat_buf =
+		(struct rkisp1_stat_buffer *)(cur_buf->vaddr[0]);
+
+	if (meas_work->isp_ris & CIF_ISP_AWB_DONE) {
+		rkisp1_stats_get_awb_meas(stats_vdev, cur_stat_buf);
+		cur_stat_buf->meas_type |= CIFISP_STAT_AWB;
+	}
+
+	if (meas_work->isp_ris & CIF_ISP_AFM_FIN) {
+		rkisp1_stats_get_afc_meas(stats_vdev, cur_stat_buf);
+		cur_stat_buf->meas_type |= CIFISP_STAT_AFM_FIN;
+	}
+
+	if (meas_work->isp_ris & CIF_ISP_EXP_END) {
+		rkisp1_stats_get_aec_meas(stats_vdev, cur_stat_buf);
+		rkisp1_stats_get_bls_meas(stats_vdev, cur_stat_buf);
+		cur_stat_buf->meas_type |= CIFISP_STAT_AUTOEXP;
+	}
+
+	if (meas_work->isp_ris & CIF_ISP_HIST_MEASURE_RDY) {
+		rkisp1_stats_get_hst_meas(stats_vdev, cur_stat_buf);
+		cur_stat_buf->meas_type |= CIFISP_STAT_HIST;
+	}
+
+	vb2_set_plane_payload(&cur_buf->vb.vb2_buf, 0,
+			      sizeof(struct rkisp1_stat_buffer));
+	cur_buf->vb.sequence = cur_frame_id;
+	cur_buf->vb.vb2_buf.timestamp = ktime_get_ns();
+	vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+}
+
+static void rkisp1_stats_readout_work(struct work_struct *work)
+{
+	struct rkisp1_isp_readout_work *readout_work = container_of(work,
+						struct rkisp1_isp_readout_work,
+						work);
+	struct rkisp1_isp_stats_vdev *stats_vdev = readout_work->stats_vdev;
+
+	if (readout_work->readout == RKISP1_ISP_READOUT_MEAS)
+		rkisp1_stats_send_measurement(stats_vdev, readout_work);
+
+	kfree(readout_work);
+}
+
+int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris)
+{
+	unsigned int isp_mis_tmp = 0;
+	struct rkisp1_isp_readout_work *work;
+	unsigned int cur_frame_id =
+		atomic_read(&stats_vdev->dev->isp_sdev.frm_sync_seq) - 1;
+#ifdef LOG_ISR_EXE_TIME
+	ktime_t in_t = ktime_get();
+#endif
+
+	writel((CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN | CIF_ISP_EXP_END |
+		CIF_ISP_HIST_MEASURE_RDY),
+		stats_vdev->dev->base_addr + CIF_ISP_ICR);
+
+	isp_mis_tmp = readl(stats_vdev->dev->base_addr + CIF_ISP_MIS);
+	if (isp_mis_tmp &
+		(CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
+		 CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
+		v4l2_err(stats_vdev->vnode.vdev.v4l2_dev,
+			 "isp icr 3A info err: 0x%x\n",
+			 isp_mis_tmp);
+
+	if (isp_ris & (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN | CIF_ISP_EXP_END |
+		CIF_ISP_HIST_MEASURE_RDY)) {
+		work = (struct rkisp1_isp_readout_work *)
+			kzalloc(sizeof(struct rkisp1_isp_readout_work),
+				GFP_ATOMIC);
+		if (work) {
+			INIT_WORK(&work->work,
+				  rkisp1_stats_readout_work);
+			work->readout = RKISP1_ISP_READOUT_MEAS;
+			work->stats_vdev = stats_vdev;
+			work->frame_id = cur_frame_id;
+			work->isp_ris = isp_ris;
+			if (!queue_work(stats_vdev->readout_wq,
+					&work->work))
+				kfree(work);
+		} else {
+			v4l2_err(stats_vdev->vnode.vdev.v4l2_dev,
+				 "Could not allocate work\n");
+		}
+	}
+
+#ifdef LOG_ISR_EXE_TIME
+	if (isp_ris & (CIF_ISP_EXP_END | CIF_ISP_AWB_DONE |
+		       CIF_ISP_FRAME | CIF_ISP_HIST_MEASURE_RDY)) {
+		unsigned int diff_us =
+		    ktime_to_us(ktime_sub(ktime_get(), in_t));
+
+		if (diff_us > g_longest_isr_time)
+			g_longest_isr_time = diff_us;
+
+		v4l2_info(stats_vdev->vnode.vdev.v4l2_dev,
+			  "isp_isr time %d %d\n", diff_us, g_longest_isr_time);
+	}
+#endif
+
+	return 0;
+}
+
+static void rkisp1_init_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev)
+{
+	stats_vdev->vdev_fmt.fmt.meta.dataformat =
+		V4L2_META_FMT_RK_ISP1_STAT_3A;
+	stats_vdev->vdev_fmt.fmt.meta.buffersize =
+		sizeof(struct rkisp1_stat_buffer);
+}
+
+int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev,
+			       struct v4l2_device *v4l2_dev,
+			       struct rkisp1_device *dev)
+{
+	int ret;
+	struct rkisp1_vdev_node *node = &stats_vdev->vnode;
+	struct video_device *vdev = &node->vdev;
+
+	stats_vdev->dev = dev;
+	mutex_init(&node->vlock);
+	INIT_LIST_HEAD(&stats_vdev->stat);
+	spin_lock_init(&stats_vdev->irq_lock);
+
+	strlcpy(vdev->name, "rkisp1-statistics", sizeof(vdev->name));
+
+	video_set_drvdata(vdev, stats_vdev);
+	vdev->ioctl_ops = &rkisp1_stats_ioctl;
+	vdev->fops = &rkisp1_stats_fops;
+	vdev->release = video_device_release_empty;
+	vdev->lock = &node->vlock;
+	vdev->v4l2_dev = v4l2_dev;
+	vdev->queue = &node->buf_queue;
+	vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING;
+	vdev->vfl_dir =  VFL_DIR_RX;
+	rkisp1_stats_init_vb2_queue(vdev->queue, stats_vdev);
+	rkisp1_init_stats_vdev(stats_vdev);
+	video_set_drvdata(vdev, stats_vdev);
+
+	node->pad.flags = MEDIA_PAD_FL_SINK;
+	vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
+	if (ret < 0)
+		goto err_release_queue;
+
+	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		dev_err(&vdev->dev,
+			"could not register Video for Linux device\n");
+		goto err_cleanup_media_entity;
+	}
+
+	stats_vdev->readout_wq =
+	    alloc_workqueue("measurement_queue",
+			    WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+
+	if (!stats_vdev->readout_wq) {
+		ret = -ENOMEM;
+			goto err_unreg_vdev;
+	}
+
+	return 0;
+err_unreg_vdev:
+	video_unregister_device(vdev);
+err_cleanup_media_entity:
+	media_entity_cleanup(&vdev->entity);
+err_release_queue:
+	vb2_queue_release(vdev->queue);
+	return ret;
+}
+
+void rkisp1_unregister_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev)
+{
+	struct rkisp1_vdev_node *node = &stats_vdev->vnode;
+	struct video_device *vdev = &node->vdev;
+
+	destroy_workqueue(stats_vdev->readout_wq);
+	video_unregister_device(vdev);
+	media_entity_cleanup(&vdev->entity);
+	vb2_queue_release(vdev->queue);
+}
diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.h b/drivers/media/platform/rockchip/isp1/isp_stats.h
new file mode 100644
index 000000000000..71fd4e447fd9
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/isp_stats.h
@@ -0,0 +1,85 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_ISP_STATS_H
+#define _RKISP1_ISP_STATS_H
+
+#include <linux/rkisp1-config.h>
+#include "common.h"
+
+struct rkisp1_isp_stats_vdev;
+
+enum rkisp1_isp_readout_cmd {
+	RKISP1_ISP_READOUT_MEAS,
+	RKISP1_ISP_READOUT_META,
+};
+
+struct rkisp1_isp_readout_work {
+	struct work_struct work;
+	struct rkisp1_isp_stats_vdev *stats_vdev;
+
+	unsigned int frame_id;
+	unsigned int isp_ris;
+	enum rkisp1_isp_readout_cmd readout;
+	struct vb2_buffer *vb;
+};
+
+/*
+ * struct rkisp1_isp_stats_vdev - ISP Statistics device
+ *
+ * @irq_lock: buffer queue lock
+ * @stat: stats buffer list
+ * @readout_wq: workqueue for statistics information read
+ */
+struct rkisp1_isp_stats_vdev {
+	struct rkisp1_vdev_node vnode;
+	struct rkisp1_device *dev;
+
+	spinlock_t irq_lock;
+	struct list_head stat;
+	struct v4l2_format vdev_fmt;
+	bool streamon;
+
+	struct workqueue_struct *readout_wq;
+};
+
+int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris);
+
+int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev,
+			       struct v4l2_device *v4l2_dev,
+			       struct rkisp1_device *dev);
+
+void rkisp1_unregister_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev);
+
+#endif /* _RKISP1_ISP_STATS_H */
diff --git a/drivers/media/platform/rockchip/isp1/regs.c b/drivers/media/platform/rockchip/isp1/regs.c
new file mode 100644
index 000000000000..46b9898044d4
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/regs.c
@@ -0,0 +1,264 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <media/v4l2-common.h>
+#include "regs.h"
+
+void disable_dcrop(struct rkisp1_stream *stream, bool async)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+	void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
+	u32 dc_ctrl = readl(dc_ctrl_addr);
+	u32 mask = ~(stream->config->dual_crop.yuvmode_mask |
+			stream->config->dual_crop.rawmode_mask);
+	u32 val = dc_ctrl & mask;
+
+	if (async)
+		val |= CIF_DUAL_CROP_GEN_CFG_UPD;
+	else
+		val |= CIF_DUAL_CROP_CFG_UPD;
+	writel(val, dc_ctrl_addr);
+}
+
+void config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect, bool async)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+	void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
+	u32 dc_ctrl = readl(dc_ctrl_addr);
+
+	writel(rect->left, base + stream->config->dual_crop.h_offset);
+	writel(rect->top, base + stream->config->dual_crop.v_offset);
+	writel(rect->width, base + stream->config->dual_crop.h_size);
+	writel(rect->height, base + stream->config->dual_crop.v_size);
+	dc_ctrl |= stream->config->dual_crop.yuvmode_mask;
+	if (async)
+		dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
+	else
+		dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
+	writel(dc_ctrl, dc_ctrl_addr);
+}
+
+void dump_rsz_regs(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	pr_info("RSZ_CTRL 0x%08x/0x%08x\n"
+			"RSZ_SCALE_HY %d/%d\n"
+			"RSZ_SCALE_HCB %d/%d\n"
+			"RSZ_SCALE_HCR %d/%d\n"
+			"RSZ_SCALE_VY %d/%d\n"
+			"RSZ_SCALE_VC %d/%d\n"
+			"RSZ_PHASE_HY %d/%d\n"
+			"RSZ_PHASE_HC %d/%d\n"
+			"RSZ_PHASE_VY %d/%d\n"
+			"RSZ_PHASE_VC %d/%d\n",
+			readl(base + stream->config->rsz.ctrl),
+			readl(base + stream->config->rsz.ctrl_shd),
+			readl(base + stream->config->rsz.scale_hy),
+			readl(base + stream->config->rsz.scale_hy_shd),
+			readl(base + stream->config->rsz.scale_hcb),
+			readl(base + stream->config->rsz.scale_hcb_shd),
+			readl(base + stream->config->rsz.scale_hcr),
+			readl(base + stream->config->rsz.scale_hcr_shd),
+			readl(base + stream->config->rsz.scale_vy),
+			readl(base + stream->config->rsz.scale_vy_shd),
+			readl(base + stream->config->rsz.scale_vc),
+			readl(base + stream->config->rsz.scale_vc_shd),
+			readl(base + stream->config->rsz.phase_hy),
+			readl(base + stream->config->rsz.phase_hy_shd),
+			readl(base + stream->config->rsz.phase_hc),
+			readl(base + stream->config->rsz.phase_hc_shd),
+			readl(base + stream->config->rsz.phase_vy),
+			readl(base + stream->config->rsz.phase_vy_shd),
+			readl(base + stream->config->rsz.phase_vc),
+			readl(base + stream->config->rsz.phase_vc_shd));
+}
+
+static void update_rsz_shadow(struct rkisp1_stream *stream)
+{
+	void *addr = stream->ispdev->base_addr + stream->config->rsz.ctrl;
+	u32 ctrl_cfg = readl(addr);
+
+	writel(CIF_RSZ_CTRL_CFG_UPD | ctrl_cfg, addr);
+}
+
+static void set_scale(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
+		struct v4l2_rect *in_c, struct v4l2_rect *out_y,
+		struct v4l2_rect *out_c)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+	void __iomem *scale_hy_addr = base + stream->config->rsz.scale_hy;
+	void __iomem *scale_hcr_addr = base + stream->config->rsz.scale_hcr;
+	void __iomem *scale_hcb_addr = base + stream->config->rsz.scale_hcb;
+	void __iomem *scale_vy_addr = base + stream->config->rsz.scale_vy;
+	void __iomem *scale_vc_addr = base + stream->config->rsz.scale_vc;
+	void __iomem *rsz_ctrl_addr = base + stream->config->rsz.ctrl;
+	u32 scale_hy, scale_hc, scale_vy, scale_vc, rsz_ctrl = 0;
+
+	if (in_y->width < out_y->width) {
+		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE |
+				CIF_RSZ_CTRL_SCALE_HY_UP;
+		scale_hy = ((in_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
+				(out_y->width - 1);
+		writel(scale_hy, scale_hy_addr);
+	} else if (in_y->width > out_y->width) {
+		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE;
+		scale_hy = ((out_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
+				(in_y->width - 1) + 1;
+		writel(scale_hy, scale_hy_addr);
+	}
+	if (in_c->width < out_c->width) {
+		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE |
+				CIF_RSZ_CTRL_SCALE_HC_UP;
+		scale_hc = ((in_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
+				(out_c->width - 1);
+		writel(scale_hc, scale_hcb_addr);
+		writel(scale_hc, scale_hcr_addr);
+	} else if (in_c->width > out_c->width) {
+		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE;
+		scale_hc = ((out_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
+				(in_c->width - 1) + 1;
+		writel(scale_hc, scale_hcb_addr);
+		writel(scale_hc, scale_hcr_addr);
+	}
+
+	if (in_y->height < out_y->height) {
+		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE |
+				CIF_RSZ_CTRL_SCALE_VY_UP;
+		scale_vy = ((in_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
+				(out_y->height - 1);
+		writel(scale_vy, scale_vy_addr);
+	} else if (in_y->height > out_y->height) {
+		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE;
+		scale_vy = ((out_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
+				(in_y->height - 1) + 1;
+		writel(scale_vy, scale_vy_addr);
+	}
+
+	if (in_c->height < out_c->height) {
+		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE |
+				CIF_RSZ_CTRL_SCALE_VC_UP;
+		scale_vc = ((in_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
+				(out_c->height - 1);
+		writel(scale_vc, scale_vc_addr);
+	} else if (in_c->height > out_c->height) {
+		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE;
+		scale_vc = ((out_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
+				(in_c->height - 1) + 1;
+		writel(scale_vc, scale_vc_addr);
+	}
+
+	writel(rsz_ctrl, rsz_ctrl_addr);
+}
+
+void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
+	struct v4l2_rect *in_c, struct v4l2_rect *out_y,
+	struct v4l2_rect *out_c, bool async)
+{
+	int i = 0;
+
+	/* No phase offset */
+	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_hy);
+	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_hc);
+	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_vy);
+	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_vc);
+
+	/* Linear interpolation */
+	for (i = 0; i < 64; i++) {
+		writel(i, stream->ispdev->base_addr + stream->config->rsz.scale_lut_addr);
+		writel(i, stream->ispdev->base_addr + stream->config->rsz.scale_lut);
+	}
+
+	set_scale(stream, in_y, in_c, out_y, out_c);
+
+	if (!async)
+		update_rsz_shadow(stream);
+}
+
+void disable_rsz(struct rkisp1_stream *stream, bool async)
+{
+	writel(0, stream->ispdev->base_addr + stream->config->rsz.ctrl);
+
+	if (!async)
+		update_rsz_shadow(stream);
+}
+
+void config_mi_ctrl(struct rkisp1_stream *stream)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+	void __iomem *addr = base + CIF_MI_CTRL;
+	u32 reg;
+
+	reg = readl(addr) & ~GENMASK(17, 16);
+	writel(reg | CIF_MI_CTRL_BURST_LEN_LUM_64, addr);
+	reg = readl(addr) & ~GENMASK(19, 18);
+	writel(reg | CIF_MI_CTRL_BURST_LEN_CHROM_64, addr);
+	reg = readl(addr);
+	writel(reg | CIF_MI_CTRL_INIT_BASE_EN, addr);
+	reg = readl(addr);
+	writel(reg | CIF_MI_CTRL_INIT_OFFSET_EN, addr);
+}
+
+void mp_clr_frame_end_int(void __iomem *base)
+{
+	writel(CIF_MI_MP_FRAME, base + CIF_MI_ICR);
+}
+
+void sp_clr_frame_end_int(void __iomem *base)
+{
+	writel(CIF_MI_SP_FRAME, base + CIF_MI_ICR);
+}
+
+bool mp_is_frame_end_int_masked(void __iomem *base)
+{
+	return (mi_get_masked_int_status(base) & CIF_MI_MP_FRAME);
+}
+
+bool sp_is_frame_end_int_masked(void __iomem *base)
+{
+	return (mi_get_masked_int_status(base) & CIF_MI_SP_FRAME);
+}
+
+bool mp_is_stream_stopped(void __iomem *base)
+{
+	int en;
+
+	en = CIF_MI_CTRL_SHD_MP_IN_ENABLED | CIF_MI_CTRL_SHD_RAW_OUT_ENABLED;
+	return !(readl(base + CIF_MI_CTRL_SHD) & en);
+}
+
+bool sp_is_stream_stopped(void __iomem *base)
+{
+	return !(readl(base + CIF_MI_CTRL_SHD) & CIF_MI_CTRL_SHD_SP_IN_ENABLED);
+}
diff --git a/drivers/media/platform/rockchip/isp1/regs.h b/drivers/media/platform/rockchip/isp1/regs.h
new file mode 100644
index 000000000000..e8709b639bc2
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/regs.h
@@ -0,0 +1,1582 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_REGS_H
+#define _RKISP1_REGS_H
+#include "dev.h"
+
+/* ISP_CTRL */
+#define CIF_ISP_CTRL_ISP_ENABLE			BIT(0)
+#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT		(0 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_ITU656		(1 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_ITU601		(2 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601	(3 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_DATA_MODE		(4 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656	(5 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656	(6 << 1)
+#define CIF_ISP_CTRL_ISP_INFORM_ENABLE		BIT(4)
+#define CIF_ISP_CTRL_ISP_GAMMA_IN_ENA		BIT(6)
+#define CIF_ISP_CTRL_ISP_AWB_ENA		BIT(7)
+#define CIF_ISP_CTRL_ISP_CFG_UPD_PERMANENT	BIT(8)
+#define CIF_ISP_CTRL_ISP_CFG_UPD		BIT(9)
+#define CIF_ISP_CTRL_ISP_GEN_CFG_UPD		BIT(10)
+#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA		BIT(11)
+#define CIF_ISP_CTRL_ISP_FLASH_MODE_ENA		BIT(12)
+#define CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA		BIT(13)
+#define CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA		BIT(14)
+
+/* ISP_ACQ_PROP */
+#define CIF_ISP_ACQ_PROP_POS_EDGE		BIT(0)
+#define CIF_ISP_ACQ_PROP_HSYNC_LOW		BIT(1)
+#define CIF_ISP_ACQ_PROP_VSYNC_LOW		BIT(2)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB		(0 << 3)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG		(1 << 3)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG		(2 << 3)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR		(3 << 3)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT(pat)		((pat) << 3)
+#define CIF_ISP_ACQ_PROP_YCBYCR			(0 << 7)
+#define CIF_ISP_ACQ_PROP_YCRYCB			(1 << 7)
+#define CIF_ISP_ACQ_PROP_CBYCRY			(2 << 7)
+#define CIF_ISP_ACQ_PROP_CRYCBY			(3 << 7)
+#define CIF_ISP_ACQ_PROP_FIELD_SEL_ALL		(0 << 9)
+#define CIF_ISP_ACQ_PROP_FIELD_SEL_EVEN		(1 << 9)
+#define CIF_ISP_ACQ_PROP_FIELD_SEL_ODD		(2 << 9)
+#define CIF_ISP_ACQ_PROP_IN_SEL_12B		(0 << 12)
+#define CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO	(1 << 12)
+#define CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB		(2 << 12)
+#define CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO		(3 << 12)
+#define CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB		(4 << 12)
+
+/* VI_DPCL */
+#define CIF_VI_DPCL_DMA_JPEG			(0 << 0)
+#define CIF_VI_DPCL_MP_MUX_MRSZ_MI		(1 << 0)
+#define CIF_VI_DPCL_MP_MUX_MRSZ_JPEG		(2 << 0)
+#define CIF_VI_DPCL_CHAN_MODE_MP		(1 << 2)
+#define CIF_VI_DPCL_CHAN_MODE_SP		(2 << 2)
+#define CIF_VI_DPCL_CHAN_MODE_MPSP		(3 << 2)
+#define CIF_VI_DPCL_DMA_SW_SPMUX		(0 << 4)
+#define CIF_VI_DPCL_DMA_SW_SI			(1 << 4)
+#define CIF_VI_DPCL_DMA_SW_IE			(2 << 4)
+#define CIF_VI_DPCL_DMA_SW_JPEG			(3 << 4)
+#define CIF_VI_DPCL_DMA_SW_ISP			(4 << 4)
+#define CIF_VI_DPCL_IF_SEL_PARALLEL		(0 << 8)
+#define CIF_VI_DPCL_IF_SEL_SMIA			(1 << 8)
+#define CIF_VI_DPCL_IF_SEL_MIPI			(2 << 8)
+#define CIF_VI_DPCL_DMA_IE_MUX_DMA		BIT(10)
+#define CIF_VI_DPCL_DMA_SP_MUX_DMA		BIT(11)
+
+/* ISP_IMSC - ISP_MIS - ISP_RIS - ISP_ICR - ISP_ISR */
+#define CIF_ISP_OFF				BIT(0)
+#define CIF_ISP_FRAME				BIT(1)
+#define CIF_ISP_DATA_LOSS			BIT(2)
+#define CIF_ISP_PIC_SIZE_ERROR			BIT(3)
+#define CIF_ISP_AWB_DONE			BIT(4)
+#define CIF_ISP_FRAME_IN			BIT(5)
+#define CIF_ISP_V_START				BIT(6)
+#define CIF_ISP_H_START				BIT(7)
+#define CIF_ISP_FLASH_ON			BIT(8)
+#define CIF_ISP_FLASH_OFF			BIT(9)
+#define CIF_ISP_SHUTTER_ON			BIT(10)
+#define CIF_ISP_SHUTTER_OFF			BIT(11)
+#define CIF_ISP_AFM_SUM_OF			BIT(12)
+#define CIF_ISP_AFM_LUM_OF			BIT(13)
+#define CIF_ISP_AFM_FIN				BIT(14)
+#define CIF_ISP_HIST_MEASURE_RDY		BIT(15)
+#define CIF_ISP_FLASH_CAP			BIT(17)
+#define CIF_ISP_EXP_END				BIT(18)
+#define CIF_ISP_VSM_END				BIT(19)
+
+/* ISP_ERR */
+#define CIF_ISP_ERR_INFORM_SIZE			BIT(0)
+#define CIF_ISP_ERR_IS_SIZE			BIT(1)
+#define CIF_ISP_ERR_OUTFORM_SIZE		BIT(2)
+
+/* MI_CTRL */
+#define CIF_MI_CTRL_MP_ENABLE			(1 << 0)
+#define CIF_MI_CTRL_SP_ENABLE			(2 << 0)
+#define CIF_MI_CTRL_JPEG_ENABLE			(4 << 0)
+#define CIF_MI_CTRL_RAW_ENABLE			(8 << 0)
+#define CIF_MI_CTRL_HFLIP			BIT(4)
+#define CIF_MI_CTRL_VFLIP			BIT(5)
+#define CIF_MI_CTRL_ROT				BIT(6)
+#define CIF_MI_BYTE_SWAP			BIT(7)
+#define CIF_MI_SP_Y_FULL_YUV2RGB		BIT(8)
+#define CIF_MI_SP_CBCR_FULL_YUV2RGB		BIT(9)
+#define CIF_MI_SP_422NONCOSITEED		BIT(10)
+#define CIF_MI_MP_PINGPONG_ENABEL		BIT(11)
+#define CIF_MI_SP_PINGPONG_ENABEL		BIT(12)
+#define CIF_MI_MP_AUTOUPDATE_ENABLE		BIT(13)
+#define CIF_MI_SP_AUTOUPDATE_ENABLE		BIT(14)
+#define CIF_MI_LAST_PIXEL_SIG_ENABLE		BIT(15)
+#define CIF_MI_CTRL_BURST_LEN_LUM_16		(0 << 16)
+#define CIF_MI_CTRL_BURST_LEN_LUM_32		(1 << 16)
+#define CIF_MI_CTRL_BURST_LEN_LUM_64		(2 << 16)
+#define CIF_MI_CTRL_BURST_LEN_CHROM_16		(0 << 18)
+#define CIF_MI_CTRL_BURST_LEN_CHROM_32		(1 << 18)
+#define CIF_MI_CTRL_BURST_LEN_CHROM_64		(2 << 18)
+#define CIF_MI_CTRL_INIT_BASE_EN		BIT(20)
+#define CIF_MI_CTRL_INIT_OFFSET_EN		BIT(21)
+#define MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8	(0 << 22)
+#define MI_CTRL_MP_WRITE_YUV_SPLA		(1 << 22)
+#define MI_CTRL_MP_WRITE_YUVINT			(2 << 22)
+#define MI_CTRL_MP_WRITE_RAW12			(2 << 22)
+#define MI_CTRL_SP_WRITE_PLA			(0 << 24)
+#define MI_CTRL_SP_WRITE_SPLA			(1 << 24)
+#define MI_CTRL_SP_WRITE_INT			(2 << 24)
+#define MI_CTRL_SP_INPUT_YUV400			(0 << 26)
+#define MI_CTRL_SP_INPUT_YUV420			(1 << 26)
+#define MI_CTRL_SP_INPUT_YUV422			(2 << 26)
+#define MI_CTRL_SP_INPUT_YUV444			(3 << 26)
+#define MI_CTRL_SP_OUTPUT_YUV400		(0 << 28)
+#define MI_CTRL_SP_OUTPUT_YUV420		(1 << 28)
+#define MI_CTRL_SP_OUTPUT_YUV422		(2 << 28)
+#define MI_CTRL_SP_OUTPUT_YUV444		(3 << 28)
+#define MI_CTRL_SP_OUTPUT_RGB565		(4 << 28)
+#define MI_CTRL_SP_OUTPUT_RGB666		(5 << 28)
+#define MI_CTRL_SP_OUTPUT_RGB888		(6 << 28)
+
+#define MI_CTRL_MP_FMT_MASK			GENMASK(23, 22)
+#define MI_CTRL_SP_FMT_MASK			GENMASK(30, 24)
+
+/* MI_INIT */
+#define CIF_MI_INIT_SKIP			BIT(2)
+#define CIF_MI_INIT_SOFT_UPD			BIT(4)
+
+/* MI_CTRL_SHD */
+#define CIF_MI_CTRL_SHD_MP_IN_ENABLED		BIT(0)
+#define CIF_MI_CTRL_SHD_SP_IN_ENABLED		BIT(1)
+#define CIF_MI_CTRL_SHD_JPEG_IN_ENABLED		BIT(2)
+#define CIF_MI_CTRL_SHD_RAW_IN_ENABLED		BIT(3)
+#define CIF_MI_CTRL_SHD_MP_OUT_ENABLED		BIT(16)
+#define CIF_MI_CTRL_SHD_SP_OUT_ENABLED		BIT(17)
+#define CIF_MI_CTRL_SHD_JPEG_OUT_ENABLED	BIT(18)
+#define CIF_MI_CTRL_SHD_RAW_OUT_ENABLED		BIT(19)
+
+/* RSZ_CTRL */
+#define CIF_RSZ_CTRL_SCALE_HY_ENABLE		BIT(0)
+#define CIF_RSZ_CTRL_SCALE_HC_ENABLE		BIT(1)
+#define CIF_RSZ_CTRL_SCALE_VY_ENABLE		BIT(2)
+#define CIF_RSZ_CTRL_SCALE_VC_ENABLE		BIT(3)
+#define CIF_RSZ_CTRL_SCALE_HY_UP		BIT(4)
+#define CIF_RSZ_CTRL_SCALE_HC_UP		BIT(5)
+#define CIF_RSZ_CTRL_SCALE_VY_UP		BIT(6)
+#define CIF_RSZ_CTRL_SCALE_VC_UP		BIT(7)
+#define CIF_RSZ_CTRL_CFG_UPD			BIT(8)
+#define CIF_RSZ_CTRL_CFG_UPD_AUTO		BIT(9)
+#define CIF_RSZ_SCALER_FACTOR			BIT(16)
+
+/* MI_IMSC - MI_MIS - MI_RIS - MI_ICR - MI_ISR */
+#define CIF_MI_MP_FRAME				BIT(0)
+#define CIF_MI_SP_FRAME				BIT(1)
+#define CIF_MI_MBLK_LINE			BIT(2)
+#define CIF_MI_FILL_MP_Y			BIT(3)
+#define CIF_MI_WRAP_MP_Y			BIT(4)
+#define CIF_MI_WRAP_MP_CB			BIT(5)
+#define CIF_MI_WRAP_MP_CR			BIT(6)
+#define CIF_MI_WRAP_SP_Y			BIT(7)
+#define CIF_MI_WRAP_SP_CB			BIT(8)
+#define CIF_MI_WRAP_SP_CR			BIT(9)
+#define CIF_MI_DMA_READY			BIT(11)
+
+/* MI_STATUS */
+#define CIF_MI_STATUS_MP_Y_FIFO_FULL		BIT(0)
+#define CIF_MI_STATUS_SP_Y_FIFO_FULL		BIT(4)
+
+/* MI_DMA_CTRL */
+#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_16	(0 << 0)
+#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_32	(1 << 0)
+#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_64	(2 << 0)
+#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_16	(0 << 2)
+#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_32	(1 << 2)
+#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64	(2 << 2)
+#define CIF_MI_DMA_CTRL_READ_FMT_PLANAR		(0 << 4)
+#define CIF_MI_DMA_CTRL_READ_FMT_SPLANAR	(1 << 4)
+#define CIF_MI_DMA_CTRL_FMT_YUV400		(0 << 6)
+#define CIF_MI_DMA_CTRL_FMT_YUV420		(1 << 6)
+#define CIF_MI_DMA_CTRL_READ_FMT_PACKED		(2 << 4)
+#define CIF_MI_DMA_CTRL_FMT_YUV422		(2 << 6)
+#define CIF_MI_DMA_CTRL_FMT_YUV444		(3 << 6)
+#define CIF_MI_DMA_CTRL_BYTE_SWAP		BIT(8)
+#define CIF_MI_DMA_CTRL_CONTINUOUS_ENA		BIT(9)
+#define CIF_MI_DMA_CTRL_RGB_BAYER_NO		(0 << 12)
+#define CIF_MI_DMA_CTRL_RGB_BAYER_8BIT		(1 << 12)
+#define CIF_MI_DMA_CTRL_RGB_BAYER_16BIT		(2 << 12)
+/* MI_DMA_START */
+#define CIF_MI_DMA_START_ENABLE			BIT(0)
+/* MI_XTD_FORMAT_CTRL  */
+#define CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP	BIT(0)
+#define CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP	BIT(1)
+#define CIF_MI_XTD_FMT_CTRL_DMA_CB_CR_SWAP	BIT(2)
+
+/* CCL */
+#define CIF_CCL_CIF_CLK_DIS			BIT(2)
+/* ICCL */
+#define CIF_ICCL_ISP_CLK			BIT(0)
+#define CIF_ICCL_CP_CLK				BIT(1)
+#define CIF_ICCL_RES_2				BIT(2)
+#define CIF_ICCL_MRSZ_CLK			BIT(3)
+#define CIF_ICCL_SRSZ_CLK			BIT(4)
+#define CIF_ICCL_JPEG_CLK			BIT(5)
+#define CIF_ICCL_MI_CLK				BIT(6)
+#define CIF_ICCL_RES_7				BIT(7)
+#define CIF_ICCL_IE_CLK				BIT(8)
+#define CIF_ICCL_SIMP_CLK			BIT(9)
+#define CIF_ICCL_SMIA_CLK			BIT(10)
+#define CIF_ICCL_MIPI_CLK			BIT(11)
+#define CIF_ICCL_DCROP_CLK			BIT(12)
+/* IRCL */
+#define CIF_IRCL_ISP_SW_RST			BIT(0)
+#define CIF_IRCL_CP_SW_RST			BIT(1)
+#define CIF_IRCL_YCS_SW_RST			BIT(2)
+#define CIF_IRCL_MRSZ_SW_RST			BIT(3)
+#define CIF_IRCL_SRSZ_SW_RST			BIT(4)
+#define CIF_IRCL_JPEG_SW_RST			BIT(5)
+#define CIF_IRCL_MI_SW_RST			BIT(6)
+#define CIF_IRCL_CIF_SW_RST			BIT(7)
+#define CIF_IRCL_IE_SW_RST			BIT(8)
+#define CIF_IRCL_SI_SW_RST			BIT(9)
+#define CIF_IRCL_MIPI_SW_RST			BIT(11)
+
+/* C_PROC_CTR */
+#define CIF_C_PROC_CTR_ENABLE			BIT(0)
+#define CIF_C_PROC_YOUT_FULL			BIT(1)
+#define CIF_C_PROC_YIN_FULL			BIT(2)
+#define CIF_C_PROC_COUT_FULL			BIT(3)
+#define CIF_C_PROC_CTRL_RESERVED		0xFFFFFFFE
+#define CIF_C_PROC_CONTRAST_RESERVED		0xFFFFFF00
+#define CIF_C_PROC_BRIGHTNESS_RESERVED		0xFFFFFF00
+#define CIF_C_PROC_HUE_RESERVED			0xFFFFFF00
+#define CIF_C_PROC_SATURATION_RESERVED		0xFFFFFF00
+#define CIF_C_PROC_MACC_RESERVED		0xE000E000
+#define CIF_C_PROC_TONE_RESERVED		0xF000
+/* DUAL_CROP_CTRL */
+#define CIF_DUAL_CROP_MP_MODE_BYPASS		(0 << 0)
+#define CIF_DUAL_CROP_MP_MODE_YUV		(1 << 0)
+#define CIF_DUAL_CROP_MP_MODE_RAW		(2 << 0)
+#define CIF_DUAL_CROP_SP_MODE_BYPASS		(0 << 2)
+#define CIF_DUAL_CROP_SP_MODE_YUV		(1 << 2)
+#define CIF_DUAL_CROP_SP_MODE_RAW		(2 << 2)
+#define CIF_DUAL_CROP_CFG_UPD_PERMANENT		BIT(4)
+#define CIF_DUAL_CROP_CFG_UPD			BIT(5)
+#define CIF_DUAL_CROP_GEN_CFG_UPD		BIT(6)
+
+/* IMG_EFF_CTRL */
+#define CIF_IMG_EFF_CTRL_ENABLE			BIT(0)
+#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE	(0 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE		(1 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_SEPIA		(2 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL		(3 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_EMBOSS		(4 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_SKETCH		(5 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_SHARPEN		(6 << 1)
+#define CIF_IMG_EFF_CTRL_CFG_UPD		BIT(4)
+#define CIF_IMG_EFF_CTRL_YCBCR_FULL		BIT(5)
+
+#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE_SHIFT	0
+#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE_SHIFT	1
+#define CIF_IMG_EFF_CTRL_MODE_SEPIA_SHIFT	2
+#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL_SHIFT	3
+#define CIF_IMG_EFF_CTRL_MODE_EMBOSS_SHIFT	4
+#define CIF_IMG_EFF_CTRL_MODE_SKETCH_SHIFT	5
+#define CIF_IMG_EFF_CTRL_MODE_SHARPEN_SHIFT	6
+#define CIF_IMG_EFF_CTRL_MODE_MASK		0xE
+
+/* IMG_EFF_COLOR_SEL */
+#define CIF_IMG_EFF_COLOR_RGB			0
+#define CIF_IMG_EFF_COLOR_B			(1 << 0)
+#define CIF_IMG_EFF_COLOR_G			(2 << 0)
+#define CIF_IMG_EFF_COLOR_GB			(3 << 0)
+#define CIF_IMG_EFF_COLOR_R			(4 << 0)
+#define CIF_IMG_EFF_COLOR_RB			(5 << 0)
+#define CIF_IMG_EFF_COLOR_RG			(6 << 0)
+#define CIF_IMG_EFF_COLOR_RGB2			(7 << 0)
+
+/* MIPI_CTRL */
+#define CIF_MIPI_CTRL_OUTPUT_ENA		BIT(0)
+#define CIF_MIPI_CTRL_SHUTDOWNLANES(a)		(((a) & 0xF) << 8)
+#define CIF_MIPI_CTRL_NUM_LANES(a)		(((a) & 0x3) << 12)
+#define CIF_MIPI_CTRL_ERR_SOT_HS_SKIP		BIT(16)
+#define CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP	BIT(17)
+#define CIF_MIPI_CTRL_CLOCKLANE_ENA		BIT(18)
+
+/* MIPI_DATA_SEL */
+#define CIF_MIPI_DATA_SEL_VC(a)			(((a) & 0x3) << 6)
+#define CIF_MIPI_DATA_SEL_DT(a)			(((a) & 0x3F) << 0)
+/* MIPI DATA_TYPE */
+#define CIF_CSI2_DT_YUV420_8b			0x18
+#define CIF_CSI2_DT_YUV420_10b			0x19
+#define CIF_CSI2_DT_YUV422_8b			0x1E
+#define CIF_CSI2_DT_YUV422_10b			0x1F
+#define CIF_CSI2_DT_RGB565			0x22
+#define CIF_CSI2_DT_RGB666			0x23
+#define CIF_CSI2_DT_RGB888			0x24
+#define CIF_CSI2_DT_RAW8			0x2A
+#define CIF_CSI2_DT_RAW10			0x2B
+#define CIF_CSI2_DT_RAW12			0x2C
+
+/* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */
+#define CIF_MIPI_SYNC_FIFO_OVFLW(a)		(((a) & 0xF) << 0)
+#define CIF_MIPI_ERR_SOT(a)			(((a) & 0xF) << 4)
+#define CIF_MIPI_ERR_SOT_SYNC(a)		(((a) & 0xF) << 8)
+#define CIF_MIPI_ERR_EOT_SYNC(a)		(((a) & 0xF) << 12)
+#define CIF_MIPI_ERR_CTRL(a)			(((a) & 0xF) << 16)
+#define CIF_MIPI_ERR_PROTOCOL			BIT(20)
+#define CIF_MIPI_ERR_ECC1			BIT(21)
+#define CIF_MIPI_ERR_ECC2			BIT(22)
+#define CIF_MIPI_ERR_CS				BIT(23)
+#define CIF_MIPI_FRAME_END			BIT(24)
+#define CIF_MIPI_ADD_DATA_OVFLW			BIT(25)
+#define CIF_MIPI_ADD_DATA_WATER_MARK		BIT(26)
+
+#define CIF_MIPI_ERR_CSI  (CIF_MIPI_ERR_PROTOCOL | \
+	CIF_MIPI_ERR_ECC1 | \
+	CIF_MIPI_ERR_ECC2 | \
+	CIF_MIPI_ERR_CS)
+
+#define CIF_MIPI_ERR_DPHY  (CIF_MIPI_ERR_SOT(3) | \
+	CIF_MIPI_ERR_SOT_SYNC(3) | \
+	CIF_MIPI_ERR_EOT_SYNC(3) | \
+	CIF_MIPI_ERR_CTRL(3))
+
+/* SUPER_IMPOSE */
+#define CIF_SUPER_IMP_CTRL_NORMAL_MODE		BIT(0)
+#define CIF_SUPER_IMP_CTRL_REF_IMG_MEM		BIT(1)
+#define CIF_SUPER_IMP_CTRL_TRANSP_DIS		BIT(2)
+
+/* ISP HISTOGRAM CALCULATION : ISP_HIST_PROP */
+#define CIF_ISP_HIST_PROP_MODE_DIS		(0 << 0)
+#define CIF_ISP_HIST_PROP_MODE_RGB		(1 << 0)
+#define CIF_ISP_HIST_PROP_MODE_RED		(2 << 0)
+#define CIF_ISP_HIST_PROP_MODE_GREEN		(3 << 0)
+#define CIF_ISP_HIST_PROP_MODE_BLUE		(4 << 0)
+#define CIF_ISP_HIST_PROP_MODE_LUM		(5 << 0)
+#define CIF_ISP_HIST_PROP_MODE_MASK		0x7
+#define CIF_ISP_HIST_PREDIV_SET(x)		(((x) & 0x7F) << 3)
+#define CIF_ISP_HIST_WEIGHT_SET(v0, v1, v2, v3)	\
+				     (((v0) & 0x1F) | (((v1) & 0x1F) << 8)  |\
+				     (((v2) & 0x1F) << 16) | \
+				     (((v3) & 0x1F) << 24))
+
+#define CIF_ISP_HIST_WINDOW_OFFSET_RESERVED	0xFFFFF000
+#define CIF_ISP_HIST_WINDOW_SIZE_RESERVED	0xFFFFF800
+#define CIF_ISP_HIST_WEIGHT_RESERVED		0xE0E0E0E0
+#define CIF_ISP_MAX_HIST_PREDIVIDER		0x0000007F
+#define CIF_ISP_HIST_ROW_NUM			5
+#define CIF_ISP_HIST_COLUMN_NUM			5
+
+/* AUTO FOCUS MEASUREMENT:  ISP_AFM_CTRL */
+#define ISP_AFM_CTRL_ENABLE			BIT(0)
+
+/* SHUTTER CONTROL */
+#define CIF_ISP_SH_CTRL_SH_ENA			BIT(0)
+#define CIF_ISP_SH_CTRL_REP_EN			BIT(1)
+#define CIF_ISP_SH_CTRL_SRC_SH_TRIG		BIT(2)
+#define CIF_ISP_SH_CTRL_EDGE_POS		BIT(3)
+#define CIF_ISP_SH_CTRL_POL_LOW			BIT(4)
+
+/* FLASH MODULE */
+/* ISP_FLASH_CMD */
+#define CIF_FLASH_CMD_PRELIGHT_ON		BIT(0)
+#define CIF_FLASH_CMD_FLASH_ON			BIT(1)
+#define CIF_FLASH_CMD_PRE_FLASH_ON		BIT(2)
+/* ISP_FLASH_CONFIG */
+#define CIF_FLASH_CONFIG_PRELIGHT_END		BIT(0)
+#define CIF_FLASH_CONFIG_VSYNC_POS		BIT(1)
+#define CIF_FLASH_CONFIG_PRELIGHT_LOW		BIT(2)
+#define CIF_FLASH_CONFIG_SRC_FL_TRIG		BIT(3)
+#define CIF_FLASH_CONFIG_DELAY(a)		(((a) & 0xF) << 4)
+
+/* Demosaic:  ISP_DEMOSAIC */
+#define CIF_ISP_DEMOSAIC_BYPASS			BIT(10)
+#define CIF_ISP_DEMOSAIC_TH(x)			((x) & 0xFF)
+
+/* AWB */
+/* ISP_AWB_PROP */
+#define CIF_ISP_AWB_YMAX_CMP_EN			BIT(2)
+#define CIFISP_AWB_YMAX_READ(x)			(((x) >> 2) & 1)
+#define CIF_ISP_AWB_MODE_RGB_EN			((1 << 31) | (0x2 << 0))
+#define CIF_ISP_AWB_MODE_YCBCR_EN		((0 << 31) | (0x2 << 0))
+#define CIF_ISP_AWB_MODE_YCBCR_EN		((0 << 31) | (0x2 << 0))
+#define CIF_ISP_AWB_MODE_MASK_NONE		0xFFFFFFFC
+#define CIF_ISP_AWB_MODE_READ(x)		((x) & 3)
+/* ISP_AWB_GAIN_RB, ISP_AWB_GAIN_G  */
+#define CIF_ISP_AWB_GAIN_R_SET(x)		(((x) & 0x3FF) << 16)
+#define CIF_ISP_AWB_GAIN_R_READ(x)		(((x) >> 16) & 0x3FF)
+#define CIF_ISP_AWB_GAIN_B_SET(x)		((x) & 0x3FFF)
+#define CIF_ISP_AWB_GAIN_B_READ(x)		((x) & 0x3FFF)
+/* ISP_AWB_REF */
+#define CIF_ISP_AWB_REF_CR_SET(x)		(((x) & 0xFF) << 8)
+#define CIF_ISP_AWB_REF_CR_READ(x)		(((x) >> 8) & 0xFF)
+#define CIF_ISP_AWB_REF_CB_READ(x)		((x) & 0xFF)
+/* ISP_AWB_THRESH */
+#define CIF_ISP_AWB_MAX_CS_SET(x)		(((x) & 0xFF) << 8)
+#define CIF_ISP_AWB_MAX_CS_READ(x)		(((x) >> 8) & 0xFF)
+#define CIF_ISP_AWB_MIN_C_READ(x)		((x) & 0xFF)
+#define CIF_ISP_AWB_MIN_Y_SET(x)		(((x) & 0xFF) << 16)
+#define CIF_ISP_AWB_MIN_Y_READ(x)		(((x) >> 16) & 0xFF)
+#define CIF_ISP_AWB_MAX_Y_SET(x)		(((x) & 0xFF) << 24)
+#define CIF_ISP_AWB_MAX_Y_READ(x)		(((x) >> 24) & 0xFF)
+/* ISP_AWB_MEAN */
+#define CIF_ISP_AWB_GET_MEAN_CR_R(x)		((x) & 0xFF)
+#define CIF_ISP_AWB_GET_MEAN_CB_B(x)		(((x) >> 8) & 0xFF)
+#define CIF_ISP_AWB_GET_MEAN_Y_G(x)		(((x) >> 16) & 0xFF)
+/* ISP_AWB_WHITE_CNT */
+#define CIF_ISP_AWB_GET_PIXEL_CNT(x)		((x) & 0x3FFFFFF)
+
+#define CIF_ISP_AWB_GAINS_MAX_VAL		0x000003FF
+#define CIF_ISP_AWB_WINDOW_OFFSET_MAX		0x00000FFF
+#define CIF_ISP_AWB_WINDOW_MAX_SIZE		0x00001FFF
+#define CIF_ISP_AWB_CBCR_MAX_REF		0x000000FF
+#define CIF_ISP_AWB_THRES_MAX_YC		0x000000FF
+
+/* AE */
+/* ISP_EXP_CTRL */
+#define CIF_ISP_EXP_ENA				BIT(0)
+#define CIF_ISP_EXP_CTRL_AUTOSTOP		BIT(1)
+/*
+ *'1' luminance calculation according to  Y=(R+G+B) x 0.332 (85/256)
+ *'0' luminance calculation according to Y=16+0.25R+0.5G+0.1094B
+ */
+#define CIF_ISP_EXP_CTRL_MEASMODE_1		BIT(31)
+
+/* ISP_EXP_H_SIZE */
+#define CIF_ISP_EXP_H_SIZE_SET(x)		((x) & 0x7FF)
+#define CIF_ISP_EXP_HEIGHT_MASK			0x000007FF
+/* ISP_EXP_V_SIZE : vertical size must be a multiple of 2). */
+#define CIF_ISP_EXP_V_SIZE_SET(x)		((x) & 0x7FE)
+
+/* ISP_EXP_H_OFFSET */
+#define CIF_ISP_EXP_H_OFFSET_SET(x)		((x) & 0x1FFF)
+#define CIF_ISP_EXP_MAX_HOFFS			2424
+/* ISP_EXP_V_OFFSET */
+#define CIF_ISP_EXP_V_OFFSET_SET(x)		((x) & 0x1FFF)
+#define CIF_ISP_EXP_MAX_VOFFS			1806
+
+#define CIF_ISP_EXP_ROW_NUM			5
+#define CIF_ISP_EXP_COLUMN_NUM			5
+#define CIF_ISP_EXP_NUM_LUMA_REGS \
+	(CIF_ISP_EXP_ROW_NUM * CIF_ISP_EXP_COLUMN_NUM)
+#define CIF_ISP_EXP_BLOCK_MAX_HSIZE		516
+#define CIF_ISP_EXP_BLOCK_MIN_HSIZE		35
+#define CIF_ISP_EXP_BLOCK_MAX_VSIZE		390
+#define CIF_ISP_EXP_BLOCK_MIN_VSIZE		28
+#define CIF_ISP_EXP_MAX_HSIZE	\
+	(CIF_ISP_EXP_BLOCK_MAX_HSIZE * CIF_ISP_EXP_COLUMN_NUM + 1)
+#define CIF_ISP_EXP_MIN_HSIZE	\
+	(CIF_ISP_EXP_BLOCK_MIN_HSIZE * CIF_ISP_EXP_COLUMN_NUM + 1)
+#define CIF_ISP_EXP_MAX_VSIZE	\
+	(CIF_ISP_EXP_BLOCK_MAX_VSIZE * CIF_ISP_EXP_ROW_NUM + 1)
+#define CIF_ISP_EXP_MIN_VSIZE	\
+	(CIF_ISP_EXP_BLOCK_MIN_VSIZE * CIF_ISP_EXP_ROW_NUM + 1)
+
+/* LSC: ISP_LSC_CTRL */
+#define CIF_ISP_LSC_CTRL_ENA			BIT(0)
+#define CIF_ISP_LSC_SECT_SIZE_RESERVED		0xFC00FC00
+#define CIF_ISP_LSC_GRAD_RESERVED		0xF000F000
+#define CIF_ISP_LSC_SAMPLE_RESERVED		0xF000F000
+#define CIF_ISP_LSC_SECTORS_MAX			16
+#define CIF_ISP_LSC_TABLE_DATA(v0, v1)     \
+	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 12))
+#define CIF_ISP_LSC_SECT_SIZE(v0, v1)      \
+	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
+#define CIF_ISP_LSC_GRAD_SIZE(v0, v1)      \
+	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
+
+/* LSC: ISP_LSC_TABLE_SEL */
+#define CIF_ISP_LSC_TABLE_0			0
+#define CIF_ISP_LSC_TABLE_1			1
+
+/* LSC: ISP_LSC_STATUS */
+#define CIF_ISP_LSC_ACTIVE_TABLE		BIT(1)
+#define CIF_ISP_LSC_TABLE_ADDRESS_0		0
+#define CIF_ISP_LSC_TABLE_ADDRESS_153		153
+
+/* FLT */
+/* ISP_FILT_MODE */
+#define CIF_ISP_FLT_ENA				BIT(0)
+
+/*
+ * 0: green filter static mode (active filter factor = FILT_FAC_MID)
+ * 1: dynamic noise reduction/sharpen Default
+ */
+#define CIF_ISP_FLT_MODE_DNR			BIT(1)
+#define CIF_ISP_FLT_MODE_MAX			1
+#define CIF_ISP_FLT_CHROMA_V_MODE(x)		(((x) & 0x3) << 4)
+#define CIF_ISP_FLT_CHROMA_H_MODE(x)		(((x) & 0x3) << 6)
+#define CIF_ISP_FLT_CHROMA_MODE_MAX		3
+#define CIF_ISP_FLT_GREEN_STAGE1(x)		(((x) & 0xF) << 8)
+#define CIF_ISP_FLT_GREEN_STAGE1_MAX		8
+#define CIF_ISP_FLT_THREAD_RESERVED		0xFFFFFC00
+#define CIF_ISP_FLT_FAC_RESERVED		0xFFFFFFC0
+#define CIF_ISP_FLT_LUM_WEIGHT_RESERVED		0xFFF80000
+
+#define CIF_ISP_CTK_COEFF_RESERVED		0xFFFFF800
+#define CIF_ISP_XTALK_OFFSET_RESERVED		0xFFFFF000
+
+/* GOC */
+#define CIF_ISP_GAMMA_OUT_MODE_EQU		BIT(0)
+#define CIF_ISP_GOC_MODE_MAX			1
+#define CIF_ISP_GOC_RESERVED			0xFFFFF800
+/* ISP_CTRL BIT 11*/
+#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA_READ(x)	(((x) >> 11) & 1)
+
+/* DPCC */
+/* ISP_DPCC_MODE */
+#define CIF_ISP_DPCC_ENA			BIT(0)
+#define CIF_ISP_DPCC_MODE_MAX			0x07
+#define CIF_ISP_DPCC_OUTPUTMODE_MAX		0x0F
+#define CIF_ISP_DPCC_SETUSE_MAX			0x0F
+#define CIF_ISP_DPCC_METHODS_SET_RESERVED	0xFFFFE000
+#define CIF_ISP_DPCC_LINE_THRESH_RESERVED	0xFFFF0000
+#define CIF_ISP_DPCC_LINE_MAD_FAC_RESERVED	0xFFFFC0C0
+#define CIF_ISP_DPCC_PG_FAC_RESERVED		0xFFFFC0C0
+#define CIF_ISP_DPCC_RND_THRESH_RESERVED	0xFFFF0000
+#define CIF_ISP_DPCC_RG_FAC_RESERVED		0xFFFFC0C0
+#define CIF_ISP_DPCC_RO_LIMIT_RESERVED		0xFFFFF000
+#define CIF_ISP_DPCC_RND_OFFS_RESERVED		0xFFFFF000
+
+/* BLS */
+/* ISP_BLS_CTRL */
+#define CIF_ISP_BLS_ENA				BIT(0)
+#define CIF_ISP_BLS_MODE_MEASURED		BIT(1)
+#define CIF_ISP_BLS_MODE_FIXED			0
+#define CIF_ISP_BLS_WINDOW_1			(1 << 2)
+#define CIF_ISP_BLS_WINDOW_2			(2 << 2)
+
+/* GAMMA-IN */
+#define CIFISP_DEGAMMA_X_RESERVED	\
+	((1 << 31) | (1 << 27) | (1 << 23) | (1 << 19) |\
+	(1 << 15) | (1 << 11) | (1 << 7) | (1 << 3))
+#define CIFISP_DEGAMMA_Y_RESERVED               0xFFFFF000
+
+/* AFM */
+#define CIF_ISP_AFM_ENA				BIT(0)
+#define CIF_ISP_AFM_THRES_RESERVED		0xFFFF0000
+#define CIF_ISP_AFM_VAR_SHIFT_RESERVED		0xFFF8FFF8
+#define CIF_ISP_AFM_WINDOW_X_RESERVED		0xE000
+#define CIF_ISP_AFM_WINDOW_Y_RESERVED		0xF000
+#define CIF_ISP_AFM_WINDOW_X_MIN		0x5
+#define CIF_ISP_AFM_WINDOW_Y_MIN		0x2
+#define CIF_ISP_AFM_WINDOW_X(x)			(((x) & 0x1FFF) << 16)
+#define CIF_ISP_AFM_WINDOW_Y(x)			((x) & 0x1FFF)
+
+/* DPF */
+#define CIF_ISP_DPF_MODE_EN			BIT(0)
+#define CIF_ISP_DPF_MODE_B_FLT_DIS		BIT(1)
+#define CIF_ISP_DPF_MODE_GB_FLT_DIS		BIT(2)
+#define CIF_ISP_DPF_MODE_GR_FLT_DIS		BIT(3)
+#define CIF_ISP_DPF_MODE_R_FLT_DIS		BIT(4)
+#define CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9		BIT(5)
+#define CIF_ISP_DPF_MODE_NLL_SEGMENTATION	BIT(6)
+#define CIF_ISP_DPF_MODE_AWB_GAIN_COMP		BIT(7)
+#define CIF_ISP_DPF_MODE_LSC_GAIN_COMP		BIT(8)
+#define CIF_ISP_DPF_MODE_USE_NF_GAIN		BIT(9)
+#define CIF_ISP_DPF_NF_GAIN_RESERVED		0xFFFFF000
+#define CIF_ISP_DPF_SPATIAL_COEFF_MAX		0x1F
+#define CIF_ISP_DPF_NLL_COEFF_N_MAX		0x3FF
+
+/* =================================================================== */
+/*                            CIF Registers                            */
+/* =================================================================== */
+#define CIF_CTRL_BASE			0x00000000
+#define CIF_CCL				(CIF_CTRL_BASE + 0x00000000)
+#define CIF_VI_ID			(CIF_CTRL_BASE + 0x00000008)
+#define CIF_ICCL			(CIF_CTRL_BASE + 0x00000010)
+#define CIF_IRCL			(CIF_CTRL_BASE + 0x00000014)
+#define CIF_VI_DPCL			(CIF_CTRL_BASE + 0x00000018)
+
+#define CIF_IMG_EFF_BASE		0x00000200
+#define CIF_IMG_EFF_CTRL		(CIF_IMG_EFF_BASE + 0x00000000)
+#define CIF_IMG_EFF_COLOR_SEL		(CIF_IMG_EFF_BASE + 0x00000004)
+#define CIF_IMG_EFF_MAT_1		(CIF_IMG_EFF_BASE + 0x00000008)
+#define CIF_IMG_EFF_MAT_2		(CIF_IMG_EFF_BASE + 0x0000000C)
+#define CIF_IMG_EFF_MAT_3		(CIF_IMG_EFF_BASE + 0x00000010)
+#define CIF_IMG_EFF_MAT_4		(CIF_IMG_EFF_BASE + 0x00000014)
+#define CIF_IMG_EFF_MAT_5		(CIF_IMG_EFF_BASE + 0x00000018)
+#define CIF_IMG_EFF_TINT		(CIF_IMG_EFF_BASE + 0x0000001C)
+#define CIF_IMG_EFF_CTRL_SHD		(CIF_IMG_EFF_BASE + 0x00000020)
+#define CIF_IMG_EFF_SHARPEN		(CIF_IMG_EFF_BASE + 0x00000024)
+
+#define CIF_SUPER_IMP_BASE		0x00000300
+#define CIF_SUPER_IMP_CTRL		(CIF_SUPER_IMP_BASE + 0x00000000)
+#define CIF_SUPER_IMP_OFFSET_X		(CIF_SUPER_IMP_BASE + 0x00000004)
+#define CIF_SUPER_IMP_OFFSET_Y		(CIF_SUPER_IMP_BASE + 0x00000008)
+#define CIF_SUPER_IMP_COLOR_Y		(CIF_SUPER_IMP_BASE + 0x0000000C)
+#define CIF_SUPER_IMP_COLOR_CB		(CIF_SUPER_IMP_BASE + 0x00000010)
+#define CIF_SUPER_IMP_COLOR_CR		(CIF_SUPER_IMP_BASE + 0x00000014)
+
+#define CIF_ISP_BASE			0x00000400
+#define CIF_ISP_CTRL			(CIF_ISP_BASE + 0x00000000)
+#define CIF_ISP_ACQ_PROP		(CIF_ISP_BASE + 0x00000004)
+#define CIF_ISP_ACQ_H_OFFS		(CIF_ISP_BASE + 0x00000008)
+#define CIF_ISP_ACQ_V_OFFS		(CIF_ISP_BASE + 0x0000000C)
+#define CIF_ISP_ACQ_H_SIZE		(CIF_ISP_BASE + 0x00000010)
+#define CIF_ISP_ACQ_V_SIZE		(CIF_ISP_BASE + 0x00000014)
+#define CIF_ISP_ACQ_NR_FRAMES		(CIF_ISP_BASE + 0x00000018)
+#define CIF_ISP_GAMMA_DX_LO		(CIF_ISP_BASE + 0x0000001C)
+#define CIF_ISP_GAMMA_DX_HI		(CIF_ISP_BASE + 0x00000020)
+#define CIF_ISP_GAMMA_R_Y0		(CIF_ISP_BASE + 0x00000024)
+#define CIF_ISP_GAMMA_R_Y1		(CIF_ISP_BASE + 0x00000028)
+#define CIF_ISP_GAMMA_R_Y2		(CIF_ISP_BASE + 0x0000002C)
+#define CIF_ISP_GAMMA_R_Y3		(CIF_ISP_BASE + 0x00000030)
+#define CIF_ISP_GAMMA_R_Y4		(CIF_ISP_BASE + 0x00000034)
+#define CIF_ISP_GAMMA_R_Y5		(CIF_ISP_BASE + 0x00000038)
+#define CIF_ISP_GAMMA_R_Y6		(CIF_ISP_BASE + 0x0000003C)
+#define CIF_ISP_GAMMA_R_Y7		(CIF_ISP_BASE + 0x00000040)
+#define CIF_ISP_GAMMA_R_Y8		(CIF_ISP_BASE + 0x00000044)
+#define CIF_ISP_GAMMA_R_Y9		(CIF_ISP_BASE + 0x00000048)
+#define CIF_ISP_GAMMA_R_Y10		(CIF_ISP_BASE + 0x0000004C)
+#define CIF_ISP_GAMMA_R_Y11		(CIF_ISP_BASE + 0x00000050)
+#define CIF_ISP_GAMMA_R_Y12		(CIF_ISP_BASE + 0x00000054)
+#define CIF_ISP_GAMMA_R_Y13		(CIF_ISP_BASE + 0x00000058)
+#define CIF_ISP_GAMMA_R_Y14		(CIF_ISP_BASE + 0x0000005C)
+#define CIF_ISP_GAMMA_R_Y15		(CIF_ISP_BASE + 0x00000060)
+#define CIF_ISP_GAMMA_R_Y16		(CIF_ISP_BASE + 0x00000064)
+#define CIF_ISP_GAMMA_G_Y0		(CIF_ISP_BASE + 0x00000068)
+#define CIF_ISP_GAMMA_G_Y1		(CIF_ISP_BASE + 0x0000006C)
+#define CIF_ISP_GAMMA_G_Y2		(CIF_ISP_BASE + 0x00000070)
+#define CIF_ISP_GAMMA_G_Y3		(CIF_ISP_BASE + 0x00000074)
+#define CIF_ISP_GAMMA_G_Y4		(CIF_ISP_BASE + 0x00000078)
+#define CIF_ISP_GAMMA_G_Y5		(CIF_ISP_BASE + 0x0000007C)
+#define CIF_ISP_GAMMA_G_Y6		(CIF_ISP_BASE + 0x00000080)
+#define CIF_ISP_GAMMA_G_Y7		(CIF_ISP_BASE + 0x00000084)
+#define CIF_ISP_GAMMA_G_Y8		(CIF_ISP_BASE + 0x00000088)
+#define CIF_ISP_GAMMA_G_Y9		(CIF_ISP_BASE + 0x0000008C)
+#define CIF_ISP_GAMMA_G_Y10		(CIF_ISP_BASE + 0x00000090)
+#define CIF_ISP_GAMMA_G_Y11		(CIF_ISP_BASE + 0x00000094)
+#define CIF_ISP_GAMMA_G_Y12		(CIF_ISP_BASE + 0x00000098)
+#define CIF_ISP_GAMMA_G_Y13		(CIF_ISP_BASE + 0x0000009C)
+#define CIF_ISP_GAMMA_G_Y14		(CIF_ISP_BASE + 0x000000A0)
+#define CIF_ISP_GAMMA_G_Y15		(CIF_ISP_BASE + 0x000000A4)
+#define CIF_ISP_GAMMA_G_Y16		(CIF_ISP_BASE + 0x000000A8)
+#define CIF_ISP_GAMMA_B_Y0		(CIF_ISP_BASE + 0x000000AC)
+#define CIF_ISP_GAMMA_B_Y1		(CIF_ISP_BASE + 0x000000B0)
+#define CIF_ISP_GAMMA_B_Y2		(CIF_ISP_BASE + 0x000000B4)
+#define CIF_ISP_GAMMA_B_Y3		(CIF_ISP_BASE + 0x000000B8)
+#define CIF_ISP_GAMMA_B_Y4		(CIF_ISP_BASE + 0x000000BC)
+#define CIF_ISP_GAMMA_B_Y5		(CIF_ISP_BASE + 0x000000C0)
+#define CIF_ISP_GAMMA_B_Y6		(CIF_ISP_BASE + 0x000000C4)
+#define CIF_ISP_GAMMA_B_Y7		(CIF_ISP_BASE + 0x000000C8)
+#define CIF_ISP_GAMMA_B_Y8		(CIF_ISP_BASE + 0x000000CC)
+#define CIF_ISP_GAMMA_B_Y9		(CIF_ISP_BASE + 0x000000D0)
+#define CIF_ISP_GAMMA_B_Y10		(CIF_ISP_BASE + 0x000000D4)
+#define CIF_ISP_GAMMA_B_Y11		(CIF_ISP_BASE + 0x000000D8)
+#define CIF_ISP_GAMMA_B_Y12		(CIF_ISP_BASE + 0x000000DC)
+#define CIF_ISP_GAMMA_B_Y13		(CIF_ISP_BASE + 0x000000E0)
+#define CIF_ISP_GAMMA_B_Y14		(CIF_ISP_BASE + 0x000000E4)
+#define CIF_ISP_GAMMA_B_Y15		(CIF_ISP_BASE + 0x000000E8)
+#define CIF_ISP_GAMMA_B_Y16		(CIF_ISP_BASE + 0x000000EC)
+#define CIF_ISP_AWB_PROP		(CIF_ISP_BASE + 0x00000110)
+#define CIF_ISP_AWB_WND_H_OFFS		(CIF_ISP_BASE + 0x00000114)
+#define CIF_ISP_AWB_WND_V_OFFS		(CIF_ISP_BASE + 0x00000118)
+#define CIF_ISP_AWB_WND_H_SIZE		(CIF_ISP_BASE + 0x0000011C)
+#define CIF_ISP_AWB_WND_V_SIZE		(CIF_ISP_BASE + 0x00000120)
+#define CIF_ISP_AWB_FRAMES		(CIF_ISP_BASE + 0x00000124)
+#define CIF_ISP_AWB_REF			(CIF_ISP_BASE + 0x00000128)
+#define CIF_ISP_AWB_THRESH		(CIF_ISP_BASE + 0x0000012C)
+#define CIF_ISP_AWB_GAIN_G		(CIF_ISP_BASE + 0x00000138)
+#define CIF_ISP_AWB_GAIN_RB		(CIF_ISP_BASE + 0x0000013C)
+#define CIF_ISP_AWB_WHITE_CNT		(CIF_ISP_BASE + 0x00000140)
+#define CIF_ISP_AWB_MEAN		(CIF_ISP_BASE + 0x00000144)
+#define CIF_ISP_CC_COEFF_0		(CIF_ISP_BASE + 0x00000170)
+#define CIF_ISP_CC_COEFF_1		(CIF_ISP_BASE + 0x00000174)
+#define CIF_ISP_CC_COEFF_2		(CIF_ISP_BASE + 0x00000178)
+#define CIF_ISP_CC_COEFF_3		(CIF_ISP_BASE + 0x0000017C)
+#define CIF_ISP_CC_COEFF_4		(CIF_ISP_BASE + 0x00000180)
+#define CIF_ISP_CC_COEFF_5		(CIF_ISP_BASE + 0x00000184)
+#define CIF_ISP_CC_COEFF_6		(CIF_ISP_BASE + 0x00000188)
+#define CIF_ISP_CC_COEFF_7		(CIF_ISP_BASE + 0x0000018C)
+#define CIF_ISP_CC_COEFF_8		(CIF_ISP_BASE + 0x00000190)
+#define CIF_ISP_OUT_H_OFFS		(CIF_ISP_BASE + 0x00000194)
+#define CIF_ISP_OUT_V_OFFS		(CIF_ISP_BASE + 0x00000198)
+#define CIF_ISP_OUT_H_SIZE		(CIF_ISP_BASE + 0x0000019C)
+#define CIF_ISP_OUT_V_SIZE		(CIF_ISP_BASE + 0x000001A0)
+#define CIF_ISP_DEMOSAIC		(CIF_ISP_BASE + 0x000001A4)
+#define CIF_ISP_FLAGS_SHD		(CIF_ISP_BASE + 0x000001A8)
+#define CIF_ISP_OUT_H_OFFS_SHD		(CIF_ISP_BASE + 0x000001AC)
+#define CIF_ISP_OUT_V_OFFS_SHD		(CIF_ISP_BASE + 0x000001B0)
+#define CIF_ISP_OUT_H_SIZE_SHD		(CIF_ISP_BASE + 0x000001B4)
+#define CIF_ISP_OUT_V_SIZE_SHD		(CIF_ISP_BASE + 0x000001B8)
+#define CIF_ISP_IMSC			(CIF_ISP_BASE + 0x000001BC)
+#define CIF_ISP_RIS			(CIF_ISP_BASE + 0x000001C0)
+#define CIF_ISP_MIS			(CIF_ISP_BASE + 0x000001C4)
+#define CIF_ISP_ICR			(CIF_ISP_BASE + 0x000001C8)
+#define CIF_ISP_ISR			(CIF_ISP_BASE + 0x000001CC)
+#define CIF_ISP_CT_COEFF_0		(CIF_ISP_BASE + 0x000001D0)
+#define CIF_ISP_CT_COEFF_1		(CIF_ISP_BASE + 0x000001D4)
+#define CIF_ISP_CT_COEFF_2		(CIF_ISP_BASE + 0x000001D8)
+#define CIF_ISP_CT_COEFF_3		(CIF_ISP_BASE + 0x000001DC)
+#define CIF_ISP_CT_COEFF_4		(CIF_ISP_BASE + 0x000001E0)
+#define CIF_ISP_CT_COEFF_5		(CIF_ISP_BASE + 0x000001E4)
+#define CIF_ISP_CT_COEFF_6		(CIF_ISP_BASE + 0x000001E8)
+#define CIF_ISP_CT_COEFF_7		(CIF_ISP_BASE + 0x000001EC)
+#define CIF_ISP_CT_COEFF_8		(CIF_ISP_BASE + 0x000001F0)
+#define CIF_ISP_GAMMA_OUT_MODE		(CIF_ISP_BASE + 0x000001F4)
+#define CIF_ISP_GAMMA_OUT_Y_0		(CIF_ISP_BASE + 0x000001F8)
+#define CIF_ISP_GAMMA_OUT_Y_1		(CIF_ISP_BASE + 0x000001FC)
+#define CIF_ISP_GAMMA_OUT_Y_2		(CIF_ISP_BASE + 0x00000200)
+#define CIF_ISP_GAMMA_OUT_Y_3		(CIF_ISP_BASE + 0x00000204)
+#define CIF_ISP_GAMMA_OUT_Y_4		(CIF_ISP_BASE + 0x00000208)
+#define CIF_ISP_GAMMA_OUT_Y_5		(CIF_ISP_BASE + 0x0000020C)
+#define CIF_ISP_GAMMA_OUT_Y_6		(CIF_ISP_BASE + 0x00000210)
+#define CIF_ISP_GAMMA_OUT_Y_7		(CIF_ISP_BASE + 0x00000214)
+#define CIF_ISP_GAMMA_OUT_Y_8		(CIF_ISP_BASE + 0x00000218)
+#define CIF_ISP_GAMMA_OUT_Y_9		(CIF_ISP_BASE + 0x0000021C)
+#define CIF_ISP_GAMMA_OUT_Y_10		(CIF_ISP_BASE + 0x00000220)
+#define CIF_ISP_GAMMA_OUT_Y_11		(CIF_ISP_BASE + 0x00000224)
+#define CIF_ISP_GAMMA_OUT_Y_12		(CIF_ISP_BASE + 0x00000228)
+#define CIF_ISP_GAMMA_OUT_Y_13		(CIF_ISP_BASE + 0x0000022C)
+#define CIF_ISP_GAMMA_OUT_Y_14		(CIF_ISP_BASE + 0x00000230)
+#define CIF_ISP_GAMMA_OUT_Y_15		(CIF_ISP_BASE + 0x00000234)
+#define CIF_ISP_GAMMA_OUT_Y_16		(CIF_ISP_BASE + 0x00000238)
+#define CIF_ISP_ERR			(CIF_ISP_BASE + 0x0000023C)
+#define CIF_ISP_ERR_CLR			(CIF_ISP_BASE + 0x00000240)
+#define CIF_ISP_FRAME_COUNT		(CIF_ISP_BASE + 0x00000244)
+#define CIF_ISP_CT_OFFSET_R		(CIF_ISP_BASE + 0x00000248)
+#define CIF_ISP_CT_OFFSET_G		(CIF_ISP_BASE + 0x0000024C)
+#define CIF_ISP_CT_OFFSET_B		(CIF_ISP_BASE + 0x00000250)
+
+#define CIF_ISP_FLASH_BASE		0x00000660
+#define CIF_ISP_FLASH_CMD		(CIF_ISP_FLASH_BASE + 0x00000000)
+#define CIF_ISP_FLASH_CONFIG		(CIF_ISP_FLASH_BASE + 0x00000004)
+#define CIF_ISP_FLASH_PREDIV		(CIF_ISP_FLASH_BASE + 0x00000008)
+#define CIF_ISP_FLASH_DELAY		(CIF_ISP_FLASH_BASE + 0x0000000C)
+#define CIF_ISP_FLASH_TIME		(CIF_ISP_FLASH_BASE + 0x00000010)
+#define CIF_ISP_FLASH_MAXP		(CIF_ISP_FLASH_BASE + 0x00000014)
+
+#define CIF_ISP_SH_BASE			0x00000680
+#define CIF_ISP_SH_CTRL			(CIF_ISP_SH_BASE + 0x00000000)
+#define CIF_ISP_SH_PREDIV		(CIF_ISP_SH_BASE + 0x00000004)
+#define CIF_ISP_SH_DELAY		(CIF_ISP_SH_BASE + 0x00000008)
+#define CIF_ISP_SH_TIME			(CIF_ISP_SH_BASE + 0x0000000C)
+
+#define CIF_C_PROC_BASE			0x00000800
+#define CIF_C_PROC_CTRL			(CIF_C_PROC_BASE + 0x00000000)
+#define CIF_C_PROC_CONTRAST		(CIF_C_PROC_BASE + 0x00000004)
+#define CIF_C_PROC_BRIGHTNESS		(CIF_C_PROC_BASE + 0x00000008)
+#define CIF_C_PROC_SATURATION		(CIF_C_PROC_BASE + 0x0000000C)
+#define CIF_C_PROC_HUE			(CIF_C_PROC_BASE + 0x00000010)
+
+#define CIF_DUAL_CROP_BASE		0x00000880
+#define CIF_DUAL_CROP_CTRL		(CIF_DUAL_CROP_BASE + 0x00000000)
+#define CIF_DUAL_CROP_M_H_OFFS		(CIF_DUAL_CROP_BASE + 0x00000004)
+#define CIF_DUAL_CROP_M_V_OFFS		(CIF_DUAL_CROP_BASE + 0x00000008)
+#define CIF_DUAL_CROP_M_H_SIZE		(CIF_DUAL_CROP_BASE + 0x0000000C)
+#define CIF_DUAL_CROP_M_V_SIZE		(CIF_DUAL_CROP_BASE + 0x00000010)
+#define CIF_DUAL_CROP_S_H_OFFS		(CIF_DUAL_CROP_BASE + 0x00000014)
+#define CIF_DUAL_CROP_S_V_OFFS		(CIF_DUAL_CROP_BASE + 0x00000018)
+#define CIF_DUAL_CROP_S_H_SIZE		(CIF_DUAL_CROP_BASE + 0x0000001C)
+#define CIF_DUAL_CROP_S_V_SIZE		(CIF_DUAL_CROP_BASE + 0x00000020)
+#define CIF_DUAL_CROP_M_H_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000024)
+#define CIF_DUAL_CROP_M_V_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000028)
+#define CIF_DUAL_CROP_M_H_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x0000002C)
+#define CIF_DUAL_CROP_M_V_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x00000030)
+#define CIF_DUAL_CROP_S_H_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000034)
+#define CIF_DUAL_CROP_S_V_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000038)
+#define CIF_DUAL_CROP_S_H_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x0000003C)
+#define CIF_DUAL_CROP_S_V_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x00000040)
+
+#define CIF_MRSZ_BASE			0x00000C00
+#define CIF_MRSZ_CTRL			(CIF_MRSZ_BASE + 0x00000000)
+#define CIF_MRSZ_SCALE_HY		(CIF_MRSZ_BASE + 0x00000004)
+#define CIF_MRSZ_SCALE_HCB		(CIF_MRSZ_BASE + 0x00000008)
+#define CIF_MRSZ_SCALE_HCR		(CIF_MRSZ_BASE + 0x0000000C)
+#define CIF_MRSZ_SCALE_VY		(CIF_MRSZ_BASE + 0x00000010)
+#define CIF_MRSZ_SCALE_VC		(CIF_MRSZ_BASE + 0x00000014)
+#define CIF_MRSZ_PHASE_HY		(CIF_MRSZ_BASE + 0x00000018)
+#define CIF_MRSZ_PHASE_HC		(CIF_MRSZ_BASE + 0x0000001C)
+#define CIF_MRSZ_PHASE_VY		(CIF_MRSZ_BASE + 0x00000020)
+#define CIF_MRSZ_PHASE_VC		(CIF_MRSZ_BASE + 0x00000024)
+#define CIF_MRSZ_SCALE_LUT_ADDR		(CIF_MRSZ_BASE + 0x00000028)
+#define CIF_MRSZ_SCALE_LUT		(CIF_MRSZ_BASE + 0x0000002C)
+#define CIF_MRSZ_CTRL_SHD		(CIF_MRSZ_BASE + 0x00000030)
+#define CIF_MRSZ_SCALE_HY_SHD		(CIF_MRSZ_BASE + 0x00000034)
+#define CIF_MRSZ_SCALE_HCB_SHD		(CIF_MRSZ_BASE + 0x00000038)
+#define CIF_MRSZ_SCALE_HCR_SHD		(CIF_MRSZ_BASE + 0x0000003C)
+#define CIF_MRSZ_SCALE_VY_SHD		(CIF_MRSZ_BASE + 0x00000040)
+#define CIF_MRSZ_SCALE_VC_SHD		(CIF_MRSZ_BASE + 0x00000044)
+#define CIF_MRSZ_PHASE_HY_SHD		(CIF_MRSZ_BASE + 0x00000048)
+#define CIF_MRSZ_PHASE_HC_SHD		(CIF_MRSZ_BASE + 0x0000004C)
+#define CIF_MRSZ_PHASE_VY_SHD		(CIF_MRSZ_BASE + 0x00000050)
+#define CIF_MRSZ_PHASE_VC_SHD		(CIF_MRSZ_BASE + 0x00000054)
+
+#define CIF_SRSZ_BASE			0x00001000
+#define CIF_SRSZ_CTRL			(CIF_SRSZ_BASE + 0x00000000)
+#define CIF_SRSZ_SCALE_HY		(CIF_SRSZ_BASE + 0x00000004)
+#define CIF_SRSZ_SCALE_HCB		(CIF_SRSZ_BASE + 0x00000008)
+#define CIF_SRSZ_SCALE_HCR		(CIF_SRSZ_BASE + 0x0000000C)
+#define CIF_SRSZ_SCALE_VY		(CIF_SRSZ_BASE + 0x00000010)
+#define CIF_SRSZ_SCALE_VC		(CIF_SRSZ_BASE + 0x00000014)
+#define CIF_SRSZ_PHASE_HY		(CIF_SRSZ_BASE + 0x00000018)
+#define CIF_SRSZ_PHASE_HC		(CIF_SRSZ_BASE + 0x0000001C)
+#define CIF_SRSZ_PHASE_VY		(CIF_SRSZ_BASE + 0x00000020)
+#define CIF_SRSZ_PHASE_VC		(CIF_SRSZ_BASE + 0x00000024)
+#define CIF_SRSZ_SCALE_LUT_ADDR		(CIF_SRSZ_BASE + 0x00000028)
+#define CIF_SRSZ_SCALE_LUT		(CIF_SRSZ_BASE + 0x0000002C)
+#define CIF_SRSZ_CTRL_SHD		(CIF_SRSZ_BASE + 0x00000030)
+#define CIF_SRSZ_SCALE_HY_SHD		(CIF_SRSZ_BASE + 0x00000034)
+#define CIF_SRSZ_SCALE_HCB_SHD		(CIF_SRSZ_BASE + 0x00000038)
+#define CIF_SRSZ_SCALE_HCR_SHD		(CIF_SRSZ_BASE + 0x0000003C)
+#define CIF_SRSZ_SCALE_VY_SHD		(CIF_SRSZ_BASE + 0x00000040)
+#define CIF_SRSZ_SCALE_VC_SHD		(CIF_SRSZ_BASE + 0x00000044)
+#define CIF_SRSZ_PHASE_HY_SHD		(CIF_SRSZ_BASE + 0x00000048)
+#define CIF_SRSZ_PHASE_HC_SHD		(CIF_SRSZ_BASE + 0x0000004C)
+#define CIF_SRSZ_PHASE_VY_SHD		(CIF_SRSZ_BASE + 0x00000050)
+#define CIF_SRSZ_PHASE_VC_SHD		(CIF_SRSZ_BASE + 0x00000054)
+
+#define CIF_MI_BASE			0x00001400
+#define CIF_MI_CTRL			(CIF_MI_BASE + 0x00000000)
+#define CIF_MI_INIT			(CIF_MI_BASE + 0x00000004)
+#define CIF_MI_MP_Y_BASE_AD_INIT	(CIF_MI_BASE + 0x00000008)
+#define CIF_MI_MP_Y_SIZE_INIT		(CIF_MI_BASE + 0x0000000C)
+#define CIF_MI_MP_Y_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000010)
+#define CIF_MI_MP_Y_OFFS_CNT_START	(CIF_MI_BASE + 0x00000014)
+#define CIF_MI_MP_Y_IRQ_OFFS_INIT	(CIF_MI_BASE + 0x00000018)
+#define CIF_MI_MP_CB_BASE_AD_INIT	(CIF_MI_BASE + 0x0000001C)
+#define CIF_MI_MP_CB_SIZE_INIT		(CIF_MI_BASE + 0x00000020)
+#define CIF_MI_MP_CB_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000024)
+#define CIF_MI_MP_CB_OFFS_CNT_START	(CIF_MI_BASE + 0x00000028)
+#define CIF_MI_MP_CR_BASE_AD_INIT	(CIF_MI_BASE + 0x0000002C)
+#define CIF_MI_MP_CR_SIZE_INIT		(CIF_MI_BASE + 0x00000030)
+#define CIF_MI_MP_CR_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000034)
+#define CIF_MI_MP_CR_OFFS_CNT_START	(CIF_MI_BASE + 0x00000038)
+#define CIF_MI_SP_Y_BASE_AD_INIT	(CIF_MI_BASE + 0x0000003C)
+#define CIF_MI_SP_Y_SIZE_INIT		(CIF_MI_BASE + 0x00000040)
+#define CIF_MI_SP_Y_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000044)
+#define CIF_MI_SP_Y_OFFS_CNT_START	(CIF_MI_BASE + 0x00000048)
+#define CIF_MI_SP_Y_LLENGTH		(CIF_MI_BASE + 0x0000004C)
+#define CIF_MI_SP_CB_BASE_AD_INIT	(CIF_MI_BASE + 0x00000050)
+#define CIF_MI_SP_CB_SIZE_INIT		(CIF_MI_BASE + 0x00000054)
+#define CIF_MI_SP_CB_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000058)
+#define CIF_MI_SP_CB_OFFS_CNT_START	(CIF_MI_BASE + 0x0000005C)
+#define CIF_MI_SP_CR_BASE_AD_INIT	(CIF_MI_BASE + 0x00000060)
+#define CIF_MI_SP_CR_SIZE_INIT		(CIF_MI_BASE + 0x00000064)
+#define CIF_MI_SP_CR_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000068)
+#define CIF_MI_SP_CR_OFFS_CNT_START	(CIF_MI_BASE + 0x0000006C)
+#define CIF_MI_BYTE_CNT			(CIF_MI_BASE + 0x00000070)
+#define CIF_MI_CTRL_SHD			(CIF_MI_BASE + 0x00000074)
+#define CIF_MI_MP_Y_BASE_AD_SHD		(CIF_MI_BASE + 0x00000078)
+#define CIF_MI_MP_Y_SIZE_SHD		(CIF_MI_BASE + 0x0000007C)
+#define CIF_MI_MP_Y_OFFS_CNT_SHD	(CIF_MI_BASE + 0x00000080)
+#define CIF_MI_MP_Y_IRQ_OFFS_SHD	(CIF_MI_BASE + 0x00000084)
+#define CIF_MI_MP_CB_BASE_AD_SHD	(CIF_MI_BASE + 0x00000088)
+#define CIF_MI_MP_CB_SIZE_SHD		(CIF_MI_BASE + 0x0000008C)
+#define CIF_MI_MP_CB_OFFS_CNT_SHD	(CIF_MI_BASE + 0x00000090)
+#define CIF_MI_MP_CR_BASE_AD_SHD	(CIF_MI_BASE + 0x00000094)
+#define CIF_MI_MP_CR_SIZE_SHD		(CIF_MI_BASE + 0x00000098)
+#define CIF_MI_MP_CR_OFFS_CNT_SHD	(CIF_MI_BASE + 0x0000009C)
+#define CIF_MI_SP_Y_BASE_AD_SHD		(CIF_MI_BASE + 0x000000A0)
+#define CIF_MI_SP_Y_SIZE_SHD		(CIF_MI_BASE + 0x000000A4)
+#define CIF_MI_SP_Y_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000A8)
+#define CIF_MI_SP_CB_BASE_AD_SHD	(CIF_MI_BASE + 0x000000B0)
+#define CIF_MI_SP_CB_SIZE_SHD		(CIF_MI_BASE + 0x000000B4)
+#define CIF_MI_SP_CB_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000B8)
+#define CIF_MI_SP_CR_BASE_AD_SHD	(CIF_MI_BASE + 0x000000BC)
+#define CIF_MI_SP_CR_SIZE_SHD		(CIF_MI_BASE + 0x000000C0)
+#define CIF_MI_SP_CR_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000C4)
+#define CIF_MI_DMA_Y_PIC_START_AD	(CIF_MI_BASE + 0x000000C8)
+#define CIF_MI_DMA_Y_PIC_WIDTH		(CIF_MI_BASE + 0x000000CC)
+#define CIF_MI_DMA_Y_LLENGTH		(CIF_MI_BASE + 0x000000D0)
+#define CIF_MI_DMA_Y_PIC_SIZE		(CIF_MI_BASE + 0x000000D4)
+#define CIF_MI_DMA_CB_PIC_START_AD	(CIF_MI_BASE + 0x000000D8)
+#define CIF_MI_DMA_CR_PIC_START_AD	(CIF_MI_BASE + 0x000000E8)
+#define CIF_MI_IMSC			(CIF_MI_BASE + 0x000000F8)
+#define CIF_MI_RIS			(CIF_MI_BASE + 0x000000FC)
+#define CIF_MI_MIS			(CIF_MI_BASE + 0x00000100)
+#define CIF_MI_ICR			(CIF_MI_BASE + 0x00000104)
+#define CIF_MI_ISR			(CIF_MI_BASE + 0x00000108)
+#define CIF_MI_STATUS			(CIF_MI_BASE + 0x0000010C)
+#define CIF_MI_STATUS_CLR		(CIF_MI_BASE + 0x00000110)
+#define CIF_MI_SP_Y_PIC_WIDTH		(CIF_MI_BASE + 0x00000114)
+#define CIF_MI_SP_Y_PIC_HEIGHT		(CIF_MI_BASE + 0x00000118)
+#define CIF_MI_SP_Y_PIC_SIZE		(CIF_MI_BASE + 0x0000011C)
+#define CIF_MI_DMA_CTRL			(CIF_MI_BASE + 0x00000120)
+#define CIF_MI_DMA_START		(CIF_MI_BASE + 0x00000124)
+#define CIF_MI_DMA_STATUS		(CIF_MI_BASE + 0x00000128)
+#define CIF_MI_PIXEL_COUNT		(CIF_MI_BASE + 0x0000012C)
+#define CIF_MI_MP_Y_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000130)
+#define CIF_MI_MP_CB_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000134)
+#define CIF_MI_MP_CR_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000138)
+#define CIF_MI_SP_Y_BASE_AD_INIT2	(CIF_MI_BASE + 0x0000013C)
+#define CIF_MI_SP_CB_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000140)
+#define CIF_MI_SP_CR_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000144)
+#define CIF_MI_XTD_FORMAT_CTRL		(CIF_MI_BASE + 0x00000148)
+
+#define CIF_SMIA_BASE			0x00001A00
+#define CIF_SMIA_CTRL			(CIF_SMIA_BASE + 0x00000000)
+#define CIF_SMIA_STATUS			(CIF_SMIA_BASE + 0x00000004)
+#define CIF_SMIA_IMSC			(CIF_SMIA_BASE + 0x00000008)
+#define CIF_SMIA_RIS			(CIF_SMIA_BASE + 0x0000000C)
+#define CIF_SMIA_MIS			(CIF_SMIA_BASE + 0x00000010)
+#define CIF_SMIA_ICR			(CIF_SMIA_BASE + 0x00000014)
+#define CIF_SMIA_ISR			(CIF_SMIA_BASE + 0x00000018)
+#define CIF_SMIA_DATA_FORMAT_SEL	(CIF_SMIA_BASE + 0x0000001C)
+#define CIF_SMIA_SOF_EMB_DATA_LINES	(CIF_SMIA_BASE + 0x00000020)
+#define CIF_SMIA_EMB_HSTART		(CIF_SMIA_BASE + 0x00000024)
+#define CIF_SMIA_EMB_HSIZE		(CIF_SMIA_BASE + 0x00000028)
+#define CIF_SMIA_EMB_VSTART		(CIF_SMIA_BASE + 0x0000002c)
+#define CIF_SMIA_NUM_LINES		(CIF_SMIA_BASE + 0x00000030)
+#define CIF_SMIA_EMB_DATA_FIFO		(CIF_SMIA_BASE + 0x00000034)
+#define CIF_SMIA_EMB_DATA_WATERMARK	(CIF_SMIA_BASE + 0x00000038)
+
+#define CIF_MIPI_BASE			0x00001C00
+#define CIF_MIPI_CTRL			(CIF_MIPI_BASE + 0x00000000)
+#define CIF_MIPI_STATUS			(CIF_MIPI_BASE + 0x00000004)
+#define CIF_MIPI_IMSC			(CIF_MIPI_BASE + 0x00000008)
+#define CIF_MIPI_RIS			(CIF_MIPI_BASE + 0x0000000C)
+#define CIF_MIPI_MIS			(CIF_MIPI_BASE + 0x00000010)
+#define CIF_MIPI_ICR			(CIF_MIPI_BASE + 0x00000014)
+#define CIF_MIPI_ISR			(CIF_MIPI_BASE + 0x00000018)
+#define CIF_MIPI_CUR_DATA_ID		(CIF_MIPI_BASE + 0x0000001C)
+#define CIF_MIPI_IMG_DATA_SEL		(CIF_MIPI_BASE + 0x00000020)
+#define CIF_MIPI_ADD_DATA_SEL_1		(CIF_MIPI_BASE + 0x00000024)
+#define CIF_MIPI_ADD_DATA_SEL_2		(CIF_MIPI_BASE + 0x00000028)
+#define CIF_MIPI_ADD_DATA_SEL_3		(CIF_MIPI_BASE + 0x0000002C)
+#define CIF_MIPI_ADD_DATA_SEL_4		(CIF_MIPI_BASE + 0x00000030)
+#define CIF_MIPI_ADD_DATA_FIFO		(CIF_MIPI_BASE + 0x00000034)
+#define CIF_MIPI_FIFO_FILL_LEVEL	(CIF_MIPI_BASE + 0x00000038)
+#define CIF_MIPI_COMPRESSED_MODE	(CIF_MIPI_BASE + 0x0000003C)
+#define CIF_MIPI_FRAME			(CIF_MIPI_BASE + 0x00000040)
+#define CIF_MIPI_GEN_SHORT_DT		(CIF_MIPI_BASE + 0x00000044)
+#define CIF_MIPI_GEN_SHORT_8_9		(CIF_MIPI_BASE + 0x00000048)
+#define CIF_MIPI_GEN_SHORT_A_B		(CIF_MIPI_BASE + 0x0000004C)
+#define CIF_MIPI_GEN_SHORT_C_D		(CIF_MIPI_BASE + 0x00000050)
+#define CIF_MIPI_GEN_SHORT_E_F		(CIF_MIPI_BASE + 0x00000054)
+
+#define CIF_ISP_AFM_BASE		0x00002000
+#define CIF_ISP_AFM_CTRL		(CIF_ISP_AFM_BASE + 0x00000000)
+#define CIF_ISP_AFM_LT_A		(CIF_ISP_AFM_BASE + 0x00000004)
+#define CIF_ISP_AFM_RB_A		(CIF_ISP_AFM_BASE + 0x00000008)
+#define CIF_ISP_AFM_LT_B		(CIF_ISP_AFM_BASE + 0x0000000C)
+#define CIF_ISP_AFM_RB_B		(CIF_ISP_AFM_BASE + 0x00000010)
+#define CIF_ISP_AFM_LT_C		(CIF_ISP_AFM_BASE + 0x00000014)
+#define CIF_ISP_AFM_RB_C		(CIF_ISP_AFM_BASE + 0x00000018)
+#define CIF_ISP_AFM_THRES		(CIF_ISP_AFM_BASE + 0x0000001C)
+#define CIF_ISP_AFM_VAR_SHIFT		(CIF_ISP_AFM_BASE + 0x00000020)
+#define CIF_ISP_AFM_SUM_A		(CIF_ISP_AFM_BASE + 0x00000024)
+#define CIF_ISP_AFM_SUM_B		(CIF_ISP_AFM_BASE + 0x00000028)
+#define CIF_ISP_AFM_SUM_C		(CIF_ISP_AFM_BASE + 0x0000002C)
+#define CIF_ISP_AFM_LUM_A		(CIF_ISP_AFM_BASE + 0x00000030)
+#define CIF_ISP_AFM_LUM_B		(CIF_ISP_AFM_BASE + 0x00000034)
+#define CIF_ISP_AFM_LUM_C		(CIF_ISP_AFM_BASE + 0x00000038)
+
+#define CIF_ISP_LSC_BASE		0x00002200
+#define CIF_ISP_LSC_CTRL		(CIF_ISP_LSC_BASE + 0x00000000)
+#define CIF_ISP_LSC_R_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000004)
+#define CIF_ISP_LSC_GR_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000008)
+#define CIF_ISP_LSC_B_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x0000000C)
+#define CIF_ISP_LSC_GB_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000010)
+#define CIF_ISP_LSC_R_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000014)
+#define CIF_ISP_LSC_GR_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000018)
+#define CIF_ISP_LSC_B_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x0000001C)
+#define CIF_ISP_LSC_GB_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000020)
+#define CIF_ISP_LSC_XGRAD_01		(CIF_ISP_LSC_BASE + 0x00000024)
+#define CIF_ISP_LSC_XGRAD_23		(CIF_ISP_LSC_BASE + 0x00000028)
+#define CIF_ISP_LSC_XGRAD_45		(CIF_ISP_LSC_BASE + 0x0000002C)
+#define CIF_ISP_LSC_XGRAD_67		(CIF_ISP_LSC_BASE + 0x00000030)
+#define CIF_ISP_LSC_YGRAD_01		(CIF_ISP_LSC_BASE + 0x00000034)
+#define CIF_ISP_LSC_YGRAD_23		(CIF_ISP_LSC_BASE + 0x00000038)
+#define CIF_ISP_LSC_YGRAD_45		(CIF_ISP_LSC_BASE + 0x0000003C)
+#define CIF_ISP_LSC_YGRAD_67		(CIF_ISP_LSC_BASE + 0x00000040)
+#define CIF_ISP_LSC_XSIZE_01		(CIF_ISP_LSC_BASE + 0x00000044)
+#define CIF_ISP_LSC_XSIZE_23		(CIF_ISP_LSC_BASE + 0x00000048)
+#define CIF_ISP_LSC_XSIZE_45		(CIF_ISP_LSC_BASE + 0x0000004C)
+#define CIF_ISP_LSC_XSIZE_67		(CIF_ISP_LSC_BASE + 0x00000050)
+#define CIF_ISP_LSC_YSIZE_01		(CIF_ISP_LSC_BASE + 0x00000054)
+#define CIF_ISP_LSC_YSIZE_23		(CIF_ISP_LSC_BASE + 0x00000058)
+#define CIF_ISP_LSC_YSIZE_45		(CIF_ISP_LSC_BASE + 0x0000005C)
+#define CIF_ISP_LSC_YSIZE_67		(CIF_ISP_LSC_BASE + 0x00000060)
+#define CIF_ISP_LSC_TABLE_SEL		(CIF_ISP_LSC_BASE + 0x00000064)
+#define CIF_ISP_LSC_STATUS		(CIF_ISP_LSC_BASE + 0x00000068)
+
+#define CIF_ISP_IS_BASE			0x00002300
+#define CIF_ISP_IS_CTRL			(CIF_ISP_IS_BASE + 0x00000000)
+#define CIF_ISP_IS_RECENTER		(CIF_ISP_IS_BASE + 0x00000004)
+#define CIF_ISP_IS_H_OFFS		(CIF_ISP_IS_BASE + 0x00000008)
+#define CIF_ISP_IS_V_OFFS		(CIF_ISP_IS_BASE + 0x0000000C)
+#define CIF_ISP_IS_H_SIZE		(CIF_ISP_IS_BASE + 0x00000010)
+#define CIF_ISP_IS_V_SIZE		(CIF_ISP_IS_BASE + 0x00000014)
+#define CIF_ISP_IS_MAX_DX		(CIF_ISP_IS_BASE + 0x00000018)
+#define CIF_ISP_IS_MAX_DY		(CIF_ISP_IS_BASE + 0x0000001C)
+#define CIF_ISP_IS_DISPLACE		(CIF_ISP_IS_BASE + 0x00000020)
+#define CIF_ISP_IS_H_OFFS_SHD		(CIF_ISP_IS_BASE + 0x00000024)
+#define CIF_ISP_IS_V_OFFS_SHD		(CIF_ISP_IS_BASE + 0x00000028)
+#define CIF_ISP_IS_H_SIZE_SHD		(CIF_ISP_IS_BASE + 0x0000002C)
+#define CIF_ISP_IS_V_SIZE_SHD		(CIF_ISP_IS_BASE + 0x00000030)
+
+#define CIF_ISP_HIST_BASE		0x00002400
+
+#define CIF_ISP_HIST_PROP		(CIF_ISP_HIST_BASE + 0x00000000)
+#define CIF_ISP_HIST_H_OFFS		(CIF_ISP_HIST_BASE + 0x00000004)
+#define CIF_ISP_HIST_V_OFFS		(CIF_ISP_HIST_BASE + 0x00000008)
+#define CIF_ISP_HIST_H_SIZE		(CIF_ISP_HIST_BASE + 0x0000000C)
+#define CIF_ISP_HIST_V_SIZE		(CIF_ISP_HIST_BASE + 0x00000010)
+#define CIF_ISP_HIST_BIN_0		(CIF_ISP_HIST_BASE + 0x00000014)
+#define CIF_ISP_HIST_BIN_1		(CIF_ISP_HIST_BASE + 0x00000018)
+#define CIF_ISP_HIST_BIN_2		(CIF_ISP_HIST_BASE + 0x0000001C)
+#define CIF_ISP_HIST_BIN_3		(CIF_ISP_HIST_BASE + 0x00000020)
+#define CIF_ISP_HIST_BIN_4		(CIF_ISP_HIST_BASE + 0x00000024)
+#define CIF_ISP_HIST_BIN_5		(CIF_ISP_HIST_BASE + 0x00000028)
+#define CIF_ISP_HIST_BIN_6		(CIF_ISP_HIST_BASE + 0x0000002C)
+#define CIF_ISP_HIST_BIN_7		(CIF_ISP_HIST_BASE + 0x00000030)
+#define CIF_ISP_HIST_BIN_8		(CIF_ISP_HIST_BASE + 0x00000034)
+#define CIF_ISP_HIST_BIN_9		(CIF_ISP_HIST_BASE + 0x00000038)
+#define CIF_ISP_HIST_BIN_10		(CIF_ISP_HIST_BASE + 0x0000003C)
+#define CIF_ISP_HIST_BIN_11		(CIF_ISP_HIST_BASE + 0x00000040)
+#define CIF_ISP_HIST_BIN_12		(CIF_ISP_HIST_BASE + 0x00000044)
+#define CIF_ISP_HIST_BIN_13		(CIF_ISP_HIST_BASE + 0x00000048)
+#define CIF_ISP_HIST_BIN_14		(CIF_ISP_HIST_BASE + 0x0000004C)
+#define CIF_ISP_HIST_BIN_15		(CIF_ISP_HIST_BASE + 0x00000050)
+#define CIF_ISP_HIST_WEIGHT_00TO30	(CIF_ISP_HIST_BASE + 0x00000054)
+#define CIF_ISP_HIST_WEIGHT_40TO21	(CIF_ISP_HIST_BASE + 0x00000058)
+#define CIF_ISP_HIST_WEIGHT_31TO12	(CIF_ISP_HIST_BASE + 0x0000005C)
+#define CIF_ISP_HIST_WEIGHT_22TO03	(CIF_ISP_HIST_BASE + 0x00000060)
+#define CIF_ISP_HIST_WEIGHT_13TO43	(CIF_ISP_HIST_BASE + 0x00000064)
+#define CIF_ISP_HIST_WEIGHT_04TO34	(CIF_ISP_HIST_BASE + 0x00000068)
+#define CIF_ISP_HIST_WEIGHT_44		(CIF_ISP_HIST_BASE + 0x0000006C)
+
+#define CIF_ISP_FILT_BASE		0x00002500
+#define CIF_ISP_FILT_MODE		(CIF_ISP_FILT_BASE + 0x00000000)
+#define CIF_ISP_FILT_THRESH_BL0		(CIF_ISP_FILT_BASE + 0x00000028)
+#define CIF_ISP_FILT_THRESH_BL1		(CIF_ISP_FILT_BASE + 0x0000002c)
+#define CIF_ISP_FILT_THRESH_SH0		(CIF_ISP_FILT_BASE + 0x00000030)
+#define CIF_ISP_FILT_THRESH_SH1		(CIF_ISP_FILT_BASE + 0x00000034)
+#define CIF_ISP_FILT_LUM_WEIGHT		(CIF_ISP_FILT_BASE + 0x00000038)
+#define CIF_ISP_FILT_FAC_SH1		(CIF_ISP_FILT_BASE + 0x0000003c)
+#define CIF_ISP_FILT_FAC_SH0		(CIF_ISP_FILT_BASE + 0x00000040)
+#define CIF_ISP_FILT_FAC_MID		(CIF_ISP_FILT_BASE + 0x00000044)
+#define CIF_ISP_FILT_FAC_BL0		(CIF_ISP_FILT_BASE + 0x00000048)
+#define CIF_ISP_FILT_FAC_BL1		(CIF_ISP_FILT_BASE + 0x0000004C)
+
+#define CIF_ISP_CAC_BASE		0x00002580
+#define CIF_ISP_CAC_CTRL		(CIF_ISP_CAC_BASE + 0x00000000)
+#define CIF_ISP_CAC_COUNT_START		(CIF_ISP_CAC_BASE + 0x00000004)
+#define CIF_ISP_CAC_A			(CIF_ISP_CAC_BASE + 0x00000008)
+#define CIF_ISP_CAC_B			(CIF_ISP_CAC_BASE + 0x0000000C)
+#define CIF_ISP_CAC_C			(CIF_ISP_CAC_BASE + 0x00000010)
+#define CIF_ISP_X_NORM			(CIF_ISP_CAC_BASE + 0x00000014)
+#define CIF_ISP_Y_NORM			(CIF_ISP_CAC_BASE + 0x00000018)
+
+#define CIF_ISP_EXP_BASE		0x00002600
+#define CIF_ISP_EXP_CTRL		(CIF_ISP_EXP_BASE + 0x00000000)
+#define CIF_ISP_EXP_H_OFFSET		(CIF_ISP_EXP_BASE + 0x00000004)
+#define CIF_ISP_EXP_V_OFFSET		(CIF_ISP_EXP_BASE + 0x00000008)
+#define CIF_ISP_EXP_H_SIZE		(CIF_ISP_EXP_BASE + 0x0000000C)
+#define CIF_ISP_EXP_V_SIZE		(CIF_ISP_EXP_BASE + 0x00000010)
+#define CIF_ISP_EXP_MEAN_00		(CIF_ISP_EXP_BASE + 0x00000014)
+#define CIF_ISP_EXP_MEAN_10		(CIF_ISP_EXP_BASE + 0x00000018)
+#define CIF_ISP_EXP_MEAN_20		(CIF_ISP_EXP_BASE + 0x0000001c)
+#define CIF_ISP_EXP_MEAN_30		(CIF_ISP_EXP_BASE + 0x00000020)
+#define CIF_ISP_EXP_MEAN_40		(CIF_ISP_EXP_BASE + 0x00000024)
+#define CIF_ISP_EXP_MEAN_01		(CIF_ISP_EXP_BASE + 0x00000028)
+#define CIF_ISP_EXP_MEAN_11		(CIF_ISP_EXP_BASE + 0x0000002c)
+#define CIF_ISP_EXP_MEAN_21		(CIF_ISP_EXP_BASE + 0x00000030)
+#define CIF_ISP_EXP_MEAN_31		(CIF_ISP_EXP_BASE + 0x00000034)
+#define CIF_ISP_EXP_MEAN_41		(CIF_ISP_EXP_BASE + 0x00000038)
+#define CIF_ISP_EXP_MEAN_02		(CIF_ISP_EXP_BASE + 0x0000003c)
+#define CIF_ISP_EXP_MEAN_12		(CIF_ISP_EXP_BASE + 0x00000040)
+#define CIF_ISP_EXP_MEAN_22		(CIF_ISP_EXP_BASE + 0x00000044)
+#define CIF_ISP_EXP_MEAN_32		(CIF_ISP_EXP_BASE + 0x00000048)
+#define CIF_ISP_EXP_MEAN_42		(CIF_ISP_EXP_BASE + 0x0000004c)
+#define CIF_ISP_EXP_MEAN_03		(CIF_ISP_EXP_BASE + 0x00000050)
+#define CIF_ISP_EXP_MEAN_13		(CIF_ISP_EXP_BASE + 0x00000054)
+#define CIF_ISP_EXP_MEAN_23		(CIF_ISP_EXP_BASE + 0x00000058)
+#define CIF_ISP_EXP_MEAN_33		(CIF_ISP_EXP_BASE + 0x0000005c)
+#define CIF_ISP_EXP_MEAN_43		(CIF_ISP_EXP_BASE + 0x00000060)
+#define CIF_ISP_EXP_MEAN_04		(CIF_ISP_EXP_BASE + 0x00000064)
+#define CIF_ISP_EXP_MEAN_14		(CIF_ISP_EXP_BASE + 0x00000068)
+#define CIF_ISP_EXP_MEAN_24		(CIF_ISP_EXP_BASE + 0x0000006c)
+#define CIF_ISP_EXP_MEAN_34		(CIF_ISP_EXP_BASE + 0x00000070)
+#define CIF_ISP_EXP_MEAN_44		(CIF_ISP_EXP_BASE + 0x00000074)
+
+#define CIF_ISP_BLS_BASE		0x00002700
+#define CIF_ISP_BLS_CTRL		(CIF_ISP_BLS_BASE + 0x00000000)
+#define CIF_ISP_BLS_SAMPLES		(CIF_ISP_BLS_BASE + 0x00000004)
+#define CIF_ISP_BLS_H1_START		(CIF_ISP_BLS_BASE + 0x00000008)
+#define CIF_ISP_BLS_H1_STOP		(CIF_ISP_BLS_BASE + 0x0000000c)
+#define CIF_ISP_BLS_V1_START		(CIF_ISP_BLS_BASE + 0x00000010)
+#define CIF_ISP_BLS_V1_STOP		(CIF_ISP_BLS_BASE + 0x00000014)
+#define CIF_ISP_BLS_H2_START		(CIF_ISP_BLS_BASE + 0x00000018)
+#define CIF_ISP_BLS_H2_STOP		(CIF_ISP_BLS_BASE + 0x0000001c)
+#define CIF_ISP_BLS_V2_START		(CIF_ISP_BLS_BASE + 0x00000020)
+#define CIF_ISP_BLS_V2_STOP		(CIF_ISP_BLS_BASE + 0x00000024)
+#define CIF_ISP_BLS_A_FIXED		(CIF_ISP_BLS_BASE + 0x00000028)
+#define CIF_ISP_BLS_B_FIXED		(CIF_ISP_BLS_BASE + 0x0000002c)
+#define CIF_ISP_BLS_C_FIXED		(CIF_ISP_BLS_BASE + 0x00000030)
+#define CIF_ISP_BLS_D_FIXED		(CIF_ISP_BLS_BASE + 0x00000034)
+#define CIF_ISP_BLS_A_MEASURED		(CIF_ISP_BLS_BASE + 0x00000038)
+#define CIF_ISP_BLS_B_MEASURED		(CIF_ISP_BLS_BASE + 0x0000003c)
+#define CIF_ISP_BLS_C_MEASURED		(CIF_ISP_BLS_BASE + 0x00000040)
+#define CIF_ISP_BLS_D_MEASURED		(CIF_ISP_BLS_BASE + 0x00000044)
+
+#define CIF_ISP_DPF_BASE		0x00002800
+#define CIF_ISP_DPF_MODE		(CIF_ISP_DPF_BASE + 0x00000000)
+#define CIF_ISP_DPF_STRENGTH_R		(CIF_ISP_DPF_BASE + 0x00000004)
+#define CIF_ISP_DPF_STRENGTH_G		(CIF_ISP_DPF_BASE + 0x00000008)
+#define CIF_ISP_DPF_STRENGTH_B		(CIF_ISP_DPF_BASE + 0x0000000C)
+#define CIF_ISP_DPF_S_WEIGHT_G_1_4	(CIF_ISP_DPF_BASE + 0x00000010)
+#define CIF_ISP_DPF_S_WEIGHT_G_5_6	(CIF_ISP_DPF_BASE + 0x00000014)
+#define CIF_ISP_DPF_S_WEIGHT_RB_1_4	(CIF_ISP_DPF_BASE + 0x00000018)
+#define CIF_ISP_DPF_S_WEIGHT_RB_5_6	(CIF_ISP_DPF_BASE + 0x0000001C)
+#define CIF_ISP_DPF_NULL_COEFF_0	(CIF_ISP_DPF_BASE + 0x00000020)
+#define CIF_ISP_DPF_NULL_COEFF_1	(CIF_ISP_DPF_BASE + 0x00000024)
+#define CIF_ISP_DPF_NULL_COEFF_2	(CIF_ISP_DPF_BASE + 0x00000028)
+#define CIF_ISP_DPF_NULL_COEFF_3	(CIF_ISP_DPF_BASE + 0x0000002C)
+#define CIF_ISP_DPF_NULL_COEFF_4	(CIF_ISP_DPF_BASE + 0x00000030)
+#define CIF_ISP_DPF_NULL_COEFF_5	(CIF_ISP_DPF_BASE + 0x00000034)
+#define CIF_ISP_DPF_NULL_COEFF_6	(CIF_ISP_DPF_BASE + 0x00000038)
+#define CIF_ISP_DPF_NULL_COEFF_7	(CIF_ISP_DPF_BASE + 0x0000003C)
+#define CIF_ISP_DPF_NULL_COEFF_8	(CIF_ISP_DPF_BASE + 0x00000040)
+#define CIF_ISP_DPF_NULL_COEFF_9	(CIF_ISP_DPF_BASE + 0x00000044)
+#define CIF_ISP_DPF_NULL_COEFF_10	(CIF_ISP_DPF_BASE + 0x00000048)
+#define CIF_ISP_DPF_NULL_COEFF_11	(CIF_ISP_DPF_BASE + 0x0000004C)
+#define CIF_ISP_DPF_NULL_COEFF_12	(CIF_ISP_DPF_BASE + 0x00000050)
+#define CIF_ISP_DPF_NULL_COEFF_13	(CIF_ISP_DPF_BASE + 0x00000054)
+#define CIF_ISP_DPF_NULL_COEFF_14	(CIF_ISP_DPF_BASE + 0x00000058)
+#define CIF_ISP_DPF_NULL_COEFF_15	(CIF_ISP_DPF_BASE + 0x0000005C)
+#define CIF_ISP_DPF_NULL_COEFF_16	(CIF_ISP_DPF_BASE + 0x00000060)
+#define CIF_ISP_DPF_NF_GAIN_R		(CIF_ISP_DPF_BASE + 0x00000064)
+#define CIF_ISP_DPF_NF_GAIN_GR		(CIF_ISP_DPF_BASE + 0x00000068)
+#define CIF_ISP_DPF_NF_GAIN_GB		(CIF_ISP_DPF_BASE + 0x0000006C)
+#define CIF_ISP_DPF_NF_GAIN_B		(CIF_ISP_DPF_BASE + 0x00000070)
+
+#define CIF_ISP_DPCC_BASE		0x00002900
+#define CIF_ISP_DPCC_MODE		(CIF_ISP_DPCC_BASE + 0x00000000)
+#define CIF_ISP_DPCC_OUTPUT_MODE	(CIF_ISP_DPCC_BASE + 0x00000004)
+#define CIF_ISP_DPCC_SET_USE		(CIF_ISP_DPCC_BASE + 0x00000008)
+#define CIF_ISP_DPCC_METHODS_SET_1	(CIF_ISP_DPCC_BASE + 0x0000000C)
+#define CIF_ISP_DPCC_METHODS_SET_2	(CIF_ISP_DPCC_BASE + 0x00000010)
+#define CIF_ISP_DPCC_METHODS_SET_3	(CIF_ISP_DPCC_BASE + 0x00000014)
+#define CIF_ISP_DPCC_LINE_THRESH_1	(CIF_ISP_DPCC_BASE + 0x00000018)
+#define CIF_ISP_DPCC_LINE_MAD_FAC_1	(CIF_ISP_DPCC_BASE + 0x0000001C)
+#define CIF_ISP_DPCC_PG_FAC_1		(CIF_ISP_DPCC_BASE + 0x00000020)
+#define CIF_ISP_DPCC_RND_THRESH_1	(CIF_ISP_DPCC_BASE + 0x00000024)
+#define CIF_ISP_DPCC_RG_FAC_1		(CIF_ISP_DPCC_BASE + 0x00000028)
+#define CIF_ISP_DPCC_LINE_THRESH_2	(CIF_ISP_DPCC_BASE + 0x0000002C)
+#define CIF_ISP_DPCC_LINE_MAD_FAC_2	(CIF_ISP_DPCC_BASE + 0x00000030)
+#define CIF_ISP_DPCC_PG_FAC_2		(CIF_ISP_DPCC_BASE + 0x00000034)
+#define CIF_ISP_DPCC_RND_THRESH_2	(CIF_ISP_DPCC_BASE + 0x00000038)
+#define CIF_ISP_DPCC_RG_FAC_2		(CIF_ISP_DPCC_BASE + 0x0000003C)
+#define CIF_ISP_DPCC_LINE_THRESH_3	(CIF_ISP_DPCC_BASE + 0x00000040)
+#define CIF_ISP_DPCC_LINE_MAD_FAC_3	(CIF_ISP_DPCC_BASE + 0x00000044)
+#define CIF_ISP_DPCC_PG_FAC_3		(CIF_ISP_DPCC_BASE + 0x00000048)
+#define CIF_ISP_DPCC_RND_THRESH_3	(CIF_ISP_DPCC_BASE + 0x0000004C)
+#define CIF_ISP_DPCC_RG_FAC_3		(CIF_ISP_DPCC_BASE + 0x00000050)
+#define CIF_ISP_DPCC_RO_LIMITS		(CIF_ISP_DPCC_BASE + 0x00000054)
+#define CIF_ISP_DPCC_RND_OFFS		(CIF_ISP_DPCC_BASE + 0x00000058)
+#define CIF_ISP_DPCC_BPT_CTRL		(CIF_ISP_DPCC_BASE + 0x0000005C)
+#define CIF_ISP_DPCC_BPT_NUMBER		(CIF_ISP_DPCC_BASE + 0x00000060)
+#define CIF_ISP_DPCC_BPT_ADDR		(CIF_ISP_DPCC_BASE + 0x00000064)
+#define CIF_ISP_DPCC_BPT_DATA		(CIF_ISP_DPCC_BASE + 0x00000068)
+
+#define CIF_ISP_WDR_BASE		0x00002A00
+#define CIF_ISP_WDR_CTRL		(CIF_ISP_WDR_BASE + 0x00000000)
+#define CIF_ISP_WDR_TONECURVE_1		(CIF_ISP_WDR_BASE + 0x00000004)
+#define CIF_ISP_WDR_TONECURVE_2		(CIF_ISP_WDR_BASE + 0x00000008)
+#define CIF_ISP_WDR_TONECURVE_3		(CIF_ISP_WDR_BASE + 0x0000000C)
+#define CIF_ISP_WDR_TONECURVE_4		(CIF_ISP_WDR_BASE + 0x00000010)
+#define CIF_ISP_WDR_TONECURVE_YM_0	(CIF_ISP_WDR_BASE + 0x00000014)
+#define CIF_ISP_WDR_TONECURVE_YM_1	(CIF_ISP_WDR_BASE + 0x00000018)
+#define CIF_ISP_WDR_TONECURVE_YM_2	(CIF_ISP_WDR_BASE + 0x0000001C)
+#define CIF_ISP_WDR_TONECURVE_YM_3	(CIF_ISP_WDR_BASE + 0x00000020)
+#define CIF_ISP_WDR_TONECURVE_YM_4	(CIF_ISP_WDR_BASE + 0x00000024)
+#define CIF_ISP_WDR_TONECURVE_YM_5	(CIF_ISP_WDR_BASE + 0x00000028)
+#define CIF_ISP_WDR_TONECURVE_YM_6	(CIF_ISP_WDR_BASE + 0x0000002C)
+#define CIF_ISP_WDR_TONECURVE_YM_7	(CIF_ISP_WDR_BASE + 0x00000030)
+#define CIF_ISP_WDR_TONECURVE_YM_8	(CIF_ISP_WDR_BASE + 0x00000034)
+#define CIF_ISP_WDR_TONECURVE_YM_9	(CIF_ISP_WDR_BASE + 0x00000038)
+#define CIF_ISP_WDR_TONECURVE_YM_10	(CIF_ISP_WDR_BASE + 0x0000003C)
+#define CIF_ISP_WDR_TONECURVE_YM_11	(CIF_ISP_WDR_BASE + 0x00000040)
+#define CIF_ISP_WDR_TONECURVE_YM_12	(CIF_ISP_WDR_BASE + 0x00000044)
+#define CIF_ISP_WDR_TONECURVE_YM_13	(CIF_ISP_WDR_BASE + 0x00000048)
+#define CIF_ISP_WDR_TONECURVE_YM_14	(CIF_ISP_WDR_BASE + 0x0000004C)
+#define CIF_ISP_WDR_TONECURVE_YM_15	(CIF_ISP_WDR_BASE + 0x00000050)
+#define CIF_ISP_WDR_TONECURVE_YM_16	(CIF_ISP_WDR_BASE + 0x00000054)
+#define CIF_ISP_WDR_TONECURVE_YM_17	(CIF_ISP_WDR_BASE + 0x00000058)
+#define CIF_ISP_WDR_TONECURVE_YM_18	(CIF_ISP_WDR_BASE + 0x0000005C)
+#define CIF_ISP_WDR_TONECURVE_YM_19	(CIF_ISP_WDR_BASE + 0x00000060)
+#define CIF_ISP_WDR_TONECURVE_YM_20	(CIF_ISP_WDR_BASE + 0x00000064)
+#define CIF_ISP_WDR_TONECURVE_YM_21	(CIF_ISP_WDR_BASE + 0x00000068)
+#define CIF_ISP_WDR_TONECURVE_YM_22	(CIF_ISP_WDR_BASE + 0x0000006C)
+#define CIF_ISP_WDR_TONECURVE_YM_23	(CIF_ISP_WDR_BASE + 0x00000070)
+#define CIF_ISP_WDR_TONECURVE_YM_24	(CIF_ISP_WDR_BASE + 0x00000074)
+#define CIF_ISP_WDR_TONECURVE_YM_25	(CIF_ISP_WDR_BASE + 0x00000078)
+#define CIF_ISP_WDR_TONECURVE_YM_26	(CIF_ISP_WDR_BASE + 0x0000007C)
+#define CIF_ISP_WDR_TONECURVE_YM_27	(CIF_ISP_WDR_BASE + 0x00000080)
+#define CIF_ISP_WDR_TONECURVE_YM_28	(CIF_ISP_WDR_BASE + 0x00000084)
+#define CIF_ISP_WDR_TONECURVE_YM_29	(CIF_ISP_WDR_BASE + 0x00000088)
+#define CIF_ISP_WDR_TONECURVE_YM_30	(CIF_ISP_WDR_BASE + 0x0000008C)
+#define CIF_ISP_WDR_TONECURVE_YM_31	(CIF_ISP_WDR_BASE + 0x00000090)
+#define CIF_ISP_WDR_TONECURVE_YM_32	(CIF_ISP_WDR_BASE + 0x00000094)
+#define CIF_ISP_WDR_OFFSET		(CIF_ISP_WDR_BASE + 0x00000098)
+#define CIF_ISP_WDR_DELTAMIN		(CIF_ISP_WDR_BASE + 0x0000009C)
+#define CIF_ISP_WDR_TONECURVE_1_SHD	(CIF_ISP_WDR_BASE + 0x000000A0)
+#define CIF_ISP_WDR_TONECURVE_2_SHD	(CIF_ISP_WDR_BASE + 0x000000A4)
+#define CIF_ISP_WDR_TONECURVE_3_SHD	(CIF_ISP_WDR_BASE + 0x000000A8)
+#define CIF_ISP_WDR_TONECURVE_4_SHD	(CIF_ISP_WDR_BASE + 0x000000AC)
+#define CIF_ISP_WDR_TONECURVE_YM_0_SHD	(CIF_ISP_WDR_BASE + 0x000000B0)
+#define CIF_ISP_WDR_TONECURVE_YM_1_SHD	(CIF_ISP_WDR_BASE + 0x000000B4)
+#define CIF_ISP_WDR_TONECURVE_YM_2_SHD	(CIF_ISP_WDR_BASE + 0x000000B8)
+#define CIF_ISP_WDR_TONECURVE_YM_3_SHD	(CIF_ISP_WDR_BASE + 0x000000BC)
+#define CIF_ISP_WDR_TONECURVE_YM_4_SHD	(CIF_ISP_WDR_BASE + 0x000000C0)
+#define CIF_ISP_WDR_TONECURVE_YM_5_SHD	(CIF_ISP_WDR_BASE + 0x000000C4)
+#define CIF_ISP_WDR_TONECURVE_YM_6_SHD	(CIF_ISP_WDR_BASE + 0x000000C8)
+#define CIF_ISP_WDR_TONECURVE_YM_7_SHD	(CIF_ISP_WDR_BASE + 0x000000CC)
+#define CIF_ISP_WDR_TONECURVE_YM_8_SHD	(CIF_ISP_WDR_BASE + 0x000000D0)
+#define CIF_ISP_WDR_TONECURVE_YM_9_SHD	(CIF_ISP_WDR_BASE + 0x000000D4)
+#define CIF_ISP_WDR_TONECURVE_YM_10_SHD	(CIF_ISP_WDR_BASE + 0x000000D8)
+#define CIF_ISP_WDR_TONECURVE_YM_11_SHD	(CIF_ISP_WDR_BASE + 0x000000DC)
+#define CIF_ISP_WDR_TONECURVE_YM_12_SHD	(CIF_ISP_WDR_BASE + 0x000000E0)
+#define CIF_ISP_WDR_TONECURVE_YM_13_SHD	(CIF_ISP_WDR_BASE + 0x000000E4)
+#define CIF_ISP_WDR_TONECURVE_YM_14_SHD	(CIF_ISP_WDR_BASE + 0x000000E8)
+#define CIF_ISP_WDR_TONECURVE_YM_15_SHD	(CIF_ISP_WDR_BASE + 0x000000EC)
+#define CIF_ISP_WDR_TONECURVE_YM_16_SHD	(CIF_ISP_WDR_BASE + 0x000000F0)
+#define CIF_ISP_WDR_TONECURVE_YM_17_SHD	(CIF_ISP_WDR_BASE + 0x000000F4)
+#define CIF_ISP_WDR_TONECURVE_YM_18_SHD	(CIF_ISP_WDR_BASE + 0x000000F8)
+#define CIF_ISP_WDR_TONECURVE_YM_19_SHD	(CIF_ISP_WDR_BASE + 0x000000FC)
+#define CIF_ISP_WDR_TONECURVE_YM_20_SHD	(CIF_ISP_WDR_BASE + 0x00000100)
+#define CIF_ISP_WDR_TONECURVE_YM_21_SHD	(CIF_ISP_WDR_BASE + 0x00000104)
+#define CIF_ISP_WDR_TONECURVE_YM_22_SHD	(CIF_ISP_WDR_BASE + 0x00000108)
+#define CIF_ISP_WDR_TONECURVE_YM_23_SHD	(CIF_ISP_WDR_BASE + 0x0000010C)
+#define CIF_ISP_WDR_TONECURVE_YM_24_SHD	(CIF_ISP_WDR_BASE + 0x00000110)
+#define CIF_ISP_WDR_TONECURVE_YM_25_SHD	(CIF_ISP_WDR_BASE + 0x00000114)
+#define CIF_ISP_WDR_TONECURVE_YM_26_SHD	(CIF_ISP_WDR_BASE + 0x00000118)
+#define CIF_ISP_WDR_TONECURVE_YM_27_SHD	(CIF_ISP_WDR_BASE + 0x0000011C)
+#define CIF_ISP_WDR_TONECURVE_YM_28_SHD	(CIF_ISP_WDR_BASE + 0x00000120)
+#define CIF_ISP_WDR_TONECURVE_YM_29_SHD	(CIF_ISP_WDR_BASE + 0x00000124)
+#define CIF_ISP_WDR_TONECURVE_YM_30_SHD	(CIF_ISP_WDR_BASE + 0x00000128)
+#define CIF_ISP_WDR_TONECURVE_YM_31_SHD	(CIF_ISP_WDR_BASE + 0x0000012C)
+#define CIF_ISP_WDR_TONECURVE_YM_32_SHD	(CIF_ISP_WDR_BASE + 0x00000130)
+
+#define CIF_ISP_VSM_BASE		0x00002F00
+#define CIF_ISP_VSM_MODE		(CIF_ISP_VSM_BASE + 0x00000000)
+#define CIF_ISP_VSM_H_OFFS		(CIF_ISP_VSM_BASE + 0x00000004)
+#define CIF_ISP_VSM_V_OFFS		(CIF_ISP_VSM_BASE + 0x00000008)
+#define CIF_ISP_VSM_H_SIZE		(CIF_ISP_VSM_BASE + 0x0000000C)
+#define CIF_ISP_VSM_V_SIZE		(CIF_ISP_VSM_BASE + 0x00000010)
+#define CIF_ISP_VSM_H_SEGMENTS		(CIF_ISP_VSM_BASE + 0x00000014)
+#define CIF_ISP_VSM_V_SEGMENTS		(CIF_ISP_VSM_BASE + 0x00000018)
+#define CIF_ISP_VSM_DELTA_H		(CIF_ISP_VSM_BASE + 0x0000001C)
+#define CIF_ISP_VSM_DELTA_V		(CIF_ISP_VSM_BASE + 0x00000020)
+
+void disable_dcrop(struct rkisp1_stream *stream, bool async);
+void config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect,
+		  bool async);
+
+void dump_rsz_regs(struct rkisp1_stream *stream);
+void disable_rsz(struct rkisp1_stream *stream, bool async);
+void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
+		struct v4l2_rect *in_c, struct v4l2_rect *out_y,
+		struct v4l2_rect *out_c, bool async);
+
+void config_mi_ctrl(struct rkisp1_stream *stream);
+
+void mp_clr_frame_end_int(void __iomem *base);
+void sp_clr_frame_end_int(void __iomem *base);
+
+bool mp_is_frame_end_int_masked(void __iomem *base);
+bool sp_is_frame_end_int_masked(void __iomem *base);
+bool mp_is_stream_stopped(void __iomem *base);
+bool sp_is_stream_stopped(void __iomem *base);
+
+static inline void mi_set_y_size(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.y_size_init);
+}
+
+static inline void mi_set_cb_size(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.cb_size_init);
+}
+
+static inline void mi_set_cr_size(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.cr_size_init);
+}
+
+static inline void mi_set_y_addr(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.y_base_ad_init);
+}
+
+static inline void mi_set_cb_addr(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.cb_base_ad_init);
+}
+
+static inline void mi_set_cr_addr(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.cr_base_ad_init);
+}
+
+static inline void mi_set_y_offset(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.y_offs_cnt_init);
+}
+
+static inline void mi_set_cb_offset(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.cb_offs_cnt_init);
+}
+
+static inline void mi_set_cr_offset(struct rkisp1_stream *stream, int val)
+{
+	void __iomem *base = stream->ispdev->base_addr;
+
+	writel(val, base + stream->config->mi.cr_offs_cnt_init);
+}
+
+static inline void mp_set_chain_mode(void __iomem *base)
+{
+	u32 dpcl = readl(base + CIF_VI_DPCL);
+
+	dpcl |= CIF_VI_DPCL_CHAN_MODE_MP;
+	writel(dpcl, base + CIF_VI_DPCL);
+}
+
+static inline void sp_set_chain_mode(void __iomem *base)
+{
+	u32 dpcl = readl(base + CIF_VI_DPCL);
+
+	dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
+	writel(dpcl, base + CIF_VI_DPCL);
+}
+
+static inline void mp_set_data_path(void __iomem *base)
+{
+	u32 dpcl = readl(base + CIF_VI_DPCL);
+
+	dpcl = dpcl | CIF_VI_DPCL_CHAN_MODE_MP | CIF_VI_DPCL_MP_MUX_MRSZ_MI;
+	writel(dpcl, base + CIF_VI_DPCL);
+}
+
+static inline void sp_set_data_path(void __iomem *base)
+{
+	u32 dpcl = readl(base + CIF_VI_DPCL);
+
+	dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
+	writel(dpcl, base + CIF_VI_DPCL);
+}
+
+static inline void mp_frame_end_int_enable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_IMSC;
+
+	writel(CIF_MI_MP_FRAME | readl(addr), addr);
+}
+
+static inline void sp_frame_end_int_enable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_IMSC;
+
+	writel(CIF_MI_SP_FRAME | readl(addr), addr);
+}
+
+static inline void mp_frame_end_int_disable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_IMSC;
+
+	writel(~CIF_MI_MP_FRAME & readl(addr), addr);
+}
+
+static inline void sp_frame_end_int_disable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_IMSC;
+
+	writel(~CIF_MI_SP_FRAME & readl(addr), addr);
+}
+
+static inline void clr_mpsp_frame_end_int(void __iomem *base)
+{
+	writel(CIF_MI_SP_FRAME | CIF_MI_MP_FRAME, base + CIF_MI_ICR);
+}
+
+static inline void clr_mp_crop_rsz_int(void __iomem *base)
+{
+	writel(~CIF_MI_MP_FRAME, base + CIF_MI_ICR);
+}
+
+static inline void clr_sp_crop_rsz_int(void __iomem *base)
+{
+	writel(~CIF_MI_SP_FRAME, base + CIF_MI_ICR);
+}
+
+static inline void clr_all_int(void __iomem *base)
+{
+	writel(~0, base + CIF_MI_ICR);
+}
+
+static inline void mp_set_uv_swap(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_XTD_FORMAT_CTRL;
+	u32 reg = readl(addr) & ~BIT(0);
+
+	writel(reg | CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP, addr);
+}
+
+static inline void sp_set_uv_swap(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_XTD_FORMAT_CTRL;
+	u32 reg = readl(addr) & ~BIT(1);
+
+	writel(reg | CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP, addr);
+}
+
+static inline void sp_set_y_width(void __iomem *base, u32 val)
+{
+	writel(val, base + CIF_MI_SP_Y_PIC_WIDTH);
+}
+
+static inline void sp_set_y_height(void __iomem *base, u32 val)
+{
+	writel(val, base + CIF_MI_SP_Y_PIC_HEIGHT);
+}
+
+static inline void sp_set_y_line_length(void __iomem *base, u32 val)
+{
+	writel(val, base + CIF_MI_SP_Y_LLENGTH);
+}
+
+static inline void mp_mi_ctrl_set_format(void __iomem *base, u32 val)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+	u32 reg = readl(addr) & ~MI_CTRL_MP_FMT_MASK;
+
+	writel(reg | val, addr);
+}
+
+static inline void sp_mi_ctrl_set_format(void __iomem *base, u32 val)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+	u32 reg = readl(addr) & ~MI_CTRL_SP_FMT_MASK;
+
+	writel(reg | val, addr);
+}
+
+static inline void mi_ctrl_mpyuv_enable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(CIF_MI_CTRL_MP_ENABLE | readl(addr), addr);
+}
+
+static inline void mi_ctrl_mpyuv_disable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(~CIF_MI_CTRL_MP_ENABLE & readl(addr), addr);
+}
+
+static inline void mi_ctrl_mp_disable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(~(CIF_MI_CTRL_MP_ENABLE | CIF_MI_CTRL_RAW_ENABLE) & readl(addr),
+	       addr);
+}
+
+static inline void mi_ctrl_spyuv_enable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(CIF_MI_CTRL_SP_ENABLE | readl(addr), addr);
+}
+
+static inline void mi_ctrl_spyuv_disable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(~CIF_MI_CTRL_SP_ENABLE & readl(addr), addr);
+}
+
+static inline void mi_ctrl_sp_disable(void __iomem *base)
+{
+	mi_ctrl_spyuv_disable(base);
+}
+
+static inline void mi_ctrl_mpraw_enable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(CIF_MI_CTRL_RAW_ENABLE | readl(addr), addr);
+}
+
+static inline void mi_ctrl_mpraw_disable(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(~CIF_MI_CTRL_RAW_ENABLE & readl(addr), addr);
+}
+
+static inline void mp_mi_ctrl_autoupdate_en(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(readl(addr) | CIF_MI_MP_AUTOUPDATE_ENABLE, addr);
+}
+
+static inline void sp_mi_ctrl_autoupdate_en(void __iomem *base)
+{
+	void __iomem *addr = base + CIF_MI_CTRL;
+
+	writel(readl(addr) | CIF_MI_SP_AUTOUPDATE_ENABLE, addr);
+}
+
+static inline void force_cfg_update(void __iomem *base)
+{
+	writel(CIF_MI_INIT_SOFT_UPD, base + CIF_MI_INIT);
+}
+
+static inline u32 mi_get_masked_int_status(void __iomem *base)
+{
+	return readl(base + CIF_MI_MIS);
+}
+
+#endif /* _RKISP1_REGS_H */
diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.c b/drivers/media/platform/rockchip/isp1/rkisp1.c
new file mode 100644
index 000000000000..7ce98b80f447
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/rkisp1.c
@@ -0,0 +1,1201 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/iopoll.h>
+#include <linux/pm_runtime.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <media/v4l2-event.h>
+
+#include "common.h"
+#include "regs.h"
+
+#define CIF_ISP_INPUT_W_MAX		4032
+#define CIF_ISP_INPUT_H_MAX		3024
+#define CIF_ISP_INPUT_W_MIN		32
+#define CIF_ISP_INPUT_H_MIN		32
+#define CIF_ISP_OUTPUT_W_MAX		CIF_ISP_INPUT_W_MAX
+#define CIF_ISP_OUTPUT_H_MAX		CIF_ISP_INPUT_H_MAX
+#define CIF_ISP_OUTPUT_W_MIN		CIF_ISP_INPUT_W_MIN
+#define CIF_ISP_OUTPUT_H_MIN		CIF_ISP_INPUT_H_MIN
+
+/*
+ * NOTE: MIPI controller and input MUX are also configured in this file,
+ * because ISP Subdev is not only describe ISP submodule(input size,format, output size, format),
+ * but also a virtual route device.
+ */
+
+/*
+ * There are many variables named with format/frame in below code,
+ * please see here for their meaning.
+ *
+ * Cropping regions of ISP
+ *
+ * +---------------------------------------------------------+
+ * | Sensor image                                            |
+ * | +---------------------------------------------------+   |
+ * | | ISP_ACQ (for black level)                         |   |
+ * | | in_frm                                            |   |
+ * | | +--------------------------------------------+    |   |
+ * | | |    ISP_OUT                                 |    |   |
+ * | | |    in_crop                                 |    |   |
+ * | | |    +---------------------------------+     |    |   |
+ * | | |    |   ISP_IS                        |     |    |   |
+ * | | |    |   rkisp1_isp_subdev: out_crop   |     |    |   |
+ * | | |    +---------------------------------+     |    |   |
+ * | | +--------------------------------------------+    |   |
+ * | +---------------------------------------------------+   |
+ * +---------------------------------------------------------+
+ */
+
+static inline struct rkisp1_device *sd_to_isp_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev);
+}
+
+/* Get sensor by enabled media link */
+static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
+{
+	struct media_pad *local;
+	struct media_entity *sensor_me;
+
+	local = &sd->entity.pads[RKISP1_ISP_PAD_SINK];
+	sensor_me = media_entity_remote_pad(local)->entity;
+
+	return media_entity_to_v4l2_subdev(sensor_me);
+}
+
+static struct rkisp1_sensor_info *sd_to_sensor(struct rkisp1_device *dev,
+					       struct v4l2_subdev *sd)
+{
+	int i;
+
+	for (i = 0; i < dev->num_sensors; ++i)
+		if (dev->sensors[i].sd == sd)
+			return &dev->sensors[i];
+
+	return NULL;
+}
+
+/****************  register operations ****************/
+
+/*
+ * Image Stabilization.
+ * This should only be called when configuring CIF
+ * or at the frame end interrupt
+ */
+static void rkisp1_config_ism(struct rkisp1_device *dev)
+{
+	void __iomem *base = dev->base_addr;
+	struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop;
+	u32 val;
+
+	writel(0, base + CIF_ISP_IS_RECENTER);
+	writel(0, base + CIF_ISP_IS_MAX_DX);
+	writel(0, base + CIF_ISP_IS_MAX_DY);
+	writel(0, base + CIF_ISP_IS_DISPLACE);
+	writel(out_crop->left, base + CIF_ISP_IS_H_OFFS);
+	writel(out_crop->top, base + CIF_ISP_IS_V_OFFS);
+	writel(out_crop->width, base + CIF_ISP_IS_H_SIZE);
+	writel(out_crop->height, base + CIF_ISP_IS_V_SIZE);
+
+	/* IS(Image Stabilization) is always on, working as output crop */
+	writel(1, base + CIF_ISP_IS_CTRL);
+	val = readl(base + CIF_ISP_CTRL);
+	val |= CIF_ISP_CTRL_ISP_CFG_UPD;
+	writel(val, base + CIF_ISP_CTRL);
+}
+
+/*
+ * configure isp blocks with input format, size......
+ */
+static int rkisp1_config_isp(struct rkisp1_device *dev)
+{
+	struct ispsd_in_fmt *in_fmt;
+	struct ispsd_out_fmt *out_fmt;
+	struct v4l2_mbus_framefmt *in_frm;
+	struct v4l2_rect *out_crop, *in_crop;
+	struct rkisp1_sensor_info *sensor;
+	void __iomem *base = dev->base_addr;
+	u32 isp_ctrl = 0;
+	u32 irq_mask = 0;
+	u32 signal = 0;
+	u32 acq_mult = 0;
+	u32 val;
+
+	sensor = dev->active_sensor;
+	in_frm = &dev->isp_sdev.in_frm;
+	in_fmt = &dev->isp_sdev.in_fmt;
+	out_fmt = &dev->isp_sdev.out_fmt;
+	out_crop = &dev->isp_sdev.out_crop;
+	in_crop = &dev->isp_sdev.in_crop;
+	val = readl(base + CIF_ICCL);
+	writel(val | CIF_ICCL_ISP_CLK, base + CIF_ICCL);
+
+	if (in_fmt->fmt_type == FMT_BAYER) {
+		acq_mult = 1;
+		if (out_fmt->fmt_type == FMT_BAYER) {
+			if (sensor->mbus.type == V4L2_MBUS_BT656)
+				isp_ctrl =
+					CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656;
+			else
+				isp_ctrl =
+					CIF_ISP_CTRL_ISP_MODE_RAW_PICT;
+		} else {
+			writel(CIF_ISP_DEMOSAIC_TH(0xc),
+			       base + CIF_ISP_DEMOSAIC);
+
+			if (sensor->mbus.type == V4L2_MBUS_BT656)
+				isp_ctrl = CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656;
+			else
+				isp_ctrl = CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601;
+		}
+	} else if (in_fmt->fmt_type == FMT_YUV) {
+		acq_mult = 2;
+		if (sensor->mbus.type == V4L2_MBUS_CSI2) {
+			isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
+		} else {
+			if (sensor->mbus.type == V4L2_MBUS_BT656)
+				isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU656;
+			else
+				isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
+
+		}
+
+		irq_mask |= CIF_ISP_DATA_LOSS;
+	}
+
+	/* Set up input acquisition properties */
+	if (sensor->mbus.type == V4L2_MBUS_BT656 ||
+	    sensor->mbus.type == V4L2_MBUS_PARALLEL) {
+		if (sensor->mbus.flags &
+			V4L2_MBUS_PCLK_SAMPLE_RISING)
+			signal = CIF_ISP_ACQ_PROP_POS_EDGE;
+	}
+
+	if (sensor->mbus.type == V4L2_MBUS_PARALLEL) {
+		if (sensor->mbus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+			signal |= CIF_ISP_ACQ_PROP_VSYNC_LOW;
+
+		if (sensor->mbus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+			signal |= CIF_ISP_ACQ_PROP_HSYNC_LOW;
+	}
+
+	writel(isp_ctrl, base + CIF_ISP_CTRL);
+	writel(signal | in_fmt->yuv_seq |
+	       CIF_ISP_ACQ_PROP_BAYER_PAT(in_fmt->bayer_pat) |
+	       CIF_ISP_ACQ_PROP_FIELD_SEL_ALL, base + CIF_ISP_ACQ_PROP);
+	writel(0, base + CIF_ISP_ACQ_NR_FRAMES);
+
+	/* Acquisition Size */
+	writel(0, base + CIF_ISP_ACQ_H_OFFS);
+	writel(0, base + CIF_ISP_ACQ_V_OFFS);
+	writel(acq_mult * in_frm->width, base + CIF_ISP_ACQ_H_SIZE);
+	writel(in_frm->height, base + CIF_ISP_ACQ_V_SIZE);
+
+	/* ISP Out Area */
+	writel(in_crop->left, base + CIF_ISP_OUT_H_OFFS);
+	writel(in_crop->top, base + CIF_ISP_OUT_V_OFFS);
+	writel(in_crop->width, base + CIF_ISP_OUT_H_SIZE);
+	writel(in_crop->height, base + CIF_ISP_OUT_V_SIZE);
+
+	/* interrupt mask */
+	irq_mask |= CIF_ISP_FRAME | CIF_ISP_V_START | CIF_ISP_PIC_SIZE_ERROR |
+		    CIF_ISP_FRAME_IN;
+	writel(irq_mask, base + CIF_ISP_IMSC);
+
+	if (out_fmt->fmt_type == FMT_BAYER)
+		rkisp1_disable_isp(&dev->params_vdev);
+	else
+		rkisp1_configure_isp(&dev->params_vdev, in_fmt, 0);
+
+	return 0;
+}
+
+static int rkisp1_config_dvp(struct rkisp1_device *dev)
+{
+	struct ispsd_in_fmt *in_fmt = &dev->isp_sdev.in_fmt;
+	void __iomem *base = dev->base_addr;
+	u32 val, input_sel;
+
+	switch (in_fmt->bus_width) {
+	case 8:
+		input_sel = CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO;
+		break;
+	case 10:
+		input_sel = CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO;
+		break;
+	case 12:
+		input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
+		break;
+	default:
+		v4l2_err(&dev->v4l2_dev, "Invalid bus width\n");
+		return -EINVAL;
+	}
+
+	val = readl(base + CIF_ISP_ACQ_PROP);
+	writel(val | input_sel, base + CIF_ISP_ACQ_PROP);
+
+	return 0;
+}
+
+static int rkisp1_config_mipi(struct rkisp1_device *dev)
+{
+	u32 mipi_ctrl, val;
+	void __iomem *base = dev->base_addr;
+	struct ispsd_in_fmt *in_fmt = &dev->isp_sdev.in_fmt;
+	struct rkisp1_sensor_info *sensor = dev->active_sensor;
+	int lanes;
+
+	/*
+	 * sensor->mbus is set in isp or d-phy notifier_bound function
+	 */
+	switch (sensor->mbus.flags & V4L2_MBUS_CSI2_LANES) {
+	case V4L2_MBUS_CSI2_4_LANE:
+		lanes = 4;
+		break;
+	case V4L2_MBUS_CSI2_3_LANE:
+		lanes = 3;
+		break;
+	case V4L2_MBUS_CSI2_2_LANE:
+		lanes = 2;
+		break;
+	case V4L2_MBUS_CSI2_1_LANE:
+		lanes = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val = readl(base + CIF_ICCL);
+	writel(val | CIF_ICCL_MIPI_CLK, base + CIF_ICCL);
+
+	mipi_ctrl = CIF_MIPI_CTRL_NUM_LANES(lanes - 1) |
+		    CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) |
+		    CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP |
+		    CIF_MIPI_CTRL_CLOCKLANE_ENA;
+
+	writel(mipi_ctrl, base + CIF_MIPI_CTRL);
+
+	/* Configure Data Type and Virtual Channel */
+	writel(CIF_MIPI_DATA_SEL_DT(in_fmt->mipi_dt) | CIF_MIPI_DATA_SEL_VC(0),
+	       base + CIF_MIPI_IMG_DATA_SEL);
+
+	/* Clear MIPI interrupts */
+	writel(~0, base + CIF_MIPI_ICR);
+	/*
+	 * Disable CIF_MIPI_ERR_DPHY interrupt here temporary for
+	 * isp bus may be dead when switch isp.
+	 */
+	writel(CIF_MIPI_FRAME_END | CIF_MIPI_ERR_CSI | CIF_MIPI_ERR_DPHY |
+	       CIF_MIPI_SYNC_FIFO_OVFLW(0x03) | CIF_MIPI_ADD_DATA_OVFLW,
+	       base + CIF_MIPI_IMSC);
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "\n  MIPI_CTRL 0x%08x\n"
+		 "  MIPI_IMG_DATA_SEL 0x%08x\n"
+		 "  MIPI_STATUS 0x%08x\n"
+		 "  MIPI_IMSC 0x%08x\n",
+		 readl(base + CIF_MIPI_CTRL),
+		 readl(base + CIF_MIPI_IMG_DATA_SEL),
+		 readl(base + CIF_MIPI_STATUS),
+		 readl(base + CIF_MIPI_IMSC));
+
+	return 0;
+}
+
+/* Configure MUX */
+static int rkisp1_config_path(struct rkisp1_device *dev)
+{
+	int ret = 0;
+	struct rkisp1_sensor_info *sensor = dev->active_sensor;
+	u32 dpcl = readl(dev->base_addr + CIF_VI_DPCL);
+
+	if (sensor->mbus.type == V4L2_MBUS_BT656 ||
+	    sensor->mbus.type == V4L2_MBUS_PARALLEL) {
+		ret = rkisp1_config_dvp(dev);
+		dpcl |= CIF_VI_DPCL_IF_SEL_PARALLEL;
+	} else if (sensor->mbus.type == V4L2_MBUS_CSI2) {
+		ret = rkisp1_config_mipi(dev);
+		dpcl |= CIF_VI_DPCL_IF_SEL_MIPI;
+	}
+
+	writel(dpcl, dev->base_addr + CIF_VI_DPCL);
+
+	return ret;
+}
+
+/* Hareware configure Entry */
+static int rkisp1_config_cif(struct rkisp1_device *dev)
+{
+	int ret = 0;
+	u32 cif_id;
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		 "SP state = %d, MP state = %d\n",
+		 dev->stream[RKISP1_STREAM_SP].state,
+		 dev->stream[RKISP1_STREAM_MP].state);
+
+	cif_id = readl(dev->base_addr + CIF_VI_ID);
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "CIF_ID 0x%08x\n", cif_id);
+
+	ret = rkisp1_config_isp(dev);
+	if (ret < 0)
+		return ret;
+	ret = rkisp1_config_path(dev);
+	if (ret < 0)
+		return ret;
+	rkisp1_config_ism(dev);
+
+	return 0;
+}
+
+/* Mess register operations to stop isp */
+static int rkisp1_isp_stop(struct rkisp1_device *dev)
+{
+	void __iomem *base = dev->base_addr;
+	u32 val;
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		 "SP state = %d, MP state = %d\n",
+		 dev->stream[RKISP1_STREAM_SP].state,
+		 dev->stream[RKISP1_STREAM_MP].state);
+
+	/*
+	 * ISP(mi) stop in mi frame end -> Stop ISP(mipi) ->
+	 * Stop ISP(isp) ->wait for ISP isp off
+	 */
+	/* stop and clear MI, MIPI, and ISP interrupts */
+	writel(0, base + CIF_MIPI_IMSC);
+	writel(~0, base + CIF_MIPI_ICR);
+
+	writel(0, base + CIF_ISP_IMSC);
+	writel(~0, base + CIF_ISP_ICR);
+
+	writel(0, base + CIF_MI_IMSC);
+	writel(~0, base + CIF_MI_ICR);
+	val = readl(base + CIF_MIPI_CTRL);
+	writel(val & (~CIF_MIPI_CTRL_OUTPUT_ENA), base + CIF_MIPI_CTRL);
+	/* stop ISP */
+	val = readl(base + CIF_ISP_CTRL);
+	val &= ~(CIF_ISP_CTRL_ISP_INFORM_ENABLE | CIF_ISP_CTRL_ISP_ENABLE);
+	writel(val, base + CIF_ISP_CTRL);
+
+	val = readl(base + CIF_ISP_CTRL);
+	writel(val | CIF_ISP_CTRL_ISP_CFG_UPD, base + CIF_ISP_CTRL);
+
+	readx_poll_timeout(readl, base + CIF_ISP_RIS,
+			   val, val & CIF_ISP_OFF, 20, 100);
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		"state(MP:%d, SP:%d), MI_CTRL:%x, ISP_CTRL:%x, MIPI_CTRL:%x\n",
+		 dev->stream[RKISP1_STREAM_SP].state,
+		 dev->stream[RKISP1_STREAM_MP].state,
+		 readl(base + CIF_MI_CTRL),
+		 readl(base + CIF_ISP_CTRL),
+		 readl(base + CIF_MIPI_CTRL));
+
+	writel(CIF_IRCL_MIPI_SW_RST | CIF_IRCL_ISP_SW_RST, base + CIF_IRCL);
+	writel(0x0, base + CIF_IRCL);
+
+	return 0;
+}
+
+/* Mess register operations to start isp */
+static int rkisp1_isp_start(struct rkisp1_device *dev)
+{
+	struct rkisp1_sensor_info *sensor = dev->active_sensor;
+	void __iomem *base = dev->base_addr;
+	u32 val;
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		 "SP state = %d, MP state = %d\n",
+		 dev->stream[RKISP1_STREAM_SP].state,
+		 dev->stream[RKISP1_STREAM_MP].state);
+
+	/* Activate MIPI */
+	if (sensor->mbus.type == V4L2_MBUS_CSI2) {
+		val = readl(base + CIF_MIPI_CTRL);
+		writel(val | CIF_MIPI_CTRL_OUTPUT_ENA, base + CIF_MIPI_CTRL);
+	}
+	/* Activate ISP */
+	val = readl(base + CIF_ISP_CTRL);
+	val |= CIF_ISP_CTRL_ISP_CFG_UPD | CIF_ISP_CTRL_ISP_ENABLE |
+	       CIF_ISP_CTRL_ISP_INFORM_ENABLE;
+	writel(val, base + CIF_ISP_CTRL);
+
+	/* XXX: Is the 1000us too long?
+	 * CIF spec says to wait for sufficient time after enabling
+	 * the MIPI interface and before starting the sensor output.
+	 */
+	usleep_range(1000, 1200);
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		 "SP state = %d, MP state = %d MI_CTRL 0x%08x\n"
+		 "  ISP_CTRL 0x%08x MIPI_CTRL 0x%08x\n",
+		 dev->stream[RKISP1_STREAM_SP].state,
+		 dev->stream[RKISP1_STREAM_MP].state,
+		 readl(base + CIF_MI_CTRL),
+		 readl(base + CIF_ISP_CTRL),
+		 readl(base + CIF_MIPI_CTRL));
+
+	return 0;
+}
+
+static void rkisp1_config_clk(struct rkisp1_device *dev)
+{
+	u32 val = CIF_ICCL_ISP_CLK | CIF_ICCL_CP_CLK | CIF_ICCL_MRSZ_CLK |
+		CIF_ICCL_SRSZ_CLK | CIF_ICCL_JPEG_CLK | CIF_ICCL_MI_CLK |
+		CIF_ICCL_MIPI_CLK | CIF_ICCL_DCROP_CLK;
+
+	writel(val, dev->base_addr + CIF_ICCL);
+}
+
+/***************************** isp sub-devs *******************************/
+
+static const struct ispsd_in_fmt rkisp1_isp_input_formats[] = {
+	{
+		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW10,
+		.bayer_pat	= RAW_BGGR,
+		.bus_width	= 10,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW10,
+		.bayer_pat	= RAW_RGGB,
+		.bus_width	= 10,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW10,
+		.bayer_pat	= RAW_GBRG,
+		.bus_width	= 10,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW10,
+		.bayer_pat	= RAW_GRBG,
+		.bus_width	= 10,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW12,
+		.bayer_pat	= RAW_RGGB,
+		.bus_width	= 12,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW12,
+		.bayer_pat	= RAW_BGGR,
+		.bus_width	= 12,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW12,
+		.bayer_pat	= RAW_GBRG,
+		.bus_width	= 12,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW12,
+		.bayer_pat	= RAW_GRBG,
+		.bus_width	= 12,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW8,
+		.bayer_pat	= RAW_RGGB,
+		.bus_width	= 8,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW8,
+		.bayer_pat	= RAW_BGGR,
+		.bus_width	= 8,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW8,
+		.bayer_pat	= RAW_GBRG,
+		.bus_width	= 8,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.fmt_type	= FMT_BAYER,
+		.mipi_dt	= CIF_CSI2_DT_RAW8,
+		.bayer_pat	= RAW_GRBG,
+		.bus_width	= 8,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_YUYV8_1X16,
+		.fmt_type	= FMT_YUV,
+		.mipi_dt	= CIF_CSI2_DT_YUV422_8b,
+		.yuv_seq	= CIF_ISP_ACQ_PROP_YCBYCR,
+		.bus_width	= 16,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_YVYU8_1X16,
+		.fmt_type	= FMT_YUV,
+		.mipi_dt	= CIF_CSI2_DT_YUV422_8b,
+		.yuv_seq	= CIF_ISP_ACQ_PROP_YCRYCB,
+		.bus_width	= 16,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_UYVY8_1X16,
+		.fmt_type	= FMT_YUV,
+		.mipi_dt	= CIF_CSI2_DT_YUV422_8b,
+		.yuv_seq	= CIF_ISP_ACQ_PROP_CBYCRY,
+		.bus_width	= 16,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_VYUY8_1X16,
+		.fmt_type	= FMT_YUV,
+		.mipi_dt	= CIF_CSI2_DT_YUV422_8b,
+		.yuv_seq	= CIF_ISP_ACQ_PROP_CRYCBY,
+		.bus_width	= 16,
+	},
+};
+
+static const struct ispsd_out_fmt rkisp1_isp_output_formats[] = {
+	{
+		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.fmt_type	= FMT_YUV,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.fmt_type	= FMT_BAYER,
+	}, {
+		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.fmt_type	= FMT_BAYER,
+	},
+};
+
+static const struct ispsd_in_fmt *find_in_fmt(u32 mbus_code)
+{
+	const struct ispsd_in_fmt *fmt;
+	int i, array_size = ARRAY_SIZE(rkisp1_isp_input_formats);
+
+	for (i = 0; i < array_size; i++) {
+		fmt = &rkisp1_isp_input_formats[i];
+		if (fmt->mbus_code == mbus_code)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static const struct ispsd_out_fmt *find_out_fmt(u32 mbus_code)
+{
+	const struct ispsd_out_fmt *fmt;
+	int i, array_size = ARRAY_SIZE(rkisp1_isp_output_formats);
+
+	for (i = 0; i < array_size; i++) {
+		fmt = &rkisp1_isp_output_formats[i];
+		if (fmt->mbus_code == mbus_code)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static int rkisp1_isp_sd_enum_mbus_code(struct v4l2_subdev *sd,
+					struct v4l2_subdev_pad_config *cfg,
+					struct v4l2_subdev_mbus_code_enum *code)
+{
+	int i = code->index;
+
+	if (code->pad == RKISP1_ISP_PAD_SINK) {
+		if (i >= ARRAY_SIZE(rkisp1_isp_input_formats))
+			return -EINVAL;
+		code->code = rkisp1_isp_input_formats[i].mbus_code;
+	} else {
+		if (i >= ARRAY_SIZE(rkisp1_isp_output_formats))
+			return -EINVAL;
+		code->code = rkisp1_isp_output_formats[i].mbus_code;
+	}
+
+	return 0;
+}
+
+#define sd_to_isp_sd(_sd) container_of(_sd, struct rkisp1_isp_subdev, sd)
+static int rkisp1_isp_sd_get_fmt(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_format *fmt)
+{
+	struct v4l2_mbus_framefmt *mf = &fmt->format;
+	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
+
+	if ((fmt->pad != RKISP1_ISP_PAD_SINK) &&
+	    (fmt->pad != RKISP1_ISP_PAD_SOURCE_PATH))
+		return -EINVAL;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+		fmt->format = *mf;
+		return 0;
+	}
+
+	if (fmt->pad == RKISP1_ISP_PAD_SINK) {
+		*mf = isp_sd->in_frm;
+	} else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
+		/* format of source pad */
+		*mf = isp_sd->in_frm;
+		/* window size of source pad */
+		mf->width = isp_sd->out_crop.width;
+		mf->height = isp_sd->out_crop.height;
+	}
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static void rkisp1_isp_sd_try_fmt(struct v4l2_subdev *sd,
+				  unsigned int pad,
+				  struct v4l2_mbus_framefmt *fmt)
+{
+	struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
+	struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
+	const struct ispsd_in_fmt *in_fmt;
+	const struct ispsd_out_fmt *out_fmt;
+
+	switch (pad) {
+	case RKISP1_ISP_PAD_SINK:
+		in_fmt = find_in_fmt(fmt->code);
+		if (in_fmt)
+			fmt->code = in_fmt->mbus_code;
+		else
+			fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
+		fmt->width  = clamp_t(u32, fmt->width, CIF_ISP_INPUT_W_MIN,
+				      CIF_ISP_INPUT_W_MAX);
+		fmt->height = clamp_t(u32, fmt->height, CIF_ISP_INPUT_H_MIN,
+				      CIF_ISP_INPUT_H_MAX);
+		break;
+	case RKISP1_ISP_PAD_SOURCE_PATH:
+		out_fmt = find_out_fmt(fmt->code);
+		if (out_fmt)
+			fmt->code = out_fmt->mbus_code;
+		else
+			fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
+		/* window size is set in s_selection */
+		fmt->width  = isp_sd->out_crop.width;
+		fmt->height = isp_sd->out_crop.height;
+		break;
+	}
+
+	fmt->field = V4L2_FIELD_NONE;
+}
+
+static int rkisp1_isp_sd_set_fmt(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_format *fmt)
+{
+	struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
+	struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
+	struct v4l2_mbus_framefmt *mf = &fmt->format;
+
+	if ((fmt->pad != RKISP1_ISP_PAD_SINK) &&
+	    (fmt->pad != RKISP1_ISP_PAD_SOURCE_PATH))
+		return -EINVAL;
+
+	rkisp1_isp_sd_try_fmt(sd, fmt->pad, mf);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_mbus_framefmt *try_mf;
+
+		mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+		*try_mf = *mf;
+		return 0;
+	}
+
+	if (fmt->pad == RKISP1_ISP_PAD_SINK) {
+		const struct ispsd_in_fmt *in_fmt;
+
+		in_fmt = find_in_fmt(mf->code);
+		isp_sd->in_fmt = *in_fmt;
+		isp_sd->in_frm = *mf;
+	} else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
+		const struct ispsd_out_fmt *out_fmt;
+
+		/* Ignore width/height */
+		out_fmt = find_out_fmt(mf->code);
+		isp_sd->out_fmt = *out_fmt;
+	}
+
+	return 0;
+}
+
+static void rkisp1_isp_sd_try_crop(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_pad_config *cfg,
+				  struct v4l2_subdev_selection *sel)
+{
+	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
+	struct v4l2_mbus_framefmt in_frm = isp_sd->in_frm;
+	struct v4l2_rect in_crop = isp_sd->in_crop;
+	struct v4l2_rect *input = &sel->r;
+
+	if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
+		in_frm = *v4l2_subdev_get_try_format(sd, cfg, RKISP1_ISP_PAD_SINK);
+		in_crop = *v4l2_subdev_get_try_crop(sd, cfg, RKISP1_ISP_PAD_SINK);
+	}
+
+	input->left = ALIGN(input->left, 2);
+	input->width = ALIGN(input->width, 2);
+
+	if (sel->pad == RKISP1_ISP_PAD_SINK) {
+		input->left = clamp_t(u32, input->left, 0, in_frm.width);
+		input->top = clamp_t(u32, input->top, 0, in_frm.height);
+		input->width = clamp_t(u32, input->width, CIF_ISP_INPUT_W_MIN,
+				in_frm.width - input->left);
+		input->height = clamp_t(u32, input->height,
+				CIF_ISP_INPUT_H_MIN,
+				in_frm.height - input->top);
+	} else if (sel->pad == RKISP1_ISP_PAD_SOURCE_PATH) {
+		input->left = clamp_t(u32, input->left, 0, in_crop.width);
+		input->top = clamp_t(u32, input->top, 0, in_crop.height);
+		input->width = clamp_t(u32, input->width, CIF_ISP_OUTPUT_W_MIN,
+				in_crop.width - input->left);
+		input->height = clamp_t(u32, input->height, CIF_ISP_OUTPUT_H_MIN,
+				in_crop.height - input->top);
+	}
+}
+
+static int rkisp1_isp_sd_get_selection(struct v4l2_subdev *sd,
+				       struct v4l2_subdev_pad_config *cfg,
+				       struct v4l2_subdev_selection *sel)
+{
+	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
+
+	if (sel->pad != RKISP1_ISP_PAD_SOURCE_PATH &&
+	    sel->pad != RKISP1_ISP_PAD_SINK)
+		return -EINVAL;
+
+	if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_rect *try_sel;
+
+		try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
+		sel->r = *try_sel;
+		return 0;
+	}
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		if (sel->pad == RKISP1_ISP_PAD_SINK) {
+			sel->r.height = isp_sd->in_frm.height;
+			sel->r.width = isp_sd->in_frm.width;
+			sel->r.left = 0;
+			sel->r.top = 0;
+		} else {
+			sel->r = isp_sd->in_crop;
+		}
+		break;
+	case V4L2_SEL_TGT_CROP:
+		if (sel->pad == RKISP1_ISP_PAD_SINK)
+			sel->r = isp_sd->in_crop;
+		else
+			sel->r = isp_sd->out_crop;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rkisp1_isp_sd_set_selection(struct v4l2_subdev *sd,
+				       struct v4l2_subdev_pad_config *cfg,
+				       struct v4l2_subdev_selection *sel)
+{
+	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
+	struct rkisp1_device *dev = sd_to_isp_dev(sd);
+
+	if (sel->pad != RKISP1_ISP_PAD_SOURCE_PATH &&
+	    sel->pad != RKISP1_ISP_PAD_SINK)
+		return -EINVAL;
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+		 "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, sel->pad,
+		 sel->r.left, sel->r.top, sel->r.width, sel->r.height);
+	rkisp1_isp_sd_try_crop(sd, cfg, sel);
+
+	if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_rect *try_sel;
+
+		try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
+		*try_sel = sel->r;
+		return 0;
+	}
+
+	if (sel->pad == RKISP1_ISP_PAD_SINK)
+		isp_sd->in_crop = sel->r;
+	else
+		isp_sd->out_crop = sel->r;
+
+	return 0;
+}
+
+static int rkisp1_isp_sd_s_stream(struct v4l2_subdev *sd, int on)
+{
+	struct rkisp1_device *isp_dev = sd_to_isp_dev(sd);
+	struct rkisp1_sensor_info *sensor;
+	struct v4l2_subdev *sensor_sd;
+	int ret = 0;
+
+	if (!on)
+		return rkisp1_isp_stop(isp_dev);
+
+	sensor_sd = get_remote_sensor(sd);
+	if (!sensor_sd)
+		return -ENODEV;
+
+	sensor = sd_to_sensor(isp_dev, sensor_sd);
+	/*
+	 * Update sensor bus configuration. This is only effective
+	 * for sensors chained off an external CSI2 PHY.
+	 */
+	ret = v4l2_subdev_call(sensor->sd, video, g_mbus_config,
+			       &sensor->mbus);
+	if (ret && ret != -ENOIOCTLCMD)
+		return ret;
+	isp_dev->active_sensor = sensor;
+
+	atomic_set(&isp_dev->isp_sdev.frm_sync_seq, 0);
+	ret = rkisp1_config_cif(isp_dev);
+	if (ret < 0)
+		return ret;
+
+	return rkisp1_isp_start(isp_dev);
+}
+
+static int rkisp1_isp_sd_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct rkisp1_device *dev = sd_to_isp_dev(sd);
+	int ret;
+
+	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "s_power: %d\n", on);
+
+	if (on) {
+		ret = pm_runtime_get_sync(dev->dev);
+		if (ret < 0)
+			return ret;
+
+		rkisp1_config_clk(dev);
+	} else {
+		ret = pm_runtime_put(dev->dev);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int rkisp1_subdev_link_validate(struct media_link *link)
+{
+	if (link->source->index == RKISP1_ISP_PAD_SINK_PARAMS)
+		return 0;
+
+	return v4l2_subdev_link_validate(link);
+}
+
+static int rkisp1_subdev_fmt_link_validate(struct v4l2_subdev *sd,
+			     struct media_link *link,
+			     struct v4l2_subdev_format *source_fmt,
+			     struct v4l2_subdev_format *sink_fmt)
+{
+	if (source_fmt->format.code != sink_fmt->format.code)
+		return -EINVAL;
+
+	/* Crop is available */
+	if (source_fmt->format.width < sink_fmt->format.width ||
+		source_fmt->format.height < sink_fmt->format.height)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void
+riksp1_isp_queue_event_sof(struct rkisp1_isp_subdev *isp)
+{
+	struct v4l2_event event = {
+		.type = V4L2_EVENT_FRAME_SYNC,
+		.u.frame_sync.frame_sequence =
+			atomic_inc_return(&isp->frm_sync_seq) - 1,
+	};
+	v4l2_event_queue(isp->sd.devnode, &event);
+}
+
+static int rkisp1_isp_sd_subs_evt(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+				  struct v4l2_event_subscription *sub)
+{
+	if (sub->type != V4L2_EVENT_FRAME_SYNC)
+		return -EINVAL;
+
+	/* Line number. For now only zero accepted. */
+	if (sub->id != 0)
+		return -EINVAL;
+
+	return v4l2_event_subscribe(fh, sub, 0, NULL);
+}
+
+static const struct v4l2_subdev_pad_ops rkisp1_isp_sd_pad_ops = {
+	.enum_mbus_code = rkisp1_isp_sd_enum_mbus_code,
+	.get_selection = rkisp1_isp_sd_get_selection,
+	.set_selection = rkisp1_isp_sd_set_selection,
+	.get_fmt = rkisp1_isp_sd_get_fmt,
+	.set_fmt = rkisp1_isp_sd_set_fmt,
+	.link_validate = rkisp1_subdev_fmt_link_validate,
+};
+
+static const struct media_entity_operations rkisp1_isp_sd_media_ops = {
+	.link_validate = rkisp1_subdev_link_validate,
+};
+
+static const struct v4l2_subdev_video_ops rkisp1_isp_sd_video_ops = {
+	.s_stream = rkisp1_isp_sd_s_stream,
+};
+
+static const struct v4l2_subdev_core_ops rkisp1_isp_core_ops = {
+	.subscribe_event = rkisp1_isp_sd_subs_evt,
+	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
+	.s_power = rkisp1_isp_sd_s_power,
+};
+
+static struct v4l2_subdev_ops rkisp1_isp_sd_ops = {
+	.core = &rkisp1_isp_core_ops,
+	.video = &rkisp1_isp_sd_video_ops,
+	.pad = &rkisp1_isp_sd_pad_ops,
+};
+
+static void rkisp1_isp_sd_init_default_fmt(struct rkisp1_isp_subdev *isp_sd)
+{
+	struct v4l2_mbus_framefmt *in_frm = &isp_sd->in_frm;
+	struct v4l2_rect *in_crop = &isp_sd->in_crop;
+	struct v4l2_rect *out_crop = &isp_sd->out_crop;
+	struct ispsd_in_fmt *in_fmt = &isp_sd->in_fmt;
+	struct ispsd_out_fmt *out_fmt = &isp_sd->out_fmt;
+
+	*in_fmt = rkisp1_isp_input_formats[0];
+	in_frm->width = RKISP1_DEFAULT_WIDTH;
+	in_frm->height = RKISP1_DEFAULT_HEIGHT;
+	in_frm->code = in_fmt->mbus_code;
+
+	in_crop->width = in_frm->width;
+	in_crop->height = in_frm->height;
+	in_crop->left = 0;
+	in_crop->top = 0;
+
+	/* propagate to source */
+	*out_crop = *in_crop;
+	*out_fmt = rkisp1_isp_output_formats[0];
+}
+
+int rkisp1_register_isp_subdev(struct rkisp1_device *isp_dev,
+			       struct v4l2_device *v4l2_dev)
+{
+	struct rkisp1_isp_subdev *isp_sdev = &isp_dev->isp_sdev;
+	struct v4l2_subdev *sd = &isp_sdev->sd;
+	int ret;
+
+	v4l2_subdev_init(sd, &rkisp1_isp_sd_ops);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+	sd->entity.ops = &rkisp1_isp_sd_media_ops;
+	snprintf(sd->name, sizeof(sd->name), "rkisp1-isp-subdev");
+
+	isp_sdev->pads[RKISP1_ISP_PAD_SINK].flags =
+		MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
+	isp_sdev->pads[RKISP1_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
+	isp_sdev->pads[RKISP1_ISP_PAD_SOURCE_PATH].flags = MEDIA_PAD_FL_SOURCE;
+	isp_sdev->pads[RKISP1_ISP_PAD_SOURCE_STATS].flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
+	ret = media_entity_pads_init(&sd->entity, RKISP1_ISP_PAD_MAX,
+				     isp_sdev->pads);
+	if (ret < 0)
+		return ret;
+
+	sd->owner = THIS_MODULE;
+	v4l2_set_subdevdata(sd, isp_dev);
+
+	sd->grp_id = GRP_ID_ISP;
+	ret = v4l2_device_register_subdev(v4l2_dev, sd);
+	if (ret < 0) {
+		v4l2_err(sd, "Failed to register isp subdev\n");
+		goto err_cleanup_media_entity;
+	}
+
+	rkisp1_isp_sd_init_default_fmt(isp_sdev);
+
+	return 0;
+err_cleanup_media_entity:
+	media_entity_cleanup(&sd->entity);
+	return ret;
+}
+
+void rkisp1_unregister_isp_subdev(struct rkisp1_device *isp_dev)
+{
+	struct v4l2_subdev *sd = &isp_dev->isp_sdev.sd;
+
+	v4l2_device_unregister_subdev(sd);
+	media_entity_cleanup(&sd->entity);
+}
+
+/****************  Interrupter Handler ****************/
+
+void rkisp1_mipi_isr(unsigned int mis, struct rkisp1_device *dev)
+{
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	void __iomem *base = dev->base_addr;
+	u32 val;
+
+	writel(~0, base + CIF_MIPI_ICR);
+
+	/*
+	 * Disable DPHY errctrl interrupt, because this dphy
+	 * erctrl signal is asserted until the next changes
+	 * of line state. This time is may be too long and cpu
+	 * is hold in this interrupt.
+	 */
+	if (mis & CIF_MIPI_ERR_CTRL(0x0f)) {
+		val = readl(base + CIF_MIPI_IMSC);
+		writel(val & ~CIF_MIPI_ERR_CTRL(0x0f), base + CIF_MIPI_IMSC);
+		dev->isp_sdev.dphy_errctrl_disabled = true;
+	}
+
+	/*
+	 * Enable DPHY errctrl interrupt again, if mipi have receive
+	 * the whole frame without any error.
+	 */
+	if (mis == CIF_MIPI_FRAME_END) {
+		/*
+		 * Enable DPHY errctrl interrupt again, if mipi have receive
+		 * the whole frame without any error.
+		 */
+		if (dev->isp_sdev.dphy_errctrl_disabled) {
+			val = readl(base + CIF_MIPI_IMSC);
+			val |= CIF_MIPI_ERR_CTRL(0x0f);
+			writel(val, base + CIF_MIPI_IMSC);
+			dev->isp_sdev.dphy_errctrl_disabled = false;
+		}
+	} else {
+		v4l2_warn(v4l2_dev, "MIPI mis error: 0x%08x\n", mis);
+	}
+}
+
+void rkisp1_isp_isr(unsigned int isp_mis, struct rkisp1_device *dev)
+{
+	void __iomem *base = dev->base_addr;
+	unsigned int isp_mis_tmp = 0;
+	unsigned int isp_err = 0;
+
+	/* start edge of v_sync */
+	if (isp_mis & CIF_ISP_V_START) {
+		riksp1_isp_queue_event_sof(&dev->isp_sdev);
+
+		writel(CIF_ISP_V_START, base + CIF_ISP_ICR);
+		isp_mis_tmp = readl(base + CIF_ISP_MIS);
+		if (isp_mis_tmp & CIF_ISP_V_START)
+			v4l2_err(&dev->v4l2_dev, "isp icr v_statr err: 0x%x\n",
+				 isp_mis_tmp);
+	}
+
+	if ((isp_mis & CIF_ISP_PIC_SIZE_ERROR)) {
+		/* Clear pic_size_error */
+		writel(CIF_ISP_PIC_SIZE_ERROR, base + CIF_ISP_ICR);
+		isp_err = readl(base + CIF_ISP_ERR);
+		v4l2_err(&dev->v4l2_dev,
+				"CIF_ISP_PIC_SIZE_ERROR (0x%08x)", isp_err);
+		writel(isp_err, base + CIF_ISP_ERR_CLR);
+	} else if ((isp_mis & CIF_ISP_DATA_LOSS)) {
+		/* Clear data_loss */
+		writel(CIF_ISP_DATA_LOSS, base + CIF_ISP_ICR);
+		v4l2_err(&dev->v4l2_dev, "CIF_ISP_DATA_LOSS\n");
+		writel(CIF_ISP_DATA_LOSS, base + CIF_ISP_ICR);
+	}
+
+	/* sampled input frame is complete */
+	if (isp_mis & CIF_ISP_FRAME_IN) {
+		writel(CIF_ISP_FRAME_IN, base + CIF_ISP_ICR);
+		isp_mis_tmp = readl(base + CIF_ISP_MIS);
+		if (isp_mis_tmp & CIF_ISP_FRAME_IN)
+			v4l2_err(&dev->v4l2_dev, "isp icr frame_in err: 0x%x\n",
+				 isp_mis_tmp);
+	}
+
+	/* frame was completely put out */
+	if (isp_mis & CIF_ISP_FRAME) {
+		u32 isp_ris = 0;
+		/* Clear Frame In (ISP) */
+		writel(CIF_ISP_FRAME, base + CIF_ISP_ICR);
+		isp_mis_tmp = readl(base + CIF_ISP_MIS);
+		if (isp_mis_tmp & CIF_ISP_FRAME)
+			v4l2_err(&dev->v4l2_dev,
+				 "isp icr frame end err: 0x%x\n", isp_mis_tmp);
+
+		isp_ris = readl(base + CIF_ISP_RIS);
+		if (isp_ris & (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
+				CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
+			rkisp1_stats_isr(&dev->stats_vdev, isp_ris);
+	}
+
+	/*
+	 * Then update changed configs. Some of them involve
+	 * lot of register writes. Do those only one per frame.
+	 * Do the updates in the order of the processing flow.
+	 */
+	rkisp1_params_isr(&dev->params_vdev, isp_mis);
+}
diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.h b/drivers/media/platform/rockchip/isp1/rkisp1.h
new file mode 100644
index 000000000000..274cafbe2d4d
--- /dev/null
+++ b/drivers/media/platform/rockchip/isp1/rkisp1.h
@@ -0,0 +1,131 @@ 
+/*
+ * Rockchip isp1 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RKISP1_H
+#define _RKISP1_H
+
+#include <linux/platform_device.h>
+#include <media/v4l2-fwnode.h>
+#include "common.h"
+
+struct rkisp1_stream;
+
+/*
+ * struct ispsd_in_fmt - ISP intput-pad format
+ *
+ * Translate mbus_code to hardware format values
+ *
+ * @bus_width: used for parallel
+ */
+struct ispsd_in_fmt {
+	u32 mbus_code;
+	u8 fmt_type;
+	u32 mipi_dt;
+	u32 yuv_seq;
+	enum rkisp1_fmt_raw_pat_type bayer_pat;
+	u8 bus_width;
+};
+
+struct ispsd_out_fmt {
+	u32 mbus_code;
+	u8 fmt_type;
+};
+
+struct rkisp1_ie_config {
+	unsigned int effect;
+};
+
+enum rkisp1_isp_pad {
+	RKISP1_ISP_PAD_SINK,
+	RKISP1_ISP_PAD_SINK_PARAMS,
+	RKISP1_ISP_PAD_SOURCE_PATH,
+	RKISP1_ISP_PAD_SOURCE_STATS,
+	RKISP1_ISP_PAD_MAX
+};
+
+/*
+ * struct rkisp1_isp_subdev - ISP sub-device
+ *
+ * See Cropping regions of ISP in rkisp1.c for details
+ * @in_frm: input size, don't have to be equal to sensor size
+ * @in_fmt: intput format
+ * @in_crop: crop for sink pad
+ * @out_fmt: output format
+ * @out_crop: output size
+ *
+ * @dphy_errctrl_disabled: if dphy errctrl is disabled(avoid endless interrupt)
+ * @frm_sync_seq: frame sequence, to sync frame_id between video devices.
+ */
+struct rkisp1_isp_subdev {
+	struct v4l2_subdev sd;
+	struct media_pad pads[RKISP1_ISP_PAD_MAX];
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_mbus_framefmt in_frm;
+	struct ispsd_in_fmt in_fmt;
+	struct v4l2_rect in_crop;
+	struct ispsd_out_fmt out_fmt;
+	struct v4l2_rect out_crop;
+	bool dphy_errctrl_disabled;
+	atomic_t frm_sync_seq;
+};
+
+int rkisp1_register_isp_subdev(struct rkisp1_device *isp_dev,
+			       struct v4l2_device *v4l2_dev);
+
+void rkisp1_unregister_isp_subdev(struct rkisp1_device *isp_dev);
+
+void rkisp1_mipi_isr(unsigned int mipi_mis, struct rkisp1_device *dev);
+
+void rkisp1_isp_isr(unsigned int isp_mis, struct rkisp1_device *dev);
+
+/* Avoid direct access to rkisp1_isp_subdev in capture.c */
+static inline
+struct ispsd_out_fmt *rkisp1_get_ispsd_out_fmt(struct rkisp1_isp_subdev *isp_sdev)
+{
+	return &isp_sdev->out_fmt;
+}
+
+static inline
+struct ispsd_in_fmt *rkisp1_get_ispsd_in_fmt(struct rkisp1_isp_subdev *isp_sdev)
+{
+	return &isp_sdev->in_fmt;
+}
+
+static inline
+struct v4l2_rect *rkisp1_get_isp_sd_win(struct rkisp1_isp_subdev *isp_sdev)
+{
+	return &isp_sdev->out_crop;
+}
+
+#endif /* _RKISP1_H */