isp10: rockchip: v0.1.6
authordalong.zhang <dalon.zhang@rock-chips.com>
Sun, 9 Oct 2016 08:32:39 +0000 (16:32 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 29 Nov 2016 13:11:43 +0000 (21:11 +0800)
Change-Id: I1b702fb51d1baabd47f190fdafd79ecd22e18be0
Signed-off-by: dalong.zhang <dalon.zhang@rock-chips.com>
26 files changed:
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/rk-isp10/Kconfig [new file with mode: 0644]
drivers/media/platform/rk-isp10/Makefile [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10.c [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10.h [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_img_src.c [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_img_src.h [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_img_src_ops.h [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.h [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_isp.c [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_isp.h [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_pltfrm.c [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_pltfrm.h [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_regs.h [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_rk3288.c [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_rk3399.c [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_v4l2.c [new file with mode: 0644]
drivers/media/platform/rk-isp10/cif_isp10_version.h [new file with mode: 0644]
include/linux/platform_data/rk_isp10_platform.h [new file with mode: 0644]
include/linux/platform_data/rk_isp10_platform_camera_module.h [new file with mode: 0644]
include/media/rk-isp10-config.h [new file with mode: 0644]
include/media/rk-isp10-ioctl.h [new file with mode: 0644]
include/media/v4l2-config_rockchip.h [new file with mode: 0644]
include/media/v4l2-controls_rockchip.h [new file with mode: 0644]

index 9f3f03bdc1bd6acdfa191d33acb48e51115a616a..d648cd80e282c24bccfc82d95fc16b1e29bca5c2 100644 (file)
@@ -120,6 +120,7 @@ source "drivers/media/platform/exynos4-is/Kconfig"
 source "drivers/media/platform/s5p-tv/Kconfig"
 source "drivers/media/platform/am437x/Kconfig"
 source "drivers/media/platform/xilinx/Kconfig"
+source "drivers/media/platform/rk-isp10/Kconfig"
 
 endif # V4L_PLATFORM_DRIVERS
 
index c52535ead13608868436f0e1e8352e9023521a2e..5c90cf2804864fb66488786b665e83a1e7b6b68a 100644 (file)
@@ -57,3 +57,5 @@ obj-$(CONFIG_VIDEO_XILINX)            += xilinx/
 obj-$(CONFIG_VIDEO_ROCKCHIP_VPU)       += rockchip-vpu/
 
 ccflags-y += -I$(srctree)/drivers/media/i2c
+
+obj-$(CONFIG_VIDEO_RK_CIF_ISP10) += rk-isp10/
diff --git a/drivers/media/platform/rk-isp10/Kconfig b/drivers/media/platform/rk-isp10/Kconfig
new file mode 100644 (file)
index 0000000..bb2679b
--- /dev/null
@@ -0,0 +1,11 @@
+config VIDEO_RK_CIF_ISP10
+       tristate "Rockchip cif isp10 camera sensors"
+       depends on VIDEO_V4L2 && I2C
+       select VIDEOBUF_GEN
+       select VIDEOBUF_DMA_CONTIG
+       select VIDEOBUF_VMALLOC
+       default n
+
+       ---help---
+         Say Y here to enable selecting the
+         rockchip cif isp10 camera sensors
diff --git a/drivers/media/platform/rk-isp10/Makefile b/drivers/media/platform/rk-isp10/Makefile
new file mode 100644 (file)
index 0000000..9caf7f9
--- /dev/null
@@ -0,0 +1,3 @@
+
+obj-$(CONFIG_VIDEO_RK_CIF_ISP10) += video_cif_isp10.o
+video_cif_isp10-objs += cif_isp10.o cif_isp10_img_src.o cif_isp10_img_src_v4l2-subdev.o cif_isp10_isp.o cif_isp10_pltfrm.o cif_isp10_rk3288.o cif_isp10_rk3399.o cif_isp10_v4l2.o
\ No newline at end of file
diff --git a/drivers/media/platform/rk-isp10/cif_isp10.c b/drivers/media/platform/rk-isp10/cif_isp10.c
new file mode 100644 (file)
index 0000000..3f1dd33
--- /dev/null
@@ -0,0 +1,6427 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/videodev2.h>
+#include <media/videobuf-dma-contig.h>
+#include "cif_isp10_regs.h"
+#include "cif_isp10.h"
+#include <linux/pm_runtime.h>
+#include <linux/vmalloc.h>
+
+static int cif_isp10_mipi_isr(
+       unsigned int mis,
+       void *cntxt);
+static int cif_isp10_isp_isr(
+       unsigned int mis,
+       void *cntxt);
+static void init_output_formats(void);
+
+struct v4l2_fmtdesc output_formats[MAX_NB_FORMATS];
+
+/* JPEG quantization tables for JPEG encoding */
+/* DC luma table according to ISO/IEC 10918-1 annex K */
+static const unsigned char dc_luma_table_annex_k[] = {
+       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+       0x08, 0x09, 0x0a, 0x0b
+};
+
+/* DC chroma table according to ISO/IEC 10918-1 annex K */
+static const unsigned char dc_chroma_table_annex_k[] = {
+       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+       0x08, 0x09, 0x0a, 0x0b
+};
+
+/* AC luma table according to ISO/IEC 10918-1 annex K */
+static const unsigned char ac_luma_table_annex_k[] = {
+       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+       0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
+       0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+       0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+       0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+       0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+       0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+       0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+       0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+       0xf9, 0xfa
+};
+
+/* AC Chroma table according to ISO/IEC 10918-1 annex K */
+static const unsigned char ac_chroma_table_annex_k[] = {
+       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+       0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
+       0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+       0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+       0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+       0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+       0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+       0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+       0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+       0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+       0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+       0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+       0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+       0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+       0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+       0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+       0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+       0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+       0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+       0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+       0xf9, 0xfa
+};
+
+/* Standard JPEG quantization tables */
+/* luma */
+/* According to JPEG spec:
+ * [
+ *     16, 11, 10, 16,  24,  40,  51,  61,
+ *     12, 12, 14, 19,  26,  58,  60,  55,
+ *     14, 13, 16, 24,  40,  57,  69,  56,
+ *     14, 17, 22, 29,  51,  87,  80,  62,
+ *     18, 22, 37, 56,  68, 109, 103,  77,
+ *     24, 35, 55, 64,  81, 104, 113,  92,
+ *     49, 64, 78, 87, 103, 121, 120, 101,
+ *     72, 92, 95, 98, 112, 100, 103,  99
+ * ]
+ */
+
+/* CIF needs it in zigzag order */
+static const unsigned char yq_table_base_zigzag[] = {
+       16, 11, 12, 14, 12, 10, 16, 14,
+       13, 14, 18, 17, 16, 19, 24, 40,
+       26, 24, 22, 22, 24, 49, 35, 37,
+       29, 40, 58, 51, 61, 60, 57, 51,
+       56, 55, 64, 72, 92, 78, 64, 68,
+       87, 69, 55, 56, 80, 109, 81, 87,
+       95, 98, 103, 104, 103, 62, 77, 113,
+       121, 112, 100, 120, 92, 101, 103, 99
+};
+
+/* chroma */
+/* According to JPEG spec:
+ * [
+ *     17, 18, 24, 47, 99, 99, 99, 99,
+ *     18, 21, 26, 66, 99, 99, 99, 99,
+ *     24, 26, 56, 99, 99, 99, 99, 99,
+ *     47, 66, 99, 99, 99, 99, 99, 99,
+ *     99, 99, 99, 99, 99, 99, 99, 99,
+ *     99, 99, 99, 99, 99, 99, 99, 99,
+ *     99, 99, 99, 99, 99, 99, 99, 99,
+ *     99, 99, 99, 99, 99, 99, 99, 99
+ * ]
+ */
+
+/* CIF needs it in zigzag order */
+static const unsigned char uvq_table_base_zigzag[] = {
+       17, 18, 18, 24, 21, 24, 47, 26,
+       26, 47, 99, 66, 56, 66, 99, 99,
+       99, 99, 99, 99, 99, 99, 99, 99,
+       99, 99, 99, 99, 99, 99, 99, 99,
+       99, 99, 99, 99, 99, 99, 99, 99,
+       99, 99, 99, 99, 99, 99, 99, 99,
+       99, 99, 99, 99, 99, 99, 99, 99,
+       99, 99, 99, 99, 99, 99, 99, 99
+};
+
+static struct cif_isp10_fmt cif_isp10_output_format[] = {
+/* ************* YUV422 ************* */
+{
+       .name           = "YUV422-Interleaved",
+       .fourcc = V4L2_PIX_FMT_YUYV,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YUV422-Interleaved",
+       .fourcc = V4L2_PIX_FMT_YUYV,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YVU422-Interleaved",
+       .fourcc = V4L2_PIX_FMT_UYVY,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YUV422-Planar",
+       .fourcc = V4L2_PIX_FMT_YUV422P,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YUV422-Semi-Planar",
+       .fourcc = V4L2_PIX_FMT_NV16,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+/* ************* YUV420 ************* */
+{
+       .name           = "YUV420-Planar",
+       .fourcc = V4L2_PIX_FMT_YUV420,
+       .flags  = 0,
+       .depth  = 12,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YUV420-Planar",
+       .fourcc = V4L2_PIX_FMT_YUV420,
+       .flags  = 0,
+       .depth  = 12,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YVU420-Planar",
+       .fourcc = V4L2_PIX_FMT_YVU420,
+       .flags  = 0,
+       .depth  = 12,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YUV420-Semi-Planar",
+       .fourcc = V4L2_PIX_FMT_NV12,
+       .flags  = 0,
+       .depth  = 12,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YVU420-Semi-Planar",
+       .fourcc = V4L2_PIX_FMT_NV21,
+       .flags  = 0,
+       .depth  = 12,
+       .rotation = false,
+       .overlay = false,
+},
+/* ************* YUV400 ************* */
+{
+       .name           = "YVU400-Grey-Planar",
+       .fourcc = V4L2_PIX_FMT_GREY,
+       .flags  = 0,
+       .depth  = 8,
+       .rotation = false,
+       .overlay = false,
+},
+/* ************* YUV444 ************* */
+{
+       .name           = "YVU444-Planar",
+       .fourcc = V4L2_PIX_FMT_YUV444,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+{
+       .name           = "YVU444-Semi-Planar",
+       .fourcc = V4L2_PIX_FMT_NV24,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+/* ************* JPEG ************* */
+{
+       .name           = "JPEG",
+       .fourcc = V4L2_PIX_FMT_JPEG,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+/* ************ RGB565 *********** */
+{
+       .name       = "RGB565",
+       .fourcc = V4L2_PIX_FMT_RGB565,
+       .flags  = 0,
+       .depth  = 16,
+       .rotation = false,
+       .overlay = false,
+},
+/* ************ SGRBG8 *********** */
+{
+       .name       = "SGRBG8",
+       .fourcc = V4L2_PIX_FMT_SGRBG8,
+       .flags  = 0,
+       .depth  = 8,
+       .rotation = false,
+       .overlay = false,
+},
+};
+
+struct cif_isp10_hw_error {
+       char *name;
+       unsigned int count;
+       unsigned int mask;
+       unsigned int type;      /* isp:0 ;mipi:1 */
+};
+
+static struct cif_isp10_hw_error cif_isp10_hw_errors[] = {
+       {
+        .name = "isp_data_loss",
+        .count = 0,
+        .mask = CIF_ISP_DATA_LOSS,
+        .type = 0,
+        },
+       {
+        .name = "isp_pic_size_err",
+        .count = 0,
+        .mask = CIF_ISP_PIC_SIZE_ERROR,
+        .type = 0,
+        },
+       {
+        .name = "mipi_fifo_err",
+        .count = 0,
+        .mask = CIF_MIPI_SYNC_FIFO_OVFLW(1),
+        .type = 1,
+        },
+       {
+        .name = "dphy_err_sot",
+        .count = 0,
+        .mask = CIF_MIPI_ERR_SOT(3),
+        .type = 1,
+        },
+       {
+        .name = "dphy_err_sot_sync",
+        .count = 0,
+        .mask = CIF_MIPI_ERR_SOT_SYNC(3),
+        .type = 1,
+        },
+       {
+        .name = "dphy_err_eot_sync",
+        .count = 0,
+        .mask = CIF_MIPI_ERR_EOT_SYNC(3),
+        .type = 1,
+        },
+       {
+        .name = "dphy_err_ctrl",
+        .count = 0,
+        .mask = CIF_MIPI_ERR_CTRL(3),
+        .type = 1,
+        },
+       {
+        .name = "csi_err_protocol",
+        .count = 0,
+        .mask = CIF_MIPI_ERR_PROTOCOL,
+        .type = 2,
+        },
+       {
+        .name = "csi_err_ecc1",
+        .count = 0,
+        .mask = CIF_MIPI_ERR_ECC1,
+        .type = 2,
+        },
+       {
+        .name = "csi_err_ecc2",
+        .count = 0,
+        .mask = CIF_MIPI_ERR_ECC2,
+        .type = 2,
+        },
+       {
+        .name = "csi_err_cs",
+        .count = 0,
+        .mask = CIF_MIPI_ERR_CS,
+        .type = 2,
+        },
+       {
+        .name = "fifo_ovf",
+        .count = 0,
+        .mask = (3 << 0),
+        .type = 2,
+        },
+       {
+        .name = "isp_outform",
+        .count = 0,
+        .mask = CIF_ISP_ERR_OUTFORM_SIZE,
+        .type = 0,
+        },
+       {
+        .name = "isp_stab",
+        .count = 0,
+        .mask = CIF_ISP_ERR_IS_SIZE,
+        .type = 0,
+        },
+       {
+        .name = "isp_inform",
+        .count = 0,
+        .mask = CIF_ISP_ERR_INFORM_SIZE,
+        .type = 0,
+       }
+};
+
+/* Defines */
+
+#define CIF_ISP10_INVALID_BUFF_ADDR ((u32)~0)
+#define CIF_ISP10_MI_IS_BUSY(dev)\
+       (dev->config.mi_config.mp.busy ||\
+       dev->config.mi_config.sp.busy ||\
+       dev->config.mi_config.dma.busy)
+enum {
+       CIF_ISP10_ASYNC_JPEG = 0x1,
+       CIF_ISP10_ASYNC_YCFLT = 0x2,
+       CIF_ISP10_ASYNC_ISM = 0x4,
+       CIF_ISP10_ASYNC_DMA = 0x8
+};
+
+#define CIF_ISP10_ALWAYS_ASYNC 0x00
+#define CIF_ISP10_ALWAYS_STALL_ON_NO_BUFS (false)
+
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y))
+#endif
+
+#ifndef DIV_TRUNCATE
+#define DIV_TRUNCATE(x, y) ((x) / (y))
+#endif
+
+/* Structures and Types */
+
+/* Static Functions */
+static const char *cif_isp10_interface_string(
+       enum pltfrm_cam_itf_type itf)
+{
+       switch (itf) {
+       case PLTFRM_CAM_ITF_MIPI:
+               return "MIPI";
+       case PLTFRM_CAM_ITF_BT601_8:
+               return "DVP_BT601_8Bit";
+       case PLTFRM_CAM_ITF_BT656_8:
+               return "DVP_BT656_8Bit";
+       case PLTFRM_CAM_ITF_BT601_10:
+               return "DVP_BT601_10Bit";
+       case PLTFRM_CAM_ITF_BT656_10:
+               return "DVP_BT656_10Bit";
+       case PLTFRM_CAM_ITF_BT601_12:
+               return "DVP_BT601_12Bit";
+       case PLTFRM_CAM_ITF_BT656_12:
+               return "DVP_BT656_12Bit";
+       case PLTFRM_CAM_ITF_BT601_16:
+               return "DVP_BT601_16Bit";
+       case PLTFRM_CAM_ITF_BT656_16:
+               return "DVP_BT656_16Bit";
+       default:
+               return "UNKNOWN/UNSUPPORTED";
+       }
+}
+
+static const char *cif_isp10_img_src_state_string(
+       enum cif_isp10_img_src_state state)
+{
+       switch (state) {
+       case CIF_ISP10_IMG_SRC_STATE_OFF:
+               return "OFF";
+       case CIF_ISP10_IMG_SRC_STATE_SW_STNDBY:
+               return "SW_STNDBY";
+       case CIF_ISP10_IMG_SRC_STATE_STREAMING:
+               return "STREAMING";
+       default:
+               return "UNKNOWN/UNSUPPORTED";
+       }
+}
+
+static const char *cif_isp10_state_string(
+       enum cif_isp10_state state)
+{
+       switch (state) {
+       case CIF_ISP10_STATE_DISABLED:
+               return "DISABLED";
+       case CIF_ISP10_STATE_INACTIVE:
+               return "INACTIVE";
+       case CIF_ISP10_STATE_READY:
+               return "READY";
+       case CIF_ISP10_STATE_STREAMING:
+               return "STREAMING";
+       default:
+               return "UNKNOWN/UNSUPPORTED";
+       }
+}
+
+static const char *cif_isp10_pm_state_string(
+       enum cif_isp10_pm_state pm_state)
+{
+       switch (pm_state) {
+       case CIF_ISP10_PM_STATE_OFF:
+               return "OFF";
+       case CIF_ISP10_PM_STATE_SW_STNDBY:
+               return "STANDBY";
+       case CIF_ISP10_PM_STATE_SUSPENDED:
+               return "SUSPENDED";
+       case CIF_ISP10_PM_STATE_STREAMING:
+               return "STREAMING";
+       default:
+               return "UNKNOWN/UNSUPPORTED";
+       }
+}
+
+static const char *cif_isp10_stream_id_string(
+       enum cif_isp10_stream_id stream_id)
+{
+       switch (stream_id) {
+       case CIF_ISP10_STREAM_SP:
+               return "SP";
+       case CIF_ISP10_STREAM_MP:
+               return "MP";
+       case CIF_ISP10_STREAM_DMA:
+               return "DMA";
+       case CIF_ISP10_STREAM_ISP:
+               return "ISP";
+       default:
+               return "UNKNOWN/UNSUPPORTED";
+       }
+}
+
+static const char *cif_isp10_inp_string(
+       enum cif_isp10_inp inp)
+{
+       switch (inp) {
+       case CIF_ISP10_INP_CSI:
+               return "CSI";
+       case CIF_ISP10_INP_CPI:
+               return "CPI";
+       case CIF_ISP10_INP_DMA:
+               return "DMA(ISP)";
+       case CIF_ISP10_INP_DMA_IE:
+               return "DMA(Image Effects)";
+       case CIF_ISP10_INP_DMA_SP:
+               return "DMA(SP)";
+       default:
+               return "UNKNOWN/UNSUPPORTED";
+       }
+}
+
+enum cif_isp10_inp cif_isp10_input_index2inp(
+       struct cif_isp10_device *dev,
+       unsigned int input)
+{
+       struct pltfrm_cam_itf itf;
+
+       if (input >= dev->img_src_cnt)
+               return input - dev->img_src_cnt + CIF_ISP10_INP_DMA;
+
+       cif_isp10_pltfrm_g_interface_config(
+               dev->img_src_array[input],
+               &itf);
+       if (PLTFRM_CAM_ITF_IS_MIPI(itf.type))
+               return CIF_ISP10_INP_CSI;
+       if (PLTFRM_CAM_ITF_IS_DVP(itf.type))
+               return CIF_ISP10_INP_CPI;
+
+       return -EINVAL;
+}
+
+static const char *cif_isp10_pix_fmt_string(int pixfmt)
+{
+       switch (pixfmt) {
+       case CIF_YUV400:
+               return "YUV400";
+       case CIF_YUV420I:
+               return "YUV420I";
+       case CIF_YUV420SP:
+               return "YUV420SP";
+       case CIF_YUV420P:
+               return "YUV420P";
+       case CIF_YVU420I:
+               return "YVU420I";
+       case CIF_YVU420SP:
+               return "YVU420SP";
+       case CIF_YVU420P:
+               return "YVU420P";
+       case CIF_YUV422I:
+               return "YUV422I";
+       case CIF_YUV422SP:
+               return "YUV422SP";
+       case CIF_YUV422P:
+               return "YUV422P";
+       case CIF_YVU422I:
+               return "YVU422I";
+       case CIF_YVU422SP:
+               return "YVU422SP";
+       case CIF_YVU422P:
+               return "YVU422P";
+       case CIF_YUV444I:
+               return "YUV444I";
+       case CIF_YUV444SP:
+               return "YUV444SP";
+       case CIF_YUV444P:
+               return "YUV444P";
+       case CIF_YVU444I:
+               return "YVU444I";
+       case CIF_YVU444SP:
+               return "YVU444SP";
+       case CIF_YVU444P:
+               return "YVU444SP";
+       case CIF_UYV400:
+               return "UYV400";
+       case CIF_UYV420I:
+               return "UYV420I";
+       case CIF_UYV420SP:
+               return "UYV420SP";
+       case CIF_UYV420P:
+               return "UYV420P";
+       case CIF_VYU420I:
+               return "VYU420I";
+       case CIF_VYU420SP:
+               return "VYU420SP";
+       case CIF_VYU420P:
+               return "VYU420P";
+       case CIF_UYV422I:
+               return "UYV422I";
+       case CIF_UYV422SP:
+               return "UYV422I";
+       case CIF_UYV422P:
+               return "UYV422P";
+       case CIF_VYU422I:
+               return "VYU422I";
+       case CIF_VYU422SP:
+               return "VYU422SP";
+       case CIF_VYU422P:
+               return "VYU422P";
+       case CIF_UYV444I:
+               return "UYV444I";
+       case CIF_UYV444SP:
+               return "UYV444SP";
+       case CIF_UYV444P:
+               return "UYV444P";
+       case CIF_VYU444I:
+               return "VYU444I";
+       case CIF_VYU444SP:
+               return "VYU444SP";
+       case CIF_VYU444P:
+               return "VYU444P";
+       case CIF_RGB565:
+               return "RGB565";
+       case CIF_RGB666:
+               return "RGB666";
+       case CIF_RGB888:
+               return "RGB888";
+       case CIF_BAYER_SBGGR8:
+               return "BAYER BGGR8";
+       case CIF_BAYER_SGBRG8:
+               return "BAYER GBRG8";
+       case CIF_BAYER_SGRBG8:
+               return "BAYER GRBG8";
+       case CIF_BAYER_SRGGB8:
+               return "BAYER RGGB8";
+       case CIF_BAYER_SBGGR10:
+               return "BAYER BGGR10";
+       case CIF_BAYER_SGBRG10:
+               return "BAYER GBRG10";
+       case CIF_BAYER_SGRBG10:
+               return "BAYER GRBG10";
+       case CIF_BAYER_SRGGB10:
+               return "BAYER RGGB10";
+       case CIF_BAYER_SBGGR12:
+               return "BAYER BGGR12";
+       case CIF_BAYER_SGBRG12:
+               return "BAYER GBRG12";
+       case CIF_BAYER_SGRBG12:
+               return "BAYER GRBG12";
+       case CIF_BAYER_SRGGB12:
+               return "BAYER RGGB12";
+       case CIF_DATA:
+               return "DATA";
+       case CIF_JPEG:
+               return "JPEG";
+       default:
+               return "unknown/unsupported";
+       }
+}
+
+static void cif_isp10_debug_print_mi_sp(struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_info(dev->dev,
+               "\n  MI_CTRL 0x%08x/0x%08x\n"
+               "  MI_STATUS 0x%08x\n"
+               "  MI_RIS 0x%08x/0x%08x\n"
+               "  MI_IMSC 0x%08x\n"
+               "  MI_SP_Y_SIZE %d/%d\n"
+               "  MI_SP_CB_SIZE %d/%d\n"
+               "  MI_SP_CR_SIZE %d/%d\n"
+               "  MI_SP_PIC_WIDTH %d\n"
+               "  MI_SP_PIC_HEIGHT %d\n"
+               "  MI_SP_PIC_LLENGTH %d\n"
+               "  MI_SP_PIC_SIZE %d\n"
+               "  MI_SP_Y_BASE_AD 0x%08x/0x%08x\n"
+               "  MI_SP_Y_OFFS_CNT %d/%d\n"
+               "  MI_SP_Y_OFFS_CNT_START %d\n"
+               "  MI_SP_CB_OFFS_CNT %d/%d\n"
+               "  MI_SP_CB_OFFS_CNT_START %d\n"
+               "  MI_SP_CR_OFFS_CNT %d/%d\n"
+               "  MI_SP_CR_OFFS_CNT_START %d\n",
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_CTRL),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_CTRL_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_STATUS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_RIS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MIS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_IMSC),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_SIZE_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CB_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CB_SIZE_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CR_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CR_SIZE_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_PIC_WIDTH),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_PIC_HEIGHT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_LLENGTH),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_PIC_SIZE),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_BASE_AD_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_BASE_AD_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_OFFS_CNT_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_OFFS_CNT_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_OFFS_CNT_START),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CB_OFFS_CNT_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CB_OFFS_CNT_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CB_OFFS_CNT_START),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CR_OFFS_CNT_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CR_OFFS_CNT_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_CR_OFFS_CNT_START));
+}
+
+static void cif_isp10_debug_print_mi_mp(struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_info(dev->dev,
+               "\n  MI_CTRL 0x%08x/0x%08x\n"
+               "  MI_STATUS 0x%08x\n"
+               "  MI_BYTE_CNT %d\n"
+               "  MI_RIS 0x%08x/0x%08x\n"
+               "  MI_IMSC 0x%08x\n"
+               "  MI_MP_Y_SIZE %d/%d\n"
+               "  MI_MP_CB_SIZE %d/%d\n"
+               "  MI_MP_CR_SIZE %d/%d\n"
+               "  MI_MP_Y_BASE_AD 0x%08x/0x%08x\n"
+               "  MI_MP_Y_OFFS_CNT %d/%d\n"
+               "  MI_MP_Y_OFFS_CNT_START %d\n"
+               "  MI_MP_CB_OFFS_CNT %d/%d\n"
+               "  MI_MP_CB_OFFS_CNT_START %d\n"
+               "  MI_MP_CR_OFFS_CNT %d/%d\n"
+               "  MI_MP_CR_OFFS_CNT_START %d\n",
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_CTRL),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_CTRL_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_STATUS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_BYTE_CNT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_RIS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MIS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_IMSC),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_SIZE_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CB_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CB_SIZE_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CR_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CR_SIZE_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_BASE_AD_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_BASE_AD_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_OFFS_CNT_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_OFFS_CNT_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_OFFS_CNT_START),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CB_OFFS_CNT_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CB_OFFS_CNT_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CB_OFFS_CNT_START),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CR_OFFS_CNT_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CR_OFFS_CNT_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CR_OFFS_CNT_START));
+}
+
+static void cif_isp10_debug_print_srsz(struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_info(dev->dev,
+               "\n  SRSZ_CTRL 0x%08x/0x%08x\n"
+               "  SRSZ_SCALE_HY %d/%d\n"
+               "  SRSZ_SCALE_HCB %d/%d\n"
+               "  SRSZ_SCALE_HCR %d/%d\n"
+               "  SRSZ_SCALE_VY %d/%d\n"
+               "  SRSZ_SCALE_VC %d/%d\n"
+               "  SRSZ_PHASE_HY %d/%d\n"
+               "  SRSZ_PHASE_HC %d/%d\n"
+               "  SRSZ_PHASE_VY %d/%d\n"
+               "  SRSZ_PHASE_VC %d/%d\n",
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_CTRL),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_CTRL_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_HY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_HY_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_HCB),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_HCB_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_HCR),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_HCR_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_VY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_VY_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_VC),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_SCALE_VC_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_PHASE_HY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_PHASE_HY_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_PHASE_HC),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_PHASE_HC_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_PHASE_VY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_PHASE_VY_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_PHASE_VC),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_SRSZ_PHASE_VC_SHD));
+}
+
+static void cif_isp10_debug_print_mrsz(struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_info(dev->dev,
+               "\n  MRSZ_CTRL 0x%08x/0x%08x\n"
+               "  MRSZ_SCALE_HY %d/%d\n"
+               "  MRSZ_SCALE_HCB %d/%d\n"
+               "  MRSZ_SCALE_HCR %d/%d\n"
+               "  MRSZ_SCALE_VY %d/%d\n"
+               "  MRSZ_SCALE_VC %d/%d\n"
+               "  MRSZ_PHASE_HY %d/%d\n"
+               "  MRSZ_PHASE_HC %d/%d\n"
+               "  MRSZ_PHASE_VY %d/%d\n"
+               "  MRSZ_PHASE_VC %d/%d\n",
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_CTRL),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_CTRL_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_HY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_HY_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_HCB),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_HCB_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_HCR),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_HCR_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_VY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_VY_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_VC),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_SCALE_VC_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_PHASE_HY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_PHASE_HY_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_PHASE_HC),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_PHASE_HC_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_PHASE_VY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_PHASE_VY_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_PHASE_VC),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MRSZ_PHASE_VC_SHD));
+}
+
+static void cif_isp10_debug_print_block(
+       struct cif_isp10_device *dev,
+       const char *block_name)
+{
+       if (!strncmp(block_name, "all", 3)) {
+               cif_isp10_debug_print_srsz(dev);
+               cif_isp10_debug_print_mrsz(dev);
+               cif_isp10_debug_print_mi_sp(dev);
+               cif_isp10_debug_print_mi_mp(dev);
+       } else if (!strncmp(block_name, "srsz", 4)) {
+               cif_isp10_debug_print_srsz(dev);
+       } else if (!strncmp(block_name, "mrsz", 4)) {
+               cif_isp10_debug_print_mrsz(dev);
+       } else if (!strncmp(block_name, "mi_sp", 5)) {
+               cif_isp10_debug_print_mi_sp(dev);
+       } else if (!strncmp(block_name, "mi_mp", 5)) {
+               cif_isp10_debug_print_mi_mp(dev);
+       } else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unknown block %s\n", block_name);
+       }
+}
+
+static u32 cif_isp10_calc_llength(
+       u32 width,
+       u32 stride,
+       enum cif_isp10_pix_fmt pix_fmt)
+{
+       if (stride == 0)
+               return width;
+
+       if (CIF_ISP10_PIX_FMT_IS_YUV(pix_fmt)) {
+               u32 num_cplanes =
+                       CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(pix_fmt);
+               if (num_cplanes == 0)
+                       return 8 * stride / CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt);
+               else
+                       return stride;
+       } else if (CIF_ISP10_PIX_FMT_IS_RGB(pix_fmt)) {
+               return 8 * stride / CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt);
+       } else {
+               return width;
+       }
+}
+
+static int cif_isp10_set_pm_state(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_pm_state pm_state)
+{
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "%s -> %s\n",
+               cif_isp10_pm_state_string(dev->pm_state),
+               cif_isp10_pm_state_string(pm_state));
+
+       if (dev->pm_state == pm_state)
+               return 0;
+
+       switch (pm_state) {
+       case CIF_ISP10_PM_STATE_OFF:
+       case CIF_ISP10_PM_STATE_SUSPENDED:
+               if ((dev->pm_state == CIF_ISP10_PM_STATE_SW_STNDBY) ||
+                       (dev->pm_state == CIF_ISP10_PM_STATE_STREAMING)) {
+                       pm_runtime_put_sync(dev->dev);
+               }
+               break;
+       case CIF_ISP10_PM_STATE_SW_STNDBY:
+       case CIF_ISP10_PM_STATE_STREAMING:
+               if ((dev->pm_state == CIF_ISP10_PM_STATE_OFF) ||
+                       (dev->pm_state == CIF_ISP10_PM_STATE_SUSPENDED)) {
+                       pm_runtime_get_sync(dev->dev);
+               }
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unknown or unsupported PM state %d\n", pm_state);
+               return -EINVAL;
+       }
+
+       dev->pm_state = pm_state;
+
+       return 0;
+}
+
+static int cif_isp10_img_src_set_state(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_img_src_state state)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "%s -> %s\n",
+               cif_isp10_img_src_state_string(dev->img_src_state),
+               cif_isp10_img_src_state_string(state));
+
+       if (dev->img_src_state == state)
+               return 0;
+
+       switch (state) {
+       case CIF_ISP10_IMG_SRC_STATE_OFF:
+               ret = cif_isp10_img_src_s_power(dev->img_src, false);
+               break;
+       case CIF_ISP10_IMG_SRC_STATE_SW_STNDBY:
+               if (dev->img_src_state == CIF_ISP10_IMG_SRC_STATE_STREAMING) {
+                       ret = cif_isp10_img_src_s_streaming(
+                               dev->img_src, false);
+               } else {
+                       ret = cif_isp10_img_src_s_power(dev->img_src, true);
+               }
+               break;
+       case CIF_ISP10_IMG_SRC_STATE_STREAMING:
+               if (dev->config.flash_mode !=
+                       CIF_ISP10_FLASH_MODE_OFF)
+                       cif_isp10_img_src_s_ctrl(dev->img_src,
+                               CIF_ISP10_CID_FLASH_MODE,
+                               dev->config.flash_mode);
+               ret = cif_isp10_img_src_s_streaming(dev->img_src, true);
+               break;
+       default:
+               break;
+       }
+
+       if ((dev->config.flash_mode != CIF_ISP10_FLASH_MODE_OFF) &&
+               (IS_ERR_VALUE(ret) ||
+               (state == CIF_ISP10_IMG_SRC_STATE_OFF)))
+               cif_isp10_img_src_s_ctrl(dev->img_src,
+                       CIF_ISP10_CID_FLASH_MODE,
+                       CIF_ISP10_FLASH_MODE_OFF);
+
+       if (!IS_ERR_VALUE(ret))
+               dev->img_src_state = state;
+       else
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "failed with err %d\n", ret);
+
+       return ret;
+}
+
+static int cif_isp10_img_srcs_init(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+
+       memset(dev->img_src_array, 0x00, sizeof(dev->img_src_array));
+       dev->img_src_cnt = cif_isp10_pltfrm_get_img_src_device(dev->dev,
+               dev->img_src_array, CIF_ISP10_NUM_INPUTS);
+
+       if (dev->img_src_cnt > 0)
+               return 0;
+
+       dev->img_src_cnt = 0;
+       ret = -EFAULT;
+
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_img_src_select_strm_fmt(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+       u32 index;
+       struct cif_isp10_strm_fmt_desc strm_fmt_desc;
+       struct cif_isp10_strm_fmt request_strm_fmt;
+       bool matching_format_found = false;
+       bool better_match = false;
+       u32 target_width, target_height;
+       u32 img_src_width, img_src_height;
+       u32 best_diff = ~0;
+       int vblanking;
+
+       if (IS_ERR_OR_NULL(dev->img_src)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "no image source selected as input (call s_input first)\n");
+               ret = -EFAULT;
+               goto err;
+       }
+
+       ret = cif_isp10_get_target_frm_size(dev,
+               &target_width, &target_height);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       /* find the best matching format from the image source */
+       /* TODO: frame interval and pixel format handling */
+       for (index = 0;; index++) {
+               if (IS_ERR_VALUE(cif_isp10_img_src_enum_strm_fmts(dev->img_src,
+                       index, &strm_fmt_desc)))
+                       break;
+               if (!strm_fmt_desc.discrete_frmsize) {
+                       if (strm_fmt_desc.min_frmsize.width >= target_width)
+                               img_src_width = strm_fmt_desc.min_frmsize.width;
+                       else if (strm_fmt_desc.max_frmsize.width >=
+                               target_width)
+                               img_src_width = target_width;
+                       else
+                               img_src_width = strm_fmt_desc.max_frmsize.width;
+                       if (strm_fmt_desc.min_frmsize.height >= target_height)
+                               img_src_height =
+                                       strm_fmt_desc.min_frmsize.height;
+                       else if (strm_fmt_desc.max_frmsize.height >=
+                               target_height)
+                               img_src_height = target_height;
+                       else
+                               img_src_height =
+                                       strm_fmt_desc.max_frmsize.height;
+               } else {
+                       img_src_width = strm_fmt_desc.min_frmsize.width;
+                       img_src_height = strm_fmt_desc.min_frmsize.height;
+               }
+               if ((img_src_width >= target_width) &&
+                       (img_src_height >= target_height)) {
+                       u32 diff = abs(
+                               target_height -
+                               (target_width * img_src_height /
+                               img_src_width));
+                       if (matching_format_found) {
+                               if (dev->config.jpeg_config.enable &&
+                               ((img_src_width >=
+                               request_strm_fmt.frm_fmt.width) &&
+                               (img_src_height >
+                               request_strm_fmt.frm_fmt.height)))
+                                       /*
+                                        * for image capturing we try to
+                                        * maximize the size
+                                        */
+                                       better_match = true;
+                               else if (!dev->config.jpeg_config.enable &&
+                               ((strm_fmt_desc.min_intrvl.denominator /
+                               strm_fmt_desc.min_intrvl.numerator) >
+                               (request_strm_fmt.frm_intrvl.denominator /
+                               request_strm_fmt.frm_intrvl.numerator)))
+                                       /* maximize fps */
+                                       better_match = true;
+                               else if (!dev->config.jpeg_config.enable &&
+                               ((strm_fmt_desc.min_intrvl.denominator /
+                               strm_fmt_desc.min_intrvl.numerator) ==
+                               (request_strm_fmt.frm_intrvl.denominator /
+                               request_strm_fmt.frm_intrvl.numerator)) &&
+                               (diff < best_diff))
+                                       /*
+                                        * chose better aspect ratio
+                                        * match if fps equal
+                                        */
+                                       better_match = true;
+                               else
+                                       better_match = false;
+                       }
+
+                       if (!matching_format_found ||
+                               better_match) {
+                               request_strm_fmt.frm_fmt.width =
+                                       strm_fmt_desc.min_frmsize.width;
+                               request_strm_fmt.frm_fmt.height =
+                                       strm_fmt_desc.min_frmsize.height;
+                               request_strm_fmt.frm_fmt.std_id =
+                                       strm_fmt_desc.std_id;
+                               request_strm_fmt.frm_fmt.pix_fmt =
+                                       strm_fmt_desc.pix_fmt;
+                               request_strm_fmt.frm_intrvl.numerator =
+                                       strm_fmt_desc.min_intrvl.numerator;
+                               request_strm_fmt.frm_intrvl.denominator =
+                                       strm_fmt_desc.min_intrvl.denominator;
+                               request_strm_fmt.frm_fmt.defrect =
+                                       strm_fmt_desc.defrect;
+                               best_diff = diff;
+                               matching_format_found = true;
+                       }
+               }
+       }
+
+       if (!matching_format_found) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "no matching image source format (%dx%d) found\n",
+                       target_width, target_height);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       cif_isp10_pltfrm_pr_dbg(
+               dev->dev,
+               "requesting format %s %dx%d(%d,%d,%d,%d)@%d/%dfps from %s\n",
+               cif_isp10_pix_fmt_string(request_strm_fmt.frm_fmt.pix_fmt),
+               request_strm_fmt.frm_fmt.width,
+               request_strm_fmt.frm_fmt.height,
+               request_strm_fmt.frm_fmt.defrect.left,
+               request_strm_fmt.frm_fmt.defrect.top,
+               request_strm_fmt.frm_fmt.defrect.width,
+               request_strm_fmt.frm_fmt.defrect.height,
+               request_strm_fmt.frm_intrvl.denominator,
+               request_strm_fmt.frm_intrvl.numerator,
+               cif_isp10_img_src_g_name(dev->img_src));
+
+       ret = cif_isp10_img_src_s_strm_fmt(dev->img_src, &request_strm_fmt);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       dev->config.img_src_output = request_strm_fmt;
+
+       ret = cif_isp10_img_src_g_ctrl(dev->img_src,
+               CIF_ISP10_CID_VBLANKING, &vblanking);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_dbg(
+                       dev->dev,
+                       "get vblanking failed: %d\n", ret);
+                       vblanking = 0;
+       }
+
+       if (vblanking >= 0)
+               dev->isp_dev.v_blanking_us = vblanking;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+/*
+ * This should only be called when configuring CIF
+ * or at the frame end interrupt
+ */
+static void cif_isp10_config_ism(struct cif_isp10_device *dev, bool async)
+{
+       const struct cif_isp10_ism_config *pconfig =
+               &dev->config.isp_config.ism_config;
+
+       if (pconfig->ism_en) {
+               cif_isp10_pltfrm_pr_dbg(dev->dev, "%dx%d -> %dx%d@(%d,%d)\n",
+                       dev->isp_dev.input_width,
+                       dev->isp_dev.input_height,
+                       pconfig->ism_params.h_size,
+                       pconfig->ism_params.v_size,
+                       pconfig->ism_params.h_offs,
+                       pconfig->ism_params.v_offs);
+               cif_iowrite32(pconfig->ism_params.recenter,
+                       dev->config.base_addr + CIF_ISP_IS_RECENTER);
+               cif_iowrite32(pconfig->ism_params.max_dx,
+                       dev->config.base_addr + CIF_ISP_IS_MAX_DX);
+               cif_iowrite32(pconfig->ism_params.max_dy,
+                       dev->config.base_addr + CIF_ISP_IS_MAX_DY);
+               cif_iowrite32(pconfig->ism_params.displace,
+                       dev->config.base_addr + CIF_ISP_IS_DISPLACE);
+               cif_iowrite32(pconfig->ism_params.h_offs,
+                       dev->config.base_addr + CIF_ISP_IS_H_OFFS);
+               cif_iowrite32(pconfig->ism_params.v_offs,
+                       dev->config.base_addr + CIF_ISP_IS_V_OFFS);
+               cif_iowrite32(pconfig->ism_params.h_size,
+                       dev->config.base_addr + CIF_ISP_IS_H_SIZE);
+               cif_iowrite32(pconfig->ism_params.v_size,
+                       dev->config.base_addr + CIF_ISP_IS_V_SIZE);
+               cif_iowrite32OR(1,
+                       dev->config.base_addr + CIF_ISP_IS_CTRL);
+               dev->config.isp_config.output.width =
+                       dev->config.isp_config.ism_config.ism_params.h_size;
+               dev->config.isp_config.output.height =
+                       dev->config.isp_config.ism_config.ism_params.v_size;
+       } else {
+               cif_iowrite32(pconfig->ism_params.recenter,
+                       dev->config.base_addr + CIF_ISP_IS_RECENTER);
+               cif_iowrite32(pconfig->ism_params.max_dx,
+                       dev->config.base_addr + CIF_ISP_IS_MAX_DX);
+               cif_iowrite32(pconfig->ism_params.max_dy,
+                       dev->config.base_addr + CIF_ISP_IS_MAX_DY);
+               cif_iowrite32(pconfig->ism_params.displace,
+                       dev->config.base_addr + CIF_ISP_IS_DISPLACE);
+               cif_iowrite32(0,
+                       dev->config.base_addr + CIF_ISP_IS_H_OFFS);
+               cif_iowrite32(0,
+                       dev->config.base_addr + CIF_ISP_IS_V_OFFS);
+               cif_iowrite32(dev->config.isp_config.output.width,
+                       dev->config.base_addr + CIF_ISP_IS_H_SIZE);
+               cif_iowrite32(dev->config.isp_config.output.height,
+                       dev->config.base_addr + CIF_ISP_IS_V_SIZE);
+               cif_iowrite32(0,
+                       dev->config.base_addr + CIF_ISP_IS_CTRL);
+       }
+
+       if (async)
+               cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD,
+                       dev->config.base_addr + CIF_ISP_CTRL);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  ISP_IS_H_OFFS %d/%d\n"
+               "  ISP_IS_V_OFFS %d/%d\n"
+               "  ISP_IS_H_SIZE %d/%d\n"
+               "  ISP_IS_V_SIZE %d/%d\n"
+               "  ISP_IS_RECENTER 0x%08x\n"
+               "  ISP_IS_MAX_DX %d\n"
+               "  ISP_IS_MAX_DY %d\n"
+               "  ISP_IS_DISPLACE 0x%08x\n"
+               "  ISP_IS_CTRL 0x%08x\n",
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_H_OFFS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_H_OFFS_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_V_OFFS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_V_OFFS_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_H_SIZE),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_H_SIZE_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_V_SIZE),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_V_SIZE_SHD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_RECENTER),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_MAX_DX),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_MAX_DY),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_DISPLACE),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_ISP_IS_CTRL));
+}
+
+static void cif_isp10_program_jpeg_tables(
+       struct cif_isp10_device *dev)
+{
+       unsigned int ratio = dev->config.jpeg_config.ratio;
+       unsigned int i = 0;
+       unsigned int q, q_next, scale;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "ratio %d\n", ratio);
+
+       /* Y q-table 0 programming */
+       cif_iowrite32(CIF_JPE_TAB_ID_QUANT0,
+               dev->config.base_addr + CIF_JPE_TABLE_ID);
+       if (ratio != 50) {
+               scale = (ratio < 50) ? 5000 / ratio : 200 - (ratio << 1);
+               for (i = 0; i < 32; i++) {
+                       q = yq_table_base_zigzag[i * 2];
+                       q_next = yq_table_base_zigzag[i * 2 + 1];
+                       q = (scale * q + 50) / 100;
+                       q = (q > 1) ? ((q < 255) ? q : 255) : 1;
+                       q_next = (scale * q_next + 50) / 100;
+                       q_next = (q_next > 1) ?
+                               ((q_next < 255) ? q_next : 255) : 1;
+                       cif_iowrite32(q_next + (q << 8),
+                               dev->config.base_addr +
+                               CIF_JPE_TABLE_DATA);
+               }
+       } else {
+               for (i = 0; i < 32; i++) {
+                       q = yq_table_base_zigzag[i * 2];
+                       q_next = yq_table_base_zigzag[i * 2 + 1];
+                       cif_iowrite32(q_next + (q << 8),
+                               dev->config.base_addr +
+                               CIF_JPE_TABLE_DATA);
+               }
+       }
+
+       /* U/V q-table 0 programming */
+       cif_iowrite32(CIF_JPE_TAB_ID_QUANT1,
+               dev->config.base_addr + CIF_JPE_TABLE_ID);
+       if (ratio != 50) {
+               for (i = 0; i < 32; i++) {
+                       q = uvq_table_base_zigzag[i * 2];
+                       q_next = uvq_table_base_zigzag[i * 2 + 1];
+                       q = (scale * q + 50) / 100;
+                       q = (q > 1) ? ((q < 255) ? q : 255) : 1;
+                       q_next = (scale * q_next + 50) / 100;
+                       q_next = (q_next > 1) ?
+                               ((q_next < 255) ? q_next : 255) : 1;
+                       cif_iowrite32(q_next + (q << 8),
+                               dev->config.base_addr +
+                               CIF_JPE_TABLE_DATA);
+               }
+       } else {
+               for (i = 0; i < 32; i++) {
+                       q = uvq_table_base_zigzag[i * 2];
+                       q_next = uvq_table_base_zigzag[i * 2 + 1];
+                       cif_iowrite32(q_next + (q << 8),
+                               dev->config.base_addr +
+                               CIF_JPE_TABLE_DATA);
+               }
+       }
+
+       /* Y AC-table 0 programming */
+       cif_iowrite32(CIF_JPE_TAB_ID_HUFFAC0,
+               dev->config.base_addr + CIF_JPE_TABLE_ID);
+       cif_iowrite32(178, dev->config.base_addr + CIF_JPE_TAC0_LEN);
+       for (i = 0; i < (178 / 2); i++) {
+               cif_iowrite32(ac_luma_table_annex_k[i * 2 + 1] +
+                       (ac_luma_table_annex_k[i * 2] << 8),
+                       dev->config.base_addr +
+                       CIF_JPE_TABLE_DATA);
+       }
+
+       /* U/V AC-table 1 programming */
+       cif_iowrite32(CIF_JPE_TAB_ID_HUFFAC1,
+               dev->config.base_addr + CIF_JPE_TABLE_ID);
+       cif_iowrite32(178, dev->config.base_addr + CIF_JPE_TAC1_LEN);
+       for (i = 0; i < (178 / 2); i++) {
+               cif_iowrite32(ac_chroma_table_annex_k[i * 2 + 1] +
+                       (ac_chroma_table_annex_k[i * 2] << 8),
+                       dev->config.base_addr +
+                       CIF_JPE_TABLE_DATA);
+       }
+
+       /* Y DC-table 0 programming */
+       cif_iowrite32(CIF_JPE_TAB_ID_HUFFDC0,
+               dev->config.base_addr + CIF_JPE_TABLE_ID);
+       cif_iowrite32(28, dev->config.base_addr + CIF_JPE_TDC0_LEN);
+       for (i = 0; i < (28 / 2); i++) {
+               cif_iowrite32(dc_luma_table_annex_k[i * 2 + 1] +
+                       (dc_luma_table_annex_k[i * 2] << 8),
+                       dev->config.base_addr +
+                       CIF_JPE_TABLE_DATA);
+       }
+
+       /* U/V DC-table 1 programming */
+       cif_iowrite32(CIF_JPE_TAB_ID_HUFFDC1,
+               dev->config.base_addr + CIF_JPE_TABLE_ID);
+       cif_iowrite32(28, dev->config.base_addr + CIF_JPE_TDC1_LEN);
+       for (i = 0; i < (28 / 2); i++) {
+               cif_iowrite32(dc_chroma_table_annex_k[i * 2 + 1] +
+               (dc_chroma_table_annex_k[i * 2] << 8),
+               dev->config.base_addr +
+               CIF_JPE_TABLE_DATA);
+       }
+}
+
+static void cif_isp10_select_jpeg_tables(
+       struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       /* Selects quantization table for Y */
+       cif_iowrite32(CIF_JPE_TQ_TAB0,
+               dev->config.base_addr + CIF_JPE_TQ_Y_SELECT);
+       /* Selects quantization table for U */
+       cif_iowrite32(CIF_JPE_TQ_TAB1,
+               dev->config.base_addr + CIF_JPE_TQ_U_SELECT);
+       /* Selects quantization table for V */
+       cif_iowrite32(CIF_JPE_TQ_TAB1,
+               dev->config.base_addr + CIF_JPE_TQ_V_SELECT);
+       /* Selects Huffman DC table */
+       cif_iowrite32(CIF_DC_V_TABLE | CIF_DC_U_TABLE,
+               dev->config.base_addr + CIF_JPE_DC_TABLE_SELECT);
+       /* Selects Huffman AC table */
+       cif_iowrite32(CIF_AC_V_TABLE | CIF_AC_U_TABLE,
+               dev->config.base_addr + CIF_JPE_AC_TABLE_SELECT);
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "\n  JPE_TQ_Y_SELECT 0x%08x\n"
+               "  JPE_TQ_U_SELECT 0x%08x\n"
+               "  JPE_TQ_V_SELECT 0x%08x\n"
+               "  JPE_DC_TABLE_SELECT 0x%08x\n"
+               "  JPE_AC_TABLE_SELECT 0x%08x\n",
+               cif_ioread32(dev->config.base_addr + CIF_JPE_TQ_Y_SELECT),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_TQ_U_SELECT),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_TQ_V_SELECT),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_DC_TABLE_SELECT),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_AC_TABLE_SELECT));
+}
+
+static int cif_isp10_config_img_src(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+       struct isp_supplemental_sensor_mode_data sensor_mode;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
+
+       ret = cif_isp10_img_src_set_state(dev,
+               CIF_ISP10_IMG_SRC_STATE_SW_STNDBY);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       if (!dev->sp_stream.updt_cfg &&
+               !dev->mp_stream.updt_cfg)
+               return 0;
+
+       ret = cif_isp10_pltfrm_g_interface_config(dev->img_src,
+                       &dev->config.cam_itf);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       ret = (int)cif_isp10_img_src_ioctl(dev->img_src,
+               RK_VIDIOC_SENSOR_MODE_DATA, &sensor_mode);
+       if (IS_ERR_VALUE(ret)) {
+               dev->img_src_exps.exp_valid_frms = 2;
+       } else {
+               if ((sensor_mode.exposure_valid_frame < 2) ||
+                       (sensor_mode.exposure_valid_frame > 6))
+                       dev->img_src_exps.exp_valid_frms = 2;
+               else
+                       dev->img_src_exps.exp_valid_frms =
+                               sensor_mode.exposure_valid_frame;
+       }
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "cam_itf: (type: 0x%x, dphy: %d, vc: %d, nb_lanes: %d, bitrate: %d)",
+               dev->config.cam_itf.type,
+               dev->config.cam_itf.cfg.mipi.dphy_index,
+               dev->config.cam_itf.cfg.mipi.vc,
+               dev->config.cam_itf.cfg.mipi.nb_lanes,
+               dev->config.cam_itf.cfg.mipi.bit_rate);
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_config_isp(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+       u32 h_offs;
+       u32 v_offs;
+       u32 yuv_seq = 0;
+       u32 bpp;
+       u32 isp_input_sel = 0;
+       u32 isp_bayer_pat = 0;
+       u32 acq_mult = 1;
+       u32 irq_mask = 0;
+       u32 signal = 0;
+       enum cif_isp10_pix_fmt in_pix_fmt;
+       struct cif_isp10_frm_fmt *output;
+       struct pltfrm_cam_itf *cam_itf;
+
+       if (dev->config.input_sel == CIF_ISP10_INP_DMA_IE) {
+               dev->config.isp_config.output =
+                       dev->config.mi_config.dma.output;
+               cifisp_disable_isp(&dev->isp_dev);
+               return 0;
+       } else if (dev->config.input_sel == CIF_ISP10_INP_DMA_SP) {
+               cif_iowrite32AND(~CIF_ICCL_ISP_CLK,
+                       dev->config.base_addr + CIF_ICCL);
+               cif_isp10_pltfrm_pr_dbg(NULL,
+                       "ISP disabled\n");
+               return 0;
+       }
+       cif_iowrite32OR(CIF_ICCL_ISP_CLK,
+               dev->config.base_addr + CIF_ICCL);
+
+       in_pix_fmt = dev->config.isp_config.input->pix_fmt;
+
+       output = &dev->config.isp_config.output;
+       cam_itf = &dev->config.cam_itf;
+
+       if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(in_pix_fmt)) {
+               if (!dev->config.mi_config.raw_enable) {
+                       output->pix_fmt = CIF_YUV422I;
+
+                       if ((dev->mp_stream.state == CIF_ISP10_STATE_READY) &&
+                               (dev->sp_stream.state ==
+                               CIF_ISP10_STATE_READY)) {
+                               if (dev->config.mi_config.mp.output.
+                                       quantization !=
+                                       dev->config.mi_config.sp.output.
+                                       quantization) {
+                                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                               "colorspace quantization (mp: %d, sp: %d) is not support!\n",
+                                               dev->
+                                               config.mi_config.mp.output.
+                                               quantization,
+                                               dev->
+                                               config.mi_config.sp.output.
+                                               quantization);
+                               }
+                       }
+
+                       if (dev->sp_stream.state == CIF_ISP10_STATE_READY) {
+                               output->quantization =
+                               dev->config.mi_config.sp.output.quantization;
+                       }
+
+                       if (dev->mp_stream.state == CIF_ISP10_STATE_READY) {
+                               output->quantization =
+                               dev->config.mi_config.sp.output.quantization;
+                       }
+
+                       cif_iowrite32(0xc,
+                               dev->config.base_addr + CIF_ISP_DEMOSAIC);
+
+                       if (PLTFRM_CAM_ITF_IS_BT656(dev->config.cam_itf.type)) {
+                               cif_iowrite32(
+                                       CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656,
+                                       dev->config.base_addr + CIF_ISP_CTRL);
+                       } else {
+                               cif_iowrite32(
+                                       CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601,
+                                       dev->config.base_addr + CIF_ISP_CTRL);
+                       }
+               } else {
+                       output->pix_fmt = in_pix_fmt;
+                       if (PLTFRM_CAM_ITF_IS_BT656(dev->config.cam_itf.type)) {
+                               cif_iowrite32(
+                                       CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656,
+                                       dev->config.base_addr + CIF_ISP_CTRL);
+                       } else {
+                               cif_iowrite32(CIF_ISP_CTRL_ISP_MODE_RAW_PICT,
+                                       dev->config.base_addr + CIF_ISP_CTRL);
+                       }
+               }
+
+               bpp = CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt);
+               if (bpp == 8) {
+                       isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB;
+               } else if (bpp == 10) {
+                       isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB;
+               } else if (bpp == 12) {
+                       isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "%d bits per pixel not supported\n", bpp);
+                       ret = -EINVAL;
+                       goto err;
+               }
+               if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_BGGR(in_pix_fmt)) {
+                       isp_bayer_pat = CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR;
+               } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GBRG(in_pix_fmt)) {
+                       isp_bayer_pat = CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG;
+               } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GRBG(in_pix_fmt)) {
+                       isp_bayer_pat = CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG;
+               } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_RGGB(in_pix_fmt)) {
+                       isp_bayer_pat = CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB;
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "BAYER pattern not supported\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else if (CIF_ISP10_PIX_FMT_IS_YUV(in_pix_fmt)) {
+               output->pix_fmt = in_pix_fmt;
+               acq_mult = 2;
+               if (dev->config.input_sel == CIF_ISP10_INP_DMA) {
+                       bpp = CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt);
+                       bpp =
+                               bpp * 4 /
+                               (4 + (CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+                                       in_pix_fmt) *
+                               CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+                                       in_pix_fmt) / 2));
+                       if (bpp == 8) {
+                               isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB;
+                       } else if (bpp == 10) {
+                               isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB;
+                       } else if (bpp == 12) {
+                               isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
+                       } else {
+                               cif_isp10_pltfrm_pr_err(dev->dev,
+                                       "format %s not supported, invalid bpp %d\n",
+                                       cif_isp10_pix_fmt_string(in_pix_fmt),
+                                       bpp);
+                               ret = -EINVAL;
+                               goto err;
+                       }
+                       cif_iowrite32(CIF_ISP_CTRL_ISP_MODE_ITU601,
+                               dev->config.base_addr + CIF_ISP_CTRL);
+               } else{
+                       if (PLTFRM_CAM_ITF_IS_MIPI(
+                               dev->config.cam_itf.type)) {
+                               isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
+                               cif_iowrite32(CIF_ISP_CTRL_ISP_MODE_ITU601,
+                                       dev->config.base_addr + CIF_ISP_CTRL);
+                       } else if (PLTFRM_CAM_ITF_IS_DVP(
+                               dev->config.cam_itf.type)) {
+                               if (PLTFRM_CAM_ITF_IS_BT656(
+                                       dev->config.cam_itf.type)) {
+                                       cif_iowrite32(
+                                       CIF_ISP_CTRL_ISP_MODE_ITU656,
+                                       dev->config.base_addr +
+                                       CIF_ISP_CTRL);
+                               } else {
+                                       cif_iowrite32(
+                                       CIF_ISP_CTRL_ISP_MODE_ITU601,
+                                       dev->config.base_addr +
+                                       CIF_ISP_CTRL);
+                               }
+
+                               switch (PLTFRM_CAM_ITF_DVP_BW(
+                               dev->config.cam_itf.type)) {
+                               case 8:
+                                       isp_input_sel =
+                                       CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO;
+                                       break;
+                               case 10:
+                                       isp_input_sel =
+                                       CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO;
+                                       break;
+                               case 12:
+                                       isp_input_sel =
+                                       CIF_ISP_ACQ_PROP_IN_SEL_12B;
+                                       break;
+                               default:
+                                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                               "%s isn't support for cif isp10\n",
+                                               cif_isp10_interface_string(
+                                               dev->config.cam_itf.type));
+                                       break;
+                               }
+                       } else {
+                               cif_isp10_pltfrm_pr_err(dev->dev,
+                                       "%s isn't support for cif isp10\n",
+                                       cif_isp10_interface_string(
+                                       dev->config.cam_itf.type));
+                       }
+                       /*
+                        * ISP DATA LOSS is only meaningful
+                        * when input is not DMA
+                        */
+                       irq_mask |= CIF_ISP_DATA_LOSS;
+               }
+               if (CIF_ISP10_PIX_FMT_YUV_IS_YC_SWAPPED(in_pix_fmt)) {
+                       yuv_seq = CIF_ISP_ACQ_PROP_CBYCRY;
+                       cif_isp10_pix_fmt_set_yc_swapped(output->pix_fmt, 0);
+               } else if (CIF_ISP10_PIX_FMT_YUV_IS_UV_SWAPPED(in_pix_fmt)) {
+                       yuv_seq = CIF_ISP_ACQ_PROP_YCRYCB;
+               } else {
+                       yuv_seq = CIF_ISP_ACQ_PROP_YCBYCR;
+               }
+       } else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "format %s not supported\n",
+                       cif_isp10_pix_fmt_string(in_pix_fmt));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* Set up input acquisition properties*/
+       if (PLTFRM_CAM_ITF_IS_DVP(cam_itf->type)) {
+               signal =
+                       ((cam_itf->cfg.dvp.pclk == PLTFRM_CAM_SDR_POS_EDG) ?
+                       CIF_ISP_ACQ_PROP_POS_EDGE : CIF_ISP_ACQ_PROP_NEG_EDGE);
+
+               if (PLTFRM_CAM_ITF_IS_BT601(cam_itf->type)) {
+                       signal |=
+                               (cam_itf->cfg.dvp.vsync ==
+                               PLTFRM_CAM_SIGNAL_HIGH_LEVEL) ?
+                               CIF_ISP_ACQ_PROP_VSYNC_HIGH :
+                               CIF_ISP_ACQ_PROP_VSYNC_LOW;
+
+                       signal |=
+                               (cam_itf->cfg.dvp.hsync ==
+                               PLTFRM_CAM_SIGNAL_HIGH_LEVEL) ?
+                               CIF_ISP_ACQ_PROP_HSYNC_HIGH :
+                               CIF_ISP_ACQ_PROP_HSYNC_LOW;
+
+               } else {
+                       signal |= CIF_ISP_ACQ_PROP_HSYNC_HIGH |
+                                       CIF_ISP_ACQ_PROP_VSYNC_HIGH;
+               }
+       } else {
+               signal = CIF_ISP_ACQ_PROP_NEG_EDGE |
+                             CIF_ISP_ACQ_PROP_HSYNC_HIGH |
+                             CIF_ISP_ACQ_PROP_VSYNC_HIGH;
+       }
+
+       cif_iowrite32(signal |
+                             yuv_seq |
+                             CIF_ISP_ACQ_PROP_FIELD_SEL_ALL |
+                             isp_input_sel |
+                             isp_bayer_pat |
+                             (0 << 20),  /* input_selection_no_app */
+                             dev->config.base_addr + CIF_ISP_ACQ_PROP);
+       cif_iowrite32(0,
+               dev->config.base_addr + CIF_ISP_ACQ_NR_FRAMES);
+
+       /* Acquisition Size */
+       cif_iowrite32(dev->config.isp_config.input->defrect.left,
+               dev->config.base_addr + CIF_ISP_ACQ_H_OFFS);
+       cif_iowrite32(dev->config.isp_config.input->defrect.top,
+               dev->config.base_addr + CIF_ISP_ACQ_V_OFFS);
+       cif_iowrite32(
+               acq_mult * dev->config.isp_config.input->defrect.width,
+               dev->config.base_addr + CIF_ISP_ACQ_H_SIZE);
+       cif_iowrite32(
+               dev->config.isp_config.input->defrect.height,
+               dev->config.base_addr + CIF_ISP_ACQ_V_SIZE);
+
+       /* do cropping to match output aspect ratio */
+       ret = cif_isp10_calc_isp_cropping(dev,
+               &output->width, &output->height,
+               &h_offs, &v_offs);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       cif_iowrite32(v_offs,
+               dev->config.base_addr + CIF_ISP_OUT_V_OFFS);
+       cif_iowrite32(h_offs,
+               dev->config.base_addr + CIF_ISP_OUT_H_OFFS);
+       cif_iowrite32(output->width,
+               dev->config.base_addr + CIF_ISP_OUT_H_SIZE);
+       cif_iowrite32(output->height,
+               dev->config.base_addr + CIF_ISP_OUT_V_SIZE);
+
+       dev->isp_dev.input_width =
+               dev->config.isp_config.input->defrect.width;
+       dev->isp_dev.input_height =
+               dev->config.isp_config.input->defrect.height;
+
+       /* interrupt mask */
+       irq_mask |=
+               CIF_ISP_FRAME |
+               CIF_ISP_PIC_SIZE_ERROR |
+               CIF_ISP_FRAME_IN |
+               CIF_ISP_V_START;
+       cif_iowrite32(irq_mask,
+               dev->config.base_addr + CIF_ISP_IMSC);
+
+       if (!dev->config.mi_config.raw_enable)
+               cifisp_configure_isp(&dev->isp_dev,
+                       in_pix_fmt,
+                       output->quantization);
+       else
+               cifisp_disable_isp(&dev->isp_dev);
+
+       cif_isp10_pltfrm_pr_dbg(
+               dev->dev,
+               "\n  ISP_CTRL 0x%08x\n"
+               "  ISP_IMSC 0x%08x\n"
+               "  ISP_ACQ_PROP 0x%08x\n"
+               "  ISP_ACQ %dx%d@(%d,%d)\n"
+               "  ISP_OUT %dx%d@(%d,%d)\n"
+               "  ISP_IS %dx%d@(%d,%d)\n",
+               cif_ioread32(dev->config.base_addr + CIF_ISP_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_IMSC),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_PROP),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_H_SIZE),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_V_SIZE),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_H_OFFS),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_V_OFFS),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_OUT_H_SIZE),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_OUT_V_SIZE),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_OUT_H_OFFS),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_OUT_V_OFFS),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_IS_H_SIZE),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_IS_V_SIZE),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_IS_H_OFFS),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_IS_V_OFFS));
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_config_mipi(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+       u32 data_type;
+       u32 mipi_ctrl;
+       u32 shutdown_lanes;
+       u32 i;
+       enum cif_isp10_pix_fmt in_pix_fmt;
+
+       if (!CIF_ISP10_INP_IS_MIPI(dev->config.input_sel)) {
+               cif_iowrite32AND(~CIF_ICCL_MIPI_CLK,
+                       dev->config.base_addr + CIF_ICCL);
+               cif_isp10_pltfrm_pr_dbg(NULL,
+                       "MIPI disabled\n");
+               return 0;
+       }
+       cif_iowrite32OR(CIF_ICCL_MIPI_CLK,
+               dev->config.base_addr + CIF_ICCL);
+
+       in_pix_fmt = dev->config.img_src_output.frm_fmt.pix_fmt;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "input %s, vc = %d, nb_lanes = %d\n",
+               cif_isp10_inp_string(dev->config.input_sel),
+               dev->config.cam_itf.cfg.mipi.vc,
+               dev->config.cam_itf.cfg.mipi.nb_lanes);
+
+       if ((dev->config.cam_itf.cfg.mipi.nb_lanes == 0) ||
+               (dev->config.cam_itf.cfg.mipi.nb_lanes > 4)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "invalid number (%d) of MIPI lanes, valid range is [1..4]\n",
+                       dev->config.cam_itf.cfg.mipi.nb_lanes);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       shutdown_lanes = 0x00;
+       for (i = 0; i < dev->config.cam_itf.cfg.mipi.nb_lanes; i++)
+               shutdown_lanes |= (1 << i);
+
+       mipi_ctrl =
+               CIF_MIPI_CTRL_NUM_LANES(
+                       dev->config.cam_itf.cfg.mipi.nb_lanes - 1) |
+               CIF_MIPI_CTRL_ERR_SOT_HS_ENA |
+               CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP |
+               CIF_MIPI_CTRL_SHUTDOWNLANES(shutdown_lanes) |
+               CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_ENA |
+               CIF_MIPI_CTRL_ERR_SOT_HS_ENA |
+               CIF_MIPI_CTRL_CLOCKLANE_ENA;
+
+       cif_iowrite32(mipi_ctrl,
+               dev->config.base_addr + CIF_MIPI_CTRL);
+
+       /* mipi_dphy */
+       cif_isp10_pltfrm_mipi_dphy_config(dev);
+
+       /* Configure Data Type and Virtual Channel */
+       if (CIF_ISP10_PIX_FMT_IS_YUV(in_pix_fmt)) {
+               if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 12))
+                       data_type = CSI2_DT_YUV420_8b;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 15))
+                       data_type = CSI2_DT_YUV420_10b;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 4) &&
+                       (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 16))
+                       data_type = CSI2_DT_YUV422_8b;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 4) &&
+                       (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 20))
+                       data_type = CSI2_DT_YUV422_10b;
+               else {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "unsupported format %s\n",
+                               cif_isp10_pix_fmt_string(in_pix_fmt));
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(in_pix_fmt)) {
+               if (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 8) {
+                       data_type = CSI2_DT_RAW8;
+               } else if (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 10) {
+                       data_type = CSI2_DT_RAW10;
+               } else if (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 12) {
+                       data_type = CSI2_DT_RAW12;
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "unsupported format %s\n",
+                               cif_isp10_pix_fmt_string(in_pix_fmt));
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else if (in_pix_fmt == CIF_RGB565) {
+               data_type = CSI2_DT_RGB565;
+       } else if (in_pix_fmt == CIF_RGB666) {
+               data_type = CSI2_DT_RGB666;
+       } else if (in_pix_fmt == CIF_RGB888) {
+               data_type = CSI2_DT_RGB888;
+       } else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unsupported format %s\n",
+                       cif_isp10_pix_fmt_string(in_pix_fmt));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       cif_iowrite32(
+               CIF_MIPI_DATA_SEL_DT(data_type) |
+               CIF_MIPI_DATA_SEL_VC(
+                       dev->config.cam_itf.cfg.mipi.vc),
+               dev->config.base_addr + CIF_MIPI_IMG_DATA_SEL);
+
+       /* Enable MIPI interrupts */
+       cif_iowrite32(~0,
+               dev->config.base_addr + CIF_MIPI_ICR);
+       /*
+        * Disable CIF_MIPI_ERR_DPHY interrupt here temporary for
+        * isp bus may be dead when switch isp.
+        */
+       cif_iowrite32(
+               CIF_MIPI_FRAME_END |
+               CIF_MIPI_ERR_CSI |
+               CIF_MIPI_ERR_DPHY |
+               CIF_MIPI_SYNC_FIFO_OVFLW(3) |
+               CIF_MIPI_ADD_DATA_OVFLW,
+               dev->config.base_addr + CIF_MIPI_IMSC);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  MIPI_CTRL 0x%08x\n"
+               "  MIPI_IMG_DATA_SEL 0x%08x\n"
+               "  MIPI_STATUS 0x%08x\n"
+               "  MIPI_IMSC 0x%08x\n",
+               cif_ioread32(dev->config.base_addr + CIF_MIPI_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_MIPI_IMG_DATA_SEL),
+               cif_ioread32(dev->config.base_addr + CIF_MIPI_STATUS),
+               cif_ioread32(dev->config.base_addr + CIF_MIPI_IMSC));
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_config_mi_mp(
+       struct cif_isp10_device *dev)
+{
+       enum cif_isp10_pix_fmt out_pix_fmt =
+               dev->config.mi_config.mp.output.pix_fmt;
+       u32 llength =
+               dev->config.mi_config.mp.llength;
+       u32 width =
+               dev->config.mi_config.mp.output.width;
+       u32 height =
+               dev->config.mi_config.mp.output.height;
+       u32 writeformat = CIF_ISP10_BUFF_FMT_PLANAR;
+       u32 swap_cb_cr = 0;
+       u32 bpp = CIF_ISP10_PIX_FMT_GET_BPP(out_pix_fmt);
+       u32 size = llength * height * bpp / 8;
+       u32 mi_ctrl;
+
+       dev->config.mi_config.mp.input =
+               &dev->config.mp_config.rsz_config.output;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s %dx%d, llength = %d\n",
+               cif_isp10_pix_fmt_string(out_pix_fmt),
+               width,
+               height,
+               llength);
+
+       dev->config.mi_config.mp.y_size = size;
+       dev->config.mi_config.mp.cb_size = 0;
+       dev->config.mi_config.mp.cr_size = 0;
+       if (CIF_ISP10_PIX_FMT_IS_YUV(out_pix_fmt)) {
+               u32 num_cplanes =
+                       CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(out_pix_fmt);
+               if (num_cplanes == 0) {
+                       writeformat = CIF_ISP10_BUFF_FMT_INTERLEAVED;
+               } else {
+                       dev->config.mi_config.mp.y_size =
+                               (dev->config.mi_config.mp.y_size * 4) /
+                               (4 + (CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+                                       out_pix_fmt) *
+                               CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+                                       out_pix_fmt) / 2));
+                       dev->config.mi_config.mp.cb_size =
+                               size -
+                               dev->config.mi_config.mp.y_size;
+                       if (num_cplanes == 1) {
+                               writeformat = CIF_ISP10_BUFF_FMT_SEMIPLANAR;
+                       } else if (num_cplanes == 2) {
+                               writeformat = CIF_ISP10_BUFF_FMT_PLANAR;
+                               dev->config.mi_config.mp.cb_size /= 2;
+                       }
+                       /* for U<->V swapping: */
+                       dev->config.mi_config.mp.cr_size =
+                               dev->config.mi_config.mp.cb_size;
+               }
+               if (CIF_ISP10_PIX_FMT_YUV_IS_UV_SWAPPED(out_pix_fmt))
+                       swap_cb_cr = CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP;
+
+               if (writeformat == CIF_ISP10_BUFF_FMT_SEMIPLANAR) {
+                       dev->config.mi_config.mp.cb_offs =
+                           dev->config.mi_config.mp.y_size;
+                       dev->config.mi_config.mp.cr_offs =
+                           dev->config.mi_config.mp.cb_offs;
+               } else if (writeformat == CIF_ISP10_BUFF_FMT_PLANAR) {
+                       if (swap_cb_cr) {
+                               swap_cb_cr = 0;
+                               dev->config.mi_config.mp.cr_offs =
+                                       dev->config.mi_config.mp.y_size;
+                               dev->config.mi_config.mp.cb_offs =
+                                       dev->config.mi_config.mp.cr_offs +
+                                       dev->config.mi_config.mp.cr_size;
+                       } else {
+                               dev->config.mi_config.mp.cb_offs =
+                                       dev->config.mi_config.mp.y_size;
+                               dev->config.mi_config.mp.cr_offs =
+                                       dev->config.mi_config.mp.cb_offs +
+                                       dev->config.mi_config.mp.cb_size;
+                       }
+               }
+       } else if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(out_pix_fmt)) {
+               if (CIF_ISP10_PIX_FMT_GET_BPP(out_pix_fmt) > 8) {
+                       writeformat = CIF_ISP10_BUFF_FMT_RAW12;
+                       dev->config.mi_config.mp.y_size = width * height * 2;
+               } else {
+                       writeformat = CIF_ISP10_BUFF_FMT_RAW8;
+                       dev->config.mi_config.mp.y_size = width * height;
+               }
+               dev->config.mi_config.mp.cb_offs = 0x00;
+               dev->config.mi_config.mp.cr_offs = 0x00;
+               dev->config.mi_config.mp.cb_size = 0x00;
+               dev->config.mi_config.mp.cr_size = 0x00;
+       }
+
+       cif_iowrite32_verify(dev->config.mi_config.mp.y_size,
+               dev->config.base_addr + CIF_MI_MP_Y_SIZE_INIT,
+               CIF_MI_ADDR_SIZE_ALIGN_MASK);
+       cif_iowrite32_verify(dev->config.mi_config.mp.cb_size,
+               dev->config.base_addr + CIF_MI_MP_CB_SIZE_INIT,
+               CIF_MI_ADDR_SIZE_ALIGN_MASK);
+       cif_iowrite32_verify(dev->config.mi_config.mp.cr_size,
+               dev->config.base_addr + CIF_MI_MP_CR_SIZE_INIT,
+               CIF_MI_ADDR_SIZE_ALIGN_MASK);
+       cif_iowrite32OR_verify(CIF_MI_MP_FRAME,
+               dev->config.base_addr +
+               CIF_MI_IMSC, ~0);
+
+       if (swap_cb_cr) {
+               cif_iowrite32OR(swap_cb_cr,
+                       dev->config.base_addr + CIF_MI_XTD_FORMAT_CTRL);
+       }
+
+       mi_ctrl = cif_ioread32(dev->config.base_addr + CIF_MI_CTRL) |
+               CIF_MI_CTRL_MP_WRITE_FMT(writeformat) |
+               CIF_MI_CTRL_BURST_LEN_LUM_64 |
+               CIF_MI_CTRL_BURST_LEN_CHROM_64 |
+               CIF_MI_CTRL_INIT_BASE_EN |
+               CIF_MI_CTRL_INIT_OFFSET_EN |
+               CIF_MI_MP_AUTOUPDATE_ENABLE;
+
+       cif_iowrite32_verify(mi_ctrl,
+               dev->config.base_addr + CIF_MI_CTRL, ~0);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  MI_CTRL 0x%08x\n"
+               "  MI_STATUS 0x%08x\n"
+               "  MI_MP_Y_SIZE %d\n"
+               "  MI_MP_CB_SIZE %d\n"
+               "  MI_MP_CR_SIZE %d\n",
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_CTRL),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_STATUS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CB_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_CR_SIZE_INIT));
+
+       return 0;
+}
+
+static int cif_isp10_config_mi_sp(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+       enum cif_isp10_pix_fmt out_pix_fmt =
+               dev->config.mi_config.sp.output.pix_fmt;
+       enum cif_isp10_pix_fmt in_pix_fmt =
+               dev->config.sp_config.rsz_config.output.pix_fmt;
+       u32 llength =
+               dev->config.mi_config.sp.llength;
+       u32 width =
+               dev->config.mi_config.sp.output.width;
+       u32 height =
+               dev->config.mi_config.sp.output.height;
+       u32 writeformat = CIF_ISP10_BUFF_FMT_PLANAR;
+       u32 swap_cb_cr = 0;
+       u32 bpp = CIF_ISP10_PIX_FMT_GET_BPP(out_pix_fmt);
+       u32 size = llength * height * bpp / 8;
+       u32 input_format = 0;
+       u32 output_format;
+       u32 mi_ctrl;
+
+       dev->config.mi_config.sp.input =
+               &dev->config.sp_config.rsz_config.output;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s %dx%d, llength = %d\n",
+               cif_isp10_pix_fmt_string(out_pix_fmt),
+               width,
+               height,
+               llength);
+
+       if (!CIF_ISP10_PIX_FMT_IS_YUV(in_pix_fmt)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unsupported format %s (must be YUV)\n",
+                       cif_isp10_pix_fmt_string(in_pix_fmt));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       dev->config.mi_config.sp.y_size = size;
+       dev->config.mi_config.sp.cb_size = 0;
+       dev->config.mi_config.sp.cr_size = 0;
+       if (CIF_ISP10_PIX_FMT_IS_YUV(out_pix_fmt)) {
+               u32 num_cplanes =
+                       CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(out_pix_fmt);
+               if (num_cplanes == 0) {
+                       writeformat = CIF_ISP10_BUFF_FMT_INTERLEAVED;
+               } else {
+                       dev->config.mi_config.sp.y_size =
+                               (dev->config.mi_config.sp.y_size * 4) /
+                               (4 + (CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+                                       out_pix_fmt) *
+                               CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+                                       out_pix_fmt) / 2));
+                       dev->config.mi_config.sp.cb_size =
+                               size -
+                               dev->config.mi_config.sp.y_size;
+                       if (num_cplanes == 1) {
+                               writeformat = CIF_ISP10_BUFF_FMT_SEMIPLANAR;
+                       } else if (num_cplanes == 2) {
+                               writeformat = CIF_ISP10_BUFF_FMT_PLANAR;
+                               dev->config.mi_config.sp.cb_size /= 2;
+                       }
+                       /* for U<->V swapping: */
+                       dev->config.mi_config.sp.cr_size =
+                               dev->config.mi_config.sp.cb_size;
+               }
+               if (CIF_ISP10_PIX_FMT_YUV_IS_UV_SWAPPED(out_pix_fmt))
+                       swap_cb_cr = CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP;
+
+               if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 0) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 0))
+                       output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV400;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 2))
+                       output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV420;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
+                       output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV422;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 4) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
+                       output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV444;
+               else {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "unsupported YUV output format %s\n",
+                               cif_isp10_pix_fmt_string(out_pix_fmt));
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else if (CIF_ISP10_PIX_FMT_IS_RGB(out_pix_fmt)) {
+               if (out_pix_fmt == CIF_RGB565) {
+                       output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_RGB565;
+               } else if (out_pix_fmt == CIF_RGB666) {
+                       output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_RGB666;
+               } else if (out_pix_fmt == CIF_RGB888) {
+                       output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_RGB888;
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "unsupported RGB output format %s\n",
+                               cif_isp10_pix_fmt_string(out_pix_fmt));
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unsupported output format %s\n",
+                       cif_isp10_pix_fmt_string(out_pix_fmt));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 0) &&
+               (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 0))
+               input_format = CIF_MI_CTRL_SP_INPUT_FMT_YUV400;
+       else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+               (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 2))
+               input_format = CIF_MI_CTRL_SP_INPUT_FMT_YUV420;
+       else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+               (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 4))
+               input_format = CIF_MI_CTRL_SP_INPUT_FMT_YUV422;
+       else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 4) &&
+               (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 4))
+               input_format = CIF_MI_CTRL_SP_INPUT_FMT_YUV444;
+       else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unsupported YUV input format %s\n",
+                       cif_isp10_pix_fmt_string(in_pix_fmt));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (writeformat == CIF_ISP10_BUFF_FMT_SEMIPLANAR) {
+               dev->config.mi_config.sp.cb_offs =
+                   dev->config.mi_config.sp.y_size;
+               dev->config.mi_config.sp.cr_offs =
+                   dev->config.mi_config.sp.cb_offs;
+       } else if (writeformat == CIF_ISP10_BUFF_FMT_PLANAR) {
+               if (swap_cb_cr) {
+                       swap_cb_cr = 0;
+                       dev->config.mi_config.sp.cr_offs =
+                               dev->config.mi_config.sp.y_size;
+                       dev->config.mi_config.sp.cb_offs =
+                               dev->config.mi_config.sp.cr_offs +
+                               dev->config.mi_config.sp.cr_size;
+               } else {
+                       dev->config.mi_config.sp.cb_offs =
+                               dev->config.mi_config.sp.y_size;
+                       dev->config.mi_config.sp.cr_offs =
+                               dev->config.mi_config.sp.cb_offs +
+                               dev->config.mi_config.sp.cb_size;
+               }
+       }
+
+       cif_iowrite32_verify(dev->config.mi_config.sp.y_size,
+               dev->config.base_addr + CIF_MI_SP_Y_SIZE_INIT,
+               CIF_MI_ADDR_SIZE_ALIGN_MASK);
+       cif_iowrite32_verify(dev->config.mi_config.sp.y_size,
+               dev->config.base_addr + CIF_MI_SP_Y_PIC_SIZE,
+               CIF_MI_ADDR_SIZE_ALIGN_MASK);
+       cif_iowrite32_verify(dev->config.mi_config.sp.cb_size,
+               dev->config.base_addr + CIF_MI_SP_CB_SIZE_INIT,
+               CIF_MI_ADDR_SIZE_ALIGN_MASK);
+       cif_iowrite32_verify(dev->config.mi_config.sp.cr_size,
+               dev->config.base_addr + CIF_MI_SP_CR_SIZE_INIT,
+               CIF_MI_ADDR_SIZE_ALIGN_MASK);
+       cif_iowrite32_verify(width,
+               dev->config.base_addr + CIF_MI_SP_Y_PIC_WIDTH, ~0x3);
+       cif_iowrite32_verify(height,
+               dev->config.base_addr + CIF_MI_SP_Y_PIC_HEIGHT, ~0x3);
+       cif_iowrite32_verify(llength,
+               dev->config.base_addr + CIF_MI_SP_Y_LLENGTH, ~0x3);
+       cif_iowrite32OR_verify(CIF_MI_SP_FRAME,
+               dev->config.base_addr +
+               CIF_MI_IMSC, ~0);
+
+       if (swap_cb_cr) {
+               cif_iowrite32OR(swap_cb_cr,
+                       dev->config.base_addr + CIF_MI_XTD_FORMAT_CTRL);
+       }
+
+       mi_ctrl = cif_ioread32(dev->config.base_addr + CIF_MI_CTRL) |
+               CIF_MI_CTRL_SP_WRITE_FMT(writeformat) |
+               input_format |
+               output_format |
+               CIF_MI_CTRL_BURST_LEN_LUM_64 |
+               CIF_MI_CTRL_BURST_LEN_CHROM_64 |
+               CIF_MI_CTRL_INIT_BASE_EN |
+               CIF_MI_CTRL_INIT_OFFSET_EN |
+               CIF_MI_SP_AUTOUPDATE_ENABLE;
+       cif_iowrite32_verify(mi_ctrl,
+               dev->config.base_addr + CIF_MI_CTRL, ~0);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  MI_CTRL 0x%08x\n"
+               "  MI_STATUS 0x%08x\n"
+               "  MI_SP_Y_SIZE %d\n"
+               "  MI_SP_CB_SIZE %d\n"
+               "  MI_SP_CR_SIZE %d\n"
+               "  MI_SP_PIC_WIDTH %d\n"
+               "  MI_SP_PIC_HEIGHT %d\n"
+               "  MI_SP_PIC_LLENGTH %d\n"
+               "  MI_SP_PIC_SIZE %d\n",
+               cif_ioread32(dev->config.base_addr + CIF_MI_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_MI_STATUS),
+               cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr + CIF_MI_SP_CB_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr + CIF_MI_SP_CR_SIZE_INIT),
+               cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_PIC_WIDTH),
+               cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_PIC_HEIGHT),
+               cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_LLENGTH),
+               cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_PIC_SIZE));
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_config_mi_dma(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+       enum cif_isp10_pix_fmt out_pix_fmt =
+               dev->config.mi_config.dma.output.pix_fmt;
+       u32 llength =
+               dev->config.mi_config.dma.llength;
+       u32 width =
+               dev->config.mi_config.dma.output.width;
+       u32 height =
+               dev->config.mi_config.dma.output.height;
+       u32 readformat = CIF_ISP10_BUFF_FMT_PLANAR;
+       u32 bpp = CIF_ISP10_PIX_FMT_GET_BPP(out_pix_fmt);
+       u32 size = llength * height * bpp / 8;
+       u32 output_format;
+       u32 mi_ctrl;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s %dx%d, llength = %d\n",
+               cif_isp10_pix_fmt_string(out_pix_fmt),
+               width,
+               height,
+               llength);
+
+       dev->config.mi_config.dma.y_size = size;
+       dev->config.mi_config.dma.cb_size = 0;
+       dev->config.mi_config.dma.cr_size = 0;
+       if (CIF_ISP10_PIX_FMT_IS_YUV(out_pix_fmt)) {
+               u32 num_cplanes =
+                       CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(out_pix_fmt);
+               if (num_cplanes == 0) {
+                       readformat = CIF_ISP10_BUFF_FMT_INTERLEAVED;
+               } else {
+                       dev->config.mi_config.dma.y_size =
+                               (dev->config.mi_config.dma.y_size * 4) /
+                                (4 + (CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+                                       out_pix_fmt) *
+                               CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+                                       out_pix_fmt) / 2));
+                       dev->config.mi_config.dma.cb_size =
+                               size -
+                               dev->config.mi_config.dma.y_size;
+                       if (num_cplanes == 1) {
+                               readformat = CIF_ISP10_BUFF_FMT_SEMIPLANAR;
+                       } else if (num_cplanes == 2) {
+                               readformat = CIF_ISP10_BUFF_FMT_PLANAR;
+                               dev->config.mi_config.dma.cb_size /= 2;
+                       }
+                       /* for U<->V swapping: */
+                       dev->config.mi_config.dma.cr_size =
+                               dev->config.mi_config.dma.cb_size;
+               }
+
+               if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 0) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 0))
+                       output_format = CIF_MI_DMA_CTRL_FMT_YUV400;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 2))
+                       output_format = CIF_MI_DMA_CTRL_FMT_YUV420;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
+                       output_format = CIF_MI_DMA_CTRL_FMT_YUV422;
+               else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 4) &&
+                       (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
+                       output_format = CIF_MI_DMA_CTRL_FMT_YUV444;
+               else {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "unsupported YUV output format %s\n",
+                               cif_isp10_pix_fmt_string(out_pix_fmt));
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unsupported output format %s\n",
+                       cif_isp10_pix_fmt_string(out_pix_fmt));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (readformat == CIF_ISP10_BUFF_FMT_SEMIPLANAR) {
+               dev->config.mi_config.dma.cb_offs =
+                   dev->config.mi_config.dma.y_size;
+               dev->config.mi_config.dma.cr_offs =
+                   dev->config.mi_config.dma.cb_offs;
+       } else if (readformat == CIF_ISP10_BUFF_FMT_PLANAR) {
+               dev->config.mi_config.dma.cb_offs =
+                       dev->config.mi_config.dma.y_size;
+               dev->config.mi_config.dma.cr_offs =
+                       dev->config.mi_config.dma.cb_offs +
+                       dev->config.mi_config.dma.cb_size;
+       }
+
+       cif_iowrite32_verify(dev->config.mi_config.dma.y_size,
+               dev->config.base_addr + CIF_MI_DMA_Y_PIC_SIZE, ~0x3);
+       cif_iowrite32_verify(width,
+               dev->config.base_addr + CIF_MI_DMA_Y_PIC_WIDTH, ~0x3);
+       cif_iowrite32_verify(llength,
+               dev->config.base_addr + CIF_MI_DMA_Y_LLENGTH, ~0x3);
+
+       mi_ctrl = cif_ioread32(dev->config.base_addr + CIF_MI_DMA_CTRL) |
+               CIF_MI_DMA_CTRL_READ_FMT(readformat) |
+               output_format |
+               CIF_MI_DMA_CTRL_BURST_LEN_LUM_64 |
+               CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64;
+       cif_iowrite32_verify(mi_ctrl,
+               dev->config.base_addr + CIF_MI_DMA_CTRL, ~0);
+
+       cif_iowrite32OR_verify(CIF_MI_DMA_READY,
+               dev->config.base_addr + CIF_MI_IMSC, ~0);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  MI_DMA_CTRL 0x%08x\n"
+               "  MI_DMA_STATUS 0x%08x\n"
+               "  MI_DMA_Y_PIC_WIDTH %d\n"
+               "  MI_DMA_Y_LLENGTH %d\n"
+               "  MI_DMA_Y_PIC_SIZE %d\n"
+               "  MI_DMA_Y_PIC_START_AD %d\n"
+               "  MI_DMA_CB_PIC_START_AD %d\n"
+               "  MI_DMA_CR_PIC_START_AD %d\n",
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_CTRL),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_STATUS),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_Y_PIC_WIDTH),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_Y_LLENGTH),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_Y_PIC_SIZE),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_Y_PIC_START_AD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_CB_PIC_START_AD),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_CR_PIC_START_AD));
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_config_jpeg_enc(
+       struct cif_isp10_device *dev)
+{
+       struct cif_isp10_frm_fmt *inp_fmt =
+               &dev->config.mp_config.rsz_config.output;
+       dev->config.jpeg_config.input = inp_fmt;
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "%s %dx%d\n",
+               cif_isp10_pix_fmt_string(inp_fmt->pix_fmt),
+               inp_fmt->width, inp_fmt->height);
+
+       /*
+        * Reset JPEG-Encoder. In contrast to other software
+        * resets this triggers the modules asynchronous reset
+        * resulting in loss of all data
+        */
+       cif_iowrite32OR(CIF_IRCL_JPEG_SW_RST,
+               dev->config.base_addr + CIF_IRCL);
+       cif_iowrite32AND(~CIF_IRCL_JPEG_SW_RST,
+               dev->config.base_addr + CIF_IRCL);
+
+       cif_iowrite32(CIF_JPE_ERROR_MASK,
+               dev->config.base_addr + CIF_JPE_ERROR_IMSC);
+
+       /* Set configuration for the Jpeg capturing */
+       cif_iowrite32(inp_fmt->width,
+               dev->config.base_addr + CIF_JPE_ENC_HSIZE);
+       cif_iowrite32(inp_fmt->height,
+               dev->config.base_addr + CIF_JPE_ENC_VSIZE);
+
+       if (CIF_ISP10_INP_IS_DMA(dev->config.input_sel) ||
+               !CIF_ISP10_PIX_FMT_IS_RAW_BAYER(
+               dev->config.isp_config.input->pix_fmt)) {
+               /*
+                * upscaling of BT601 color space to full range 0..255
+                * TODO: DMA or YUV sensor input in full range.
+                */
+               cif_iowrite32(CIF_JPE_LUM_SCALE_ENABLE,
+                       dev->config.base_addr + CIF_JPE_Y_SCALE_EN);
+               cif_iowrite32(CIF_JPE_CHROM_SCALE_ENABLE,
+                       dev->config.base_addr + CIF_JPE_CBCR_SCALE_EN);
+       }
+
+       switch (inp_fmt->pix_fmt) {
+       case CIF_YUV422I:
+       case CIF_YVU422I:
+       case CIF_YUV422SP:
+       case CIF_YVU422SP:
+       case CIF_YUV422P:
+       case CIF_YVU422P:
+               cif_iowrite32(CIF_JPE_PIC_FORMAT_YUV422,
+                       dev->config.base_addr + CIF_JPE_PIC_FORMAT);
+               break;
+       case CIF_YUV400:
+       case CIF_YVU400:
+               cif_iowrite32(CIF_JPE_PIC_FORMAT_YUV400,
+                       dev->config.base_addr + CIF_JPE_PIC_FORMAT);
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "format %s not supported as input for JPEG encoder\n",
+                       cif_isp10_pix_fmt_string(inp_fmt->pix_fmt));
+               WARN_ON(1);
+               break;
+       }
+
+       /*
+        * Set to normal operation (wait for encoded image data
+        * to fill output buffer)
+        */
+       cif_iowrite32(0, dev->config.base_addr + CIF_JPE_TABLE_FLUSH);
+
+       /*
+        *  CIF Spec 4.7
+        *  3.14 JPEG Encoder Programming
+        *  Do not forget to re-program all AC and DC tables
+        *  after system reset as well as after
+        *  module software reset because after any reset
+        *  the internal RAM is filled with FFH which
+        *  is an illegal symbol. This filling takes
+        *  approximately 400 clock cycles. So do not start
+        *  any table programming during the first 400 clock
+        *  cycles after reset is de-asserted.
+        *  Note: depends on CIF clock setting
+        *  400 clock cycles at 312 Mhz CIF clock-> 1.3 us
+        *  400 clock cycles at 208 Mhz CIF clock-> 1.93 us
+        *  -> 2us ok for both
+        */
+       udelay(2);
+
+       /* Program JPEG tables */
+       cif_isp10_program_jpeg_tables(dev);
+       /* Select JPEG tables */
+       cif_isp10_select_jpeg_tables(dev);
+
+       switch (dev->config.jpeg_config.header) {
+       case CIF_ISP10_JPEG_HEADER_JFIF:
+               cif_isp10_pltfrm_pr_dbg(NULL,
+                       "generate JFIF header\n");
+               cif_iowrite32(CIF_JPE_HEADER_MODE_JFIF,
+                       dev->config.base_addr +
+                       CIF_JPE_HEADER_MODE);
+               break;
+       case CIF_ISP10_JPEG_HEADER_NONE:
+               cif_isp10_pltfrm_pr_dbg(NULL,
+                       "generate no JPEG header\n");
+               cif_iowrite32(CIF_JPE_HEADER_MODE_NOAPPN,
+                       dev->config.base_addr +
+                       CIF_JPE_HEADER_MODE);
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown/unsupport JPEG header type %d\n",
+                       dev->config.jpeg_config.header);
+               WARN_ON(1);
+               break;
+       }
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  JPE_PIC_FORMAT 0x%08x\n"
+               "  JPE_ENC_HSIZE %d\n"
+               "  JPE_ENC_VSIZE %d\n"
+               "  JPE_Y_SCALE_EN 0x%08x\n"
+               "  JPE_CBCR_SCALE_EN 0x%08x\n"
+               "  JPE_ERROR_RIS 0x%08x\n"
+               "  JPE_ERROR_IMSC 0x%08x\n"
+               "  JPE_STATUS_RIS 0x%08x\n"
+               "  JPE_STATUS_IMSC 0x%08x\n"
+               "  JPE_DEBUG 0x%08x\n",
+               cif_ioread32(dev->config.base_addr + CIF_JPE_PIC_FORMAT),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_ENC_HSIZE),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_ENC_VSIZE),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_Y_SCALE_EN),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_CBCR_SCALE_EN),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_ERROR_RIS),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_ERROR_IMSC),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_STATUS_RIS),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_STATUS_IMSC),
+               cif_ioread32(dev->config.base_addr + CIF_JPE_DEBUG));
+
+       return 0;
+}
+
+static int cif_isp10_config_path(
+       struct cif_isp10_device *dev,
+       u32 stream_ids)
+{
+       u32 dpcl = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
+
+       /* if_sel */
+       if (dev->config.input_sel == CIF_ISP10_INP_DMA) {
+               dpcl |= CIF_VI_DPCL_DMA_SW_ISP;
+       }       else if (dev->config.input_sel == CIF_ISP10_INP_DMA_IE) {
+               dpcl |= CIF_VI_DPCL_DMA_IE_MUX_DMA |
+                       CIF_VI_DPCL_DMA_SW_IE;
+       } else if (dev->config.input_sel == CIF_ISP10_INP_DMA_SP) {
+               dpcl |= CIF_VI_DPCL_DMA_SP_MUX_DMA;
+       } else {
+               if (PLTFRM_CAM_ITF_IS_DVP(dev->config.cam_itf.type)) {
+                       dpcl |= CIF_VI_DPCL_IF_SEL_PARALLEL;
+               } else if (PLTFRM_CAM_ITF_IS_MIPI(dev->config.cam_itf.type)) {
+                       dpcl |= CIF_VI_DPCL_IF_SEL_MIPI;
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "Sensor Interface: 0x%x isn't support\n",
+                               dev->config.cam_itf.type);
+                       return -EINVAL;
+               }
+       }
+
+       /* chan_mode */
+       if (stream_ids & CIF_ISP10_STREAM_SP)
+               dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
+
+       if ((stream_ids & CIF_ISP10_STREAM_MP) &&
+               !(dev->config.input_sel == CIF_ISP10_INP_DMA_SP)) {
+               dpcl |= CIF_VI_DPCL_CHAN_MODE_MP;
+               /* mp_dmux */
+               if (dev->config.jpeg_config.enable)
+                       dpcl |= CIF_VI_DPCL_MP_MUX_MRSZ_JPEG;
+               else
+                       dpcl |= CIF_VI_DPCL_MP_MUX_MRSZ_MI;
+       }
+
+       cif_iowrite32(dpcl,
+               dev->config.base_addr + CIF_VI_DPCL);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "CIF_DPCL 0x%08x\n", dpcl);
+
+       return 0;
+}
+
+int cif_isp10_config_dcrop(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id,
+       bool async)
+{
+       unsigned int dc_ctrl = cif_ioread32(
+                                               dev->config.base_addr +
+                                               CIF_DUAL_CROP_CTRL);
+
+       if (stream_id == CIF_ISP10_STREAM_MP) {
+               cif_iowrite32(0, dev->config.base_addr +
+               CIF_DUAL_CROP_M_H_OFFS);
+               cif_iowrite32(0, dev->config.base_addr +
+               CIF_DUAL_CROP_M_V_OFFS);
+               cif_iowrite32(0, dev->config.base_addr +
+               CIF_DUAL_CROP_M_H_SIZE);
+               cif_iowrite32(0, dev->config.base_addr +
+               CIF_DUAL_CROP_M_V_SIZE);
+
+               dc_ctrl |= CIF_DUAL_CROP_MP_MODE_BYPASS;
+               if (async)
+                       dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
+               else
+                       dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
+
+               cif_iowrite32(dc_ctrl,
+                       dev->config.base_addr + CIF_DUAL_CROP_CTRL);
+       } else if (stream_id == CIF_ISP10_STREAM_SP) {
+               cif_iowrite32(0, dev->config.base_addr +
+               CIF_DUAL_CROP_S_H_OFFS);
+               cif_iowrite32(0, dev->config.base_addr +
+               CIF_DUAL_CROP_S_V_OFFS);
+               cif_iowrite32(0, dev->config.base_addr +
+               CIF_DUAL_CROP_S_H_SIZE);
+               cif_iowrite32(0, dev->config.base_addr +
+               CIF_DUAL_CROP_S_V_SIZE);
+
+               dc_ctrl |= CIF_DUAL_CROP_MP_MODE_BYPASS;
+               if (async)
+                       dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
+               else
+                       dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
+
+               cif_iowrite32(dc_ctrl,
+                       dev->config.base_addr + CIF_DUAL_CROP_CTRL);
+       }
+
+       return 0;
+}
+
+int cif_isp10_config_rsz(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id,
+       bool async)
+{
+       int ret;
+       u32 i;
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_h_y_addr =
+               dev->config.base_addr;
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_h_cr_addr =
+               dev->config.base_addr;
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_h_cb_addr =
+               dev->config.base_addr;
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_v_y_addr =
+               dev->config.base_addr;
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_v_c_addr =
+               dev->config.base_addr;
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR rsz_ctrl_addr =
+               dev->config.base_addr;
+       struct cif_isp10_frm_fmt *rsz_input;
+       struct cif_isp10_frm_fmt *rsz_output;
+       struct cif_isp10_frm_fmt *mi_output;
+       u32 rsz_ctrl;
+       u32 input_width_y;
+       u32 output_width_y;
+       u32 input_height_y;
+       u32 output_height_y;
+       u32 input_width_c;
+       u32 output_width_c;
+       u32 input_height_c;
+       u32 output_height_c;
+       u32 scale_h_c;
+
+       if (stream_id == CIF_ISP10_STREAM_MP) {
+               rsz_ctrl_addr += CIF_MRSZ_CTRL;
+               scale_h_y_addr += CIF_MRSZ_SCALE_HY;
+               scale_v_y_addr += CIF_MRSZ_SCALE_VY;
+               scale_h_cb_addr += CIF_MRSZ_SCALE_HCB;
+               scale_h_cr_addr += CIF_MRSZ_SCALE_HCR;
+               scale_v_c_addr += CIF_MRSZ_SCALE_VC;
+               dev->config.mp_config.rsz_config.input =
+                       &dev->config.isp_config.output;
+               rsz_input = dev->config.mp_config.rsz_config.input;
+               rsz_output = &dev->config.mp_config.rsz_config.output;
+               mi_output = &dev->config.mi_config.mp.output;
+               /* No phase offset */
+               cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_PHASE_HY);
+               cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_PHASE_HC);
+               cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_PHASE_VY);
+               cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_PHASE_VC);
+               /* Linear interpolation */
+               for (i = 0; i < 64; i++) {
+                       cif_iowrite32(i,
+                               dev->config.base_addr +
+                                       CIF_MRSZ_SCALE_LUT_ADDR);
+                       cif_iowrite32(i,
+                               dev->config.base_addr +
+                                       CIF_MRSZ_SCALE_LUT);
+               }
+       } else {
+               rsz_ctrl_addr += CIF_SRSZ_CTRL;
+               scale_h_y_addr += CIF_SRSZ_SCALE_HY;
+               scale_v_y_addr += CIF_SRSZ_SCALE_VY;
+               scale_h_cb_addr += CIF_SRSZ_SCALE_HCB;
+               scale_h_cr_addr += CIF_SRSZ_SCALE_HCR;
+               scale_v_c_addr += CIF_SRSZ_SCALE_VC;
+               if (dev->config.input_sel == CIF_ISP10_INP_DMA_SP)
+                       dev->config.sp_config.rsz_config.input =
+                               &dev->config.mi_config.dma.output;
+               else
+                       dev->config.sp_config.rsz_config.input =
+                               &dev->config.isp_config.output;
+
+               rsz_input = dev->config.sp_config.rsz_config.input;
+               rsz_output = &dev->config.sp_config.rsz_config.output;
+               mi_output = &dev->config.mi_config.sp.output;
+               /* No phase offset */
+               cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_PHASE_HY);
+               cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_PHASE_HC);
+               cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_PHASE_VY);
+               cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_PHASE_VC);
+               /* Linear interpolation */
+               for (i = 0; i < 64; i++) {
+                       cif_iowrite32(i,
+                               dev->config.base_addr +
+                                       CIF_SRSZ_SCALE_LUT_ADDR);
+                       cif_iowrite32(i,
+                               dev->config.base_addr +
+                                       CIF_SRSZ_SCALE_LUT);
+               }
+       }
+
+       /* set RSZ input and output */
+       rsz_output->width = mi_output->width;
+       rsz_output->height = mi_output->height;
+       rsz_output->pix_fmt = rsz_input->pix_fmt;
+       if (CIF_ISP10_PIX_FMT_IS_YUV(mi_output->pix_fmt)) {
+               cif_isp10_pix_fmt_set_y_subs(
+                       rsz_output->pix_fmt,
+                       CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(mi_output->pix_fmt));
+               cif_isp10_pix_fmt_set_x_subs(
+                       rsz_output->pix_fmt,
+                       CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(mi_output->pix_fmt));
+               cif_isp10_pix_fmt_set_bpp(
+                       rsz_output->pix_fmt,
+                       CIF_ISP10_PIX_FMT_GET_BPP(mi_output->pix_fmt));
+       } else if (CIF_ISP10_PIX_FMT_IS_JPEG(mi_output->pix_fmt)) {
+               cif_isp10_pix_fmt_set_y_subs(
+                       rsz_output->pix_fmt, 4);
+               cif_isp10_pix_fmt_set_x_subs(
+                       rsz_output->pix_fmt, 2);
+               cif_isp10_pix_fmt_set_bpp(
+                       rsz_output->pix_fmt, 16);
+       }
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s %s %dx%d -> %s %dx%d\n",
+               cif_isp10_stream_id_string(stream_id),
+               cif_isp10_pix_fmt_string(rsz_input->pix_fmt),
+               rsz_input->width,
+               rsz_input->height,
+               cif_isp10_pix_fmt_string(rsz_output->pix_fmt),
+               rsz_output->width,
+               rsz_output->height);
+
+       /* set input and output sizes for scale calculation */
+       input_width_y = rsz_input->width;
+       output_width_y = rsz_output->width;
+       input_height_y = rsz_input->height;
+       output_height_y = rsz_output->height;
+       input_width_c = input_width_y;
+       output_width_c = output_width_y;
+       input_height_c = input_height_y;
+       output_height_c = output_height_y;
+
+       if (CIF_ISP10_PIX_FMT_IS_YUV(rsz_output->pix_fmt)) {
+               input_width_c = (input_width_c *
+                       CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+                               rsz_input->pix_fmt)) / 4;
+               input_height_c = (input_height_c *
+                       CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+                               rsz_input->pix_fmt)) / 4;
+               output_width_c = (output_width_c *
+                       CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+                               rsz_output->pix_fmt)) / 4;
+               output_height_c = (output_height_c *
+                       CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+                               rsz_output->pix_fmt)) / 4;
+
+               cif_isp10_pltfrm_pr_dbg(NULL,
+                       "chroma scaling %dx%d -> %dx%d\n",
+                       input_width_c, input_height_c,
+                       output_width_c, output_height_c);
+
+               if (((input_width_c == 0) && (output_width_c > 0)) ||
+                       ((input_height_c == 0) && (output_height_c > 0))) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "input is black and white, cannot output colour\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else {
+               if ((input_width_y != output_width_y) ||
+                       (input_height_y != output_height_y)) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "%dx%d -> %dx%d isn't support, can only scale YUV input\n",
+                               input_width_y, input_height_y,
+                               output_width_y, output_height_y);
+                       ret = -EINVAL;
+                       goto err;
+               }
+       }
+
+       /* calculate and set scale */
+       rsz_ctrl = 0;
+       if (input_width_y < output_width_y) {
+               rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE |
+                       CIF_RSZ_CTRL_SCALE_HY_UP;
+               cif_iowrite32(
+                       DIV_TRUNCATE((input_width_y - 1)
+                       * CIF_RSZ_SCALER_BYPASS,
+                       output_width_y - 1),
+                       scale_h_y_addr);
+       } else if (input_width_y > output_width_y) {
+               rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE;
+               cif_iowrite32(
+                       DIV_TRUNCATE((output_width_y - 1)
+                       * CIF_RSZ_SCALER_BYPASS,
+                       input_width_y - 1) + 1,
+                       scale_h_y_addr);
+       }
+       if (input_width_c < output_width_c) {
+               rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE |
+                       CIF_RSZ_CTRL_SCALE_HC_UP;
+               scale_h_c = DIV_TRUNCATE((input_width_c - 1)
+               * CIF_RSZ_SCALER_BYPASS,
+               output_width_c - 1);
+               cif_iowrite32(scale_h_c, scale_h_cb_addr);
+               cif_iowrite32(scale_h_c, scale_h_cr_addr);
+       } else if (input_width_c > output_width_c) {
+               rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE;
+               scale_h_c = DIV_TRUNCATE((output_width_c - 1)
+               * CIF_RSZ_SCALER_BYPASS,
+               input_width_c - 1) + 1;
+               cif_iowrite32(scale_h_c, scale_h_cb_addr);
+               cif_iowrite32(scale_h_c, scale_h_cr_addr);
+       }
+
+       if (input_height_y < output_height_y) {
+               rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE |
+                       CIF_RSZ_CTRL_SCALE_VY_UP;
+               cif_iowrite32(
+                       DIV_TRUNCATE((input_height_y - 1)
+                       * CIF_RSZ_SCALER_BYPASS,
+                       output_height_y - 1),
+                       scale_v_y_addr);
+       } else if (input_height_y > output_height_y) {
+               rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE;
+               cif_iowrite32(
+                       DIV_TRUNCATE((output_height_y - 1)
+                       * CIF_RSZ_SCALER_BYPASS,
+                       input_height_y - 1) + 1,
+                       scale_v_y_addr);
+       }
+
+       if (input_height_c < output_height_c) {
+               rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE |
+                       CIF_RSZ_CTRL_SCALE_VC_UP;
+               cif_iowrite32(
+                       DIV_TRUNCATE((input_height_c - 1)
+                       * CIF_RSZ_SCALER_BYPASS,
+                       output_height_c - 1),
+                       scale_v_c_addr);
+       } else if (input_height_c > output_height_c) {
+               rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE;
+               cif_iowrite32(
+                       DIV_TRUNCATE((output_height_c - 1)
+                       * CIF_RSZ_SCALER_BYPASS,
+                       input_height_c - 1) + 1,
+                       scale_v_c_addr);
+       }
+
+       cif_iowrite32(rsz_ctrl, rsz_ctrl_addr);
+
+       if (stream_id == CIF_ISP10_STREAM_MP) {
+               if (async)
+                       cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+                               dev->config.base_addr + CIF_MRSZ_CTRL);
+               dev->config.mp_config.rsz_config.ycflt_adjust = false;
+               dev->config.mp_config.rsz_config.ism_adjust = false;
+               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "\n  MRSZ_CTRL 0x%08x/0x%08x\n"
+                       "  MRSZ_SCALE_HY %d/%d\n"
+                       "  MRSZ_SCALE_HCB %d/%d\n"
+                       "  MRSZ_SCALE_HCR %d/%d\n"
+                       "  MRSZ_SCALE_VY %d/%d\n"
+                       "  MRSZ_SCALE_VC %d/%d\n"
+                       "  MRSZ_PHASE_HY %d/%d\n"
+                       "  MRSZ_PHASE_HC %d/%d\n"
+                       "  MRSZ_PHASE_VY %d/%d\n"
+                       "  MRSZ_PHASE_VC %d/%d\n",
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_CTRL),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_CTRL_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_HY),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_HY_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_HCB),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_HCB_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_HCR),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_HCR_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_VY),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_VY_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_VC),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_SCALE_VC_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_PHASE_HY),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_PHASE_HY_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_PHASE_HC),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_PHASE_HC_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_PHASE_VY),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_PHASE_VY_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_PHASE_VC),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MRSZ_PHASE_VC_SHD));
+       } else {
+               if (async)
+                       cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+                               dev->config.base_addr + CIF_SRSZ_CTRL);
+               dev->config.sp_config.rsz_config.ycflt_adjust = false;
+               dev->config.sp_config.rsz_config.ism_adjust = false;
+               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "\n  SRSZ_CTRL 0x%08x/0x%08x\n"
+                       "  SRSZ_SCALE_HY %d/%d\n"
+                       "  SRSZ_SCALE_HCB %d/%d\n"
+                       "  SRSZ_SCALE_HCR %d/%d\n"
+                       "  SRSZ_SCALE_VY %d/%d\n"
+                       "  SRSZ_SCALE_VC %d/%d\n"
+                       "  SRSZ_PHASE_HY %d/%d\n"
+                       "  SRSZ_PHASE_HC %d/%d\n"
+                       "  SRSZ_PHASE_VY %d/%d\n"
+                       "  SRSZ_PHASE_VC %d/%d\n",
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_CTRL),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_CTRL_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_HY),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_HY_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_HCB),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_HCB_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_HCR),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_HCR_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_VY),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_VY_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_VC),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_SCALE_VC_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_PHASE_HY),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_PHASE_HY_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_PHASE_HC),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_PHASE_HC_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_PHASE_VY),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_PHASE_VY_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_PHASE_VC),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_SRSZ_PHASE_VC_SHD));
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_config_sp(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       ret = cif_isp10_config_rsz(dev, CIF_ISP10_STREAM_SP, true);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       ret = cif_isp10_config_dcrop(dev, CIF_ISP10_STREAM_SP, true);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       ret = cif_isp10_config_mi_sp(dev);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       dev->sp_stream.updt_cfg = false;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_config_mp(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       ret = cif_isp10_config_rsz(dev, CIF_ISP10_STREAM_MP, true);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       ret = cif_isp10_config_dcrop(dev, CIF_ISP10_STREAM_MP, true);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       ret = cif_isp10_config_mi_mp(dev);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+       if (dev->config.jpeg_config.enable) {
+               ret = cif_isp10_config_jpeg_enc(dev);
+               if (IS_ERR_VALUE(ret))
+                       goto err;
+               dev->config.jpeg_config.busy = false;
+       }
+
+       dev->mp_stream.updt_cfg = false;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static void cif_isp10_config_clk(
+       struct cif_isp10_device *dev)
+{
+       cif_iowrite32(CIF_CCL_CIF_CLK_ENA,
+               dev->config.base_addr + CIF_CCL);
+       cif_iowrite32(0x0000187B, dev->config.base_addr + CIF_ICCL);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  CIF_CCL 0x%08x\n"
+               "  CIF_ICCL 0x%08x\n",
+               cif_ioread32(dev->config.base_addr + CIF_CCL),
+               cif_ioread32(dev->config.base_addr + CIF_ICCL));
+}
+
+static int cif_isp10_config_cif(
+       struct cif_isp10_device *dev,
+       u32 stream_ids)
+{
+       int ret = 0;
+       u32 cif_id;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "config MP = %d, config SP = %d, img_src state = %s, PM state = %s, SP state = %s, MP state = %s\n",
+               (stream_ids & CIF_ISP10_STREAM_MP) == CIF_ISP10_STREAM_MP,
+               (stream_ids & CIF_ISP10_STREAM_SP) == CIF_ISP10_STREAM_SP,
+               cif_isp10_img_src_state_string(dev->img_src_state),
+               cif_isp10_pm_state_string(dev->pm_state),
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state));
+
+       cif_isp10_pltfrm_rtrace_printf(NULL,
+               "start configuring CIF...\n");
+
+       if ((stream_ids & CIF_ISP10_STREAM_MP) ||
+               (stream_ids & CIF_ISP10_STREAM_SP)) {
+               ret = cif_isp10_set_pm_state(dev,
+                       CIF_ISP10_PM_STATE_SW_STNDBY);
+               if (IS_ERR_VALUE(ret))
+                       goto err;
+
+               if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+                       /* configure sensor */
+                       ret = cif_isp10_config_img_src(dev);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               }
+
+               cif_id = cif_ioread32(dev->config.base_addr + CIF_VI_ID);
+               dev->config.out_of_buffer_stall =
+                               CIF_ISP10_ALWAYS_STALL_ON_NO_BUFS;
+
+               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "CIF_ID 0x%08x\n", cif_id);
+
+               /*
+                * Cancel isp reset internal here temporary for
+                * isp bus may be dead when switch isp.
+                */
+               /*
+                * cif_iowrite32(CIF_IRCL_CIF_SW_RST,
+                * dev->config.base_addr + CIF_IRCL);
+                */
+
+               cif_isp10_config_clk(dev);
+
+               /* Decide when to switch to asynchronous mode */
+               /*
+                * TODO: remove dev->isp_dev.ycflt_en check for
+                * HW with the scaler fix.
+                */
+               dev->config.mi_config.async_updt = CIF_ISP10_ALWAYS_ASYNC;
+               if (CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+                       dev->config.mi_config.async_updt |= CIF_ISP10_ASYNC_DMA;
+                       ret = cif_isp10_config_mi_dma(dev);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               }
+               if ((stream_ids & CIF_ISP10_STREAM_MP) &&
+                       (dev->config.jpeg_config.enable))
+                       dev->config.mi_config.async_updt |=
+                               CIF_ISP10_ASYNC_JPEG;
+               if (dev->config.isp_config.ism_config.ism_en)
+                       dev->config.mi_config.async_updt |=
+                               CIF_ISP10_ASYNC_ISM;
+
+               if (PLTFRM_CAM_ITF_IS_MIPI(dev->config.cam_itf.type)) {
+                       ret = cif_isp10_config_mipi(dev);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               }
+
+               ret = cif_isp10_config_isp(dev);
+               if (IS_ERR_VALUE(ret))
+                       goto err;
+
+               cif_isp10_config_ism(dev, true);
+               dev->config.isp_config.ism_config.ism_update_needed = false;
+
+               if (stream_ids & CIF_ISP10_STREAM_SP)
+                       dev->config.sp_config.rsz_config.ism_adjust = true;
+               if (stream_ids & CIF_ISP10_STREAM_MP)
+                       dev->config.mp_config.rsz_config.ism_adjust = true;
+
+               if (stream_ids & CIF_ISP10_STREAM_SP) {
+                       ret = cif_isp10_config_sp(dev);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               }
+
+               if (stream_ids & CIF_ISP10_STREAM_MP) {
+                       ret = cif_isp10_config_mp(dev);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               }
+               ret = cif_isp10_config_path(dev, stream_ids);
+               if (IS_ERR_VALUE(ret))
+                       goto err;
+       }
+
+       /* Turn off XNR vertical subsampling when ism cropping is enabled */
+       if (dev->config.isp_config.ism_config.ism_en) {
+               if (!dev->isp_dev.cif_ism_cropping)
+                       dev->isp_dev.cif_ism_cropping = true;
+       } else {
+               if (dev->isp_dev.cif_ism_cropping)
+                       dev->isp_dev.cif_ism_cropping = false;
+       }
+
+       if (dev->config.sp_config.rsz_config.ycflt_adjust ||
+               dev->config.sp_config.rsz_config.ism_adjust) {
+               if (dev->sp_stream.state == CIF_ISP10_STATE_READY) {
+                       ret = cif_isp10_config_rsz(dev,
+                               CIF_ISP10_STREAM_SP, true);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               } else {
+                       /* Disable SRSZ if SP is not used */
+                       cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_CTRL);
+                       cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+                               dev->config.base_addr + CIF_SRSZ_CTRL);
+                       dev->config.sp_config.rsz_config.ycflt_adjust = false;
+                       dev->config.sp_config.rsz_config.ism_adjust = false;
+               }
+       }
+
+       if (dev->config.mp_config.rsz_config.ycflt_adjust ||
+               dev->config.mp_config.rsz_config.ism_adjust) {
+               if (dev->mp_stream.state == CIF_ISP10_STATE_READY) {
+                       ret = cif_isp10_config_rsz(dev,
+                               CIF_ISP10_STREAM_MP, true);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               } else {
+                       /* Disable MRSZ if MP is not used */
+                       cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_CTRL);
+                       cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+                               dev->config.base_addr + CIF_MRSZ_CTRL);
+                       dev->config.mp_config.rsz_config.ycflt_adjust = false;
+                       dev->config.mp_config.rsz_config.ism_adjust = false;
+               }
+       }
+
+       if (dev->config.mi_config.async_updt)
+               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "CIF in asynchronous mode (0x%08x)\n",
+                       dev->config.mi_config.async_updt);
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static void cif_isp10_init_stream(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id)
+{
+       struct cif_isp10_stream *stream = NULL;
+
+       switch (stream_id) {
+       case CIF_ISP10_STREAM_SP:
+               stream = &dev->sp_stream;
+               dev->config.sp_config.rsz_config.ycflt_adjust = false;
+               dev->config.sp_config.rsz_config.ism_adjust = false;
+               dev->config.mi_config.sp.busy = false;
+               break;
+       case CIF_ISP10_STREAM_MP:
+               stream = &dev->mp_stream;
+               dev->config.jpeg_config.ratio = 50;
+               dev->config.jpeg_config.header =
+                       CIF_ISP10_JPEG_HEADER_JFIF;
+               dev->config.jpeg_config.enable = false;
+               dev->config.mi_config.raw_enable = false;
+               dev->config.mp_config.rsz_config.ycflt_adjust = false;
+               dev->config.mp_config.rsz_config.ism_adjust = false;
+               dev->config.mi_config.mp.busy = false;
+               break;
+       case CIF_ISP10_STREAM_DMA:
+               stream = &dev->dma_stream;
+               dev->config.mi_config.dma.busy = false;
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown/unsupported stream ID %d\n", stream_id);
+               WARN_ON(1);
+               break;
+       }
+
+       INIT_LIST_HEAD(&stream->buf_queue);
+       stream->next_buf = NULL;
+       stream->curr_buf = NULL;
+       stream->updt_cfg = false;
+       stream->stop = false;
+       stream->stall = false;
+
+       cif_isp10_pltfrm_event_clear(dev->dev, &stream->done);
+       stream->state = CIF_ISP10_STATE_INACTIVE;
+}
+
+static int cif_isp10_jpeg_gen_header(
+       struct cif_isp10_device *dev)
+{
+       unsigned int timeout = 10000;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       cif_iowrite32(CIF_JPE_GEN_HEADER_ENABLE,
+               dev->config.base_addr + CIF_JPE_GEN_HEADER);
+
+       while (timeout--) {
+               if (cif_ioread32(dev->config.base_addr +
+                       CIF_JPE_STATUS_RIS) &
+                       CIF_JPE_STATUS_GENHEADER_DONE) {
+                       cif_isp10_pltfrm_pr_dbg(NULL,
+                               "JPEG header generated\n");
+                       cif_iowrite32(CIF_JPE_STATUS_GENHEADER_DONE,
+                               dev->config.base_addr + CIF_JPE_STATUS_ICR);
+                       break;
+               }
+       }
+
+       if (!timeout) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "JPEG header generation timeout\n");
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "failed with error %d\n", -ETIMEDOUT);
+               return -ETIMEDOUT;
+       }
+
+#ifdef CIF_ISP10_VERIFY_JPEG_HEADER
+       {
+               u32 *buff = (u32 *)phys_to_virt(
+                       dev->config.mi_config.mp.curr_buff_addr);
+               if (buff[0] != 0xe0ffd8ff)
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "JPEG HEADER WRONG: 0x%08x\n"
+                               "curr_buff_addr 0x%08x\n"
+                               "MI_MP_Y_SIZE_SHD 0x%08x\n"
+                               "MI_MP_Y_BASE_AD_SHD 0x%08x\n",
+                               buff[0],
+                               dev->config.mi_config.mp.curr_buff_addr,
+                               cif_ioread32(dev->config.base_addr +
+                                       CIF_MI_MP_Y_SIZE_SHD),
+                               cif_ioread32(dev->config.base_addr +
+                                       CIF_MI_MP_Y_BASE_AD_SHD));
+       }
+#endif
+
+       return 0;
+}
+
+static void cif_isp10_mi_update_buff_addr(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id strm_id)
+{
+       if (strm_id == CIF_ISP10_STREAM_SP) {
+               cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr,
+                       dev->config.base_addr +
+                       CIF_MI_SP_Y_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr +
+                       dev->config.mi_config.sp.cb_offs,
+                       dev->config.base_addr +
+                       CIF_MI_SP_CB_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr +
+                       dev->config.mi_config.sp.cr_offs,
+                       dev->config.base_addr +
+                       CIF_MI_SP_CR_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               /*
+                * There have bee repeatedly issues with
+                * the offset registers, it is safer to write
+                * them each time, even though it is always
+                * 0 and even though that is the
+                * register's default value
+                */
+               cif_iowrite32_verify(0,
+                       dev->config.base_addr +
+                       CIF_MI_SP_Y_OFFS_CNT_INIT,
+                       CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(0,
+                       dev->config.base_addr +
+                       CIF_MI_SP_CB_OFFS_CNT_INIT,
+                       CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(0,
+                       dev->config.base_addr +
+                       CIF_MI_SP_CR_OFFS_CNT_INIT,
+                       CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "\n  MI_SP_Y_BASE_AD 0x%08x/0x%08x\n"
+                       "  MI_SP_CB_BASE_AD 0x%08x/0x%08x\n"
+                       "  MI_SP_CR_BASE_AD 0x%08x/0x%08x\n",
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_SP_Y_BASE_AD_INIT),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_SP_Y_BASE_AD_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_SP_CB_BASE_AD_INIT),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_SP_CB_BASE_AD_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_SP_CR_BASE_AD_INIT),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_SP_CR_BASE_AD_SHD));
+       } else if (strm_id == CIF_ISP10_STREAM_MP) {
+               cif_iowrite32_verify(dev->config.mi_config.mp.next_buff_addr,
+                       dev->config.base_addr +
+                       CIF_MI_MP_Y_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(dev->config.mi_config.mp.next_buff_addr +
+                       dev->config.mi_config.mp.cb_offs,
+                       dev->config.base_addr +
+                       CIF_MI_MP_CB_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(dev->config.mi_config.mp.next_buff_addr +
+                       dev->config.mi_config.mp.cr_offs,
+                       dev->config.base_addr +
+                       CIF_MI_MP_CR_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               /*
+                * There have bee repeatedly issues with
+                * the offset registers, it is safer to write
+                * them each time, even though it is always
+                * 0 and even though that is the
+                * register's default value
+                */
+               cif_iowrite32_verify(0,
+                       dev->config.base_addr +
+                       CIF_MI_MP_Y_OFFS_CNT_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(0,
+                       dev->config.base_addr +
+                       CIF_MI_MP_CB_OFFS_CNT_INIT,
+                       CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(0,
+                       dev->config.base_addr +
+                       CIF_MI_MP_CR_OFFS_CNT_INIT,
+                       CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "\n  MI_MP_Y_BASE_AD 0x%08x/0x%08x\n"
+                       "  MI_MP_CB_BASE_AD 0x%08x/0x%08x\n"
+                       "  MI_MP_CR_BASE_AD 0x%08x/0x%08x\n",
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_MP_Y_BASE_AD_INIT),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_MP_Y_BASE_AD_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_MP_CB_BASE_AD_INIT),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_MP_CB_BASE_AD_SHD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_MP_CR_BASE_AD_INIT),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_MP_CR_BASE_AD_SHD));
+       } else { /* DMA */
+               cif_iowrite32_verify(dev->config.mi_config.dma.next_buff_addr,
+                       dev->config.base_addr +
+                       CIF_MI_DMA_Y_PIC_START_AD, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(dev->config.mi_config.dma.next_buff_addr +
+                       dev->config.mi_config.dma.cb_offs,
+                       dev->config.base_addr +
+                       CIF_MI_DMA_CB_PIC_START_AD,
+                       CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_iowrite32_verify(dev->config.mi_config.dma.next_buff_addr +
+                       dev->config.mi_config.dma.cr_offs,
+                       dev->config.base_addr +
+                       CIF_MI_DMA_CR_PIC_START_AD,
+                       CIF_MI_ADDR_SIZE_ALIGN_MASK);
+               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "\n  MI_DMA_Y_PIC_START_AD 0x%08x\n"
+                       "  MI_DMA_CB_PIC_START_AD 0x%08x\n"
+                       "  MI_DMA_CR_PIC_START_AD 0x%08x\n",
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_DMA_Y_PIC_START_AD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_DMA_CB_PIC_START_AD),
+                       cif_ioread32(dev->config.base_addr +
+                               CIF_MI_DMA_CR_PIC_START_AD));
+       }
+}
+
+static int cif_isp10_update_mi_mp(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+       enum cif_isp10_pix_fmt out_pix_fmt =
+               dev->config.mi_config.mp.output.pix_fmt;
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "curr 0x%08x next 0x%08x\n",
+               dev->config.mi_config.mp.curr_buff_addr,
+               dev->config.mi_config.mp.next_buff_addr);
+
+       if (dev->config.jpeg_config.enable) {
+               /*
+                * in case of jpeg encoding, we don't have to disable the
+                * MI, because the encoding
+                * anyway has to be started explicitly
+                */
+               if (!dev->config.jpeg_config.busy) {
+                       if ((dev->config.mi_config.mp.curr_buff_addr !=
+                               dev->config.mi_config.mp.next_buff_addr) &&
+                               (dev->config.mi_config.mp.curr_buff_addr !=
+                               CIF_ISP10_INVALID_BUFF_ADDR)) {
+                               ret = cif_isp10_jpeg_gen_header(dev);
+                               if (IS_ERR_VALUE(ret))
+                                       goto err;
+                               cif_isp10_pltfrm_pr_dbg(NULL,
+                                       "Starting JPEG encoding\n");
+                               cif_isp10_pltfrm_rtrace_printf(dev->dev,
+                                       "Starting JPEG encoding\n");
+                               cif_iowrite32(CIF_JPE_ENCODE_ENABLE,
+                                       dev->config.base_addr + CIF_JPE_ENCODE);
+                               cif_iowrite32(CIF_JPE_INIT_ENABLE,
+                                       dev->config.base_addr +
+                                       CIF_JPE_INIT);
+                               dev->config.jpeg_config.busy = true;
+                       }
+                       if (dev->config.mi_config.mp.next_buff_addr !=
+                               CIF_ISP10_INVALID_BUFF_ADDR)
+                               cif_isp10_mi_update_buff_addr(dev,
+                                       CIF_ISP10_STREAM_MP);
+                       dev->config.mi_config.mp.curr_buff_addr =
+                               dev->config.mi_config.mp.next_buff_addr;
+               }
+       } else {
+               if (dev->config.mi_config.mp.next_buff_addr !=
+                       dev->config.mi_config.mp.curr_buff_addr) {
+                       if (dev->config.mi_config.mp.next_buff_addr ==
+                               CIF_ISP10_INVALID_BUFF_ADDR) {
+                               /* disable MI MP */
+                               cif_isp10_pltfrm_pr_dbg(NULL,
+                                       "disabling MP MI\n");
+                               cif_iowrite32AND_verify(
+                                   ~(CIF_MI_CTRL_MP_ENABLE_IN |
+                                       CIF_MI_CTRL_JPEG_ENABLE |
+                                       CIF_MI_CTRL_RAW_ENABLE),
+                                       dev->config.base_addr + CIF_MI_CTRL,
+                                       ~0);
+                       } else if (dev->config.mi_config.mp.curr_buff_addr ==
+                               CIF_ISP10_INVALID_BUFF_ADDR) {
+                               /* re-enable MI MP */
+                               cif_isp10_pltfrm_pr_dbg(NULL,
+                                       "enabling MP MI\n");
+                               cif_iowrite32(CIF_MI_MP_FRAME,
+                                       dev->config.base_addr + CIF_MI_ICR);
+                               cif_iowrite32AND_verify(
+                                           ~(CIF_MI_CTRL_MP_ENABLE_IN |
+                                               CIF_MI_CTRL_JPEG_ENABLE |
+                                               CIF_MI_CTRL_RAW_ENABLE),
+                                               dev->config.base_addr +
+                                               CIF_MI_CTRL, ~0);
+                               if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER
+                                       (out_pix_fmt)) {
+                                       cif_iowrite32OR_verify(
+                                               CIF_MI_CTRL_RAW_ENABLE,
+                                               dev->config.base_addr +
+                                               CIF_MI_CTRL,
+                                               ~0);
+                               } else if (CIF_ISP10_PIX_FMT_IS_YUV
+                                       (out_pix_fmt)) {
+                                       cif_iowrite32OR_verify(
+                                               CIF_MI_CTRL_MP_ENABLE_IN,
+                                               dev->config.base_addr +
+                                               CIF_MI_CTRL, ~0);
+                               }
+                       }
+                       cif_isp10_mi_update_buff_addr(dev, CIF_ISP10_STREAM_MP);
+                       dev->config.mi_config.mp.curr_buff_addr =
+                               dev->config.mi_config.mp.next_buff_addr;
+               }
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_update_mi_sp(
+       struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "curr 0x%08x next 0x%08x\n",
+               dev->config.mi_config.sp.curr_buff_addr,
+               dev->config.mi_config.sp.next_buff_addr);
+
+       if (dev->config.mi_config.sp.next_buff_addr !=
+               dev->config.mi_config.sp.curr_buff_addr) {
+               if (dev->config.mi_config.sp.next_buff_addr ==
+                       CIF_ISP10_INVALID_BUFF_ADDR) {
+                       /* disable MI SP */
+                       cif_isp10_pltfrm_pr_dbg(NULL, "disabling SP MI\n");
+                       /* 'switch off' MI interface */
+                       cif_iowrite32AND_verify(~CIF_MI_CTRL_SP_ENABLE,
+                               dev->config.base_addr + CIF_MI_CTRL, ~0);
+               } else if (dev->config.mi_config.sp.curr_buff_addr ==
+                       CIF_ISP10_INVALID_BUFF_ADDR) {
+                       /* re-enable MI SP */
+                       cif_isp10_pltfrm_pr_dbg(NULL, "enabling SP MI\n");
+                       cif_iowrite32(CIF_MI_SP_FRAME,
+                               dev->config.base_addr + CIF_MI_ICR);
+                       cif_iowrite32OR_verify(CIF_MI_CTRL_SP_ENABLE,
+                               dev->config.base_addr + CIF_MI_CTRL, ~0);
+               }
+               cif_isp10_mi_update_buff_addr(dev, CIF_ISP10_STREAM_SP);
+               dev->config.mi_config.sp.curr_buff_addr =
+                       dev->config.mi_config.sp.next_buff_addr;
+       }
+
+       return 0;
+}
+
+static int cif_isp10_s_fmt_mp(
+       struct cif_isp10_device *dev,
+       struct cif_isp10_strm_fmt *strm_fmt,
+       u32 stride)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s %dx%d@%d/%dfps, stride = %d, quantization: %d\n",
+               cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+               strm_fmt->frm_fmt.width,
+               strm_fmt->frm_fmt.height,
+               strm_fmt->frm_intrvl.numerator,
+               strm_fmt->frm_intrvl.denominator,
+               stride,
+               strm_fmt->frm_fmt.quantization);
+
+       /* TBD: check whether format is a valid format for MP */
+
+       if (CIF_ISP10_PIX_FMT_IS_JPEG(strm_fmt->frm_fmt.pix_fmt)) {
+               dev->config.jpeg_config.enable = true;
+       }       else if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER
+               (strm_fmt->frm_fmt.pix_fmt)) {
+               if ((dev->sp_stream.state == CIF_ISP10_STATE_READY) ||
+                       (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING))
+                       cif_isp10_pltfrm_pr_warn(dev->dev,
+                               "cannot output RAW data when SP is active, you will not be able to (re-)start streaming\n");
+               dev->config.mi_config.raw_enable = true;
+       }
+
+       dev->config.mi_config.mp.output = strm_fmt->frm_fmt;
+       dev->config.mi_config.mp.output.stride = stride;
+
+       dev->config.mi_config.mp.llength =
+               cif_isp10_calc_llength(
+                       strm_fmt->frm_fmt.width,
+                       stride,
+                       strm_fmt->frm_fmt.pix_fmt);
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "mp llength=0x%x\n", dev->config.mi_config.mp.llength);
+
+       dev->mp_stream.updt_cfg = true;
+       dev->mp_stream.state = CIF_ISP10_STATE_READY;
+
+       if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+               ret = cif_isp10_img_src_select_strm_fmt(dev);
+               if (IS_ERR_VALUE(ret)) {
+                       dev->mp_stream.updt_cfg = false;
+                       dev->mp_stream.state = CIF_ISP10_STATE_INACTIVE;
+                       goto err;
+               }
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_s_fmt_sp(
+       struct cif_isp10_device *dev,
+       struct cif_isp10_strm_fmt *strm_fmt,
+       u32 stride)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s %dx%d@%d/%dfps, stride = %d, quantization: %d\n",
+               cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+               strm_fmt->frm_fmt.width,
+               strm_fmt->frm_fmt.height,
+               strm_fmt->frm_intrvl.numerator,
+               strm_fmt->frm_intrvl.denominator,
+               stride,
+               strm_fmt->frm_fmt.quantization);
+
+       if (dev->config.mi_config.raw_enable)
+               cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "cannot activate SP when MP is set to RAW data output, you will not be able to (re-)start streaming\n");
+
+       /* TBD: more detailed check whether format is a valid format for SP */
+       /* TBD: remove the mode stuff */
+       if (!CIF_ISP10_PIX_FMT_IS_YUV(strm_fmt->frm_fmt.pix_fmt) &&
+               !CIF_ISP10_PIX_FMT_IS_RGB(strm_fmt->frm_fmt.pix_fmt)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "format %s %dx%d@%d/%dfps, stride = %d not supported on SP\n",
+                       cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+                       strm_fmt->frm_fmt.width,
+                       strm_fmt->frm_fmt.height,
+                       strm_fmt->frm_intrvl.numerator,
+                       strm_fmt->frm_intrvl.denominator,
+                       stride);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       dev->config.mi_config.sp.output = strm_fmt->frm_fmt;
+       dev->config.mi_config.sp.llength =
+               cif_isp10_calc_llength(
+               strm_fmt->frm_fmt.width,
+               stride,
+               strm_fmt->frm_fmt.pix_fmt);
+
+       dev->sp_stream.updt_cfg = true;
+       dev->sp_stream.state = CIF_ISP10_STATE_READY;
+
+       if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+               ret = cif_isp10_img_src_select_strm_fmt(dev);
+               if (IS_ERR_VALUE(ret)) {
+                       dev->sp_stream.updt_cfg = false;
+                       dev->sp_stream.state = CIF_ISP10_STATE_INACTIVE;
+                       goto err;
+               }
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_s_fmt_dma(
+       struct cif_isp10_device *dev,
+       struct cif_isp10_strm_fmt *strm_fmt,
+       u32 stride)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s %dx%d@%d/%dfps, stride = %d\n",
+               cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+               strm_fmt->frm_fmt.width,
+               strm_fmt->frm_fmt.height,
+               strm_fmt->frm_intrvl.numerator,
+               strm_fmt->frm_intrvl.denominator,
+               stride);
+
+       if (!CIF_ISP10_PIX_FMT_IS_YUV(strm_fmt->frm_fmt.pix_fmt) &&
+               !CIF_ISP10_PIX_FMT_IS_RAW_BAYER(strm_fmt->frm_fmt.pix_fmt)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "format %s %dx%d@%d/%dfps, stride = %d not supported for DMA\n",
+                       cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+                       strm_fmt->frm_fmt.width,
+                       strm_fmt->frm_fmt.height,
+                       strm_fmt->frm_intrvl.numerator,
+                       strm_fmt->frm_intrvl.denominator,
+                       stride);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       dev->config.mi_config.dma.output = strm_fmt->frm_fmt;
+       dev->config.mi_config.dma.llength =
+               cif_isp10_calc_llength(
+               strm_fmt->frm_fmt.width,
+               stride,
+               strm_fmt->frm_fmt.pix_fmt);
+
+       dev->dma_stream.updt_cfg = true;
+       dev->dma_stream.state = CIF_ISP10_STATE_READY;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static void cif_isp10_dma_next_buff(
+       struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       if (!list_empty(&dev->dma_stream.buf_queue) &&
+               !dev->dma_stream.stop) {
+               if (dev->dma_stream.curr_buf)
+                       WARN_ON(1);
+               dev->dma_stream.curr_buf =
+                       list_first_entry(&dev->dma_stream.buf_queue,
+                               struct videobuf_buffer, queue);
+               list_del(&dev->dma_stream.curr_buf->queue);
+               dev->dma_stream.curr_buf->state = VIDEOBUF_ACTIVE;
+               dev->config.mi_config.dma.next_buff_addr =
+                       videobuf_to_dma_contig(
+                               dev->dma_stream.curr_buf);
+               cif_isp10_mi_update_buff_addr(dev,
+                       CIF_ISP10_STREAM_DMA);
+               dev->config.mi_config.dma.busy = true;
+               if ((dev->sp_stream.state == CIF_ISP10_STATE_STREAMING) &&
+                       dev->sp_stream.curr_buf)
+                       dev->config.mi_config.sp.busy = true;
+               if ((dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) &&
+                       dev->mp_stream.curr_buf)
+                       dev->config.mi_config.mp.busy = true;
+               /* workaround for write register failure bug */
+               do {
+                       cif_iowrite32(CIF_MI_DMA_START_ENABLE,
+                               dev->config.base_addr + CIF_MI_DMA_START);
+                       udelay(1);
+               } while (!cif_ioread32(
+                       dev->config.base_addr + CIF_MI_DMA_STATUS));
+       }
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  MI_DMA_CTRL 0x%08x\n"
+               "  MI_DMA_STATUS 0x%08x\n",
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_CTRL),
+               cif_ioread32(dev->config.base_addr +
+                       CIF_MI_DMA_STATUS));
+}
+
+static void cif_isp10_dma_ready(
+       struct cif_isp10_device *dev)
+{
+       unsigned int mi_mis_tmp;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       cif_iowrite32(CIF_MI_DMA_READY,
+               dev->config.base_addr + CIF_MI_ICR);
+       mi_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_MI_MIS);
+       if (mi_mis_tmp & CIF_MI_DMA_READY)
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                                       "dma icr err: 0x%x\n",
+                                       mi_mis_tmp);
+       dev->dma_stream.curr_buf->state = VIDEOBUF_DONE;
+       wake_up(&dev->dma_stream.curr_buf->done);
+       dev->dma_stream.curr_buf = NULL;
+       dev->config.mi_config.dma.busy = false;
+       cif_isp10_pltfrm_event_signal(dev->dev, &dev->dma_stream.done);
+}
+
+static int cif_isp10_mi_frame_end(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id)
+{
+       struct cif_isp10_stream *stream = NULL;
+       u32 *next_buff_addr = NULL;
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR y_base_addr;
+       int (*update_mi)(
+               struct cif_isp10_device *dev);
+       struct cif_isp10_isp_readout_work *work;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+               cif_isp10_stream_id_string(stream_id));
+
+       if (stream_id == CIF_ISP10_STREAM_MP) {
+               stream = &dev->mp_stream;
+               y_base_addr =
+                       dev->config.base_addr + CIF_MI_MP_Y_BASE_AD_SHD;
+               next_buff_addr = &dev->config.mi_config.mp.next_buff_addr;
+               update_mi = cif_isp10_update_mi_mp;
+               if (dev->config.jpeg_config.enable) {
+                       unsigned int jpe_status =
+                               cif_ioread32(dev->config.base_addr +
+                                       CIF_JPE_STATUS_RIS);
+                       if (jpe_status & CIF_JPE_STATUS_ENCODE_DONE) {
+                               cif_iowrite32(CIF_JPE_STATUS_ENCODE_DONE,
+                                       dev->config.base_addr +
+                                               CIF_JPE_STATUS_ICR);
+                               if (stream->curr_buf) {
+                                       stream->curr_buf->size =
+                                       cif_ioread32(dev->config.base_addr +
+                                               CIF_MI_BYTE_CNT);
+                                       cif_isp10_pltfrm_pr_dbg(NULL,
+                                               "JPEG encoding done, size %lu\n",
+                                               stream->curr_buf->size);
+                                       if (cif_ioread32(dev->config.base_addr +
+                                               CIF_MI_RIS) & CIF_MI_WRAP_MP_Y)
+                                               cif_isp10_pltfrm_pr_err(NULL,
+                                                       "buffer wrap around detected, JPEG presumably corrupted (%d/%d/%lu)\n",
+                                                       dev->config.mi_config.
+                                                       mp.y_size,
+                                                       cif_ioread32(
+                                                       dev->config.base_addr +
+                                                       CIF_MI_MP_Y_SIZE_SHD),
+                                                       stream->curr_buf->size);
+                               }
+                       }
+               }
+       } else if (stream_id == CIF_ISP10_STREAM_SP) {
+               stream = &dev->sp_stream;
+               y_base_addr =
+                       dev->config.base_addr + CIF_MI_SP_Y_BASE_AD_SHD;
+               next_buff_addr = &dev->config.mi_config.sp.next_buff_addr;
+               update_mi = cif_isp10_update_mi_sp;
+       } else {
+               WARN_ON(1);
+       }
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s Y_BASE_AD_INIT/Y_BASE_AD_SHD (0x%08x/0x%08x)\n",
+               cif_isp10_stream_id_string(stream_id),
+               (stream_id & CIF_ISP10_STREAM_MP) ?
+                       cif_ioread32(dev->config.base_addr +
+                       CIF_MI_MP_Y_BASE_AD_INIT) :
+                       cif_ioread32(dev->config.base_addr +
+                       CIF_MI_SP_Y_BASE_AD_INIT),
+               cif_ioread32(y_base_addr));
+
+       if ((!stream->next_buf) &&
+               !(dev->config.jpeg_config.enable &&
+               (stream_id == CIF_ISP10_STREAM_MP))) {
+               stream->stall = dev->config.out_of_buffer_stall;
+       } else if ((stream->next_buf) &&
+               (videobuf_to_dma_contig(stream->next_buf) !=
+                       cif_ioread32(y_base_addr))) {
+               cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "%s buffer queue is not advancing (0x%08x/0x%08x)\n",
+                       cif_isp10_stream_id_string(stream_id),
+                       (stream_id & CIF_ISP10_STREAM_MP) ?
+                               cif_ioread32(dev->config.base_addr +
+                               CIF_MI_MP_Y_BASE_AD_INIT) :
+                               cif_ioread32(dev->config.base_addr +
+                               CIF_MI_SP_Y_BASE_AD_INIT),
+                       cif_ioread32(y_base_addr));
+               stream->stall = true;
+       }
+
+       if (!stream->stall) {
+               /*
+                * If mi restart after switch off for buffer is empty,
+                * mi may be restart failed. So mi write data to last
+                * buffer, the last buffer isn't been release to user
+                * until new buffer queue;
+                */
+               if ((stream->curr_buf) &&
+                       (stream->next_buf)) {
+                       bool wake_now;
+
+                       stream->curr_buf->field_count = dev->isp_dev.frame_id;
+                       stream->curr_buf->state = VIDEOBUF_DONE;
+                       wake_now = false;
+
+                       if (stream->metadata.d && dev->isp_dev.streamon) {
+                               struct v4l2_buffer_metadata_s *metadata;
+
+                               metadata = (struct v4l2_buffer_metadata_s *)
+                                       (stream->metadata.d +
+                                       stream->curr_buf->i *
+                                       CAMERA_METADATA_LEN);
+                               metadata->frame_id = dev->isp_dev.frame_id;
+                               metadata->frame_t.vs_t = dev->isp_dev.vs_t;
+                               metadata->frame_t.fi_t = dev->isp_dev.fi_t;
+
+                               work = (struct cif_isp10_isp_readout_work *)
+                                       kmalloc(
+                                       sizeof(
+                                       struct cif_isp10_isp_readout_work),
+                                       GFP_ATOMIC);
+                               if (work) {
+                                       INIT_WORK((struct work_struct *)work,
+                                               cifisp_isp_readout_work);
+                                       work->readout =
+                                               CIF_ISP10_ISP_READOUT_META;
+                                       work->isp_dev =
+                                               &dev->isp_dev;
+                                       work->frame_id =
+                                               dev->isp_dev.frame_id;
+                                       work->vb = stream->curr_buf;
+                                       work->stream_id = stream->id;
+                                       if (!queue_work(dev->isp_dev.readout_wq,
+                                               (struct work_struct *)work)) {
+                                               cif_isp10_pltfrm_pr_err(
+                                               dev->dev,
+                                               "Could not schedule work\n");
+                                               wake_now = true;
+                                               kfree((void *)work);
+                                       }
+                               } else {
+                                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                               "Could not allocate work\n");
+                                       wake_now = true;
+                               }
+                       } else {
+                               wake_now = true;
+                       }
+
+                       if (wake_now) {
+                               cif_isp10_pltfrm_pr_dbg(NULL,
+                                       "frame done\n");
+                               wake_up(&stream->curr_buf->done);
+                       }
+                       stream->curr_buf = NULL;
+               }
+
+               if (!stream->curr_buf) {
+                       stream->curr_buf = stream->next_buf;
+                       stream->next_buf = NULL;
+               }
+       }
+
+       if (!stream->next_buf) {
+               /*
+                * in case of jpeg encoding, we are only programming
+                * a new buffer, if the jpeg header was generated, because
+                * we need the curent buffer for the jpeg encoding
+                * in the current frame period
+                */
+               if (!list_empty(&stream->buf_queue)) {
+                       stream->next_buf =
+                               list_first_entry(&stream->buf_queue,
+                                       struct videobuf_buffer, queue);
+                       list_del(&stream->next_buf->queue);
+                       stream->next_buf->state = VIDEOBUF_ACTIVE;
+                       *next_buff_addr = videobuf_to_dma_contig(
+                               stream->next_buf);
+               } else if (
+               !dev->config.out_of_buffer_stall ||
+               (dev->config.jpeg_config.enable &&
+               (stream_id == CIF_ISP10_STREAM_MP))) {
+/*
+ * If mi restart after switch off for buffer is empty,
+ * mi may be restart failed. So mi write data to last
+ * buffer, the last buffer isn't been release to user
+ * until new buffer queue;
+ *
+ * if
+ * *next_buff_addr = CIF_ISP10_INVALID_BUFF_ADDR;
+ * mi will stop;
+ */
+                       *next_buff_addr =
+                       videobuf_to_dma_contig(
+                       stream->curr_buf);
+               }
+       }
+       (void)update_mi(dev);
+
+       stream->stall = false;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s curr_buff: %d, 0x%08x next_buf: %d, 0x%x\n",
+               cif_isp10_stream_id_string(stream_id),
+               (stream->curr_buf) ? stream->curr_buf->i : -1,
+               (stream->curr_buf) ? (int)videobuf_to_dma_contig
+               (stream->curr_buf) : -1,
+               (stream->next_buf) ? stream->next_buf->i : -1,
+               *next_buff_addr);
+
+       return 0;
+}
+
+static void cif_isp10_stream_metadata_reset(
+       struct cif_isp10_stream *stream_dev
+)
+{
+       unsigned int i;
+       struct v4l2_buffer_metadata_s *metadata;
+       struct cifisp_isp_metadata *isp_metadata;
+
+       if (stream_dev->metadata.d) {
+               for (i = 0; i < stream_dev->metadata.cnt; i++) {
+                       metadata = (struct v4l2_buffer_metadata_s *)
+                               (stream_dev->metadata.d +
+                               i * CAMERA_METADATA_LEN);
+                       isp_metadata = (struct cifisp_isp_metadata *)
+                               metadata->isp;
+                       isp_metadata->other_cfg.s_frame_id = 0xffffffff;
+                       isp_metadata->meas_cfg.s_frame_id = 0xffffffff;
+               }
+       }
+}
+
+static void cif_isp10_start_mi(
+       struct cif_isp10_device *dev,
+       bool start_mi_sp,
+       bool start_mi_mp)
+{
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
+
+       if (start_mi_sp &&
+               (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING))
+               start_mi_sp = false;
+       if (start_mi_mp &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING))
+               start_mi_mp = false;
+       if (!start_mi_sp && !start_mi_mp)
+               return;
+
+       if ((start_mi_sp &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)) ||
+               (start_mi_mp &&
+               (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)))
+               WARN_ON(1);
+
+       if (start_mi_sp) {
+               cif_isp10_stream_metadata_reset(&dev->sp_stream);
+               dev->config.mi_config.sp.next_buff_addr =
+                       CIF_ISP10_INVALID_BUFF_ADDR;
+               dev->config.mi_config.sp.curr_buff_addr =
+                       CIF_ISP10_INVALID_BUFF_ADDR;
+               spin_lock(&dev->vbq_lock);
+               cif_isp10_mi_frame_end(dev, CIF_ISP10_STREAM_SP);
+               spin_unlock(&dev->vbq_lock);
+               dev->sp_stream.stall = false;
+       }
+
+       if (start_mi_mp) {
+               cif_isp10_stream_metadata_reset(&dev->mp_stream);
+               dev->config.mi_config.mp.next_buff_addr =
+                       CIF_ISP10_INVALID_BUFF_ADDR;
+               dev->config.mi_config.mp.curr_buff_addr =
+                       CIF_ISP10_INVALID_BUFF_ADDR;
+               spin_lock(&dev->vbq_lock);
+               cif_isp10_mi_frame_end(dev, CIF_ISP10_STREAM_MP);
+               spin_unlock(&dev->vbq_lock);
+               dev->mp_stream.stall = false;
+       }
+
+       cif_iowrite32OR(CIF_MI_INIT_SOFT_UPD,
+               dev->config.base_addr + CIF_MI_INIT);
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "CIF_MI_INIT_SOFT_UPD\n");
+
+       if (start_mi_sp) {
+               spin_lock(&dev->vbq_lock);
+               cif_isp10_mi_frame_end(dev, CIF_ISP10_STREAM_SP);
+               spin_unlock(&dev->vbq_lock);
+               if (dev->sp_stream.curr_buf &&
+                       (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)))
+                       dev->config.mi_config.sp.busy = true;
+       }
+
+       if (start_mi_mp) {
+               spin_lock(&dev->vbq_lock);
+               cif_isp10_mi_frame_end(dev, CIF_ISP10_STREAM_MP);
+               spin_unlock(&dev->vbq_lock);
+               if (dev->mp_stream.curr_buf &&
+                       (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)))
+                       dev->config.mi_config.mp.busy = true;
+       }
+
+       if (!dev->config.mi_config.async_updt)
+               cif_iowrite32OR(CIF_ISP_CTRL_ISP_GEN_CFG_UPD,
+                       dev->config.base_addr + CIF_ISP_CTRL);
+}
+
+static void cif_isp10_stop_mi(
+       struct cif_isp10_device *dev,
+       bool stop_mi_sp,
+       bool stop_mi_mp)
+{
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
+
+       if (stop_mi_sp &&
+               (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING))
+               stop_mi_sp = false;
+       if (stop_mi_mp &&
+               (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING))
+               stop_mi_mp = false;
+
+       if (!stop_mi_sp && !stop_mi_mp)
+               return;
+
+       if (stop_mi_sp && stop_mi_mp) {
+               cif_iowrite32AND_verify(~(CIF_MI_SP_FRAME |
+                       CIF_MI_MP_FRAME |
+                       CIF_JPE_STATUS_ENCODE_DONE),
+                       dev->config.base_addr + CIF_MI_IMSC, ~0);
+               cif_iowrite32(CIF_MI_SP_FRAME |
+                       CIF_MI_MP_FRAME |
+                       CIF_JPE_STATUS_ENCODE_DONE,
+                       dev->config.base_addr + CIF_MI_ICR);
+               cif_iowrite32AND_verify(~CIF_MI_CTRL_SP_ENABLE,
+                       dev->config.base_addr + CIF_MI_CTRL, ~0);
+               cif_iowrite32AND_verify(~(CIF_MI_CTRL_MP_ENABLE_IN |
+                       CIF_MI_CTRL_SP_ENABLE |
+                       CIF_MI_CTRL_JPEG_ENABLE |
+                       CIF_MI_CTRL_RAW_ENABLE),
+                       dev->config.base_addr + CIF_MI_CTRL, ~0);
+               cif_iowrite32(CIF_MI_INIT_SOFT_UPD,
+                       dev->config.base_addr + CIF_MI_INIT);
+       } else if (stop_mi_sp) {
+               cif_iowrite32(CIF_MI_SP_FRAME,
+                       dev->config.base_addr + CIF_MI_ICR);
+               cif_iowrite32AND_verify(~CIF_MI_CTRL_SP_ENABLE,
+                       dev->config.base_addr + CIF_MI_CTRL, ~0);
+       } else if (stop_mi_mp) {
+               cif_iowrite32(CIF_MI_MP_FRAME |
+                       CIF_JPE_STATUS_ENCODE_DONE,
+                       dev->config.base_addr + CIF_MI_ICR);
+               cif_iowrite32AND_verify(~(CIF_MI_CTRL_MP_ENABLE_IN |
+                       CIF_MI_CTRL_JPEG_ENABLE |
+                       CIF_MI_CTRL_RAW_ENABLE),
+                       dev->config.base_addr + CIF_MI_CTRL, ~0);
+       }
+}
+
+static void cif_isp10_requeue_bufs(
+       struct cif_isp10_device *dev,
+       struct cif_isp10_stream *stream)
+{
+       INIT_LIST_HEAD(&stream->buf_queue);
+       stream->next_buf = NULL;
+       stream->curr_buf = NULL;
+       dev->requeue_bufs(dev, stream->id);
+}
+
+static void cif_isp10_stop_sp(
+       struct cif_isp10_device *dev)
+{
+       int ret;
+
+       if (dev->sp_stream.state ==
+               CIF_ISP10_STATE_STREAMING) {
+               dev->sp_stream.stop = true;
+               ret = cif_isp10_pltfrm_event_wait_timeout(dev->dev,
+                       &dev->sp_stream.done,
+                       dev->sp_stream.state !=
+               CIF_ISP10_STATE_STREAMING,
+                       1000000);
+               dev->sp_stream.stop = false;
+               if (IS_ERR_VALUE(ret)) {
+                       cif_isp10_pltfrm_pr_warn(NULL,
+                               "waiting on event returned with error %d\n",
+                               ret);
+               }
+               if (dev->config.mi_config.sp.busy)
+                       cif_isp10_pltfrm_pr_warn(NULL,
+                               "SP path still active while stopping it\n");
+       }
+}
+
+static void cif_isp10_stop_mp(
+       struct cif_isp10_device *dev)
+{
+       int ret;
+
+       if (dev->mp_stream.state ==
+               CIF_ISP10_STATE_STREAMING) {
+               dev->mp_stream.stop = true;
+               ret = cif_isp10_pltfrm_event_wait_timeout(dev->dev,
+                       &dev->mp_stream.done,
+                       dev->mp_stream.state !=
+               CIF_ISP10_STATE_STREAMING,
+                       1000000);
+               dev->mp_stream.stop = false;
+               if (IS_ERR_VALUE(ret)) {
+                       cif_isp10_pltfrm_pr_warn(NULL,
+                               "waiting on event returned with error %d\n",
+                               ret);
+               }
+               if (dev->config.mi_config.mp.busy ||
+                       dev->config.jpeg_config.busy)
+                       cif_isp10_pltfrm_pr_warn(NULL,
+                               "MP path still active while stopping it\n");
+       }
+}
+
+static void cif_isp10_stop_dma(
+       struct cif_isp10_device *dev)
+{
+       unsigned long flags = 0;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       if (dev->dma_stream.state ==
+               CIF_ISP10_STATE_STREAMING) {
+               /* we should not stop during an active DMA transfer */
+               dev->dma_stream.stop = true;
+               (void)cif_isp10_pltfrm_event_wait_timeout(dev->dev,
+                       &dev->dma_stream.done,
+                       dev->dma_stream.state !=
+                       CIF_ISP10_STATE_STREAMING,
+                       50000);
+               /* intentionally NOT checking dma.busy again */
+               if (dev->config.mi_config.dma.busy)
+                       cif_isp10_pltfrm_pr_warn(NULL,
+                               "DMA transfer still active while stopping it\n");
+               dev->dma_stream.state = CIF_ISP10_STATE_READY;
+               spin_lock_irqsave(&dev->vbq_lock, flags);
+               cif_isp10_requeue_bufs(dev, &dev->dma_stream);
+               spin_unlock_irqrestore(&dev->vbq_lock, flags);
+       }
+}
+
+static int cif_isp10_stop(
+       struct cif_isp10_device *dev,
+       bool stop_sp,
+       bool stop_mp)
+{
+       unsigned long flags = 0;
+       bool stop_all;
+       int timeout;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, img_src state = %s, stop_sp = %d, stop_mp = %d\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_img_src_state_string(dev->img_src_state),
+               stop_sp,
+               stop_mp);
+
+       if (!((stop_mp &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)) ||
+               (stop_sp &&
+               (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)))) {
+               return 0;
+       }
+
+       stop_all = ((stop_mp && stop_sp) ||
+               (stop_sp &&
+               (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING)) ||
+               (stop_mp &&
+               (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING)));
+
+       if (stop_all) {
+               /*
+                * Modify ISP stop sequence for isp bus dead:
+                * ISP(mi) stop in mi frame end -> Stop ISP(mipi) ->
+                * Stop ISP(isp) ->wait for ISP isp off
+                */
+
+               cif_isp10_stop_mp(dev);
+               cif_isp10_stop_sp(dev);
+               cif_isp10_stop_dma(dev);
+
+               local_irq_save(flags);
+               /* stop and clear MI, MIPI, and ISP interrupts */
+               cif_iowrite32(0, dev->config.base_addr + CIF_MIPI_IMSC);
+               cif_iowrite32(~0, dev->config.base_addr + CIF_MIPI_ICR);
+
+               cif_iowrite32(0, dev->config.base_addr + CIF_ISP_IMSC);
+               cif_iowrite32(~0, dev->config.base_addr + CIF_ISP_ICR);
+
+               cif_iowrite32_verify(0,
+                       dev->config.base_addr + CIF_MI_IMSC, ~0);
+               cif_iowrite32(~0, dev->config.base_addr + CIF_MI_ICR);
+
+               cif_iowrite32AND(~CIF_MIPI_CTRL_OUTPUT_ENA,
+                       dev->config.base_addr + CIF_MIPI_CTRL);
+               /* stop ISP */
+               cif_iowrite32AND(~(CIF_ISP_CTRL_ISP_INFORM_ENABLE |
+                       CIF_ISP_CTRL_ISP_ENABLE),
+                       dev->config.base_addr + CIF_ISP_CTRL);
+               cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD,
+                       dev->config.base_addr + CIF_ISP_CTRL);
+
+               timeout = 100;
+               while ((timeout-- > 0) &&
+                       ((cif_ioread32(dev->config.base_addr + CIF_ISP_RIS)
+                       & CIF_ISP_OFF) != CIF_ISP_OFF)) {
+                       msleep(20);
+               };
+               local_irq_restore(flags);
+
+               if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+                       if (IS_ERR_VALUE(cif_isp10_img_src_set_state(dev,
+                               CIF_ISP10_IMG_SRC_STATE_SW_STNDBY)))
+                               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                                       "unable to put image source into standby\n");
+               }
+               if (IS_ERR_VALUE(cif_isp10_set_pm_state(dev,
+                       CIF_ISP10_PM_STATE_SW_STNDBY)))
+                       cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "unable to put CIF into standby\n");
+       } else if (stop_sp) {
+               if (!dev->config.mi_config.async_updt) {
+                       local_irq_save(flags);
+                       cif_isp10_stop_mi(dev, true, false);
+                       local_irq_restore(flags);
+               }
+               cif_isp10_stop_sp(dev);
+               cif_iowrite32AND_verify(~CIF_MI_SP_FRAME,
+                       dev->config.base_addr + CIF_MI_IMSC, ~0);
+
+       } else /* stop_mp */ {
+               if (!dev->config.mi_config.async_updt) {
+                       local_irq_save(flags);
+                       cif_isp10_stop_mi(dev, false, true);
+                       local_irq_restore(flags);
+               }
+               cif_isp10_stop_mp(dev);
+               cif_iowrite32AND_verify(~(CIF_MI_MP_FRAME |
+                       CIF_JPE_STATUS_ENCODE_DONE),
+                       dev->config.base_addr + CIF_MI_IMSC, ~0);
+       }
+
+       if (stop_mp && (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING))
+               dev->mp_stream.state = CIF_ISP10_STATE_READY;
+
+       if (stop_sp && (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING))
+               dev->sp_stream.state = CIF_ISP10_STATE_READY;
+
+       spin_lock(&dev->vbq_lock);
+       if (stop_sp) {
+               dev->config.mi_config.sp.busy = false;
+               cif_isp10_requeue_bufs(dev, &dev->sp_stream);
+       }
+       if (stop_mp) {
+               dev->config.mi_config.mp.busy = false;
+               cif_isp10_requeue_bufs(dev, &dev->mp_stream);
+       }
+       spin_unlock(&dev->vbq_lock);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s\n"
+               "  MI_CTRL 0x%08x\n"
+               "  ISP_CTRL 0x%08x\n"
+               "  MIPI_CTRL 0x%08x\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state),
+               cif_isp10_img_src_state_string(dev->img_src_state),
+               cif_ioread32(dev->config.base_addr + CIF_MI_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_MIPI_CTRL));
+
+       return 0;
+}
+
+static int cif_isp10_start(
+       struct cif_isp10_device *dev,
+       bool start_sp,
+       bool start_mp)
+{
+       unsigned int ret;
+       struct videobuf_buffer *vb, *n;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s, start_sp = %d, start_mp = %d\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state),
+               cif_isp10_img_src_state_string(dev->img_src_state),
+               start_sp,
+               start_mp);
+
+       if (!((start_mp &&
+               (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING)) ||
+               (start_sp &&
+               (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING))))
+               return 0;
+
+       if (CIF_ISP10_INP_IS_DMA(dev->config.input_sel) &&
+               (dev->dma_stream.state < CIF_ISP10_STATE_READY)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "cannot start streaming, input source (DMA) not ready\n");
+               ret = -EFAULT;
+               goto err;
+       }
+
+       /* Activate MI */
+       cif_isp10_start_mi(dev, start_sp, start_mp);
+
+       if ((dev->sp_stream.state != CIF_ISP10_STATE_STREAMING) &&
+               (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING)) {
+               /* Activate MIPI */
+               if (CIF_ISP10_INP_IS_MIPI(dev->config.input_sel))
+                       cif_iowrite32OR(CIF_MIPI_CTRL_OUTPUT_ENA,
+                               dev->config.base_addr + CIF_MIPI_CTRL);
+
+               /* Activate ISP ! */
+               if (CIF_ISP10_INP_NEED_ISP(dev->config.input_sel))
+                       cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD |
+                               CIF_ISP_CTRL_ISP_INFORM_ENABLE |
+                               CIF_ISP_CTRL_ISP_ENABLE,
+                               dev->config.base_addr + CIF_ISP_CTRL);
+       }
+
+       if (start_sp &&
+               (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING)) {
+               dev->sp_stream.state = CIF_ISP10_STATE_STREAMING;
+       }
+       if (start_mp &&
+               (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING)) {
+               dev->mp_stream.state = CIF_ISP10_STATE_STREAMING;
+       }
+       ret = cif_isp10_set_pm_state(dev,
+               CIF_ISP10_PM_STATE_STREAMING);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+               /*
+                * CIF spec says to wait for sufficient time after enabling
+                * the MIPI interface and before starting the sensor output.
+                */
+               mdelay(1);
+               /* start sensor output! */
+               dev->isp_dev.frame_id = 0;
+               dev->isp_dev.frame_id_setexp = 0;
+               videobuf_queue_lock(&dev->isp_dev.vbq_stat);
+               list_for_each_entry_safe(
+                       vb, n, &dev->isp_dev.vbq_stat.stream, queue) {
+                       if (vb->state == VIDEOBUF_DONE) {
+                               vb->field_count = -1;
+                               cif_isp10_pltfrm_pr_info(
+                                       dev->dev,
+                                       "discard vb: %d\n", vb->i);
+                       }
+               }
+               videobuf_queue_unlock(&dev->isp_dev.vbq_stat);
+
+               mutex_lock(&dev->img_src_exps.mutex);
+               cif_isp10_img_src_ioctl(dev->img_src,
+                       RK_VIDIOC_SENSOR_MODE_DATA,
+                       &dev->img_src_exps.data[0].data);
+               cif_isp10_img_src_ioctl(dev->img_src,
+                       RK_VIDIOC_SENSOR_MODE_DATA,
+                       &dev->img_src_exps.data[1].data);
+               dev->img_src_exps.data[0].v_frame_id = 0;
+               dev->img_src_exps.data[1].v_frame_id = 0;
+               mutex_unlock(&dev->img_src_exps.mutex);
+
+               cif_isp10_pltfrm_rtrace_printf(dev->dev,
+                       "starting image source...\n");
+               ret = cif_isp10_img_src_set_state(dev,
+                       CIF_ISP10_IMG_SRC_STATE_STREAMING);
+               if (IS_ERR_VALUE(ret))
+                       goto err;
+       } else {
+               cif_isp10_pltfrm_rtrace_printf(dev->dev,
+                       "starting DMA...\n");
+               dev->dma_stream.state = CIF_ISP10_STATE_STREAMING;
+               dev->dma_stream.stop = false;
+               cif_isp10_dma_next_buff(dev);
+       }
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s\n"
+               "  MI_CTRL 0x%08x\n"
+               "  ISP_CTRL 0x%08x\n"
+               "  MIPI_CTRL 0x%08x\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state),
+               cif_isp10_img_src_state_string(dev->img_src_state),
+               cif_ioread32(dev->config.base_addr + CIF_MI_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_MIPI_CTRL));
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s\n"
+               "  MI_CTRL 0x%08x\n"
+               "  ISP_CTRL 0x%08x\n"
+               "  MIPI_CTRL 0x%08x\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state),
+               cif_isp10_img_src_state_string(dev->img_src_state),
+               cif_ioread32(dev->config.base_addr + CIF_MI_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_CTRL),
+               cif_ioread32(dev->config.base_addr + CIF_MIPI_CTRL));
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+/* Function to be called inside ISR to update CIF ISM/DCROP/RSZ */
+static int cif_isp10_update_ism_dcr_rsz(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+
+       if (dev->config.isp_config.ism_config.ism_update_needed) {
+               if (dev->config.isp_config.ism_config.ism_en) {
+                       if (!dev->isp_dev.cif_ism_cropping)
+                               dev->isp_dev.cif_ism_cropping = true;
+               } else {
+                       if (dev->isp_dev.cif_ism_cropping)
+                               dev->isp_dev.cif_ism_cropping = false;
+               }
+       }
+
+       /*
+        * Update ISM, cif_isp10_config_ism() changes the output size of isp,
+        * so it must be called before cif_isp10_config_rsz()
+        */
+       if (dev->config.isp_config.ism_config.ism_update_needed) {
+               cif_isp10_config_ism(dev, false);
+               if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)
+                       dev->config.mp_config.rsz_config.ism_adjust = true;
+               if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)
+                       dev->config.sp_config.rsz_config.ism_adjust = true;
+
+               dev->config.isp_config.ism_config.ism_update_needed = false;
+               cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD,
+                       dev->config.base_addr + CIF_ISP_CTRL);
+
+               if (dev->config.isp_config.ism_config.ism_en)
+                       dev->config.mi_config.async_updt |= CIF_ISP10_ASYNC_ISM;
+       }
+
+       /* Update RSZ */
+       if ((dev->config.mp_config.rsz_config.ycflt_adjust ||
+               dev->config.mp_config.rsz_config.ism_adjust)) {
+               ret = cif_isp10_config_rsz(dev, CIF_ISP10_STREAM_MP, true);
+               if (IS_ERR_VALUE(ret))
+                       goto err;
+       }
+       if ((dev->config.sp_config.rsz_config.ycflt_adjust ||
+               dev->config.sp_config.rsz_config.ism_adjust)) {
+               ret = cif_isp10_config_rsz(dev, CIF_ISP10_STREAM_SP, true);
+               if (IS_ERR_VALUE(ret))
+                       goto err;
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_mi_isr(unsigned int mi_mis, void *cntxt)
+{
+       struct cif_isp10_device *dev = cntxt;
+       unsigned int mi_mis_tmp;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "\n  MI_RIS 0x%08x\n"
+               "  MI_IMSC 0x%08x\n"
+               "  MI_MIS 0x%08x\n",
+               cif_ioread32(dev->config.base_addr + CIF_MI_RIS),
+               cif_ioread32(dev->config.base_addr + CIF_MI_IMSC),
+               mi_mis);
+
+       cif_isp10_pltfrm_rtrace_printf(dev->dev,
+               "MI_MIS %08x, MI_RIS %08x, MI_IMSC %08x\n",
+               mi_mis,
+               cif_ioread32(dev->config.base_addr + CIF_MI_RIS),
+               cif_ioread32(dev->config.base_addr + CIF_MI_IMSC));
+
+       if (mi_mis & CIF_MI_SP_FRAME) {
+               dev->config.mi_config.sp.busy = false;
+               cif_iowrite32(CIF_MI_SP_FRAME,
+                       dev->config.base_addr + CIF_MI_ICR);
+               mi_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_MI_MIS);
+               if (mi_mis_tmp & CIF_MI_SP_FRAME)
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                               "sp icr err: 0x%x\n",
+                                               mi_mis_tmp);
+       }
+
+       if (mi_mis & CIF_MI_MP_FRAME) {
+               dev->config.mi_config.mp.busy = false;
+               cif_iowrite32(CIF_MI_MP_FRAME,
+                       dev->config.base_addr + CIF_MI_ICR);
+               mi_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_MI_MIS);
+               if (mi_mis_tmp & CIF_MI_MP_FRAME)
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                               "mp icr err: 0x%x\n",
+                                               mi_mis_tmp);
+       }
+       if (mi_mis & CIF_MI_DMA_READY)
+               (void)cif_isp10_dma_ready(dev);
+       if (dev->config.jpeg_config.enable &&
+               (cif_ioread32(dev->config.base_addr +
+                       CIF_JPE_STATUS_RIS) & CIF_JPE_STATUS_ENCODE_DONE))
+               dev->config.jpeg_config.busy = false;
+
+       if (!CIF_ISP10_MI_IS_BUSY(dev) &&
+               !dev->config.jpeg_config.busy) {
+               if (dev->config.mi_config.async_updt) {
+                       u32 mp_y_off_cnt_shd =
+                               cif_ioread32(dev->config.base_addr +
+                               CIF_MI_MP_Y_OFFS_CNT_SHD);
+                       u32 sp_y_off_cnt_shd =
+                               cif_ioread32(dev->config.base_addr +
+                               CIF_MI_SP_Y_OFFS_CNT_SHD);
+
+                       cif_iowrite32(CIF_MI_INIT_SOFT_UPD,
+                               dev->config.base_addr + CIF_MI_INIT);
+                       cif_isp10_pltfrm_pr_dbg(NULL,
+                               "CIF_MI_INIT_SOFT_UPD\n");
+                       if (!dev->config.isp_config.ism_config.ism_en &&
+                               (dev->config.mi_config.async_updt &
+                               CIF_ISP10_ASYNC_ISM))
+                               dev->config.mi_config.async_updt &=
+                                       ~CIF_ISP10_ASYNC_ISM;
+                       if (sp_y_off_cnt_shd != 0) {
+                               spin_lock(&dev->vbq_lock);
+                               cif_isp10_requeue_bufs(dev, &dev->sp_stream);
+                               spin_unlock(&dev->vbq_lock);
+                       }
+                       if ((mp_y_off_cnt_shd != 0) &&
+                               (!dev->config.jpeg_config.enable)) {
+                               spin_lock(&dev->vbq_lock);
+                               cif_isp10_requeue_bufs(dev, &dev->mp_stream);
+                               spin_unlock(&dev->vbq_lock);
+                       }
+                       if (((mp_y_off_cnt_shd != 0) &&
+                               !dev->config.jpeg_config.enable) ||
+                               (sp_y_off_cnt_shd != 0)) {
+                               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                                       "soft update too late (SP offset %d, MP offset %d)\n",
+                                       sp_y_off_cnt_shd, mp_y_off_cnt_shd);
+                       }
+               }
+
+               if (dev->mp_stream.stop &&
+                       (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)) {
+                       cif_isp10_stop_mi(dev, false, true);
+                       dev->mp_stream.state = CIF_ISP10_STATE_READY;
+                       dev->mp_stream.stop = false;
+
+                       /* Turn off MRSZ since it is not needed */
+                       cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_CTRL);
+                       cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+                               dev->config.base_addr + CIF_MRSZ_CTRL);
+
+                       cif_isp10_pltfrm_pr_dbg(NULL,
+                               "MP has stopped\n");
+                       cif_isp10_pltfrm_event_signal(dev->dev,
+                               &dev->mp_stream.done);
+               }
+               if (dev->sp_stream.stop &&
+                       (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)) {
+                       cif_isp10_stop_mi(dev, true, false);
+                       dev->sp_stream.state = CIF_ISP10_STATE_READY;
+                       dev->sp_stream.stop = false;
+
+                       /* Turn off SRSZ since it is not needed */
+                       cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_CTRL);
+                       cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+                               dev->config.base_addr + CIF_SRSZ_CTRL);
+
+                       cif_isp10_pltfrm_pr_dbg(NULL,
+                               "SP has stopped\n");
+                       cif_isp10_pltfrm_event_signal(dev->dev,
+                               &dev->sp_stream.done);
+               }
+
+               if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING) {
+                       spin_lock(&dev->vbq_lock);
+                       (void)cif_isp10_mi_frame_end(dev,
+                               CIF_ISP10_STREAM_SP);
+                       spin_unlock(&dev->vbq_lock);
+               }
+               if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) {
+                       spin_lock(&dev->vbq_lock);
+                       (void)cif_isp10_mi_frame_end(dev,
+                               CIF_ISP10_STREAM_MP);
+                       spin_unlock(&dev->vbq_lock);
+               }
+
+               dev->b_mi_frame_end = true;
+
+               if (dev->dma_stream.state == CIF_ISP10_STATE_STREAMING) {
+                       cif_isp10_dma_next_buff(dev);
+               } else {
+                       if ((dev->sp_stream.state ==
+                               CIF_ISP10_STATE_STREAMING) &&
+                               dev->sp_stream.curr_buf)
+                               dev->config.mi_config.sp.busy = true;
+                       if ((dev->mp_stream.state ==
+                               CIF_ISP10_STATE_STREAMING) &&
+                               dev->mp_stream.curr_buf)
+                               dev->config.mi_config.mp.busy = true;
+               }
+
+               if (dev->b_isp_frame_in &&
+               ((dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) ||
+               (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)))
+                       cif_isp10_update_ism_dcr_rsz(dev);
+       }
+
+       cif_iowrite32(~(CIF_MI_MP_FRAME |
+               CIF_MI_SP_FRAME | CIF_MI_DMA_READY),
+               dev->config.base_addr + CIF_MI_ICR);
+
+       return 0;
+}
+
+static int cif_isp10_register_isrs(struct cif_isp10_device *dev)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_irq_register_isr(
+               dev->dev,
+               CIF_ISP_MIS,
+               cif_isp10_isp_isr,
+               dev);
+       if (IS_ERR_VALUE(ret))
+               cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "unable to register ISP ISR, some processing errors may go unnoticed\n");
+
+       cif_isp10_pltfrm_irq_register_isr(
+               dev->dev,
+               CIF_MIPI_MIS,
+               cif_isp10_mipi_isr,
+               dev);
+       if (IS_ERR_VALUE(ret))
+               cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "unable to register MIPI ISR, MIPI errors may go unnoticed\n");
+
+       ret = cif_isp10_pltfrm_irq_register_isr(
+               dev->dev,
+               CIF_MI_MIS,
+               cif_isp10_mi_isr,
+               dev);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unable to register MI ISR, aborting\n");
+               goto err;
+       }
+
+       return 0;
+
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev, "failed with error %d", ret);
+       return ret;
+}
+
+static void cif_isp10_vs_work(struct work_struct *work)
+{
+       struct cif_isp10_isp_vs_work *vs_wk =
+               container_of(work, struct cif_isp10_isp_vs_work, work);
+       struct cif_isp10_device *dev = vs_wk->dev;
+
+       switch (vs_wk->cmd) {
+       case CIF_ISP10_VS_EXP: {
+               struct cif_isp10_img_src_exp *exp =
+                       (struct cif_isp10_img_src_exp *)vs_wk->param;
+               struct cif_isp10_img_src_ext_ctrl *exp_ctrl = exp->exp;
+               struct cif_isp10_img_src_data *new_data;
+
+               if (dev->img_src)
+                       cif_isp10_img_src_s_ext_ctrls(dev->img_src, exp_ctrl);
+               else
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                       "dev->img_src is NULL\n");
+
+               if (dev->img_src_exps.data[0].v_frame_id <
+                       dev->img_src_exps.data[1].v_frame_id)
+                       new_data = &dev->img_src_exps.data[0];
+               else
+                       new_data = &dev->img_src_exps.data[1];
+
+               mutex_lock(&dev->img_src_exps.mutex);
+               new_data->v_frame_id = dev->isp_dev.frame_id +
+                       dev->img_src_exps.exp_valid_frms;
+               cif_isp10_img_src_ioctl(dev->img_src,
+                       RK_VIDIOC_SENSOR_MODE_DATA,
+                       &new_data->data);
+               mutex_unlock(&dev->img_src_exps.mutex);
+
+               /*
+                * pr_info("%s: exp_time: %d gain: %d, frame_id: s %d, v %d\n",
+                * __func__,
+                * new_data->data.exp_time,
+                * new_data->data.gain,
+                * dev->isp_dev.frame_id,
+                * new_data->v_frame_id);
+                */
+
+               kfree(exp->exp->ctrls);
+               exp->exp->ctrls = NULL;
+               kfree(exp->exp);
+               exp->exp = NULL;
+               kfree(exp);
+               exp = NULL;
+               break;
+       }
+       default:
+               break;
+       }
+
+       kfree(vs_wk);
+       vs_wk = NULL;
+}
+
+/* Public Functions */
+void cif_isp10_sensor_mode_data_sync(
+       struct cif_isp10_device *dev,
+       unsigned int frame_id,
+       struct isp_supplemental_sensor_mode_data *data)
+{
+       struct cif_isp10_img_src_data *last_data;
+       struct cif_isp10_img_src_data *new_data;
+
+       mutex_lock(&dev->img_src_exps.mutex);
+       if (dev->img_src_exps.data[0].v_frame_id <
+               dev->img_src_exps.data[1].v_frame_id) {
+               last_data = &dev->img_src_exps.data[0];
+               new_data = &dev->img_src_exps.data[1];
+       } else {
+               last_data = &dev->img_src_exps.data[1];
+               new_data = &dev->img_src_exps.data[0];
+       }
+
+       if (frame_id >= new_data->v_frame_id) {
+               memcpy(data,
+                       &new_data->data,
+                       sizeof(struct isp_supplemental_sensor_mode_data));
+       } else {
+               memcpy(data,
+                       &last_data->data,
+                       sizeof(struct isp_supplemental_sensor_mode_data));
+       }
+       mutex_unlock(&dev->img_src_exps.mutex);
+}
+
+int cif_isp10_streamon(
+       struct cif_isp10_device *dev,
+       u32 stream_ids)
+{
+       int ret = 0;
+       bool streamon_sp = stream_ids & CIF_ISP10_STREAM_SP;
+       bool streamon_mp = stream_ids & CIF_ISP10_STREAM_MP;
+       bool streamon_dma = stream_ids & CIF_ISP10_STREAM_DMA;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s, streamon SP = %d, streamon MP = %d, streamon DMA = %d\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state),
+               streamon_sp, streamon_mp, streamon_dma);
+
+       if (!((streamon_sp &&
+               (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING)) ||
+               (streamon_mp &&
+               (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING))))
+               return 0;
+
+       if (streamon_sp &&
+               (dev->sp_stream.state != CIF_ISP10_STATE_READY)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "cannot start streaming on SP path, path not yet enabled\n");
+               ret = -EFAULT;
+               goto err;
+       }
+
+       if (streamon_mp && (dev->mp_stream.state != CIF_ISP10_STATE_READY)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "cannot start streaming on MP path, path not yet enabled\n");
+               ret = -EFAULT;
+               goto err;
+       }
+
+       if (streamon_sp && dev->config.mi_config.raw_enable &&
+               (streamon_mp ||
+               (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING))) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "cannot start streaming on SP path when MP is active and set to RAW output\n");
+               ret = -EBUSY;
+               goto err;
+       }
+
+       if (streamon_mp &&
+               (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING))
+               dev->mp_stream.updt_cfg = true;
+       if (streamon_sp &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING))
+               dev->sp_stream.updt_cfg = true;
+
+       if (streamon_sp && dev->sp_stream.updt_cfg &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)) {
+               ret = cif_isp10_stop(dev, false, true);
+                               if (IS_ERR_VALUE(ret))
+                                       goto err;
+                               streamon_mp = true;
+                               dev->mp_stream.updt_cfg = true;
+       }
+       if (streamon_mp && dev->mp_stream.updt_cfg &&
+               (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)) {
+               ret = cif_isp10_stop(dev, true, false);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+
+                       streamon_sp = true;
+                       dev->sp_stream.updt_cfg = true;
+       }
+
+       stream_ids = 0;
+       if (streamon_mp && dev->mp_stream.updt_cfg)
+               stream_ids |= CIF_ISP10_STREAM_MP;
+       if (streamon_sp && dev->sp_stream.updt_cfg)
+               stream_ids |= CIF_ISP10_STREAM_SP;
+
+       ret = cif_isp10_config_cif(dev, stream_ids);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       ret = cif_isp10_start(dev, streamon_sp, streamon_mp);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state));
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state));
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_streamoff(
+       struct cif_isp10_device *dev,
+       u32 stream_ids)
+{
+       int ret = 0;
+       bool streamoff_sp = stream_ids & CIF_ISP10_STREAM_SP;
+       bool streamoff_mp = stream_ids & CIF_ISP10_STREAM_MP;
+       bool streamoff_dma = stream_ids & CIF_ISP10_STREAM_DMA;
+       unsigned int streamoff_all = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s, streamoff SP = %d, streamoff MP = %d, streamoff DMA = %d\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state),
+               streamoff_sp,
+               streamoff_mp,
+               streamoff_dma);
+
+       if (dev->config.flash_mode != CIF_ISP10_FLASH_MODE_OFF &&
+               ((streamoff_sp &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_INACTIVE)) ||
+               (streamoff_mp &&
+               (dev->sp_stream.state == CIF_ISP10_STATE_INACTIVE))))
+               cif_isp10_img_src_s_ctrl(dev->img_src,
+                       CIF_ISP10_CID_FLASH_MODE,
+                       CIF_ISP10_FLASH_MODE_OFF);
+
+       streamoff_all = 0;
+       if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING) {
+               if (streamoff_sp)
+                       streamoff_all |= CIF_ISP10_STREAM_SP;
+       } else {
+               streamoff_all |= CIF_ISP10_STREAM_SP;
+       }
+       if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) {
+               if (streamoff_mp)
+                       streamoff_all |= CIF_ISP10_STREAM_MP;
+       } else {
+               streamoff_all |= CIF_ISP10_STREAM_MP;
+       }
+       if (streamoff_all == (CIF_ISP10_STREAM_MP | CIF_ISP10_STREAM_SP))
+               drain_workqueue(dev->vs_wq);
+
+       ret = cif_isp10_stop(dev, streamoff_sp, streamoff_mp);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+       if ((streamoff_sp) &&
+               (dev->sp_stream.state == CIF_ISP10_STATE_READY))
+               dev->sp_stream.state = CIF_ISP10_STATE_INACTIVE;
+       if (streamoff_mp) {
+               dev->config.jpeg_config.enable = false;
+               dev->config.mi_config.raw_enable = false;
+               dev->config.mi_config.mp.output.width = 0;
+               dev->config.mi_config.mp.output.height = 0;
+               dev->config.mi_config.mp.output.pix_fmt =
+                       CIF_UNKNOWN_FORMAT;
+               if (dev->mp_stream.state == CIF_ISP10_STATE_READY)
+                       dev->mp_stream.state = CIF_ISP10_STATE_INACTIVE;
+       }
+       if (streamoff_dma) {
+               cif_isp10_stop_dma(dev);
+               if (dev->dma_stream.state == CIF_ISP10_STATE_READY)
+                       dev->dma_stream.state = CIF_ISP10_STATE_INACTIVE;
+       }
+       if ((dev->dma_stream.state <= CIF_ISP10_STATE_INACTIVE) &&
+               (dev->mp_stream.state <= CIF_ISP10_STATE_INACTIVE) &&
+               (dev->sp_stream.state <= CIF_ISP10_STATE_INACTIVE)) {
+               dev->isp_dev.input_width = 0;
+               dev->isp_dev.input_height = 0;
+               dev->config.isp_config.ism_config.ism_en = 0;
+       }
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s, # frames received = %d\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state),
+               dev->isp_dev.frame_id >> 1);
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s, DMA state = %s\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state),
+               cif_isp10_state_string(dev->dma_stream.state));
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_suspend(
+       struct cif_isp10_device *dev)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state));
+
+       if ((dev->pm_state == CIF_ISP10_PM_STATE_SUSPENDED) ||
+               (dev->pm_state == CIF_ISP10_PM_STATE_OFF))
+               return 0;
+
+       dev->sp_stream.saved_state = dev->sp_stream.state;
+       dev->mp_stream.saved_state = dev->mp_stream.state;
+       ret = cif_isp10_stop(dev, true, true);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+       ret = cif_isp10_set_pm_state(dev, CIF_ISP10_PM_STATE_SUSPENDED);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+       ret = cif_isp10_img_src_set_state(dev, CIF_ISP10_IMG_SRC_STATE_OFF);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_resume(
+       struct cif_isp10_device *dev)
+{
+       u32 stream_ids = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "SP state = %s, MP state = %s\n",
+               cif_isp10_state_string(dev->sp_stream.state),
+               cif_isp10_state_string(dev->mp_stream.state));
+
+       if ((dev->sp_stream.saved_state == CIF_ISP10_STATE_READY) ||
+               (dev->sp_stream.saved_state == CIF_ISP10_STATE_STREAMING)) {
+               dev->sp_stream.updt_cfg = true;
+               dev->sp_stream.state = CIF_ISP10_STATE_READY;
+               if (dev->sp_stream.saved_state == CIF_ISP10_STATE_STREAMING)
+                       stream_ids |= CIF_ISP10_STREAM_SP;
+       }
+       if ((dev->mp_stream.saved_state == CIF_ISP10_STATE_READY) ||
+               (dev->mp_stream.saved_state == CIF_ISP10_STATE_STREAMING)) {
+               dev->mp_stream.updt_cfg = true;
+               dev->mp_stream.state = CIF_ISP10_STATE_READY;
+               if (dev->mp_stream.saved_state == CIF_ISP10_STATE_STREAMING)
+                       stream_ids |= CIF_ISP10_STREAM_MP;
+       }
+
+       if ((dev->dma_stream.saved_state == CIF_ISP10_STATE_READY) ||
+               (dev->dma_stream.saved_state == CIF_ISP10_STATE_STREAMING)) {
+               dev->dma_stream.state = CIF_ISP10_STATE_READY;
+               if (dev->dma_stream.saved_state == CIF_ISP10_STATE_STREAMING)
+                       stream_ids |= CIF_ISP10_STREAM_DMA;
+       }
+
+       return cif_isp10_streamon(dev, stream_ids);
+}
+
+int cif_isp10_s_fmt(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id,
+       struct cif_isp10_strm_fmt *strm_fmt,
+       u32 stride)
+{
+       int ret;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+               cif_isp10_stream_id_string(stream_id));
+
+       switch (stream_id) {
+       case CIF_ISP10_STREAM_SP:
+               return cif_isp10_s_fmt_sp(dev, strm_fmt, stride);
+       case CIF_ISP10_STREAM_MP:
+               return cif_isp10_s_fmt_mp(dev, strm_fmt, stride);
+       case CIF_ISP10_STREAM_DMA:
+               return cif_isp10_s_fmt_dma(dev, strm_fmt, stride);
+       default:
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown/unsupported stream ID %d\n", stream_id);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(NULL,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_init(
+       struct cif_isp10_device *dev,
+       u32 stream_ids)
+{
+       int ret;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "0x%08x\n", stream_ids);
+
+       if (stream_ids & ~(CIF_ISP10_ALL_STREAMS)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown/unsupported stream IDs 0x%08x\n",
+                       stream_ids);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* set default input, failure is not fatal here */
+       if ((dev->sp_stream.state == CIF_ISP10_STATE_DISABLED) &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_DISABLED)) {
+               (void)cif_isp10_s_input(dev, 0);
+               dev->config.isp_config.si_enable = false;
+               dev->config.isp_config.ie_config.effect =
+                       CIF_ISP10_IE_NONE;
+       }
+
+       if (stream_ids & CIF_ISP10_STREAM_SP)
+               cif_isp10_init_stream(dev, CIF_ISP10_STREAM_SP);
+       if (stream_ids & CIF_ISP10_STREAM_MP)
+               cif_isp10_init_stream(dev, CIF_ISP10_STREAM_MP);
+       if (stream_ids & CIF_ISP10_STREAM_DMA)
+               cif_isp10_init_stream(dev, CIF_ISP10_STREAM_DMA);
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(NULL,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_release(
+       struct cif_isp10_device *dev,
+       int stream_ids)
+{
+       int ret;
+       struct cif_isp10_stream *strm_dev;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "0x%08x\n", stream_ids);
+
+       if ((dev->sp_stream.state == CIF_ISP10_STATE_DISABLED) &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_DISABLED) &&
+               (dev->dma_stream.state == CIF_ISP10_STATE_DISABLED))
+               return 0;
+
+       if (stream_ids & ~(CIF_ISP10_ALL_STREAMS)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown/unsupported stream IDs 0x%08x\n",
+                       stream_ids);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (stream_ids == CIF_ISP10_STREAM_MP)
+               strm_dev = &dev->mp_stream;
+       else if (stream_ids == CIF_ISP10_STREAM_SP)
+               strm_dev = &dev->sp_stream;
+       else
+               strm_dev = NULL;
+
+       if (strm_dev) {
+               if (strm_dev->metadata.d) {
+                       vfree(strm_dev->metadata.d);
+                       strm_dev->metadata.d = NULL;
+                       strm_dev->metadata.cnt = 0;
+               }
+       }
+
+       if (stream_ids & CIF_ISP10_STREAM_SP) {
+               if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING) {
+                       cif_isp10_pltfrm_pr_warn(dev->dev,
+                               "CIF SP in streaming state, should be stopped before release, trying to stop it\n");
+                       ret = cif_isp10_stop(dev, true, false);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               }
+               dev->sp_stream.state = CIF_ISP10_STATE_DISABLED;
+       }
+       if (stream_ids & CIF_ISP10_STREAM_MP) {
+               if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) {
+                       cif_isp10_pltfrm_pr_warn(dev->dev,
+                               "CIF MP in streaming state, should be stopped before release, trying to stop it\n");
+                       ret = cif_isp10_stop(dev, false, true);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+               }
+               dev->mp_stream.state = CIF_ISP10_STATE_DISABLED;
+       }
+
+       if ((dev->sp_stream.state == CIF_ISP10_STATE_DISABLED) &&
+               (dev->mp_stream.state == CIF_ISP10_STATE_DISABLED)) {
+               if (IS_ERR_VALUE(cif_isp10_set_pm_state(dev,
+                       CIF_ISP10_PM_STATE_OFF)))
+                       cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "CIF power off failed\n");
+               if (dev->img_src) {
+                       if (IS_ERR_VALUE(cif_isp10_img_src_set_state(dev,
+                               CIF_ISP10_IMG_SRC_STATE_OFF)))
+                               cif_isp10_pltfrm_pr_warn(dev->dev,
+                                       "image source power off failed\n");
+                       dev->img_src = NULL;
+               }
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+struct cif_isp10_device *cif_isp10_create(
+       CIF_ISP10_PLTFRM_DEVICE pdev,
+       void (*sof_event)(struct cif_isp10_device *dev, __u32 frame_sequence),
+       void (*requeue_bufs)(struct cif_isp10_device *dev,
+                                       enum cif_isp10_stream_id stream_id),
+       struct pltfrm_soc_cfg *soc_cfg)
+{
+       int ret;
+       struct cif_isp10_device *dev;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       /* Allocate needed structures */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "memory allocation failed\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+       dev->sof_event = sof_event;
+       dev->requeue_bufs = requeue_bufs;
+
+       ret = cif_isp10_pltfrm_dev_init(dev,
+               &pdev, &dev->config.base_addr);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+       cif_isp10_pltfrm_debug_register_print_cb(
+               dev->dev,
+               (void (*)(void *, const char *))cif_isp10_debug_print_block,
+               dev);
+
+       cif_isp10_pltfrm_soc_init(dev, soc_cfg);
+
+       ret = cif_isp10_img_srcs_init(dev);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+               "cif_isp10_img_srcs_init failed\n");
+               goto err;
+       }
+
+       ret = cif_isp10_register_isrs(dev);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       (void)cif_isp10_init(dev, CIF_ISP10_ALL_STREAMS);
+       dev->pm_state = CIF_ISP10_PM_STATE_OFF;
+       dev->sp_stream.state = CIF_ISP10_STATE_DISABLED;
+       dev->sp_stream.id = CIF_ISP10_STREAM_SP;
+       dev->mp_stream.state = CIF_ISP10_STATE_DISABLED;
+       dev->mp_stream.id = CIF_ISP10_STREAM_MP;
+       dev->dma_stream.state = CIF_ISP10_STATE_DISABLED;
+       dev->dma_stream.id = CIF_ISP10_STREAM_DMA;
+       dev->config.mi_config.async_updt = 0;
+       cif_isp10_pltfrm_event_init(dev->dev, &dev->dma_stream.done);
+       cif_isp10_pltfrm_event_init(dev->dev, &dev->sp_stream.done);
+       cif_isp10_pltfrm_event_init(dev->dev, &dev->mp_stream.done);
+
+       dev->img_src_exps.exp_valid_frms = 2;
+       mutex_init(&dev->img_src_exps.mutex);
+       memset(&dev->img_src_exps.data, 0x00, sizeof(dev->img_src_exps.data));
+       spin_lock_init(&dev->img_src_exps.lock);
+       INIT_LIST_HEAD(&dev->img_src_exps.list);
+       dev->vs_wq = alloc_workqueue("cif isp10 vs workqueue",
+                       WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+
+       /* TBD: clean this up */
+       init_output_formats();
+
+       return dev;
+err:
+       cif_isp10_pltfrm_pr_err(NULL,
+               "failed with error %d\n", ret);
+       if (!IS_ERR_OR_NULL(dev))
+               kfree(dev);
+       return ERR_PTR(ret);
+}
+
+void cif_isp10_destroy(
+       struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+       if (!IS_ERR_OR_NULL(dev))
+               kfree(dev);
+}
+
+int cif_isp10_s_input(
+       struct cif_isp10_device *dev,
+       unsigned int input)
+{
+       int ret;
+       enum cif_isp10_inp inp;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "setting input to %s\n",
+               cif_isp10_inp_string(
+               cif_isp10_input_index2inp(dev, input)));
+
+       if (input >= dev->img_src_cnt + CIF_ISP10_INP_DMA_CNT()) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "invalid input %d\n", input);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       dev->img_src = NULL;
+
+       inp = cif_isp10_input_index2inp(dev, input);
+
+       /* DMA -> ISP or DMA -> IE */
+       if ((inp == CIF_ISP10_INP_DMA) || (inp == CIF_ISP10_INP_DMA_IE))
+               dev->config.isp_config.input =
+                       &dev->config.mi_config.dma.output;
+       else {
+               dev->img_src = dev->img_src_array[input];
+               dev->config.isp_config.input =
+                       &dev->config.img_src_output.frm_fmt;
+       }
+       dev->config.input_sel = inp;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(NULL,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+const char *cif_isp10_g_input_name(
+       struct cif_isp10_device *dev,
+       unsigned int input_index)
+{
+       if (input_index >=
+               dev->img_src_cnt + CIF_ISP10_INP_DMA_CNT()) {
+               cif_isp10_pltfrm_pr_dbg(NULL,
+                       "index %d out of bounds\n",
+                       input_index);
+               return NULL;
+       }
+
+       if (input_index < dev->img_src_cnt)
+               return cif_isp10_img_src_g_name(
+                       dev->img_src_array[input_index]);
+       else
+               return cif_isp10_inp_string(CIF_ISP10_INP_DMA +
+                       ((input_index - dev->img_src_cnt) << 24));
+}
+
+int cif_isp10_qbuf(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream,
+       struct cif_isp10_buffer *buf)
+{
+       int ret = 0;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "%s\n",
+               cif_isp10_stream_id_string(stream));
+
+       switch (stream) {
+       case CIF_ISP10_STREAM_SP:
+               list_add_tail(&buf->queue, &dev->sp_stream.buf_queue);
+               break;
+       case CIF_ISP10_STREAM_MP:
+               list_add_tail(&buf->queue, &dev->mp_stream.buf_queue);
+               break;
+       case CIF_ISP10_STREAM_DMA:
+               list_add_tail(&buf->queue, &dev->dma_stream.buf_queue);
+               if ((dev->dma_stream.state == CIF_ISP10_STATE_STREAMING) &&
+                       !CIF_ISP10_MI_IS_BUSY(dev))
+                       cif_isp10_dma_next_buff(dev);
+               break;
+       case CIF_ISP10_STREAM_ISP:
+               WARN_ON(1);
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unknown stream %d\n", stream);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_reqbufs(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id strm,
+       struct v4l2_requestbuffers *req)
+{
+       struct cif_isp10_stream *strm_dev = NULL;
+
+       switch (strm) {
+       case CIF_ISP10_STREAM_MP:
+               strm_dev = &dev->mp_stream;
+               break;
+       case CIF_ISP10_STREAM_SP:
+               strm_dev = &dev->sp_stream;
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unknown stream id%d\n", strm);
+               break;
+       }
+
+       strm_dev->metadata.cnt = req->count;
+
+       return 0;
+}
+
+int cif_isp10_s_exp(
+       struct cif_isp10_device *dev,
+       struct cif_isp10_img_src_ext_ctrl *exp_ctrl)
+{
+       struct cif_isp10_img_src_exp *exp = NULL;
+       unsigned long lock_flags;
+       int retval;
+
+       if (!dev->vs_wq)
+               return -ENODEV;
+
+       exp = kmalloc(sizeof(*exp), GFP_KERNEL);
+       if (!exp) {
+               retval = -ENOMEM;
+               goto failed;
+       }
+
+       exp->exp = exp_ctrl;
+
+       spin_lock_irqsave(&dev->img_src_exps.lock, lock_flags);
+       list_add_tail(&exp->list, &dev->img_src_exps.list);
+       spin_unlock_irqrestore(&dev->img_src_exps.lock, lock_flags);
+
+       return 0;
+
+failed:
+       return retval;
+}
+
+int cif_isp10_s_isp_metadata(
+       struct cif_isp10_device *dev,
+       struct cif_isp10_isp_readout_work *readout_work,
+       struct cifisp_isp_other_cfg *new_other,
+       struct cifisp_isp_meas_cfg *new_meas,
+       struct cifisp_stat_buffer *new_stats)
+{
+       unsigned int stream_id =
+               readout_work->stream_id;
+       struct videobuf_buffer *vb =
+               readout_work->vb;
+       struct cif_isp10_stream *strm_dev = NULL;
+       struct v4l2_buffer_metadata_s *metadata;
+       struct cifisp_isp_metadata *isp_last;
+
+       switch (stream_id) {
+       case CIF_ISP10_STREAM_MP:
+               strm_dev = &dev->mp_stream;
+               break;
+       case CIF_ISP10_STREAM_SP:
+               strm_dev = &dev->sp_stream;
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unknown stream id%d\n", stream_id);
+               break;
+       }
+
+       if (vb && strm_dev->metadata.d) {
+               metadata = (struct v4l2_buffer_metadata_s *)
+                       (strm_dev->metadata.d +
+                       vb->i * CAMERA_METADATA_LEN);
+
+               metadata->frame_id = readout_work->frame_id;
+               isp_last =
+                       (struct cifisp_isp_metadata *)metadata->isp;
+
+               if (new_meas) {
+                       if ((isp_last->meas_cfg.s_frame_id == 0xffffffff) ||
+                               (isp_last->meas_cfg.s_frame_id <
+                               new_meas->s_frame_id)) {
+                               memcpy(&isp_last->meas_cfg,
+                                       new_meas,
+                                       sizeof(struct cifisp_isp_meas_cfg));
+                       }
+               }
+
+               if (new_other) {
+                       if ((isp_last->other_cfg.s_frame_id == 0xffffffff) ||
+                               (isp_last->other_cfg.s_frame_id <
+                               new_other->s_frame_id)) {
+                               memcpy(&isp_last->other_cfg,
+                                       new_other,
+                                       sizeof(struct cifisp_isp_other_cfg));
+                       }
+               }
+
+               if (new_stats) {
+                       memcpy(&isp_last->meas_stat,
+                               new_stats,
+                               sizeof(struct cifisp_stat_buffer));
+                       metadata->sensor.exp_time =
+                               new_stats->sensor_mode.exp_time;
+                       metadata->sensor.gain =
+                               new_stats->sensor_mode.gain;
+               } else {
+                       isp_last->meas_stat.meas_type = 0x00;
+               }
+       }
+
+       if (vb) {
+               cif_isp10_pltfrm_pr_dbg(NULL,
+                               "frame done\n");
+               wake_up(&vb->done);
+       }
+
+       return 0;
+}
+
+int cif_isp10_mmap(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id,
+       struct vm_area_struct *vma)
+{
+       struct cif_isp10_stream *strm_dev;
+       void *mem_vaddr;
+       int retval = 0, pages;
+       unsigned long mem_size;
+
+       switch (stream_id) {
+       case CIF_ISP10_STREAM_MP:
+               strm_dev = &dev->mp_stream;
+               break;
+       case CIF_ISP10_STREAM_SP:
+               strm_dev = &dev->sp_stream;
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unknown stream id%d\n", stream_id);
+               return -ENODEV;
+       }
+
+       mem_size = vma->vm_end - vma->vm_start;
+       if (mem_size > strm_dev->metadata.cnt * CAMERA_METADATA_LEN) {
+               retval = -ENOMEM;
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "mmap size(0x%lx) > metadata memory size(0x%lx), so failed!",
+                       mem_size,
+                       (unsigned long)(strm_dev->metadata.cnt
+                       * CAMERA_METADATA_LEN));
+               goto done;
+       }
+
+       pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
+       mem_vaddr = (struct v4l2_buffer_metadata_s *)vmalloc_user(pages);
+       if (!mem_vaddr) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "vmalloc (%d bytes) failed for %s metadata\n",
+                       pages,
+                       (stream_id == CIF_ISP10_STREAM_MP) ? "mp" : "sp");
+               retval = -ENOMEM;
+               goto done;
+       }
+
+       /* Try to remap memory */
+       retval = remap_vmalloc_range(vma, mem_vaddr, 0);
+       if (retval < 0) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "mmap: remap failed with error %d. ", retval);
+               vfree(mem_vaddr);
+               goto done;
+       }
+
+       strm_dev->metadata.d = (unsigned char *)mem_vaddr;
+
+       vma->vm_private_data = (void *)&strm_dev->metadata;
+
+done:
+       return retval;
+}
+
+int cif_isp10_get_target_frm_size(
+       struct cif_isp10_device *dev,
+       u32 *target_width,
+       u32 *target_height)
+{
+       if (dev->sp_stream.state >= CIF_ISP10_STATE_READY) {
+               if ((dev->mp_stream.state >= CIF_ISP10_STATE_READY) &&
+                       (dev->config.mi_config.mp.output.width >
+                       dev->config.mi_config.sp.output.width))
+                       *target_width =
+                               dev->config.mi_config.mp.output.width;
+               else
+                       *target_width =
+                               dev->config.mi_config.sp.output.width;
+               if ((dev->mp_stream.state >= CIF_ISP10_STATE_READY) &&
+                       (dev->config.mi_config.mp.output.height >
+                       dev->config.mi_config.sp.output.height))
+                       *target_height =
+                               dev->config.mi_config.mp.output.height;
+               else
+                       *target_height =
+                               dev->config.mi_config.sp.output.height;
+       } else if (dev->mp_stream.state >= CIF_ISP10_STATE_READY) {
+               *target_width = dev->config.mi_config.mp.output.width;
+               *target_height = dev->config.mi_config.mp.output.height;
+       } else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "cannot get target frame size, no path ready\n");
+               return -EFAULT;
+       }
+       return 0;
+}
+
+int cif_isp10_calc_isp_cropping(
+       struct cif_isp10_device *dev,
+       u32 *width,
+       u32 *height,
+       u32 *h_offs,
+       u32 *v_offs)
+{
+       int ret = 0;
+       u32 input_width;
+       u32 input_height;
+       u32 target_width;
+       u32 target_height;
+
+       if (IS_ERR_OR_NULL(dev->config.isp_config.input)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "no input selected for ISP\n");
+               ret = -EFAULT;
+               goto err;
+       }
+
+       input_width = dev->config.isp_config.input->defrect.width;
+       input_height = dev->config.isp_config.input->defrect.height;
+
+       ret = cif_isp10_get_target_frm_size(dev,
+               &target_width, &target_height);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       *width = input_width;
+       *height = input_width * target_height / target_width;
+       *v_offs = 0;
+       *h_offs = 0;
+       *height &= ~1;
+       if (*height < input_height)
+               /* vertical cropping */
+               *v_offs = (input_height - *height) >> 1;
+       else if (*height > input_height) {
+               /* horizontal cropping */
+               *height = input_height;
+               *width = input_height * target_width / target_height;
+               *width &= ~1;
+               *h_offs = (input_width - *width) >> 1;
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_calc_min_out_buff_size(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id,
+       u32 *size)
+{
+       int ret = 0;
+       enum cif_isp10_pix_fmt pix_fmt;
+       u32 llength;
+       u32 height;
+       u32 bpp;
+       struct cif_isp10_mi_path_config *mi_path;
+       struct cif_isp10_stream *stream;
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "%s\n",
+               cif_isp10_stream_id_string(stream_id));
+
+       if (stream_id == CIF_ISP10_STREAM_SP) {
+               mi_path = &dev->config.mi_config.sp;
+               stream = &dev->sp_stream;
+       } else if (stream_id == CIF_ISP10_STREAM_MP) {
+               mi_path = &dev->config.mi_config.mp;
+               stream = &dev->mp_stream;
+       } else if (stream_id == CIF_ISP10_STREAM_DMA) {
+               mi_path = &dev->config.mi_config.dma;
+               stream = &dev->dma_stream;
+       } else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "cannot calculate buffer size for this stream (%s)\n",
+                       cif_isp10_stream_id_string(stream_id));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (stream->state < CIF_ISP10_STATE_READY) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "cannot calculate buffer size, %s stream not ready\n",
+                       cif_isp10_stream_id_string(stream_id));
+               ret = -EINVAL;
+               goto err;
+       }
+       pix_fmt = mi_path->output.pix_fmt;
+       llength = mi_path->llength;
+       height = mi_path->output.height;
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "mi_path->llength: 0x%x\n",
+               mi_path->llength);
+
+       if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(pix_fmt) &&
+               CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt) > 8)
+               /* RAW input > 8BPP is stored with 16BPP by MI */
+               bpp = 16;
+       else
+               bpp = CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt);
+       *size = llength * height * bpp / 8;
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "calculated buffer size: %d\n",
+               *size);
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev->dev,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_s_ctrl(
+       struct cif_isp10_device *dev,
+       const enum cif_isp10_cid id,
+       int val)
+{
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "id %d, val %d\n",
+               id, val);
+
+       switch (id) {
+       case CIF_ISP10_CID_SUPER_IMPOSE:
+               dev->config.isp_config.si_enable = val;
+               break;
+       case CIF_ISP10_CID_IMAGE_EFFECT:
+               if ((u32)val > CIF_ISP10_IE_NONE) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "unknown/unsupported image effect %d\n", val);
+                       return -EINVAL;
+               }
+               dev->config.isp_config.ie_config.effect = val;
+               break;
+       case CIF_ISP10_CID_JPEG_QUALITY:
+               if ((u32)val > 100) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "JPEG quality (%d) must be in [1..100]\n", val);
+                       return -EINVAL;
+               }
+               dev->config.jpeg_config.ratio = val;
+               break;
+       case CIF_ISP10_CID_FLASH_MODE:
+               if ((u32)val > CIF_ISP10_FLASH_MODE_TORCH) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "unknown/unsupported flash mode (%d)\n", val);
+                       return -EINVAL;
+               }
+               dev->config.flash_mode = val;
+               cif_isp10_img_src_s_ctrl(
+                       dev->img_src,
+                       CIF_ISP10_CID_FLASH_MODE,
+                       dev->config.flash_mode);
+               if (dev->config.flash_mode == CIF_ISP10_FLASH_MODE_FLASH) {
+                       do_gettimeofday(&dev->flash_t.mainflash_start_t);
+                       dev->flash_t.mainflash_start_t.tv_usec +=
+                               dev->flash_t.flash_turn_on_time;
+                       dev->flash_t.mainflash_end_t =
+                               dev->flash_t.mainflash_start_t;
+                       dev->flash_t.mainflash_end_t.tv_sec +=
+                               dev->flash_t.flash_on_timeout;
+               } else if (dev->config.flash_mode ==
+                          CIF_ISP10_FLASH_MODE_TORCH) {
+                       do_gettimeofday(&dev->flash_t.preflash_start_t);
+                       dev->flash_t.preflash_end_t =
+                               dev->flash_t.preflash_start_t;
+                       dev->flash_t.preflash_end_t.tv_sec = 0x00;
+                       dev->flash_t.preflash_end_t.tv_usec = 0x00;
+               } else if (dev->config.flash_mode == CIF_ISP10_FLASH_MODE_OFF) {
+                       do_gettimeofday(&dev->flash_t.preflash_end_t);
+                       if (dev->flash_t.preflash_end_t.tv_sec * 1000000 +
+                           dev->flash_t.preflash_end_t.tv_usec <
+                           dev->flash_t.mainflash_end_t.tv_sec * 1000000 +
+                           dev->flash_t.mainflash_end_t.tv_usec) {
+                               dev->flash_t.mainflash_end_t =
+                                       dev->flash_t.preflash_end_t;
+                       }
+               }
+               break;
+       case CIF_ISP10_CID_WB_TEMPERATURE:
+       case CIF_ISP10_CID_ANALOG_GAIN:
+       case CIF_ISP10_CID_EXPOSURE_TIME:
+       case CIF_ISP10_CID_BLACK_LEVEL:
+       case CIF_ISP10_CID_FOCUS_ABSOLUTE:
+       case CIF_ISP10_CID_AUTO_N_PRESET_WHITE_BALANCE:
+       case CIF_ISP10_CID_SCENE_MODE:
+       case CIF_ISP10_CID_AUTO_FPS:
+       case CIF_ISP10_CID_HFLIP:
+       case CIF_ISP10_CID_VFLIP:
+               return cif_isp10_img_src_s_ctrl(dev->img_src,
+                       id, val);
+       default:
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "unknown/unsupported control %d\n", id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* end */
+
+enum {
+       isp_data_loss = 0,
+       isp_pic_size_err,
+       mipi_fifo_err,
+       dphy_err_sot,
+       dphy_err_sot_sync,
+       dphy_err_eot_sync,
+       dphy_err_ctrl,
+       csi_err_protocol,
+       csi_ecc1_err,
+       csi_ecc2_err,
+       csi_cs_err,
+};
+
+static void cif_isp10_hw_restart(struct cif_isp10_device *dev)
+{
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       cif_isp10_hw_errors[isp_pic_size_err].count = 0;
+       cif_isp10_hw_errors[isp_data_loss].count = 0;
+       cif_isp10_hw_errors[csi_err_protocol].count = 0;
+       cif_isp10_hw_errors[csi_ecc1_err].count = 0;
+       cif_isp10_hw_errors[csi_ecc2_err].count = 0;
+       cif_isp10_hw_errors[csi_cs_err].count = 0;
+       cif_iowrite32(0x00000841, dev->config.base_addr + CIF_IRCL);
+       cif_iowrite32(0x0, dev->config.base_addr + CIF_IRCL);
+
+       /* enable mipi frame end interrupt */
+       cif_iowrite32(CIF_MIPI_FRAME_END,
+                     dev->config.base_addr + CIF_MIPI_IMSC);
+       /* enable csi protocol errors interrupts */
+       cif_iowrite32OR(CIF_MIPI_ERR_CSI,
+                       dev->config.base_addr + CIF_MIPI_IMSC);
+       /* enable dphy errors interrupts */
+       cif_iowrite32OR(CIF_MIPI_ERR_DPHY,
+                       dev->config.base_addr + CIF_MIPI_IMSC);
+       /* add fifo error */
+       cif_iowrite32OR(CIF_MIPI_SYNC_FIFO_OVFLW(3),
+                       dev->config.base_addr + CIF_MIPI_IMSC);
+       /* add data overflow_error */
+       cif_iowrite32OR(CIF_MIPI_ADD_DATA_OVFLW,
+                       dev->config.base_addr + CIF_MIPI_IMSC);
+
+       cif_iowrite32(0x0,
+                     dev->config.base_addr + CIF_MI_MP_Y_OFFS_CNT_INIT);
+       cif_iowrite32(0x0,
+                     dev->config.base_addr +
+                     CIF_MI_MP_CR_OFFS_CNT_INIT);
+       cif_iowrite32(0x0,
+                     dev->config.base_addr +
+                     CIF_MI_MP_CB_OFFS_CNT_INIT);
+       cif_iowrite32(0x0,
+                     dev->config.base_addr + CIF_MI_SP_Y_OFFS_CNT_INIT);
+       cif_iowrite32(0x0,
+                     dev->config.base_addr +
+                     CIF_MI_SP_CR_OFFS_CNT_INIT);
+       cif_iowrite32(0x0,
+                     dev->config.base_addr +
+                     CIF_MI_SP_CB_OFFS_CNT_INIT);
+       cif_iowrite32OR(CIF_MI_CTRL_INIT_OFFSET_EN,
+                       dev->config.base_addr + CIF_MI_CTRL);
+
+       /* Enable ISP ! */
+       cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD |
+                       CIF_ISP_CTRL_ISP_INFORM_ENABLE |
+                       CIF_ISP_CTRL_ISP_ENABLE,
+                       dev->config.base_addr + CIF_ISP_CTRL);
+       /* enable MIPI */
+       cif_iowrite32OR(CIF_MIPI_CTRL_OUTPUT_ENA,
+                       dev->config.base_addr + CIF_MIPI_CTRL);
+}
+
+int cif_isp10_mipi_isr(unsigned int mipi_mis, void *cntxt)
+{
+       struct cif_isp10_device *dev =
+           (struct cif_isp10_device *)cntxt;
+       unsigned int mipi_ris = 0;
+
+       mipi_ris = cif_ioread32(dev->config.base_addr + CIF_MIPI_RIS);
+       mipi_mis = cif_ioread32(dev->config.base_addr + CIF_MIPI_MIS);
+
+       cif_isp10_pltfrm_rtrace_printf(dev->dev,
+               "MIPI_MIS %08x, MIPI_RIS %08x, MIPI_IMSC %08x\n",
+               mipi_mis,
+               mipi_ris,
+               cif_ioread32(dev->config.base_addr + CIF_MIPI_IMSC));
+
+       cif_iowrite32(~0,
+               dev->config.base_addr + CIF_MIPI_ICR);
+
+       if (mipi_mis & CIF_MIPI_ERR_DPHY) {
+               cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "CIF_MIPI_ERR_DPHY: 0x%x\n", mipi_mis);
+
+               /*
+                * Disable DPHY errctrl interrupt, because this dphy
+                * erctrl signal is assert and until the next changes
+                * in line state. This time is may be too long and cpu
+                * is hold in this interrupt.
+                */
+               if (mipi_mis & CIF_MIPI_ERR_CTRL(3))
+                       cif_iowrite32AND(~(CIF_MIPI_ERR_CTRL(3)),
+                               dev->config.base_addr + CIF_MIPI_IMSC);
+       }
+
+       if (mipi_mis & CIF_MIPI_ERR_CSI) {
+               cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "CIF_MIPI_ERR_CSI: 0x%x\n", mipi_mis);
+       }
+
+       if (mipi_mis & CIF_MIPI_SYNC_FIFO_OVFLW(3)) {
+               cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "CIF_MIPI_SYNC_FIFO_OVFLW: 0x%x\n", mipi_mis);
+       }
+
+       if (mipi_mis == CIF_MIPI_FRAME_END) {
+               /*
+                * Enable DPHY errctrl interrupt again, if mipi have receive
+                * the whole frame without any error.
+                */
+               cif_iowrite32OR(CIF_MIPI_ERR_CTRL(3),
+                       dev->config.base_addr + CIF_MIPI_IMSC);
+       }
+
+       mipi_mis = cif_ioread32(dev->config.base_addr + CIF_MIPI_MIS);
+
+       if (mipi_mis) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "mipi_mis icr err: 0x%x\n", mipi_mis);
+       }
+
+       return 0;
+}
+
+/* ======================================================================== */
+int cif_isp10_isp_isr(unsigned int isp_mis, void *cntxt)
+{
+       struct cif_isp10_device *dev =
+           (struct cif_isp10_device *)cntxt;
+       unsigned int isp_mis_tmp = 0;
+       unsigned int isp_err = 0;
+       struct timeval tv;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "ISP_MIS %08x, ISP_RIS %08x, ISP_IMSC %08x\n",
+               isp_mis,
+               cif_ioread32(dev->config.base_addr + CIF_ISP_RIS),
+               cif_ioread32(dev->config.base_addr + CIF_ISP_IMSC));
+
+       if (isp_mis & CIF_ISP_V_START) {
+               struct cif_isp10_isp_vs_work *vs_wk;
+               struct cif_isp10_img_src_exp *exp;
+
+               do_gettimeofday(&tv);
+               dev->b_isp_frame_in = false;
+               dev->b_mi_frame_end = false;
+               cifisp_v_start(&dev->isp_dev, &tv);
+
+               cif_iowrite32(CIF_ISP_V_START,
+                     dev->config.base_addr + CIF_ISP_ICR);
+               isp_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_ISP_MIS);
+               if (isp_mis_tmp & CIF_ISP_V_START)
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                               "isp icr v_statr err: 0x%x\n",
+                                               isp_mis_tmp);
+
+               if (!dev->config.mi_config.async_updt) {
+                       cif_iowrite32OR(CIF_ISP_CTRL_ISP_GEN_CFG_UPD,
+                               dev->config.base_addr + CIF_ISP_CTRL);
+                       cif_isp10_pltfrm_pr_dbg(NULL,
+                               "CIF_ISP_CTRL_ISP_GEN_CFG_UPD\n");
+               }
+               if (dev->sof_event)
+                       dev->sof_event(dev, dev->isp_dev.frame_id >> 1);
+               spin_lock(&dev->img_src_exps.lock);
+               if (!list_empty(&dev->img_src_exps.list)) {
+                       exp = list_first_entry(&dev->img_src_exps.list,
+                               struct cif_isp10_img_src_exp,
+                               list);
+                       list_del(&exp->list);
+               } else {
+                       exp = NULL;
+               }
+               spin_unlock(&dev->img_src_exps.lock);
+
+               if (exp) {
+                       vs_wk = kmalloc(sizeof(*vs_wk),
+                               GFP_KERNEL);
+                       if (vs_wk) {
+                               vs_wk->cmd = CIF_ISP10_VS_EXP;
+                               vs_wk->dev = dev;
+                               vs_wk->param = (void *)exp;
+                               INIT_WORK((struct work_struct *)&vs_wk->work,
+                                       cif_isp10_vs_work);
+                               if (!queue_work(dev->vs_wq,
+                                       (struct work_struct *)&vs_wk->work)) {
+                                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                       "%s: queue work failed\n", __func__);
+                                       kfree(vs_wk);
+                               }
+                       }
+               }
+       }
+
+       if (isp_mis & CIF_ISP_FRAME_IN) {
+               do_gettimeofday(&tv);
+               cif_iowrite32(CIF_ISP_FRAME_IN,
+                             dev->config.base_addr + CIF_ISP_ICR);
+               cifisp_frame_in(&dev->isp_dev, &tv);
+       }
+
+       if ((isp_mis & (CIF_ISP_DATA_LOSS | CIF_ISP_PIC_SIZE_ERROR))) {
+               dev->sp_stream.stall = true;
+               dev->mp_stream.stall = true;
+
+               if ((isp_mis & CIF_ISP_PIC_SIZE_ERROR)) {
+                       /* Clear pic_size_error */
+                       cif_iowrite32(CIF_ISP_PIC_SIZE_ERROR,
+                               dev->config.base_addr +
+                               CIF_ISP_ICR);
+                       cif_isp10_hw_errors[isp_pic_size_err].count++;
+                       isp_err =
+                           cif_ioread32(dev->config.base_addr +
+                                        CIF_ISP_ERR);
+                       dev_err(dev->dev,
+                               "CIF_ISP_PIC_SIZE_ERROR (0x%08x)",
+                               isp_err);
+                       cif_iowrite32(isp_err,
+                               dev->config.base_addr +
+                               CIF_ISP_ERR_CLR);
+               } else if ((isp_mis & CIF_ISP_DATA_LOSS)) {
+                       /* Clear data_loss */
+                       cif_iowrite32(CIF_ISP_DATA_LOSS,
+                               dev->config.base_addr +
+                               CIF_ISP_ICR);
+                       cif_isp10_hw_errors[isp_data_loss].count++;
+                       dev_err(dev->dev,
+                               "CIF_ISP_DATA_LOSS\n");
+                       cif_iowrite32(CIF_ISP_DATA_LOSS,
+                                     dev->config.base_addr +
+                                     CIF_ISP_ICR);
+               }
+
+               /* Stop ISP */
+               cif_iowrite32AND(~CIF_ISP_CTRL_ISP_INFORM_ENABLE &
+                               ~CIF_ISP_CTRL_ISP_ENABLE,
+                               dev->config.base_addr + CIF_ISP_CTRL);
+               /* isp_update */
+               cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD,
+                               dev->config.base_addr + CIF_ISP_CTRL);
+               cif_isp10_hw_restart(dev);
+       }
+
+       if (isp_mis & CIF_ISP_FRAME_IN) {
+               cif_iowrite32(CIF_ISP_FRAME_IN,
+                       dev->config.base_addr + CIF_ISP_ICR);
+               isp_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_ISP_MIS);
+               if (isp_mis_tmp & CIF_ISP_FRAME_IN)
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                               "isp icr frame_in err: 0x%x\n",
+                                               isp_mis_tmp);
+
+               /* restart MI if CIF has run out of buffers */
+               if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel) &&
+                       !CIF_ISP10_MI_IS_BUSY(dev) &&
+                       !dev->config.jpeg_config.busy &&
+                       (dev->config.mi_config.async_updt ||
+                       (!dev->sp_stream.next_buf &&
+                       !dev->mp_stream.next_buf))){
+                       u32 mi_isr = 0;
+
+                       if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)
+                               mi_isr |= CIF_MI_SP_FRAME;
+                       if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)
+                               mi_isr |= CIF_MI_MP_FRAME;
+                       cif_iowrite32(mi_isr,
+                                     dev->config.base_addr + CIF_MI_ISR);
+               }
+       }
+
+       if (isp_mis & CIF_ISP_FRAME) {
+               /* Clear Frame In (ISP) */
+               cif_iowrite32(CIF_ISP_FRAME,
+                             dev->config.base_addr + CIF_ISP_ICR);
+               isp_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_ISP_MIS);
+               if (isp_mis_tmp & CIF_ISP_FRAME)
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                                               "isp icr frame end err: 0x%x\n",
+                                               isp_mis_tmp);
+
+               if (dev->b_mi_frame_end)
+                       cif_isp10_update_ism_dcr_rsz(dev);
+               dev->b_isp_frame_in = true;
+       }
+
+       cifisp_isp_isr(&dev->isp_dev, isp_mis);
+
+       return 0;
+}
+
+/* ======================================================================== */
+
+void init_output_formats(void)
+{
+       unsigned int i = 0;
+       int ret = 0;            /* RF*/
+       int xgold_num_format = 0;       /*RF*/
+
+       xgold_num_format =
+           (sizeof(cif_isp10_output_format) / sizeof(struct cif_isp10_fmt));
+
+       for (i = 0; i < xgold_num_format; i++) {
+               struct v4l2_fmtdesc fmtdesc;
+
+               memset(&fmtdesc, 0, sizeof(fmtdesc));
+               fmtdesc.index = i;
+               fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+               strlcpy((&fmtdesc)->description,
+                       cif_isp10_output_format[(&fmtdesc)->index].name,
+                       sizeof((&fmtdesc)->description));
+               (&fmtdesc)->pixelformat =
+                   cif_isp10_output_format[(&fmtdesc)->index].fourcc;
+               (&fmtdesc)->flags =
+                   cif_isp10_output_format[(&fmtdesc)->index].flags;
+
+               if (ret < 0)
+                       break;
+
+               output_formats[i] = fmtdesc;
+       }
+}
+
+int get_cif_isp10_output_format_size(void)
+{
+       return sizeof(cif_isp10_output_format) / sizeof(struct cif_isp10_fmt);
+}
+
+struct cif_isp10_fmt *get_cif_isp10_output_format(int index)
+{
+       struct cif_isp10_fmt *fmt = NULL;
+
+       if ((index >= 0) && (index < get_cif_isp10_output_format_size()))
+               fmt = &cif_isp10_output_format[index];
+
+       return fmt;
+}
+
+struct v4l2_fmtdesc *get_cif_isp10_output_format_desc(int index)
+{
+       struct v4l2_fmtdesc *desc = NULL;
+
+       if ((index >= 0) && (index < get_cif_isp10_output_format_desc_size()))
+               desc = &output_formats[index];
+
+       return desc;
+}
+
+int get_cif_isp10_output_format_desc_size(void)
+{
+       return ARRAY_SIZE(cif_isp10_output_format);
+}
diff --git a/drivers/media/platform/rk-isp10/cif_isp10.h b/drivers/media/platform/rk-isp10/cif_isp10.h
new file mode 100644 (file)
index 0000000..c8eb6c5
--- /dev/null
@@ -0,0 +1,713 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_H
+#define _CIF_ISP10_H
+
+#include <linux/platform_device.h>
+#include "cif_isp10_pltfrm.h"
+#include "cif_isp10_img_src.h"
+#include "cif_isp10_isp.h"
+#include <linux/platform_data/rk_isp10_platform.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-controls_rockchip.h>
+/*****************************************************************************/
+/* Definitions */
+
+#define CONFIG_CIF_ISP_AUTO_UPD_CFG_BUG
+
+#define CIF_ISP10_NUM_INPUTS    10
+
+/* FORMAT */
+#define MAX_NB_FORMATS          30
+
+#define CONTRAST_DEF            0x80
+#define BRIGHTNESS_DEF          0x0
+#define HUE_DEF                 0x0
+
+/*
+ *     MIPI CSI2.0
+ */
+#define CSI2_DT_YUV420_8b       (0x18)
+#define CSI2_DT_YUV420_10b      (0x19)
+#define CSI2_DT_YUV422_8b       (0x1E)
+#define CSI2_DT_YUV422_10b      (0x1F)
+#define CSI2_DT_RGB565          (0x22)
+#define CSI2_DT_RGB666          (0x23)
+#define CSI2_DT_RGB888          (0x24)
+#define CSI2_DT_RAW8            (0x2A)
+#define CSI2_DT_RAW10           (0x2B)
+#define CSI2_DT_RAW12           (0x2C)
+
+enum cif_isp10_img_src_state {
+       CIF_ISP10_IMG_SRC_STATE_OFF       = 0,
+       CIF_ISP10_IMG_SRC_STATE_SW_STNDBY = 1,
+       CIF_ISP10_IMG_SRC_STATE_STREAMING = 2
+};
+
+enum cif_isp10_state {
+       /* path not yet opened: */
+       CIF_ISP10_STATE_DISABLED  = 0,
+       /* path opened but not yet configured: */
+       CIF_ISP10_STATE_INACTIVE  = 1,
+       /* path opened and configured, ready for streaming: */
+       CIF_ISP10_STATE_READY     = 2,
+       /* path is streaming: */
+       CIF_ISP10_STATE_STREAMING = 3
+};
+
+enum cif_isp10_pm_state {
+       CIF_ISP10_PM_STATE_OFF,
+       CIF_ISP10_PM_STATE_SUSPENDED,
+       CIF_ISP10_PM_STATE_SW_STNDBY,
+       CIF_ISP10_PM_STATE_STREAMING
+};
+
+enum cif_isp10_inp {
+       CIF_ISP10_INP_CSI     = 0x10000000,
+       CIF_ISP10_INP_CPI     = 0x20000000,
+
+       CIF_ISP10_INP_DMA     = 0x30000000, /* DMA -> ISP */
+       CIF_ISP10_INP_DMA_IE  = 0x31000000, /* DMA -> IE */
+       CIF_ISP10_INP_DMA_SP  = 0x32000000, /* DMA -> SP */
+       CIF_ISP10_INP_DMA_MAX = 0x33000000,
+
+       CIF_ISP10_INP_MAX     = 0x7fffffff
+};
+
+#define CIF_ISP10_INP_IS_DMA(inp) \
+       (((inp) & 0xf0000000) == CIF_ISP10_INP_DMA)
+#define CIF_ISP10_INP_IS_MIPI(inp) \
+       (((inp) & 0xf0000000) == CIF_ISP10_INP_CSI)
+#define CIF_ISP10_INP_IS_DVP(inp) \
+       (((inp) & 0xf0000000) == CIF_ISP10_INP_CPI)
+#define CIF_ISP10_INP_NEED_ISP(inp) \
+       ((inp) <  CIF_ISP10_INP_DMA_IE)
+#define CIF_ISP10_INP_DMA_CNT() \
+       ((CIF_ISP10_INP_DMA_MAX -\
+       CIF_ISP10_INP_DMA) >> 24)
+
+enum cif_isp10_pinctrl_state {
+       CIF_ISP10_PINCTRL_STATE_SLEEP,
+       CIF_ISP10_PINCTRL_STATE_INACTIVE,
+       CIF_ISP10_PINCTRL_STATE_DEFAULT,
+       CIF_ISP10_PINCTRL_STATE_ACTIVE
+};
+
+enum cif_isp10_flash_mode {
+       CIF_ISP10_FLASH_MODE_OFF,
+       CIF_ISP10_FLASH_MODE_FLASH,
+       CIF_ISP10_FLASH_MODE_TORCH,
+};
+
+enum cif_isp10_cid {
+       CIF_ISP10_CID_FLASH_MODE                  = 0,
+       CIF_ISP10_CID_EXPOSURE_TIME               = 1,
+       CIF_ISP10_CID_ANALOG_GAIN                 = 2,
+       CIF_ISP10_CID_WB_TEMPERATURE              = 3,
+       CIF_ISP10_CID_BLACK_LEVEL                 = 4,
+       CIF_ISP10_CID_AUTO_GAIN                   = 5,
+       CIF_ISP10_CID_AUTO_EXPOSURE               = 6,
+       CIF_ISP10_CID_AUTO_WHITE_BALANCE          = 7,
+       CIF_ISP10_CID_FOCUS_ABSOLUTE              = 8,
+       CIF_ISP10_CID_AUTO_N_PRESET_WHITE_BALANCE = 9,
+       CIF_ISP10_CID_SCENE_MODE                  = 10,
+       CIF_ISP10_CID_SUPER_IMPOSE                = 11,
+       CIF_ISP10_CID_JPEG_QUALITY                = 12,
+       CIF_ISP10_CID_IMAGE_EFFECT                = 13,
+       CIF_ISP10_CID_HFLIP                       = 14,
+       CIF_ISP10_CID_VFLIP                       = 15,
+       CIF_ISP10_CID_AUTO_FPS                    = 16,
+       CIF_ISP10_CID_VBLANKING                   = 17,
+       CIF_ISP10_CID_ISO_SENSITIVITY             = 18,
+
+};
+
+/* correspond to bit field values */
+enum cif_isp10_image_effect {
+       CIF_ISP10_IE_BW       = 0,
+       CIF_ISP10_IE_NEGATIVE = 1,
+       CIF_ISP10_IE_SEPIA    = 2,
+       CIF_ISP10_IE_C_SEL    = 3,
+       CIF_ISP10_IE_EMBOSS   = 4,
+       CIF_ISP10_IE_SKETCH   = 5,
+       CIF_ISP10_IE_NONE /* not a bit field value */
+};
+
+#define CIF_ISP10_PIX_FMT_MASK                  0xf0000000
+#define CIF_ISP10_PIX_FMT_MASK_BPP              0x0003f000
+#define CIF_ISP10_PIX_FMT_YUV_MASK_CPLANES      0x00000003
+#define CIF_ISP10_PIX_FMT_YUV_MASK_UVSWAP       0x00000004
+#define CIF_ISP10_PIX_FMT_YUV_MASK_YCSWAP       0x00000008
+#define CIF_ISP10_PIX_FMT_YUV_MASK_X            0x00000f00
+#define CIF_ISP10_PIX_FMT_YUV_MASK_Y            0x000000f0
+#define CIF_ISP10_PIX_FMT_RGB_MASK_PAT          0x000000f0
+#define CIF_ISP10_PIX_FMT_BAYER_MASK_PAT        0x000000f0
+#define CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK_BPP) >> 12)
+#define cif_isp10_pix_fmt_set_bpp(pix_fmt, bpp) \
+       { \
+               pix_fmt = (((pix_fmt) & ~CIF_ISP10_PIX_FMT_MASK_BPP) | \
+                       (((bpp) << 12) & CIF_ISP10_PIX_FMT_MASK_BPP)); \
+       }
+
+#define CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(pix_fmt) \
+       ((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_CPLANES)
+#define CIF_ISP10_PIX_FMT_YUV_IS_YC_SWAPPED(pix_fmt) \
+       ((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_YCSWAP)
+#define CIF_ISP10_PIX_FMT_YUV_IS_UV_SWAPPED(pix_fmt) \
+               ((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_UVSWAP)
+#define CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_X) >> 8)
+#define CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_Y) >> 4)
+#define cif_isp10_pix_fmt_set_y_subs(pix_fmt, y_subs) \
+       { \
+               pix_fmt = (((pix_fmt) & ~CIF_ISP10_PIX_FMT_YUV_MASK_Y) | \
+                       ((y_subs << 4) & CIF_ISP10_PIX_FMT_YUV_MASK_Y)); \
+       }
+#define cif_isp10_pix_fmt_set_x_subs(pix_fmt, x_subs) \
+       { \
+               pix_fmt = (((pix_fmt) & ~CIF_ISP10_PIX_FMT_YUV_MASK_X) | \
+                       (((x_subs) << 8) & CIF_ISP10_PIX_FMT_YUV_MASK_X)); \
+       }
+#define cif_isp10_pix_fmt_set_yc_swapped(pix_fmt, yc_swapped) \
+       { \
+               pix_fmt = (((pix_fmt) & ~CIF_ISP10_PIX_FMT_YUV_MASK_YCSWAP) | \
+                       (((yc_swapped) << 3) & \
+                       CIF_ISP10_PIX_FMT_YUV_MASK_YCSWAP)); \
+       }
+
+#define CIF_ISP10_PIX_FMT_BAYER_PAT_IS_BGGR(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_BAYER_MASK_PAT) == 0x0)
+#define CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GBRG(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_BAYER_MASK_PAT) == 0x10)
+#define CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GRBG(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_BAYER_MASK_PAT) == 0x20)
+#define CIF_ISP10_PIX_FMT_BAYER_PAT_IS_RGGB(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_BAYER_MASK_PAT) == 0x30)
+
+#define CIF_ISP10_PIX_FMT_IS_YUV(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK) == 0x10000000)
+#define CIF_ISP10_PIX_FMT_IS_RGB(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK) == 0x20000000)
+#define CIF_ISP10_PIX_FMT_IS_RAW_BAYER(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK) == 0x30000000)
+#define CIF_ISP10_PIX_FMT_IS_JPEG(pix_fmt) \
+       (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK) == 0x40000000)
+
+#define CIF_ISP10_PIX_FMT_IS_INTERLEAVED(pix_fmt) \
+       (!CIF_ISP10_PIX_FMT_IS_YUV(pix_fmt) ||\
+       !CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(pix_fmt))
+
+enum cif_isp10_pix_fmt {
+       /* YUV */
+       CIF_YUV400                      = 0x10008000,
+       CIF_YVU400                      = 0x10008004,
+
+       CIF_YUV420I                     = 0x1000c220,
+       CIF_YUV420SP                    = 0x1000c221,   /* NV12 */
+       CIF_YUV420P                     = 0x1000c222,
+       CIF_YVU420I                     = 0x1000c224,
+       CIF_YVU420SP                    = 0x1000c225,   /* NV21 */
+       CIF_YVU420P                     = 0x1000c226,   /* YV12 */
+
+       CIF_YUV422I                     = 0x10010240,
+       CIF_YUV422SP                    = 0x10010241,
+       CIF_YUV422P                     = 0x10010242,
+       CIF_YVU422I                     = 0x10010244,
+       CIF_YVU422SP                    = 0x10010245,
+       CIF_YVU422P                     = 0x10010246,
+
+       CIF_YUV444I                     = 0x10018440,
+       CIF_YUV444SP                    = 0x10018441,
+       CIF_YUV444P                     = 0x10018442,
+       CIF_YVU444I                     = 0x10018444,
+       CIF_YVU444SP                    = 0x10018445,
+       CIF_YVU444P                     = 0x10018446,
+
+       CIF_UYV400                      = 0x10008008,
+
+       CIF_UYV420I                     = 0x1000c228,
+       CIF_UYV420SP                    = 0x1000c229,
+       CIF_UYV420P                     = 0x1000c22a,
+       CIF_VYU420I                     = 0x1000c22c,
+       CIF_VYU420SP                    = 0x1000c22d,
+       CIF_VYU420P                     = 0x1000c22e,
+
+       CIF_UYV422I                     = 0x10010248,
+       CIF_UYV422SP                    = 0x10010249,
+       CIF_UYV422P                     = 0x1001024a,
+       CIF_VYU422I                     = 0x1001024c,
+       CIF_VYU422SP                    = 0x1001024d,
+       CIF_VYU422P                     = 0x1001024e,
+
+       CIF_UYV444I                     = 0x10018448,
+       CIF_UYV444SP                    = 0x10018449,
+       CIF_UYV444P                     = 0x1001844a,
+       CIF_VYU444I                     = 0x1001844c,
+       CIF_VYU444SP                    = 0x1001844d,
+       CIF_VYU444P                     = 0x1001844e,
+
+       /* RGB */
+       CIF_RGB565                      = 0x20010000,
+       CIF_RGB666                      = 0x20012000,
+       CIF_RGB888                      = 0x20018000,
+
+       /* RAW Bayer */
+       CIF_BAYER_SBGGR8                = 0x30008000,
+       CIF_BAYER_SGBRG8                = 0x30008010,
+       CIF_BAYER_SGRBG8                = 0x30008020,
+       CIF_BAYER_SRGGB8                = 0x30008030,
+
+       CIF_BAYER_SBGGR10               = 0x3000a000,
+       CIF_BAYER_SGBRG10               = 0x3000a010,
+       CIF_BAYER_SGRBG10               = 0x3000a020,
+       CIF_BAYER_SRGGB10               = 0x3000a030,
+
+       CIF_BAYER_SBGGR12               = 0x3000c000,
+       CIF_BAYER_SGBRG12               = 0x3000c010,
+       CIF_BAYER_SGRBG12               = 0x3000c020,
+       CIF_BAYER_SRGGB12               = 0x3000c030,
+
+       /* JPEG */
+       CIF_JPEG                        = 0x40008000,
+
+       /* Data */
+       CIF_DATA                        = 0x70000000,
+
+       CIF_UNKNOWN_FORMAT              = 0x80000000
+};
+
+enum cif_isp10_stream_id {
+       CIF_ISP10_STREAM_SP     = 0x1,
+       CIF_ISP10_STREAM_MP     = 0x2,
+       CIF_ISP10_STREAM_DMA    = 0x4,
+       CIF_ISP10_STREAM_ISP    = 0x8
+};
+
+#define CIF_ISP10_ALL_STREAMS \
+       (CIF_ISP10_STREAM_SP | \
+       CIF_ISP10_STREAM_MP | \
+       CIF_ISP10_STREAM_DMA)
+
+enum cif_isp10_buff_fmt {
+       /* values correspond to bitfield values */
+       CIF_ISP10_BUFF_FMT_PLANAR       = 0,
+       CIF_ISP10_BUFF_FMT_SEMIPLANAR   = 1,
+       CIF_ISP10_BUFF_FMT_INTERLEAVED  = 2,
+
+       CIF_ISP10_BUFF_FMT_RAW8         = 0,
+       CIF_ISP10_BUFF_FMT_RAW12        = 2
+};
+
+enum cif_isp10_jpeg_header {
+       CIF_ISP10_JPEG_HEADER_JFIF,
+       CIF_ISP10_JPEG_HEADER_NONE
+};
+
+struct cif_isp10_csi_config {
+       u32 vc;
+       u32 nb_lanes;
+       u32 bit_rate;
+       /* really used csi */
+       u32 used_csi; /* xuhf@rock-chips.com: v1.0.4 */
+};
+
+struct cif_isp10_paraport_config {
+       u32 cif_vsync;
+       u32 cif_hsync;
+       u32 cif_pclk;
+       /* really used csi */
+       u32 used_csi; /* xuhf@rock-chips.com: v1.0.4 */
+};
+
+struct cif_isp10_frm_intrvl {
+       u32 numerator;
+       u32 denominator;
+};
+
+struct cif_isp10_frm_fmt {
+       u32 width;
+       u32 height;
+       u32 stride;
+       u32 std_id;
+       enum cif_isp10_pix_fmt pix_fmt;
+       enum cif_isp10_pix_fmt_quantization quantization;
+       struct v4l2_rect defrect;
+};
+
+struct cif_isp10_strm_fmt {
+       struct cif_isp10_frm_fmt frm_fmt;
+       struct cif_isp10_frm_intrvl frm_intrvl;
+};
+
+struct cif_isp10_strm_fmt_desc {
+       bool discrete_frmsize;
+       struct {
+               u32 width;
+               u32 height;
+       } min_frmsize;
+       struct {
+               u32 width;
+               u32 height;
+       } max_frmsize;
+       enum cif_isp10_pix_fmt pix_fmt;
+       bool discrete_intrvl;
+       struct cif_isp10_frm_intrvl min_intrvl;
+       struct cif_isp10_frm_intrvl max_intrvl;
+       struct v4l2_rect defrect;
+       u32 std_id;
+};
+
+struct cif_isp10_rsz_config {
+       struct cif_isp10_frm_fmt *input;
+       struct cif_isp10_frm_fmt output;
+       bool ycflt_adjust;
+       bool ism_adjust;
+};
+
+struct cif_isp10_dcrop_config {
+       unsigned int h_offs;
+       unsigned int v_offs;
+       unsigned int h_size;
+       unsigned int v_size;
+};
+
+struct cif_isp10_sp_config {
+       struct cif_isp10_rsz_config rsz_config;
+       struct cif_isp10_dcrop_config dcrop;
+};
+
+struct cif_isp10_mp_config {
+       struct cif_isp10_rsz_config rsz_config;
+       struct cif_isp10_dcrop_config dcrop;
+};
+
+struct cif_isp10_mi_path_config {
+       struct cif_isp10_frm_fmt *input;
+       struct cif_isp10_frm_fmt output;
+       u32 llength;
+       u32 curr_buff_addr;
+       u32 next_buff_addr;
+       u32 cb_offs;
+       u32 cr_offs;
+       u32 y_size;
+       u32 cb_size;
+       u32 cr_size;
+       bool busy;
+};
+
+struct cif_isp10_zoom_buffer_info {
+       u32 width;
+       u32 height;
+       unsigned long  buff_addr;
+       u32 flags;
+};
+
+struct cif_isp10_mi_config {
+       bool raw_enable;
+       u32 async_updt;
+       struct cif_isp10_mi_path_config mp;
+       struct cif_isp10_mi_path_config sp;
+       struct cif_isp10_mi_path_config dma;
+};
+
+#ifdef NO_YET
+struct cif_isp10_buffer {
+       struct list_head list;
+       u32 dma_addr;
+       u32 size;
+};
+#else
+#define cif_isp10_buffer videobuf_buffer
+#endif
+
+struct cif_isp10_metadata_s {
+       unsigned int cnt;
+       unsigned int vmas;
+       unsigned char *d;
+};
+
+struct cif_isp10_stream {
+       enum cif_isp10_stream_id id;
+       enum cif_isp10_state state;
+       enum cif_isp10_state saved_state;
+       struct list_head buf_queue;
+       struct videobuf_buffer *curr_buf;
+       struct videobuf_buffer *next_buf;
+       bool updt_cfg;
+       bool stall;
+       bool stop;
+       CIF_ISP10_PLTFRM_EVENT done;
+       struct cif_isp10_metadata_s metadata;
+};
+
+struct cif_isp10_jpeg_config {
+       bool enable;
+       bool busy;
+       u32 ratio;
+       struct cif_isp10_frm_fmt *input;
+       enum cif_isp10_jpeg_header header;
+};
+
+struct cif_isp10_ie_config {
+       enum cif_isp10_image_effect effect;
+};
+
+/* IS */
+struct cif_isp10_ism_params {
+       unsigned int ctrl;
+       unsigned int recenter;
+       unsigned int h_offs;
+       unsigned int v_offs;
+       unsigned int h_size;
+       unsigned int v_size;
+       unsigned int max_dx;
+       unsigned int max_dy;
+       unsigned int displace;
+};
+
+struct cif_isp10_ism_config {
+       bool ism_en;
+       struct cif_isp10_ism_params ism_params;
+       bool ism_update_needed;
+};
+
+struct cif_isp10_isp_config {
+       bool si_enable;
+       struct cif_isp10_ie_config ie_config;
+       struct cif_isp10_ism_config ism_config;
+       struct cif_isp10_frm_fmt *input;
+       struct cif_isp10_frm_fmt output;
+};
+
+struct cif_isp10_config {
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR base_addr;
+       enum cif_isp10_flash_mode flash_mode;
+       enum cif_isp10_inp input_sel;
+       struct cif_isp10_jpeg_config jpeg_config;
+       struct cif_isp10_mi_config mi_config;
+       struct cif_isp10_sp_config sp_config;
+       struct cif_isp10_mp_config mp_config;
+       struct cif_isp10_strm_fmt img_src_output;
+       struct cif_isp10_isp_config isp_config;
+       struct pltfrm_cam_itf cam_itf;
+       bool out_of_buffer_stall;
+};
+
+struct cif_isp10_mi_state {
+       unsigned long flags;
+       unsigned int isp_ctrl;
+       unsigned int y_base_ad;
+       unsigned int y_size;
+       unsigned int cb_base_ad;
+       unsigned int cb_size;
+       unsigned int cr_base_ad;
+       unsigned int cr_size;
+};
+
+struct cif_isp10_img_src_exp {
+       struct list_head list;
+       struct cif_isp10_img_src_ext_ctrl *exp;
+};
+
+struct cif_isp10_img_src_data {
+       unsigned int v_frame_id;
+       struct isp_supplemental_sensor_mode_data data;
+};
+
+struct cif_isp10_img_src_exps {
+       spinlock_t lock;        /* protect list */
+       struct list_head list;
+
+       struct mutex mutex;     /* protect frm_exp */
+       struct cif_isp10_img_src_data data[2];
+       unsigned char exp_valid_frms;
+};
+
+enum cif_isp10_isp_vs_cmd {
+       CIF_ISP10_VS_EXP = 0,
+};
+
+struct cif_isp10_isp_vs_work {
+       struct work_struct work;
+       struct cif_isp10_device *dev;
+       enum cif_isp10_isp_vs_cmd cmd;
+       void *param;
+};
+
+struct cif_isp10_fmt {
+       char *name;
+       u32 fourcc;
+       int flags;
+       int depth;
+       unsigned char rotation;
+       unsigned char overlay;
+};
+
+struct cif_isp10_device {
+       unsigned int dev_id;
+       CIF_ISP10_PLTFRM_DEVICE dev;
+       struct v4l2_device v4l2_dev;
+       enum cif_isp10_pm_state pm_state;
+       enum cif_isp10_img_src_state img_src_state;
+
+       spinlock_t vbq_lock;    /* spinlock for videobuf queues */
+       spinlock_t vbreq_lock;  /* spinlock for videobuf requeues */
+
+       struct cif_isp10_img_src *img_src;
+       struct cif_isp10_img_src *img_src_array[CIF_ISP10_NUM_INPUTS];
+       unsigned int img_src_cnt;
+       struct cif_isp10_img_src_exps img_src_exps;
+
+       struct cif_isp10_config config;
+       struct cif_isp10_isp_dev isp_dev;
+       struct cif_isp10_stream sp_stream;
+       struct cif_isp10_stream mp_stream;
+       struct cif_isp10_stream dma_stream;
+
+       struct workqueue_struct *vs_wq;
+       void (*sof_event)(struct cif_isp10_device *dev, __u32 frame_sequence);
+       /*
+        * requeue_bufs() is used to clean and rebuild the local buffer
+        * lists xx_stream.buf_queue. This is used e.g. in the CAPTURE use
+        * case where we start MP and SP separately and needs to shortly
+        * stop and start SP when start MP
+        */
+       void (*requeue_bufs)(struct cif_isp10_device *dev,
+                               enum cif_isp10_stream_id stream_id);
+       bool   b_isp_frame_in;
+       bool   b_mi_frame_end;
+       int   otf_zsl_mode;
+       struct flash_timeinfo_s flash_t;
+
+       struct pltfrm_soc_cfg *soc_cfg;
+       void *nodes;
+
+};
+
+struct cif_isp10_fmt *get_cif_isp10_output_format(int index);
+int get_cif_isp10_output_format_size(void);
+
+struct v4l2_fmtdesc *get_cif_isp10_output_format_desc(int index);
+int get_cif_isp10_output_format_desc_size(void);
+
+/* Clean code starts from here */
+
+struct cif_isp10_device *cif_isp10_create(
+       CIF_ISP10_PLTFRM_DEVICE pdev,
+       void (*sof_event)(struct cif_isp10_device *dev, __u32 frame_sequence),
+       void (*requeue_bufs)(struct cif_isp10_device *dev,
+                               enum cif_isp10_stream_id stream_id),
+       struct pltfrm_soc_cfg *soc_cfg);
+
+void cif_isp10_destroy(
+       struct cif_isp10_device *dev);
+
+int cif_isp10_init(
+       struct cif_isp10_device *dev,
+       u32 stream_ids);
+
+int cif_isp10_release(
+       struct cif_isp10_device *dev,
+       int stream_ids);
+
+int cif_isp10_streamon(
+       struct cif_isp10_device *dev,
+       u32 stream_ids);
+
+int cif_isp10_streamoff(
+       struct cif_isp10_device *dev,
+       u32 stream_ids);
+
+int cif_isp10_s_input(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_inp inp);
+
+int cif_isp10_s_fmt(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id,
+       struct cif_isp10_strm_fmt *strm_fmt,
+       u32 stride);
+
+int cif_isp10_resume(
+       struct cif_isp10_device *dev);
+
+int cif_isp10_suspend(
+       struct cif_isp10_device *dev);
+
+int cif_isp10_qbuf(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream,
+       struct cif_isp10_buffer *buf);
+
+int cif_isp10_reqbufs(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id strm,
+       struct v4l2_requestbuffers *req);
+int cif_isp10_mmap(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id,
+       struct vm_area_struct *vma);
+
+int cif_isp10_get_target_frm_size(
+       struct cif_isp10_device *dev,
+       u32 *target_width,
+       u32 *target_height);
+
+int cif_isp10_calc_isp_cropping(
+       struct cif_isp10_device *dev,
+       u32 *width,
+       u32 *height,
+       u32 *h_offs,
+       u32 *v_offs);
+
+const char *cif_isp10_g_input_name(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_inp inp);
+
+int cif_isp10_calc_min_out_buff_size(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id,
+       u32 *size);
+
+int cif_isp10_s_ctrl(
+       struct cif_isp10_device *dev,
+       const enum cif_isp10_cid id,
+       int val);
+
+void cif_isp10_dbgfs_fill_sensor_aec_para(
+       struct cif_isp10_device *cif_isp10_dev,
+       s32 exp_time,
+       u16 gain);
+
+int cif_isp10_s_isp_metadata(
+       struct cif_isp10_device *dev,
+       struct cif_isp10_isp_readout_work *readout_work,
+       struct cifisp_isp_other_cfg *new_other,
+       struct cifisp_isp_meas_cfg *new_meas,
+       struct cifisp_stat_buffer *new_stats);
+
+int cif_isp10_s_exp(
+       struct cif_isp10_device *dev,
+       struct cif_isp10_img_src_ext_ctrl *exp_ctrl);
+
+void cif_isp10_sensor_mode_data_sync(
+       struct cif_isp10_device *dev,
+       unsigned int frame_id,
+       struct isp_supplemental_sensor_mode_data *data);
+#endif
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_img_src.c b/drivers/media/platform/rk-isp10/cif_isp10_img_src.c
new file mode 100644 (file)
index 0000000..7d8a18c
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_data/rk_isp10_platform.h>
+#include "cif_isp10.h"
+#include "cif_isp10_img_src_ops.h"
+
+struct cif_isp10_img_src {
+       void *img_src;
+       const struct cif_isp10_img_src_ops *ops;
+};
+
+struct cif_isp10_img_src *cif_isp10_img_src_to_img_src(
+       CIF_ISP10_PLTFRM_DEVICE dev,
+       struct pltfrm_soc_cfg *soc_cfg)
+{
+       int ret = 0;
+       int i;
+       const char *device_type;
+       struct cif_isp10_img_src *img_src;
+
+       img_src = devm_kzalloc(dev, sizeof(*img_src), GFP_KERNEL);
+       if (!img_src) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       device_type = cif_isp10_pltfrm_get_device_type(dev);
+
+       img_src->ops = NULL;
+       for (i = 0; i < ARRAY_SIZE(cif_isp10_img_src_ops); i++) {
+               if (!strcmp(device_type, cif_isp10_img_src_ops->device_type)) {
+                       img_src->ops = &cif_isp10_img_src_ops[i].ops;
+                       break;
+               }
+       }
+       if (!img_src->ops) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unsupported device type %s\n",
+                       device_type);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       WARN_ON(!img_src->ops->to_img_src);
+       WARN_ON(!img_src->ops->s_streaming);
+       WARN_ON(!img_src->ops->s_power);
+       WARN_ON(!img_src->ops->enum_strm_fmts);
+       WARN_ON(!img_src->ops->s_strm_fmt);
+       WARN_ON(!img_src->ops->g_ctrl);
+       WARN_ON(!img_src->ops->s_ctrl);
+
+       img_src->img_src = img_src->ops->to_img_src(dev, soc_cfg);
+       if (IS_ERR_OR_NULL(img_src->img_src)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "to_img_src failed!\n");
+               ret = -EFAULT;
+               goto err;
+       }
+
+       return img_src;
+err:
+       cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n",
+               ret);
+       if (!IS_ERR_OR_NULL(img_src))
+               devm_kfree(dev, img_src);
+
+       return ERR_PTR(ret);
+}
+
+int cif_isp10_img_src_s_streaming(
+       struct cif_isp10_img_src *img_src,
+       bool enable)
+{
+       return img_src->ops->s_streaming(img_src->img_src, enable);
+}
+
+int cif_isp10_img_src_s_power(
+       struct cif_isp10_img_src *img_src,
+       bool on)
+{
+       return img_src->ops->s_power(img_src->img_src, on);
+}
+
+int cif_isp10_img_src_enum_strm_fmts(
+       struct cif_isp10_img_src *img_src,
+       u32 index,
+       struct cif_isp10_strm_fmt_desc *strm_fmt_desc)
+{
+       return img_src->ops->enum_strm_fmts(img_src->img_src,
+               index, strm_fmt_desc);
+}
+
+int cif_isp10_img_src_s_strm_fmt(
+       struct cif_isp10_img_src *img_src,
+       struct cif_isp10_strm_fmt *strm_fmt)
+{
+       if (!img_src) {
+               cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+               return -EINVAL;
+       }
+       return img_src->ops->s_strm_fmt(img_src->img_src, strm_fmt);
+}
+
+int cif_isp10_img_src_g_ctrl(
+       struct cif_isp10_img_src *img_src,
+       int id,
+       int *val)
+{
+       if (!img_src) {
+               cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+               return -EINVAL;
+       }
+       return img_src->ops->g_ctrl(img_src->img_src, id, val);
+}
+
+int cif_isp10_img_src_s_ctrl(
+       struct cif_isp10_img_src *img_src,
+       int id,
+       int val)
+{
+       if (!img_src) {
+               cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+               return -EINVAL;
+       }
+       return img_src->ops->s_ctrl(img_src->img_src, id, val);
+}
+
+int cif_isp10_img_src_s_ext_ctrls(
+       struct cif_isp10_img_src *img_src,
+       struct cif_isp10_img_src_ext_ctrl *ctrl)
+{
+       if (!img_src) {
+               cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+               return -EINVAL;
+       }
+       return img_src->ops->s_ext_ctrls(img_src->img_src, ctrl);
+}
+
+long cif_isp10_img_src_ioctl(
+       struct cif_isp10_img_src *img_src,
+       unsigned int cmd,
+       void *arg)
+{
+       if (!img_src) {
+               cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+               return -EINVAL;
+       }
+       return img_src->ops->ioctl(img_src->img_src, cmd, arg);
+}
+
+const char *cif_isp10_img_src_g_name(
+       struct cif_isp10_img_src *img_src)
+{
+       if (!img_src) {
+               cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+               return ERR_PTR(-EINVAL);
+       }
+       return img_src->ops->g_name(img_src->img_src);
+}
+
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_img_src.h b/drivers/media/platform/rk-isp10/cif_isp10_img_src.h
new file mode 100644 (file)
index 0000000..0ef90b0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_IMG_SRC_H
+#define _CIF_ISP10_IMG_SRC_H
+
+struct cif_isp10_img_src;
+struct cif_isp10_strm_fmt_desc;
+struct cif_isp10_strm_fmt;
+struct cif_isp10_csi_config;
+enum cif_isp10_pix_fmt;
+
+struct cif_isp10_img_src;
+struct pltfrm_soc_cfg;
+
+struct cif_isp10_img_src_ctrl {
+       unsigned int id;
+       int val;
+};
+
+struct cif_isp10_img_src_ext_ctrl {
+       int cnt;
+       unsigned int class;
+       struct cif_isp10_img_src_ctrl *ctrls;
+};
+
+struct cif_isp10_img_src *cif_isp10_img_src_to_img_src(
+       CIF_ISP10_PLTFRM_DEVICE dev,
+       struct pltfrm_soc_cfg *soc_cfg);
+
+int cif_isp10_img_src_s_streaming(
+       struct cif_isp10_img_src *img_src,
+       bool enable);
+
+int cif_isp10_img_src_s_power(
+       struct cif_isp10_img_src *img_src,
+       bool on);
+
+int cif_isp10_img_src_enum_strm_fmts(
+       struct cif_isp10_img_src *img_src,
+       u32 index,
+       struct cif_isp10_strm_fmt_desc *strm_fmt_desc);
+
+int cif_isp10_img_src_s_strm_fmt(
+       struct cif_isp10_img_src *img_src,
+       struct cif_isp10_strm_fmt *strm_fmt);
+
+int cif_isp10_img_src_g_ctrl(
+       struct cif_isp10_img_src *img_src,
+       int id,
+       int *val);
+
+int cif_isp10_img_src_s_ctrl(
+       struct cif_isp10_img_src *img_src,
+       int id,
+       int val);
+
+const char *cif_isp10_img_src_g_name(
+       struct cif_isp10_img_src *img_src);
+
+int cif_isp10_img_src_s_ext_ctrls(
+       struct cif_isp10_img_src *img_src,
+       struct cif_isp10_img_src_ext_ctrl *ctrls);
+
+long cif_isp10_img_src_ioctl(
+       struct cif_isp10_img_src *img_src,
+       unsigned int cmd,
+       void *arg);
+
+#endif
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_img_src_ops.h b/drivers/media/platform/rk-isp10/cif_isp10_img_src_ops.h
new file mode 100644 (file)
index 0000000..130af3b
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_IMG_SRC_OPS_H
+#define _CIF_ISP10_IMG_SRC_OPS_H
+#include <linux/platform_data/rk_isp10_platform.h>
+#include "cif_isp10_img_src_v4l2-subdev.h"
+
+struct cif_isp10_img_src_ops {
+       void * (*to_img_src)(
+               CIF_ISP10_PLTFRM_DEVICE dev,
+               struct pltfrm_soc_cfg *soc_cfg);
+       int (*s_streaming)(
+               void *img_src,
+               bool enable);
+       int (*s_power)(
+               void *img_src,
+               bool on);
+       int (*enum_strm_fmts)(
+               void *img_src,
+               u32 index,
+               struct cif_isp10_strm_fmt_desc *strm_fmt_desc);
+       int (*s_strm_fmt)(
+               void *img_src,
+               struct cif_isp10_strm_fmt *strm_fmt);
+       int (*g_ctrl)(
+               void *img_src,
+               int id,
+               int *val);
+       const char * (*g_name)(
+               void *img_src);
+       int (*s_ctrl)(
+               void *img_src,
+               int id,
+               int val);
+       int (*s_ext_ctrls)(
+               void *img_src,
+           struct cif_isp10_img_src_ext_ctrl *ctrl);
+       long (*ioctl)(
+               void *img_src,
+               unsigned int cmd,
+               void *arg);
+};
+
+const struct {
+       const char *device_type;
+       struct cif_isp10_img_src_ops ops;
+} cif_isp10_img_src_ops[] = {
+       {
+               .device_type = CIF_ISP10_IMG_SRC_V4L2_I2C_SUBDEV,
+               .ops = {
+                       .to_img_src =
+                               cif_isp10_img_src_v4l2_i2c_subdev_to_img_src,
+                       .s_streaming =
+                               cif_isp10_img_src_v4l2_subdev_s_streaming,
+                       .s_power =
+                               cif_isp10_img_src_v4l2_subdev_s_power,
+                       .enum_strm_fmts =
+                               cif_isp10_img_src_v4l2_subdev_enum_strm_fmts,
+                       .s_strm_fmt =
+                               cif_isp10_img_src_v4l2_subdev_s_strm_fmt,
+                       .g_ctrl =
+                               cif_isp10_img_src_v4l2_subdev_g_ctrl,
+                       .g_name =
+                               cif_isp10_img_src_v4l2_subdev_g_name,
+                       .s_ctrl =
+                               cif_isp10_img_src_v4l2_subdev_s_ctrl,
+                       .s_ext_ctrls =
+                               cif_isp10_img_src_v4l2_subdev_s_ext_ctrls,
+                       .ioctl =
+                               cif_isp10_img_src_v4l2_subdev_ioctl
+               }
+       },
+};
+
+#endif
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c b/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c
new file mode 100644 (file)
index 0000000..7b9b45e
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "cif_isp10.h"
+#include <linux/platform_data/rk_isp10_platform.h>
+#include <media/v4l2-controls_rockchip.h>
+#include <linux/slab.h>
+/* ===================== */
+/* Image Source */
+/* ===================== */
+void *cif_isp10_img_src_v4l2_i2c_subdev_to_img_src(
+       struct device *dev,
+       struct pltfrm_soc_cfg *soc_cfg)
+{
+       int ret = 0;
+       struct i2c_client *client;
+       struct v4l2_subdev *subdev;
+
+       client = i2c_verify_client(dev);
+       if (IS_ERR_OR_NULL(client)) {
+               cif_isp10_pltfrm_pr_err(dev,
+                       "not an I2C device\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       subdev = i2c_get_clientdata(client);
+       if (IS_ERR_OR_NULL(subdev))
+               return subdev;
+
+       ret = v4l2_subdev_call(subdev,
+               core,
+               ioctl,
+               PLTFRM_CIFCAM_ATTACH,
+               (void *)soc_cfg);
+       if (ret != 0)
+               goto err;
+
+       return (void *)subdev;
+err:
+       cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+       return ERR_PTR(ret);
+}
+
+static enum cif_isp10_pix_fmt img_src_v4l2_subdev_pix_fmt2cif_isp10_pix_fmt(
+       int img_src_pix_fmt)
+{
+       switch (img_src_pix_fmt) {
+       case MEDIA_BUS_FMT_YUYV8_1_5X8:
+       case MEDIA_BUS_FMT_YUYV8_2X8:
+       case MEDIA_BUS_FMT_YUYV10_2X10:
+       case MEDIA_BUS_FMT_YUYV8_1X16:
+       case MEDIA_BUS_FMT_YUYV10_1X20:
+               return CIF_YUV422I;
+       case MEDIA_BUS_FMT_UYVY8_1_5X8:
+       case MEDIA_BUS_FMT_UYVY8_2X8:
+       case MEDIA_BUS_FMT_UYVY8_1X16:
+               return CIF_UYV422I;
+       case MEDIA_BUS_FMT_RGB565_2X8_BE:
+       case MEDIA_BUS_FMT_RGB565_2X8_LE:
+               return CIF_RGB565;
+       case MEDIA_BUS_FMT_RGB666_1X18:
+               return CIF_RGB666;
+       case MEDIA_BUS_FMT_RGB888_1X24:
+       case MEDIA_BUS_FMT_RGB888_2X12_BE:
+       case MEDIA_BUS_FMT_RGB888_2X12_LE:
+               return CIF_RGB888;
+       case MEDIA_BUS_FMT_SBGGR8_1X8:
+               return CIF_BAYER_SBGGR8;
+       case MEDIA_BUS_FMT_SGBRG8_1X8:
+               return CIF_BAYER_SGBRG8;
+       case MEDIA_BUS_FMT_SGRBG8_1X8:
+               return CIF_BAYER_SGRBG8;
+       case MEDIA_BUS_FMT_SRGGB8_1X8:
+               return CIF_BAYER_SRGGB8;
+       case MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8:
+       case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
+       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
+       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
+       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
+       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
+       case MEDIA_BUS_FMT_SBGGR10_1X10:
+               return CIF_BAYER_SBGGR10;
+       case MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8:
+       case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
+       case MEDIA_BUS_FMT_SGBRG10_1X10:
+               return CIF_BAYER_SGBRG10;
+       case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
+       case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
+       case MEDIA_BUS_FMT_SGRBG10_1X10:
+               return CIF_BAYER_SGRBG10;
+       case MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8:
+       case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
+       case MEDIA_BUS_FMT_SRGGB10_1X10:
+               return CIF_BAYER_SRGGB10;
+       case MEDIA_BUS_FMT_SBGGR12_1X12:
+               return CIF_BAYER_SBGGR12;
+       case MEDIA_BUS_FMT_SGBRG12_1X12:
+               return CIF_BAYER_SGBRG12;
+       case MEDIA_BUS_FMT_SGRBG12_1X12:
+               return CIF_BAYER_SGRBG12;
+       case MEDIA_BUS_FMT_SRGGB12_1X12:
+               return CIF_BAYER_SRGGB12;
+       case MEDIA_BUS_FMT_JPEG_1X8:
+               return CIF_JPEG;
+       default:
+               return CIF_UNKNOWN_FORMAT;
+       }
+}
+
+static int cif_isp10_pix_fmt2img_src_v4l2_subdev_pix_fmt(
+       enum cif_isp10_pix_fmt cif_isp10_pix_fmt)
+{
+       switch (cif_isp10_pix_fmt) {
+       case CIF_YUV422I:
+               return MEDIA_BUS_FMT_YUYV8_2X8;
+       case CIF_UYV422I:
+               return MEDIA_BUS_FMT_UYVY8_2X8;
+       case CIF_RGB565:
+               return MEDIA_BUS_FMT_RGB565_2X8_LE;
+       case CIF_RGB666:
+               return MEDIA_BUS_FMT_RGB666_1X18;
+       case CIF_RGB888:
+               return MEDIA_BUS_FMT_RGB888_1X24;
+       case CIF_BAYER_SBGGR8:
+               return MEDIA_BUS_FMT_SBGGR8_1X8;
+       case CIF_BAYER_SGBRG8:
+               return MEDIA_BUS_FMT_SGBRG8_1X8;
+       case CIF_BAYER_SGRBG8:
+               return MEDIA_BUS_FMT_SGRBG8_1X8;
+       case CIF_BAYER_SRGGB8:
+               return MEDIA_BUS_FMT_SRGGB8_1X8;
+       case CIF_BAYER_SBGGR10:
+               return MEDIA_BUS_FMT_SBGGR10_1X10;
+       case CIF_BAYER_SGBRG10:
+               return MEDIA_BUS_FMT_SGBRG10_1X10;
+       case CIF_BAYER_SGRBG10:
+               return MEDIA_BUS_FMT_SGRBG10_1X10;
+       case CIF_BAYER_SRGGB10:
+               return MEDIA_BUS_FMT_SRGGB10_1X10;
+       case CIF_BAYER_SBGGR12:
+               return MEDIA_BUS_FMT_SBGGR12_1X12;
+       case CIF_BAYER_SGBRG12:
+               return MEDIA_BUS_FMT_SGBRG12_1X12;
+       case CIF_BAYER_SGRBG12:
+               return MEDIA_BUS_FMT_SGRBG12_1X12;
+       case CIF_BAYER_SRGGB12:
+               return MEDIA_BUS_FMT_SRGGB12_1X12;
+       case CIF_JPEG:
+               return MEDIA_BUS_FMT_JPEG_1X8;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int cif_isp10_v4l2_cid2v4l2_cid(u32 cif_isp10_cid)
+{
+       switch (cif_isp10_cid) {
+       case CIF_ISP10_CID_FLASH_MODE:
+               return V4L2_CID_FLASH_LED_MODE;
+       case CIF_ISP10_CID_AUTO_GAIN:
+               return V4L2_CID_AUTOGAIN;
+       case CIF_ISP10_CID_AUTO_EXPOSURE:
+               return V4L2_EXPOSURE_AUTO;
+       case CIF_ISP10_CID_AUTO_WHITE_BALANCE:
+               return V4L2_CID_AUTO_WHITE_BALANCE;
+       case CIF_ISP10_CID_BLACK_LEVEL:
+               return V4L2_CID_BLACK_LEVEL;
+       case CIF_ISP10_CID_WB_TEMPERATURE:
+               return V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+       case CIF_ISP10_CID_EXPOSURE_TIME:
+               return V4L2_CID_EXPOSURE;
+       case CIF_ISP10_CID_ANALOG_GAIN:
+               return V4L2_CID_GAIN;
+       case CIF_ISP10_CID_FOCUS_ABSOLUTE:
+               return V4L2_CID_FOCUS_ABSOLUTE;
+       case CIF_ISP10_CID_AUTO_N_PRESET_WHITE_BALANCE:
+               return V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE;
+       case CIF_ISP10_CID_SCENE_MODE:
+               return V4L2_CID_SCENE_MODE;
+       case CIF_ISP10_CID_ISO_SENSITIVITY:
+               return V4L2_CID_ISO_SENSITIVITY;
+       case CIF_ISP10_CID_AUTO_FPS:
+               return RK_V4L2_CID_AUTO_FPS;
+       case CIF_ISP10_CID_VBLANKING:
+               return RK_V4L2_CID_VBLANKING;
+       case CIF_ISP10_CID_HFLIP:
+               return V4L2_CID_HFLIP;
+       case CIF_ISP10_CID_VFLIP:
+               return V4L2_CID_VFLIP;
+       default:
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown/unsupported CIF ISP20 ID %d\n",
+                       cif_isp10_cid);
+               break;
+       }
+       return -EINVAL;
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_streaming(
+       void *img_src,
+       bool enable)
+{
+       struct v4l2_subdev *subdev = img_src;
+
+       if (enable)
+               return v4l2_subdev_call(subdev, video, s_stream, 1);
+       else
+               return v4l2_subdev_call(subdev, video, s_stream, 0);
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_power(
+       void *img_src,
+       bool on)
+{
+       struct v4l2_subdev *subdev = img_src;
+
+       if (on)
+               return v4l2_subdev_call(subdev, core, s_power, 1);
+       else
+               return v4l2_subdev_call(subdev, core, s_power, 0);
+}
+
+int cif_isp10_img_src_v4l2_subdev_enum_strm_fmts(
+       void *img_src,
+       u32 index,
+       struct cif_isp10_strm_fmt_desc *strm_fmt_desc)
+{
+       int ret;
+       struct v4l2_subdev *subdev = img_src;
+       struct v4l2_subdev_frame_interval_enum fie = {.index = index};
+       struct pltfrm_cam_defrect defrect;
+       v4l2_std_id std;
+
+       ret = v4l2_subdev_call(subdev, video, querystd, &std);
+       if (!IS_ERR_VALUE(ret))
+               strm_fmt_desc->std_id = std;
+       else
+               strm_fmt_desc->std_id = 0;
+
+       ret = v4l2_subdev_call(subdev, pad,
+               enum_frame_interval, NULL, &fie);
+       if (!IS_ERR_VALUE(ret)) {
+               strm_fmt_desc->discrete_intrvl = true;
+               strm_fmt_desc->min_intrvl.numerator =
+                       fie.interval.numerator;
+               strm_fmt_desc->min_intrvl.denominator =
+                       fie.interval.denominator;
+               strm_fmt_desc->discrete_frmsize = true;
+               strm_fmt_desc->min_frmsize.width = fie.width;
+               strm_fmt_desc->min_frmsize.height = fie.height;
+               strm_fmt_desc->pix_fmt =
+                       img_src_v4l2_subdev_pix_fmt2cif_isp10_pix_fmt(
+                               fie.code);
+
+               defrect.width = fie.width;
+               defrect.height = fie.height;
+               memset(&defrect, 0x00, sizeof(struct v4l2_rect));
+               v4l2_subdev_call(subdev,
+                       core,
+                       ioctl,
+                       PLTFRM_CIFCAM_G_DEFRECT,
+                       (void *)&defrect);
+               if ((defrect.defrect.width == 0) ||
+                       (defrect.defrect.height == 0)) {
+                       strm_fmt_desc->defrect.left = 0;
+                       strm_fmt_desc->defrect.top = 0;
+                       strm_fmt_desc->defrect.width = fie.width;
+                       strm_fmt_desc->defrect.height = fie.height;
+               } else {
+                       strm_fmt_desc->defrect = defrect.defrect;
+               }
+       }
+
+       return ret;
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_strm_fmt(
+       void *img_src,
+       struct cif_isp10_strm_fmt *strm_fmt)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev = img_src;
+       struct v4l2_subdev_format format;
+       struct v4l2_subdev_frame_interval intrvl;
+
+       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = cif_isp10_pix_fmt2img_src_v4l2_subdev_pix_fmt(
+               strm_fmt->frm_fmt.pix_fmt);
+       format.format.width = strm_fmt->frm_fmt.width;
+       format.format.height = strm_fmt->frm_fmt.height;
+       ret = v4l2_subdev_call(subdev, pad, set_fmt, NULL, &format);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+       intrvl.interval.numerator = strm_fmt->frm_intrvl.numerator;
+       intrvl.interval.denominator = strm_fmt->frm_intrvl.denominator;
+       ret = v4l2_subdev_call(subdev, video, s_frame_interval, &intrvl);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+       return 0;
+err:
+       pr_err("img_src.%s ERR: failed with error %d\n", __func__, ret);
+       return ret;
+}
+
+int cif_isp10_img_src_v4l2_subdev_g_ctrl(
+       void *img_src,
+       int id,
+       int *val)
+{
+       struct v4l2_control ctrl;
+       int ret;
+       struct v4l2_subdev *subdev = img_src;
+
+       ctrl.id = cif_isp10_v4l2_cid2v4l2_cid(id);
+
+       if (IS_ERR_VALUE(ctrl.id))
+               return (int)ctrl.id;
+
+       ret = v4l2_subdev_call(subdev, core, g_ctrl, &ctrl);
+       if (!IS_ERR_VALUE(ret)) {
+               if (id == CIF_ISP10_CID_FLASH_MODE) {
+                       if (ctrl.value == V4L2_FLASH_LED_MODE_NONE) {
+                               ctrl.value = CIF_ISP10_FLASH_MODE_OFF;
+                       } else if (ctrl.value == V4L2_FLASH_LED_MODE_FLASH) {
+                               ctrl.value = CIF_ISP10_FLASH_MODE_FLASH;
+                       } else if (ctrl.value == V4L2_FLASH_LED_MODE_TORCH) {
+                               ctrl.value = CIF_ISP10_FLASH_MODE_TORCH;
+                       } else {
+                               cif_isp10_pltfrm_pr_err(NULL,
+                                       "unknown/unsupported value %d for control ID 0x%x\n",
+                                       ctrl.value, id);
+                               return -EINVAL;
+                       }
+               }
+               *val = ctrl.value;
+       }
+       return ret;
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_ctrl(
+       void *img_src,
+       int id,
+       int val)
+{
+       struct v4l2_control ctrl;
+       struct v4l2_subdev *subdev = img_src;
+
+       ctrl.value = val;
+       ctrl.id = cif_isp10_v4l2_cid2v4l2_cid(id);
+
+       if (IS_ERR_VALUE(ctrl.id)) {
+               return (int)ctrl.id;
+       } else if (id == CIF_ISP10_CID_FLASH_MODE) {
+               if (val == CIF_ISP10_FLASH_MODE_OFF) {
+                       ctrl.value = V4L2_FLASH_LED_MODE_NONE;
+               } else if (val == CIF_ISP10_FLASH_MODE_FLASH) {
+                       ctrl.value = V4L2_FLASH_LED_MODE_FLASH;
+               } else if (val == CIF_ISP10_FLASH_MODE_TORCH) {
+                       ctrl.value = V4L2_FLASH_LED_MODE_TORCH;
+               } else {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "unknown/unsupported value %d for control ID %d\n",
+                               val, id);
+                       return -EINVAL;
+               }
+       }
+       return v4l2_subdev_call(subdev, core, s_ctrl, &ctrl);
+}
+
+const char *cif_isp10_img_src_v4l2_subdev_g_name(
+       void *img_src)
+{
+       struct v4l2_subdev *subdev = img_src;
+
+       return dev_driver_string(subdev->dev);
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_ext_ctrls(
+       void *img_src,
+       struct cif_isp10_img_src_ext_ctrl *ctrl)
+{
+       struct v4l2_ext_controls ctrls;
+       struct v4l2_ext_control *controls;
+       int i;
+       int ret;
+       struct v4l2_subdev *subdev = img_src;
+
+       if (ctrl->cnt == 0)
+               return -EINVAL;
+
+       controls = kmalloc_array(ctrl->cnt, sizeof(struct v4l2_ext_control),
+               GFP_KERNEL);
+
+       if (!controls)
+               return -ENOMEM;
+
+       for (i = 0; i < ctrl->cnt; i++) {
+               controls[i].id = ctrl->ctrls[i].id;
+               controls[i].value = ctrl->ctrls[i].val;
+       }
+
+       ctrls.count = ctrl->cnt;
+       ctrls.controls = controls;
+       /*
+        * current kernel version don't define
+        * this member for struct v4l2_ext_control.
+        */
+       /* ctrls.ctrl_class = ctrl->class; */
+       ctrls.reserved[0] = 0;
+       ctrls.reserved[1] = 0;
+
+       ret = v4l2_subdev_call(subdev,
+               core, s_ext_ctrls, &ctrls);
+
+       kfree(controls);
+
+       return ret;
+}
+
+long cif_isp10_img_src_v4l2_subdev_ioctl(
+       void *img_src,
+       unsigned int cmd,
+       void *arg)
+{
+       struct v4l2_subdev *subdev = img_src;
+       long ret = -EINVAL;
+
+       switch (cmd) {
+       case RK_VIDIOC_SENSOR_MODE_DATA:
+       case RK_VIDIOC_CAMERA_MODULEINFO:
+
+       case PLTFRM_CIFCAM_G_ITF_CFG:
+       case PLTFRM_CIFCAM_G_DEFRECT:
+       case PLTFRM_CIFCAM_ATTACH:
+               ret = v4l2_subdev_call(subdev,
+                       core,
+                       ioctl,
+                       cmd,
+                       arg);
+
+               break;
+       default:
+               break;
+       }
+
+       if (IS_ERR_VALUE(ret))
+               pr_err("img_src.%s subdev call(cmd: 0x%x) failed with error %ld\n",
+               __func__, cmd, ret);
+
+       return ret;
+}
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.h b/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.h
new file mode 100644 (file)
index 0000000..a5ba17e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_IMG_SRC_V4L2_SUBDEV_H
+#define _CIF_ISP10_IMG_SRC_V4L2_SUBDEV_H
+
+#define CIF_ISP10_IMG_SRC_V4L2_I2C_SUBDEV  "v4l2-i2c-subdev"
+
+void *cif_isp10_img_src_v4l2_i2c_subdev_to_img_src(
+       struct device *dev,
+       struct pltfrm_soc_cfg *soc_cfg);
+
+int cif_isp10_img_src_v4l2_subdev_s_streaming(
+       void *img_src,
+       bool enable);
+
+int cif_isp10_img_src_v4l2_subdev_s_power(
+       void *img_src,
+       bool on);
+
+int cif_isp10_img_src_v4l2_subdev_enum_strm_fmts(
+       void *img_src,
+       u32 index,
+       struct cif_isp10_strm_fmt_desc *strm_fmt_desc);
+
+int cif_isp10_img_src_v4l2_subdev_s_strm_fmt(
+       void *img_src,
+       struct cif_isp10_strm_fmt *strm_fmt);
+
+int cif_isp10_img_src_v4l2_subdev_g_ctrl(
+       void *img_src,
+       int id,
+       int *val);
+
+int cif_isp10_img_src_v4l2_subdev_s_ctrl(
+       void *img_src,
+       int id,
+       int val);
+
+const char *cif_isp10_img_src_v4l2_subdev_g_name(
+       void *img_src);
+
+int cif_isp10_img_src_v4l2_subdev_s_ext_ctrls(
+       void *img_src,
+       struct cif_isp10_img_src_ext_ctrl *ctrl);
+
+long cif_isp10_img_src_v4l2_subdev_ioctl(
+       void *img_src,
+       unsigned int cmd,
+       void *arg);
+
+#endif
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_isp.c b/drivers/media/platform/rk-isp10/cif_isp10_isp.c
new file mode 100644 (file)
index 0000000..a01f591
--- /dev/null
@@ -0,0 +1,5190 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/videodev2.h>
+#include <media/videobuf-core.h>
+#include <media/videobuf-vmalloc.h>    /* for ISP statistics */
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include "cif_isp10_regs.h"
+#include "cif_isp10_isp.h"
+#include "cif_isp10_pltfrm.h"
+#include "cif_isp10.h"
+
+#define _GET_ 0
+#define _SET_ 1
+#define CIFISP_MODULE_EN(v, m)             ((v) |= (m))
+#define CIFISP_MODULE_DIS(v, m)            ((v) &= ~(m))
+#define CIFISP_MODULE_IS_EN(v, m)          (((v) & (m)) == (m))
+#define CIFISP_MODULE_UPDATE(v, m)         ((v) |= (m))
+#define CIFISP_MODULE_CLR_UPDATE(v, m)     ((v) &= ~(m))
+#define CIFISP_MODULE_IS_UPDATE(v, m)      (((v) & (m)) == (m))
+
+/* Demosaic */
+#define CIFISP_BDM_BYPASS_EN(val)          ((val) << 10)
+/* HIST */
+#define CIFISP_HIST_PREDIV_SET(val)        ((val) << 3)
+#define CIFISP_HIST_WEIGHT_SET(v0, v1, v2, v3) ((v0) | ((v1) << 8)  |\
+                                               ((v2) << 16) | ((v3) << 24))
+#define CIFISP_HIST_WINDOW_OFFSET_RESERVED (0xFFFFF000)
+#define CIFISP_HIST_WINDOW_SIZE_RESERVED   (0xFFFFF800)
+#define CIFISP_HIST_WEIGHT_RESERVED        (0xE0E0E0E0)
+#define CIFISP_MAX_HIST_PREDIVIDER         (0x0000007F)
+#define CIFISP_HIST_ROW_NUM                (5)
+#define CIFISP_HIST_COLUMN_NUM             (5)
+/* ISP Ctrl */
+#define CIF_ISP_CTRL_ISP_GAMMA_IN_ENA       BIT(6)
+#define CIF_ISP_CTRL_ISP_AWB_ENA            BIT(7)
+#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA      BIT(11)
+/* AWB */
+#define CIFISP_AWB_GAIN_R_SET(val)   ((val) << 16)
+#define CIFISP_AWB_GAIN_R_READ(val)  ((val) >> 16)
+#define CIFISP_AWB_GAIN_B_READ(val)  ((val) & 0xFFFF)
+
+#define CIFISP_AWB_YMAX_CMP_EN       BIT(2)
+#define CIFISP_AWB_REF_CR_SET(val)   ((val) << 8)
+#define CIFISP_AWB_REF_CR_READ(val)  ((val) >> 8)
+#define CIFISP_AWB_REF_CB_READ(val)  ((val) & 0xFF)
+#define CIFISP_AWB_MAX_CS_SET(val)   ((val) << 8)
+#define CIFISP_AWB_MAX_CS_READ(val)  (((val) >> 8) & 0xFF)
+#define CIFISP_AWB_MIN_C_READ(val)   ((val) & 0xFF)
+#define CIFISP_AWB_MIN_Y_SET(val)    ((val) << 16)
+#define CIFISP_AWB_MIN_Y_READ(val)   (((val) >> 16) & 0xFF)
+#define CIFISP_AWB_MAX_Y_SET(val)    ((val) << 24)
+#define CIFISP_AWB_MAX_Y_READ(val)   ((val) >> 24)
+#define CIFISP_AWB_MODE_RGB_EN       ((1 << 31) | (0x02 << 0))
+#define CIFISP_AWB_MODE_YCBCR_EN     ((0 << 31) | (0x02 << 0))
+#define CIFISP_AWB_MODE_READ(val)    ((val) & 3)
+#define CIFISP_AWB_YMAX_READ(val)    (((val) >> 2) & 1)
+
+#define CIFISP_AWB_GET_MEAN_CR(val)   ((val) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_CB(val)   (((val) >> 8) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_Y(val)    (((val) >> 16) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_R(val)    ((val) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_B(val)    (((val) >> 8) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_G(val)    (((val) >> 16) & 0xFF)
+#define CIFISP_AWB_GET_PIXEL_CNT(val) ((val) & 0x3FFFFFF)
+
+#define CIFISP_AWB_GAINS_MAX_VAL           (0x000003FF)
+#define CIFISP_AWB_WINDOW_OFFSET_MAX       (0x00000FFF)
+#define CIFISP_AWB_WINDOW_MAX_SIZE         (0x00001FFF)
+#define CIFISP_AWB_CBCR_MAX_REF            (0x000000FF)
+#define CIFISP_AWB_THRES_MAX_YC            (0x000000FF)
+/* AE */
+#define CIFISP_EXP_ENA                    (1)
+#define CIFISP_EXP_DIS                    (0)
+#define CIFISP_EXP_ROW_NUM                 (5)
+#define CIFISP_EXP_COLUMN_NUM              (5)
+#define CIFISP_EXP_NUM_LUMA_REGS           (CIFISP_EXP_ROW_NUM *\
+               CIFISP_EXP_COLUMN_NUM)
+#define CIFISP_EXP_MAX_HOFFS               (2424)
+#define CIFISP_EXP_MAX_VOFFS               (1806)
+#define CIFISP_EXP_BLOCK_MAX_HSIZE         (516)
+#define CIFISP_EXP_BLOCK_MIN_HSIZE         (35)
+#define CIFISP_EXP_BLOCK_MAX_VSIZE         (390)
+#define CIFISP_EXP_BLOCK_MIN_VSIZE         (28)
+#define CIFISP_EXP_MAX_HSIZE   \
+       (CIFISP_EXP_BLOCK_MAX_HSIZE * CIFISP_EXP_COLUMN_NUM + 1)
+#define CIFISP_EXP_MIN_HSIZE   \
+       (CIFISP_EXP_BLOCK_MIN_HSIZE * CIFISP_EXP_COLUMN_NUM + 1)
+#define CIFISP_EXP_MAX_VSIZE   \
+       (CIFISP_EXP_BLOCK_MAX_VSIZE * CIFISP_EXP_ROW_NUM + 1)
+#define CIFISP_EXP_MIN_VSIZE   \
+       (CIFISP_EXP_BLOCK_MIN_VSIZE * CIFISP_EXP_ROW_NUM + 1)
+#define CIFISP_EXP_HEIGHT_MASK             (0x000007FF)
+#define CIFISP_EXP_MAX_HOFFSET             (0x00000FFF)
+#define CIFISP_EXP_MAX_VOFFSET             (0x00000FFF)
+
+#define CIFISP_EXP_CTRL_AUTOSTOP(val)      ((val) << 1)
+#define CIFISP_EXP_CTRL_MEASMODE(val)      ((val) << 31)
+#define CIFISP_EXP_HSIZE(val)              ((val) & 0x7FF)
+#define CIFISP_EXP_VSIZE(val)              ((val) & 0x7FE)
+/* LSC */
+#define CIFISP_LSC_GRADH_SET(val)          ((val) << 11)
+#define CIFISP_LSC_SECTH_SET(val)          ((val) << 10)
+
+/* FLT */
+#define CIFISP_FLT_MODE_MAX               (1)
+#define CIFISP_FLT_CHROMA_MODE_MAX        (3)
+#define CIFISP_FLT_GREEN_STAGE1_MAX       (8)
+#define CIFISP_FLT_MODE(v)                ((v) << 1)
+#define CIFISP_FLT_CHROMA_V_MODE(v)       ((v) << 4)
+#define CIFISP_FLT_CHROMA_H_MODE(v)       ((v) << 6)
+#define CIFISP_FLT_GREEN_STAGE1(v)        ((v) << 8)
+#define CIFISP_FLT_THREAD_RESERVED        (0xfffffc00)
+#define CIFISP_FLT_FAC_RESERVED               (0xffffffc0)
+#define CIFISP_FLT_LUM_WEIGHT_RESERVED (0xfff80000)
+#define CIFISP_FLT_ENA                (1)
+#define CIFISP_FLT_DIS                 (0)
+
+#define CIFISP_CTK_COEFF_RESERVED      0xFFFFF800
+#define CIFISP_XTALK_OFFSET_RESERVED   0xFFFFF000
+
+/* GOC */
+#define CIFISP_GOC_MODE_MAX            (1)
+#define CIFISP_GOC_RESERVED            0xFFFFF800
+#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA_READ(value) (((value) >> 11) & 1)
+/* DPCC */
+#define CIFISP_DPCC_ENA                BIT(0)
+#define CIFISP_DPCC_DIS                (0 << 0)
+#define CIFISP_DPCC_MODE_MAX           (0x07)
+#define CIFISP_DPCC_OUTPUTMODE_MAX     (0x0f)
+#define CIFISP_DPCC_SETUSE_MAX         (0x0f)
+#define CIFISP_DPCC_METHODS_SET_RESERVED    (0xFFFFE000)
+#define CIFISP_DPCC_LINE_THRESH_RESERVED    (0xFFFF0000)
+#define CIFISP_DPCC_LINE_MAD_FAC_RESERVED   (0xFFFFC0C0)
+#define CIFISP_DPCC_PG_FAC_RESERVED         (0xFFFFC0C0)
+#define CIFISP_DPCC_RND_THRESH_RESERVED     (0xFFFF0000)
+#define CIFISP_DPCC_RG_FAC_RESERVED         (0xFFFFC0C0)
+#define CIFISP_DPCC_RO_LIMIT_RESERVED       (0xFFFFF000)
+#define CIFISP_DPCC_RND_OFFS_RESERVED       (0xFFFFF000)
+/* BLS */
+#define CIFISP_BLS_ENA           BIT(0)
+#define CIFISP_BLS_DIS           (0 << 0)
+#define CIFISP_BLS_MODE_MEASURED BIT(1)
+#define CIFISP_BLS_MODE_FIXED    (0 << 1)
+#define CIFISP_BLS_WINDOW_1      BIT(2)
+#define CIFISP_BLS_WINDOW_2      BIT(3)
+/* 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
+/*CPROC*/
+#define CIFISP_CPROC_CTRL_RESERVED         0xFFFFFFFE
+#define CIFISP_CPROC_CONTRAST_RESERVED     0xFFFFFF00
+#define CIFISP_CPROC_BRIGHTNESS_RESERVED   0xFFFFFF00
+#define CIFISP_CPROC_HUE_RESERVED          0xFFFFFF00
+#define CIFISP_CPROC_SATURATION_RESERVED   0xFFFFFF00
+#define CIFISP_CPROC_MACC_RESERVED         0xE000E000
+#define CIFISP_CPROC_TONE_RESERVED         0xF000
+#define CIFISP_CPROC_TONE_Y(value)         ((value) << 16)
+#define CIFISP_CPROC_TONE_C(value)         ((value))
+#define CIFISP_CPROC_TONE_Y_READ(value)    ((value) >> 16)
+#define CIFISP_CPROC_TONE_C_READ(value)    ((value) & 0xFFFF)
+#define CIFISP_CPROC_EN                    1
+#define CIFISP_CPROC_MACC_EN               BIT(4)
+#define CIFISP_CPROC_TMAP_EN               BIT(5)
+/* LSC */
+#define CIFISP_LSC_SECT_SIZE_RESERVED      0xFC00FC00
+#define CIFISP_LSC_GRAD_RESERVED           0xF000F000
+#define CIFISP_LSC_SAMPLE_RESERVED         0xF000F000
+#define CIFISP_LSC_SECTORS_MAX             16
+#define CIFISP_LSC_TABLE_DATA(v0, v1)     (v0 | ((v1) << 12))
+#define CIFISP_LSC_SECT_SIZE(v0, v1)      (v0 | ((v1) << 16))
+#define CIFISP_LSC_GRAD_SIZE(v0, v1)      (v0 | ((v1) << 16))
+/* AFC */
+#define CIFISP_AFC_THRES_RESERVED     0xFFFF0000
+#define CIFISP_AFC_VAR_SHIFT_RESERVED 0xFFF8FFF8
+#define CIFISP_AFC_WINDOW_X_RESERVED  0xE000
+#define CIFISP_AFC_WINDOW_Y_RESERVED  0xF000
+#define CIFISP_AFC_WINDOW_X_MIN       0x5
+#define CIFISP_AFC_WINDOW_Y_MIN       0x2
+#define CIFISP_AFC_WINDOW_X(value)    ((value) << 16)
+#define CIFISP_AFC_WINDOW_Y(value)    (value)
+#define CIFISP_AFC_ENA                (1)
+#define CIFISP_AFC_DIS                (0)
+
+/* DPF */
+#define CIFISP_DPF_NF_GAIN_RESERVED     0xFFFFF000
+#define CIFISP_DPF_SPATIAL_COEFF_MAX    0x1f
+#define CIFISP_DPF_NLL_COEFF_N_MAX      0x3ff
+
+#define CIFISP_DPF_MODE_USE_NF_GAIN     BIT(9)
+#define CIFISP_DPF_MODE_LSC_GAIN_COMP   BIT(8)
+#define CIFISP_DPF_MODE_AWB_GAIN_COMP   BIT(7)
+#define CIFISP_DPF_MODE_NLL_SEGMENTATION(a)   ((a) << 6)
+#define CIFISP_DPF_MODE_RB_FLTSIZE(a)         ((a) << 5)
+#define CIFISP_DPF_MODE_R_FLT_DIS             BIT(4)
+#define CIFISP_DPF_MODE_R_FLT_EN              (0 << 4)
+#define CIFISP_DPF_MODE_GR_FLT_DIS            BIT(3)
+#define CIFISP_DPF_MODE_GR_FLT_EN             (0 << 3)
+#define CIFISP_DPF_MODE_GB_FLT_DIS            BIT(2)
+#define CIFISP_DPF_MODE_GB_FLT_EN             (0 << 2)
+#define CIFISP_DPF_MODE_B_FLT_DIS             BIT(1)
+#define CIFISP_DPF_MODE_B_FLT_EN              (0 << 1)
+#define CIFISP_DPF_MODE_EN                    BIT(0)
+
+#define CIFISP_DEBUG                        BIT(0)
+#define CIFISP_ERROR                        BIT(1)
+
+/*
+ * Empirical rough (relative) times it takes to perform
+ * given function.
+ */
+#define CIFISP_MODULE_DPCC_PROC_TIME     3
+#define CIFISP_MODULE_BLS_PROC_TIME      10
+#define CIFISP_MODULE_LSC_PROC_TIME      1747
+#define CIFISP_MODULE_FLT_PROC_TIME      15
+#define CIFISP_MODULE_BDM_PROC_TIME      1
+#define CIFISP_MODULE_SDG_PROC_TIME      53
+#define CIFISP_MODULE_GOC_PROC_TIME      1000
+#define CIFISP_MODULE_CTK_PROC_TIME      772
+#define CIFISP_MODULE_AWB_PROC_TIME      8
+#define CIFISP_MODULE_HST_PROC_TIME      5
+#define CIFISP_MODULE_AEC_PROC_TIME      5
+#define CIFISP_MODULE_AWB_GAIN_PROC_TIME 2
+#define CIFISP_MODULE_CPROC_PROC_TIME    5
+#define CIFISP_MODULE_AFC_PROC_TIME      8
+#define CIFISP_MODULE_IE_PROC_TIME       5
+#define CIFISP_MODULE_DPF_TIME           5
+#define CIFISP_MODULE_DPF_STRENGTH_TIME  2
+#define CIFISP_MODULE_CSM_PROC_TIME      8
+
+/* For Debugging only!!! */
+
+#define CIFISP_MODULE_DEFAULT_VBLANKING_TIME 2000
+
+#define V4L2_DEV_DEBUG_LEVEL 0
+
+#define CIFISP_DPRINT(level, fmt, arg...) \
+       do { \
+               if (level == CIFISP_ERROR) \
+                       pr_err(fmt, ##arg); \
+               else \
+                       pr_debug(fmt, ##arg); \
+       } while (0)
+
+#define cifisp_iowrite32(d, a) \
+       cif_isp10_pltfrm_write_reg(NULL, (u32)(d), isp_dev->base_addr + (a))
+#define cifisp_ioread32(a) \
+       cif_isp10_pltfrm_read_reg(NULL, isp_dev->base_addr + (a))
+#define cifisp_iowrite32OR(d, a) \
+       cif_isp10_pltfrm_write_reg_OR(NULL, (u32)(d), isp_dev->base_addr + (a))
+#define cifisp_iowrite32AND(d, a) \
+       cif_isp10_pltfrm_write_reg_AND(NULL, (u32)(d), isp_dev->base_addr + (a))
+
+/*
+ * Set this flag to enable CIF ISP Register debug
+ * #define CIFISP_DEBUG_REG
+ */
+/*
+ * Set this flag to dump the parameters
+ * #define CIFISP_DEBUG_PARAM
+ */
+/*
+ * Set this flag to trace the capture params
+ * #define LOG_CAPTURE_PARAMS
+ */
+/*
+ * Set this flag to trace the isr execution time
+ * #define LOG_ISR_EXE_TIME
+ */
+/*
+ * Set this flag to exclude everything except
+ * measurements
+ * #define CIFISP_DEBUG_DISABLE_BLOCKS
+ */
+
+#ifdef LOG_CAPTURE_PARAMS
+static struct cifisp_last_capture_config g_last_capture_config;
+#endif
+
+#ifdef LOG_ISR_EXE_TIME
+static unsigned int g_longest_isr_time;
+#endif
+
+/* Functions for Debugging */
+static void cifisp_param_dump(const void *config, unsigned int module);
+#ifdef CIFISP_DEBUG_REG
+static void cifisp_reg_dump(const struct cif_isp10_isp_dev *isp_dev,
+                           unsigned int module, int level);
+#endif
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_reg_dump_capture(const struct cif_isp10_isp_dev *isp_dev);
+#endif
+
+static int cifisp_module_enable(struct cif_isp10_isp_dev *isp_dev,
+       bool flag, __s32 *value, unsigned int module)
+{
+       unsigned int *curr_ens, *updates, *new_ens;
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (module & (CIFISP_MODULE_AWB |
+               CIFISP_MODULE_AEC |
+               CIFISP_MODULE_AFC |
+               CIFISP_MODULE_HST)) {
+               curr_ens = &isp_dev->meas_cfgs.curr->module_ens;
+               new_ens = &isp_dev->meas_cfgs.last_or_new->module_ens;
+               updates = &isp_dev->meas_cfgs.module_updates;
+       } else {
+               curr_ens = &isp_dev->other_cfgs.curr->module_ens;
+               new_ens = &isp_dev->other_cfgs.last_or_new->module_ens;
+               updates = &isp_dev->other_cfgs.module_updates;
+       }
+
+       if (flag == _GET_) {
+               *value = CIFISP_MODULE_IS_EN(*curr_ens, module);
+               goto end;
+       }
+
+       if (CIFISP_MODULE_IS_EN(*curr_ens, module) != *value) {
+               if (*value)
+                       CIFISP_MODULE_EN(*new_ens, module);
+               else
+                       CIFISP_MODULE_DIS(*new_ens, module);
+
+               CIFISP_MODULE_UPDATE(*updates, module);
+       }
+
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP BP interface function */
+static int cifisp_dpcc_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_dpcc_config *arg)
+{
+       unsigned long lock_flags = 0;
+       unsigned int i;
+       struct cifisp_dpcc_methods_config *method;
+       int retval = 0;
+
+       if (!arg) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "arg is NULL: %s\n", __func__);
+
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->dpcc_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_DPCC);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->dpcc_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->mode > CIFISP_DPCC_MODE_MAX ||
+               arg->output_mode > CIFISP_DPCC_OUTPUTMODE_MAX ||
+               arg->set_use > CIFISP_DPCC_SETUSE_MAX ||
+               arg->ro_limits & CIFISP_DPCC_RO_LIMIT_RESERVED ||
+               arg->rnd_offs & CIFISP_DPCC_RND_OFFS_RESERVED) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       method = &arg->methods[i];
+       for (i = 0; i < CIFISP_DPCC_METHODS_MAX; i++) {
+               if ((method->method &
+                       CIFISP_DPCC_METHODS_SET_RESERVED) ||
+                       (method->line_thresh &
+                       CIFISP_DPCC_LINE_THRESH_RESERVED) ||
+                       (method->line_mad_fac &
+                       CIFISP_DPCC_LINE_MAD_FAC_RESERVED) ||
+                       (method->pg_fac &
+                       CIFISP_DPCC_PG_FAC_RESERVED) ||
+                       (method->rnd_thresh &
+                       CIFISP_DPCC_RND_THRESH_RESERVED) ||
+                       (method->rg_fac & CIFISP_DPCC_RG_FAC_RESERVED)) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+               method++;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->dpcc_config,
+               arg,
+               sizeof(struct cifisp_dpcc_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_DPCC);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP black level subtraction interface function */
+static int cifisp_bls_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_bls_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->bls_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_BLS);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->bls_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->bls_window1.h_offs > CIFISP_BLS_START_H_MAX ||
+           arg->bls_window1.h_size > CIFISP_BLS_STOP_H_MAX ||
+           arg->bls_window1.v_offs > CIFISP_BLS_START_V_MAX ||
+           arg->bls_window1.v_size > CIFISP_BLS_STOP_V_MAX ||
+           arg->bls_window2.h_offs > CIFISP_BLS_START_H_MAX ||
+           arg->bls_window2.h_size > CIFISP_BLS_STOP_H_MAX ||
+           arg->bls_window2.v_offs > CIFISP_BLS_START_V_MAX ||
+           arg->bls_window2.v_size > CIFISP_BLS_STOP_V_MAX ||
+           arg->bls_samples > CIFISP_BLS_SAMPLES_MAX ||
+           arg->fixed_val.r > CIFISP_BLS_FIX_SUB_MAX ||
+           arg->fixed_val.gr > CIFISP_BLS_FIX_SUB_MAX ||
+           arg->fixed_val.gb > CIFISP_BLS_FIX_SUB_MAX ||
+           arg->fixed_val.b > CIFISP_BLS_FIX_SUB_MAX ||
+           arg->fixed_val.r < (s16)CIFISP_BLS_FIX_SUB_MIN ||
+           arg->fixed_val.gr < (s16)CIFISP_BLS_FIX_SUB_MIN ||
+           arg->fixed_val.gb < (s16)CIFISP_BLS_FIX_SUB_MIN ||
+           arg->fixed_val.b < (s16)CIFISP_BLS_FIX_SUB_MIN) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->bls_config,
+               arg,
+               sizeof(struct cifisp_bls_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_BLS);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP LS correction interface function */
+static int cifisp_lsc_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_lsc_config *arg)
+{
+       int i;
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->lsc_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_LSC);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->lsc_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       for (i = 0; i < CIFISP_LSC_SIZE_TBL_SIZE; i++) {
+               if ((*(arg->x_size_tbl + i) & CIFISP_LSC_SECT_SIZE_RESERVED) ||
+                   (*(arg->y_size_tbl + i) & CIFISP_LSC_SECT_SIZE_RESERVED)) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                                     "incompatible sect size x 0x%x y 0x%x in function: %s\n",
+                                     *(arg->x_size_tbl + i),
+                                     *(arg->y_size_tbl + i), __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+       }
+
+       for (i = 0; i < CIFISP_LSC_GRAD_TBL_SIZE; i++) {
+               if ((*(arg->x_grad_tbl + i) & CIFISP_LSC_GRAD_RESERVED) ||
+                   (*(arg->y_grad_tbl + i) & CIFISP_LSC_GRAD_RESERVED)) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                                     "incompatible grad x 0x%x y 0x%xin function: %s\n",
+                                     *(arg->x_grad_tbl + i),
+                                     *(arg->y_grad_tbl + i), __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+       }
+
+       for (i = 0; i < CIFISP_LSC_DATA_TBL_SIZE; i++) {
+               if ((*(arg->r_data_tbl + i) &
+                       CIFISP_LSC_SAMPLE_RESERVED) ||
+                       (*(arg->gr_data_tbl + i) &
+                       CIFISP_LSC_SAMPLE_RESERVED) ||
+                       (*(arg->gb_data_tbl + i) &
+                       CIFISP_LSC_SAMPLE_RESERVED) ||
+                       (*(arg->b_data_tbl + i) &
+                       CIFISP_LSC_SAMPLE_RESERVED)) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                                       "incompatible sample r 0x%x gr 0x%x gb 0x%x b 0x%x in function: %s\n",
+                                       *(arg->r_data_tbl + i),
+                                       *(arg->gr_data_tbl + i),
+                                       *(arg->gb_data_tbl + i),
+                                       *(arg->b_data_tbl + i), __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->lsc_config,
+               arg,
+               sizeof(struct cifisp_lsc_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_LSC);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP Filtering function */
+static int cifisp_flt_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_flt_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->flt_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_FLT);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->flt_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       /* Parameter check */
+       if (arg->mode > CIFISP_FLT_MODE_MAX ||
+               arg->grn_stage1 > CIFISP_FLT_GREEN_STAGE1_MAX ||
+               arg->chr_v_mode > CIFISP_FLT_CHROMA_MODE_MAX ||
+               arg->chr_h_mode > CIFISP_FLT_CHROMA_MODE_MAX ||
+               arg->thresh_sh0 & CIFISP_FLT_THREAD_RESERVED ||
+               arg->thresh_sh1 & CIFISP_FLT_THREAD_RESERVED ||
+               arg->thresh_bl0 & CIFISP_FLT_THREAD_RESERVED ||
+               arg->thresh_bl1 & CIFISP_FLT_THREAD_RESERVED ||
+               arg->fac_bl0 & CIFISP_FLT_FAC_RESERVED ||
+               arg->fac_bl1 & CIFISP_FLT_FAC_RESERVED ||
+               arg->fac_sh0 & CIFISP_FLT_FAC_RESERVED ||
+               arg->fac_sh1 & CIFISP_FLT_FAC_RESERVED ||
+               arg->fac_mid & CIFISP_FLT_FAC_RESERVED ||
+               arg->lum_weight & CIFISP_FLT_LUM_WEIGHT_RESERVED) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->flt_config,
+               arg,
+               sizeof(struct cifisp_flt_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_FLT);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP demosaic interface function */
+static int cifisp_bdm_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_bdm_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->bdm_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_BDM);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->bdm_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->bdm_config,
+               arg,
+               sizeof(struct cifisp_bdm_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_BDM);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP GAMMA correction interface function */
+static int cifisp_sdg_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_sdg_config *arg)
+{
+       unsigned long lock_flags = 0;
+       unsigned int i;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->sdg_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_SDG);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->sdg_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->xa_pnts.gamma_dx0 & CIFISP_DEGAMMA_X_RESERVED ||
+           arg->xa_pnts.gamma_dx1 & CIFISP_DEGAMMA_X_RESERVED) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+               if ((arg->curve_b.gamma_y[i] & CIFISP_DEGAMMA_Y_RESERVED) ||
+                       (arg->curve_r.gamma_y[i] & CIFISP_DEGAMMA_Y_RESERVED) ||
+                       (arg->curve_g.gamma_y[i] & CIFISP_DEGAMMA_Y_RESERVED)) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->sdg_config,
+               arg,
+               sizeof(struct cifisp_sdg_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_SDG);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP GAMMA correction interface function */
+static int cifisp_goc_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_goc_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->goc_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_GOC);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->goc_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->mode > CIFISP_GOC_MODE_MAX) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                                     "incompatible param 0x%x in  function: %s\n",
+                                     arg->mode, __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->goc_config,
+               arg,
+               sizeof(struct cifisp_goc_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_GOC);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP Cross Talk */
+static int cifisp_ctk_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_ctk_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->ctk_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_CTK);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->ctk_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       /* Perform parameter check */
+       if (arg->coeff0 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->coeff1 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->coeff2 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->coeff3 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->coeff4 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->coeff5 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->coeff6 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->coeff7 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->coeff8 & CIFISP_CTK_COEFF_RESERVED ||
+           arg->ct_offset_r & CIFISP_XTALK_OFFSET_RESERVED ||
+           arg->ct_offset_g & CIFISP_XTALK_OFFSET_RESERVED ||
+           arg->ct_offset_b & CIFISP_XTALK_OFFSET_RESERVED) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->ctk_config,
+               arg,
+               sizeof(struct cifisp_ctk_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_CTK);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP White Balance Mode */
+static int cifisp_awb_meas_param(struct cif_isp10_isp_dev *isp_dev,
+                                bool flag, struct cifisp_awb_meas_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->meas_cfgs.curr->awb_meas_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_AWB);
+
+       if (memcmp(arg,
+               &isp_dev->meas_cfgs.curr->awb_meas_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->awb_mode > CIFISP_AWB_MODE_YCBCR ||
+           arg->awb_wnd.h_offs > CIFISP_AWB_WINDOW_OFFSET_MAX ||
+           arg->awb_wnd.v_offs > CIFISP_AWB_WINDOW_OFFSET_MAX ||
+           arg->awb_wnd.h_size > CIFISP_AWB_WINDOW_MAX_SIZE ||
+           arg->awb_wnd.v_size > CIFISP_AWB_WINDOW_MAX_SIZE ||
+           arg->frames > CIFISP_AWB_MAX_FRAMES) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->meas_cfgs.last_or_new->awb_meas_config,
+               arg,
+               sizeof(struct cifisp_awb_meas_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->meas_cfgs.module_updates,
+               CIFISP_MODULE_AWB);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+static int cifisp_awb_gain_param(struct cif_isp10_isp_dev *isp_dev,
+                                bool flag, struct cifisp_awb_gain_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->awb_gain_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_AWB_GAIN);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->awb_gain_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->gain_red > CIFISP_AWB_GAINS_MAX_VAL ||
+           arg->gain_green_r > CIFISP_AWB_GAINS_MAX_VAL ||
+           arg->gain_green_b > CIFISP_AWB_GAINS_MAX_VAL ||
+           arg->gain_blue > CIFISP_AWB_GAINS_MAX_VAL) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->awb_gain_config,
+               arg,
+               sizeof(struct cifisp_awb_gain_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_AWB_GAIN);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+static int cifisp_aec_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_aec_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->meas_cfgs.curr->aec_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_AEC);
+
+       if (memcmp(arg,
+               &isp_dev->meas_cfgs.curr->aec_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->meas_window.h_offs > CIFISP_EXP_MAX_HOFFS ||
+               arg->meas_window.h_size > CIFISP_EXP_MAX_HSIZE ||
+               arg->meas_window.h_size < CIFISP_EXP_MIN_HSIZE ||
+               arg->meas_window.v_offs > CIFISP_EXP_MAX_VOFFS ||
+               arg->meas_window.v_size > CIFISP_EXP_MAX_VSIZE ||
+               arg->meas_window.v_size < CIFISP_EXP_MIN_VSIZE ||
+               arg->mode > CIFISP_EXP_MEASURING_MODE_1) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->meas_cfgs.last_or_new->aec_config,
+               arg,
+               sizeof(struct cifisp_aec_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->meas_cfgs.module_updates,
+               CIFISP_MODULE_AEC);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+static int cifisp_cproc_param(struct cif_isp10_isp_dev *isp_dev,
+                             bool flag, struct cifisp_cproc_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->cproc_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_CPROC);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->cproc_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->c_out_range & CIFISP_CPROC_CTRL_RESERVED ||
+           arg->y_out_range & CIFISP_CPROC_CTRL_RESERVED ||
+           arg->y_in_range & CIFISP_CPROC_CTRL_RESERVED ||
+           arg->contrast & CIFISP_CPROC_CONTRAST_RESERVED ||
+           arg->brightness & CIFISP_CPROC_BRIGHTNESS_RESERVED ||
+           arg->sat & CIFISP_CPROC_SATURATION_RESERVED ||
+           arg->hue & CIFISP_CPROC_HUE_RESERVED) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->cproc_config,
+               arg,
+               sizeof(struct cifisp_cproc_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_CPROC);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+static int cifisp_hst_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_hst_config *arg)
+{
+       unsigned long lock_flags = 0;
+       unsigned int i;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->meas_cfgs.curr->hst_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       if (memcmp(arg,
+               &isp_dev->meas_cfgs.curr->hst_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->mode > CIFISP_HISTOGRAM_MODE_Y_HISTOGRAM ||
+               arg->histogram_predivider > CIFISP_MAX_HIST_PREDIVIDER ||
+               arg->meas_window.v_offs & CIFISP_HIST_WINDOW_OFFSET_RESERVED ||
+               arg->meas_window.h_offs & CIFISP_HIST_WINDOW_OFFSET_RESERVED ||
+               (arg->meas_window.v_size / (CIFISP_HIST_ROW_NUM - 1)) &
+                       CIFISP_HIST_WINDOW_SIZE_RESERVED ||
+               (arg->meas_window.h_size / (CIFISP_HIST_COLUMN_NUM - 1)) &
+                       CIFISP_HIST_WINDOW_SIZE_RESERVED) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+               "incompatible param in function: %s line: %d\n",
+               __func__, __LINE__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       for (i = 0; i < CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE; i++) {
+               if (arg->hist_weight[i] & CIFISP_HIST_WEIGHT_RESERVED) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                       "incompatible param in function: %s line: %d\n",
+                       __func__, __LINE__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+       }
+
+       memcpy(&isp_dev->meas_cfgs.last_or_new->hst_config,
+               arg,
+               sizeof(struct cifisp_hst_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->meas_cfgs.module_updates,
+               CIFISP_MODULE_HST);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+static int cifisp_afc_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_afc_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int i;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->meas_cfgs.curr->afc_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_AFC);
+
+       if (memcmp(arg,
+               &isp_dev->meas_cfgs.curr->afc_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->num_afm_win > CIFISP_AFM_MAX_WINDOWS ||
+           arg->thres & CIFISP_AFC_THRES_RESERVED ||
+           arg->var_shift & CIFISP_AFC_VAR_SHIFT_RESERVED) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       for (i = 0; i < arg->num_afm_win; i++) {
+               if (arg->afm_win[i].h_offs & CIFISP_AFC_WINDOW_X_RESERVED ||
+                   arg->afm_win[i].h_offs < CIFISP_AFC_WINDOW_X_MIN ||
+                   arg->afm_win[i].v_offs & CIFISP_AFC_WINDOW_Y_RESERVED ||
+                   arg->afm_win[i].v_offs < CIFISP_AFC_WINDOW_Y_MIN ||
+                   arg->afm_win[i].h_size & CIFISP_AFC_WINDOW_X_RESERVED ||
+                   arg->afm_win[i].v_size & CIFISP_AFC_WINDOW_Y_RESERVED) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                                     "incompatible param in function: %s\n",
+                                     __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+       }
+
+       memcpy(&isp_dev->meas_cfgs.last_or_new->afc_config,
+               arg,
+               sizeof(struct cifisp_afc_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->meas_cfgs.module_updates,
+               CIFISP_MODULE_AFC);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+static int cifisp_ie_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_ie_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->ie_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_IE);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->ie_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       if (arg->effect != V4L2_COLORFX_NONE &&
+                       arg->effect != V4L2_COLORFX_BW &&
+                       arg->effect != V4L2_COLORFX_SEPIA &&
+                       arg->effect != V4L2_COLORFX_NEGATIVE &&
+                       arg->effect != V4L2_COLORFX_EMBOSS &&
+                       arg->effect != V4L2_COLORFX_SKETCH &&
+                       arg->effect != V4L2_COLORFX_AQUA &&
+                       arg->effect != V4L2_COLORFX_SET_CBCR) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                             "incompatible param in function: %s\n", __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->ie_config,
+               arg,
+               sizeof(struct cifisp_ie_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_IE);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+/* ISP De-noise Pre-Filter(DPF) function */
+static int cifisp_dpf_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_dpf_config *arg)
+{
+       unsigned long lock_flags = 0;
+       unsigned int i;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->dpf_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_DPF);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->dpf_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       /* Parameter check */
+       if ((arg->gain.mode >= CIFISP_DPF_GAIN_USAGE_MAX) ||
+               (arg->gain.mode < CIFISP_DPF_GAIN_USAGE_DISABLED) ||
+               (arg->gain.nf_b_gain & CIFISP_DPF_NF_GAIN_RESERVED) ||
+               (arg->gain.nf_r_gain & CIFISP_DPF_NF_GAIN_RESERVED) ||
+               (arg->gain.nf_gr_gain & CIFISP_DPF_NF_GAIN_RESERVED) ||
+               (arg->gain.nf_gb_gain & CIFISP_DPF_NF_GAIN_RESERVED)) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+               "incompatible DPF GAIN param in function: %s\n",
+               __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       for (i = 0; i < CIFISP_DPF_MAX_SPATIAL_COEFFS; i++) {
+               if ((arg->g_flt.spatial_coeff[i] >
+                       CIFISP_DPF_SPATIAL_COEFF_MAX)) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                       "incompatible DPF G Spatial param in function: %s\n",
+                       __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+
+               if (arg->rb_flt.spatial_coeff[i] >
+                       CIFISP_DPF_SPATIAL_COEFF_MAX) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                       "incompatible DPF RB Spatial param in function: %s\n",
+                       __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+       }
+
+       if ((arg->rb_flt.fltsize != CIFISP_DPF_RB_FILTERSIZE_9x9) &&
+               (arg->rb_flt.fltsize != CIFISP_DPF_RB_FILTERSIZE_13x9)) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                       "incompatible DPF RB filter size param in function: %s\n",
+                       __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       for (i = 0; i < CIFISP_DPF_MAX_NLF_COEFFS; i++) {
+               if (arg->nll.coeff[i] > CIFISP_DPF_NLL_COEFF_N_MAX) {
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                               "incompatible DPF NLL coeff param in function: %s\n",
+                               __func__);
+                       retval = -EINVAL;
+                       goto end;
+               }
+       }
+
+       if ((arg->nll.scale_mode != CIFISP_NLL_SCALE_LINEAR) &&
+               (arg->nll.scale_mode != CIFISP_NLL_SCALE_LOGARITHMIC)) {
+               CIFISP_DPRINT(CIFISP_ERROR,
+                       "incompatible DPF NLL scale mode param in function: %s\n",
+                       __func__);
+               retval = -EINVAL;
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->dpf_config,
+               arg,
+               sizeof(struct cifisp_dpf_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_DPF);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+static int cifisp_dpf_strength_param(struct cif_isp10_isp_dev *isp_dev,
+                           bool flag, struct cifisp_dpf_strength_config *arg)
+{
+       unsigned long lock_flags = 0;
+       int retval = 0;
+
+       if (!arg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+       if (flag == _GET_) {
+               memcpy(arg,
+                       &isp_dev->other_cfgs.curr->dpf_strength_config,
+                       sizeof(*arg));
+               goto end;
+       }
+
+       cifisp_param_dump(arg, CIFISP_MODULE_DPF_STRENGTH);
+
+       if (memcmp(arg,
+               &isp_dev->other_cfgs.curr->dpf_strength_config,
+               sizeof(*arg)) == 0) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                             "same param in function: %s\n", __func__);
+               goto end;
+       }
+
+       memcpy(&isp_dev->other_cfgs.last_or_new->dpf_strength_config,
+               arg,
+               sizeof(struct cifisp_dpf_strength_config));
+       CIFISP_MODULE_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_DPF_STRENGTH);
+end:
+       spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+       return retval;
+}
+
+static int cifisp_last_capture_config(struct cifisp_last_capture_config *arg)
+{
+#ifdef LOG_CAPTURE_PARAMS
+       if (!arg)
+               return -EINVAL;
+
+       memcpy(arg, &g_last_capture_config, sizeof(*arg));
+
+       return 0;
+#else
+       return -EPERM;
+#endif
+}
+
+/* DPCC */
+static void cifisp_dpcc_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_dpcc_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->dpcc_config;
+       unsigned int i;
+
+       cifisp_iowrite32(pconfig->mode, CIF_ISP_DPCC_MODE);
+       cifisp_iowrite32(pconfig->output_mode, CIF_ISP_DPCC_OUTPUT_MODE);
+       cifisp_iowrite32(pconfig->set_use, CIF_ISP_DPCC_SET_USE);
+
+       cifisp_iowrite32(pconfig->methods[0].method,
+                       CIF_ISP_DPCC_METHODS_SET_1);
+       cifisp_iowrite32(pconfig->methods[1].method,
+                       CIF_ISP_DPCC_METHODS_SET_2);
+       cifisp_iowrite32(pconfig->methods[2].method,
+                       CIF_ISP_DPCC_METHODS_SET_3);
+       for (i = 0; i < CIFISP_DPCC_METHODS_MAX; i++) {
+               cifisp_iowrite32(pconfig->methods[i].line_thresh,
+                       CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * i);
+               cifisp_iowrite32(pconfig->methods[i].line_mad_fac,
+                       CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * i);
+               cifisp_iowrite32(pconfig->methods[i].pg_fac,
+                       CIF_ISP_DPCC_PG_FAC_1 + 0x14 * i);
+               cifisp_iowrite32(pconfig->methods[i].rnd_thresh,
+                       CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * i);
+               cifisp_iowrite32(pconfig->methods[i].rg_fac,
+                       CIF_ISP_DPCC_RG_FAC_1 + 0x14 * i);
+       }
+
+       cifisp_iowrite32(pconfig->rnd_offs, CIF_ISP_DPCC_RND_OFFS);
+       cifisp_iowrite32(pconfig->ro_limits, CIF_ISP_DPCC_RO_LIMITS);
+}
+
+static void cifisp_dpcc_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32OR(CIFISP_DPCC_ENA, CIF_ISP_DPCC_MODE);
+}
+
+static void cifisp_dpcc_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32(CIFISP_DPCC_DIS, CIF_ISP_DPCC_MODE);
+}
+
+/* Lens Shade Correction */
+
+/*****************************************************************************/
+static void cifisp_lsc_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32(0, CIF_ISP_LSC_CTRL);
+}
+
+static bool cifisp_lsc_correct_matrix_config(struct cif_isp10_isp_dev *isp_dev)
+{
+       int i, n;
+       unsigned int isp_lsc_status, sram_addr, isp_lsc_table_sel;
+       unsigned int data;
+       struct cifisp_lsc_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->lsc_config;
+
+       isp_lsc_status = cifisp_ioread32(CIF_ISP_LSC_STATUS);
+       sram_addr = (isp_lsc_status & 0x2U) ? 0U : 153U; /* ( 17 * 18 ) >> 1 */
+
+       cifisp_iowrite32(sram_addr, CIF_ISP_LSC_R_TABLE_ADDR);
+       cifisp_iowrite32(sram_addr, CIF_ISP_LSC_GR_TABLE_ADDR);
+       cifisp_iowrite32(sram_addr, CIF_ISP_LSC_GB_TABLE_ADDR);
+       cifisp_iowrite32(sram_addr, CIF_ISP_LSC_B_TABLE_ADDR);
+
+       /* program data tables (table size is 9 * 17 = 153) */
+       for (n = 0; n < ((CIFISP_LSC_SECTORS_MAX + 1) *
+                       (CIFISP_LSC_SECTORS_MAX + 1));
+                       n += CIFISP_LSC_SECTORS_MAX + 1) {
+               /*
+                * 17 sectors with 2 values in one DWORD = 9
+                * DWORDs (8 steps + 1 outside loop)
+                */
+               for (i = 0; i < (CIFISP_LSC_SECTORS_MAX); i += 2) {
+                       data = CIFISP_LSC_TABLE_DATA(pconfig->r_data_tbl[n + i],
+                               pconfig->r_data_tbl[n + i + 1]);
+                       cifisp_iowrite32(data, CIF_ISP_LSC_R_TABLE_DATA);
+
+                       data = CIFISP_LSC_TABLE_DATA(
+                               pconfig->gr_data_tbl[n + i],
+                               pconfig->gr_data_tbl[n + i + 1]);
+                       cifisp_iowrite32(data, CIF_ISP_LSC_GR_TABLE_DATA);
+
+                       data = CIFISP_LSC_TABLE_DATA(
+                               pconfig->gb_data_tbl[n + i],
+                               pconfig->gb_data_tbl[n + i + 1]);
+                       cifisp_iowrite32(data, CIF_ISP_LSC_GB_TABLE_DATA);
+
+                       data = CIFISP_LSC_TABLE_DATA(pconfig->b_data_tbl[n + i],
+                               pconfig->b_data_tbl[n + i + 1]);
+                       cifisp_iowrite32(data, CIF_ISP_LSC_B_TABLE_DATA);
+               }
+
+               data = CIFISP_LSC_TABLE_DATA(
+                       pconfig->r_data_tbl[n + CIFISP_LSC_SECTORS_MAX],
+                       /* isp_dev->lsc_config.r_data_tbl[n + i] */0);
+               cifisp_iowrite32(data, CIF_ISP_LSC_R_TABLE_DATA);
+
+               data = CIFISP_LSC_TABLE_DATA(
+                       pconfig->gr_data_tbl[n + CIFISP_LSC_SECTORS_MAX],
+                       /* isp_dev->lsc_config.gr_data_tbl[n + i] */0);
+               cifisp_iowrite32(data, CIF_ISP_LSC_GR_TABLE_DATA);
+
+               data = CIFISP_LSC_TABLE_DATA(
+                       pconfig->gb_data_tbl[n + CIFISP_LSC_SECTORS_MAX],
+                       /* isp_dev->lsc_config.gr_data_tbl[n + i] */0);
+               cifisp_iowrite32(data, CIF_ISP_LSC_GB_TABLE_DATA);
+
+               data = CIFISP_LSC_TABLE_DATA(
+                               pconfig->b_data_tbl[n + CIFISP_LSC_SECTORS_MAX],
+                               /* isp_dev->lsc_config.b_data_tbl[n + i] */0);
+               cifisp_iowrite32(data, CIF_ISP_LSC_B_TABLE_DATA);
+       }
+
+       isp_lsc_table_sel = (isp_lsc_status & 0x2U) ? 0U : 1U;
+       cifisp_iowrite32(isp_lsc_table_sel, CIF_ISP_LSC_TABLE_SEL);
+       return true;
+}
+
+/*****************************************************************************/
+static bool cifisp_lsc_config(struct cif_isp10_isp_dev *isp_dev)
+{
+       int i;
+       unsigned int data;
+       struct cifisp_lsc_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->lsc_config;
+
+       if (pconfig->config_width != isp_dev->input_width ||
+               pconfig->config_height != isp_dev->input_height) {
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "LSC config: lsc_w %d lsc_h %d act_w %d act_h %d\n",
+                       pconfig->config_width,
+                       pconfig->config_height,
+                       isp_dev->input_width,
+                       isp_dev->input_height);
+               return false;
+       }
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+               "LSC config: lsc_w %d lsc_h %d\n",
+               pconfig->config_width,
+               pconfig->config_height);
+
+       /* To config must be off */
+       cifisp_iowrite32(0, CIF_ISP_LSC_CTRL);
+
+       cifisp_lsc_correct_matrix_config(isp_dev);
+
+       if (isp_dev->active_lsc_width !=
+               pconfig->config_width ||
+               isp_dev->active_lsc_height !=
+               pconfig->config_height) {
+               for (i = 0; i < 4; i++) {
+                       /* program x size tables */
+                       data = CIFISP_LSC_SECT_SIZE(
+                                       pconfig->x_size_tbl[i * 2],
+                                       pconfig->x_size_tbl[i * 2 + 1]);
+                       cifisp_iowrite32(data, CIF_ISP_LSC_XSIZE_01 + i * 4);
+
+                       /* program x grad tables */
+                       data = CIFISP_LSC_SECT_SIZE(
+                                       pconfig->x_grad_tbl[i * 2],
+                                       pconfig->x_grad_tbl[i * 2 + 1]);
+                       cifisp_iowrite32(data, CIF_ISP_LSC_XGRAD_01 + i * 4);
+
+                       /* program y size tables */
+                       data = CIFISP_LSC_SECT_SIZE(
+                                       pconfig->y_size_tbl[i * 2],
+                                       pconfig->y_size_tbl[i * 2 + 1]);
+                       cifisp_iowrite32(data, CIF_ISP_LSC_YSIZE_01 + i * 4);
+
+                       /* program y grad tables */
+                       data = CIFISP_LSC_SECT_SIZE(
+                                       pconfig->y_grad_tbl[i * 2],
+                                       pconfig->y_grad_tbl[i * 2 + 1]);
+                       cifisp_iowrite32(data, CIF_ISP_LSC_YGRAD_01 + i * 4);
+               }
+
+               isp_dev->active_lsc_width = pconfig->config_width;
+               isp_dev->active_lsc_height = pconfig->config_height;
+       }
+
+       cifisp_iowrite32(1, CIF_ISP_LSC_CTRL);
+
+       return true;
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_lsc_config_read(const struct cif_isp10_isp_dev *isp_dev,
+                                  struct cifisp_lsc_config *pconfig)
+{
+);
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_bls_get_meas(const struct cif_isp10_isp_dev *isp_dev,
+       struct cifisp_stat_buffer *pbuf)
+{
+       const struct cif_isp10_device *cif_dev =
+               container_of(isp_dev, struct cif_isp10_device, isp_dev);
+       enum cif_isp10_pix_fmt in_pix_fmt;
+
+       in_pix_fmt = cif_dev->config.isp_config.input->pix_fmt;
+       if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_BGGR(in_pix_fmt)) {
+               pbuf->params.ae.bls_val.meas_b =
+                       cifisp_ioread32(CIF_ISP_BLS_A_MEASURED);
+               pbuf->params.ae.bls_val.meas_gb =
+                       cifisp_ioread32(CIF_ISP_BLS_B_MEASURED);
+               pbuf->params.ae.bls_val.meas_gr =
+                       cifisp_ioread32(CIF_ISP_BLS_C_MEASURED);
+               pbuf->params.ae.bls_val.meas_r =
+                       cifisp_ioread32(CIF_ISP_BLS_D_MEASURED);
+       } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GBRG(in_pix_fmt)) {
+               pbuf->params.ae.bls_val.meas_gb =
+                       cifisp_ioread32(CIF_ISP_BLS_A_MEASURED);
+               pbuf->params.ae.bls_val.meas_b =
+                       cifisp_ioread32(CIF_ISP_BLS_B_MEASURED);
+               pbuf->params.ae.bls_val.meas_r =
+                       cifisp_ioread32(CIF_ISP_BLS_C_MEASURED);
+               pbuf->params.ae.bls_val.meas_gr =
+                       cifisp_ioread32(CIF_ISP_BLS_D_MEASURED);
+       } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GRBG(in_pix_fmt)) {
+               pbuf->params.ae.bls_val.meas_gr =
+                       cifisp_ioread32(CIF_ISP_BLS_A_MEASURED);
+               pbuf->params.ae.bls_val.meas_r =
+                       cifisp_ioread32(CIF_ISP_BLS_B_MEASURED);
+               pbuf->params.ae.bls_val.meas_b =
+                       cifisp_ioread32(CIF_ISP_BLS_C_MEASURED);
+               pbuf->params.ae.bls_val.meas_gb =
+                       cifisp_ioread32(CIF_ISP_BLS_D_MEASURED);
+       } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_RGGB(in_pix_fmt)) {
+               pbuf->params.ae.bls_val.meas_r =
+                       cifisp_ioread32(CIF_ISP_BLS_A_MEASURED);
+               pbuf->params.ae.bls_val.meas_gr =
+                       cifisp_ioread32(CIF_ISP_BLS_B_MEASURED);
+               pbuf->params.ae.bls_val.meas_gb =
+                       cifisp_ioread32(CIF_ISP_BLS_C_MEASURED);
+               pbuf->params.ae.bls_val.meas_b =
+                       cifisp_ioread32(CIF_ISP_BLS_D_MEASURED);
+       }
+}
+
+/*****************************************************************************/
+static void cifisp_bls_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_bls_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->bls_config;
+       u32 new_control = 0;
+       const struct cif_isp10_device *cif_dev =
+               container_of(isp_dev, struct cif_isp10_device, isp_dev);
+       enum cif_isp10_pix_fmt in_pix_fmt;
+
+       in_pix_fmt = cif_dev->config.isp_config.input->pix_fmt;
+
+       /* fixed subtraction values */
+       if (!pconfig->enable_auto) {
+               const struct cifisp_bls_fixed_val *pval =
+                   &isp_dev->other_cfgs.last_or_new->bls_config.fixed_val;
+
+               if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_BGGR(in_pix_fmt)) {
+                       cifisp_iowrite32(pval->r, CIF_ISP_BLS_D_FIXED);
+                       cifisp_iowrite32(pval->gr, CIF_ISP_BLS_C_FIXED);
+                       cifisp_iowrite32(pval->gb, CIF_ISP_BLS_B_FIXED);
+                       cifisp_iowrite32(pval->b, CIF_ISP_BLS_A_FIXED);
+               } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GBRG(in_pix_fmt)) {
+                       cifisp_iowrite32(pval->r, CIF_ISP_BLS_C_FIXED);
+                       cifisp_iowrite32(pval->gr, CIF_ISP_BLS_D_FIXED);
+                       cifisp_iowrite32(pval->gb, CIF_ISP_BLS_A_FIXED);
+                       cifisp_iowrite32(pval->b, CIF_ISP_BLS_B_FIXED);
+               } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GRBG(in_pix_fmt)) {
+                       cifisp_iowrite32(pval->r, CIF_ISP_BLS_B_FIXED);
+                       cifisp_iowrite32(pval->gr, CIF_ISP_BLS_A_FIXED);
+                       cifisp_iowrite32(pval->gb, CIF_ISP_BLS_D_FIXED);
+                       cifisp_iowrite32(pval->b, CIF_ISP_BLS_C_FIXED);
+               } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_RGGB(in_pix_fmt)) {
+                       cifisp_iowrite32(pval->r, CIF_ISP_BLS_A_FIXED);
+                       cifisp_iowrite32(pval->gr, CIF_ISP_BLS_B_FIXED);
+                       cifisp_iowrite32(pval->gb, CIF_ISP_BLS_C_FIXED);
+                       cifisp_iowrite32(pval->b, CIF_ISP_BLS_D_FIXED);
+               }
+
+               new_control = CIFISP_BLS_MODE_FIXED;
+               cifisp_iowrite32(new_control, CIF_ISP_BLS_CTRL);
+       } else {
+               if (pconfig->en_windows & 2) {
+                       cifisp_iowrite32(pconfig->bls_window2.h_offs,
+                                     CIF_ISP_BLS_H2_START);
+                       cifisp_iowrite32(pconfig->bls_window2.h_size,
+                                     CIF_ISP_BLS_H2_STOP);
+                       cifisp_iowrite32(pconfig->bls_window2.v_offs,
+                                     CIF_ISP_BLS_V2_START);
+                       cifisp_iowrite32(pconfig->bls_window2.v_size,
+                                     CIF_ISP_BLS_V2_STOP);
+                       new_control |= CIFISP_BLS_WINDOW_2;
+               }
+
+               if (pconfig->en_windows & 1) {
+                       cifisp_iowrite32(pconfig->bls_window1.h_offs,
+                                     CIF_ISP_BLS_H1_START);
+                       cifisp_iowrite32(pconfig->bls_window1.h_size,
+                                     CIF_ISP_BLS_H1_STOP);
+                       cifisp_iowrite32(pconfig->bls_window1.v_offs,
+                                     CIF_ISP_BLS_V1_START);
+                       cifisp_iowrite32(pconfig->bls_window1.v_size,
+                                     CIF_ISP_BLS_V1_STOP);
+                       new_control |= CIFISP_BLS_WINDOW_1;
+               }
+
+               cifisp_iowrite32(pconfig->bls_samples, CIF_ISP_BLS_SAMPLES);
+
+               new_control |= CIFISP_BLS_MODE_MEASURED;
+
+               cifisp_iowrite32(new_control, CIF_ISP_BLS_CTRL);
+       }
+}
+
+/*****************************************************************************/
+static void cifisp_bls_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32OR(CIFISP_BLS_ENA, CIF_ISP_BLS_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_bls_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32(CIFISP_BLS_DIS, CIF_ISP_BLS_CTRL);
+}
+
+/* Gamma correction */
+/*****************************************************************************/
+static void cifisp_sdg_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_sdg_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->sdg_config;
+       unsigned int i;
+
+       cifisp_iowrite32(pconfig->xa_pnts.gamma_dx0, CIF_ISP_GAMMA_DX_LO);
+       cifisp_iowrite32(pconfig->xa_pnts.gamma_dx1, CIF_ISP_GAMMA_DX_HI);
+
+       for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+               cifisp_iowrite32(pconfig->curve_r.gamma_y[i],
+                       CIF_ISP_GAMMA_R_Y0 + i * 4);
+               cifisp_iowrite32(pconfig->curve_g.gamma_y[i],
+                       CIF_ISP_GAMMA_G_Y0 + i * 4);
+               cifisp_iowrite32(pconfig->curve_b.gamma_y[i],
+                       CIF_ISP_GAMMA_B_Y0 + i * 4);
+       }
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_sdg_config_read(const struct cif_isp10_isp_dev *isp_dev,
+                                  struct cifisp_sdg_config *pconfig)
+{
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_sdg_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_GAMMA_IN_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_sdg_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_GAMMA_IN_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_goc_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       int i;
+       const struct cifisp_goc_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->goc_config;
+
+       cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA, CIF_ISP_CTRL);
+
+       cifisp_iowrite32(pconfig->mode, CIF_ISP_GAMMA_OUT_MODE);
+       for (i = 0; i < CIFISP_GAMMA_OUT_MAX_SAMPLES; i++)
+               cifisp_iowrite32(pconfig->gamma_y[i],
+               CIF_ISP_GAMMA_OUT_Y_0 + i * 4);
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_goc_config_read(const struct cif_isp10_isp_dev *isp_dev,
+                                  struct cifisp_goc_config *pconfig)
+{
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_goc_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_goc_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_bdm_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_bdm_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->bdm_config;
+
+       /*set demosaic threshold */
+       cifisp_iowrite32(pconfig->demosaic_th, CIF_ISP_DEMOSAIC);
+}
+
+/*****************************************************************************/
+static void cifisp_bdm_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32AND(~(CIFISP_BDM_BYPASS_EN(1)), CIF_ISP_DEMOSAIC);
+}
+
+/*****************************************************************************/
+static void cifisp_bdm_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32(0, CIF_ISP_DEMOSAIC);
+}
+
+/*****************************************************************************/
+static void cifisp_flt_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_flt_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->flt_config;
+
+       cifisp_iowrite32(pconfig->thresh_bl0,
+               CIF_ISP_FILT_THRESH_BL0);
+       cifisp_iowrite32(pconfig->thresh_bl1,
+               CIF_ISP_FILT_THRESH_BL1);
+       cifisp_iowrite32(pconfig->thresh_sh0,
+               CIF_ISP_FILT_THRESH_SH0);
+       cifisp_iowrite32(pconfig->thresh_sh1,
+               CIF_ISP_FILT_THRESH_SH1);
+       cifisp_iowrite32(pconfig->fac_bl0,
+               CIF_ISP_FILT_FAC_BL0);
+       cifisp_iowrite32(pconfig->fac_bl1,
+               CIF_ISP_FILT_FAC_BL1);
+       cifisp_iowrite32(pconfig->fac_mid,
+               CIF_ISP_FILT_FAC_MID);
+       cifisp_iowrite32(pconfig->fac_sh0,
+               CIF_ISP_FILT_FAC_SH0);
+       cifisp_iowrite32(pconfig->fac_sh1,
+               CIF_ISP_FILT_FAC_SH1);
+       cifisp_iowrite32(pconfig->lum_weight,
+               CIF_ISP_FILT_LUM_WEIGHT);
+
+       cifisp_iowrite32(CIFISP_FLT_MODE(pconfig->mode) |
+               CIFISP_FLT_CHROMA_V_MODE(pconfig->chr_v_mode) |
+               CIFISP_FLT_CHROMA_H_MODE(pconfig->chr_h_mode) |
+               CIFISP_FLT_GREEN_STAGE1(pconfig->grn_stage1),
+               CIF_ISP_FILT_MODE);
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_flt_config_read(const struct cif_isp10_isp_dev *isp_dev,
+                                  struct cifisp_flt_config *pconfig)
+{
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_flt_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32OR(CIFISP_FLT_ENA, CIF_ISP_FILT_MODE);
+}
+
+/*****************************************************************************/
+static void cifisp_flt_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32(CIFISP_FLT_DIS, CIF_ISP_FILT_MODE);
+}
+
+/* Auto White Balance */
+/*****************************************************************************/
+static void cifisp_awb_gain_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_awb_gain_config *pconfig =
+           &isp_dev->other_cfgs.last_or_new->awb_gain_config;
+
+       cifisp_iowrite32(CIFISP_AWB_GAIN_R_SET(pconfig->gain_green_r) |
+                     pconfig->gain_green_b, CIF_ISP_AWB_GAIN_G);
+
+       cifisp_iowrite32(CIFISP_AWB_GAIN_R_SET(pconfig->gain_red) |
+                     pconfig->gain_blue, CIF_ISP_AWB_GAIN_RB);
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_awb_gain_config_read(const struct cif_isp10_isp_dev *isp_dev,
+                                       struct cifisp_awb_gain_config *pconfig)
+{
+       unsigned int reg = cifisp_ioread32(CIF_ISP_AWB_GAIN_G);
+
+       pconfig->gain_green_r = CIFISP_AWB_GAIN_R_READ(reg);
+       pconfig->gain_green_b = CIFISP_AWB_GAIN_B_READ(reg);
+       reg = cifisp_ioread32(CIF_ISP_AWB_GAIN_RB);
+       pconfig->gain_red = CIFISP_AWB_GAIN_R_READ(reg);
+       pconfig->gain_blue = CIFISP_AWB_GAIN_B_READ(reg);
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_awb_meas_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_awb_meas_config *pconfig =
+               &isp_dev->meas_cfgs.last_or_new->awb_meas_config;
+       unsigned int awb_prob = 0;
+
+       /* based on the mode,configure the awb module */
+       if (pconfig->awb_mode == CIFISP_AWB_MODE_RGB) {
+               awb_prob = CIFISP_AWB_MODE_RGB_EN;
+       } else {
+               if (pconfig->enable_ymax_cmp)
+                       awb_prob = CIFISP_AWB_YMAX_CMP_EN;
+
+               /* Reference Cb and Cr */
+               cifisp_iowrite32(CIFISP_AWB_REF_CR_SET(pconfig->awb_ref_cr) |
+                       pconfig->awb_ref_cb, CIF_ISP_AWB_REF);
+               /* Yc Threshold */
+               cifisp_iowrite32(CIFISP_AWB_MAX_Y_SET(pconfig->max_y) |
+                       CIFISP_AWB_MIN_Y_SET(pconfig->min_y) |
+                       CIFISP_AWB_MAX_CS_SET(pconfig->max_csum) |
+                       pconfig->min_c, CIF_ISP_AWB_THRESH);
+       }
+
+       /* Common Configuration */
+       cifisp_iowrite32(awb_prob, CIF_ISP_AWB_PROP);
+       /* window offset */
+       cifisp_iowrite32(pconfig->awb_wnd.v_offs,
+               CIF_ISP_AWB_WND_V_OFFS);
+       cifisp_iowrite32(pconfig->awb_wnd.h_offs,
+               CIF_ISP_AWB_WND_H_OFFS);
+       /* AWB window size */
+       cifisp_iowrite32(pconfig->awb_wnd.v_size, CIF_ISP_AWB_WND_V_SIZE);
+       cifisp_iowrite32(pconfig->awb_wnd.h_size, CIF_ISP_AWB_WND_H_SIZE);
+       /* Number of frames */
+       cifisp_iowrite32(pconfig->frames, CIF_ISP_AWB_FRAMES);
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_awb_meas_config_read(const struct cif_isp10_isp_dev *isp_dev,
+                                       struct cifisp_awb_meas_config *pconfig)
+{
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_awb_meas_en(struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_awb_meas_config *pconfig =
+               &isp_dev->meas_cfgs.last_or_new->awb_meas_config;
+       u32 reg_val = cifisp_ioread32(CIF_ISP_AWB_PROP);
+
+       /* switch off */
+       reg_val &= 0xFFFFFFFC;
+
+       if (pconfig->awb_mode == CIFISP_AWB_MODE_RGB)
+               reg_val |= CIFISP_AWB_MODE_RGB_EN;
+       else
+               reg_val |= CIFISP_AWB_MODE_YCBCR_EN;
+
+       cifisp_iowrite32(reg_val, CIF_ISP_AWB_PROP);
+
+       isp_dev->active_meas |= CIF_ISP_AWB_DONE;
+
+       /* Measurements require AWB block be active. */
+       cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_AWB_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_awb_meas_end(struct cif_isp10_isp_dev *isp_dev)
+{
+       u32 reg_val = cifisp_ioread32(CIF_ISP_AWB_PROP);
+
+       /* switch off */
+       reg_val &= 0xFFFFFFFC;
+
+       cifisp_iowrite32(reg_val, CIF_ISP_AWB_PROP);
+
+       isp_dev->active_meas &= ~CIF_ISP_AWB_DONE;
+
+       if (!CIFISP_MODULE_IS_EN(
+               isp_dev->meas_cfgs.last_or_new->module_ens,
+               CIFISP_MODULE_AWB))
+               cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_AWB_ENA,
+               CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_awb_gain_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_AWB_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_awb_gain_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       if (!CIFISP_MODULE_IS_EN(
+               isp_dev->meas_cfgs.last_or_new->module_ens,
+               CIFISP_MODULE_AWB))
+               cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_AWB_ENA,
+               CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_get_awb_meas(struct cif_isp10_isp_dev *isp_dev,
+       struct cifisp_stat_buffer *pbuf)
+{
+       /* Protect against concurrent access from ISR? */
+       u32 reg_val;
+       const struct cifisp_awb_meas_config *pconfig =
+               &isp_dev->meas_cfgs.curr->awb_meas_config;
+
+       pbuf->meas_type |= CIFISP_STAT_AWB;
+       reg_val = cifisp_ioread32(CIF_ISP_AWB_WHITE_CNT);
+       pbuf->params.awb.awb_mean[0].cnt =
+               CIFISP_AWB_GET_PIXEL_CNT(reg_val);
+       reg_val = cifisp_ioread32(CIF_ISP_AWB_MEAN);
+
+       if (pconfig->awb_mode == CIFISP_AWB_MODE_RGB) {
+               pbuf->params.awb.awb_mean[0].mean_r =
+                       CIFISP_AWB_GET_MEAN_R(reg_val);
+               pbuf->params.awb.awb_mean[0].mean_b =
+                       CIFISP_AWB_GET_MEAN_B(reg_val);
+               pbuf->params.awb.awb_mean[0].mean_g =
+                       CIFISP_AWB_GET_MEAN_G(reg_val);
+       } else {
+               pbuf->params.awb.awb_mean[0].mean_cr =
+                       (u8)CIFISP_AWB_GET_MEAN_CR(reg_val);
+               pbuf->params.awb.awb_mean[0].mean_cb =
+                       (u8)CIFISP_AWB_GET_MEAN_CB(reg_val);
+               pbuf->params.awb.awb_mean[0].mean_y =
+                       (u8)CIFISP_AWB_GET_MEAN_Y(reg_val);
+       }
+}
+
+/* Auto Exposure */
+/*****************************************************************************/
+static void cifisp_aec_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_aec_config *pconfig =
+               &isp_dev->meas_cfgs.last_or_new->aec_config;
+       unsigned int block_hsize, block_vsize;
+
+       cifisp_iowrite32(CIFISP_EXP_CTRL_AUTOSTOP(pconfig->autostop) |
+                       CIFISP_EXP_CTRL_MEASMODE(pconfig->mode),
+                       CIF_ISP_EXP_CTRL);
+
+       cifisp_iowrite32(pconfig->meas_window.h_offs, CIF_ISP_EXP_H_OFFSET);
+       cifisp_iowrite32(pconfig->meas_window.v_offs, CIF_ISP_EXP_V_OFFSET);
+
+       block_hsize = pconfig->meas_window.h_size /
+               CIFISP_EXP_COLUMN_NUM - 1;
+       block_vsize = pconfig->meas_window.v_size /
+               CIFISP_EXP_ROW_NUM - 1;
+
+       cifisp_iowrite32(CIFISP_EXP_HSIZE(block_hsize), CIF_ISP_EXP_H_SIZE);
+       cifisp_iowrite32(CIFISP_EXP_VSIZE(block_vsize), CIF_ISP_EXP_V_SIZE);
+}
+
+/*****************************************************************************/
+static void cifisp_aec_en(struct cif_isp10_isp_dev *isp_dev)
+{
+       isp_dev->active_meas |= CIF_ISP_EXP_END;
+
+       cifisp_iowrite32OR(CIFISP_EXP_ENA, CIF_ISP_EXP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_aec_end(struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32(CIFISP_EXP_DIS, CIF_ISP_EXP_CTRL);
+
+       isp_dev->active_meas &= ~CIF_ISP_EXP_END;
+}
+
+/*****************************************************************************/
+static void cifisp_get_aec_meas(struct cif_isp10_isp_dev *isp_dev,
+                               struct cifisp_stat_buffer *pbuf)
+{
+       unsigned int i;
+
+       pbuf->meas_type |= CIFISP_STAT_AUTOEXP; /*Set the measurement type */
+       for (i = 0; i < CIFISP_AE_MEAN_MAX; i++) {
+               pbuf->params.ae.exp_mean[i] =
+                       (u8)cifisp_ioread32(CIF_ISP_EXP_MEAN_00 + i * 4);
+       }
+}
+
+/* X-Talk Matrix */
+/*****************************************************************************/
+static void cifisp_ctk_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       /* Nothing to do */
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_ctk_config_read(const struct cif_isp10_isp_dev *isp_dev,
+                                  struct cifisp_ctk_config *pconfig)
+{
+       pconfig->coeff0 = cifisp_ioread32(CIF_ISP_CT_COEFF_0);
+       pconfig->coeff1 = cifisp_ioread32(CIF_ISP_CT_COEFF_1);
+       pconfig->coeff2 = cifisp_ioread32(CIF_ISP_CT_COEFF_2);
+       pconfig->coeff3 = cifisp_ioread32(CIF_ISP_CT_COEFF_3);
+       pconfig->coeff4 = cifisp_ioread32(CIF_ISP_CT_COEFF_4);
+       pconfig->coeff5 = cifisp_ioread32(CIF_ISP_CT_COEFF_5);
+       pconfig->coeff6 = cifisp_ioread32(CIF_ISP_CT_COEFF_6);
+       pconfig->coeff7 = cifisp_ioread32(CIF_ISP_CT_COEFF_7);
+       pconfig->coeff8 = cifisp_ioread32(CIF_ISP_CT_COEFF_8);
+       pconfig->ct_offset_r = cifisp_ioread32(CIF_ISP_CT_OFFSET_R);
+       pconfig->ct_offset_g = cifisp_ioread32(CIF_ISP_CT_OFFSET_G);
+       pconfig->ct_offset_b = cifisp_ioread32(CIF_ISP_CT_OFFSET_B);
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_ctk_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_ctk_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->ctk_config;
+
+       cifisp_iowrite32(pconfig->coeff0, CIF_ISP_CT_COEFF_0);
+       cifisp_iowrite32(pconfig->coeff1, CIF_ISP_CT_COEFF_1);
+       cifisp_iowrite32(pconfig->coeff2, CIF_ISP_CT_COEFF_2);
+       cifisp_iowrite32(pconfig->coeff3, CIF_ISP_CT_COEFF_3);
+       cifisp_iowrite32(pconfig->coeff4, CIF_ISP_CT_COEFF_4);
+       cifisp_iowrite32(pconfig->coeff5, CIF_ISP_CT_COEFF_5);
+       cifisp_iowrite32(pconfig->coeff6, CIF_ISP_CT_COEFF_6);
+       cifisp_iowrite32(pconfig->coeff7, CIF_ISP_CT_COEFF_7);
+       cifisp_iowrite32(pconfig->coeff8, CIF_ISP_CT_COEFF_8);
+       cifisp_iowrite32(pconfig->ct_offset_r, CIF_ISP_CT_OFFSET_R);
+       cifisp_iowrite32(pconfig->ct_offset_g, CIF_ISP_CT_OFFSET_G);
+       cifisp_iowrite32(pconfig->ct_offset_b, CIF_ISP_CT_OFFSET_B);
+}
+
+/*****************************************************************************/
+static void cifisp_ctk_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       /* Write back the default values. */
+       cifisp_iowrite32(0x80, CIF_ISP_CT_COEFF_0);
+       cifisp_iowrite32(0, CIF_ISP_CT_COEFF_1);
+       cifisp_iowrite32(0, CIF_ISP_CT_COEFF_2);
+       cifisp_iowrite32(0, CIF_ISP_CT_COEFF_3);
+       cifisp_iowrite32(0x80, CIF_ISP_CT_COEFF_4);
+       cifisp_iowrite32(0, CIF_ISP_CT_COEFF_5);
+       cifisp_iowrite32(0, CIF_ISP_CT_COEFF_6);
+       cifisp_iowrite32(0, CIF_ISP_CT_COEFF_7);
+       cifisp_iowrite32(0x80, CIF_ISP_CT_COEFF_8);
+
+       cifisp_iowrite32(0, CIF_ISP_CT_OFFSET_R);
+       cifisp_iowrite32(0, CIF_ISP_CT_OFFSET_G);
+       cifisp_iowrite32(0, CIF_ISP_CT_OFFSET_B);
+}
+
+/* CPROC */
+/*****************************************************************************/
+static void cifisp_cproc_config(const struct cif_isp10_isp_dev *isp_dev,
+       enum cif_isp10_pix_fmt_quantization quantization)
+{
+       const struct cifisp_cproc_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->cproc_config;
+       const struct cifisp_ie_config *ie_pconfig =
+               &isp_dev->other_cfgs.last_or_new->ie_config;
+
+       cifisp_iowrite32(pconfig->contrast, CIF_C_PROC_CONTRAST);
+       cifisp_iowrite32(pconfig->hue, CIF_C_PROC_HUE);
+       cifisp_iowrite32(pconfig->sat, CIF_C_PROC_SATURATION);
+       cifisp_iowrite32(pconfig->brightness, CIF_C_PROC_BRIGHTNESS);
+
+       if ((quantization != CIF_ISP10_QUANTIZATION_FULL_RANGE) ||
+                (ie_pconfig->effect != V4L2_COLORFX_NONE)) {
+               cifisp_iowrite32(
+                       ~(CIF_C_PROC_YOUT_FULL |
+                       CIF_C_PROC_YIN_FULL |
+                       CIF_C_PROC_COUT_FULL),
+                       CIF_C_PROC_CTRL);
+       } else {
+               cifisp_iowrite32OR(
+                       (CIF_C_PROC_YOUT_FULL |
+                       CIF_C_PROC_YIN_FULL |
+                       CIF_C_PROC_COUT_FULL),
+                       CIF_C_PROC_CTRL);
+       }
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_cproc_config_read(const struct cif_isp10_isp_dev *isp_dev,
+                                    struct cifisp_cproc_config *pconfig)
+{
+       unsigned int reg;
+
+       pconfig->contrast = cifisp_ioread32(CIF_C_PROC_CONTRAST);
+       pconfig->hue = cifisp_ioread32(CIF_C_PROC_HUE);
+       pconfig->sat = cifisp_ioread32(CIF_C_PROC_SATURATION);
+       pconfig->brightness = cifisp_ioread32(CIF_C_PROC_BRIGHTNESS);
+       reg = cifisp_ioread32(CIF_C_PROC_CTRL);
+       pconfig->y_out_range = (reg >> 1) & 1;
+       pconfig->y_in_range = (reg >> 2) & 1;
+       pconfig->c_out_range = (reg >> 3) & 1;
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_cproc_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32OR(CIFISP_CPROC_EN, CIF_C_PROC_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_cproc_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32AND(~CIFISP_CPROC_EN, CIF_C_PROC_CTRL);
+}
+
+static void cifisp_afc_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_afc_config *pconfig =
+               &isp_dev->meas_cfgs.last_or_new->afc_config;
+       int num_of_win = pconfig->num_afm_win, i;
+
+       /* Switch off to configure. Enabled during normal flow in frame isr. */
+       cifisp_iowrite32(0, CIF_ISP_AFM_CTRL);
+
+       for (i = 0; i < num_of_win; i++) {
+               cifisp_iowrite32(
+                       CIFISP_AFC_WINDOW_X(pconfig->afm_win[0].h_offs) |
+                       CIFISP_AFC_WINDOW_Y(pconfig->afm_win[0].v_offs),
+                       CIF_ISP_AFM_LT_A + i * 8);
+               cifisp_iowrite32(
+                       CIFISP_AFC_WINDOW_X(pconfig->afm_win[0].h_size +
+                       pconfig->afm_win[0].h_offs) |
+                       CIFISP_AFC_WINDOW_Y(pconfig->afm_win[0].v_size +
+                       pconfig->afm_win[0].v_offs),
+                       CIF_ISP_AFM_RB_A + i * 8);
+       }
+
+       cifisp_iowrite32(pconfig->thres, CIF_ISP_AFM_THRES);
+       cifisp_iowrite32(pconfig->var_shift, CIF_ISP_AFM_VAR_SHIFT);
+}
+
+/*****************************************************************************/
+static void cifisp_afc_en(struct cif_isp10_isp_dev *isp_dev)
+{
+       isp_dev->active_meas |= CIF_ISP_AFM_FIN;
+
+       cifisp_iowrite32(CIFISP_AFC_ENA, CIF_ISP_AFM_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_afc_end(struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32(CIFISP_AFC_DIS, CIF_ISP_AFM_CTRL);
+       isp_dev->active_meas &= ~CIF_ISP_AFM_FIN;
+}
+
+/*****************************************************************************/
+static void cifisp_get_afc_meas(struct cif_isp10_isp_dev *isp_dev,
+                               struct cifisp_stat_buffer *pbuf)
+{
+       pbuf->meas_type = CIFISP_STAT_AFM_FIN;
+
+       pbuf->params.af.window[0].sum =
+               cifisp_ioread32(CIF_ISP_AFM_SUM_A);
+       pbuf->params.af.window[0].lum =
+               cifisp_ioread32(CIF_ISP_AFM_LUM_A);
+       pbuf->params.af.window[1].sum =
+               cifisp_ioread32(CIF_ISP_AFM_SUM_B);
+       pbuf->params.af.window[1].lum =
+               cifisp_ioread32(CIF_ISP_AFM_LUM_B);
+       pbuf->params.af.window[2].sum =
+               cifisp_ioread32(CIF_ISP_AFM_SUM_C);
+       pbuf->params.af.window[2].lum =
+               cifisp_ioread32(CIF_ISP_AFM_LUM_C);
+}
+
+/* HISTOGRAM CALCULATION */
+/*****************************************************************************/
+static void cifisp_hst_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_hst_config *pconfig =
+               &isp_dev->meas_cfgs.last_or_new->hst_config;
+       unsigned int block_hsize, block_vsize;
+
+       cifisp_iowrite32(CIFISP_HIST_PREDIV_SET(pconfig->histogram_predivider),
+                     CIF_ISP_HIST_PROP);
+       cifisp_iowrite32(pconfig->meas_window.h_offs, CIF_ISP_HIST_H_OFFS);
+       cifisp_iowrite32(pconfig->meas_window.v_offs, CIF_ISP_HIST_V_OFFS);
+
+       block_hsize = pconfig->meas_window.h_size /
+               CIFISP_HIST_COLUMN_NUM - 1;
+       block_vsize = pconfig->meas_window.v_size /
+               CIFISP_HIST_ROW_NUM - 1;
+
+       cifisp_iowrite32(block_hsize, CIF_ISP_HIST_H_SIZE);
+       cifisp_iowrite32(block_vsize, CIF_ISP_HIST_V_SIZE);
+
+       cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[0],
+               pconfig->hist_weight[1], pconfig->hist_weight[2],
+               pconfig->hist_weight[3]), CIF_ISP_HIST_WEIGHT_00TO30);
+       cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[4],
+               pconfig->hist_weight[5], pconfig->hist_weight[6],
+               pconfig->hist_weight[7]), CIF_ISP_HIST_WEIGHT_40TO21);
+       cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[8],
+               pconfig->hist_weight[9], pconfig->hist_weight[10],
+               pconfig->hist_weight[11]), CIF_ISP_HIST_WEIGHT_31TO12);
+       cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[12],
+               pconfig->hist_weight[13], pconfig->hist_weight[14],
+               pconfig->hist_weight[15]), CIF_ISP_HIST_WEIGHT_22TO03);
+       cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[16],
+               pconfig->hist_weight[17], pconfig->hist_weight[18],
+               pconfig->hist_weight[19]), CIF_ISP_HIST_WEIGHT_13TO43);
+       cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[20],
+               pconfig->hist_weight[21], pconfig->hist_weight[22],
+               pconfig->hist_weight[23]), CIF_ISP_HIST_WEIGHT_04TO34);
+       cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[24],
+               0, 0, 0), CIF_ISP_HIST_WEIGHT_44);
+}
+
+static void cifisp_hst_en(struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_hst_config *pconfig =
+               &isp_dev->meas_cfgs.last_or_new->hst_config;
+
+       isp_dev->active_meas |= CIF_ISP_HIST_MEASURE_RDY;
+
+       cifisp_iowrite32OR(pconfig->mode,
+               CIF_ISP_HIST_PROP);
+}
+
+/*****************************************************************************/
+static void cifisp_hst_end(struct cif_isp10_isp_dev *isp_dev)
+{
+       /* Disable measurement */
+       cifisp_iowrite32(CIFISP_HISTOGRAM_MODE_DISABLE,
+               CIF_ISP_HIST_PROP);
+
+       isp_dev->active_meas &= ~CIF_ISP_HIST_MEASURE_RDY;
+}
+
+/*****************************************************************************/
+static void cifisp_get_hst_meas(const struct cif_isp10_isp_dev *isp_dev,
+                               struct cifisp_stat_buffer *pbuf)
+{
+       int i;
+
+       pbuf->meas_type |= CIFISP_STAT_HIST;
+       for (i = 0; i < CIFISP_HIST_BIN_N_MAX; i++) {
+               pbuf->params.hist.hist_bins[i] =
+                   cifisp_ioread32(CIF_ISP_HIST_BIN_0 + (i * 4));
+       }
+}
+
+/* IMAGE EFFECT */
+/*****************************************************************************/
+static void cifisp_ie_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_ie_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->ie_config;
+
+       switch (pconfig->effect) {
+       case V4L2_COLORFX_SET_CBCR:
+               cifisp_iowrite32(pconfig->eff_tint, CIF_IMG_EFF_TINT);
+               break;
+       /*
+        * Color selection is similar to water color(AQUA):
+        * grayscale + selected color w threshold
+        */
+       case V4L2_COLORFX_AQUA:
+               cifisp_iowrite32(pconfig->color_sel, CIF_IMG_EFF_COLOR_SEL);
+               break;
+       case V4L2_COLORFX_EMBOSS:
+               cifisp_iowrite32(pconfig->eff_mat_1, CIF_IMG_EFF_MAT_1);
+               cifisp_iowrite32(pconfig->eff_mat_2, CIF_IMG_EFF_MAT_2);
+               cifisp_iowrite32(pconfig->eff_mat_3, CIF_IMG_EFF_MAT_3);
+               break;
+       case V4L2_COLORFX_SKETCH:
+               cifisp_iowrite32(pconfig->eff_mat_3, CIF_IMG_EFF_MAT_3);
+               cifisp_iowrite32(pconfig->eff_mat_4, CIF_IMG_EFF_MAT_4);
+               cifisp_iowrite32(pconfig->eff_mat_5, CIF_IMG_EFF_MAT_5);
+               break;
+       default:
+               break;
+       }
+}
+
+static void cifisp_ie_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_ie_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->ie_config;
+       enum cif_isp10_image_effect effect;
+
+       switch (pconfig->effect) {
+       case V4L2_COLORFX_SEPIA:
+       case V4L2_COLORFX_SET_CBCR:
+               effect = CIF_ISP10_IE_SEPIA;
+               break;
+       case V4L2_COLORFX_BW:
+               effect = CIF_ISP10_IE_BW;
+               break;
+       case V4L2_COLORFX_NEGATIVE:
+               effect = CIF_ISP10_IE_NEGATIVE;
+               break;
+       case V4L2_COLORFX_EMBOSS:
+               effect = CIF_ISP10_IE_EMBOSS;
+               break;
+       case V4L2_COLORFX_SKETCH:
+               effect = CIF_ISP10_IE_SKETCH;
+               break;
+       case V4L2_COLORFX_AQUA:
+               effect = CIF_ISP10_IE_C_SEL;
+               break;
+       case V4L2_COLORFX_NONE:
+       default:
+               effect = CIF_ISP10_IE_NONE;
+               break;
+       }
+
+       if (effect < CIF_ISP10_IE_NONE) {
+               cifisp_iowrite32OR(CIF_ICCL_IE_CLK, CIF_ICCL);
+               cifisp_iowrite32(CIF_IMG_EFF_CTRL_ENABLE |
+                       effect << 1, CIF_IMG_EFF_CTRL);
+               cifisp_iowrite32OR(CIF_IMG_EFF_CTRL_CFG_UPD, CIF_IMG_EFF_CTRL);
+       } else if (effect == CIF_ISP10_IE_NONE) {
+               cifisp_iowrite32AND(~CIF_IMG_EFF_CTRL_ENABLE, CIF_IMG_EFF_CTRL);
+               cifisp_iowrite32AND(~CIF_ICCL_IE_CLK, CIF_ICCL);
+       }
+}
+
+static void cifisp_ie_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+       /* Disable measurement */
+       cifisp_iowrite32AND(~CIF_IMG_EFF_CTRL_ENABLE, CIF_IMG_EFF_CTRL);
+       cifisp_iowrite32AND(~CIF_ICCL_IE_CLK, CIF_ICCL);
+}
+
+static void cifisp_csm_config(const struct cif_isp10_isp_dev *isp_dev,
+       enum cif_isp10_pix_fmt_quantization quantization)
+{
+       const struct cifisp_ie_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->ie_config;
+
+       if ((quantization != CIF_ISP10_QUANTIZATION_FULL_RANGE) ||
+               ((pconfig->effect != V4L2_COLORFX_NONE) &&
+               CIFISP_MODULE_IS_EN(
+               isp_dev->other_cfgs.last_or_new->module_ens,
+               CIFISP_MODULE_CPROC))) {
+               /* Limit range conversion */
+               cifisp_iowrite32(0x21, CIF_ISP_CC_COEFF_0);
+               cifisp_iowrite32(0x40, CIF_ISP_CC_COEFF_1);
+               cifisp_iowrite32(0xd, CIF_ISP_CC_COEFF_2);
+               cifisp_iowrite32(0x1ed, CIF_ISP_CC_COEFF_3);
+               cifisp_iowrite32(0x1db, CIF_ISP_CC_COEFF_4);
+               cifisp_iowrite32(0x38, CIF_ISP_CC_COEFF_5);
+               cifisp_iowrite32(0x38, CIF_ISP_CC_COEFF_6);
+               cifisp_iowrite32(0x1d1, CIF_ISP_CC_COEFF_7);
+               cifisp_iowrite32(0x1f7, CIF_ISP_CC_COEFF_8);
+               cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA,
+                       CIF_ISP_CTRL);
+               cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA,
+                       CIF_ISP_CTRL);
+       } else {
+               cifisp_iowrite32(0x26, CIF_ISP_CC_COEFF_0);
+               cifisp_iowrite32(0x4b, CIF_ISP_CC_COEFF_1);
+               cifisp_iowrite32(0xf, CIF_ISP_CC_COEFF_2);
+               cifisp_iowrite32(0x1ea, CIF_ISP_CC_COEFF_3);
+               cifisp_iowrite32(0x1d6, CIF_ISP_CC_COEFF_4);
+               cifisp_iowrite32(0x40, CIF_ISP_CC_COEFF_5);
+               cifisp_iowrite32(0x40, CIF_ISP_CC_COEFF_6);
+               cifisp_iowrite32(0x1ca, CIF_ISP_CC_COEFF_7);
+               cifisp_iowrite32(0x1f6, CIF_ISP_CC_COEFF_8);
+               cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA,
+                       CIF_ISP_CTRL);
+               cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA,
+                       CIF_ISP_CTRL);
+       }
+}
+
+/* DPF */
+/*****************************************************************************/
+static void cifisp_dpf_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_dpf_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->dpf_config;
+       unsigned int isp_dpf_mode;
+       unsigned int i;
+       unsigned int spatial_coeff;
+
+       isp_dpf_mode = 0x00;
+
+       switch (pconfig->gain.mode) {
+       case CIFISP_DPF_GAIN_USAGE_DISABLED:
+               break;
+       case CIFISP_DPF_GAIN_USAGE_NF_GAINS:
+               isp_dpf_mode |= CIFISP_DPF_MODE_USE_NF_GAIN |
+                       CIFISP_DPF_MODE_AWB_GAIN_COMP;
+               break;
+       case CIFISP_DPF_GAIN_USAGE_LSC_GAINS:
+               isp_dpf_mode |= CIFISP_DPF_MODE_LSC_GAIN_COMP;
+               break;
+       case CIFISP_DPF_GAIN_USAGE_NF_LSC_GAINS:
+               isp_dpf_mode |= CIFISP_DPF_MODE_USE_NF_GAIN |
+                       CIFISP_DPF_MODE_AWB_GAIN_COMP |
+                       CIFISP_DPF_MODE_LSC_GAIN_COMP;
+               break;
+       case CIFISP_DPF_GAIN_USAGE_AWB_GAINS:
+               isp_dpf_mode |= CIFISP_DPF_MODE_AWB_GAIN_COMP;
+               break;
+       case CIFISP_DPF_GAIN_USAGE_AWB_LSC_GAINS:
+               isp_dpf_mode |= CIFISP_DPF_MODE_LSC_GAIN_COMP |
+                       CIFISP_DPF_MODE_AWB_GAIN_COMP;
+               break;
+       default:
+               break;
+       }
+
+       isp_dpf_mode |=
+       CIFISP_DPF_MODE_NLL_SEGMENTATION(pconfig->nll.scale_mode);
+       isp_dpf_mode |=
+       CIFISP_DPF_MODE_RB_FLTSIZE(pconfig->rb_flt.fltsize);
+
+       isp_dpf_mode |= (pconfig->rb_flt.r_enable) ?
+               CIFISP_DPF_MODE_R_FLT_EN : CIFISP_DPF_MODE_R_FLT_DIS;
+       isp_dpf_mode |= (pconfig->rb_flt.b_enable) ?
+               CIFISP_DPF_MODE_B_FLT_EN : CIFISP_DPF_MODE_B_FLT_DIS;
+       isp_dpf_mode |= (pconfig->g_flt.gb_enable) ?
+               CIFISP_DPF_MODE_GB_FLT_EN : CIFISP_DPF_MODE_GB_FLT_DIS;
+       isp_dpf_mode |= (pconfig->g_flt.gr_enable) ?
+               CIFISP_DPF_MODE_GR_FLT_EN : CIFISP_DPF_MODE_GR_FLT_DIS;
+
+       cifisp_iowrite32(isp_dpf_mode, CIF_ISP_DPF_MODE);
+       cifisp_iowrite32(pconfig->gain.nf_b_gain, CIF_ISP_DPF_NF_GAIN_B);
+       cifisp_iowrite32(pconfig->gain.nf_r_gain, CIF_ISP_DPF_NF_GAIN_R);
+       cifisp_iowrite32(pconfig->gain.nf_gb_gain, CIF_ISP_DPF_NF_GAIN_GB);
+       cifisp_iowrite32(pconfig->gain.nf_gr_gain, CIF_ISP_DPF_NF_GAIN_GR);
+
+       for (i = 0; i < CIFISP_DPF_MAX_NLF_COEFFS; i++) {
+               cifisp_iowrite32(pconfig->nll.coeff[i],
+                       CIF_ISP_DPF_NULL_COEFF_0 + i * 4);
+       }
+
+       spatial_coeff = pconfig->g_flt.spatial_coeff[0] |
+               ((unsigned int)pconfig->g_flt.spatial_coeff[1] << 8) |
+               ((unsigned int)pconfig->g_flt.spatial_coeff[2] << 16) |
+               ((unsigned int)pconfig->g_flt.spatial_coeff[3] << 24);
+       cifisp_iowrite32(spatial_coeff, CIF_ISP_DPF_S_WEIGHT_G_1_4);
+       spatial_coeff = pconfig->g_flt.spatial_coeff[4] |
+               ((unsigned int)pconfig->g_flt.spatial_coeff[5] << 8);
+       cifisp_iowrite32(spatial_coeff, CIF_ISP_DPF_S_WEIGHT_G_5_6);
+       spatial_coeff = pconfig->rb_flt.spatial_coeff[0] |
+               ((unsigned int)pconfig->rb_flt.spatial_coeff[1] << 8) |
+               ((unsigned int)pconfig->rb_flt.spatial_coeff[2] << 16) |
+               ((unsigned int)pconfig->rb_flt.spatial_coeff[3] << 24);
+       cifisp_iowrite32(spatial_coeff, CIF_ISP_DPF_S_WEIGHT_RB_1_4);
+       spatial_coeff = pconfig->rb_flt.spatial_coeff[4] |
+               ((unsigned int)pconfig->rb_flt.spatial_coeff[5] << 8);
+       cifisp_iowrite32(spatial_coeff, CIF_ISP_DPF_S_WEIGHT_RB_5_6);
+}
+
+static void cifisp_dpf_strength_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+       const struct cifisp_dpf_strength_config *pconfig =
+               &isp_dev->other_cfgs.last_or_new->dpf_strength_config;
+
+       cifisp_iowrite32(pconfig->b, CIF_ISP_DPF_STRENGTH_B);
+       cifisp_iowrite32(pconfig->g, CIF_ISP_DPF_STRENGTH_G);
+       cifisp_iowrite32(pconfig->r, CIF_ISP_DPF_STRENGTH_R);
+}
+
+static void cifisp_dpf_en(struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32OR(CIFISP_DPF_MODE_EN,
+               CIF_ISP_DPF_MODE);
+}
+
+static void cifisp_dpf_end(struct cif_isp10_isp_dev *isp_dev)
+{
+       cifisp_iowrite32AND(~CIFISP_DPF_MODE_EN,
+               CIF_ISP_DPF_MODE);
+}
+
+/* ================================QUEUE OPS ================== */
+static int cifisp_stat_vbq_setup(struct videobuf_queue *vq,
+                                unsigned int *cnt, unsigned int *size)
+{
+       *size = sizeof(struct cifisp_stat_buffer);
+
+       return 0;
+}
+
+static void cifisp_stat_vbq_release(struct videobuf_queue *vq,
+                                   struct videobuf_buffer *vb)
+{
+       CIFISP_DPRINT(CIFISP_DEBUG, "Releasing buffer entry!\n");
+
+       videobuf_waiton(vq, vb, 0, 0);
+
+       videobuf_vmalloc_free(vb);
+
+       CIFISP_DPRINT(CIFISP_DEBUG, "Releasing buffer exit!\n");
+}
+
+static int cifisp_stat_vbq_prepare(struct videobuf_queue *vq,
+                                  struct videobuf_buffer *vb,
+                                  enum v4l2_field field)
+{
+       int err = 0;
+
+       vb->size = sizeof(struct cifisp_stat_buffer);
+       vb->width = 0;
+       vb->height = 0;
+       vb->field = field;
+
+       if (vb->state == VIDEOBUF_NEEDS_INIT)
+               err = videobuf_iolock(vq, vb, NULL);
+
+       if (!err)
+               vb->state = VIDEOBUF_PREPARED;
+       else
+               cifisp_stat_vbq_release(vq, vb);
+
+       return err;
+}
+
+static void cifisp_stat_vbq_queue(struct videobuf_queue *vq,
+                                 struct videobuf_buffer *vb)
+{
+       struct cif_isp10_isp_dev *isp_dev = vq->priv_data;
+
+       vb->state = VIDEOBUF_QUEUED;
+
+       CIFISP_DPRINT(CIFISP_DEBUG, "Queueing stat buffer!\n");
+
+       list_add_tail(&vb->queue, &isp_dev->stat);
+}
+
+/* Queue Ops */
+static struct videobuf_queue_ops cifisp_stat_qops = {
+       .buf_setup = cifisp_stat_vbq_setup,
+       .buf_prepare = cifisp_stat_vbq_prepare,
+       .buf_queue = cifisp_stat_vbq_queue,
+       .buf_release = cifisp_stat_vbq_release,
+};
+
+/* ================== IOCTL implementation ========================= */
+static int cifisp_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *p)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+                     " %s: %s: p->type %d p->count %d\n",
+                     ISP_VDEV_NAME, __func__, p->type, p->count);
+
+       return videobuf_reqbufs(&isp_dev->vbq_stat, p);
+}
+
+static int cifisp_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+                     " %s: %s: p->type %d p->index %d\n",
+                     ISP_VDEV_NAME, __func__, p->type, p->index);
+
+       return videobuf_querybuf(&isp_dev->vbq_stat, p);
+}
+
+static int cifisp_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+                     " %s: %s: p->type %d p->index %d\n",
+                     ISP_VDEV_NAME, __func__, p->type, p->index);
+
+       return videobuf_qbuf(&isp_dev->vbq_stat, p);
+}
+
+/* ========================================================== */
+
+static int cifisp_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+                     " %s: %s: p->type %d p->index %d\n",
+                     ISP_VDEV_NAME, __func__, p->type, p->index);
+
+       return videobuf_dqbuf(&isp_dev->vbq_stat, p,
+                             file->f_flags & O_NONBLOCK);
+}
+
+static int cifisp_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       int ret = videobuf_streamon(&isp_dev->vbq_stat);
+
+       if (ret == 0)
+               isp_dev->streamon = true;
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+                     " %s: %s: ret %d\n", ISP_VDEV_NAME, __func__, ret);
+
+       return ret;
+}
+
+/* ========================================================== */
+static int cifisp_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+       int ret;
+
+       drain_workqueue(isp_dev->readout_wq);
+
+       ret = videobuf_streamoff(&isp_dev->vbq_stat);
+
+       if (ret == 0)
+               isp_dev->streamon = false;
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+               " %s: %s: ret %d\n", ISP_VDEV_NAME, __func__, ret);
+
+       return ret;
+}
+
+static int cifisp_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
+{
+       int ret;
+
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       switch (vc->id) {
+       case V4L2_CID_CIFISP_DPCC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_DPCC);
+               break;
+       case V4L2_CID_CIFISP_BLS:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_BLS);
+               break;
+       case V4L2_CID_CIFISP_SDG:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_SDG);
+               break;
+       case V4L2_CID_CIFISP_LSC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_LSC);
+               break;
+       case V4L2_CID_CIFISP_AWB_MEAS:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_AWB);
+               break;
+       case V4L2_CID_CIFISP_AWB_GAIN:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_AWB_GAIN);
+               break;
+       case V4L2_CID_CIFISP_FLT:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_FLT);
+               break;
+       case V4L2_CID_CIFISP_BDM:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_BDM);
+               break;
+       case V4L2_CID_CIFISP_CTK:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_CTK);
+               break;
+       case V4L2_CID_CIFISP_GOC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_GOC);
+               break;
+       case V4L2_CID_CIFISP_HST:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_HST);
+               break;
+       case V4L2_CID_CIFISP_AEC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_AEC);
+               break;
+       case V4L2_CID_CIFISP_CPROC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_CPROC);
+               break;
+       case V4L2_CID_CIFISP_AFC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_AFC);
+               break;
+       case V4L2_CID_CIFISP_IE:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_IE);
+               break;
+       case V4L2_CID_CIFISP_DPF:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _GET_,
+                       &vc->value,
+                       CIFISP_MODULE_DPF);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int cifisp_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+       int ret;
+
+       switch (vc->id) {
+       case V4L2_CID_CIFISP_DPCC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_DPCC);
+               break;
+       case V4L2_CID_CIFISP_BLS:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_BLS);
+               break;
+       case V4L2_CID_CIFISP_SDG:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_SDG);
+               break;
+       case V4L2_CID_CIFISP_LSC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_LSC);
+               break;
+       case V4L2_CID_CIFISP_AWB_MEAS:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_AWB);
+               break;
+       case V4L2_CID_CIFISP_AWB_GAIN:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_AWB_GAIN);
+               break;
+       case V4L2_CID_CIFISP_FLT:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_FLT);
+               break;
+       case V4L2_CID_CIFISP_BDM:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_BDM);
+               break;
+       case V4L2_CID_CIFISP_CTK:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_CTK);
+               break;
+       case V4L2_CID_CIFISP_GOC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_GOC);
+               break;
+       case V4L2_CID_CIFISP_HST:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_HST);
+                       break;
+       case V4L2_CID_CIFISP_AEC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_AEC);
+               break;
+       case V4L2_CID_CIFISP_CPROC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_CPROC);
+               break;
+       case V4L2_CID_CIFISP_AFC:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_AFC);
+               break;
+       case V4L2_CID_CIFISP_IE:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_IE);
+               break;
+       case V4L2_CID_CIFISP_DPF:
+               ret = cifisp_module_enable(
+                       isp_dev,
+                       _SET_,
+                       &vc->value,
+                       CIFISP_MODULE_DPF);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static long cifisp_ioctl_default(struct file *file,
+        void *fh, bool valid_prio, unsigned int cmd, void *arg)
+{
+       struct cif_isp10_isp_dev *isp = video_get_drvdata(video_devdata(file));
+       long ret;
+
+       switch (cmd) {
+       case CIFISP_IOC_G_DPCC:
+               ret = cifisp_dpcc_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_DPCC:
+               ret = cifisp_dpcc_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_BLS:
+               ret = cifisp_bls_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_BLS:
+               ret = cifisp_bls_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_SDG:
+               ret = cifisp_sdg_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_SDG:
+               ret = cifisp_sdg_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_LSC:
+               ret = cifisp_lsc_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_LSC:
+               ret = cifisp_lsc_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_AWB_MEAS:
+               ret = cifisp_awb_meas_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_AWB_MEAS:
+               ret = cifisp_awb_meas_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_AWB_GAIN:
+               ret = cifisp_awb_gain_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_AWB_GAIN:
+               ret = cifisp_awb_gain_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_FLT:
+               ret = cifisp_flt_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_FLT:
+               ret = cifisp_flt_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_BDM:
+               ret = cifisp_bdm_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_BDM:
+               ret = cifisp_bdm_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_CTK:
+               ret = cifisp_ctk_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_CTK:
+               ret = cifisp_ctk_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_GOC:
+               ret = cifisp_goc_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_GOC:
+               ret = cifisp_goc_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_HST:
+               ret = cifisp_hst_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_HST:
+               ret = cifisp_hst_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_AEC:
+               ret = cifisp_aec_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_AEC:
+               ret = cifisp_aec_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_CPROC:
+               ret = cifisp_cproc_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_CPROC:
+               ret = cifisp_cproc_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_AFC:
+               ret = cifisp_afc_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_AFC:
+               ret = cifisp_afc_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_IE:
+               ret = cifisp_ie_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_IE:
+               ret = cifisp_ie_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_DPF:
+               ret = cifisp_dpf_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_DPF:
+               ret = cifisp_dpf_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_DPF_STRENGTH:
+               ret = cifisp_dpf_strength_param(isp, _GET_, arg);
+               break;
+       case CIFISP_IOC_S_DPF_STRENGTH:
+               ret = cifisp_dpf_strength_param(isp, _SET_, arg);
+               break;
+       case CIFISP_IOC_G_LAST_CONFIG:
+               ret = cifisp_last_capture_config(arg);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int cifisp_g_fmt_vid_cap(struct file *file, void *fh,
+                               struct v4l2_format *f)
+{
+       /*
+        * Dummy function needed to allow allocation of
+        * buffers on this device
+        */
+       return 0;
+}
+
+static int cifisp_querycap(struct file *file,
+                        void *priv, struct v4l2_capability *cap)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cif_isp10_isp_dev *isp_dev = video_get_drvdata(vdev);
+
+       strcpy(cap->driver, DRIVER_NAME);
+       strlcpy(cap->card, vdev->name, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+               "platform:" DRIVER_NAME "-%03i",
+               *isp_dev->dev_id);
+
+       cap->capabilities = V4L2_CAP_DEVICE_CAPS;
+       cap->device_caps = V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+/* ISP video device IOCTLs */
+static const struct v4l2_ioctl_ops cifisp_ioctl = {
+       .vidioc_reqbufs = cifisp_reqbufs,
+       .vidioc_querybuf = cifisp_querybuf,
+       .vidioc_qbuf = cifisp_qbuf,
+       .vidioc_dqbuf = cifisp_dqbuf,
+       .vidioc_streamon = cifisp_streamon,
+       .vidioc_streamoff = cifisp_streamoff,
+       .vidioc_g_ctrl = cifisp_g_ctrl,
+       .vidioc_s_ctrl = cifisp_s_ctrl,
+       .vidioc_default = cifisp_ioctl_default,
+       .vidioc_g_fmt_vid_cap = cifisp_g_fmt_vid_cap,
+       .vidioc_querycap = cifisp_querycap
+};
+
+/* ======================================================== */
+
+static unsigned int cifisp_poll(struct file *file,
+                               struct poll_table_struct *wait)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+       unsigned int ret;
+
+       ret = videobuf_poll_stream(file, &isp_dev->vbq_stat, wait);
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+                     "Polling on vbq_stat buffer %d\n", ret);
+
+       return ret;
+}
+
+/* ======================================================== */
+static int cifisp_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       return videobuf_mmap_mapper(&isp_dev->vbq_stat, vma);
+}
+
+/* ddl@rock-chips.com: v1.0.8 */
+static int cifisp_reset(struct file *file)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       memset(isp_dev->other_cfgs.cfgs, 0, sizeof(isp_dev->other_cfgs.cfgs));
+       memset(isp_dev->meas_cfgs.cfgs, 0, sizeof(isp_dev->meas_cfgs.cfgs));
+
+       isp_dev->other_cfgs.last_or_new = &isp_dev->other_cfgs.cfgs[0];
+       isp_dev->other_cfgs.curr = &isp_dev->other_cfgs.cfgs[1];
+       isp_dev->other_cfgs.module_updates = 0;
+
+       isp_dev->meas_cfgs.last_or_new = &isp_dev->meas_cfgs.cfgs[0];
+       isp_dev->meas_cfgs.curr = &isp_dev->meas_cfgs.cfgs[1];
+       isp_dev->meas_cfgs.module_updates = 0;
+       isp_dev->active_lsc_width = 0;
+       isp_dev->active_lsc_height = 0;
+
+       isp_dev->streamon = false;
+       isp_dev->active_meas = 0;
+       isp_dev->frame_id = 0;
+       isp_dev->cif_ism_cropping = false;
+       return 0;
+}
+
+static int cifisp_open(struct file *file)
+{
+       CIFISP_DPRINT(CIFISP_DEBUG, "cifisp_open\n");
+
+       cifisp_reset(file);
+
+       return 0;
+}
+
+static int cifisp_close(struct file *file)
+{
+       struct cif_isp10_isp_dev *isp_dev =
+               video_get_drvdata(video_devdata(file));
+
+       CIFISP_DPRINT(CIFISP_DEBUG, "cifisp_close\n");
+
+       videobuf_stop(&isp_dev->vbq_stat);
+       videobuf_mmap_free(&isp_dev->vbq_stat);
+
+       /* cifisp_reset(file); */
+       return 0;
+}
+
+struct v4l2_file_operations cifisp_fops = {
+       .mmap = cifisp_mmap,
+       .unlocked_ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl32 = video_ioctl2,
+#endif
+       .poll = cifisp_poll,
+       .open = cifisp_open,
+       .release = cifisp_close
+};
+
+static void cifisp_release(struct video_device *vdev)
+{
+       struct cif_isp10_isp_dev *isp_dev = video_get_drvdata(vdev);
+
+       CIFISP_DPRINT(CIFISP_DEBUG, "cifisp_release\n");
+       video_device_release(vdev);
+       destroy_workqueue(isp_dev->readout_wq);
+}
+
+/************************************************************/
+int register_cifisp_device(struct cif_isp10_isp_dev *isp_dev,
+       struct video_device *vdev_cifisp,
+       struct v4l2_device *v4l2_dev,
+       void __iomem *cif_reg_baseaddress)
+{
+       isp_dev->base_addr = cif_reg_baseaddress;
+       WARN_ON(!(isp_dev->base_addr));
+
+       INIT_LIST_HEAD(&isp_dev->stat);
+       spin_lock_init(&isp_dev->irq_lock);
+       spin_lock_init(&isp_dev->config_lock);
+       strlcpy(vdev_cifisp->name, ISP_VDEV_NAME, sizeof(vdev_cifisp->name));
+       vdev_cifisp->vfl_type = V4L2_CAP_VIDEO_CAPTURE;
+       video_set_drvdata(vdev_cifisp, isp_dev);
+       vdev_cifisp->ioctl_ops = &cifisp_ioctl;
+       vdev_cifisp->fops = &cifisp_fops;
+
+       /*
+        * This might not release all resources,
+        * but unregistering is anyway not going to happen.
+        */
+       vdev_cifisp->release = cifisp_release;
+       mutex_init(&isp_dev->mutex);
+       /*
+        * Provide a mutex to v4l2 core. It will be used
+        * to protect all fops and v4l2 ioctls.
+        */
+       vdev_cifisp->lock = &isp_dev->mutex;
+       vdev_cifisp->v4l2_dev = v4l2_dev;
+
+       videobuf_queue_vmalloc_init(
+               &isp_dev->vbq_stat,
+               &cifisp_stat_qops,
+               NULL,
+               &isp_dev->irq_lock,
+               V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               V4L2_FIELD_NONE,
+               sizeof(struct videobuf_buffer),
+               isp_dev,
+               NULL);  /* ext_lock: NULL */
+
+       if (video_register_device(vdev_cifisp, VFL_TYPE_GRABBER, -1) < 0) {
+               dev_err(&vdev_cifisp->dev,
+                       "could not register Video for Linux device\n");
+               return -ENODEV;
+       }
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+               "%s: CIFISP vdev minor =  %d\n",
+               __func__, vdev_cifisp->minor);
+
+       isp_dev->readout_wq =
+               alloc_workqueue("measurement_queue",
+                       WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+
+       if (!isp_dev->readout_wq)
+               return -ENOMEM;
+
+       isp_dev->v_blanking_us = CIFISP_MODULE_DEFAULT_VBLANKING_TIME;
+
+       return 0;
+}
+
+void unregister_cifisp_device(struct video_device *vdev_cifisp)
+{
+       if (!IS_ERR_OR_NULL(vdev_cifisp))
+               video_unregister_device(vdev_cifisp);
+}
+
+static void cifisp_dump_reg(struct cif_isp10_isp_dev *isp_dev, int level)
+{
+#ifdef CIFISP_DEBUG_REG
+       if (isp_dev->dpcc_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_DPCC, level);
+
+       if (isp_dev->lsc_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_LSC, level);
+
+       if (isp_dev->bls_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_BLS, level);
+
+       if (isp_dev->sdg_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_SDG, level);
+
+       if (isp_dev->goc_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_GOC, level);
+
+       if (isp_dev->bdm_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_BDM, level);
+
+       if (isp_dev->flt_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_FLT, level);
+
+       if (isp_dev->awb_meas_en || isp_dev->awb_gain_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_AWB, level);
+
+       if (isp_dev->aec_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_AEC, level);
+
+       if (isp_dev->ctk_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_CTK, level);
+
+       if (isp_dev->cproc_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_CPROC, level);
+
+       if (isp_dev->afc_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_AFC, level);
+
+       if (isp_dev->hst_en)
+               cifisp_reg_dump(isp_dev, CIFISP_MODULE_HST, level);
+#endif
+}
+
+static inline void cifisp_meas_config_swap(
+       struct cif_isp10_isp_dev *isp_dev)
+{
+       struct cifisp_isp_meas_cfg *new_cfg;
+
+       new_cfg = isp_dev->meas_cfgs.last_or_new;
+       new_cfg->s_frame_id = isp_dev->frame_id;
+       isp_dev->meas_cfgs.last_or_new =
+               isp_dev->meas_cfgs.curr;
+       isp_dev->meas_cfgs.curr = new_cfg;
+}
+
+static inline void cifisp_other_config_swap(
+       struct cif_isp10_isp_dev *isp_dev)
+{
+       struct cifisp_isp_other_cfg *new_cfg;
+
+       new_cfg = isp_dev->other_cfgs.last_or_new;
+       new_cfg->s_frame_id = isp_dev->frame_id;
+       isp_dev->other_cfgs.last_or_new =
+               isp_dev->other_cfgs.curr;
+       isp_dev->other_cfgs.curr = new_cfg;
+}
+
+/* Not called when the camera active, thus not isr protection. */
+void cifisp_configure_isp(
+       struct cif_isp10_isp_dev *isp_dev,
+       enum cif_isp10_pix_fmt in_pix_fmt,
+       enum cif_isp10_pix_fmt_quantization quantization)
+{
+       unsigned int *other_ens, *other_updates;
+       unsigned int *meas_ens, *meas_updates;
+
+       CIFISP_DPRINT(CIFISP_DEBUG, "%s\n", __func__);
+
+       mutex_lock(&isp_dev->mutex);
+       spin_lock(&isp_dev->config_lock);
+
+       other_ens = &isp_dev->other_cfgs.last_or_new->module_ens;
+       other_updates = &isp_dev->other_cfgs.module_updates;
+       meas_ens = &isp_dev->meas_cfgs.last_or_new->module_ens;
+       meas_updates = &isp_dev->meas_cfgs.module_updates;
+       isp_dev->quantization = quantization;
+       if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(in_pix_fmt)) {
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_DPCC)) {
+                       cifisp_dpcc_config(isp_dev);
+                       cifisp_dpcc_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_DPCC);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_LSC)) {
+                       if (cifisp_lsc_config(isp_dev))
+                               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                                       CIFISP_MODULE_LSC);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_BLS)) {
+                       cifisp_bls_config(isp_dev);
+                       cifisp_bls_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_BLS);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_SDG)) {
+                       cifisp_sdg_config(isp_dev);
+                       cifisp_sdg_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_SDG);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_GOC)) {
+                       cifisp_goc_config(isp_dev);
+                       cifisp_goc_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_GOC);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_BDM)) {
+                       cifisp_bdm_config(isp_dev);
+                       cifisp_bdm_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_BDM);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_FLT)) {
+                       cifisp_flt_config(isp_dev);
+                       cifisp_flt_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_FLT);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_AWB_GAIN)) {
+                       cifisp_awb_gain_config(isp_dev);
+                       cifisp_awb_gain_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_AWB_GAIN);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_CTK)) {
+                       cifisp_ctk_config(isp_dev);
+                       cifisp_ctk_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_CTK);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_CPROC)) {
+                       cifisp_cproc_config(isp_dev, quantization);
+                       cifisp_cproc_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_CPROC);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_IE)) {
+                       cifisp_ie_config(isp_dev);
+                       cifisp_ie_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_IE);
+               }
+
+               cifisp_csm_config(isp_dev, quantization);
+
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_DPF)) {
+                       cifisp_dpf_config(isp_dev);
+                       cifisp_dpf_strength_config(isp_dev);
+                       cifisp_dpf_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_DPF | CIFISP_MODULE_DPF_STRENGTH);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*meas_ens, CIFISP_MODULE_AFC)) {
+                       cifisp_afc_config(isp_dev);
+                       cifisp_afc_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+                               CIFISP_MODULE_AFC);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*meas_ens, CIFISP_MODULE_AWB)) {
+                       cifisp_awb_meas_config(isp_dev);
+                       cifisp_awb_meas_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+                               CIFISP_MODULE_AWB);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*meas_ens, CIFISP_MODULE_AEC)) {
+                       cifisp_aec_config(isp_dev);
+                       cifisp_aec_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+                               CIFISP_MODULE_AEC);
+               }
+
+               if (CIFISP_MODULE_IS_EN(*meas_ens, CIFISP_MODULE_HST)) {
+                       cifisp_hst_config(isp_dev);
+                       cifisp_hst_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+                               CIFISP_MODULE_HST);
+               }
+       } else {
+               /* Disable modules for yuv */
+               cifisp_dpcc_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_DPCC);
+
+               cifisp_lsc_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_LSC);
+
+               cifisp_bls_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_BLS);
+
+               cifisp_sdg_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_SDG);
+
+               cifisp_goc_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_GOC);
+
+               cifisp_bdm_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_BDM);
+
+               cifisp_flt_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_FLT);
+
+               cifisp_awb_meas_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+                               CIFISP_MODULE_AWB);
+
+               cifisp_awb_gain_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_AWB_GAIN);
+
+               cifisp_aec_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+                               CIFISP_MODULE_AEC);
+
+               cifisp_ctk_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_CTK);
+
+               cifisp_dpf_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_DPF);
+
+               /* cproc can be used for yuv in reduced range */
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_CPROC)) {
+                       cifisp_cproc_config(isp_dev, false);
+                       cifisp_cproc_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_CPROC);
+               }
+
+               cifisp_hst_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+                               CIFISP_MODULE_HST);
+
+               cifisp_afc_end(isp_dev);
+               CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+                               CIFISP_MODULE_AFC);
+               /* ie can be used for yuv */
+               if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_IE)) {
+                       cifisp_ie_config(isp_dev);
+                       cifisp_ie_en(isp_dev);
+                       CIFISP_MODULE_CLR_UPDATE(*other_updates,
+                               CIFISP_MODULE_IE);
+               } else {
+                       cifisp_ie_end(isp_dev);
+               }
+       }
+
+       cifisp_dump_reg(isp_dev, CIFISP_DEBUG);
+
+       cifisp_meas_config_swap(isp_dev);
+       cifisp_other_config_swap(isp_dev);
+
+       memcpy(isp_dev->other_cfgs.last_or_new,
+               isp_dev->other_cfgs.curr,
+               sizeof(struct cifisp_isp_other_cfg));
+       memcpy(isp_dev->meas_cfgs.last_or_new,
+               isp_dev->meas_cfgs.curr,
+               sizeof(struct cifisp_isp_meas_cfg));
+
+       spin_unlock(&isp_dev->config_lock);
+       mutex_unlock(&isp_dev->mutex);
+}
+
+void cifisp_frame_in(
+       struct cif_isp10_isp_dev *isp_dev,
+       const struct timeval *fi_t)
+{
+       /* Called in an interrupt context. */
+       isp_dev->fi_t = *fi_t;
+}
+
+void cifisp_v_start(
+       struct cif_isp10_isp_dev *isp_dev,
+       const struct timeval *vs_t)
+{
+       /* Called in an interrupt context. */
+       isp_dev->frame_id += 2;
+       isp_dev->vs_t = *vs_t;
+}
+
+/* Not called when the camera active, thus not isr protection. */
+void cifisp_disable_isp(struct cif_isp10_isp_dev *isp_dev)
+{
+       CIFISP_DPRINT(CIFISP_DEBUG, "%s\n", __func__);
+
+       mutex_lock(&isp_dev->mutex);
+
+       cifisp_dpcc_end(isp_dev);
+       cifisp_lsc_end(isp_dev);
+       cifisp_bls_end(isp_dev);
+       cifisp_sdg_end(isp_dev);
+       cifisp_goc_end(isp_dev);
+       cifisp_bdm_end(isp_dev);
+       cifisp_flt_end(isp_dev);
+       cifisp_awb_meas_end(isp_dev);
+       cifisp_awb_gain_end(isp_dev);
+       cifisp_aec_end(isp_dev);
+       cifisp_ctk_end(isp_dev);
+       cifisp_cproc_end(isp_dev);
+       cifisp_hst_end(isp_dev);
+       cifisp_afc_end(isp_dev);
+       cifisp_ie_end(isp_dev);
+       cifisp_dpf_end(isp_dev);
+
+       /*
+        * Isp isn't active, isp interrupt isn't enabled, spin_lock is enough;
+        */
+       spin_lock(&isp_dev->config_lock);
+
+       isp_dev->other_cfgs.last_or_new->module_ens = 0;
+       isp_dev->meas_cfgs.last_or_new->module_ens = 0;
+
+       /*
+        * 1. Swap last_or_new and curr pointer;
+        * 2. Sync last_or_new and curr configuration;
+        */
+       cifisp_meas_config_swap(isp_dev);
+       cifisp_other_config_swap(isp_dev);
+
+       memcpy(isp_dev->other_cfgs.last_or_new,
+               isp_dev->other_cfgs.curr,
+               sizeof(struct cifisp_isp_other_cfg));
+       memcpy(isp_dev->meas_cfgs.last_or_new,
+               isp_dev->meas_cfgs.curr,
+               sizeof(struct cifisp_isp_meas_cfg));
+
+       spin_unlock(&isp_dev->config_lock);
+
+       mutex_unlock(&isp_dev->mutex);
+}
+
+static void cifisp_send_measurement(
+       struct cif_isp10_isp_dev *isp_dev,
+       struct cif_isp10_isp_readout_work *meas_work)
+{
+       unsigned long lock_flags = 0;
+       struct videobuf_buffer *vb = NULL;
+       unsigned int active_meas = isp_dev->active_meas;
+       struct cifisp_stat_buffer *stat_buf;
+       struct cif_isp10_device *cif_dev =
+               container_of(isp_dev, struct cif_isp10_device, isp_dev);
+
+       spin_lock_irqsave(&isp_dev->irq_lock, lock_flags);
+       if (isp_dev->frame_id != meas_work->frame_id) {
+               spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+               CIFISP_DPRINT(CIFISP_ERROR,
+                       "Measurement late(%d, %d)\n",
+                       isp_dev->frame_id,
+                       meas_work->frame_id);
+               goto end;
+       }
+
+       if (!list_empty(&isp_dev->stat)) {
+               vb = list_first_entry(&isp_dev->stat,
+               struct videobuf_buffer, queue);
+       } else {
+               spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "Not enought measurement bufs\n");
+               goto end;
+       }
+
+       spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+       vb->state = VIDEOBUF_ACTIVE;
+
+       stat_buf = (struct cifisp_stat_buffer *)videobuf_to_vmalloc(vb);
+       memset(stat_buf, 0x00, sizeof(struct cifisp_stat_buffer));
+
+       if (active_meas & CIF_ISP_AWB_DONE)
+               cifisp_get_awb_meas(isp_dev, stat_buf);
+
+       if (active_meas & CIF_ISP_AFM_FIN)
+               cifisp_get_afc_meas(isp_dev, stat_buf);
+
+       if (active_meas & CIF_ISP_EXP_END) {
+               cifisp_get_aec_meas(isp_dev, stat_buf);
+               cifisp_bls_get_meas(isp_dev, stat_buf);
+       }
+
+       if (active_meas & CIF_ISP_HIST_MEASURE_RDY)
+               cifisp_get_hst_meas(isp_dev, stat_buf);
+
+       spin_lock_irqsave(&isp_dev->irq_lock, lock_flags);
+
+       if (isp_dev->frame_id != meas_work->frame_id) {
+               spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+               CIFISP_DPRINT(CIFISP_ERROR,
+                       "Measurement late(%d, %d)\n",
+                       isp_dev->frame_id,
+                       meas_work->frame_id);
+               goto end;
+       }
+
+       vb->ts = isp_dev->vs_t;
+       list_del(&vb->queue);
+       spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+
+       if (active_meas & CIF_ISP_AWB_DONE) {
+               memcpy(&isp_dev->meas_stats.stat.params.awb,
+                       &stat_buf->params.awb,
+                       sizeof(struct cifisp_awb_stat));
+               isp_dev->meas_stats.stat.meas_type |= CIFISP_STAT_AWB;
+       }
+       if (active_meas & CIF_ISP_AFM_FIN) {
+               memcpy(&isp_dev->meas_stats.stat.params.af,
+                       &stat_buf->params.af,
+                       sizeof(struct cifisp_af_stat));
+               isp_dev->meas_stats.stat.meas_type |= CIFISP_STAT_AFM_FIN;
+       }
+       if (active_meas & CIF_ISP_EXP_END) {
+               cif_isp10_sensor_mode_data_sync(cif_dev,
+                       meas_work->frame_id,
+                       &stat_buf->sensor_mode);
+               memcpy(&isp_dev->meas_stats.stat.params.ae,
+                       &stat_buf->params.ae,
+                       sizeof(struct cifisp_ae_stat));
+               memcpy(&isp_dev->meas_stats.stat.sensor_mode,
+                       &stat_buf->sensor_mode,
+                       sizeof(struct isp_supplemental_sensor_mode_data));
+
+               isp_dev->meas_stats.stat.meas_type |= CIFISP_STAT_AUTOEXP;
+       }
+       if (active_meas & CIF_ISP_HIST_MEASURE_RDY) {
+               memcpy(&isp_dev->meas_stats.stat.params.hist,
+                       &stat_buf->params.hist,
+                       sizeof(struct cifisp_hist_stat));
+               isp_dev->meas_stats.stat.meas_type |= CIFISP_STAT_HIST;
+       }
+       isp_dev->meas_stats.g_frame_id = meas_work->frame_id;
+
+       vb->field_count = meas_work->frame_id;
+       vb->state = VIDEOBUF_DONE;
+       wake_up(&vb->done);
+
+       CIFISP_DPRINT(CIFISP_DEBUG,
+               "Measurement done(%d, %d)\n",
+               vb->field_count,
+               vb->i);
+       vb = NULL;
+end:
+
+       if (vb && (vb->state == VIDEOBUF_ACTIVE))
+               vb->state = VIDEOBUF_QUEUED;
+}
+
+void cifisp_isp_readout_work(struct work_struct *work)
+{
+       struct cif_isp10_isp_readout_work *readout_work =
+               (struct cif_isp10_isp_readout_work *)work;
+       struct cif_isp10_isp_dev *isp_dev =
+               readout_work->isp_dev;
+       struct cif_isp10_device *cif_dev =
+               container_of(isp_dev, struct cif_isp10_device, isp_dev);
+       unsigned long int lock_flags;
+
+       if (!isp_dev->streamon)
+               return;
+
+       switch (readout_work->readout) {
+       case CIF_ISP10_ISP_READOUT_MEAS:
+               cifisp_send_measurement(isp_dev, readout_work);
+               break;
+
+       case CIF_ISP10_ISP_READOUT_META: {
+               struct cifisp_isp_other_cfg *other_new = NULL;
+               struct cifisp_isp_meas_cfg *meas_new = NULL;
+               struct cifisp_stat_buffer *stat_new = NULL;
+
+               spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+               if (isp_dev->other_cfgs.module_updates == 0) {
+                       if (readout_work->frame_id ==
+                               isp_dev->other_cfgs.curr->s_frame_id)
+                               other_new = isp_dev->other_cfgs.last_or_new;
+                       else if (readout_work->frame_id >
+                               isp_dev->other_cfgs.curr->s_frame_id)
+                               other_new = isp_dev->other_cfgs.curr;
+                       else
+                               other_new = NULL;
+               }
+
+               if (isp_dev->meas_cfgs.module_updates == 0) {
+                       if (readout_work->frame_id ==
+                               isp_dev->meas_cfgs.curr->s_frame_id)
+                               meas_new = isp_dev->meas_cfgs.last_or_new;
+                       else if (readout_work->frame_id >
+                               isp_dev->meas_cfgs.curr->s_frame_id)
+                               meas_new = isp_dev->meas_cfgs.curr;
+                       else
+                               meas_new = NULL;
+               }
+
+               if ((isp_dev->meas_stats.g_frame_id ==
+                       readout_work->frame_id) &&
+                       isp_dev->meas_stats.stat.meas_type)
+                       stat_new = &isp_dev->meas_stats.stat;
+               else
+                       stat_new = NULL;
+
+               cif_isp10_s_isp_metadata(
+                       cif_dev,
+                       readout_work,
+                       other_new,
+                       meas_new,
+                       stat_new);
+               spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+               break;
+       }
+       default:
+               break;
+       }
+
+       kfree((void *)work);
+}
+
+static inline bool cifisp_isp_isr_other_config(
+       struct cif_isp10_isp_dev *isp_dev,
+       unsigned int *time_left)
+{
+       unsigned int time_in = *time_left;
+       bool config_chk;
+       unsigned int *ens;
+
+       ens = &isp_dev->other_cfgs.last_or_new->module_ens;
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_DPCC)) {
+               /*update dpc config */
+               cifisp_dpcc_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_DPCC))
+                       cifisp_dpcc_en(isp_dev);
+               else
+                       cifisp_dpcc_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_DPCC);
+
+               *time_left -= CIFISP_MODULE_DPCC_PROC_TIME;
+
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "dpcc time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_BLS) &&
+               *time_left >= CIFISP_MODULE_BLS_PROC_TIME) {
+               /* update bls config */
+               cifisp_bls_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_BLS))
+                       cifisp_bls_en(isp_dev);
+               else
+                       cifisp_bls_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_BLS);
+
+               *time_left -= CIFISP_MODULE_BLS_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "bls time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_SDG) &&
+               *time_left >= CIFISP_MODULE_SDG_PROC_TIME) {
+               /* update sdg config */
+               cifisp_sdg_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_SDG))
+                       cifisp_sdg_en(isp_dev);
+               else
+                       cifisp_sdg_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_SDG);
+
+               *time_left -= CIFISP_MODULE_SDG_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "sdg time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_LSC) &&
+               *time_left >= CIFISP_MODULE_LSC_PROC_TIME) {
+               /* update lsc config */
+               bool res = true;
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_LSC)) {
+                       if (!cifisp_lsc_config(isp_dev))
+                               res = false;
+               } else {
+                       cifisp_lsc_end(isp_dev);
+               }
+
+               if (res)
+                       CIFISP_MODULE_CLR_UPDATE(
+                               isp_dev->other_cfgs.module_updates,
+                               CIFISP_MODULE_LSC);
+
+               *time_left -= CIFISP_MODULE_LSC_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "lsc time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_AWB_GAIN) &&
+               *time_left >= CIFISP_MODULE_AWB_GAIN_PROC_TIME) {
+               /* update awb gains */
+               cifisp_awb_gain_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_AWB_GAIN))
+                       cifisp_awb_gain_en(isp_dev);
+               else
+                       cifisp_awb_gain_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_AWB_GAIN);
+
+               *time_left -= CIFISP_MODULE_AWB_GAIN_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "awb-g time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_BDM) &&
+               *time_left >= CIFISP_MODULE_BDM_PROC_TIME) {
+               /* update bdm config */
+               cifisp_bdm_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_BDM))
+                       cifisp_bdm_en(isp_dev);
+               else
+                       cifisp_bdm_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_BDM);
+
+               *time_left -= CIFISP_MODULE_BDM_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "bdm time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_FLT) &&
+               *time_left >= CIFISP_MODULE_FLT_PROC_TIME) {
+               /* update filter config */
+               cifisp_flt_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_FLT))
+                       cifisp_flt_en(isp_dev);
+               else
+                       cifisp_flt_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_FLT);
+
+               *time_left -= CIFISP_MODULE_FLT_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "flt time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_CTK) &&
+               *time_left >= CIFISP_MODULE_CTK_PROC_TIME) {
+               /* update ctk config */
+               cifisp_ctk_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_CTK))
+                       cifisp_ctk_en(isp_dev);
+               else
+                       cifisp_ctk_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_CTK);
+
+               *time_left -= CIFISP_MODULE_CTK_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "ctk time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_GOC) &&
+               *time_left >= CIFISP_MODULE_GOC_PROC_TIME) {
+               /* update goc config */
+               cifisp_goc_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_GOC))
+                       cifisp_goc_en(isp_dev);
+               else
+                       cifisp_goc_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_IE);
+
+               *time_left -= CIFISP_MODULE_GOC_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "goc time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_CPROC) &&
+               *time_left >= CIFISP_MODULE_CPROC_PROC_TIME) {
+               /* update cprc config */
+               cifisp_cproc_config(
+                       isp_dev,
+                       isp_dev->quantization);
+
+               cifisp_csm_config(isp_dev,
+                       isp_dev->quantization);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_CPROC))
+                       cifisp_cproc_en(isp_dev);
+               else
+                       cifisp_cproc_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_CPROC);
+
+               *time_left -= CIFISP_MODULE_CPROC_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "cproc time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_IE) &&
+               *time_left >= CIFISP_MODULE_IE_PROC_TIME) {
+               /* update ie config */
+               cifisp_ie_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_IE))
+                       cifisp_ie_en(isp_dev);
+               else
+                       cifisp_ie_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_IE);
+
+               *time_left -= CIFISP_MODULE_IE_PROC_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "ie time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_DPF) &&
+               *time_left >= CIFISP_MODULE_DPF_TIME) {
+               /* update dpf  config */
+               cifisp_dpf_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_DPF))
+                       cifisp_dpf_en(isp_dev);
+               else
+                       cifisp_dpf_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_DPF);
+
+               *time_left -= CIFISP_MODULE_DPF_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "dpf time-left :%d\n",
+                       *time_left);
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->other_cfgs.module_updates,
+               CIFISP_MODULE_DPF_STRENGTH) &&
+               *time_left >= CIFISP_MODULE_DPF_STRENGTH_TIME) {
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_DPF)) {
+                       /* update dpf strength config */
+                       cifisp_dpf_strength_config(isp_dev);
+                       cifisp_dpf_en(isp_dev);
+               } else {
+                       cifisp_dpf_end(isp_dev);
+               }
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->other_cfgs.module_updates,
+                       CIFISP_MODULE_DPF_STRENGTH);
+
+               *time_left -= CIFISP_MODULE_DPF_STRENGTH_TIME;
+               CIFISP_DPRINT(CIFISP_DEBUG,
+                       "dpf strength time-left :%d\n",
+                       *time_left);
+       }
+
+       config_chk = time_in > *time_left;
+       if (config_chk)
+               cifisp_other_config_swap(isp_dev);
+
+       return config_chk;
+}
+
+static inline bool cifisp_isp_isr_meas_config(
+       struct cif_isp10_isp_dev *isp_dev,
+       unsigned int *time_left)
+{
+       unsigned int time_in = *time_left;
+       bool config_chk;
+       unsigned int *ens;
+
+       ens = &isp_dev->meas_cfgs.last_or_new->module_ens;
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->meas_cfgs.module_updates,
+               CIFISP_MODULE_AWB)) {
+               /* update awb config */
+               cifisp_awb_meas_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_AWB))
+                       cifisp_awb_meas_en(isp_dev);
+               else
+                       cifisp_awb_meas_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->meas_cfgs.module_updates,
+                       CIFISP_MODULE_AWB);
+               *time_left -= CIFISP_MODULE_AWB_PROC_TIME;
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->meas_cfgs.module_updates,
+               CIFISP_MODULE_AFC)) {
+               /* update afc config */
+               cifisp_afc_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_AFC))
+                       cifisp_afc_en(isp_dev);
+               else
+                       cifisp_afc_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->meas_cfgs.module_updates,
+                       CIFISP_MODULE_AFC);
+               *time_left -= CIFISP_MODULE_AFC_PROC_TIME;
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->meas_cfgs.module_updates,
+               CIFISP_MODULE_HST)) {
+               /* update hst config */
+               cifisp_hst_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_HST))
+                       cifisp_hst_en(isp_dev);
+               else
+                       cifisp_hst_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->meas_cfgs.module_updates,
+                       CIFISP_MODULE_HST);
+               *time_left -= CIFISP_MODULE_HST_PROC_TIME;
+       }
+
+       if (CIFISP_MODULE_IS_UPDATE(
+               isp_dev->meas_cfgs.module_updates,
+               CIFISP_MODULE_AEC)) {
+               /* update aec config */
+               cifisp_aec_config(isp_dev);
+
+               if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_AEC))
+                       cifisp_aec_en(isp_dev);
+               else
+                       cifisp_aec_end(isp_dev);
+
+               CIFISP_MODULE_CLR_UPDATE(
+                       isp_dev->meas_cfgs.module_updates,
+                       CIFISP_MODULE_AEC);
+               *time_left -= CIFISP_MODULE_AEC_PROC_TIME;
+       }
+
+       config_chk = time_in > *time_left;
+       if (config_chk)
+               cifisp_meas_config_swap(isp_dev);
+
+       return config_chk;
+}
+
+int cifisp_isp_isr(struct cif_isp10_isp_dev *isp_dev, u32 isp_mis)
+{
+       unsigned int isp_mis_tmp = 0;
+       struct cif_isp10_isp_readout_work *work;
+       unsigned int time_left = isp_dev->v_blanking_us;
+#ifdef LOG_ISR_EXE_TIME
+       ktime_t in_t = ktime_get();
+#endif
+       if (isp_mis & (CIF_ISP_DATA_LOSS | CIF_ISP_PIC_SIZE_ERROR))
+               return 0;
+
+       if (isp_mis & CIF_ISP_FRAME) {
+               u32 isp_ris = cifisp_ioread32(CIF_ISP_RIS);
+
+               cifisp_iowrite32(
+                       (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
+                       CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY),
+                       CIF_ISP_ICR);
+               isp_mis_tmp = cifisp_ioread32(CIF_ISP_MIS);
+               if (isp_mis_tmp &
+                       (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
+                       CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
+                       CIFISP_DPRINT(CIFISP_ERROR,
+                                     "isp icr 3A info err: 0x%x\n",
+                                     isp_mis_tmp);
+
+               CIFISP_DPRINT(CIFISP_DEBUG, "isp_ris 0x%x\n", isp_ris);
+
+               if (((isp_dev->meas_cfgs.module_updates &
+                       (CIFISP_MODULE_AWB |
+                       CIFISP_MODULE_AEC |
+                       CIFISP_MODULE_AFC)) == 0) &&
+                       isp_dev->active_meas &&
+                       ((isp_dev->active_meas & isp_ris) ==
+                       isp_dev->active_meas)) {
+                       work = (struct cif_isp10_isp_readout_work *)
+                               kmalloc(sizeof(
+                               struct cif_isp10_isp_readout_work),
+                               GFP_ATOMIC);
+                       if (work) {
+                               INIT_WORK((struct work_struct *)work,
+                                       cifisp_isp_readout_work);
+                               work->readout = CIF_ISP10_ISP_READOUT_MEAS;
+                               work->isp_dev = isp_dev;
+                               work->frame_id = isp_dev->frame_id;
+                               if (!queue_work(isp_dev->readout_wq,
+                                       (struct work_struct *)work)) {
+                                       CIFISP_DPRINT(CIFISP_ERROR,
+                                       "Could not schedule work\n");
+                                       kfree((void *)work);
+                               }
+                       } else {
+                               CIFISP_DPRINT(CIFISP_ERROR,
+                               "Could not allocate work\n");
+                       }
+               }
+
+               /*
+                * 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.
+                */
+               spin_lock(&isp_dev->config_lock);
+               if (cifisp_isp_isr_other_config(isp_dev, &time_left) == false)
+                       cifisp_isp_isr_meas_config(isp_dev, &time_left);
+               spin_unlock(&isp_dev->config_lock);
+
+               cifisp_dump_reg(isp_dev, CIFISP_DEBUG);
+       }
+#ifdef LOG_ISR_EXE_TIME
+       if (isp_mis & (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;
+
+               pr_info("isp_isr time %d %d\n", diff_us, g_longest_isr_time);
+       }
+#endif
+
+       return 0;
+}
+
+static void cifisp_param_dump(const void *config, unsigned int module)
+{
+#ifdef CIFISP_DEBUG_PARAM
+       switch (module) {
+       case CIFISP_MODULE_AWB_GAIN:{
+                       struct cifisp_awb_gain_config *pconfig =
+                           (struct cifisp_awb_gain_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: AWB Gain Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, "g_g: %d\n",
+                                     pconfig->gain_green_r);
+                       CIFISP_DPRINT(CIFISP_DEBUG, "g_b: %d\n",
+                                     pconfig->gain_green_b);
+                       CIFISP_DPRINT(CIFISP_DEBUG, "r: %d\n",
+                                     pconfig->gain_red);
+                       CIFISP_DPRINT(CIFISP_DEBUG, "b: %d\n",
+                                     pconfig->gain_blue);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: AWB Gain Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+       case CIFISP_MODULE_DPCC:{
+               }
+               break;
+
+       case CIFISP_MODULE_BLS:{
+                       struct cifisp_bls_config *pconfig =
+                           (struct cifisp_bls_config *)config;
+                       struct cifisp_bls_fixed_val *pval = &pconfig->fixed_val;
+
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: BLS Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " enable_auto: %d\n",
+                                     pconfig->enable_auto);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " en_windows: %d\n",
+                                     pconfig->en_windows);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " bls_window1.h_offs: %d\n",
+                                     pconfig->bls_window1.h_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " bls_window1.v_offs: %d\n",
+                                     pconfig->bls_window1.v_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " bls_window1.h_size: %d\n",
+                                     pconfig->bls_window1.h_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " bls_window1.v_size: %d\n",
+                                     pconfig->bls_window1.v_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " bls_window2.h_offs: %d\n",
+                                     pconfig->bls_window2.h_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " bls_window2.v_offs: %d\n",
+                                     pconfig->bls_window2.v_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " bls_window2.h_size: %d\n",
+                                     pconfig->bls_window2.h_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " bls_window2.v_size: %d\n",
+                                     pconfig->bls_window2.v_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " bls_samples: %d\n",
+                                     pconfig->bls_samples);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " fixed_A: %d\n",
+                                     pval->fixed_a);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " fixed_B: %d\n",
+                                     pval->fixed_b);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " fixed_C: %d\n",
+                                     pval->fixed_c);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " fixed_D: %d\n",
+                                     pval->fixed_d);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: BLS Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+       case CIFISP_MODULE_LSC:{
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### LSC Parameters - BEGIN ####\n");
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### LSC Parameters - END ####\n");
+               }
+               break;
+       case CIFISP_MODULE_FLT:{
+                       struct cifisp_flt_config *pconfig =
+                           (struct cifisp_flt_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: FLT Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_mask_sharp0: %d\n",
+                                     pconfig->flt_mask_sharp0);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_mask_sharp1: %d\n",
+                                     pconfig->flt_mask_sharp1);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_mask_diag: %d\n",
+                                     pconfig->flt_mask_diag);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_mask_blur_max: %d\n",
+                                     pconfig->flt_mask_blur_max);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_mask_blur: %d\n",
+                                     pconfig->flt_mask_blur);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_mask_lin: %d\n",
+                                     pconfig->flt_mask_lin);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_mask_orth: %d\n",
+                                     pconfig->flt_mask_orth);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_mask_v_diag: %d\n",
+                                     pconfig->flt_mask_v_diag);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_mask_h_diag: %d\n",
+                                     pconfig->flt_mask_h_diag);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_lum_weight: %d\n",
+                                     pconfig->flt_lum_weight);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_blur_th0: %d\n",
+                                     pconfig->flt_blur_th0);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_blur_th1: %d\n",
+                                     pconfig->flt_blur_th1);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_sharp0_th: %d\n",
+                                     pconfig->flt_sharp0_th);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_sharp1_th: %d\n",
+                                     pconfig->flt_sharp1_th);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_chrom_h_mode: %d\n",
+                                     pconfig->flt_chrom_h_mode);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_chrom_v_mode: %d\n",
+                                     pconfig->flt_chrom_v_mode);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " flt_diag_sharp_mode: %d\n",
+                                     pconfig->flt_diag_sharp_mode);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " flt_mode: %d\n",
+                                     pconfig->flt_mode);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: FLT Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+
+       case CIFISP_MODULE_BDM:{
+                       struct cifisp_bdm_config *pconfig =
+                           (struct cifisp_bdm_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: BDM Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " demosaic_th: %d\n",
+                                     pconfig->demosaic_th);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: BDM Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+
+       case CIFISP_MODULE_SDG:{
+                       struct cifisp_sdg_config *pconfig =
+                           (struct cifisp_sdg_config *)config;
+                       unsigned int i;
+
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: SDG Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " RED -Curve parameters\n");
+                       for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+                               CIFISP_DPRINT(CIFISP_DEBUG,
+                                       " gamma_y[%d]: %d\n",
+                                       pconfig->curve_r.gamma_y[i]);
+                       }
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " GREEN -Curve parameters\n");
+                       for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+                               CIFISP_DPRINT(CIFISP_DEBUG,
+                                       " gamma_y[%d]: %d\n",
+                                       pconfig->curve_g.gamma_y[i]);
+                       }
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " BLUE -Curve parameters\n");
+                       for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+                               CIFISP_DPRINT(CIFISP_DEBUG,
+                                       " gamma_y[%d]: %d\n",
+                                       pconfig->curve_b.gamma_y[i]);
+                       }
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: SDG Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+
+       case CIFISP_MODULE_GOC:{
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: GOC Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: GOC Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+
+       case CIFISP_MODULE_CTK:{
+                       struct cifisp_ctk_config *pconfig =
+                           (struct cifisp_ctk_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: CTK Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff0: %d\n",
+                                     pconfig->coeff0);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff1: %d\n",
+                                     pconfig->coeff1);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff2: %d\n",
+                                     pconfig->coeff2);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff3: %d\n",
+                                     pconfig->coeff3);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff4: %d\n",
+                                     pconfig->coeff4);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff5: %d\n",
+                                     pconfig->coeff5);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff6: %d\n",
+                                     pconfig->coeff6);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff7: %d\n",
+                                     pconfig->coeff7);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " coeff8: %d\n",
+                                     pconfig->coeff8);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " ct_offset_r: %d\n",
+                                     pconfig->ct_offset_r);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " ct_offset_g: %d\n",
+                                     pconfig->ct_offset_g);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " ct_offset_b: %d\n",
+                                     pconfig->ct_offset_b);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: CTK Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+
+       case CIFISP_MODULE_AWB:{
+                       struct cifisp_awb_meas_config *pconfig =
+                           (struct cifisp_awb_meas_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: AWB Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " awb_mode: %d\n",
+                                     pconfig->awb_mode);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " max_y: %d\n",
+                                     pconfig->max_y);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " min_y: %d\n",
+                                     pconfig->min_y);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " max_csum: %d\n",
+                                     pconfig->max_csum);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " min_c: %d\n",
+                                     pconfig->min_c);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " frames: %d\n",
+                                     pconfig->frames);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " awb_ref_cr: %d\n",
+                                     pconfig->awb_ref_cr);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " awb_ref_cb: %d\n",
+                                     pconfig->awb_ref_cb);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " gb_sat: %d\n",
+                                     pconfig->gb_sat);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " gr_sat: %d\n",
+                                     pconfig->gr_sat);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " r_sat: %d\n",
+                                     pconfig->b_sat);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " grid_h_dim: %d\n",
+                                     pconfig->grid_h_dim);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " grid_v_dim: %d\n",
+                                     pconfig->grid_v_dim);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " grid_h_dist: %d\n",
+                                     pconfig->grid_h_dist);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " grid_v_dist: %d\n",
+                                     pconfig->grid_v_dist);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " enable_ymax_cmp: %d\n",
+                                     pconfig->enable_ymax_cmp);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " rgb_meas_pnt: %d\n",
+                                     pconfig->rgb_meas_pnt);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " AWB Window size\n");
+                       CIFISP_DPRINT(CIFISP_DEBUG, " h_offs: %d\n",
+                                     pconfig->awb_wnd.h_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " v_offs: %d\n",
+                                     pconfig->awb_wnd.v_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " h_size: %d\n",
+                                     pconfig->awb_wnd.h_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " v_size: %d\n",
+                                     pconfig->awb_wnd.v_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: AWB Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+
+       case CIFISP_MODULE_HST:{
+                       struct cifisp_hst_config *pconfig =
+                           (struct cifisp_hst_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: HST Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " mode: %d\n",
+                                     pconfig->mode);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " histogram_predivider: %d\n",
+                                     pconfig->histogram_predivider);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " HST Window size\n");
+                       CIFISP_DPRINT(CIFISP_DEBUG, " h_offs: %d\n",
+                                     pconfig->meas_window.h_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " v_offs: %d\n",
+                                     pconfig->meas_window.v_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " h_size: %d\n",
+                                     pconfig->meas_window.h_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " v_size: %d\n",
+                                     pconfig->meas_window.v_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: HST Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+
+               } break;
+
+       case CIFISP_MODULE_AEC:{
+                       struct cifisp_aec_config *pconfig =
+                           (struct cifisp_aec_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: AEC Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " autostop: %d\n",
+                                     pconfig->autostop);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " AEC Window size\n");
+                       CIFISP_DPRINT(CIFISP_DEBUG, " h_offs: %d\n",
+                                     pconfig->meas_window.h_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " v_offs: %d\n",
+                                     pconfig->meas_window.v_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " h_size: %d\n",
+                                     pconfig->meas_window.h_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " v_size: %d\n",
+                                     pconfig->meas_window.v_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: AEC Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+
+       case CIFISP_MODULE_CPROC:{
+                       struct cifisp_cproc_config *pconfig =
+                           (struct cifisp_cproc_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: CPROC Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " contrast: %d\n",
+                                     pconfig->contrast);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " hue: %d\n",
+                                     pconfig->hue);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " sat: %d\n",
+                                     pconfig->sat);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " brightness: %d\n",
+                                     pconfig->brightness);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: CPROC Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+               } break;
+       case CIFISP_MODULE_YCFLT:{
+                       struct cifisp_ycflt_config *pconfig =
+                           (struct cifisp_ycflt_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: YCFLT Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " chr_ss_ctrl: %d\n",
+                       CIFISP_DPRINT(CIFISP_DEBUG, " ctrl: %d\n",
+                                       pconfig->ctrl);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " chr_ss_ctrl: %d\n",
+                                     pconfig->chr_ss_ctrl);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " chr_ss_fac: %d\n",
+                                     pconfig->chr_ss_fac);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " chr_ss_offs: %d\n",
+                                     pconfig->chr_ss_offs);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " chr_nr_ctrl: %d\n",
+                                     pconfig->chr_nr_ctrl);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " lum_eenr_edge_gain: %d\n",
+                                     pconfig->lum_eenr_edge_gain);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " lum_eenr_corner_gain: %d\n",
+                                     pconfig->lum_eenr_corner_gain);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " lum_eenr_fc_crop_neg: %d\n",
+                                     pconfig->lum_eenr_fc_crop_neg);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " lum_eenr_fc_crop_pos: %d\n",
+                                     pconfig->lum_eenr_fc_crop_pos);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " lum_eenr_fc_gain_neg: %d\n",
+                                     pconfig->lum_eenr_fc_gain_neg);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " lum_eenr_fc_gain_pos: %d\n",
+                                     pconfig->lum_eenr_fc_gain_pos);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: YCFLT Parameters - END ####\n",
+                                     ISP_VDEV_NAME);
+                       break;
+               }
+       case CIFISP_MODULE_AFC:{
+                       struct cifisp_afc_config *pconfig =
+                           (struct cifisp_afc_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     "#### %s: AFC Parameters - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " window A %d %d %d %d\n",
+                                     pconfig->afm_win[0].h_offs,
+                                     pconfig->afm_win[0].v_offs,
+                                     pconfig->afm_win[0].h_size,
+                                     pconfig->afm_win[0].v_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " window B %d %d %d %d\n",
+                                     pconfig->afm_win[1].h_offs,
+                                     pconfig->afm_win[1].v_offs,
+                                     pconfig->afm_win[1].h_size,
+                                     pconfig->afm_win[1].v_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                                     " window C %d %d %d %d\n",
+                                     pconfig->afm_win[2].h_offs,
+                                     pconfig->afm_win[2].v_offs,
+                                     pconfig->afm_win[2].h_size,
+                                     pconfig->afm_win[2].v_size);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " thres: %d\n",
+                                     pconfig->thres);
+                       CIFISP_DPRINT(CIFISP_DEBUG, " var_shift: %d\n",
+                                     pconfig->var_shift);
+                       break;
+               }
+       case CIFISP_MODULE_IE: {
+                       struct cifisp_ie_config *pconfig =
+                           (struct cifisp_ie_config *)config;
+                       CIFISP_DPRINT(CIFISP_DEBUG,
+                               "effect %d, %x, %x, %x, %x, %x, %x %d\n",
+                               pconfig->effect, pconfig->color_sel,
+                               pconfig->eff_mat_1, pconfig->eff_mat_2,
+                               pconfig->eff_mat_3, pconfig->eff_mat_4,
+                               pconfig->eff_mat_5, pconfig->eff_tint);
+                       break;
+               }
+       default:
+               CIFISP_DPRINT(CIFISP_DEBUG,
+               "####%s: Invalid Module ID ####\n", ISP_VDEV_NAME);
+               break;
+       }
+#endif
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_reg_dump_capture(const struct cif_isp10_isp_dev *isp_dev)
+{
+       memset(&g_last_capture_config, 0, sizeof(g_last_capture_config));
+
+       if (isp_dev->bls_en) {
+               g_last_capture_config.bls.fixed_val.fixed_a =
+                   cifisp_ioread32(CIF_ISP_BLS_A_FIXED);
+               g_last_capture_config.bls.fixed_val.fixed_b =
+                   cifisp_ioread32(CIF_ISP_BLS_B_FIXED);
+               g_last_capture_config.bls.fixed_val.fixed_c =
+                   cifisp_ioread32(CIF_ISP_BLS_C_FIXED);
+               g_last_capture_config.bls.fixed_val.fixed_d =
+                   cifisp_ioread32(CIF_ISP_BLS_D_FIXED);
+       }
+
+       if (isp_dev->lsc_en)
+               cifisp_lsc_config_read(isp_dev, &g_last_capture_config.lsc);
+
+       if (isp_dev->flt_en)
+               cifisp_flt_config_read(isp_dev, &g_last_capture_config.flt);
+
+       if (isp_dev->bdm_en)
+               g_last_capture_config.bdm.demosaic_th =
+                   cifisp_ioread32(CIF_ISP_DEMOSAIC);
+
+       if (isp_dev->sdg_en)
+               cifisp_sdg_config_read(isp_dev, &g_last_capture_config.sdg);
+
+       if (isp_dev->goc_en)
+               cifisp_goc_config_read(isp_dev, &g_last_capture_config.goc);
+
+       if (isp_dev->ctk_en)
+               cifisp_ctk_config_read(isp_dev, &g_last_capture_config.ctk);
+
+       if (isp_dev->awb_meas_en)
+               cifisp_awb_meas_config_read(isp_dev,
+                                           &g_last_capture_config.awb_meas);
+
+       if (isp_dev->awb_gain_en)
+               cifisp_awb_gain_config_read(isp_dev,
+                                           &g_last_capture_config.awb_gain);
+
+       if (isp_dev->cproc_en)
+               cifisp_cproc_config_read(isp_dev, &g_last_capture_config.cproc);
+}
+#endif
+
+#ifdef CIFISP_DEBUG_REG
+static void cifisp_reg_dump(const struct cif_isp10_isp_dev *isp_dev,
+                           unsigned int module, int level)
+{
+       switch (module) {
+       case CIFISP_MODULE_DPCC:
+               CIFISP_DPRINT(level, "#### BPC Registers - BEGIN ####\n");
+               CIFISP_DPRINT(level, "#### BPC Registers - END ####\n");
+               break;
+       case CIFISP_MODULE_BLS:
+               CIFISP_DPRINT(level, "#### BLS Registers - BEGIN ####\n");
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_CTRL: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_CTRL));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_SAMPLES: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_SAMPLES));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_H1_START: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_H1_START));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_H1_STOP: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_H1_STOP));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_H1_START: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_H1_START));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_V1_START: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_V1_START));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_V1_STOP: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_V1_STOP));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_H2_START: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_H2_START));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_H2_STOP: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_H2_STOP));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_V2_START: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_V2_START));
+               CIFISP_DPRINT(level, " CIF_ISP_BLS_V2_STOP: %d\n",
+                             cifisp_ioread32(CIF_ISP_BLS_V2_STOP));
+               CIFISP_DPRINT(level, "#### BLS Registers - END ####\n");
+               break;
+       case CIFISP_MODULE_LSC:
+               CIFISP_DPRINT(level, "#### LSC Registers - BEGIN ####\n");
+               CIFISP_DPRINT(level, "#### LSC Registers - END ####\n");
+               break;
+       case CIFISP_MODULE_FLT:{
+                       CIFISP_DPRINT(level,
+                               "#### %s: FLT Registers - BEGIN ####\n",
+                               ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level,
+                               " CIF_ISP_FILT_MODE: %d\n",
+                               cifisp_ioread32(CIF_ISP_FILT_MODE));
+                       CIFISP_DPRINT(level,
+                               " CIF_ISP_FILT_LUM_WEIGHT: %d\n",
+                               cifisp_ioread32(CIF_ISP_FILT_LUM_WEIGHT));
+                       CIFISP_DPRINT(level,
+                               "#### %s: FLT Registers - END ####\n",
+                               ISP_VDEV_NAME);
+               }
+               break;
+
+       case CIFISP_MODULE_BDM:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: BDM Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level, " CIF_ISP_DEMOSAIC: %d\n",
+                                     cifisp_ioread32(CIF_ISP_DEMOSAIC));
+                       CIFISP_DPRINT(level,
+                                     "#### %s: BDM Registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+
+       case CIFISP_MODULE_SDG:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: SDG Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_DX_LO: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_DX_LO));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_DX_HI: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_DX_HI));
+
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y0: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y0));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y1: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y1));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y2: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y2));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y3: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y3));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y4: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y4));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y5: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y5));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y6: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y6));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y7: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y7));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y8: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y8));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y9: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y9));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y10: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y10));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y11: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y11));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y12: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y12));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y13: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y13));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y14: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y14));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y15: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y15));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y16: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_R_Y16));
+
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y0: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y0));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y1: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y1));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y2: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y2));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y3: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y3));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y4: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y4));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y5: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y5));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y6: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y6));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y7: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y7));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y8: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y8));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y9: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y9));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y10: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y10));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y11: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y11));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y12: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y12));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y13: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y13));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y14: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y14));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y15: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y15));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y16: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_G_Y16));
+
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y0: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y0));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y1: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y1));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y2: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y2));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y3: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y3));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y4: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y4));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y5: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y5));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y6: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y6));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y7: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y7));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y8: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y8));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y9: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y9));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y10: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y10));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y11: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y11));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y12: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y12));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y13: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y13));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y14: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y14));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y15: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y15));
+                       CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y16: %d\n",
+                                     cifisp_ioread32(CIF_ISP_GAMMA_B_Y16));
+                       CIFISP_DPRINT(level,
+                                     "#### %s: SDG Registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+
+       case CIFISP_MODULE_GOC:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: GOC Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level,
+                                     "#### %s: GOC registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+
+       case CIFISP_MODULE_CTK:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: CTK Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_0: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_0));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_1: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_1));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_2: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_2));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_3: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_3));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_4: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_4));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_5: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_5));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_6: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_6));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_7: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_7));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_8: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_COEFF_8));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_OFFSET_R: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_OFFSET_R));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_OFFSET_G: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_OFFSET_G));
+                       CIFISP_DPRINT(level, " CIF_ISP_CT_OFFSET_B: %d\n",
+                                     cifisp_ioread32(CIF_ISP_CT_OFFSET_B));
+                       CIFISP_DPRINT(level,
+                                     "#### %s: CTK Registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+
+       case CIFISP_MODULE_AWB:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: AWB Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level, " CIF_ISP_AWB_PROP: %x\n",
+                                     cifisp_ioread32(CIF_ISP_AWB_PROP));
+                       CIFISP_DPRINT(level, " CIF_ISP_AWB_GAIN_G: %x\n",
+                                     cifisp_ioread32(CIF_ISP_AWB_GAIN_G));
+                       CIFISP_DPRINT(level, " CIF_ISP_AWB_GAIN_RB: %x\n",
+                                     cifisp_ioread32(CIF_ISP_AWB_GAIN_RB));
+                       CIFISP_DPRINT(level, " CIF_ISP_AWB_REF: %x\n",
+                                     cifisp_ioread32(CIF_ISP_AWB_REF));
+                       CIFISP_DPRINT(level, " CIF_ISP_AWB_GAIN_RB: %x\n",
+                                     cifisp_ioread32(CIF_ISP_AWB_PROP));
+                       CIFISP_DPRINT(level, " CIF_ISP_AWB_FRAMES: %x\n",
+                                     cifisp_ioread32(CIF_ISP_AWB_FRAMES));
+                       CIFISP_DPRINT(level,
+                                     "#### %s: AWB Registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+
+       case CIFISP_MODULE_HST:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: HST Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level, " CIF_ISP_HIST_PROP: %d\n",
+                                     cifisp_ioread32(CIF_ISP_HIST_PROP));
+                       CIFISP_DPRINT(level, " CIF_ISP_HIST_H_OFFS: %d\n",
+                                     cifisp_ioread32(CIF_ISP_HIST_H_OFFS));
+                       CIFISP_DPRINT(level, " CIF_ISP_HIST_H_SIZE: %d\n",
+                                     cifisp_ioread32(CIF_ISP_HIST_H_SIZE));
+                       CIFISP_DPRINT(level, " CIF_ISP_HIST_V_OFFS: %d\n",
+                                     cifisp_ioread32(CIF_ISP_HIST_V_OFFS));
+                       CIFISP_DPRINT(level, " CIF_ISP_HIST_V_SIZE: %d\n",
+                                     cifisp_ioread32(CIF_ISP_HIST_V_SIZE));
+                       CIFISP_DPRINT(level,
+                                     "#### %s: HST Registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+
+       case CIFISP_MODULE_AEC:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: AEC Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level, " CIF_ISP_EXP_CTRL: %d\n",
+                                     cifisp_ioread32(CIF_ISP_EXP_CTRL));
+                       CIFISP_DPRINT(level, " CIF_ISP_EXP_H_OFFSET: %d\n",
+                                     cifisp_ioread32(CIF_ISP_EXP_H_OFFSET));
+                       CIFISP_DPRINT(level, " CIF_ISP_EXP_V_OFFSET: %d\n",
+                                     cifisp_ioread32(CIF_ISP_EXP_V_OFFSET));
+                       CIFISP_DPRINT(level, " CIF_ISP_EXP_H_SIZE: %d\n",
+                                     cifisp_ioread32(CIF_ISP_EXP_H_SIZE));
+                       CIFISP_DPRINT(level, " CIF_ISP_EXP_V_SIZE: %d\n",
+                                     cifisp_ioread32(CIF_ISP_EXP_V_SIZE));
+                       CIFISP_DPRINT(level,
+                                     "#### %s: AEC Registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+
+       case CIFISP_MODULE_CPROC:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: CPROC Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level, " ctrl: %d\n",
+                                     cifisp_ioread32(CIF_C_PROC_CTRL));
+                       CIFISP_DPRINT(level, " contrast: %d\n",
+                                     cifisp_ioread32(CIF_C_PROC_CONTRAST));
+                       CIFISP_DPRINT(level, " hue: %d\n",
+                                     cifisp_ioread32(CIF_C_PROC_HUE));
+                       CIFISP_DPRINT(level, " sat: %d\n",
+                                     cifisp_ioread32(CIF_C_PROC_SATURATION));
+                       CIFISP_DPRINT(level, " brightness: %d\n",
+                                     cifisp_ioread32(CIF_C_PROC_BRIGHTNESS));
+                       CIFISP_DPRINT(level,
+                                     "#### %s: CPROC Registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+       case CIFISP_MODULE_AFC:{
+                       CIFISP_DPRINT(level,
+                                     "#### %s: AFC Registers - BEGIN ####\n",
+                                     ISP_VDEV_NAME);
+                       CIFISP_DPRINT(level, " afm_ctr: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_CTRL));
+                       CIFISP_DPRINT(level, " afm_lt_a: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_LT_A));
+                       CIFISP_DPRINT(level, " afm_rb_a: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_RB_A));
+                       CIFISP_DPRINT(level, " afm_lt_b: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_LT_B));
+                       CIFISP_DPRINT(level, " afm_rb_b: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_RB_B));
+                       CIFISP_DPRINT(level, " afm_lt_c: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_LT_C));
+                       CIFISP_DPRINT(level, " afm_rb_c: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_RB_C));
+                       CIFISP_DPRINT(level, " afm_thres: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_THRES));
+                       CIFISP_DPRINT(level, " afm_var_shift: %d\n",
+                                     cifisp_ioread32(CIF_ISP_AFM_VAR_SHIFT));
+                       CIFISP_DPRINT(level,
+                                     "#### %s: YCFLT Registers - END ####\n",
+                                     ISP_VDEV_NAME);
+               }
+               break;
+       default:
+               CIFISP_DPRINT(level, "####%s: Invalid Module ID ####\n",
+                             ISP_VDEV_NAME);
+               break;
+       }
+}
+#endif
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_isp.h b/drivers/media/platform/rk-isp10/cif_isp10_isp.h
new file mode 100644 (file)
index 0000000..27f6bb6
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_ISP_H
+#define _CIF_ISP10_ISP_H
+
+#include <media/v4l2-common.h>
+#include <media/videobuf-core.h>
+#include <media/rk-isp10-ioctl.h>
+#include <media/v4l2-controls_rockchip.h>
+
+/*
+ * ISP device struct
+ */
+enum cif_isp10_pix_fmt;
+
+enum cif_isp10_pix_fmt_quantization {
+       CIF_ISP10_QUANTIZATION_DEFAULT = 0,
+       CIF_ISP10_QUANTIZATION_FULL_RANGE = 1,
+       CIF_ISP10_QUANTIZATION_LIM_RANGE = 2
+};
+
+struct cif_isp10_isp_other_cfgs {
+       struct cifisp_isp_other_cfg *last_or_new;
+       struct cifisp_isp_other_cfg *curr;
+       struct cifisp_isp_other_cfg cfgs[2];
+       unsigned int module_updates;
+};
+
+struct cif_isp10_isp_meas_cfgs {
+       struct cifisp_isp_meas_cfg *last_or_new;
+       struct cifisp_isp_meas_cfg *curr;
+       struct cifisp_isp_meas_cfg cfgs[2];
+       unsigned int module_updates;
+};
+
+struct cif_isp10_isp_meas_stats {
+       unsigned int g_frame_id;
+       struct cifisp_stat_buffer stat;
+};
+
+struct cif_isp10_isp_dev {
+       /*
+        * Purpose of mutex is to protect and serialize use
+        * of isp data structure and CIF API calls.
+        */
+       struct mutex mutex;
+       /* Current ISP parameters */
+       spinlock_t config_lock;
+       struct cif_isp10_isp_other_cfgs other_cfgs;
+       struct cif_isp10_isp_meas_cfgs meas_cfgs;
+       struct cif_isp10_isp_meas_stats meas_stats;
+
+       bool cif_ism_cropping;
+
+       enum cif_isp10_pix_fmt_quantization quantization;
+
+       /* input resolution needed for LSC param check */
+       unsigned int input_width;
+       unsigned int input_height;
+       unsigned int active_lsc_width;
+       unsigned int active_lsc_height;
+
+       /* ISP statistics related */
+       spinlock_t irq_lock;
+       /* ISP statistics related */
+       spinlock_t req_lock;
+       struct videobuf_queue vbq_stat;
+       struct list_head stat;
+       void __iomem *base_addr;    /* registers base address */
+
+       bool streamon;
+       unsigned int v_blanking_us;
+
+       unsigned int frame_id;
+       unsigned int frame_id_setexp;
+       unsigned int active_meas;
+
+       struct timeval vs_t;    /* updated each frame */
+       struct timeval fi_t;    /* updated each frame */
+       struct workqueue_struct *readout_wq;
+
+       unsigned int *dev_id;
+};
+
+enum cif_isp10_isp_readout_cmd {
+       CIF_ISP10_ISP_READOUT_MEAS = 0,
+       CIF_ISP10_ISP_READOUT_META = 1,
+};
+
+struct cif_isp10_isp_readout_work {
+       struct work_struct work;
+       struct cif_isp10_isp_dev *isp_dev;
+
+       unsigned int frame_id;
+       enum cif_isp10_isp_readout_cmd readout;
+       struct videobuf_buffer *vb;
+       unsigned int stream_id;
+};
+
+int register_cifisp_device(
+       struct cif_isp10_isp_dev *isp_dev,
+       struct video_device *vdev_cifisp,
+       struct v4l2_device *v4l2_dev,
+       void __iomem *cif_reg_baseaddress);
+void unregister_cifisp_device(struct video_device *vdev_cifisp);
+void cifisp_configure_isp(
+       struct cif_isp10_isp_dev *isp_dev,
+       enum cif_isp10_pix_fmt in_pix_fmt,
+       enum cif_isp10_pix_fmt_quantization quantization);
+void cifisp_disable_isp(struct cif_isp10_isp_dev *isp_dev);
+int cifisp_isp_isr(struct cif_isp10_isp_dev *isp_dev, u32 isp_mis);
+void cifisp_v_start(struct cif_isp10_isp_dev *isp_dev,
+       const struct timeval *timestamp);
+void cifisp_frame_in(
+       struct cif_isp10_isp_dev *isp_dev,
+       const struct timeval *fi_t);
+void cifisp_isp_readout_work(struct work_struct *work);
+
+#endif
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.c b/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.c
new file mode 100644 (file)
index 0000000..126a037
--- /dev/null
@@ -0,0 +1,1443 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef CONFIG_OF
+#error "this driver requires a kernel with device tree support"
+#endif
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/list.h>
+#include "cif_isp10.h"
+#include <linux/platform_data/rk_isp10_platform.h>
+#include "cif_isp10_regs.h"
+#ifndef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <media/v4l2-controls_rockchip.h>
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+#include <stdarg.h>
+
+static struct {
+       char *reg_trace;
+       loff_t reg_trace_read_pos;
+       loff_t reg_trace_write_pos;
+       size_t reg_trace_max_size;
+       void __iomem *base_addr;
+       bool rtrace;
+       bool ftrace;
+       bool internal;
+       spinlock_t lock;/* spin lock */
+} cif_isp10_reg_trace;
+#endif
+#endif
+
+struct cif_isp10_pltfrm_csi_config {
+       struct list_head list;
+       u32 pps;
+       struct cif_isp10_csi_config csi_config;
+};
+
+struct cif_isp10_pltfrm_data {
+       struct pinctrl *pinctrl;
+       struct pinctrl_state *pins_default;
+       struct pinctrl_state *pins_sleep;
+       struct pinctrl_state *pins_inactive;
+       void __iomem *base_addr;
+       int irq;
+       struct {
+               int mis;
+               int (*isr)(unsigned int mis, void *cntxt);
+       } irq_handlers[4];
+       struct list_head csi0_configs;
+       struct list_head csi1_configs;
+       s32 exp_time;
+       u16 gain;
+
+#ifndef CONFIG_DEBUG_FS
+       struct {
+               struct dentry *dir;
+               struct dentry *cif_isp10_file;
+               struct dentry *csi0_file;
+               struct dentry *csi1_file;
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+               struct dentry *reg_trace_file;
+#endif
+               void (*print_func)(void *cntxt, const char *block_name);
+               void *print_cntxt;
+       } dbgfs;
+#endif
+};
+
+void cif_isp10_pltfrm_debug_register_print_cb(
+       struct device *dev,
+       void (*print)(void *cntxt, const char *block),
+       void *cntxt) {
+#ifndef CONFIG_DEBUG_FS
+       struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+
+       pdata->dbgfs.print_cntxt = cntxt;
+       pdata->dbgfs.print_func = print;
+#endif
+}
+
+#ifndef CONFIG_DEBUG_FS
+#define CIF_ISP10_DBGFS_BUF_SIZE 1024
+static char cif_isp10_dbgfs_buf[CIF_ISP10_DBGFS_BUF_SIZE];
+
+static int cif_isp10_dbgfs_fill_csi_config_from_string(
+       struct device *dev,
+       struct cif_isp10_csi_config *csi_config,
+       char *strp)
+{
+       char *token;
+
+       token = strsep(&strp, " ");
+       if (IS_ERR_OR_NULL(token))
+               goto missing_token;
+       if (IS_ERR_VALUE(kstrtou32(token, 10,
+                       &csi_config->vc)))
+               goto wrong_token_format;
+       token = strsep(&strp, " ");
+       if (IS_ERR_OR_NULL(token))
+               goto missing_token;
+       if (IS_ERR_VALUE(kstrtou32(token, 10,
+                       &csi_config->nb_lanes)))
+               goto wrong_token_format;
+       token = strsep(&strp, " ");
+       if (IS_ERR_OR_NULL(token))
+               goto missing_token;
+       if (IS_ERR_VALUE(kstrtou32(token, 16,
+                       &csi_config->dphy1)))
+               goto wrong_token_format;
+       token = strsep(&strp, " ");
+       if (IS_ERR_OR_NULL(token))
+               goto missing_token;
+       if (IS_ERR_VALUE(kstrtou32(token, 16,
+                       &csi_config->dphy2)))
+               goto wrong_token_format;
+       token = strsep(&strp, " ");
+       if (!IS_ERR_OR_NULL(token)) {
+               if (IS_ERR_VALUE(kstrtou32(token, 10,
+                               &csi_config->ana_bandgab_bias)))
+                       goto wrong_token_format;
+       } else {
+               csi_config->ana_bandgab_bias = (u32)-1;
+       }
+
+       return 0;
+missing_token:
+       cif_isp10_pltfrm_pr_err(dev,
+               "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
+       return -EINVAL;
+wrong_token_format:
+       cif_isp10_pltfrm_pr_err(dev,
+               "wrong token format, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
+       return -EINVAL;
+}
+
+static int cif_isp10_dbgfs_csi_configs_init(
+       struct device *dev,
+       enum cif_isp10_inp inp,
+       struct list_head *csi_configs)
+{
+       int ret = 0;
+       struct device *img_src_dev = NULL;
+       struct device_node *parent_node = NULL;
+       struct device_node *child_node = NULL, *prev_node = NULL;
+       struct cif_isp10_pltfrm_csi_config *cfg = NULL;
+       u32 pps;
+
+       img_src_dev = cif_isp10_pltfrm_get_img_src_device(dev, inp);
+       if (IS_ERR_OR_NULL(img_src_dev)) {
+               ret = -EFAULT;
+               goto err;
+       }
+       parent_node = of_node_get(img_src_dev->of_node);
+       put_device(img_src_dev);
+       img_src_dev = NULL;
+
+       while (!IS_ERR_OR_NULL(child_node =
+               of_get_next_child(parent_node, prev_node))) {
+               if (!strncasecmp(child_node->name,
+                       "intel,camera-module-csi-config",
+                       strlen("intel,camera-module-csi-config"))) {
+                       ret = of_property_read_u32(child_node,
+                               "intel,csi-pixels-per-second", &pps);
+                       if (IS_ERR_VALUE(ret)) {
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "reading property 'intel,csi-pixels-per-second'\n");
+                               goto err;
+                       }
+                       cfg = kmalloc(
+                               sizeof(struct cif_isp10_pltfrm_csi_config),
+                       GFP_KERNEL);
+                       if (!cfg) {
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "memory allocation failed\n");
+                               ret = -ENOMEM;
+                               goto err;
+                       }
+                       cfg->pps = pps;
+                       ret = cif_isp10_pltfrm_fill_csi_config_from_node(
+                                       dev, &cfg->csi_config, child_node);
+                       if (IS_ERR_VALUE(ret))
+                               goto err;
+                       list_add_tail(&cfg->list, csi_configs);
+                       cfg = NULL;
+               }
+               of_node_put(prev_node);
+               prev_node = child_node;
+       }
+       of_node_put(prev_node);
+       of_node_put(parent_node);
+
+       return 0;
+err:
+       of_node_put(prev_node);
+       of_node_put(child_node);
+       of_node_put(parent_node);
+       kfree(cfg);
+       if (!IS_ERR_OR_NULL(img_src_dev))
+               put_device(img_src_dev);
+       return ret;
+}
+
+static ssize_t cif_isp10_dbgfs_csi_read(
+       struct file *f,
+       char __user *out,
+       size_t count,
+       loff_t *pos)
+{
+       u32 out_size = 0;
+       u32 str_len;
+       struct cif_isp10_pltfrm_csi_config *cfg;
+       u32 index = 0;
+       struct list_head *list_pos;
+       struct device *dev = f->f_inode->i_private;
+       struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+       struct list_head *csi_configs;
+       enum cif_isp10_inp inp;
+
+       if (f->f_inode == pdata->dbgfs.csi0_file->d_inode) {
+               csi_configs = &pdata->csi0_configs;
+               inp = CIF_ISP10_INP_CSI_0;
+       } else if (f->f_inode == pdata->dbgfs.csi1_file->d_inode) {
+               csi_configs = &pdata->csi1_configs;
+               inp = CIF_ISP10_INP_CSI_1;
+       } else {
+               cif_isp10_pltfrm_pr_err(dev, "wrong file handle\n");
+               return -EINVAL;
+       }
+
+       if (list_empty(csi_configs))
+               if (IS_ERR_VALUE(cif_isp10_dbgfs_csi_configs_init(
+               dev, inp, csi_configs)))
+                       return -EFAULT;
+
+       if (*pos)
+               return 0;
+
+       list_for_each(list_pos, csi_configs) {
+               cfg = list_entry(list_pos,
+                       struct cif_isp10_pltfrm_csi_config, list);
+               sprintf(cif_isp10_dbgfs_buf,
+                       "csi-config-%d:\n"
+                       "   pps = %d\n"
+                       "   vc = %d\n"
+                       "   nb_lanes = %d\n"
+                       "   dphy1 = 0x%08x\n"
+                       "   dphy2 = 0x%08x\n"
+                       "   ana_bandgap_bias = %d\n",
+                       index,
+                       cfg->pps, cfg->csi_config.vc, cfg->csi_config.nb_lanes,
+                       cfg->csi_config.dphy1, cfg->csi_config.dphy2,
+                       cfg->csi_config.ana_bandgab_bias);
+               index++;
+               str_len = strnlen(cif_isp10_dbgfs_buf,
+                       CIF_ISP10_DBGFS_BUF_SIZE);
+               if (str_len > count) {
+                       *pos += out_size;
+                       return 0;
+               }
+               *pos = 0;
+               if (IS_ERR_VALUE(simple_read_from_buffer(
+                       out + out_size, str_len, pos,
+                       cif_isp10_dbgfs_buf, str_len)))
+                       break;
+               out_size += strnlen(cif_isp10_dbgfs_buf,
+                       CIF_ISP10_DBGFS_BUF_SIZE);
+               count -= str_len;
+       }
+
+       *pos += out_size;
+       return out_size;
+}
+
+static ssize_t cif_isp10_dbgfs_csi_write(
+       struct file *f,
+       const char __user *in,
+       size_t count,
+       loff_t *pos)
+{
+       ssize_t ret;
+       char *strp = cif_isp10_dbgfs_buf;
+       char *token;
+       struct device *dev = f->f_inode->i_private;
+       struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+       struct list_head *csi_configs;
+       enum cif_isp10_inp inp;
+
+       if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
+               cif_isp10_pltfrm_pr_err(dev, "command line too large\n");
+               return -EINVAL;
+       }
+
+       if (f->f_inode == pdata->dbgfs.csi0_file->d_inode) {
+               csi_configs = &pdata->csi0_configs;
+               inp = CIF_ISP10_INP_CSI_0;
+       } else if (f->f_inode == pdata->dbgfs.csi1_file->d_inode) {
+               csi_configs = &pdata->csi1_configs;
+               inp = CIF_ISP10_INP_CSI_1;
+       } else {
+               cif_isp10_pltfrm_pr_err(dev, "wrong file handle\n");
+               return -EINVAL;
+       }
+
+       if (list_empty(csi_configs))
+               if (IS_ERR_VALUE(cif_isp10_dbgfs_csi_configs_init(
+               dev, inp, csi_configs)))
+                       return -EFAULT;
+
+       memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
+       ret = simple_write_to_buffer(strp,
+               CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       token = strsep(&strp, " ");
+       if (!strcmp(token, "push")) {
+               struct cif_isp10_pltfrm_csi_config cfg;
+
+               token = strsep(&strp, " ");
+               if (IS_ERR_OR_NULL(token)) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
+                       return -EINVAL;
+               }
+               if (IS_ERR_VALUE(kstrtou32(token, 10,
+                               &cfg.pps))) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
+                       return -EINVAL;
+               }
+               ret = cif_isp10_dbgfs_fill_csi_config_from_string(
+                       dev, &cfg.csi_config, strp);
+               if (IS_ERR_VALUE(ret))
+                       return ret;
+               ret = cif_isp10_pltfrm_l_s_csi_config(
+                       dev, inp, cfg.pps, &cfg.csi_config);
+               if (IS_ERR_VALUE(ret))
+                       return ret;
+       } else if (!strncmp(token, "reset", 5)) {
+       } else {
+               cif_isp10_pltfrm_pr_err(dev, "unknown command %s\n", token);
+               return -EINVAL;
+       }
+
+       return count;
+}
+
+void cif_isp10_dbgfs_fill_sensor_aec_para(
+       struct cif_isp10_device *cif_isp10_dev,
+       s32 exp_time,
+       u16 gain)
+{
+       struct cif_isp10_pltfrm_data *pdata;
+
+       pdata = (struct cif_isp10_pltfrm_data *)
+                       cif_isp10_dev->dev->platform_data;
+       pdata->exp_time = exp_time;
+       pdata->gain = gain;
+}
+
+static ssize_t cif_isp10_dbgfs_sensor_read(
+       struct file *f,
+       char __user *out,
+       size_t count,
+       loff_t *pos)
+{
+       u32 out_size = 0;
+       u32 str_len;
+       struct device *dev = f->f_inode->i_private;
+       struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+
+       if (*pos)
+               return 0;
+
+       sprintf(cif_isp10_dbgfs_buf,
+               "sensor current exp_time: %d\n"
+               "               gain = %d\n",
+               pdata->exp_time,
+               pdata->gain);
+       str_len = strnlen(cif_isp10_dbgfs_buf,
+                         CIF_ISP10_DBGFS_BUF_SIZE);
+       if (str_len > count) {
+               *pos += out_size;
+               return 0;
+       }
+       *pos = 0;
+       if (IS_ERR_VALUE(simple_read_from_buffer(
+               out + out_size, str_len, pos,
+               cif_isp10_dbgfs_buf, str_len)))
+               goto ERR;
+       out_size += strnlen(cif_isp10_dbgfs_buf,
+               CIF_ISP10_DBGFS_BUF_SIZE);
+       count -= str_len;
+
+       *pos += out_size;
+ERR:
+       return out_size;
+}
+
+static ssize_t cif_isp10_dbgfs_sensor_write(
+       struct file *f,
+       const char __user *in,
+       size_t count,
+       loff_t *pos)
+{
+       return 0;
+}
+
+static ssize_t cif_isp10_dbgfs_write(
+       struct file *f,
+       const char __user *in,
+       size_t count,
+       loff_t *pos)
+{
+       ssize_t ret;
+       char *strp = cif_isp10_dbgfs_buf;
+       char *token;
+       struct device *dev = f->f_inode->i_private;
+       struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+
+       if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
+               cif_isp10_pltfrm_pr_err(dev, "command line too large\n");
+               return -EINVAL;
+       }
+
+       memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
+       ret = simple_write_to_buffer(strp,
+               CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       token = strsep(&strp, " ");
+       if (!strncmp(token, "print", 5)) {
+               token = strsep(&strp, " ");
+               if (IS_ERR_OR_NULL(token)) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'print all|<list of block name>'\n");
+                       return -EINVAL;
+               }
+               if (!strncmp(token, "register", 8)) {
+                       u32 addr;
+                       struct cif_isp10_pltfrm_data *pdata =
+                               dev->platform_data;
+                       token = strsep(&strp, " ");
+                       while (token) {
+                               if (IS_ERR_VALUE(kstrtou32(token,
+                                       16, &addr))) {
+                                       cif_isp10_pltfrm_pr_err(dev,
+                                               "malformed token, must be a hexadecimal register address\n");
+                                       return -EINVAL;
+                               }
+                               pr_info("0x%04x: 0x%08x\n",
+                                       addr,
+                                       ioread32(pdata->base_addr +
+                                               addr));
+                               token = strsep(&strp, " ");
+                       }
+               } else if (pdata->dbgfs.print_func) {
+                       unsigned long flags;
+
+                       local_irq_save(flags);
+                       while (token) {
+                               pdata->dbgfs.print_func(
+                                       pdata->dbgfs.print_cntxt,
+                                       token);
+                               token = strsep(&strp, " ");
+                       }
+                       local_irq_restore(flags);
+               }
+       } else if (!strncmp(token, "power", 5)) {
+               token = strsep(&strp, " ");
+               if (IS_ERR_OR_NULL(token)) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'power [off|on]'\n");
+                       return -EINVAL;
+               }
+               if (!strncmp(token, "on", 2)) {
+                       if (IS_ERR_VALUE(cif_isp10_pltfrm_pm_set_state(dev,
+                               CIF_ISP10_PM_STATE_SW_STNDBY, NULL)))
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "power on failed\n");
+                       else
+                               cif_isp10_pltfrm_pr_info(dev,
+                                       "switched on\n");
+               } else if (!strncmp(token, "off", 3)) {
+                       if (IS_ERR_VALUE(cif_isp10_pltfrm_pm_set_state(dev,
+                               CIF_ISP10_PM_STATE_OFF, NULL)))
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "power off failed\n");
+                       else
+                               cif_isp10_pltfrm_pr_info(dev,
+                                       "switched off\n");
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'power [off|on]'\n");
+                       return -EINVAL;
+               }
+       } else if (!strncmp(token, "set", 3)) {
+               token = strsep(&strp, " ");
+               if (IS_ERR_OR_NULL(token)) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'set register <hex addr>=<hex val>'\n");
+                       return -EINVAL;
+               }
+               if (!strncmp(token, "register", 8)) {
+                       u32 addr;
+                       u32 val;
+                       struct cif_isp10_pltfrm_data *pdata =
+                               dev->platform_data;
+                       token = strsep(&strp, "=");
+                       if (IS_ERR_VALUE(kstrtou32(token,
+                               16, &addr))) {
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "malformed token, address must be a hexadecimal register address\n");
+                               return -EINVAL;
+                       }
+                       token = strp;
+                       if (IS_ERR_VALUE(kstrtou32(token,
+                               16, &val))) {
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "malformed token, value must be a hexadecimal value\n");
+                               return -EINVAL;
+                       }
+                       iowrite32(val, pdata->base_addr + addr);
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "unknown command %s\n", token);
+                       return -EINVAL;
+               }
+       } else {
+               cif_isp10_pltfrm_pr_err(dev,
+                       "unknown command %s\n", token);
+               return -EINVAL;
+       }
+       return count;
+}
+
+static const struct file_operations cif_isp10_dbgfs_csi_fops = {
+       .read = cif_isp10_dbgfs_csi_read,
+       .write = cif_isp10_dbgfs_csi_write
+};
+
+static const struct file_operations cif_isp10_dbgfs_fops = {
+       .write = cif_isp10_dbgfs_write
+};
+
+static const struct file_operations cif_isp10_dbgfs_sensor_fops = {
+       .read = cif_isp10_dbgfs_sensor_read,
+       .write = cif_isp10_dbgfs_sensor_write
+};
+
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+
+static inline int cif_isp10_pltfrm_trace_printf(
+       struct device *dev,
+       const char *fmt,
+       va_list args)
+{
+       int i;
+       u32 rem_size;
+       unsigned long flags = 0;
+
+       if (!in_irq())
+               spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
+       cif_isp10_reg_trace.internal = true;
+
+       rem_size = cif_isp10_reg_trace.reg_trace_max_size -
+               cif_isp10_reg_trace.reg_trace_write_pos;
+
+       if (rem_size <= 0) {
+               if (!in_irq())
+                       spin_unlock_irqrestore(
+                               &cif_isp10_reg_trace.lock, flags);
+               cif_isp10_reg_trace.internal = false;
+               return 0;
+       }
+
+       i = vsnprintf(cif_isp10_reg_trace.reg_trace +
+               cif_isp10_reg_trace.reg_trace_write_pos,
+               rem_size,
+               fmt, args);
+       if (i == rem_size) /* buffer full */
+               i = 0;
+       else if (i < 0)
+               cif_isp10_pltfrm_pr_err(dev,
+                       "error writing trace buffer, error %d\n", i);
+       else
+               cif_isp10_reg_trace.reg_trace_write_pos += i;
+       cif_isp10_reg_trace.internal = false;
+       if (!in_irq())
+               spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
+
+       return i;
+}
+
+inline int cif_isp10_pltfrm_rtrace_printf(
+       struct device *dev,
+       const char *fmt,
+       ...)
+{
+       va_list args;
+       int i;
+
+       va_start(args, fmt);
+       i = cif_isp10_pltfrm_trace_printf(dev, fmt, args);
+       va_end(args);
+
+       return i;
+}
+
+inline int cif_isp10_pltfrm_ftrace_printf(
+       struct device *dev,
+       const char *fmt,
+       ...)
+{
+       va_list args;
+       int i;
+
+       if (!cif_isp10_reg_trace.ftrace ||
+               cif_isp10_reg_trace.internal)
+               return 0;
+
+       va_start(args, fmt);
+       i = cif_isp10_pltfrm_trace_printf(dev, fmt, args);
+       va_end(args);
+
+       return i;
+}
+
+static void cif_isp10_dbgfs_reg_trace_clear(
+       struct device *dev)
+{
+       cif_isp10_reg_trace.reg_trace_write_pos = 0;
+       cif_isp10_reg_trace.reg_trace_read_pos = 0;
+}
+
+static ssize_t cif_isp10_dbgfs_reg_trace_read(
+       struct file *f,
+       char __user *out,
+       size_t count,
+       loff_t *pos)
+{
+       ssize_t bytes;
+       size_t available = cif_isp10_reg_trace.reg_trace_write_pos -
+               cif_isp10_reg_trace.reg_trace_read_pos;
+       size_t rem = count;
+
+       cif_isp10_reg_trace.internal = true;
+
+       if (!available)
+               cif_isp10_reg_trace.reg_trace_read_pos = 0;
+
+       while (rem && available) {
+               bytes = simple_read_from_buffer(
+                       out + (count - rem), count,
+                       &cif_isp10_reg_trace.reg_trace_read_pos,
+                       cif_isp10_reg_trace.reg_trace,
+                       cif_isp10_reg_trace.reg_trace_write_pos);
+               if (bytes < 0) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "buffer read failed with error %d\n",
+                               bytes);
+                       cif_isp10_reg_trace.internal = false;
+                       return bytes;
+               }
+               rem -= bytes;
+               available = cif_isp10_reg_trace.reg_trace_write_pos -
+                       cif_isp10_reg_trace.reg_trace_read_pos;
+       }
+
+       cif_isp10_reg_trace.internal = false;
+       return count - rem;
+}
+
+static ssize_t cif_isp10_dbgfs_reg_trace_write(
+       struct file *f,
+       const char __user *in,
+       size_t count,
+       loff_t *pos)
+{
+       ssize_t ret;
+       char *strp = cif_isp10_dbgfs_buf;
+       char *token;
+       struct device *dev = f->f_inode->i_private;
+       u32 max_size;
+       unsigned long flags = 0;
+
+       if (!in_irq())
+               spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
+
+       cif_isp10_reg_trace.internal = true;
+
+       if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
+               cif_isp10_pltfrm_pr_err(dev, "command line too long\n");
+               return -EINVAL;
+       }
+
+       memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
+       ret = simple_write_to_buffer(strp,
+               CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       token = strsep(&strp, " ");
+       if (!strncmp(token, "clear", 5)) {
+               cif_isp10_dbgfs_reg_trace_clear(dev);
+               cif_isp10_pltfrm_pr_info(dev,
+                       "register trace buffer cleared\n");
+       } else if (!strcmp(token, "size")) {
+               token = strsep(&strp, " ");
+               if (IS_ERR_OR_NULL(token)) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'size <num entries>'\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+               if (IS_ERR_VALUE(kstrtou32(token, 10,
+                               &max_size))) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "wrong token format, <num entries> must be positive integer>'\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+               if (cif_isp10_reg_trace.reg_trace) {
+                       devm_kfree(dev, cif_isp10_reg_trace.reg_trace);
+                       cif_isp10_reg_trace.reg_trace = NULL;
+               }
+               cif_isp10_dbgfs_reg_trace_clear(dev);
+               if (max_size > 0) {
+                       cif_isp10_reg_trace.reg_trace = devm_kzalloc(dev,
+                               max_size, GFP_KERNEL);
+                       if (!cif_isp10_reg_trace.reg_trace) {
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "memory allocation failed\n");
+                               ret = -ENOMEM;
+                               goto err;
+                       }
+                       cif_isp10_reg_trace.reg_trace_max_size = max_size;
+                       cif_isp10_pltfrm_pr_info(dev,
+                               "register trace buffer size set to %d Byte\n",
+                               max_size);
+               }
+       } else if (!strncmp(token, "rtrace", 6)) {
+               token = strsep(&strp, " ");
+               if (IS_ERR_OR_NULL(token)) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'rtrace [off|on]'\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+               if (!strncmp(token, "on", 2)) {
+                       cif_isp10_reg_trace.rtrace = true;
+                       cif_isp10_pltfrm_pr_info(dev,
+                               "register trace enabled\n");
+               } else if (!strncmp(token, "off", 3)) {
+                       cif_isp10_reg_trace.rtrace = false;
+                       cif_isp10_pltfrm_pr_info(dev,
+                               "register trace disabled\n");
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'rtrace [off|on]'\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else if (!strncmp(token, "ftrace", 6)) {
+               token = strsep(&strp, " ");
+               if (IS_ERR_OR_NULL(token)) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'ftrace [off|on]'\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+               if (!strncmp(token, "on", 2)) {
+                       cif_isp10_reg_trace.ftrace = true;
+                       cif_isp10_pltfrm_pr_info(dev,
+                               "function trace enabled\n");
+               } else if (!strncmp(token, "off", 3)) {
+                       cif_isp10_reg_trace.ftrace = false;
+                       cif_isp10_pltfrm_pr_info(dev,
+                               "function trace disabled\n");
+               } else {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "missing token, command format is 'ftrace [off|on]'\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+       } else {
+               cif_isp10_pltfrm_pr_err(dev, "unknown command %s\n", token);
+               ret = -EINVAL;
+               goto err;
+       }
+       cif_isp10_reg_trace.internal = false;
+       if (!in_irq())
+               spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
+       return count;
+err:
+       cif_isp10_reg_trace.internal = false;
+       if (!in_irq())
+               spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
+       return ret;
+}
+
+static const struct file_operations
+cif_isp10_dbgfs_reg_trace_fops = {
+       .read = cif_isp10_dbgfs_reg_trace_read,
+       .write = cif_isp10_dbgfs_reg_trace_write
+};
+
+#endif
+#endif
+
+static irqreturn_t cif_isp10_pltfrm_irq_handler(int irq, void *cntxt)
+{
+       unsigned int i, mis_val;
+       int ret;
+       struct device *dev = cntxt;
+       struct cif_isp10_pltfrm_data *pdata =
+               dev_get_platdata(dev);
+       void *cif_isp10_dev = dev_get_drvdata(dev);
+
+       if (irq != pdata->irq)
+               return IRQ_NONE;
+
+       for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++) {
+               if (IS_ERR_VALUE(pdata->irq_handlers[i].mis))
+                       break;
+
+               if (IS_ERR_OR_NULL(pdata->irq_handlers[i].isr)) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "ISR for IRQ #%d not set\n", irq);
+                       break;
+               }
+
+               mis_val = cif_ioread32(pdata->base_addr +
+                       pdata->irq_handlers[i].mis);
+               if (mis_val == 0)
+                       continue;
+
+               ret = pdata->irq_handlers[i].isr(mis_val, cif_isp10_dev);
+               if (IS_ERR_VALUE(ret)) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "ISR for IRQ #%d failed with error %d\n",
+                               irq, ret);
+               }
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
+const char *cif_isp10_pltfrm_pm_state_string(
+       enum cif_isp10_pm_state pm_state)
+{
+       switch (pm_state) {
+       case CIF_ISP10_PM_STATE_OFF:
+               return "CIF_ISP10_PM_STATE_OFF";
+       case CIF_ISP10_PM_STATE_SUSPENDED:
+               return "CIF_ISP10_PM_STATE_SUSPENDED";
+       case CIF_ISP10_PM_STATE_SW_STNDBY:
+               return "CIF_ISP10_PM_STATE_SW_STNDBY";
+       case CIF_ISP10_PM_STATE_STREAMING:
+               return "CIF_ISP10_PM_STATE_STREAMING";
+       default:
+               return "PM_STATE_UNKNOWN";
+       }
+}
+
+inline void cif_isp10_pltfrm_write_reg(
+       struct device *dev,
+       u32 data,
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
+{
+       iowrite32(data, addr);
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+       {
+               unsigned long flags = 0;
+
+               if (!in_irq())
+                       spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
+               cif_isp10_reg_trace.internal = true;
+               if (((cif_isp10_reg_trace.reg_trace_write_pos +
+                       (20 * sizeof(char))) <
+                       cif_isp10_reg_trace.reg_trace_max_size) &&
+                       cif_isp10_reg_trace.rtrace) {
+                       int bytes =
+                               sprintf(cif_isp10_reg_trace.reg_trace +
+                                       cif_isp10_reg_trace.reg_trace_write_pos,
+                                       "%04x %08x\n",
+                                       addr - cif_isp10_reg_trace.base_addr,
+                                       data);
+                       if (bytes > 0)
+                               cif_isp10_reg_trace.reg_trace_write_pos +=
+                                       bytes;
+                       else
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "error writing trace buffer, error %d\n",
+                                       bytes);
+               }
+               cif_isp10_reg_trace.internal = false;
+               if (!in_irq())
+                       spin_unlock_irqrestore(
+                               &cif_isp10_reg_trace.lock, flags);
+       }
+#endif
+}
+
+inline void cif_isp10_pltfrm_write_reg_OR(
+       struct device *dev,
+       u32 data,
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
+{
+       cif_isp10_pltfrm_write_reg(dev,
+               (ioread32(addr) | data), addr);
+}
+
+inline void cif_isp10_pltfrm_write_reg_AND(
+       struct device *dev,
+       u32 data,
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
+{
+       cif_isp10_pltfrm_write_reg(dev,
+               (ioread32(addr) & data), addr);
+}
+
+inline u32 cif_isp10_pltfrm_read_reg(
+       struct device *dev,
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
+{
+       return ioread32(addr);
+}
+
+int cif_isp10_pltfrm_dev_init(
+       struct cif_isp10_device *cif_isp10_dev,
+       struct device **_dev,
+       void __iomem **reg_base_addr)
+{
+       int ret;
+       struct cif_isp10_pltfrm_data *pdata;
+       struct device *dev = *_dev;
+       struct platform_device *pdev =
+               container_of(dev, struct platform_device, dev);
+       struct resource *res;
+       void __iomem *base_addr;
+       unsigned int i, irq;
+
+       dev_set_drvdata(dev, cif_isp10_dev);
+       cif_isp10_dev->dev = dev;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               cif_isp10_pltfrm_pr_err(dev,
+                       "could not allocate memory for platform data\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "register");
+       if (!res) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "platform_get_resource_byname failed\n");
+               ret = -ENODEV;
+               goto err;
+       }
+       base_addr = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR_OR_NULL(base_addr)) {
+               cif_isp10_pltfrm_pr_err(NULL, "devm_ioremap_resource failed\n");
+               if (IS_ERR(base_addr))
+                       ret = PTR_ERR(base_addr);
+               else
+                       ret = -ENODEV;
+       }
+       *reg_base_addr = base_addr;
+       pdata->base_addr = base_addr;
+
+       irq = platform_get_irq_byname(pdev, "cif_isp10_irq");
+       if (IS_ERR_VALUE(irq)) {
+               ret = irq;
+               cif_isp10_pltfrm_pr_err(NULL,
+               "platform_get_irq_byname failed\n");
+               goto err;
+       }
+
+       ret = devm_request_threaded_irq(dev,
+                       irq,
+                       cif_isp10_pltfrm_irq_handler,
+                       NULL,
+                       0,
+                       dev_driver_string(dev),
+                       dev);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+               "devm_request_threaded_irq failed\n");
+               goto err;
+       }
+       pdata->irq = irq;
+
+       pdata->pinctrl = devm_pinctrl_get(dev);
+       if (!IS_ERR_OR_NULL(pdata->pinctrl)) {
+               pdata->pins_default = pinctrl_lookup_state(pdata->pinctrl,
+                       PINCTRL_STATE_DEFAULT);
+               if (IS_ERR(pdata->pins_default))
+                       cif_isp10_pltfrm_pr_err(dev,
+                                               "could not get default pinstate\n");
+
+               pdata->pins_sleep = pinctrl_lookup_state(pdata->pinctrl,
+                       PINCTRL_STATE_SLEEP);
+               if (IS_ERR(pdata->pins_sleep))
+                       cif_isp10_pltfrm_pr_warn(dev,
+                                               "could not get pins_sleep pinstate\n");
+
+               pdata->pins_inactive = pinctrl_lookup_state(pdata->pinctrl,
+                       "inactive");
+               if (IS_ERR(pdata->pins_inactive))
+                       cif_isp10_pltfrm_pr_warn(dev,
+                                               "could not get pins_inactive pinstate\n");
+
+               if (!IS_ERR_OR_NULL(pdata->pins_default))
+                       pinctrl_select_state(pdata->pinctrl,
+                               pdata->pins_default);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++)
+               pdata->irq_handlers[i].mis = -EINVAL;
+
+       dev->platform_data = pdata;
+
+       INIT_LIST_HEAD(&pdata->csi0_configs);
+       INIT_LIST_HEAD(&pdata->csi1_configs);
+
+#ifndef CONFIG_DEBUG_FS
+       pdata->dbgfs.dir = debugfs_create_dir("cif_isp10", NULL);
+       pdata->dbgfs.csi0_file = debugfs_create_file(
+               "csi-0",
+               0644,
+               pdata->dbgfs.dir,
+               dev,
+               &cif_isp10_dbgfs_csi_fops);
+       pdata->dbgfs.csi1_file = debugfs_create_file(
+               "csi-1",
+               0644,
+               pdata->dbgfs.dir,
+               dev,
+               &cif_isp10_dbgfs_csi_fops);
+       pdata->dbgfs.cif_isp10_file = debugfs_create_file(
+               "cif_isp20",
+               0200,
+               pdata->dbgfs.dir,
+               dev,
+               &cif_isp10_dbgfs_fops);
+       pdata->dbgfs.cif_isp10_file = debugfs_create_file(
+               "sensor",
+               0644,
+               pdata->dbgfs.dir,
+               dev,
+               &cif_isp10_dbgfs_sensor_fops);
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+       pdata->dbgfs.reg_trace_file = debugfs_create_file(
+               "reg_trace",
+               0644,
+               pdata->dbgfs.dir,
+               dev,
+               &cif_isp10_dbgfs_reg_trace_fops);
+       spin_lock_init(&cif_isp10_reg_trace.lock);
+       cif_isp10_reg_trace.reg_trace = NULL;
+       cif_isp10_dbgfs_reg_trace_clear(dev);
+       cif_isp10_reg_trace.reg_trace_max_size = 0;
+       cif_isp10_reg_trace.base_addr = base_addr;
+       cif_isp10_reg_trace.rtrace = true;
+       cif_isp10_reg_trace.ftrace = false;
+       cif_isp10_reg_trace.internal = false;
+#endif
+#endif
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+       if (!IS_ERR_OR_NULL(pdata))
+               devm_kfree(dev, pdata);
+       return ret;
+}
+
+int cif_isp10_pltfrm_soc_init(
+       struct cif_isp10_device *cif_isp10_dev,
+       struct pltfrm_soc_cfg *soc_cfg)
+{
+       struct pltfrm_soc_cfg_para cfg_para;
+       struct device *dev = cif_isp10_dev->dev;
+       struct platform_device *pdev =
+               container_of(dev, struct platform_device, dev);
+       struct pltfrm_soc_init_para init_para;
+       int ret = 0;
+
+       if (!IS_ERR_OR_NULL(soc_cfg) && !IS_ERR_OR_NULL(soc_cfg->soc_cfg)) {
+               cfg_para.cmd = PLTFRM_SOC_INIT;
+               cfg_para.cfg_para = &init_para;
+               init_para.pdev = pdev;
+               init_para.isp_base = cif_isp10_dev->config.base_addr;
+               ret = soc_cfg->soc_cfg(&cfg_para);
+               if (ret == 0)
+                       cif_isp10_dev->soc_cfg = soc_cfg;
+       }
+
+       return ret;
+}
+
+int cif_isp10_pltfrm_mipi_dphy_config(
+       struct cif_isp10_device *cif_isp10_dev)
+{
+       struct pltfrm_soc_cfg_para cfg_para;
+       struct pltfrm_soc_cfg *soc_cfg;
+       int ret = 0;
+
+       soc_cfg = cif_isp10_dev->soc_cfg;
+       if (!IS_ERR_OR_NULL(soc_cfg) &&
+               !IS_ERR_OR_NULL(soc_cfg->soc_cfg)) {
+               cfg_para.cmd =
+                       PLTFRM_MIPI_DPHY_CFG;
+               cfg_para.cfg_para =
+                       (void *)(&cif_isp10_dev->config.cam_itf.cfg.mipi);
+               ret = soc_cfg->soc_cfg(&cfg_para);
+       }
+
+       return ret;
+}
+
+int cif_isp10_pltfrm_pm_set_state(
+       struct device *dev,
+       enum cif_isp10_pm_state pm_state)
+{
+       int ret;
+       struct cif_isp10_device *cif_isp10_dev = dev_get_drvdata(dev);
+       struct pltfrm_soc_cfg *soc_cfg = cif_isp10_dev->soc_cfg;
+       struct pltfrm_soc_cfg_para cfg_para;
+
+       switch (pm_state) {
+       case CIF_ISP10_PM_STATE_OFF:
+       case CIF_ISP10_PM_STATE_SUSPENDED:
+               cfg_para.cmd = PLTFRM_CLKDIS;
+               cfg_para.cfg_para = NULL;
+               ret = soc_cfg->soc_cfg(&cfg_para);
+               break;
+       case CIF_ISP10_PM_STATE_SW_STNDBY:
+       case CIF_ISP10_PM_STATE_STREAMING:
+               cfg_para.cmd = PLTFRM_CLKEN;
+               cfg_para.cfg_para = NULL;
+               ret = soc_cfg->soc_cfg(&cfg_para);
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(dev,
+                       "unknown or unsupported PM state %d\n", pm_state);
+               return -EINVAL;
+       }
+
+       if (IS_ERR_VALUE(ret))
+               cif_isp10_pltfrm_pr_err(dev,
+                       "setting pm state to %s failed with error %d\n",
+                       cif_isp10_pltfrm_pm_state_string(pm_state), ret);
+       else
+               cif_isp10_pltfrm_pr_dbg(dev,
+                       "successfully changed pm state to %s\n",
+                       cif_isp10_pltfrm_pm_state_string(pm_state));
+       return ret;
+}
+
+int cif_isp10_pltfrm_g_interface_config(
+       struct cif_isp10_img_src *img_src,
+       struct pltfrm_cam_itf *cam_itf)
+{
+       int ret = 0;
+
+       ret = cif_isp10_img_src_ioctl(img_src,
+                       PLTFRM_CIFCAM_G_ITF_CFG, (void *)cam_itf);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(
+                       dev,
+                       "cif_isp10_img_src_ioctl PLTFRM_CIFCAM_G_ITF_CFG failed!\n");
+               return ret;
+       }
+       return 0;
+}
+
+int cif_isp10_pltfrm_pinctrl_set_state(
+       struct device *dev,
+       enum cif_isp10_pinctrl_state pinctrl_state)
+{
+       int ret = 0;
+       struct cif_isp10_pltfrm_data *pdata = dev_get_platdata(dev);
+
+       cif_isp10_pltfrm_pr_dbg(dev,
+               "set pinctrl state to %d\n", pinctrl_state);
+
+       if (!pdata) {
+               cif_isp10_pltfrm_pr_err(dev,
+                       "unable to retrieve CIF platform data\n");
+               ret = -EINVAL;
+               goto err;
+       }
+       if (IS_ERR_OR_NULL(pdata->pinctrl))
+               return 0;
+
+       switch (pinctrl_state) {
+       case CIF_ISP10_PINCTRL_STATE_SLEEP:
+               if (!IS_ERR_OR_NULL(pdata->pins_sleep))
+                       ret = pinctrl_select_state(pdata->pinctrl,
+                               pdata->pins_sleep);
+               break;
+       case CIF_ISP10_PINCTRL_STATE_ACTIVE:
+       case CIF_ISP10_PINCTRL_STATE_DEFAULT:
+               if (!IS_ERR_OR_NULL(pdata->pins_default))
+                       ret = pinctrl_select_state(pdata->pinctrl,
+                               pdata->pins_default);
+               break;
+       case CIF_ISP10_PINCTRL_STATE_INACTIVE:
+               if (!IS_ERR_OR_NULL(pdata->pins_inactive))
+                       ret = pinctrl_select_state(pdata->pinctrl,
+                               pdata->pins_inactive);
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(dev,
+                       "unknown or unsupported pinctrl state %d\n",
+                       pinctrl_state);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev, "failed with error %d\n", ret);
+       return ret;
+}
+
+int cif_isp10_pltfrm_irq_register_isr(
+       struct device *dev,
+       unsigned int mis,
+       int (*isr)(unsigned int mis, void *cntxt),
+       void *cntxt)
+{
+       int ret = 0;
+       unsigned int i;
+       int slot = -EINVAL;
+       struct platform_device *pdev =
+               container_of(dev, struct platform_device, dev);
+       struct cif_isp10_pltfrm_data *pdata =
+               dev_get_platdata(&pdev->dev);
+       bool skip_request_irq = false;
+       const char *irq_name;
+
+       switch (mis) {
+       case CIF_MIPI_MIS:
+               irq_name = "CIF_ISP10_MIPI_IRQ";
+               break;
+       case CIF_ISP_MIS:
+               irq_name = "CIF_ISP10_ISP_IRQ";
+               break;
+       case CIF_MI_MIS:
+               irq_name = "CIF_ISP10_MI_IRQ";
+               break;
+       default:
+               cif_isp10_pltfrm_pr_err(dev,
+                       "unknown or unsupported IRQ %d\n", mis);
+               ret = -EINVAL;
+               goto err;
+       }
+       cif_isp10_pltfrm_pr_dbg(dev,
+               "registering ISR for IRQ %s\n", irq_name);
+
+       for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++) {
+               if (IS_ERR_VALUE(slot) &&
+                       IS_ERR_VALUE(pdata->irq_handlers[i].mis))
+                       slot = (int)i;
+               if (pdata->irq_handlers[i].mis == mis) {
+                       cif_isp10_pltfrm_pr_dbg(dev,
+                               "overwriting ISR for IRQ %s\n", irq_name);
+                       slot = (int)i;
+                       skip_request_irq = true;
+                       break;
+               }
+       }
+       if (IS_ERR_VALUE(slot)) {
+               if (!isr)
+                       return 0;
+               cif_isp10_pltfrm_pr_err(dev,
+                       "cannot register ISR for IRQ %s, too many ISRs already registered\n",
+                       irq_name);
+               ret = -EFAULT;
+               goto err;
+       }
+       pdata->irq_handlers[slot].isr = isr;
+       if (!isr) {
+               pdata->irq_handlers[slot].mis = -EINVAL;
+               skip_request_irq = true;
+       } else {
+               pdata->irq_handlers[slot].mis = mis;
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(dev, "failed with error %d\n", ret);
+       return ret;
+}
+
+const char *cif_isp10_pltfrm_get_device_type(
+       struct device *dev)
+{
+       return dev->of_node->type;
+}
+
+const char *cif_isp10_pltfrm_dev_string(
+       struct device *dev)
+{
+       return dev_driver_string(dev);
+}
+
+int cif_isp10_pltfrm_get_img_src_device(
+       struct device *dev,
+       struct cif_isp10_img_src **img_src_array,
+       unsigned int array_len)
+{
+       struct device_node *node = NULL;
+       struct device_node *camera_list_node = NULL;
+       struct i2c_client *client = NULL;
+       int ret = 0;
+       int index, size = 0;
+       const __be32 *phandle;
+       int num_cameras = 0;
+       struct cif_isp10_device *cif_isp10_dev = dev_get_drvdata(dev);
+
+       node = of_node_get(dev->of_node);
+       if (IS_ERR_OR_NULL(node)) {
+               dev_err(dev, "Unable to obtain CIF device node\n");
+               ret = -EEXIST;
+               goto err;
+       }
+
+       phandle = of_get_property(node,
+               "rockchip,camera-modules-attached", &size);
+       if (IS_ERR_OR_NULL(phandle)) {
+               cif_isp10_pltfrm_pr_err(dev,
+                       "no camera-modules-attached'\n");
+                       ret = -EINVAL;
+                       goto err;
+       }
+
+       for (index = 0; index < size / sizeof(*phandle); index++) {
+               camera_list_node = of_parse_phandle(node,
+                       "rockchip,camera-modules-attached", index);
+               of_node_put(node);
+               if (IS_ERR_OR_NULL(camera_list_node)) {
+                       cif_isp10_pltfrm_pr_err(dev,
+                               "invalid index %d for property 'rockchip,camera-modules-attached'\n",
+                               index);
+                               ret = -EINVAL;
+                               goto err;
+               }
+
+               if (!strcmp(camera_list_node->type,
+                                       "v4l2-i2c-subdev")) {
+                       client = of_find_i2c_device_by_node(
+                               camera_list_node);
+                       of_node_put(camera_list_node);
+                       if (IS_ERR_OR_NULL(client)) {
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "could not get camera i2c client, maybe not yet created, deferring device probing...\n");
+                               continue;
+                       }
+               } else {
+                       cif_isp10_pltfrm_pr_dbg(dev,
+                               "device of type %s not supported\n",
+                               camera_list_node->type);
+                       of_node_put(camera_list_node);
+                       continue;
+               }
+
+               img_src_array[num_cameras] =
+                       cif_isp10_img_src_to_img_src(
+                               &client->dev,
+                               cif_isp10_dev->soc_cfg);
+               if (!IS_ERR_OR_NULL(img_src_array[num_cameras])) {
+                       cif_isp10_pltfrm_pr_info(dev,
+                               "%s attach to cif isp10 img_src_array[%d]\n",
+                               cif_isp10_img_src_g_name(
+                                       img_src_array[num_cameras]),
+                               num_cameras);
+                       num_cameras++;
+                       if (num_cameras >= array_len) {
+                               cif_isp10_pltfrm_pr_err(dev,
+                                       "cif isp10 isn't support > %d 'camera modules attached'\n",
+                                       array_len);
+                               break;
+                       }
+               } else {
+                       continue;
+               }
+       }
+
+       return num_cameras;
+err:
+       dev_err(dev, "failed with error %d\n", ret);
+       if (!IS_ERR_OR_NULL(client))
+               put_device(&client->dev);
+       if (!IS_ERR_OR_NULL(camera_list_node))
+               of_node_put(camera_list_node);
+       return ret;
+}
+
+void cif_isp10_pltfrm_dev_release(
+       struct device *dev)
+{
+#ifndef CONFIG_DEBUG_FS
+       {
+               struct cif_isp10_pltfrm_data *pdata =
+                       dev->platform_data;
+               debugfs_remove(pdata->dbgfs.csi0_file);
+               debugfs_remove(pdata->dbgfs.csi1_file);
+               debugfs_remove_recursive(pdata->dbgfs.dir);
+       }
+#endif
+}
+
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.h b/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.h
new file mode 100644 (file)
index 0000000..4a20547
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_PLTFRM_H
+#define _CIF_ISP10_PLTFRM_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/platform_data/rk_isp10_platform.h>
+
+struct cif_isp10_strm_fmt;
+struct cif_isp10_csi_config;
+struct cif_isp10_device;
+struct cif_isp10_img_src;
+struct pltfrm_cam_itf;
+enum cif_isp10_pinctrl_state;
+enum cif_isp10_inp;
+enum cif_isp10_pm_state;
+
+#define CIF_ISP10_PLTFRM_DEVICE struct device *
+#define CIF_ISP10_PLTFRM_MEM_IO_ADDR void __iomem *
+#define CIF_ISP10_PLTFRM_EVENT wait_queue_head_t
+
+extern spinlock_t iowrite32_verify_lock;
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+int
+cif_isp10_pltfrm_rtrace_printf(
+       struct device *dev,
+       const char *fmt,
+       ...);
+
+int
+cif_isp10_pltfrm_ftrace_printf(
+       struct device *dev,
+       const char *fmt,
+       ...);
+
+#else
+#define cif_isp10_pltfrm_rtrace_printf(dev, str, ...)
+#define cif_isp10_pltfrm_ftrace_printf(dev, str, ...)
+#endif
+
+#define cif_isp10_pltfrm_pr_dbg(dev, fmt, arg...) \
+       do { \
+               pr_debug("%s: " fmt, \
+                       __func__, ## arg); \
+               cif_isp10_pltfrm_ftrace_printf(dev, "%s: " fmt, \
+                       __func__, ## arg); \
+       } while (0)
+#define cif_isp10_pltfrm_pr_info(dev, fmt, arg...) \
+       do { \
+               pr_info("%s: " fmt, \
+                       __func__, ## arg); \
+               cif_isp10_pltfrm_ftrace_printf(dev, "%s: " fmt, \
+                       __func__, ## arg); \
+       } while (0)
+#define cif_isp10_pltfrm_pr_warn(dev, fmt, arg...) \
+       do { \
+               pr_warn("%s WARN: " fmt, \
+                       __func__, ## arg); \
+               cif_isp10_pltfrm_ftrace_printf(dev, "%s WARN: " fmt, \
+                       __func__, ## arg); \
+       } while (0)
+#define cif_isp10_pltfrm_pr_err(dev, fmt, arg...) \
+       do { \
+               pr_err("%s(%d) ERR: " fmt, \
+                       __func__, __LINE__, ## arg); \
+               cif_isp10_pltfrm_ftrace_printf(dev, "%s(%d) ERR: " fmt, \
+                       __func__, __LINE__, ## arg); \
+       } while (0)
+
+void cif_isp10_pltfrm_write_reg(
+       struct device *dev,
+       u32 data,
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR addr);
+
+void cif_isp10_pltfrm_write_reg_OR(
+       struct device *dev,
+       u32 data,
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR addr);
+
+void cif_isp10_pltfrm_write_reg_AND(
+       struct device *dev,
+       u32 data,
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR addr);
+
+u32 cif_isp10_pltfrm_read_reg(
+       struct device *dev,
+       CIF_ISP10_PLTFRM_MEM_IO_ADDR addr);
+
+#define cif_iowrite32(d, a) \
+       cif_isp10_pltfrm_write_reg(NULL, (u32)(d), a)
+#define cif_ioread32(a) \
+       cif_isp10_pltfrm_read_reg(NULL, a)
+#define cif_iowrite32OR(d, a) \
+       cif_isp10_pltfrm_write_reg_OR(NULL, (u32)(d), a)
+#define cif_iowrite32AND(d, a) \
+       cif_isp10_pltfrm_write_reg_AND(NULL, (u32)(d), a)
+/* BUG: Register write seems to fail sometimes w/o read before write. */
+#define cif_iowrite32_verify(d, a, mask) \
+       { \
+               unsigned int i = 0; \
+               unsigned long flags = 0; \
+               spin_lock_irqsave(&iowrite32_verify_lock, flags); \
+               do { \
+                       cif_iowrite32(d, a); \
+                       udelay(1); \
+                       if (i++ == 50) { \
+                               pr_err("Error in writing %x@0x%p, read %x\n", \
+                                       (d) & (mask), a, ioread32(a)); \
+                                       WARN_ON(1); \
+                       } \
+               } while ((ioread32(a) & mask) != ((d) & mask)); \
+               spin_unlock_irqrestore(&iowrite32_verify_lock, flags);\
+       }
+#define cif_iowrite32OR_verify(d, a, mask) \
+       cif_iowrite32_verify((u32)(d) | cif_ioread32(a), a, mask)
+#define cif_iowrite32AND_verify(d, a, mask) \
+       cif_iowrite32_verify((u32)(d) & cif_ioread32(a), a, mask)
+
+#define cif_isp10_pltfrm_event_init(_dev, _event) \
+       init_waitqueue_head(_event)
+
+#define cif_isp10_pltfrm_event_clear(_dev, _event)
+
+#define cif_isp10_pltfrm_event_signal(_dev, _event) \
+       wake_up_interruptible(_event)
+
+#define cif_isp10_pltfrm_event_wait_timeout( \
+       _dev, _event, _condition, _timeout_us) \
+       wait_event_interruptible_timeout( \
+               *(_event), _condition, ((_timeout_us) * HZ) / 1000000)
+
+void
+cif_isp10_pltfrm_debug_register_print_cb(
+       struct device *dev,
+       void (*print)(void *cntxt, const char *block_name),
+       void *cntxt);
+
+int cif_isp10_pltfrm_dev_init(
+       struct cif_isp10_device *cif_isp_dev,
+       struct device **dev,
+       void __iomem **reg_base_addr);
+
+void cif_isp10_pltfrm_dev_release(
+       struct device *dev);
+
+int cif_isp10_pltfrm_pm_set_state(
+       struct device *dev,
+       enum cif_isp10_pm_state state);
+
+int cif_isp10_pltfrm_write_cif_ana_bandgap_bias(
+       struct device *dev,
+       u32 val);
+
+int cif_isp10_pltfrm_pinctrl_set_state(
+       struct device *dev,
+       enum cif_isp10_pinctrl_state pinctrl_state);
+
+int cif_isp10_pltfrm_get_img_src_device(
+       struct device *dev,
+       struct cif_isp10_img_src **img_src_array,
+       unsigned int array_len);
+
+int cif_isp10_pltfrm_g_interface_config(
+       struct cif_isp10_img_src *img_src,
+       struct pltfrm_cam_itf *cam_itf);
+
+int cif_isp10_pltfrm_irq_register_isr(
+       struct device *dev,
+       unsigned int mis,
+       int (*isr)(unsigned int mis, void *cntxt),
+       void *cntxt);
+
+const char *cif_isp10_pltfrm_get_device_type(
+       struct device *dev);
+
+const char *cif_isp10_pltfrm_dev_string(
+       struct device *dev);
+
+int cif_isp10_pltfrm_soc_init(
+       struct cif_isp10_device *cif_isp10_dev,
+       struct pltfrm_soc_cfg *soc_cfg);
+
+int cif_isp10_pltfrm_mipi_dphy_config(
+       struct cif_isp10_device *cif_isp10_dev);
+
+#endif
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_regs.h b/drivers/media/platform/rk-isp10/cif_isp10_regs.h
new file mode 100644 (file)
index 0000000..f5ac74f
--- /dev/null
@@ -0,0 +1,1203 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _RK_CIF_ISP10_REGS_H
+#define _RK_CIF_ISP10_REGS_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           BIT(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_GAMMA_IN_DIS          (0 << 6)
+#define CIF_ISP_CTRL_ISP_AWB_ENA               BIT(7)
+#define CIF_ISP_CTRL_ISP_AWB_DIS               (0 << 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_GAMMA_OUT_DIS         (0 << 11)
+#define CIF_ISP_CTRL_ISP_FLASH_MODE_ENA        BIT(12)
+#define CIF_ISP_CTRL_ISP_FLASH_MODE_DIS        (0 << 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_NEG_EDGE              (0 << 0)
+#define CIF_ISP_ACQ_PROP_POS_EDGE              BIT(0)
+#define CIF_ISP_ACQ_PROP_HSYNC_HIGH            (0 << 1)
+#define CIF_ISP_ACQ_PROP_HSYNC_LOW             BIT(1)
+#define CIF_ISP_ACQ_PROP_VSYNC_HIGH            (0 << 2)
+#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        BIT(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_YCBYCR                (0 << 7)
+#define CIF_ISP_ACQ_PROP_YCRYCB                BIT(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        BIT(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       BIT(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         BIT(0)
+#define CIF_VI_DPCL_MP_MUX_MRSZ_JPEG       (2 << 0)
+#define CIF_VI_DPCL_CHAN_MODE_MP           BIT(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              BIT(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            BIT(8)
+#define CIF_VI_DPCL_IF_SEL_MIPI            (2 << 8)
+#define CIF_VI_DPCL_DMA_IE_MUX_CIF         (0 << 10)
+#define CIF_VI_DPCL_DMA_IE_MUX_DMA         BIT(10)
+#define CIF_VI_DPCL_DMA_SP_MUX_CIF         (0 << 11)
+#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_IN           BIT(0)
+#define CIF_MI_CTRL_MP_ENABLE_OUT          BIT(16)
+#define CIF_MI_CTRL_MP_DISABLE             (0 << 0)
+#define CIF_MI_CTRL_SP_ENABLE              BIT(1)
+#define CIF_MI_CTRL_SP_DISABLE             (0 << 1)
+#define CIF_MI_CTRL_JPEG_ENABLE            BIT(2)
+#define CIF_MI_CTRL_JPEG_DISABLE           (0 << 2)
+#define CIF_MI_CTRL_RAW_ENABLE             BIT(3)
+#define CIF_MI_CTRL_RAW_DISABLE            (0 << 3)
+#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_NO_BYTE_SWAP               (0 << 7)
+#define CIF_MI_SP_Y_FULL_YUV2RGB           BIT(8)
+#define CIF_MI_SP_Y_REDUCED_YUV2RGB        (0 << 8)
+#define CIF_MI_SP_CBCR_FULL_YUV2RGB        BIT(9)
+#define CIF_MI_SP_CBCR_REDUCED_YUV2RGB     (0 << 9)
+#define CIF_MI_SP_422NONCOSITEED           BIT(10)
+#define CIF_MI_MP_PINGPONG_ENABEL          BIT(11)
+#define CIF_MI_MP_PINGPONG_DISABEL         (0 << 11)
+#define CIF_MI_SP_PINGPONG_ENABEL          BIT(12)
+#define CIF_MI_SP_PINGPONG_DISABEL         (0 << 12)
+#define CIF_MI_MP_AUTOUPDATE_ENABLE        BIT(13)
+#define CIF_MI_MP_AUTOUPDATE_DISABLE       (0 << 13)
+#define CIF_MI_SP_AUTOUPDATE_ENABLE        BIT(14)
+#define CIF_MI_SP_AUTOUPDATE_DISABLE       (0 << 14)
+#define CIF_MI_LAST_PIXEL_SIG_ENABLE       BIT(15)
+#define CIF_MI_LAST_PIXEL_SIG_DISABLE      (0 << 15)
+#define CIF_MI_CTRL_BURST_LEN_LUM_16       (0 << 16)
+#define CIF_MI_CTRL_BURST_LEN_LUM_32       BIT(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     BIT(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_BASE_DIS          (0 << 20)
+#define CIF_MI_CTRL_INIT_OFFSET_EN         BIT(21)
+#define CIF_MI_CTRL_INIT_OFFSET_DIS        (0 << 21)
+#define CIF_MI_CTRL_MP_WRITE_FMT(a)        ((a) << 22)
+#define CIF_MI_CTRL_MP_WRITE_FMT_PLA       (0 << 22)
+#define CIF_MI_CTRL_MP_WRITE_FMT_SPLA      BIT(22)
+#define CIF_MI_CTRL_MP_WRITE_FMT_INT       (2 << 22)
+#define CIF_MI_CTRL_SP_WRITE_FMT(a)        ((a) << 24)
+#define CIF_MI_CTRL_SP_WRITE_FMT_PLA       (0 << 24)
+#define CIF_MI_CTRL_SP_WRITE_FMT_SPLA      BIT(24)
+#define CIF_MI_CTRL_SP_WRITE_FMT_INT       (2 << 24)
+#define CIF_MI_CTRL_SP_INPUT_FMT_YUV400    (0 << 26)
+#define CIF_MI_CTRL_SP_INPUT_FMT_YUV420    BIT(26)
+#define CIF_MI_CTRL_SP_INPUT_FMT_YUV422    (2 << 26)
+#define CIF_MI_CTRL_SP_INPUT_FMT_YUV444    (3 << 26)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_YUV400   (0 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_YUV420   BIT(28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_YUV422   (2 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_YUV444   (3 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_RGB565   (4 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_RGB666   (5 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_RGB888   (6 << 28)
+
+#define CIF_MI_CTRL_HFLIP_SHIFT  4
+#define CIF_MI_CTRL_VFLIP_SHIFT  5
+
+/* MI_INIT */
+#define CIF_MI_INIT_SKIP                  BIT(2)
+#define CIF_MI_INIT_SOFT_UPD              BIT(4)
+
+/* 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_BYPASS             BIT(16)
+
+/* MI_IMSC - MI_MIS - MI_RIS - MI_ICR - MI_ISR */
+#define CIF_MI_NOTHING                     (0 << 0)
+#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   BIT(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 BIT(2)
+#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64 (2 << 2)
+#define CIF_MI_DMA_CTRL_READ_FMT(a)        ((a) << 4)
+#define CIF_MI_DMA_CTRL_READ_FMT_PLANAR    (0 << 4)
+#define CIF_MI_DMA_CTRL_READ_FMT_SPLANAR   BIT(4)
+#define CIF_MI_DMA_CTRL_READ_FMT_PACKED    (2 << 4)
+#define CIF_MI_DMA_CTRL_FMT_YUV444         (3 << 6)
+#define CIF_MI_DMA_CTRL_FMT_YUV422         (2 << 6)
+#define CIF_MI_DMA_CTRL_FMT_YUV420         BIT(6)
+#define CIF_MI_DMA_CTRL_FMT_YUV400         (0 << 6)
+#define CIF_MI_DMA_CTRL_BYTE_SWAP          BIT(8)
+#define CIF_MI_DMA_CTRL_NO_BYTE_SWAP       (0 << 8)
+#define CIF_MI_DMA_CTRL_CONTINUOUS_ENA      BIT(9)
+#define CIF_MI_DMA_CTRL_CONTINUOUS_DIS     (0 << 9)
+#define CIF_MI_DMA_CTRL_RGB_BAYER_NO       (0 << 12)
+#define CIF_MI_DMA_CTRL_RGB_BAYER_8BIT      BIT(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)
+
+#define CIF_MI_ADDR_SIZE_ALIGN_MASK        0xfffffff8
+
+/* CCL */
+#define CIF_CCL_CIF_CLK_ENA                (0 << 2)
+#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_ALL_CLK                   (-1)
+#define CIF_ICCL_NO_CLK                    (0)
+/* 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_CTR_DIS                 (0 << 0)
+#define CIF_C_PROC_YOUT_FULL               BIT(1)
+#define CIF_C_PROC_YOUT_LIM                (0 << 1)
+#define CIF_C_PROC_YIN_FULL                BIT(2)
+#define CIF_C_PROC_YIN_LIM                 (0 << 2)
+#define CIF_C_PROC_COUT_FULL               BIT(3)
+#define CIF_C_PROC_COUT_LIM                (0 << 3)
+
+/* DUAL_CROP_CTRL */
+#define CIF_DUAL_CROP_MP_MODE_BYPASS      (0 << 0)
+#define CIF_DUAL_CROP_MP_MODE_YUV         BIT(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         BIT(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    BIT(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)
+
+/* IMG_EFF_COLOR_SEL */
+#define CIF_IMG_EFF_COLOR_RGB              (0 << 0)
+#define CIF_IMG_EFF_COLOR_B                BIT(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)
+
+/* JPE */
+#define CIF_JPE_GEN_HEADER_ENABLE          BIT(0)
+#define CIF_JPE_ENCODE_ENABLE              BIT(0)
+#define CIF_JPE_INIT_ENABLE                BIT(0)
+#define CIF_JPE_LUM_SCALE_ENABLE           BIT(0)
+#define CIF_JPE_CHROM_SCALE_ENABLE         BIT(0)
+#define CIF_JPE_PIC_FORMAT_YUV422          BIT(0)
+#define CIF_JPE_PIC_FORMAT_YUV400          (4 << 0)
+
+#define CIF_JPE_TQ_TAB3                    (3 << 0)
+#define CIF_JPE_TQ_TAB2                    (2 << 0)
+#define CIF_JPE_TQ_TAB1                    BIT(0)
+#define CIF_JPE_TQ_TAB0                    (0 << 0)
+
+#define CIF_TQ_Y_SELECT                    (3 << 0)
+#define CIF_TQ_U_SELECT                    (3 << 0)
+#define CIF_TQ_V_SELECT                    (3 << 0)
+#define CIF_DC_V_TABLE                     (4 << 0)
+#define CIF_DC_U_TABLE                     (2 << 0)
+#define CIF_DC_Y_TABLE                     BIT(0)
+#define CIF_AC_V_TABLE                     (4 << 0)
+#define CIF_AC_U_TABLE                     (2 << 0)
+#define CIF_AC_Y_TABLE                     BIT(0)
+
+/* JPE_TAB_ID */
+#define CIF_JPE_TAB_ID_HUFFAC1             (7 << 0)
+#define CIF_JPE_TAB_ID_HUFFDC1             (6 << 0)
+#define CIF_JPE_TAB_ID_HUFFAC0             (5 << 0)
+#define CIF_JPE_TAB_ID_HUFFDC0             (4 << 0)
+#define CIF_JPE_TAB_ID_QUANT3              (3 << 0)
+#define CIF_JPE_TAB_ID_QUANT2              (2 << 0)
+#define CIF_JPE_TAB_ID_QUANT1              BIT(0)
+#define CIF_JPE_TAB_ID_QUANT0              (0 << 0)
+/* JPE_ENCODER_BUSY */
+#define CIF_ENCODER_BUSY                   BIT(0)
+/* JPE_HEADER_MODE */
+#define CIF_JPE_HEADER_MODE_NOAPPN         (0 << 0)
+#define CIF_JPE_HEADER_MODE_NOAPPN1        BIT(0)
+#define CIF_JPE_HEADER_MODE_JFIF           (2 << 0)
+#define CIF_JPE_HEADER_MODE_JFIF1          (3 << 0)
+/* JPE_ERROR_RIS */
+#define CIF_JPE_VLC_SYMB_ERROR             BIT(4)
+#define CIF_JPE_DCT_ERROR                  BIT(7)
+#define CIF_JPE_R2B_IMG_SIZE_ERROR         BIT(9)
+#define CIF_JPE_VLC_TAB_ERROR              BIT(10)
+#define CIF_JPE_ERROR_MASK   (CIF_JPE_VLC_SYMB_ERROR |\
+                                       CIF_JPE_DCT_ERROR |\
+                                       CIF_JPE_R2B_IMG_SIZE_ERROR |\
+                                       CIF_JPE_VLC_TAB_ERROR)
+/* JPE_STATUS_RIS */
+#define CIF_JPE_STATUS_ENCODE_DONE         BIT(4)
+#define CIF_JPE_STATUS_GENHEADER_DONE      BIT(5)
+
+/* MIPI */
+
+/* MIPI_DPHY1 */
+
+/* MIPI_DPHY2 */
+
+/* MIPI_CTRL */
+#define CIF_MIPI_CTRL_OUTPUT_ENA             BIT(0)
+#define CIF_MIPI_CTRL_SHUTDOWNLANES(a)       ((a) << 8)
+#define CIF_CSI_LANE_2                       BIT(1)
+#define CIF_CSI_LANE_3                       BIT(2)
+#define CIF_CSI_LANE_4                       BIT(3)
+#define CIF_MIPI_CTRL_NUM_LANES(a)           ((a) << 12)
+#define CIF_MIPI_CTRL_ERR_SOT_HS_ENA         (0 << 16)
+#define CIF_MIPI_CTRL_ERR_SOT_HS_SKIP        BIT(16)
+#define CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_ENA    (0 << 17)
+#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) << 6)
+#define CIF_MIPI_DATA_SEL_DT(a)              ((a) << 0)
+
+#define CIF_MIPI_INTERRUPT_ALL               (-1)
+
+/* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */
+#define CIF_MIPI_SYNC_FIFO_OVFLW(a)    ((a) << 0)
+#define CIF_MIPI_ERR_SOT(a)            ((a) << 4)
+#define CIF_MIPI_ERR_SOT_SYNC(a)       ((a) << 8)
+#define CIF_MIPI_ERR_EOT_SYNC(a)       ((a) << 12)
+#define CIF_MIPI_ERR_CTRL(a)           ((a) << 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_BYPASS_MODE (0 << 0)
+#define CIF_SUPER_IMP_CTRL_REF_IMG_MEM BIT(1)
+#define CIF_SUPER_IMP_CTRL_REF_IMG_IE  (0 << 1)
+#define CIF_SUPER_IMP_CTRL_TRANSP_DIS  BIT(2)
+#define CIF_SUPER_IMP_CTRL_TRANSP_ENA  (0 << 2)
+
+/* ISP HISTOGRAM CALCULATION : ISP_HIST_PROP */
+#define CIF_ISP_HIST_PROP_PDIV(a)    ((a) << 3)
+#define CIF_ISP_HIST_PROP_MODE_DIS   (0 << 0)
+#define CIF_ISP_HIST_PROP_MODE_RGB   BIT(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)
+
+/* AUTO FOCUS MEASUREMENT:  ISP_AFM_CTRL */
+#define ISP_AFM_CTRL_ENABLE   BIT(0)
+#define ISP_AFM_CTRL_DISABLE  (0 << 0)
+
+/* SHUTTER CONTROL */
+#define CIF_ISP_SH_CTRL_SH_ENA      BIT(0)
+#define CIF_ISP_SH_CTRL_SH_DIS      (0 << 0)
+#define CIF_ISP_SH_CTRL_REP_EN      BIT(1)
+#define CIF_ISP_SH_CTRL_REP_DIS     (0 << 1)
+#define CIF_ISP_SH_CTRL_SRC_SH_TRIG BIT(2)
+#define CIF_ISP_SH_CTRL_SRC_VSYNC  (0 << 2)
+#define CIF_ISP_SH_CTRL_EDGE_POS    BIT(3)
+#define CIF_ISP_SH_CTRL_EDGE_NEG   (0 << 3)
+#define CIF_ISP_SH_CTRL_POL_LOW     BIT(4)
+#define CIF_ISP_SH_CTRL_POL_HIGH   (0 << 4)
+
+/* FLASH MODULE */
+/* ISP_FLASH_CMD */
+#define CIF_FLASH_CMD_PRELIGHT_ON   BIT(0)
+#define CIF_FLASH_CMD_PRELIGHT_OFF  (0 << 0)
+#define CIF_FLASH_CMD_FLASH_ON      BIT(1)
+#define CIF_FLASH_CMD_FLASH_OFF     (0 << 1)
+#define CIF_FLASH_CMD_PRE_FLASH_ON  BIT(2)
+#define CIF_FLASH_CMD_PRE_FLASH_OFF (0 << 2)
+/* ISP_FLASH_CONFIG */
+#define CIF_FLASH_CONFIG_PRELIGHT_BEG   (0 << 1)
+#define CIF_FLASH_CONFIG_PRELIGHT_END   BIT(0)
+#define CIF_FLASH_CONFIG_VSYNC_NEG      (0 << 1)
+#define CIF_FLASH_CONFIG_VSYNC_POS      BIT(1)
+#define CIF_FLASH_CONFIG_PRELIGHT_HIGH  (0 << 2)
+#define CIF_FLASH_CONFIG_PRELIGHT_LOW   BIT(2)
+#define CIF_FLASH_CONFIG_SRC_VSYNC      (0 << 3)
+#define CIF_FLASH_CONFIG_SRC_FL_TRIG    BIT(3)
+#define CIF_FLASH_CONFIG_DELAY(a)      ((a) << 4)
+
+/* BAD PIXEL DETECTION */
+
+/* =================================================================== */
+/*                            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_JPE_BASE                (0x00001800)
+#define CIF_JPE_GEN_HEADER          ((CIF_JPE_BASE + 0x00000000))
+#define CIF_JPE_ENCODE              ((CIF_JPE_BASE + 0x00000004))
+#define CIF_JPE_INIT                ((CIF_JPE_BASE + 0x00000008))
+#define CIF_JPE_Y_SCALE_EN          ((CIF_JPE_BASE + 0x0000000C))
+#define CIF_JPE_CBCR_SCALE_EN       ((CIF_JPE_BASE + 0x00000010))
+#define CIF_JPE_TABLE_FLUSH         ((CIF_JPE_BASE + 0x00000014))
+#define CIF_JPE_ENC_HSIZE           ((CIF_JPE_BASE + 0x00000018))
+#define CIF_JPE_ENC_VSIZE           ((CIF_JPE_BASE + 0x0000001C))
+#define CIF_JPE_PIC_FORMAT          ((CIF_JPE_BASE + 0x00000020))
+#define CIF_JPE_RESTART_INTERVAL    ((CIF_JPE_BASE + 0x00000024))
+#define CIF_JPE_TQ_Y_SELECT         ((CIF_JPE_BASE + 0x00000028))
+#define CIF_JPE_TQ_U_SELECT         ((CIF_JPE_BASE + 0x0000002C))
+#define CIF_JPE_TQ_V_SELECT         ((CIF_JPE_BASE + 0x00000030))
+#define CIF_JPE_DC_TABLE_SELECT     ((CIF_JPE_BASE + 0x00000034))
+#define CIF_JPE_AC_TABLE_SELECT     ((CIF_JPE_BASE + 0x00000038))
+#define CIF_JPE_TABLE_DATA          ((CIF_JPE_BASE + 0x0000003C))
+#define CIF_JPE_TABLE_ID            ((CIF_JPE_BASE + 0x00000040))
+#define CIF_JPE_TAC0_LEN            ((CIF_JPE_BASE + 0x00000044))
+#define CIF_JPE_TDC0_LEN            ((CIF_JPE_BASE + 0x00000048))
+#define CIF_JPE_TAC1_LEN            ((CIF_JPE_BASE + 0x0000004C))
+#define CIF_JPE_TDC1_LEN            ((CIF_JPE_BASE + 0x00000050))
+#define CIF_JPE_ENCODER_BUSY        ((CIF_JPE_BASE + 0x00000058))
+#define CIF_JPE_HEADER_MODE         ((CIF_JPE_BASE + 0x0000005C))
+#define CIF_JPE_ENCODE_MODE         ((CIF_JPE_BASE + 0x00000060))
+#define CIF_JPE_DEBUG               ((CIF_JPE_BASE + 0x00000064))
+#define CIF_JPE_ERROR_IMSC          ((CIF_JPE_BASE + 0x00000068))
+#define CIF_JPE_ERROR_RIS           ((CIF_JPE_BASE + 0x0000006C))
+#define CIF_JPE_ERROR_MIS           ((CIF_JPE_BASE + 0x00000070))
+#define CIF_JPE_ERROR_ICR           ((CIF_JPE_BASE + 0x00000074))
+#define CIF_JPE_ERROR_ISR           ((CIF_JPE_BASE + 0x00000078))
+#define CIF_JPE_STATUS_IMSC         ((CIF_JPE_BASE + 0x0000007C))
+#define CIF_JPE_STATUS_RIS          ((CIF_JPE_BASE + 0x00000080))
+#define CIF_JPE_STATUS_MIS          ((CIF_JPE_BASE + 0x00000084))
+#define CIF_JPE_STATUS_ICR          ((CIF_JPE_BASE + 0x00000088))
+#define CIF_JPE_STATUS_ISR          ((CIF_JPE_BASE + 0x0000008C))
+#define CIF_JPE_CONFIG              ((CIF_JPE_BASE + 0x00000090))
+
+#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)
+#endif
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_rk3288.c b/drivers/media/platform/rk-isp10/cif_isp10_rk3288.c
new file mode 100644 (file)
index 0000000..b616059
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/rk_isp10_platform.h>
+
+#define ONE_LANE_ENABLE_BIT     0x1
+#define TWO_LANE_ENABLE_BIT     0x2
+#define FOUR_LANE_ENABLE_BIT    0x4
+
+#define MRV_MIPI_BASE           0x1C00
+#define MRV_MIPI_CTRL           0x00
+
+/*
+ * GRF_SOC_CON14
+ * bit 0     dphy_rx0_testclr
+ * bit 1     dphy_rx0_testclk
+ * bit 2     dphy_rx0_testen
+ * bit 3:10 dphy_rx0_testdin
+ */
+#define GRF_SOC_CON14_OFFSET    (0x027c)
+#define DPHY_RX0_TESTCLR_MASK   (0x1 << 16)
+#define DPHY_RX0_TESTCLK_MASK   (0x1 << 17)
+#define DPHY_RX0_TESTEN_MASK    (0x1 << 18)
+#define DPHY_RX0_TESTDIN_MASK   (0xff << 19)
+
+#define DPHY_RX0_TESTCLR         BIT(0)
+#define DPHY_RX0_TESTCLK         BIT(1)
+#define DPHY_RX0_TESTEN          BIT(2)
+#define DPHY_RX0_TESTDIN_OFFSET  (3)
+
+#define DPHY_TX1RX1_ENABLECLK_MASK    (0x1 << 28)
+#define DPHY_RX1_SRC_SEL_MASK         (0x1 << 29)
+#define DPHY_TX1RX1_MASTERSLAVEZ_MASK (0x1 << 30)
+#define DPHY_TX1RX1_BASEDIR_OFFSET    (0x1 << 31)
+
+#define DPHY_TX1RX1_ENABLECLK         (0x1 << 12)
+#define DPHY_TX1RX1_DISABLECLK        (0x0 << 12)
+#define DPHY_RX1_SRC_SEL_ISP          (0x1 << 13)
+#define DPHY_TX1RX1_SLAVEZ            (0x0 << 14)
+#define DPHY_TX1RX1_BASEDIR_REC       (0x1 << 15)
+
+/*
+ * GRF_SOC_CON6
+ * bit 0 grf_con_disable_isp
+ * bit 1 grf_con_isp_dphy_sel  1'b0 mipi phy rx0
+ */
+#define GRF_SOC_CON6_OFFSET            (0x025c)
+#define MIPI_PHY_DISABLE_ISP_MASK      (0x1 << 16)
+#define MIPI_PHY_DISABLE_ISP           (0x0 << 0)
+
+#define DSI_CSI_TESTBUS_SEL_MASK       (0x1 << 30)
+#define DSI_CSI_TESTBUS_SEL_OFFSET_BIT (14)
+
+#define MIPI_PHY_DPHYSEL_OFFSET_MASK   (0x1 << 17)
+#define MIPI_PHY_DPHYSEL_OFFSET_BIT    (0x1)
+
+/*
+ * GRF_SOC_CON10
+ * bit12:15 grf_dphy_rx0_enable
+ * bit 0:3 turn disable
+ */
+#define GRF_SOC_CON10_OFFSET                (0x026c)
+#define DPHY_RX0_TURN_DISABLE_MASK          (0xf << 16)
+#define DPHY_RX0_TURN_DISABLE_OFFSET_BITS   (0x0)
+#define DPHY_RX0_ENABLE_MASK                (0xf << 28)
+#define DPHY_RX0_ENABLE_OFFSET_BITS         (12)
+
+/*
+ * GRF_SOC_CON9
+ * bit12:15 grf_dphy_rx0_enable
+ * bit 0:3 turn disable
+ */
+#define GRF_SOC_CON9_OFFSET                    (0x0268)
+#define DPHY_TX1RX1_TURN_DISABLE_MASK          (0xf << 16)
+#define DPHY_TX1RX1_TURN_DISABLE_OFFSET_BITS   (0x0)
+#define DPHY_TX1RX1_ENABLE_MASK                (0xf << 28)
+#define DPHY_TX1RX1_ENABLE_OFFSET_BITS         (12)
+
+/*
+ * GRF_SOC_CON15
+ * bit 0:3   turn request
+ */
+#define GRF_SOC_CON15_OFFSET                (0x03a4)
+#define DPHY_RX0_TURN_REQUEST_MASK          (0xf << 16)
+#define DPHY_RX0_TURN_REQUEST_OFFSET_BITS   (0x0)
+
+#define DPHY_TX1RX1_TURN_REQUEST_MASK          (0xf << 20)
+#define DPHY_TX1RX1_TURN_REQUEST_OFFSET_BITS   (0x0)
+
+/*
+ * GRF_SOC_STATUS21
+ * bit0:7   dphy_rx0_testdout
+ */
+#define GRF_SOC_STATUS21_OFFSET      (0x2D4)
+#define DPHY_RX0_TESTDOUT(a)         ((a) & 0xff)
+
+/*
+ * GRF_IO_VSEL
+ */
+#define GRF_IO_VSEL_OFFSET             (0x0380)
+#define DVP_V18SEL                     ((1 << 1) | (1 << 17))
+#define DVP_V33SEL                     ((0 << 1) | (1 << 17))
+
+/*
+ * GRF_IO_VSEL
+ */
+#define GRF_GPIO2B_E_OFFSET       (0x0380)
+#define CIF_CLKOUT_STRENGTH(a)    ((((a) & 0x03) << 3) | (0x03 << 19))
+
+/*
+ * CSI HOST
+ */
+
+#define CSIHOST_PHY_TEST_CTRL0            (0x30)
+#define CSIHOST_PHY_TEST_CTRL1            (0x34)
+#define CSIHOST_PHY_SHUTDOWNZ             (0x08)
+#define CSIHOST_DPHY_RSTZ                 (0x0c)
+#define CSIHOST_N_LANES                   (0x04)
+#define CSIHOST_CSI2_RESETN               (0x10)
+#define CSIHOST_PHY_STATE                 (0x14)
+#define CSIHOST_DATA_IDS1                 (0x18)
+#define CSIHOST_DATA_IDS2                 (0x1C)
+#define CSIHOST_ERR1                      (0x20)
+#define CSIHOST_ERR2                      (0x24)
+
+#define write_cifisp_reg(addr, val)    \
+               __raw_writel(val, (addr) + rk3288->isp_base)
+#define read_cifisp_reg(addr)  \
+               __raw_readl((addr) + rk3288->isp_base)
+
+#define write_grf_reg(addr, val)       \
+               regmap_write(rk3288->regmap_grf, addr, val)
+#define read_grf_reg(addr, val)        regmap_read(rk3288->regmap_grf, addr, val)
+
+#define write_csihost_reg(addr, val)   \
+               __raw_writel(val, (addr) + rk3288->csihost_base)
+#define read_csihost_reg(addr) __raw_readl((addr) + rk3288->csihost_base)
+
+struct cif_isp10_clk_rst_rk3288 {
+       struct clk      *aclk_isp;
+       struct clk      *hclk_isp;
+       struct clk      *sclk_isp;
+       struct clk      *sclk_isp_jpe;
+       struct clk *sclk_mipidsi_24m;
+       struct clk *pclk_mipi_csi;
+       struct clk *pclk_isp_in;
+       struct reset_control *isp_rst;
+};
+
+struct cif_isp10_rk3288 {
+       struct regmap *regmap_grf;
+       void __iomem *csihost_base;
+       void __iomem *isp_base;
+       struct cif_isp10_clk_rst_rk3288 clk_rst;
+       struct cif_isp10_device *cif_isp10;
+};
+
+struct mipi_dphy_hsfreqrange {
+       unsigned int range_l;
+       unsigned int range_h;
+       unsigned char cfg_bit;
+};
+
+static struct mipi_dphy_hsfreqrange mipi_dphy_hsfreq_range[] = {
+       {80, 90, 0x00},
+       {90, 100, 0x10},
+       {100, 110, 0x20},
+       {110, 130, 0x01},
+       {130, 140, 0x11},
+       {140, 150, 0x21},
+       {150, 170, 0x02},
+       {170, 180, 0x12},
+       {180, 200, 0x22},
+       {200, 220, 0x03},
+       {220, 240, 0x13},
+       {240, 250, 0x23},
+       {250, 270, 0x4},
+       {270, 300, 0x14},
+       {300, 330, 0x5},
+       {330, 360, 0x15},
+       {360, 400, 0x25},
+       {400, 450, 0x06},
+       {450, 500, 0x16},
+       {500, 550, 0x07},
+       {550, 600, 0x17},
+       {600, 650, 0x08},
+       {650, 700, 0x18},
+       {700, 750, 0x09},
+       {750, 800, 0x19},
+       {800, 850, 0x29},
+       {850, 900, 0x39},
+       {900, 950, 0x0a},
+       {950, 1000, 0x1a}
+};
+
+static struct cif_isp10_rk3288 *rk3288;
+static int mipi_dphy0_wr_reg(unsigned char addr, unsigned char data)
+{
+       /*
+        * TESTCLK=1
+        * TESTEN =1,TESTDIN=addr
+        * TESTCLK=0
+        */
+       write_grf_reg(GRF_SOC_CON14_OFFSET,
+               DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
+       write_grf_reg(GRF_SOC_CON14_OFFSET,
+               ((addr << DPHY_RX0_TESTDIN_OFFSET) | DPHY_RX0_TESTDIN_MASK
+                | DPHY_RX0_TESTEN | DPHY_RX0_TESTEN_MASK));
+       write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK);
+
+       /*
+        * write data:
+        * TESTEN =0,TESTDIN=data
+        * TESTCLK=1
+        */
+       if (data != 0xff) {
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       ((data << DPHY_RX0_TESTDIN_OFFSET) |
+                       DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN_MASK));
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
+       }
+       return 0;
+}
+
+static int mipi_dphy1_wr_reg(unsigned char addr, unsigned char data)
+{
+       /*
+        * TESTEN =1,TESTDIN=addr
+        * TESTCLK=0
+        * TESTEN =0,TESTDIN=data
+        * TESTCLK=1
+        */
+       write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
+       write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000000);
+       write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, (0x00000000 | data));
+       write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
+
+       return 0;
+}
+
+static int mipi_dphy1_rd_reg(unsigned char addr)
+{
+       return (read_csihost_reg(((CSIHOST_PHY_TEST_CTRL1) & 0xff00)) >> 8);
+}
+
+static int mipi_dphy_cfg(struct pltfrm_cam_mipi_config *para)
+{
+       unsigned char hsfreqrange = 0xff, i;
+       struct mipi_dphy_hsfreqrange *hsfreqrange_p;
+       unsigned char datalane_en, input_sel;
+
+       hsfreqrange_p = mipi_dphy_hsfreq_range;
+       for (i = 0;
+               i < (sizeof(mipi_dphy_hsfreq_range) /
+               sizeof(struct mipi_dphy_hsfreqrange));
+               i++) {
+               if ((para->bit_rate > hsfreqrange_p->range_l) &&
+                        (para->bit_rate <= hsfreqrange_p->range_h)) {
+                       hsfreqrange = hsfreqrange_p->cfg_bit;
+                       break;
+               }
+               hsfreqrange_p++;
+       }
+
+       if (hsfreqrange == 0xff)
+               hsfreqrange = 0x00;
+
+       hsfreqrange <<= 1;
+
+       input_sel = para->dphy_index;
+       datalane_en = 0;
+       for (i = 0; i < para->nb_lanes; i++)
+               datalane_en |= (1 << i);
+
+       if (input_sel == 0) {
+               write_grf_reg(GRF_SOC_CON6_OFFSET,
+                       MIPI_PHY_DPHYSEL_OFFSET_MASK |
+                       (input_sel << MIPI_PHY_DPHYSEL_OFFSET_BIT));
+               /* set lane num */
+               write_grf_reg(GRF_SOC_CON10_OFFSET,
+                       DPHY_RX0_ENABLE_MASK |
+                       (datalane_en << DPHY_RX0_ENABLE_OFFSET_BITS));
+               /* set lan turndisab as 1 */
+               write_grf_reg(GRF_SOC_CON10_OFFSET,
+                       DPHY_RX0_TURN_DISABLE_MASK |
+                       (0xf << DPHY_RX0_TURN_DISABLE_OFFSET_BITS));
+               write_grf_reg(GRF_SOC_CON10_OFFSET,
+               (0x0 << 4) | (0xf << 20));
+               /* set lan turnrequest as 0 */
+               write_grf_reg(GRF_SOC_CON15_OFFSET,
+                       DPHY_RX0_TURN_REQUEST_MASK |
+                       (0x0 << DPHY_RX0_TURN_REQUEST_OFFSET_BITS));
+
+               /* phy start */
+               /*
+                * TESTCLK=1
+                * TESTCLR=1
+                * delay 100us
+                * TESTCLR=0
+                */
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       DPHY_RX0_TESTCLR_MASK | DPHY_RX0_TESTCLR);
+               usleep_range(100, 150);
+               write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLR_MASK);
+               usleep_range(100, 150);
+
+               /* set clock lane */
+               mipi_dphy0_wr_reg(0x34, 0x15);
+               if (datalane_en == ONE_LANE_ENABLE_BIT) {
+                       mipi_dphy0_wr_reg(0x44, hsfreqrange);
+               } else if (datalane_en == TWO_LANE_ENABLE_BIT) {
+                       mipi_dphy0_wr_reg(0x44, hsfreqrange);
+                       mipi_dphy0_wr_reg(0x54, hsfreqrange);
+               } else if (datalane_en == FOUR_LANE_ENABLE_BIT) {
+                       mipi_dphy0_wr_reg(0x44, hsfreqrange);
+                       mipi_dphy0_wr_reg(0x54, hsfreqrange);
+                       mipi_dphy0_wr_reg(0x84, hsfreqrange);
+                       mipi_dphy0_wr_reg(0x94, hsfreqrange);
+               }
+
+               /* Normal operation */
+               /*
+                * TESTCLK=1
+                * TESTEN =0
+                */
+               mipi_dphy0_wr_reg(0x0, -1);
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       (DPHY_RX0_TESTEN_MASK));
+
+               write_cifisp_reg((MRV_MIPI_BASE + MRV_MIPI_CTRL),
+                       read_cifisp_reg(MRV_MIPI_BASE + MRV_MIPI_CTRL) |
+                       (0x0f << 8));
+
+       } else if (input_sel == 1) {
+               write_grf_reg(GRF_SOC_CON6_OFFSET,
+                       MIPI_PHY_DPHYSEL_OFFSET_MASK |
+                       (input_sel << MIPI_PHY_DPHYSEL_OFFSET_BIT));
+               write_grf_reg(GRF_SOC_CON6_OFFSET,
+                       DSI_CSI_TESTBUS_SEL_MASK |
+                       (1 << DSI_CSI_TESTBUS_SEL_OFFSET_BIT));
+
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       DPHY_RX1_SRC_SEL_ISP | DPHY_RX1_SRC_SEL_MASK);
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       DPHY_TX1RX1_SLAVEZ | DPHY_TX1RX1_MASTERSLAVEZ_MASK);
+               write_grf_reg(GRF_SOC_CON14_OFFSET,
+                       DPHY_TX1RX1_BASEDIR_REC | DPHY_TX1RX1_BASEDIR_OFFSET);
+
+               /* set lane num */
+               write_grf_reg(GRF_SOC_CON9_OFFSET,
+                       DPHY_TX1RX1_ENABLE_MASK |
+                       (datalane_en << DPHY_TX1RX1_ENABLE_OFFSET_BITS));
+               /* set lan turndisab as 1 */
+               write_grf_reg(GRF_SOC_CON9_OFFSET,
+                       DPHY_TX1RX1_TURN_DISABLE_MASK |
+                       (0xf << DPHY_TX1RX1_TURN_DISABLE_OFFSET_BITS));
+               /* set lan turnrequest as 0   */
+               write_grf_reg(GRF_SOC_CON15_OFFSET,
+                       DPHY_TX1RX1_TURN_REQUEST_MASK |
+                       (0x0 << DPHY_TX1RX1_TURN_REQUEST_OFFSET_BITS));
+
+               /* phy1 start */
+               /*
+                * SHUTDOWNZ=0
+                * RSTZ=0
+                * TESTCLK=1
+                * TESTCLR=1 TESTCLK=1
+                * TESTCLR=0 TESTCLK=1
+                */
+               write_csihost_reg(CSIHOST_PHY_SHUTDOWNZ, 0x00000000);
+               write_csihost_reg(CSIHOST_DPHY_RSTZ, 0x00000000);
+               write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
+               write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000003);
+               usleep_range(100, 150);
+               write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
+               usleep_range(100, 150);
+
+               /* set clock lane */
+               mipi_dphy1_wr_reg(0x34, 0x15);
+
+               if (datalane_en == ONE_LANE_ENABLE_BIT) {
+                       mipi_dphy1_wr_reg(0x44, hsfreqrange);
+               } else if (datalane_en == TWO_LANE_ENABLE_BIT) {
+                       mipi_dphy1_wr_reg(0x44, hsfreqrange);
+                       mipi_dphy1_wr_reg(0x54, hsfreqrange);
+               } else if (datalane_en == FOUR_LANE_ENABLE_BIT) {
+                       mipi_dphy1_wr_reg(0x44, hsfreqrange);
+                       mipi_dphy1_wr_reg(0x54, hsfreqrange);
+                       mipi_dphy1_wr_reg(0x84, hsfreqrange);
+                       mipi_dphy1_wr_reg(0x94, hsfreqrange);
+               }
+
+               mipi_dphy1_rd_reg(0x0);
+               /*
+                * TESTCLK=1
+                * TESTEN =0
+                * SHUTDOWNZ=1
+                * RSTZ=1
+                */
+               write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
+               write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, 0x00000000);
+               write_csihost_reg(CSIHOST_PHY_SHUTDOWNZ, 0x00000001);
+               write_csihost_reg(CSIHOST_DPHY_RSTZ, 0x00000001);
+       } else {
+               goto fail;
+       }
+
+       return 0;
+fail:
+       return -1;
+}
+
+static int soc_clk_enable(void)
+{
+       struct cif_isp10_clk_rst_rk3288 *clk_rst = &rk3288->clk_rst;
+
+       clk_prepare_enable(clk_rst->hclk_isp);
+       clk_prepare_enable(clk_rst->aclk_isp);
+       clk_prepare_enable(clk_rst->sclk_isp);
+       clk_prepare_enable(clk_rst->sclk_isp_jpe);
+       clk_prepare_enable(clk_rst->sclk_mipidsi_24m);
+       clk_prepare_enable(clk_rst->pclk_isp_in);
+       clk_prepare_enable(clk_rst->pclk_mipi_csi);
+       return 0;
+}
+
+static int soc_clk_disable(void)
+{
+       struct cif_isp10_clk_rst_rk3288 *clk_rst = &rk3288->clk_rst;
+
+       clk_disable_unprepare(clk_rst->hclk_isp);
+       clk_disable_unprepare(clk_rst->aclk_isp);
+       clk_disable_unprepare(clk_rst->sclk_isp);
+       clk_disable_unprepare(clk_rst->sclk_isp_jpe);
+       clk_disable_unprepare(clk_rst->sclk_mipidsi_24m);
+       clk_disable_unprepare(clk_rst->pclk_isp_in);
+       clk_disable_unprepare(clk_rst->pclk_mipi_csi);
+       return 0;
+}
+
+static int soc_init(struct pltfrm_soc_init_para *init)
+{
+       struct cif_isp10_clk_rst_rk3288 *clk_rst;
+       struct platform_device *pdev = init->pdev;
+       struct device_node *np = pdev->dev.of_node, *node;
+       struct resource *res;
+       int err;
+
+       rk3288 = (struct cif_isp10_rk3288 *)devm_kzalloc(
+                               &pdev->dev,
+                               sizeof(struct cif_isp10_rk3288),
+                               GFP_KERNEL);
+       if (!rk3288) {
+               dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3288\n");
+               err = -ENOMEM;
+               goto alloc_failed;
+       }
+
+       node = of_parse_phandle(np, "rockchip,grf", 0);
+       if (node) {
+               rk3288->regmap_grf = syscon_node_to_regmap(node);
+               if (IS_ERR(rk3288->regmap_grf)) {
+                       dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3288\n");
+                       err = -ENODEV;
+                       goto regmap_failed;
+               }
+       }
+
+       res = platform_get_resource_byname(pdev,
+                               IORESOURCE_MEM, "csihost-register");
+       if (!res) {
+               dev_err(&pdev->dev,
+                       "platform_get_resource_byname csihost-register failed\n");
+               err = -ENODEV;
+               goto regmap_failed;
+       }
+       rk3288->csihost_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR_OR_NULL(rk3288->csihost_base)) {
+               dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+               if (IS_ERR(rk3288->csihost_base))
+                       err = PTR_ERR(rk3288->csihost_base);
+               else
+                       err = -ENODEV;
+               goto regmap_failed;
+       }
+
+       clk_rst = &rk3288->clk_rst;
+       clk_rst->aclk_isp = devm_clk_get(&pdev->dev, "aclk_isp");
+       clk_rst->hclk_isp = devm_clk_get(&pdev->dev, "hclk_isp");
+       clk_rst->sclk_isp = devm_clk_get(&pdev->dev, "sclk_isp");
+       clk_rst->sclk_isp_jpe = devm_clk_get(&pdev->dev, "sclk_isp_jpe");
+       clk_rst->sclk_mipidsi_24m =
+                       devm_clk_get(&pdev->dev, "sclk_mipidsi_24m");
+       clk_rst->pclk_mipi_csi = devm_clk_get(&pdev->dev, "pclk_mipi_csi");
+       clk_rst->isp_rst = devm_reset_control_get(&pdev->dev, "rst_isp");
+       clk_rst->pclk_isp_in = devm_clk_get(&pdev->dev, "pclk_isp_in");
+
+       if (IS_ERR_OR_NULL(clk_rst->aclk_isp) ||
+               IS_ERR_OR_NULL(clk_rst->hclk_isp) ||
+               IS_ERR_OR_NULL(clk_rst->sclk_isp) ||
+               IS_ERR_OR_NULL(clk_rst->sclk_isp_jpe) ||
+               IS_ERR_OR_NULL(clk_rst->pclk_mipi_csi) ||
+               IS_ERR_OR_NULL(clk_rst->isp_rst) ||
+               IS_ERR_OR_NULL(clk_rst->pclk_isp_in) ||
+               IS_ERR_OR_NULL(clk_rst->sclk_mipidsi_24m)) {
+               dev_err(&pdev->dev, "Get rk3288 cif isp10 clock resouce failed !\n");
+               err = -EINVAL;
+               goto clk_failed;
+       }
+
+       clk_set_rate(clk_rst->sclk_isp, 400000000);
+       clk_set_rate(clk_rst->sclk_isp_jpe, 400000000);
+       reset_control_deassert(clk_rst->isp_rst);
+
+       rk3288->isp_base = init->isp_base;
+       return 0;
+
+clk_failed:
+       if (!IS_ERR_OR_NULL(clk_rst->aclk_isp))
+               devm_clk_put(&pdev->dev, clk_rst->aclk_isp);
+       if (!IS_ERR_OR_NULL(clk_rst->hclk_isp))
+               devm_clk_put(&pdev->dev, clk_rst->hclk_isp);
+       if (!IS_ERR_OR_NULL(clk_rst->sclk_isp))
+               devm_clk_put(&pdev->dev, clk_rst->sclk_isp);
+       if (!IS_ERR_OR_NULL(clk_rst->sclk_isp_jpe))
+               devm_clk_put(&pdev->dev, clk_rst->sclk_isp_jpe);
+       if (!IS_ERR_OR_NULL(clk_rst->pclk_mipi_csi))
+               devm_clk_put(&pdev->dev, clk_rst->pclk_mipi_csi);
+       if (!IS_ERR_OR_NULL(clk_rst->pclk_isp_in))
+               devm_clk_put(&pdev->dev, clk_rst->pclk_isp_in);
+       if (!IS_ERR_OR_NULL(clk_rst->sclk_mipidsi_24m))
+               devm_clk_put(&pdev->dev, clk_rst->sclk_mipidsi_24m);
+
+       if (!IS_ERR_OR_NULL(clk_rst->isp_rst))
+               reset_control_put(clk_rst->isp_rst);
+
+regmap_failed:
+
+alloc_failed:
+
+       return err;
+}
+
+int pltfrm_rk3288_cfg(
+               struct pltfrm_soc_cfg_para *cfg)
+{
+       switch (cfg->cmd) {
+       case PLTFRM_MCLK_CFG: {
+               struct pltfrm_soc_mclk_para *mclk_para;
+
+               mclk_para = (struct pltfrm_soc_mclk_para *)cfg->cfg_para;
+               if (mclk_para->io_voltage == PLTFRM_IO_1V8)
+                       write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V18SEL);
+               else
+                       write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V33SEL);
+
+               write_grf_reg(GRF_GPIO2B_E_OFFSET,
+                       CIF_CLKOUT_STRENGTH(mclk_para->drv_strength));
+               break;
+       }
+       case PLTFRM_MIPI_DPHY_CFG:
+               mipi_dphy_cfg((struct pltfrm_cam_mipi_config *)cfg->cfg_para);
+               break;
+
+       case PLTFRM_CLKEN:
+               soc_clk_enable();
+               break;
+
+       case PLTFRM_CLKDIS:
+               soc_clk_disable();
+               break;
+
+       case PLTFRM_CLKRST:
+               reset_control_assert(rk3288->clk_rst.isp_rst);
+               usleep_range(10, 15);
+               reset_control_deassert(rk3288->clk_rst.isp_rst);
+               break;
+
+       case PLTFRM_SOC_INIT:
+               soc_init((struct pltfrm_soc_init_para *)cfg->cfg_para);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_rk3399.c b/drivers/media/platform/rk-isp10/cif_isp10_rk3399.c
new file mode 100644 (file)
index 0000000..1188891
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/rk_isp10_platform.h>
+
+#define VI_IRCL               0x0014
+#define MRV_MIPI_BASE         0x1C00
+#define MRV_MIPI_CTRL         0x00
+/*
+ * GRF_IO_VSEL
+ */
+#define GRF_IO_VSEL_OFFSET    (0x0900)
+#define DVP_V18SEL            ((1 << 1) | (1 << 17))
+#define DVP_V33SEL            ((0 << 1) | (1 << 17))
+/*
+ * GRF_IO_VSEL
+ */
+#define GRF_GPIO2B_E_OFFSET   (0x0204)
+#define CIF_CLKOUT_STRENGTH(a) \
+                       ((((a) & 0x03) << 3) | (0x03 << 19))
+#define GRF_SOC_STATUS1       (0x0e2a4)
+
+#define GRF_SOC_CON9_OFFSET   (0x6224)
+#define DPHY_RX0_TURNREQUEST_MASK     (0xF << 16)
+#define DPHY_RX0_TURNREQUEST_BIT      (0)
+
+#define GRF_SOC_CON21_OFFSET          (0x6254)
+#define DPHY_RX0_FORCERXMODE_MASK     (0xF << 20)
+#define DPHY_RX0_FORCERXMODE_BIT      (4)
+#define DPHY_RX0_FORCETXSTOPMODE_MASK (0xF << 24)
+#define DPHY_RX0_FORCETXSTOPMODE_BIT  (8)
+#define DPHY_RX0_TURNDISABLE_MASK     (0xF << 28)
+#define DPHY_RX0_TURNDISABLE_BIT      (12)
+#define DPHY_RX0_ENABLE_MASK          (0xF << 16)
+#define DPHY_RX0_ENABLE_BIT           (0)
+
+#define GRF_SOC_CON23_OFFSET          (0x625c)
+#define DPHY_TX1RX1_TURNDISABLE_MASK  (0xF << 28)
+#define DPHY_TX1RX1_TURNDISABLE_BIT   (12)
+#define DPHY_TX1RX1_FORCERXMODE_MASK  (0xF << 20)
+#define DPHY_TX1RX1_FORCERXMODE_BIT   (4)
+#define DPHY_TX1RX1_FORCETXSTOPMODE_MASK   (0xF << 24)
+#define DPHY_TX1RX1_FORCETXSTOPMODE_BIT    (8)
+#define DPHY_TX1RX1_ENABLE_MASK            (0xF << 16)
+#define DPHY_TX1RX1_ENABLE_BIT             (0)
+
+#define GRF_SOC_CON24_OFFSET               (0x6260)
+#define DPHY_TX1RX1_MASTERSLAVEZ_MASK      (0x1 << 23)
+#define DPHY_TX1RX1_MASTERSLAVEZ_BIT       (7)
+#define DPHY_TX1RX1_BASEDIR_MASK           (0x1 << 21)
+#define DPHY_TX1RX1_BASEDIR_BIT            (5)
+#define DPHY_RX1_MASK                      (0x1 << 20)
+#define DPHY_RX1_SEL_BIT                   (4)
+
+#define GRF_SOC_CON25_OFFSET               (0x6264)
+#define DPHY_RX0_TESTCLK_MASK              (0x1 << 25)
+#define DPHY_RX0_TESTCLK_BIT               (9)
+#define DPHY_RX0_TESTCLR_MASK              (0x1 << 26)
+#define DPHY_RX0_TESTCLR_BIT               (10)
+#define DPHY_RX0_TESTDIN_MASK              (0xFF << 16)
+#define DPHY_RX0_TESTDIN_BIT               (0)
+#define DPHY_RX0_TESTEN_MASK               (0x1 << 24)
+#define DPHY_RX0_TESTEN_BIT                (8)
+
+#define DPHY_TX1RX1_TURNREQUEST_MASK       (0xF << 16)
+#define DPHY_TX1RX1_TURNREQUEST_BIT        (0)
+
+#define DSIHOST_PHY_SHUTDOWNZ              (0x00a0)
+#define DSIHOST_DPHY_RSTZ                  (0x00a0)
+#define DSIHOST_PHY_TEST_CTRL0             (0x00b4)
+#define DSIHOST_PHY_TEST_CTRL1             (0x00b8)
+
+#define write_cifisp_reg(addr, val)    \
+               __raw_writel(val, (addr) + rk3399->isp_base)
+#define read_cifisp_reg(addr)  \
+               __raw_readl((addr) + rk3399->isp_base)
+
+#define write_grf_reg(addr, val)       \
+               regmap_write(rk3399->regmap_grf, addr, val)
+#define read_grf_reg(addr, val)        \
+               regmap_read(rk3399->regmap_grf, addr, val)
+
+#define write_dsihost_reg(addr, val)   \
+               __raw_writel(val, (addr) + rk3399->dsihost_base)
+#define read_dsihost_reg(addr) \
+               __raw_readl((addr) + rk3399->dsihost_base)
+
+struct cif_isp10_clk_rst_rk3399 {
+       struct clk      *hclk_isp0_noc;
+       struct clk      *hclk_isp0_wrapper;
+       struct clk      *hclk_isp1_noc;
+       struct clk      *hclk_isp1_wrapper;
+       struct clk      *aclk_isp0_noc;
+       struct clk      *aclk_isp0_wrapper;
+       struct clk      *aclk_isp1_noc;
+       struct clk      *aclk_isp1_wrapper;
+       struct clk      *clk_isp0;
+       struct clk      *clk_isp1;
+       struct clk      *pclkin_isp1;
+       struct clk      *pclk_dphy_ref;
+       struct clk      *pclk_dphytxrx;
+       struct clk      *pclk_dphyrx;
+       struct clk      *cif_clk_out;
+       struct clk      *cif_clk_pll;
+       struct clk      *cif_clk_mipi_dsi;
+       struct clk      *cif_clk_mipi_dphy_cfg;
+};
+
+struct cif_isp10_rk3399 {
+       struct regmap *regmap_grf;
+       void __iomem *dsihost_base;
+       void __iomem *isp_base;
+       struct cif_isp10_clk_rst_rk3399 clk_rst;
+       struct cif_isp10_device *cif_isp10;
+};
+
+struct mipi_dphy_hsfreqrange {
+       unsigned int range_l;
+       unsigned int range_h;
+       unsigned char cfg_bit;
+};
+
+static struct mipi_dphy_hsfreqrange mipi_dphy_hsfreq_range[] = {
+       {80, 90, 0x00},
+       {90, 100, 0x10},
+       {100, 110, 0x20},
+       {110, 130, 0x01},
+       {130, 140, 0x11},
+       {140, 150, 0x21},
+       {150, 170, 0x02},
+       {170, 180, 0x12},
+       {180, 200, 0x22},
+       {200, 220, 0x03},
+       {220, 240, 0x13},
+       {240, 250, 0x23},
+       {250, 270, 0x4},
+       {270, 300, 0x14},
+       {300, 330, 0x5},
+       {330, 360, 0x15},
+       {360, 400, 0x25},
+       {400, 450, 0x06},
+       {450, 500, 0x16},
+       {500, 550, 0x07},
+       {550, 600, 0x17},
+       {600, 650, 0x08},
+       {650, 700, 0x18},
+       {700, 750, 0x09},
+       {750, 800, 0x19},
+       {800, 850, 0x29},
+       {850, 900, 0x39},
+       {900, 950, 0x0a},
+       {950, 1000, 0x1a},
+       {1000, 1050, 0x2a},
+       {1100, 1150, 0x3a},
+       {1150, 1200, 0x0b},
+       {1200, 1250, 0x1b},
+       {1250, 1300, 0x2b},
+       {1300, 1350, 0x0c},
+       {1350, 1400, 0x1c},
+       {1400, 1450, 0x2c},
+       {1450, 1500, 0x3c}
+};
+
+static struct cif_isp10_rk3399 *rk3399;
+static int mipi_dphy0_wr_reg(unsigned char addr, unsigned char data)
+{
+       /*
+        * TESTCLK=1
+        * TESTEN =1,TESTDIN=addr
+        * TESTCLK=0
+        */
+       write_grf_reg(GRF_SOC_CON25_OFFSET,
+               DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
+       write_grf_reg(GRF_SOC_CON25_OFFSET,
+               ((addr << DPHY_RX0_TESTDIN_BIT) | DPHY_RX0_TESTDIN_MASK
+                | (1 << DPHY_RX0_TESTEN_BIT) | DPHY_RX0_TESTEN_MASK));
+       write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK);
+
+       /*
+        * write data:
+        * TESTEN =0,TESTDIN=data
+        * TESTCLK=1
+        */
+       if (data != 0xff) {
+               write_grf_reg(GRF_SOC_CON25_OFFSET,
+                       ((data << DPHY_RX0_TESTDIN_BIT) |
+                       DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN_MASK));
+               write_grf_reg(GRF_SOC_CON25_OFFSET,
+                       DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
+       }
+       return 0;
+}
+
+static int mipi_dphy0_rd_reg(unsigned char addr)
+{
+       int val = 0;
+       /*TESTCLK=1*/
+       write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK |
+                               (1 << DPHY_RX0_TESTCLK_BIT));
+       /*TESTEN =1,TESTDIN=addr*/
+       write_grf_reg(GRF_SOC_CON25_OFFSET,
+                               ((addr << DPHY_RX0_TESTDIN_BIT) |
+                               DPHY_RX0_TESTDIN_MASK |
+                               (1 << DPHY_RX0_TESTEN_BIT) |
+                               DPHY_RX0_TESTEN_MASK));
+       /*TESTCLK=0*/
+       write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK);
+       read_grf_reg(GRF_SOC_STATUS1, &val);
+       return val & 0xff;
+}
+
+static int mipi_dphy1_wr_reg(unsigned char addr, unsigned char data)
+{
+       /*
+        * TESTEN =1,TESTDIN=addr
+        * TESTCLK=0
+        * TESTEN =0,TESTDIN=data
+        * TESTCLK=1
+        */
+       write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
+       write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000000);
+       write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00000000 | data));
+       write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
+
+       return 0;
+}
+
+static int mipi_dphy1_rd_reg(unsigned char addr)
+{
+       /* TESTEN =1,TESTDIN=addr */
+       write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
+       /* TESTCLK=0 */
+       write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000000);
+       return (read_dsihost_reg(DSIHOST_PHY_TEST_CTRL1) >> 8);
+}
+
+static int mipi_dphy_cfg(struct pltfrm_cam_mipi_config *para)
+{
+       unsigned char hsfreqrange = 0xff, i;
+       struct mipi_dphy_hsfreqrange *hsfreqrange_p;
+       unsigned char datalane_en, input_sel;
+
+       hsfreqrange_p = mipi_dphy_hsfreq_range;
+       for (i = 0;
+               i < (sizeof(mipi_dphy_hsfreq_range) /
+               sizeof(struct mipi_dphy_hsfreqrange));
+               i++) {
+               if ((para->bit_rate > hsfreqrange_p->range_l) &&
+                        (para->bit_rate <= hsfreqrange_p->range_h)) {
+                       hsfreqrange = hsfreqrange_p->cfg_bit;
+                       break;
+               }
+               hsfreqrange_p++;
+       }
+
+       if (hsfreqrange == 0xff)
+               hsfreqrange = 0x00;
+
+       hsfreqrange <<= 1;
+
+       input_sel = para->dphy_index;
+       datalane_en = 0;
+       for (i = 0; i < para->nb_lanes; i++)
+               datalane_en |= (1 << i);
+
+       if (input_sel == 0) {
+               write_grf_reg(GRF_SOC_CON21_OFFSET,
+                                       DPHY_RX0_FORCERXMODE_MASK |
+                                       (0x0 << DPHY_RX0_FORCERXMODE_BIT) |
+                                       DPHY_RX0_FORCETXSTOPMODE_MASK |
+                                       (0x0 << DPHY_RX0_FORCETXSTOPMODE_BIT));
+
+               /* set lane num */
+               write_grf_reg(GRF_SOC_CON21_OFFSET,
+                       DPHY_RX0_ENABLE_MASK |
+                       (datalane_en << DPHY_RX0_ENABLE_BIT));
+
+               /* set lan turndisab as 1 */
+               write_grf_reg(GRF_SOC_CON21_OFFSET,
+                       DPHY_RX0_TURNDISABLE_MASK |
+                       (0xf << DPHY_RX0_TURNDISABLE_BIT));
+               write_grf_reg(GRF_SOC_CON21_OFFSET, (0x0 << 4) | (0xf << 20));
+
+               /* set lan turnrequest as 0 */
+               write_grf_reg(GRF_SOC_CON9_OFFSET,
+                       DPHY_RX0_TURNREQUEST_MASK |
+                       (0x0 << DPHY_RX0_TURNREQUEST_BIT));
+
+               /* phy start */
+               /*
+                * TESTCLK=1
+                * TESTCLR=1
+                * delay 100us
+                * TESTCLR=0
+                */
+               write_grf_reg(GRF_SOC_CON25_OFFSET,
+                       DPHY_RX0_TESTCLK_MASK |
+                       (0x1 << DPHY_RX0_TESTCLK_BIT)); /* TESTCLK=1 */
+               write_grf_reg(GRF_SOC_CON25_OFFSET,
+                       DPHY_RX0_TESTCLR_MASK |
+                       (0x1 << DPHY_RX0_TESTCLR_BIT));   /* TESTCLR=1 */
+               usleep_range(100, 150);
+               /* TESTCLR=0  zyc */
+               write_grf_reg(GRF_SOC_CON25_OFFSET,
+                       DPHY_RX0_TESTCLR_MASK);
+               usleep_range(100, 150);
+
+               /* set clock lane */
+               mipi_dphy0_wr_reg
+                       (0x34, 0);
+               /* HS hsfreqrange & lane 0  settle bypass */
+               mipi_dphy0_wr_reg(0x44, hsfreqrange);
+               mipi_dphy0_wr_reg(0x54, 0);
+               mipi_dphy0_wr_reg(0x84, 0);
+               mipi_dphy0_wr_reg(0x94, 0);
+               mipi_dphy0_wr_reg(0x75, 0x04);
+               mipi_dphy0_rd_reg(0x75);
+
+               /* Normal operation */
+               /*
+                * TESTCLK=1
+                * TESTEN =0
+                */
+               mipi_dphy0_wr_reg(0x0, -1);
+               write_grf_reg(GRF_SOC_CON25_OFFSET,
+                       DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
+               write_grf_reg(GRF_SOC_CON25_OFFSET,
+                       (DPHY_RX0_TESTEN_MASK));
+
+               write_cifisp_reg((MRV_MIPI_BASE + MRV_MIPI_CTRL),
+                       read_cifisp_reg(MRV_MIPI_BASE + MRV_MIPI_CTRL)
+                       | (0x0f << 8));
+
+       } else if (input_sel == 1) {
+               write_grf_reg(GRF_SOC_CON23_OFFSET,
+                       DPHY_RX0_FORCERXMODE_MASK |
+                       (0x0 << DPHY_RX0_FORCERXMODE_BIT) |
+                       DPHY_RX0_FORCETXSTOPMODE_MASK |
+                       (0x0 << DPHY_RX0_FORCETXSTOPMODE_BIT));
+               write_grf_reg(GRF_SOC_CON24_OFFSET,
+                       DPHY_TX1RX1_MASTERSLAVEZ_MASK |
+                       (0x0 << DPHY_TX1RX1_MASTERSLAVEZ_BIT) |
+                       DPHY_TX1RX1_BASEDIR_MASK |
+                       (0x1 << DPHY_TX1RX1_BASEDIR_BIT) |
+                       DPHY_RX1_MASK | 0x0 << DPHY_RX1_SEL_BIT);
+
+               /* set lane num */
+               write_grf_reg(GRF_SOC_CON23_OFFSET,
+                       DPHY_TX1RX1_ENABLE_MASK |
+                       (datalane_en << DPHY_TX1RX1_ENABLE_BIT));
+
+               /* set lan turndisab as 1 */
+               write_grf_reg(GRF_SOC_CON23_OFFSET,
+                       DPHY_TX1RX1_TURNDISABLE_MASK |
+                       (0xf << DPHY_TX1RX1_TURNDISABLE_BIT));
+               write_grf_reg(GRF_SOC_CON23_OFFSET, (0x0 << 4) | (0xf << 20));
+
+               /* set lan turnrequest as 0   */
+               write_grf_reg(GRF_SOC_CON24_OFFSET,
+                       DPHY_TX1RX1_TURNREQUEST_MASK |
+                       (0x0 << DPHY_TX1RX1_TURNREQUEST_BIT));
+
+               /* phy1 start */
+               /*
+                * SHUTDOWNZ=0
+                * RSTZ=0
+                * TESTCLK=1
+                * TESTCLR=1 TESTCLK=1
+                * TESTCLR=0 TESTCLK=1
+                */
+               write_dsihost_reg(DSIHOST_PHY_SHUTDOWNZ, 0x00000000);
+               write_dsihost_reg(DSIHOST_DPHY_RSTZ, 0x00000000);
+               write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
+               write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, 0x00000003);
+               usleep_range(100, 150);
+               write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
+               usleep_range(100, 150);
+
+               /* set clock lane */
+               mipi_dphy1_wr_reg(0x34, 0x00);
+               mipi_dphy1_wr_reg(0x44, hsfreqrange);
+               mipi_dphy1_wr_reg(0x54, 0);
+               mipi_dphy1_wr_reg(0x84, 0);
+               mipi_dphy1_wr_reg(0x94, 0);
+               mipi_dphy1_wr_reg(0x75, 0x04);
+
+               mipi_dphy1_rd_reg(0x0);
+               /*
+                * TESTCLK=1
+                * TESTEN =0
+                * SHUTDOWNZ=1
+                * RSTZ=1
+                */
+               write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
+               write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, 0x00000000);
+               write_dsihost_reg(DSIHOST_PHY_SHUTDOWNZ, 0x00000001);
+               write_dsihost_reg(DSIHOST_DPHY_RSTZ, 0x00000001);
+       } else {
+               goto fail;
+       }
+
+       return 0;
+fail:
+       return -1;
+}
+
+static int soc_clk_enable(void)
+{
+       struct cif_isp10_clk_rst_rk3399 *clk_rst = &rk3399->clk_rst;
+
+       clk_prepare_enable(clk_rst->hclk_isp0_noc);
+       clk_prepare_enable(clk_rst->hclk_isp0_wrapper);
+       clk_prepare_enable(clk_rst->aclk_isp0_noc);
+       clk_prepare_enable(clk_rst->aclk_isp0_wrapper);
+       clk_prepare_enable(clk_rst->clk_isp0);
+       clk_prepare_enable(clk_rst->cif_clk_out);
+       clk_prepare_enable(clk_rst->pclk_dphyrx);
+       clk_prepare_enable(clk_rst->pclk_dphy_ref);
+
+       return 0;
+}
+
+static int soc_clk_disable(void)
+{
+       struct cif_isp10_clk_rst_rk3399 *clk_rst = &rk3399->clk_rst;
+
+       clk_disable_unprepare(clk_rst->hclk_isp0_noc);
+       clk_disable_unprepare(clk_rst->hclk_isp0_wrapper);
+       clk_disable_unprepare(clk_rst->aclk_isp0_noc);
+       clk_disable_unprepare(clk_rst->aclk_isp0_wrapper);
+       clk_disable_unprepare(clk_rst->clk_isp0);
+       clk_disable_unprepare(clk_rst->pclk_dphyrx);
+       clk_disable_unprepare(clk_rst->pclk_dphy_ref);
+       if (!IS_ERR_OR_NULL(clk_rst->cif_clk_pll)) {
+               clk_set_parent(clk_rst->cif_clk_out,
+                       clk_rst->cif_clk_pll);
+       }
+       clk_disable_unprepare(clk_rst->cif_clk_out);
+
+       return 0;
+}
+
+static int soc_init(struct pltfrm_soc_init_para *init)
+{
+       struct cif_isp10_clk_rst_rk3399 *clk_rst;
+       struct platform_device *pdev = init->pdev;
+       struct device_node *np = pdev->dev.of_node, *node;
+       struct resource *res;
+       int err;
+
+       rk3399 = (struct cif_isp10_rk3399 *)devm_kzalloc(
+                               &pdev->dev,
+                               sizeof(struct cif_isp10_rk3399),
+                               GFP_KERNEL);
+       if (!rk3399) {
+               dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3399\n");
+               err = -ENOMEM;
+               goto alloc_failed;
+       }
+
+       node = of_parse_phandle(np, "rockchip,grf", 0);
+       if (node) {
+               rk3399->regmap_grf = syscon_node_to_regmap(node);
+               if (IS_ERR(rk3399->regmap_grf)) {
+                       dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3399\n");
+                       err = -ENODEV;
+                       goto regmap_failed;
+               }
+       }
+
+       res = platform_get_resource_byname(pdev,
+                               IORESOURCE_MEM, "dsihost-register");
+       if (!res) {
+               dev_err(&pdev->dev,
+                       "platform_get_resource_byname dsihost-register failed\n");
+               err = -ENODEV;
+               goto regmap_failed;
+       }
+       rk3399->dsihost_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR_OR_NULL(rk3399->dsihost_base)) {
+               dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+               if (IS_ERR(rk3399->dsihost_base))
+                       err = PTR_ERR(rk3399->dsihost_base);
+               else
+                       err = -ENODEV;
+               goto regmap_failed;
+       }
+
+       clk_rst = &rk3399->clk_rst;
+
+       clk_rst->hclk_isp0_noc     =
+               devm_clk_get(&pdev->dev, "hclk_isp0_noc");
+       clk_rst->hclk_isp0_wrapper =
+               devm_clk_get(&pdev->dev, "hclk_isp0_wrapper");
+       clk_rst->aclk_isp0_noc     =
+               devm_clk_get(&pdev->dev, "aclk_isp0_noc");
+       clk_rst->aclk_isp0_wrapper =
+               devm_clk_get(&pdev->dev, "aclk_isp0_wrapper");
+       clk_rst->clk_isp0                  =
+               devm_clk_get(&pdev->dev, "clk_isp0");
+       clk_rst->cif_clk_out       =
+               devm_clk_get(&pdev->dev, "clk_cif_out");
+       clk_rst->cif_clk_pll       =
+               devm_clk_get(&pdev->dev, "cif_clk_pll");
+       clk_rst->pclk_dphyrx       =
+               devm_clk_get(&pdev->dev, "pclk_dphyrx");
+       clk_rst->pclk_dphy_ref     =
+               devm_clk_get(&pdev->dev, "pclk_dphy_ref");
+
+       if (IS_ERR_OR_NULL(clk_rst->hclk_isp0_noc)               ||
+               IS_ERR_OR_NULL(clk_rst->hclk_isp0_wrapper)       ||
+               IS_ERR_OR_NULL(clk_rst->aclk_isp0_noc)           ||
+               IS_ERR_OR_NULL(clk_rst->aclk_isp0_wrapper)       ||
+               IS_ERR_OR_NULL(clk_rst->clk_isp0)                        ||
+               IS_ERR_OR_NULL(clk_rst->cif_clk_out)             ||
+               IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref)           ||
+               IS_ERR_OR_NULL(clk_rst->pclk_dphyrx)) {
+               dev_err(&pdev->dev, "Get rk3399 cif isp10 clock resouce failed !\n");
+               err = -EINVAL;
+               goto clk_failed;
+       }
+
+       clk_set_rate(clk_rst->clk_isp0, 420000000);
+
+       rk3399->isp_base = init->isp_base;
+       return 0;
+
+clk_failed:
+       if (!IS_ERR_OR_NULL(clk_rst->hclk_isp0_noc))
+               devm_clk_put(&pdev->dev, clk_rst->hclk_isp0_noc);
+
+       if (!IS_ERR_OR_NULL(clk_rst->hclk_isp0_wrapper))
+               devm_clk_put(&pdev->dev, clk_rst->hclk_isp0_wrapper);
+
+       if (!IS_ERR_OR_NULL(clk_rst->aclk_isp0_noc))
+               devm_clk_put(&pdev->dev, clk_rst->aclk_isp0_noc);
+
+       if (!IS_ERR_OR_NULL(clk_rst->aclk_isp0_wrapper))
+               devm_clk_put(&pdev->dev, clk_rst->aclk_isp0_wrapper);
+
+       if (!IS_ERR_OR_NULL(clk_rst->clk_isp0))
+               devm_clk_put(&pdev->dev, clk_rst->clk_isp0);
+
+       if (!IS_ERR_OR_NULL(clk_rst->cif_clk_out))
+               devm_clk_put(&pdev->dev, clk_rst->cif_clk_out);
+
+       if (!IS_ERR_OR_NULL(clk_rst->cif_clk_pll))
+               devm_clk_put(&pdev->dev, clk_rst->cif_clk_pll);
+
+       if (!IS_ERR_OR_NULL(clk_rst->pclk_dphyrx))
+               devm_clk_put(&pdev->dev, clk_rst->pclk_dphyrx);
+
+       if (!IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref))
+               devm_clk_put(&pdev->dev, clk_rst->pclk_dphy_ref);
+
+regmap_failed:
+
+alloc_failed:
+
+       return err;
+}
+
+int pltfrm_rk3399_cfg(
+               struct pltfrm_soc_cfg_para *cfg)
+{
+       switch (cfg->cmd) {
+       case PLTFRM_MCLK_CFG: {
+               struct pltfrm_soc_mclk_para *mclk_para;
+
+               mclk_para = (struct pltfrm_soc_mclk_para *)cfg->cfg_para;
+               if (mclk_para->io_voltage == PLTFRM_IO_1V8)
+                       write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V18SEL);
+               else
+                       write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V33SEL);
+
+               write_grf_reg(GRF_GPIO2B_E_OFFSET,
+                       CIF_CLKOUT_STRENGTH(mclk_para->drv_strength));
+               break;
+       }
+       case PLTFRM_MIPI_DPHY_CFG:
+               mipi_dphy_cfg((struct pltfrm_cam_mipi_config *)cfg->cfg_para);
+               break;
+
+       case PLTFRM_CLKEN:
+               soc_clk_enable();
+               break;
+
+       case PLTFRM_CLKDIS:
+               soc_clk_disable();
+               break;
+
+       case PLTFRM_CLKRST:
+               write_cifisp_reg(VI_IRCL, 0x80);
+               usleep_range(10, 15);
+               write_cifisp_reg(VI_IRCL, 0x00);
+               break;
+
+       case PLTFRM_SOC_INIT:
+               soc_init((struct pltfrm_soc_init_para *)cfg->cfg_para);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c
new file mode 100644 (file)
index 0000000..448ecfe
--- /dev/null
@@ -0,0 +1,1854 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf-dma-contig.h>
+#include "cif_isp10.h"
+#include "cif_isp10_regs.h"
+#include "cif_isp10_version.h"
+#include <linux/module.h>
+#include <linux/of.h>
+#include <media/v4l2-controls_rockchip.h>
+#include <linux/pm_runtime.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+
+#define CIF_ISP10_V4L2_SP_DEV_MAJOR 0
+#define CIF_ISP10_V4L2_ISP_DEV_MAJOR 1
+#define CIF_ISP10_V4L2_MP_DEV_MAJOR 2
+#define CIF_ISP10_V4L2_DMA_DEV_MAJOR 3
+
+#define SP_DEV 0
+#define MP_DEV 1
+#define DMA_DEV 2
+#define ISP_DEV 3
+
+/* One structure per open file handle */
+struct cif_isp10_v4l2_fh {
+       enum cif_isp10_stream_id stream_id;
+       struct v4l2_fh fh;
+};
+
+/* One structure per video node */
+struct cif_isp10_v4l2_node {
+       struct videobuf_queue buf_queue;
+       struct video_device vdev;
+       int users;
+       struct cif_isp10_v4l2_fh *owner;
+};
+
+/* One structure per device */
+struct cif_isp10_v4l2_device {
+       struct cif_isp10_v4l2_node node[4];
+};
+
+/* spinlock define */
+spinlock_t iowrite32_verify_lock;
+
+static struct cif_isp10_v4l2_fh *to_fh(struct file *file)
+{
+       if (!file || !file->private_data)
+               return NULL;
+
+       return container_of(file->private_data, struct cif_isp10_v4l2_fh, fh);
+}
+
+static struct cif_isp10_v4l2_node *to_node(struct cif_isp10_v4l2_fh *fh)
+{
+       struct video_device *vdev = fh ? fh->fh.vdev : NULL;
+
+       if (!fh || !vdev)
+               return NULL;
+
+       return container_of(vdev, struct cif_isp10_v4l2_node, vdev);
+}
+
+static struct videobuf_queue *to_videobuf_queue(
+       struct file *file)
+{
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       struct video_device *vdev = fh ? fh->fh.vdev : NULL;
+       struct cif_isp10_v4l2_node *node = to_node(fh);
+       struct videobuf_queue *q;
+
+       if (unlikely(!vdev)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "vdev is NULL\n");
+               WARN_ON(1);
+       }
+       q = &node->buf_queue;
+       if (unlikely(!q)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "buffer queue is NULL\n");
+               WARN_ON(1);
+       }
+
+       return q;
+}
+
+static enum cif_isp10_stream_id to_stream_id(
+       struct file *file)
+{
+       struct cif_isp10_v4l2_fh *fh;
+
+       if (unlikely(!file)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "NULL file handle\n");
+               WARN_ON(1);
+       }
+       fh = to_fh(file);
+       if (unlikely(!fh)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "fh is NULL\n");
+               WARN_ON(1);
+       }
+
+       return fh->stream_id;
+}
+
+static struct cif_isp10_device *to_cif_isp10_device(
+       struct videobuf_queue *queue)
+{
+       return queue->priv_data;
+}
+
+static enum cif_isp10_stream_id to_cif_isp10_stream_id(
+       struct videobuf_queue *queue)
+{
+       struct cif_isp10_v4l2_node *node =
+               container_of(queue, struct cif_isp10_v4l2_node, buf_queue);
+       struct video_device *vdev =
+               &node->vdev;
+
+       if (!strcmp(vdev->name, SP_VDEV_NAME))
+               return CIF_ISP10_STREAM_SP;
+       if (!strcmp(vdev->name, MP_VDEV_NAME))
+               return CIF_ISP10_STREAM_MP;
+       if (!strcmp(vdev->name, DMA_VDEV_NAME))
+               return CIF_ISP10_STREAM_DMA;
+
+       cif_isp10_pltfrm_pr_err(NULL,
+               "unsupported/unknown device name %s\n", vdev->name);
+       return -EINVAL;
+}
+
+static const char *cif_isp10_v4l2_buf_type_string(
+       enum v4l2_buf_type buf_type)
+{
+       switch (buf_type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return "VIDEO_CAPTURE";
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               return "VIDEO_OVERLAY";
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               return "VIDEO_OUTPUT";
+       default:
+               break;
+       }
+       return "UNKNOWN/UNSUPPORTED";
+}
+
+const char *cif_isp10_v4l2_pix_fmt_string(
+       int pix_fmt)
+{
+       switch (pix_fmt) {
+       case V4L2_PIX_FMT_RGB332:
+               return "V4L2-RGB332";
+       case V4L2_PIX_FMT_RGB555:
+               return "V4L2-RGB555";
+       case V4L2_PIX_FMT_RGB565:
+               return "V4L2-RGB565";
+       case V4L2_PIX_FMT_RGB555X:
+               return "V4L2-RGB555X";
+       case V4L2_PIX_FMT_RGB565X:
+               return "V4L2-RGB565X";
+       case V4L2_PIX_FMT_BGR24:
+               return "V4L2-BGR24";
+       case V4L2_PIX_FMT_RGB24:
+               return "V4L2-RGB24";
+       case V4L2_PIX_FMT_BGR32:
+               return "V4L2-BGR32";
+       case V4L2_PIX_FMT_RGB32:
+               return "V4L2-RGB32";
+       case V4L2_PIX_FMT_GREY:
+               return "V4L2-GREY";
+       case V4L2_PIX_FMT_YVU410:
+               return "V4L2-YVU410";
+       case V4L2_PIX_FMT_YVU420:
+               return "V4L2-YVU420";
+       case V4L2_PIX_FMT_YUYV:
+               return "V4L2-YUYV";
+       case V4L2_PIX_FMT_UYVY:
+               return "V4L2-UYVY";
+       case V4L2_PIX_FMT_YUV422P:
+               return "V4L2-YUV422P";
+       case V4L2_PIX_FMT_YUV411P:
+               return "V4L2-YUV411P";
+       case V4L2_PIX_FMT_Y41P:
+               return "V4L2-Y41P";
+       case V4L2_PIX_FMT_NV12:
+               return "V4L2-NV12";
+       case V4L2_PIX_FMT_NV21:
+               return "V4L2-NV21";
+       case V4L2_PIX_FMT_YUV410:
+               return "V4L2-YUV410";
+       case V4L2_PIX_FMT_YUV420:
+               return "V4L2--YUV420";
+       case V4L2_PIX_FMT_YYUV:
+               return "V4L2-YYUV";
+       case V4L2_PIX_FMT_HI240:
+               return "V4L2-HI240";
+       case V4L2_PIX_FMT_WNVA:
+               return "V4L2-WNVA";
+       case V4L2_PIX_FMT_NV16:
+               return "V4L2-NV16";
+       case V4L2_PIX_FMT_YUV444:
+               return "V4L2-YUV444P";
+       case V4L2_PIX_FMT_NV24:
+               return "M5-YUV444SP";
+       case V4L2_PIX_FMT_JPEG:
+               return "V4L2-JPEG";
+       case V4L2_PIX_FMT_SGRBG10:
+               return "RAW-BAYER-10Bits";
+       case V4L2_PIX_FMT_SGRBG8:
+               return "RAW-BAYER-8Bits";
+       }
+       return "UNKNOWN/UNSUPPORTED";
+}
+
+static int cif_isp10_v4l2_cid2cif_isp10_cid(u32 v4l2_cid)
+{
+       switch (v4l2_cid) {
+       case V4L2_CID_FLASH_LED_MODE:
+               return CIF_ISP10_CID_FLASH_MODE;
+       case V4L2_CID_AUTOGAIN:
+               return CIF_ISP10_CID_AUTO_GAIN;
+       case V4L2_EXPOSURE_AUTO:
+               return CIF_ISP10_CID_AUTO_EXPOSURE;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               return CIF_ISP10_CID_AUTO_WHITE_BALANCE;
+       case V4L2_CID_BLACK_LEVEL:
+               return CIF_ISP10_CID_BLACK_LEVEL;
+       case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
+               return CIF_ISP10_CID_WB_TEMPERATURE;
+       case V4L2_CID_EXPOSURE:
+               return CIF_ISP10_CID_EXPOSURE_TIME;
+       case V4L2_CID_GAIN:
+               return CIF_ISP10_CID_ANALOG_GAIN;
+       case V4L2_CID_FOCUS_ABSOLUTE:
+               return CIF_ISP10_CID_FOCUS_ABSOLUTE;
+       case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
+               return CIF_ISP10_CID_AUTO_N_PRESET_WHITE_BALANCE;
+       case V4L2_CID_SCENE_MODE:
+               return CIF_ISP10_CID_SCENE_MODE;
+       case V4L2_CID_COLORFX:
+               return CIF_ISP10_CID_IMAGE_EFFECT;
+       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+               return CIF_ISP10_CID_JPEG_QUALITY;
+       case V4L2_CID_HFLIP:
+               return CIF_ISP10_CID_HFLIP;
+       case V4L2_CID_VFLIP:
+               return CIF_ISP10_CID_VFLIP;
+       case V4L2_CID_ISO_SENSITIVITY:
+               return CIF_ISP10_CID_ISO_SENSITIVITY;
+       case RK_V4L2_CID_AUTO_FPS:
+               return CIF_ISP10_CID_AUTO_FPS;
+       default:
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown/unsupported V4L2 CID 0x%x\n",
+                       v4l2_cid);
+               break;
+       }
+       return -EINVAL;
+}
+
+static enum cif_isp10_image_effect cif_isp10_v4l2_colorfx2cif_isp10_ie(
+       u32 v4l2_colorfx)
+{
+       switch (v4l2_colorfx) {
+       case V4L2_COLORFX_SEPIA:
+               return CIF_ISP10_IE_SEPIA;
+       case V4L2_COLORFX_BW:
+               return CIF_ISP10_IE_BW;
+       case V4L2_COLORFX_NEGATIVE:
+               return CIF_ISP10_IE_NEGATIVE;
+       case V4L2_COLORFX_EMBOSS:
+               return CIF_ISP10_IE_EMBOSS;
+       case V4L2_COLORFX_SKETCH:
+               return CIF_ISP10_IE_SKETCH;
+       case V4L2_COLORFX_NONE:
+               return CIF_ISP10_IE_NONE;
+       default:
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown/unsupported V4L2 COLORFX %d\n",
+                       v4l2_colorfx);
+               break;
+       }
+       return -EINVAL;
+}
+
+static enum cif_isp10_pix_fmt cif_isp10_v4l2_pix_fmt2cif_isp10_pix_fmt(
+       u32 v4l2_pix_fmt, struct videobuf_queue *queue)
+{
+/*struct cif_isp10_v4l2_node *node =
+ *     container_of(queue, struct cif_isp10_v4l2_node, buf_queue);
+ *     struct video_device *vdev =
+ *     &node->vdev;
+ */
+
+       switch (v4l2_pix_fmt) {
+       case V4L2_PIX_FMT_GREY:
+               return CIF_YUV400;
+       case V4L2_PIX_FMT_YUV420:
+               return CIF_YUV420P;
+       case V4L2_PIX_FMT_YVU420:
+               return CIF_YVU420P;
+       case V4L2_PIX_FMT_NV12:
+               return CIF_YUV420SP;
+       case V4L2_PIX_FMT_NV21:
+               return CIF_YVU420SP;
+       case V4L2_PIX_FMT_YUYV:
+               return CIF_YUV422I;
+       case V4L2_PIX_FMT_UYVY:
+               return CIF_UYV422I;
+       case V4L2_PIX_FMT_YUV422P:
+               return CIF_YUV422P;
+       case V4L2_PIX_FMT_NV16:
+               return CIF_YUV422SP;
+       case V4L2_PIX_FMT_YUV444:
+               return CIF_YUV444P;
+       case V4L2_PIX_FMT_NV24:
+               return CIF_YUV444SP;
+       case V4L2_PIX_FMT_RGB565:
+               return CIF_RGB565;
+       case V4L2_PIX_FMT_RGB24:
+               return CIF_RGB888;
+       case V4L2_PIX_FMT_SBGGR8:
+               return CIF_BAYER_SBGGR8;
+       case V4L2_PIX_FMT_SGBRG8:
+               return CIF_BAYER_SGBRG8;
+       case V4L2_PIX_FMT_SGRBG8:
+               return CIF_BAYER_SGRBG8;
+       case V4L2_PIX_FMT_SRGGB8:
+               return CIF_BAYER_SRGGB8;
+       case V4L2_PIX_FMT_SBGGR10:
+               return CIF_BAYER_SBGGR10;
+       case V4L2_PIX_FMT_SGBRG10:
+               return CIF_BAYER_SGBRG10;
+       case V4L2_PIX_FMT_SGRBG10:
+               return CIF_BAYER_SGRBG10;
+       case V4L2_PIX_FMT_SRGGB10:
+               return CIF_BAYER_SRGGB10;
+       case V4L2_PIX_FMT_SBGGR12:
+               return CIF_BAYER_SBGGR12;
+       case V4L2_PIX_FMT_SGBRG12:
+               return CIF_BAYER_SGBRG12;
+       case V4L2_PIX_FMT_SGRBG12:
+               return CIF_BAYER_SGRBG12;
+       case V4L2_PIX_FMT_SRGGB12:
+               return CIF_BAYER_SRGGB12;
+       case V4L2_PIX_FMT_JPEG:
+               return CIF_JPEG;
+       default:
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "unknown or unsupported V4L2 pixel format %c%c%c%c\n",
+                       (u8)(v4l2_pix_fmt & 0xff),
+                       (u8)((v4l2_pix_fmt >> 8) & 0xff),
+                       (u8)((v4l2_pix_fmt >> 16) & 0xff),
+                       (u8)((v4l2_pix_fmt >> 24) & 0xff));
+               return CIF_UNKNOWN_FORMAT;
+       }
+}
+
+static int cif_isp10_v4l2_register_video_device(
+       struct cif_isp10_device *dev,
+       struct video_device *vdev,
+       const char *name,
+       int qtype,
+       int major,
+       const struct v4l2_file_operations *fops,
+       const struct v4l2_ioctl_ops *ioctl_ops)
+{
+       int ret;
+
+       vdev->release = video_device_release;
+       strlcpy(vdev->name, name, sizeof(vdev->name));
+       vdev->vfl_type = qtype;
+       vdev->fops = fops;
+       video_set_drvdata(vdev, dev);
+       vdev->minor = -1;
+       vdev->ioctl_ops = ioctl_ops;
+       vdev->v4l2_dev = &dev->v4l2_dev;
+       if (qtype == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               vdev->vfl_dir = VFL_DIR_TX;
+       else
+               vdev->vfl_dir = VFL_DIR_RX;
+
+       ret = video_register_device(vdev, VFL_TYPE_GRABBER, major);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "video_register_device failed with error %d\n", ret);
+               goto err;
+       }
+
+       cif_isp10_pltfrm_pr_info(NULL,
+               "video device video%d.%d (%s) successfully registered\n",
+               major, vdev->minor, name);
+
+       return 0;
+err:
+       video_device_release(vdev);
+       cif_isp10_pltfrm_pr_err(NULL,
+               "failed with err %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_v4l2_streamon(
+       struct file *file,
+       void *priv,
+       enum v4l2_buf_type buf_type)
+{
+       int ret;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       static u32 streamon_cnt_sp;
+       static u32 streamon_cnt_mp;
+       static u32 streamon_cnt_dma;
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       struct cif_isp10_v4l2_node *node = to_node(fh);
+       u32 stream_ids = to_stream_id(file);
+
+       if (node->owner != fh)
+               return -EBUSY;
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "%s(%d)\n",
+               cif_isp10_v4l2_buf_type_string(queue->type),
+               (stream_ids & CIF_ISP10_STREAM_MP) ? ++streamon_cnt_mp :
+               ((stream_ids & CIF_ISP10_STREAM_SP) ? ++streamon_cnt_sp :
+               ++streamon_cnt_dma));
+
+       ret = videobuf_streamon(queue);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "videobuf_streamon failed\n");
+               goto err;
+       }
+
+       ret = cif_isp10_streamon(dev, stream_ids);
+       if (IS_ERR_VALUE(ret)) {
+               videobuf_queue_cancel(queue);
+               goto err;
+       }
+
+       return 0;
+err:
+       (void)videobuf_mmap_free(queue);
+       cif_isp10_pltfrm_pr_err(dev->dev, "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_v4l2_do_streamoff(
+       struct file *file)
+{
+       int ret = 0;
+       int err;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       struct cif_isp10_v4l2_node *node = to_node(fh);
+       u32 stream_ids = to_stream_id(file);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "%s\n",
+               cif_isp10_v4l2_buf_type_string(queue->type));
+
+       if (node->owner != fh)
+               return -EBUSY;
+
+       err = cif_isp10_streamoff(dev, stream_ids);
+       if (IS_ERR_VALUE(err))
+               ret = -EFAULT;
+       err = videobuf_streamoff(queue);
+       if (IS_ERR_VALUE(err)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "videobuf_streamoff failed with error %d\n", err);
+               ret = -EFAULT;
+       }
+       err = videobuf_mmap_free(queue);
+       if (IS_ERR_VALUE(err)) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "videobuf_mmap_free failed with error %d\n", err);
+               ret = -EFAULT;
+       }
+
+       if (IS_ERR_VALUE(ret))
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "failed with error %d\n", ret);
+
+       return ret;
+}
+
+static int cif_isp10_v4l2_streamoff(
+       struct file *file,
+       void *priv,
+       enum v4l2_buf_type buf_type)
+{
+       int ret = cif_isp10_v4l2_do_streamoff(file);
+
+       if (IS_ERR_VALUE(ret))
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "failed with error %d\n", ret);
+
+       return ret;
+}
+
+static int cif_isp10_v4l2_qbuf(
+       struct file *file,
+       void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       struct cif_isp10_v4l2_node *node = to_node(fh);
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "%s buffer type %s, index %d, length %d\n",
+               cif_isp10_v4l2_buf_type_string(queue->type),
+               cif_isp10_v4l2_buf_type_string(buf->type),
+               buf->index, buf->length);
+
+       if (node->owner != fh)
+               return -EBUSY;
+
+       ret = videobuf_qbuf(queue, buf);
+       if (IS_ERR_VALUE(ret))
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "videobuf_qbuf failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_v4l2_dqbuf(
+       struct file *file,
+       void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       struct cif_isp10_v4l2_node *node = to_node(fh);
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+               cif_isp10_v4l2_buf_type_string(queue->type));
+
+       if (node->owner != fh)
+               return -EBUSY;
+
+       ret = videobuf_dqbuf(queue, buf, file->f_flags & O_NONBLOCK);
+       if (IS_ERR_VALUE(ret) && (ret != -EAGAIN))
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "videobuf_dqbuf failed with error %d\n", ret);
+       else
+               cif_isp10_pltfrm_pr_dbg(NULL,
+                       "dequeued buffer %d, size %d\n",
+                       buf->index, buf->length);
+       return ret;
+}
+
+static void cif_isp10_v4l2_buf_release(
+       struct videobuf_queue *queue,
+       struct videobuf_buffer *buf)
+{
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "%s\n",
+               cif_isp10_v4l2_buf_type_string(queue->type));
+
+       if (in_interrupt())
+               WARN_ON(1);
+
+       videobuf_dma_contig_free(queue, buf);
+
+       buf->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static void cif_isp10_v4l2_buf_queue(
+       struct videobuf_queue *queue,
+       struct videobuf_buffer *buf)
+{
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "%s %dx%d, size %lu, bytesperline %d\n",
+               cif_isp10_v4l2_buf_type_string(queue->type),
+               buf->width, buf->height, buf->size, buf->bytesperline);
+
+       if (!IS_ERR_VALUE(cif_isp10_qbuf(dev, strm, buf)))
+               buf->state = VIDEOBUF_QUEUED;
+       else
+               cif_isp10_pltfrm_pr_err(NULL, "failed\n");
+}
+
+static int cif_isp10_v4l2_buf_setup(
+       struct videobuf_queue *queue,
+       unsigned int *cnt,
+       unsigned int *size)
+{
+       int ret;
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "%s count %d, size %d\n",
+               cif_isp10_v4l2_buf_type_string(queue->type),
+               *cnt, *size);
+
+       ret = cif_isp10_calc_min_out_buff_size(
+               dev, strm, size);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+               return ret;
+       }
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "%s count %d, size %d\n",
+               cif_isp10_v4l2_buf_type_string(queue->type),
+               *cnt, *size);
+
+       return 0;
+}
+
+static int cif_isp10_v4l2_buf_prepare(
+       struct videobuf_queue *queue,
+       struct videobuf_buffer *buf,
+       enum v4l2_field field)
+{
+       int ret;
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+       u32 size;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+               cif_isp10_v4l2_buf_type_string(queue->type));
+
+       ret = cif_isp10_calc_min_out_buff_size(
+               dev, strm, &size);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+       buf->size = size;
+       if (strm == CIF_ISP10_STREAM_SP) {
+               buf->width =
+                       dev->config.mi_config.sp.output.width;
+               buf->height =
+                       dev->config.mi_config.sp.output.height;
+       } else if (strm == CIF_ISP10_STREAM_MP) {
+               buf->width =
+                       dev->config.mi_config.mp.output.width;
+               buf->height =
+                       dev->config.mi_config.mp.output.height;
+       } else if (strm == CIF_ISP10_STREAM_DMA) {
+               buf->width =
+                       dev->config.mi_config.dma.output.width;
+               buf->height =
+                       dev->config.mi_config.dma.output.height;
+       } else {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "wrong buffer queue %d\n", queue->type);
+               ret = -EINVAL;
+               goto err;
+       }
+       buf->field = field;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "%s buffer prepared %dx%d, size %d\n",
+               cif_isp10_v4l2_buf_type_string(queue->type),
+               buf->width, buf->height, size);
+
+       if (buf->state == VIDEOBUF_NEEDS_INIT) {
+               ret = videobuf_iolock(queue, buf, NULL);
+               if (IS_ERR_VALUE(ret)) {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "videobuf_iolock failed with error %d\n", ret);
+                       goto err;
+               }
+       }
+       buf->state = VIDEOBUF_PREPARED;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+       cif_isp10_v4l2_buf_release(queue, buf);
+       return ret;
+}
+
+static int cif_isp10_v4l2_reqbufs(
+       struct file *file,
+       void *priv,
+       struct v4l2_requestbuffers *req)
+{
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       struct cif_isp10_v4l2_node *node = to_node(fh);
+       int ret;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "%s requested type %s, count %d\n",
+               cif_isp10_v4l2_buf_type_string(queue->type),
+               cif_isp10_v4l2_buf_type_string(req->type),
+               req->count);
+
+       if (node->owner && node->owner != fh)
+               return -EBUSY;
+       node->owner = fh;
+
+       ret = videobuf_reqbufs(queue, req);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "videobuf_reqbufs failed with error %d\n", ret);
+       }
+       cif_isp10_reqbufs(dev, strm, req);
+       return ret;
+}
+
+static int cif_isp10_v4l2_querybuf(
+       struct file *file,
+       void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "%s, index %d\n",
+               cif_isp10_v4l2_buf_type_string(queue->type), buf->index);
+
+       ret = videobuf_querybuf(queue, buf);
+       if (IS_ERR_VALUE(ret))
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "videobuf_querybuf failed with error %d\n", ret);
+
+       return ret;
+}
+
+static int cif_isp10_v4l2_s_ctrl(
+       struct file *file,
+       void *priv,
+       struct v4l2_control *vc)
+{
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       enum cif_isp10_cid id =
+               cif_isp10_v4l2_cid2cif_isp10_cid(vc->id);
+       int val = vc->value;
+
+       if (IS_ERR_VALUE(id))
+               return id;
+
+       switch (vc->id) {
+       case V4L2_CID_COLORFX:
+               val = cif_isp10_v4l2_colorfx2cif_isp10_ie(val);
+               break;
+       case V4L2_CID_FLASH_LED_MODE:
+               if (vc->value == V4L2_FLASH_LED_MODE_NONE)
+                       val = CIF_ISP10_FLASH_MODE_OFF;
+               else if (vc->value == V4L2_FLASH_LED_MODE_FLASH)
+                       val = CIF_ISP10_FLASH_MODE_FLASH;
+               else if (vc->value == V4L2_FLASH_LED_MODE_TORCH)
+                       val = CIF_ISP10_FLASH_MODE_TORCH;
+               else
+                       val = -EINVAL;
+               break;
+       default:
+               break;
+       }
+
+       return cif_isp10_s_ctrl(dev, id, val);
+}
+
+static int cif_isp10_v4l2_s_fmt(
+       struct file *file,
+       void *priv,
+       struct v4l2_format *f)
+{
+       int ret;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       struct cif_isp10_v4l2_node *node = to_node(fh);
+       struct cif_isp10_strm_fmt strm_fmt;
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "%s\n",
+               cif_isp10_v4l2_buf_type_string(queue->type));
+
+       if (node->owner && node->owner != fh)
+               return -EBUSY;
+
+       strm_fmt.frm_fmt.pix_fmt =
+               cif_isp10_v4l2_pix_fmt2cif_isp10_pix_fmt(
+                       f->fmt.pix.pixelformat, queue);
+       strm_fmt.frm_fmt.width = f->fmt.pix.width;
+       strm_fmt.frm_fmt.height = f->fmt.pix.height;
+/* strm_fmt.frm_fmt.quantization = f->fmt.pix.quantization; */
+       strm_fmt.frm_fmt.quantization = 0;
+       ret = cif_isp10_s_fmt(dev,
+               to_stream_id(file),
+               &strm_fmt,
+               f->fmt.pix.bytesperline);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(NULL,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+/* existence of this function is checked by V4L2 */
+static int cif_isp10_v4l2_g_fmt(
+       struct file *file,
+       void *priv,
+       struct v4l2_format *f)
+{
+       return -EFAULT;
+}
+
+static int cif_isp10_v4l2_s_input(
+       struct file *file,
+       void *priv,
+       unsigned int i)
+{
+       int ret;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "setting input to %d\n", i);
+
+       ret = cif_isp10_s_input(dev, i);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(NULL,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_v4l2_enum_framesizes(
+       struct file *file,
+       void *priv,
+       struct v4l2_frmsizeenum *fsize)
+{
+       /* THIS FUNCTION IS UNDER CONSTRUCTION */
+       int ret;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+
+       if (IS_ERR_OR_NULL(dev->img_src)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "input has not yet been selected, cannot enumerate formats\n");
+               ret = -ENODEV;
+               goto err;
+       }
+
+       return -EINVAL;
+err:
+       cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+       return ret;
+}
+
+/* fops **********************************************************************/
+
+const struct videobuf_queue_ops cif_isp10_qops = {
+       .buf_setup = cif_isp10_v4l2_buf_setup,
+       .buf_prepare = cif_isp10_v4l2_buf_prepare,
+       .buf_queue = cif_isp10_v4l2_buf_queue,
+       .buf_release = cif_isp10_v4l2_buf_release,
+};
+
+static int cif_isp10_v4l2_open(
+       struct file *file)
+{
+       int ret;
+       struct video_device *vdev = video_devdata(file);
+       struct cif_isp10_device *dev = video_get_drvdata(vdev);
+       struct cif_isp10_v4l2_fh *fh;
+       struct cif_isp10_v4l2_node *node;
+       enum v4l2_buf_type buf_type;
+       enum cif_isp10_stream_id stream_id;
+       struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev =
+               (struct cif_isp10_v4l2_device *)dev->nodes;
+
+       cif_isp10_pltfrm_pr_dbg(NULL,
+               "video device video%d.%d (%s)\n",
+               vdev->num, vdev->minor, vdev->name);
+
+       if (vdev->minor == cif_isp10_v4l2_dev->node[SP_DEV].vdev.minor) {
+               buf_type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+               stream_id = CIF_ISP10_STREAM_SP;
+       } else if (vdev->minor == cif_isp10_v4l2_dev->node[MP_DEV].vdev.minor) {
+               buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               stream_id = CIF_ISP10_STREAM_MP;
+       } else if (vdev->minor ==
+                               cif_isp10_v4l2_dev->node[DMA_DEV].vdev.minor) {
+               buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+               stream_id = CIF_ISP10_STREAM_DMA;
+       } else {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "invalid video device video%d.%d (%s)\n",
+                       vdev->num, vdev->minor, vdev->name);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (!fh) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "memory allocation failed\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+       fh->stream_id = stream_id;
+
+       file->private_data = &fh->fh;
+       v4l2_fh_init(&fh->fh, vdev);
+       v4l2_fh_add(&fh->fh);
+
+       node = to_node(fh);
+       if (++node->users > 1)
+               return 0;
+
+       /* First open of the device, so initialize everything */
+       node->owner = NULL;
+
+       videobuf_queue_dma_contig_init(
+               to_videobuf_queue(file),
+               &cif_isp10_qops,
+               dev->dev,
+               &dev->vbq_lock,
+               buf_type,
+               V4L2_FIELD_NONE,
+               sizeof(struct videobuf_buffer),
+               dev, NULL);
+
+       ret = cif_isp10_init(dev, to_stream_id(file));
+       if (IS_ERR_VALUE(ret)) {
+               v4l2_fh_del(&fh->fh);
+               v4l2_fh_exit(&fh->fh);
+               kfree(fh);
+               node->users--;
+               goto err;
+       }
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(NULL,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_v4l2_release(struct file *file)
+{
+       int ret = 0;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       struct cif_isp10_v4l2_node *node = to_node(fh);
+       enum cif_isp10_stream_id stream_id = to_stream_id(file);
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "%s\n",
+               cif_isp10_v4l2_buf_type_string(queue->type));
+
+       if (node->users) {
+               --node->users;
+       } else {
+               cif_isp10_pltfrm_pr_warn(dev->dev,
+                       "number of users for this device is already 0\n");
+               return 0;
+       }
+
+       if (!node->users) {
+               if (queue->streaming)
+                       if (IS_ERR_VALUE(cif_isp10_v4l2_do_streamoff(file)))
+                               cif_isp10_pltfrm_pr_warn(dev->dev,
+                                       "streamoff failed\n");
+
+               /* Last close, so uninitialize hardware */
+               ret = cif_isp10_release(dev, stream_id);
+       }
+
+       if (node->owner == fh)
+               node->owner = NULL;
+
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
+       kfree(fh);
+
+       if (IS_ERR_VALUE(ret))
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "failed with error %d\n", ret);
+       return ret;
+}
+
+static unsigned int cif_isp10_v4l2_poll(
+       struct file *file,
+       struct poll_table_struct *wait)
+{
+       struct cif_isp10_v4l2_fh *fh = to_fh(file);
+       int ret = 0;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       unsigned long req_events = poll_requested_events(wait);
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+               cif_isp10_v4l2_buf_type_string(queue->type));
+
+       if (v4l2_event_pending(&fh->fh))
+               ret = POLLPRI;
+       else if (req_events & POLLPRI)
+               poll_wait(file, &fh->fh.wait, wait);
+
+       if (!(req_events & (POLLIN | POLLOUT | POLLRDNORM)))
+               return ret;
+
+       ret |= videobuf_poll_stream(file, queue, wait);
+       if (ret & POLLERR) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "videobuf_poll_stream failed with error 0x%x\n", ret);
+       }
+       return ret;
+}
+
+/*
+ * VMA operations.
+ */
+static void cif_isp10_v4l2_vm_open(struct vm_area_struct *vma)
+{
+       struct cif_isp10_metadata_s *metadata =
+               (struct cif_isp10_metadata_s *)vma->vm_private_data;
+
+       metadata->vmas++;
+}
+
+static void cif_isp10_v4l2_vm_close(struct vm_area_struct *vma)
+{
+       struct cif_isp10_metadata_s *metadata =
+               (struct cif_isp10_metadata_s *)vma->vm_private_data;
+
+       metadata->vmas--;
+}
+
+static const struct vm_operations_struct cif_isp10_vm_ops = {
+       .open           = cif_isp10_v4l2_vm_open,
+       .close          = cif_isp10_v4l2_vm_close,
+};
+
+int cif_isp10_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       enum cif_isp10_stream_id strm = to_stream_id(file);
+       int retval;
+
+       retval = cif_isp10_mmap(dev, strm, vma);
+       if (retval < 0)
+               goto done;
+
+       vma->vm_ops          = &cif_isp10_vm_ops;
+       vma->vm_flags       |= VM_DONTEXPAND | VM_DONTDUMP;
+       cif_isp10_v4l2_vm_open(vma);
+
+done:
+       return retval;
+}
+
+const struct v4l2_file_operations cif_isp10_v4l2_fops = {
+       .open = cif_isp10_v4l2_open,
+       .unlocked_ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl32 = video_ioctl2,
+#endif
+       .release = cif_isp10_v4l2_release,
+       .poll = cif_isp10_v4l2_poll,
+       .mmap = cif_isp10_v4l2_mmap,
+};
+
+/*TBD: clean up code below this line******************************************/
+
+static int v4l2_querycap(struct file *file,
+                        void *priv, struct v4l2_capability *cap)
+{
+       int ret = 0;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct video_device *vdev = video_devdata(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       u32 stream_ids = to_stream_id(file);
+
+       strcpy(cap->driver, DRIVER_NAME);
+       strlcpy(cap->card, vdev->name, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+               "platform:" DRIVER_NAME "-%03i",
+               dev->dev_id);
+
+       if (stream_ids == CIF_ISP10_STREAM_SP)
+               cap->capabilities = V4L2_CAP_VIDEO_OVERLAY |
+                       V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+                       V4L2_CAP_STREAMING;
+       else if (stream_ids == CIF_ISP10_STREAM_MP)
+               cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+                       V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+                       V4L2_CAP_STREAMING;
+       else if (stream_ids == CIF_ISP10_STREAM_DMA)
+               cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE |
+                       V4L2_CAP_VIDEO_M2M;
+       cap->capabilities |= V4L2_CAP_DEVICE_CAPS;
+       cap->device_caps = V4L2_CAP_DEVICE_CAPS;
+       return ret;
+}
+
+static int cif_isp10_v4l2_subscribe_event(struct v4l2_fh *fh,
+                               const struct v4l2_event_subscription *sub)
+{
+       if (sub->type != V4L2_EVENT_FRAME_SYNC)
+               return -EINVAL;
+       return v4l2_event_subscribe(fh, sub, 16, NULL);
+}
+
+static int cif_isp10_v4l2_unsubscribe_event(struct v4l2_fh *fh,
+                               const struct v4l2_event_subscription *sub)
+{
+       return v4l2_event_unsubscribe(fh, sub);
+}
+
+static void cif_isp10_v4l2_event(
+       struct cif_isp10_device *dev,
+       __u32 frame_sequence)
+{
+       struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev =
+               (struct cif_isp10_v4l2_device *)dev->nodes;
+       struct v4l2_event ev;
+
+       memset(&ev, 0, sizeof(ev));
+       ev.type = V4L2_EVENT_FRAME_SYNC;
+       ev.u.frame_sync.frame_sequence = frame_sequence;
+       v4l2_event_queue(&cif_isp10_v4l2_dev->node[SP_DEV].vdev, &ev);
+}
+
+static void cif_isp10_v4l2_requeue_bufs(
+       struct cif_isp10_device *dev,
+       enum cif_isp10_stream_id stream_id)
+{
+       struct videobuf_buffer *buf;
+       struct videobuf_queue *q = NULL;
+       struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev =
+               (struct cif_isp10_v4l2_device *)dev->nodes;
+
+       if (stream_id == CIF_ISP10_STREAM_SP)
+               q = &cif_isp10_v4l2_dev->node[SP_DEV].buf_queue;
+       else if (stream_id == CIF_ISP10_STREAM_MP)
+               q = &cif_isp10_v4l2_dev->node[MP_DEV].buf_queue;
+       else if (stream_id == CIF_ISP10_STREAM_DMA)
+               q = &cif_isp10_v4l2_dev->node[DMA_DEV].buf_queue;
+       else
+               WARN_ON(1);
+
+       dev = to_cif_isp10_device(q);
+
+       list_for_each_entry(buf, &q->stream, stream) {
+               if (!IS_ERR_VALUE(cif_isp10_qbuf(
+                       to_cif_isp10_device(q), stream_id, buf))) {
+                       spin_lock(&dev->vbreq_lock);
+                       if ((buf->state == VIDEOBUF_QUEUED) ||
+                           (buf->state == VIDEOBUF_ACTIVE) ||
+                           (buf->state == VIDEOBUF_DONE))
+                               buf->state = VIDEOBUF_QUEUED;
+                       else
+                               cif_isp10_pltfrm_pr_err(NULL,
+                                       "ERR: buf->state is: %d\n",
+                                       buf->state);
+                       spin_unlock(&dev->vbreq_lock);
+               } else {
+                       cif_isp10_pltfrm_pr_err(NULL,
+                               "failed for buffer %d\n", buf->i);
+               }
+       }
+}
+
+static long v4l2_default_ioctl(struct file *file, void *fh,
+                              bool valid_prio, unsigned int cmd, void *arg)
+{
+       int ret = -EINVAL;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+
+       if (!arg) {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "NULL Pointer Violation from IOCTL arg:0x%lx\n",
+                       (unsigned long)arg);
+               return ret;
+       }
+
+       if (cmd == RK_VIDIOC_SENSOR_MODE_DATA) {
+               struct isp_supplemental_sensor_mode_data *p_mode_data =
+               (struct isp_supplemental_sensor_mode_data *)arg;
+
+               ret = (int)cif_isp10_img_src_ioctl(dev->img_src,
+                       RK_VIDIOC_SENSOR_MODE_DATA, p_mode_data);
+
+               if (ret < 0) {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "failed to get sensor mode data\n");
+                       return ret;
+               }
+
+               p_mode_data->isp_input_width =
+                       dev->config.isp_config.input->defrect.width;
+               p_mode_data->isp_input_height =
+                       dev->config.isp_config.input->defrect.height;
+               p_mode_data->isp_input_horizontal_start =
+                       dev->config.isp_config.input->defrect.left;
+               p_mode_data->isp_input_vertical_start =
+                       dev->config.isp_config.input->defrect.top;
+
+               p_mode_data->isp_output_width =
+                       dev->config.isp_config.output.width;
+               p_mode_data->isp_output_height =
+                       dev->config.isp_config.output.height;
+
+               if (ret < 0) {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "failed to get isp input info\n");
+                       return ret;
+               }
+       } else if (cmd == RK_VIDIOC_CAMERA_MODULEINFO) {
+               struct camera_module_info_s *p_camera_module =
+               (struct camera_module_info_s *)arg;
+
+               ret = (int)cif_isp10_img_src_ioctl(dev->img_src,
+                       RK_VIDIOC_CAMERA_MODULEINFO, p_camera_module);
+
+               if (ret < 0) {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "failed to get camera module information\n");
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static int v4l2_s_parm(
+       struct file *file,
+       void *priv,
+       struct v4l2_streamparm *a)
+{
+       return 0;
+}
+
+static int v4l2_enum_input(struct file *file, void *priv,
+                          struct v4l2_input *input)
+{
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       const char *inp_name;
+
+       if ((queue->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (queue->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "wrong buffer queue %d\n", queue->type);
+               return -EINVAL;
+       }
+
+       inp_name = cif_isp10_g_input_name(dev, input->index);
+       if (IS_ERR_OR_NULL(inp_name))
+               return -EINVAL;
+
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+       input->std = V4L2_STD_UNKNOWN;
+       strncpy(input->name, inp_name, sizeof(input->name)-1);
+
+       return 0;
+}
+
+/* ================================================================= */
+
+static int mainpath_g_ctrl(
+       struct file *file,
+       void *priv,
+       struct v4l2_control *vc)
+{
+       int ret = -EINVAL;
+
+       switch (vc->id) {
+       default:
+               return -EINVAL;
+       }
+       return ret;
+}
+
+#ifdef NOT_YET
+static int mainpath_try_fmt_cap(struct v4l2_format *f)
+{
+       int ifmt = 0;
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+
+       cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+       for (ifmt = 0; ifmt < get_cif_isp10_output_format_size(); ifmt++) {
+               if (pix->pixelformat ==
+               get_cif_isp10_output_format(ifmt)->fourcc)
+                       break;
+       }
+
+       if (ifmt == get_cif_isp10_output_format_size())
+               ifmt = 0;
+
+       pix->bytesperline = pix->width *
+               get_cif_isp10_output_format(ifmt)->depth / 8;
+
+       switch (pix->pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_YUV422P:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_YVU420:
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_YUV444:
+       case V4L2_PIX_FMT_NV24:
+       case V4L2_PIX_FMT_JPEG:
+               pix->colorspace = V4L2_COLORSPACE_JPEG;
+               break;
+       case V4L2_PIX_FMT_RGB32:
+       case V4L2_PIX_FMT_BGR32:
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_RGB565X:
+       case V4L2_PIX_FMT_SGRBG10:
+               pix->colorspace = V4L2_COLORSPACE_SRGB;
+               break;
+       default:
+               WARN_ON(1);
+               break;
+       }
+
+       return 0;
+}
+#endif
+
+static int v4l2_enum_fmt_cap(struct file *file, void *fh,
+                            struct v4l2_fmtdesc *f)
+{
+       int ret = 0;
+       int xgold_num_format = 0;
+
+       xgold_num_format = get_cif_isp10_output_format_desc_size();
+       if ((f->index >= xgold_num_format) ||
+       (get_cif_isp10_output_format_desc(f->index)->pixelformat == 0)) {
+               cif_isp10_pltfrm_pr_err(NULL, "index %d\n", f->index);
+               return -EINVAL;
+       }
+       strlcpy(f->description,
+               get_cif_isp10_output_format_desc(f->index)->description,
+                       sizeof(f->description));
+       f->pixelformat =
+       get_cif_isp10_output_format_desc(f->index)->pixelformat;
+       f->flags = get_cif_isp10_output_format_desc(f->index)->flags;
+
+       return ret;
+}
+
+static int v4l2_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *vc)
+{
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       enum cif_isp10_cid id =
+               cif_isp10_v4l2_cid2cif_isp10_cid(vc->id);
+
+       return cif_isp10_img_src_g_ctrl(dev->img_src,
+               id, &vc->value);
+}
+
+static int v4l2_s_ext_ctrls(struct file *file, void *priv,
+       struct v4l2_ext_controls *vc_ext)
+{
+       struct cif_isp10_img_src_ctrl *ctrls;
+       struct cif_isp10_img_src_ext_ctrl *ctrl;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       int ret = -EINVAL;
+       unsigned int i;
+
+       /* The only use-case is gain and exposure to sensor. Thus no check if
+        * this shall go to img_src or not as of now.
+        */
+       cif_isp10_pltfrm_pr_dbg(dev->dev, "count %d\n",
+               vc_ext->count);
+
+       if (vc_ext->count == 0)
+               return ret;
+
+       ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL);
+       if (!ctrl)
+               return -ENOMEM;
+
+       ctrls = kmalloc(vc_ext->count *
+               sizeof(struct cif_isp10_img_src_ctrl), GFP_KERNEL);
+       if (!ctrls) {
+               kfree(ctrl);
+               return -ENOMEM;
+       }
+
+       ctrl->cnt = vc_ext->count;
+       /*current kernel version don't define
+        *this member for struct v4l2_ext_control.
+        */
+       /*ctrl->class = vc_ext->ctrl_class;*/
+       ctrl->ctrls = ctrls;
+
+       for (i = 0; i < vc_ext->count; i++) {
+               ctrls[i].id = vc_ext->controls[i].id;
+               ctrls[i].val = vc_ext->controls[i].value;
+       }
+
+       ret = cif_isp10_s_exp(dev, ctrl);
+       return ret;
+}
+
+int cif_isp10_v4l2_cropcap(
+       struct file *file,
+       void *fh,
+       struct v4l2_cropcap *a)
+{
+       int ret = 0;
+       struct videobuf_queue *queue = to_videobuf_queue(file);
+       struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+       u32 target_width, target_height;
+       u32 h_offs, v_offs;
+
+       if ((dev->config.input_sel == CIF_ISP10_INP_DMA) ||
+               (dev->config.input_sel == CIF_ISP10_INP_DMA_IE)) {
+               /* calculate cropping for aspect ratio */
+               ret = cif_isp10_calc_isp_cropping(dev,
+                       &dev->isp_dev.input_width, &dev->isp_dev.input_height,
+                       &h_offs, &v_offs);
+
+               /* Get output size */
+               ret = cif_isp10_get_target_frm_size(dev,
+                       &target_width, &target_height);
+               if (ret < 0) {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "failed to get target frame size\n");
+                       return ret;
+               }
+
+               cif_isp10_pltfrm_pr_dbg(dev->dev,
+                       "CIF_IN_W=%d, CIF_IN_H=%d, ISP_IN_W=%d, ISP_IN_H=%d, target_width=%d, target_height=%d\n",
+                       dev->config.isp_config.input->width,
+                       dev->config.isp_config.input->height,
+                       dev->isp_dev.input_width,
+                       dev->isp_dev.input_height,
+                       target_width,
+                       target_height);
+
+               /* This is the input to Bayer after input formatter cropping */
+               a->defrect.top = 0;
+               a->defrect.left = 0;
+               a->defrect.width = dev->isp_dev.input_width;
+               a->defrect.height = dev->isp_dev.input_height;
+               /* This is the minimum cropping window for the IS module */
+               a->bounds.width = 2;
+               a->bounds.height = 2;
+               a->bounds.top = (a->defrect.height - a->bounds.height) / 2;
+               a->bounds.left = (a->defrect.width - a->bounds.width) / 2;
+
+               a->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+       } else if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+               /* calculate cropping for aspect ratio */
+               ret = cif_isp10_calc_isp_cropping(dev,
+                       &dev->isp_dev.input_width, &dev->isp_dev.input_height,
+                       &h_offs, &v_offs);
+
+               /* Get output size */
+               ret = cif_isp10_get_target_frm_size(dev,
+                       &target_width, &target_height);
+               if (ret < 0) {
+                       cif_isp10_pltfrm_pr_err(dev->dev,
+                               "failed to get target frame size\n");
+                       return ret;
+               }
+
+               /* This is the input to Bayer after input formatter cropping */
+               a->defrect.top =
+                       v_offs + dev->config.isp_config.input->defrect.top;
+               a->defrect.left =
+                       h_offs + dev->config.isp_config.input->defrect.left;
+               a->defrect.width = dev->isp_dev.input_width;
+               a->defrect.height = dev->isp_dev.input_height;
+
+               a->bounds.top = 0;
+               a->bounds.left = 0;
+               a->bounds.width = dev->config.isp_config.input->width;
+               a->bounds.height = dev->config.isp_config.input->height;
+               a->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+       } else {
+               cif_isp10_pltfrm_pr_err(dev->dev,
+                       "invalid input\n");
+       }
+
+       cif_isp10_pltfrm_pr_dbg(dev->dev,
+               "v4l2_cropcap: defrect(%d,%d,%d,%d) bounds(%d,%d,%d,%d)\n",
+               a->defrect.width,
+               a->defrect.height,
+               a->defrect.left,
+               a->defrect.top,
+               a->bounds.width,
+               a->bounds.height,
+               a->bounds.left,
+               a->bounds.top);
+
+       return ret;
+}
+
+int cif_isp10_v4l2_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+       return 0;
+}
+
+/*
+ * This is a write only function, so the upper layer
+ * will ignore the changes to 'a'. So don't use 'a' to pass
+ * the actual cropping parameters, the upper layer
+ * should call g_crop to get the actual window.
+ */
+int cif_isp10_v4l2_s_crop(
+       struct file *file,
+       void *fh,
+       const struct v4l2_crop *a)
+{
+       return 0;
+}
+
+const struct v4l2_ioctl_ops cif_isp10_v4l2_sp_ioctlops = {
+       .vidioc_reqbufs = cif_isp10_v4l2_reqbufs,
+       .vidioc_querybuf = cif_isp10_v4l2_querybuf,
+       .vidioc_qbuf = cif_isp10_v4l2_qbuf,
+       .vidioc_dqbuf = cif_isp10_v4l2_dqbuf,
+       .vidioc_streamon = cif_isp10_v4l2_streamon,
+       .vidioc_streamoff = cif_isp10_v4l2_streamoff,
+       .vidioc_s_input = cif_isp10_v4l2_s_input,
+       .vidioc_enum_input = v4l2_enum_input,
+       .vidioc_g_ctrl = v4l2_g_ctrl,
+       .vidioc_s_ctrl = cif_isp10_v4l2_s_ctrl,
+       .vidioc_s_fmt_vid_overlay = cif_isp10_v4l2_s_fmt,
+       .vidioc_g_fmt_vid_overlay = cif_isp10_v4l2_g_fmt,
+       .vidioc_s_ext_ctrls = v4l2_s_ext_ctrls,
+       .vidioc_querycap = v4l2_querycap,
+       .vidioc_cropcap = cif_isp10_v4l2_cropcap,
+       .vidioc_s_crop = cif_isp10_v4l2_s_crop,
+       .vidioc_g_crop = cif_isp10_v4l2_g_crop,
+       .vidioc_subscribe_event = cif_isp10_v4l2_subscribe_event,
+       .vidioc_unsubscribe_event = cif_isp10_v4l2_unsubscribe_event,
+       .vidioc_default = v4l2_default_ioctl,
+};
+
+const struct v4l2_ioctl_ops cif_isp10_v4l2_mp_ioctlops = {
+       .vidioc_reqbufs = cif_isp10_v4l2_reqbufs,
+       .vidioc_querybuf = cif_isp10_v4l2_querybuf,
+       .vidioc_qbuf = cif_isp10_v4l2_qbuf,
+       .vidioc_dqbuf = cif_isp10_v4l2_dqbuf,
+       .vidioc_streamon = cif_isp10_v4l2_streamon,
+       .vidioc_streamoff = cif_isp10_v4l2_streamoff,
+       .vidioc_s_input = cif_isp10_v4l2_s_input,
+       .vidioc_enum_input = v4l2_enum_input,
+       .vidioc_g_ctrl = mainpath_g_ctrl,
+       .vidioc_s_ctrl = cif_isp10_v4l2_s_ctrl,
+       .vidioc_s_fmt_vid_cap = cif_isp10_v4l2_s_fmt,
+       .vidioc_g_fmt_vid_cap = cif_isp10_v4l2_g_fmt,
+       .vidioc_enum_fmt_vid_cap = v4l2_enum_fmt_cap,
+       .vidioc_enum_framesizes = cif_isp10_v4l2_enum_framesizes,
+       .vidioc_s_parm = v4l2_s_parm,
+       .vidioc_querycap = v4l2_querycap,
+       .vidioc_cropcap = cif_isp10_v4l2_cropcap,
+       .vidioc_s_crop = cif_isp10_v4l2_s_crop,
+       .vidioc_g_crop = cif_isp10_v4l2_g_crop,
+       .vidioc_default = v4l2_default_ioctl,
+};
+
+const struct v4l2_ioctl_ops cif_isp10_v4l2_dma_ioctlops = {
+       .vidioc_reqbufs = cif_isp10_v4l2_reqbufs,
+       .vidioc_querybuf = cif_isp10_v4l2_querybuf,
+       .vidioc_qbuf = cif_isp10_v4l2_qbuf,
+       .vidioc_dqbuf = cif_isp10_v4l2_dqbuf,
+       .vidioc_streamon = cif_isp10_v4l2_streamon,
+       .vidioc_streamoff = cif_isp10_v4l2_streamoff,
+       .vidioc_s_fmt_vid_out = cif_isp10_v4l2_s_fmt,
+       .vidioc_g_fmt_vid_out = cif_isp10_v4l2_g_fmt,
+       .vidioc_cropcap = cif_isp10_v4l2_cropcap,
+       .vidioc_s_crop = cif_isp10_v4l2_s_crop,
+       .vidioc_g_crop = cif_isp10_v4l2_g_crop,
+};
+
+static struct pltfrm_soc_cfg rk3288_cfg = {
+       .name = CIF_ISP10_SOC_RK3288,
+       .soc_cfg = pltfrm_rk3288_cfg,
+};
+
+static struct pltfrm_soc_cfg rk3399_cfg = {
+       .name = CIF_ISP10_SOC_RK3399,
+       .soc_cfg = pltfrm_rk3399_cfg,
+};
+
+static const struct of_device_id cif_isp10_v4l2_of_match[] = {
+       {.compatible = "rockchip,rk3288-cif-isp",
+       .data = (void *)&rk3288_cfg},
+       {.compatible = "rockchip,rk3399-cif-isp",
+       .data = (void *)&rk3399_cfg},
+       {},
+};
+
+static unsigned int cif_isp10_v4l2_dev_cnt;
+static int cif_isp10_v4l2_drv_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       struct device_node *node = pdev->dev.of_node;
+       struct cif_isp10_device *dev = NULL;
+       struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev;
+       int ret;
+
+       cif_isp10_pltfrm_pr_info(NULL, "probing...\n");
+
+       cif_isp10_v4l2_dev = devm_kzalloc(
+                               &pdev->dev,
+                               sizeof(struct cif_isp10_v4l2_device),
+                               GFP_KERNEL);
+       if (IS_ERR_OR_NULL(cif_isp10_v4l2_dev)) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       match = of_match_node(cif_isp10_v4l2_of_match, node);
+       dev = cif_isp10_create(&pdev->dev,
+               cif_isp10_v4l2_event,
+               cif_isp10_v4l2_requeue_bufs,
+               (struct pltfrm_soc_cfg *)match->data);
+       if (IS_ERR_OR_NULL(dev)) {
+               ret = -ENODEV;
+               goto err;
+       }
+
+       dev->dev_id = cif_isp10_v4l2_dev_cnt;
+       dev->isp_dev.dev_id = &dev->dev_id;
+       dev->nodes = (void *)cif_isp10_v4l2_dev;
+       spin_lock_init(&dev->vbq_lock);
+       spin_lock_init(&dev->vbreq_lock);
+       spin_lock_init(&iowrite32_verify_lock);
+
+       ret = v4l2_device_register(dev->dev, &dev->v4l2_dev);
+       if (IS_ERR_VALUE(ret)) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "V4L2 device registration failed\n");
+               goto err;
+       }
+
+       ret = cif_isp10_v4l2_register_video_device(
+               dev,
+               &cif_isp10_v4l2_dev->node[SP_DEV].vdev,
+               SP_VDEV_NAME,
+               V4L2_CAP_VIDEO_OVERLAY,
+               CIF_ISP10_V4L2_SP_DEV_MAJOR,
+               &cif_isp10_v4l2_fops,
+               &cif_isp10_v4l2_sp_ioctlops);
+       if (ret)
+               goto err;
+
+       ret = register_cifisp_device(&dev->isp_dev,
+               &cif_isp10_v4l2_dev->node[ISP_DEV].vdev,
+               &dev->v4l2_dev,
+               dev->config.base_addr);
+       if (ret)
+               goto err;
+
+       ret = cif_isp10_v4l2_register_video_device(
+               dev,
+               &cif_isp10_v4l2_dev->node[MP_DEV].vdev,
+               MP_VDEV_NAME,
+               V4L2_CAP_VIDEO_CAPTURE,
+               CIF_ISP10_V4L2_MP_DEV_MAJOR,
+               &cif_isp10_v4l2_fops,
+               &cif_isp10_v4l2_mp_ioctlops);
+       if (ret)
+               goto err;
+
+       ret = cif_isp10_v4l2_register_video_device(
+               dev,
+               &cif_isp10_v4l2_dev->node[DMA_DEV].vdev,
+               DMA_VDEV_NAME,
+               V4L2_CAP_VIDEO_OUTPUT,
+               CIF_ISP10_V4L2_DMA_DEV_MAJOR,
+               &cif_isp10_v4l2_fops,
+               &cif_isp10_v4l2_dma_ioctlops);
+       if (ret)
+               goto err;
+
+       pm_runtime_enable(&pdev->dev);
+
+       cif_isp10_v4l2_dev_cnt++;
+       return 0;
+err:
+       cif_isp10_destroy(dev);
+       return ret;
+}
+
+/* ======================================================================== */
+
+static int cif_isp10_v4l2_drv_remove(struct platform_device *pdev)
+{
+       struct cif_isp10_device *cif_isp10_dev =
+               (struct cif_isp10_device *)platform_get_drvdata(pdev);
+       struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev =
+               (struct cif_isp10_v4l2_device *)cif_isp10_dev->nodes;
+
+       if (IS_ERR_VALUE(cif_isp10_release(cif_isp10_dev,
+               CIF_ISP10_ALL_STREAMS)))
+               cif_isp10_pltfrm_pr_warn(cif_isp10_dev->dev,
+                       "CIF power off failed\n");
+
+       video_unregister_device(&cif_isp10_v4l2_dev->node[SP_DEV].vdev);
+       video_unregister_device(&cif_isp10_v4l2_dev->node[MP_DEV].vdev);
+       video_unregister_device(&cif_isp10_v4l2_dev->node[DMA_DEV].vdev);
+       unregister_cifisp_device(&cif_isp10_v4l2_dev->node[ISP_DEV].vdev);
+       v4l2_device_unregister(&cif_isp10_dev->v4l2_dev);
+       cif_isp10_pltfrm_dev_release(&pdev->dev);
+       cif_isp10_destroy(cif_isp10_dev);
+
+       cif_isp10_v4l2_dev_cnt--;
+       return 0;
+}
+
+static int cif_isp10_v4l2_drv_suspend(struct platform_device *pdev,
+       pm_message_t state)
+{
+       int ret = 0;
+       struct cif_isp10_device *cif_isp10_dev =
+               (struct cif_isp10_device *)platform_get_drvdata(pdev);
+
+       cif_isp10_pltfrm_pr_dbg(cif_isp10_dev->dev, "\n");
+
+       ret = cif_isp10_suspend(cif_isp10_dev);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       cif_isp10_pltfrm_pinctrl_set_state(&pdev->dev,
+               CIF_ISP10_PINCTRL_STATE_SLEEP);
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(cif_isp10_dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_v4l2_drv_resume(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct cif_isp10_device *cif_isp10_dev =
+               (struct cif_isp10_device *)platform_get_drvdata(pdev);
+
+       cif_isp10_pltfrm_pr_dbg(cif_isp10_dev->dev, "\n");
+
+       if (!cif_isp10_dev->img_src) {
+               cif_isp10_pltfrm_pr_err(
+                       cif_isp10_dev->dev,
+                       "cif_isp10_dev img_src is null!\n");
+               goto err;
+       }
+
+       ret = cif_isp10_resume(cif_isp10_dev);
+       if (IS_ERR_VALUE(ret))
+               goto err;
+
+       cif_isp10_pltfrm_pinctrl_set_state(&pdev->dev,
+               CIF_ISP10_PINCTRL_STATE_DEFAULT);
+
+       return 0;
+err:
+       cif_isp10_pltfrm_pr_err(cif_isp10_dev->dev,
+               "failed with error %d\n", ret);
+       return ret;
+}
+
+static int cif_isp10_runtime_suspend(struct device *dev)
+{
+       cif_isp10_pltfrm_pr_dbg(dev, "\n");
+       return cif_isp10_pltfrm_pm_set_state(dev, CIF_ISP10_PM_STATE_SUSPENDED);
+}
+
+static int cif_isp10_runtime_resume(struct device *dev)
+{
+       cif_isp10_pltfrm_pr_dbg(dev, "\n");
+       return cif_isp10_pltfrm_pm_set_state(dev, CIF_ISP10_PM_STATE_SW_STNDBY);
+}
+
+static const struct dev_pm_ops cif_isp10_dev_pm_ops = {
+       SET_RUNTIME_PM_OPS(cif_isp10_runtime_suspend,
+                          cif_isp10_runtime_resume, NULL)
+};
+
+static struct platform_driver cif_isp10_v4l2_plat_drv = {
+       .driver = {
+               .name = DRIVER_NAME,
+               .of_match_table = of_match_ptr(cif_isp10_v4l2_of_match),
+               .pm = &cif_isp10_dev_pm_ops,
+                  },
+       .probe = cif_isp10_v4l2_drv_probe,
+       .remove = cif_isp10_v4l2_drv_remove,
+       .suspend = cif_isp10_v4l2_drv_suspend,
+       .resume = cif_isp10_v4l2_drv_resume,
+};
+
+/* ======================================================================== */
+static int cif_isp10_v4l2_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&cif_isp10_v4l2_plat_drv);
+       if (ret) {
+               cif_isp10_pltfrm_pr_err(NULL,
+                       "cannot register platform driver, failed with %d\n",
+                       ret);
+               return -ENODEV;
+       }
+
+       return ret;
+}
+
+/* ======================================================================== */
+static void __exit cif_isp10_v4l2_exit(void)
+{
+       platform_driver_unregister(&cif_isp10_v4l2_plat_drv);
+}
+
+device_initcall_sync(cif_isp10_v4l2_init);
+module_exit(cif_isp10_v4l2_exit);
+
+MODULE_DESCRIPTION("V4L2 interface for CIF ISP10 driver");
+MODULE_AUTHOR("George");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_version.h b/drivers/media/platform/rk-isp10/cif_isp10_version.h
new file mode 100644 (file)
index 0000000..4a01ec3
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+ #ifndef _CIF_ISP10_RK_VERSION_H_
+#define _CIF_ISP10_RK_VERSION_H_
+#include <linux/version.h>
+
+/*
+ *       CIF DRIVER VERSION NOTE
+ *
+ *v0.1.0:
+ *1. New mi register update mode is invalidate in raw/jpeg for rk1108,
+ * All path used old mode for rk1108;
+ *v0.1.1:
+ *1. Modify CIF stop sequence for fix isp bus may dead when switch isp:
+ *Original stop sequence: Stop ISP(mipi) -> Stop ISP(isp) ->wait for ISP
+ *isp off -> Stop ISP(mi)
+ *Current stop sequence: ISP(mi) stop in mi frame end -> Stop ISP(mipi)
+ *-> Stop ISP(isp) ->wait for ISP isp off;
+ * Current stop sequence is only match sensor stream v-blanking >= 1.5ms;
+ *
+ *v0.1.2:
+ *1. Disable CIF_MIPI_ERR_DPHY interrupt here temporary for
+ *isp bus may be dead when switch isp;
+ *2. Cancel hw restart isp operation in mipi isr, only notice error log;
+ *
+ *v0.1.3:
+ *1. fix camerahal query exp info failed from cifisp_stat_buffer, because
+ *wake_up buffer before cif_isp11_sensor_mode_data_sync;
+ *
+ *v0.1.4:
+ *1. Disable DPHY errctrl interrupt, because this dphy erctrl signal
+ *is assert and until the next changes in line state. This time is may
+ *be too long and cpu is hold in this interrupt. Enable DPHY errctrl
+ *interrupt again, if mipi have receive the whole frame without any error.
+ *2. Modify mipi_dphy_cfg follow vendor recommended process in
+ *document.
+ *3. Select the limit dphy setting if sensor mipi datarate is overflow,
+ *and print warning information to user.
+ *
+ *v0.1.5:
+ *Exposure list must be queue operation, not stack. list_add switch to
+ *list_add_tail in cif_isp11_s_exp;
+ *
+ *v0.1.6:
+ *Add isp output size in struct isp_supplemental_sensor_mode_data.
+ *
+ */
+
+#define CONFIG_CIFISP10_DRIVER_VERSION KERNEL_VERSION(0, 1, 6)
+
+#endif
diff --git a/include/linux/platform_data/rk_isp10_platform.h b/include/linux/platform_data/rk_isp10_platform.h
new file mode 100644 (file)
index 0000000..8974945
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+#ifndef _CIF_ISP10_PLATFORM_H
+#define _CIF_ISP10_PLATFORM_H
+#include <linux/videodev2.h>
+
+#define CIF_ISP10_SOC_RK3288   "rk3288"
+#define CIF_ISP10_SOC_RK3368   "rk3368"
+#define CIF_ISP10_SOC_RK3399   "rk3399"
+
+#define DRIVER_NAME "rkisp10"
+#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"
+
+enum pltfrm_cam_signal_polarity {
+       PLTFRM_CAM_SIGNAL_HIGH_LEVEL = 0,
+       PLTFRM_CAM_SIGNAL_LOW_LEVEL = 1,
+};
+
+enum pltfrm_cam_sample_type {
+       PLTFRM_CAM_SDR_NEG_EDG = 0x10000001,
+       PLTFRM_CAM_SDR_POS_EDG = 0x10000002,
+       PLTFRM_CAM_DDR         = 0x20000000
+};
+
+enum pltfrm_cam_itf_type {
+       PLTFRM_CAM_ITF_MIPI     = 0x10000000,
+       PLTFRM_CAM_ITF_BT601_8  = 0x20000071,
+       PLTFRM_CAM_ITF_BT656_8  = 0x20000072,
+       PLTFRM_CAM_ITF_BT601_10 = 0x20000091,
+       PLTFRM_CAM_ITF_BT656_10 = 0x20000092,
+       PLTFRM_CAM_ITF_BT601_12 = 0x200000B1,
+       PLTFRM_CAM_ITF_BT656_12 = 0x200000B2,
+       PLTFRM_CAM_ITF_BT601_16 = 0x200000F1,
+       PLTFRM_CAM_ITF_BT656_16 = 0x200000F2
+};
+
+#define PLTFRM_CAM_ITF_MAIN_MASK   0xf0000000
+#define PLTFRM_CAM_ITF_SUB_MASK    0x0000000f
+#define PLTFRM_CAM_ITF_DVP_BW_MASK 0x000000f0
+
+#define PLTFRM_CAM_ITF_IS_MIPI(a)    \
+               (((a) & PLTFRM_CAM_ITF_MAIN_MASK) == 0x10000000)
+#define PLTFRM_CAM_ITF_IS_DVP(a)    \
+               (((a) & PLTFRM_CAM_ITF_MAIN_MASK) == 0x20000000)
+#define PLTFRM_CAM_ITF_IS_BT656(a)     (PLTFRM_CAM_ITF_IS_DVP(a) &&\
+               (((a) & PLTFRM_CAM_ITF_SUB_MASK) == 0x02))
+#define PLTFRM_CAM_ITF_IS_BT601(a)     (PLTFRM_CAM_ITF_IS_DVP(a) &&\
+               (((a) & PLTFRM_CAM_ITF_SUB_MASK) == 0x01))
+#define PLTFRM_CAM_ITF_DVP_BW(a)    \
+               ((((a) & PLTFRM_CAM_ITF_DVP_BW_MASK) >> 4) + 1)
+
+struct pltfrm_cam_mipi_config {
+       u32 dphy_index;
+       u32 vc;
+       u32 nb_lanes;
+       u32 bit_rate;
+};
+
+struct pltfrm_cam_dvp_config {
+       enum pltfrm_cam_signal_polarity vsync;
+       enum pltfrm_cam_signal_polarity hsync;
+       enum pltfrm_cam_sample_type pclk;
+};
+
+struct pltfrm_cam_itf {
+       enum pltfrm_cam_itf_type type;
+
+       union {
+               struct pltfrm_cam_mipi_config mipi;
+               struct pltfrm_cam_dvp_config dvp;
+       } cfg;
+       unsigned int mclk_hz;
+};
+
+#define PLTFRM_CAM_ITF_MIPI_CFG(v, nb, br, mk)\
+       .itf_cfg = {\
+               .type =  PLTFRM_CAM_ITF_MIPI,\
+                       .cfg = {\
+                               .mipi = {\
+                                       .dphy_index = 0,\
+                                       .vc = v,\
+                                       .nb_lanes = nb,\
+                                       .bit_rate = br,\
+                               } \
+                       },\
+               .mclk_hz = mk\
+       }
+#define PLTFRM_CAM_ITF_DVP_CFG(ty, vs, hs, ck, mk)\
+       .itf_cfg = {\
+               .type =  ty,\
+               .cfg = {\
+                       .dvp = {\
+                               .vsync = vs,\
+                               .hsync = hs,\
+                               .pclk = ck,\
+                       } \
+               },\
+               .mclk_hz = mk\
+       }
+
+#define PLTFRM_CIFCAM_IOCTL_INTERNAL_BASE    0x00
+#define PLTFRM_CIFCAM_G_ITF_CFG    \
+                               (PLTFRM_CIFCAM_IOCTL_INTERNAL_BASE + 1)
+#define PLTFRM_CIFCAM_G_DEFRECT    \
+                               (PLTFRM_CIFCAM_IOCTL_INTERNAL_BASE + 2)
+#define PLTFRM_CIFCAM_ATTACH    \
+                               (PLTFRM_CIFCAM_IOCTL_INTERNAL_BASE + 3)
+
+struct pltfrm_cam_defrect {
+       unsigned int width;
+       unsigned int height;
+       struct v4l2_rect defrect;
+};
+
+enum pltfrm_soc_cfg_cmd {
+       PLTFRM_MCLK_CFG = 0,
+       PLTFRM_MIPI_DPHY_CFG,
+
+       PLTFRM_CLKEN,
+       PLTFRM_CLKDIS,
+       PLTFRM_CLKRST,
+
+       PLTFRM_SOC_INIT
+};
+
+enum pltfrm_soc_io_voltage {
+       PLTFRM_IO_1V8 = 0,
+       PLTFRM_IO_3V3 = 1
+};
+
+enum pltfrm_soc_drv_strength {
+       PLTFRM_DRV_STRENGTH_0 = 0,
+       PLTFRM_DRV_STRENGTH_1 = 1,
+       PLTFRM_DRV_STRENGTH_2 = 2,
+       PLTFRM_DRV_STRENGTH_3 = 3
+
+};
+
+struct pltfrm_soc_init_para {
+       struct platform_device *pdev;
+       void __iomem *isp_base;
+};
+
+struct pltfrm_soc_mclk_para {
+       enum pltfrm_soc_io_voltage io_voltage;
+       enum pltfrm_soc_drv_strength drv_strength;
+};
+
+struct pltfrm_soc_cfg_para {
+       enum pltfrm_soc_cfg_cmd cmd;
+       void *cfg_para;
+};
+
+struct pltfrm_soc_cfg {
+       char name[32];
+       int (*soc_cfg)(struct pltfrm_soc_cfg_para *cfg);
+};
+
+int pltfrm_rk3288_cfg(
+               struct pltfrm_soc_cfg_para *cfg);
+int pltfrm_rk3399_cfg(
+               struct pltfrm_soc_cfg_para *cfg);
+
+#endif
diff --git a/include/linux/platform_data/rk_isp10_platform_camera_module.h b/include/linux/platform_data/rk_isp10_platform_camera_module.h
new file mode 100644 (file)
index 0000000..276d218
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef PLATFORM_CAMERA_MODULE_H
+#define PLATFORM_CAMERA_MODULE_H
+#include <linux/videodev2.h>
+
+#define PLTFRM_CAMERA_MODULE_REG_TYPE_DATA 0
+#define PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT 1
+
+extern const char *PLTFRM_CAMERA_MODULE_PIN_PD;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_PWR;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_FLASH;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_TORCH;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_RESET;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_VSYNC;
+
+enum pltfrm_camera_module_pin_state {
+       PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE = 0,
+       PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE   = 1
+};
+
+struct pltfrm_camera_module_reg {
+       u32 flag;
+       u16 reg;
+       u16 val;
+};
+
+struct pltfrm_camera_module_reg_table {
+       u32 reg_table_num_entries;
+       struct pltfrm_camera_module_reg *reg_table;
+};
+
+int pltfrm_camera_module_set_pm_state(
+       struct v4l2_subdev *sd,
+       int on);
+
+int pltfrm_camera_module_set_pin_state(
+       struct v4l2_subdev *sd,
+       const char *pin,
+       enum pltfrm_camera_module_pin_state state);
+
+int pltfrm_camera_module_get_pin_state(
+       struct v4l2_subdev *sd,
+       const char *pin);
+
+int pltfrm_camera_module_s_power(
+       struct v4l2_subdev *sd,
+       int on);
+
+int pltfrm_camera_module_patch_config(
+       struct v4l2_subdev *sd,
+       struct v4l2_mbus_framefmt *frm_fmt,
+       struct v4l2_subdev_frame_interval *frm_intrvl);
+
+struct v4l2_subdev *pltfrm_camera_module_get_af_ctrl(
+       struct v4l2_subdev *sd);
+
+struct v4l2_subdev *pltfrm_camera_module_get_fl_ctrl(
+       struct v4l2_subdev *sd);
+
+char *pltfrm_camera_module_get_flash_driver_name(
+       struct v4l2_subdev *sd);
+
+int pltfrm_camera_module_init(
+       struct v4l2_subdev *sd,
+       void **pldata);
+
+void pltfrm_camera_module_release(
+       struct v4l2_subdev *sd);
+
+int pltfrm_camera_module_read_reg(struct v4l2_subdev *sd,
+       u16 data_length,
+       u16 reg,
+       u32 *val);
+
+int pltfrm_superpix_camera_module_read_reg(struct v4l2_subdev *sd,
+       u16 data_length,
+       u8 reg,
+       u8 *val);
+
+int pltfrm_camera_module_write_reg(struct v4l2_subdev *sd,
+       u16 reg, u8 val);
+
+int pltfrm_camera_module_write_reglist(
+       struct v4l2_subdev *sd,
+       const struct pltfrm_camera_module_reg reglist[],
+       int len);
+
+long pltfrm_camera_module_ioctl(struct v4l2_subdev *sd,
+       unsigned int cmd,
+       void *arg);
+
+const char *pltfrm_dev_string(struct v4l2_subdev *sd);
+
+int pltfrm_camera_module_get_flip_mirror(
+       struct v4l2_subdev *sd);
+
+#define pltfrm_camera_module_pr_debug(dev, fmt, arg...) \
+       pr_debug("%s.%s: " fmt, \
+               pltfrm_dev_string(dev), __func__, ## arg)
+#define pltfrm_camera_module_pr_info(dev, fmt, arg...) \
+       pr_info("%s.%s: " fmt, \
+               pltfrm_dev_string(dev), __func__, ## arg)
+#define pltfrm_camera_module_pr_warn(dev, fmt, arg...) \
+       pr_warn("%s.%s WARN: " fmt, \
+               pltfrm_dev_string(dev), __func__, ## arg)
+#define pltfrm_camera_module_pr_err(dev, fmt, arg...) \
+       pr_err("%s.%s(%d) ERR: " fmt, \
+               pltfrm_dev_string(dev), __func__, __LINE__, \
+               ## arg)
+
+#endif
diff --git a/include/media/rk-isp10-config.h b/include/media/rk-isp10-config.h
new file mode 100644 (file)
index 0000000..6cdad63
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+#ifndef _RK_ISP11_CONFIG_H
+#define _RK_ISP11_CONFIG_H
+
+#include <media/v4l2-config_rockchip.h>
+
+#define CIFISP_MODULE_DPCC              BIT(0)
+#define CIFISP_MODULE_BLS               BIT(1)
+#define CIFISP_MODULE_SDG               BIT(2)
+#define CIFISP_MODULE_HST               BIT(3)
+#define CIFISP_MODULE_LSC               BIT(4)
+#define CIFISP_MODULE_AWB_GAIN          BIT(5)
+#define CIFISP_MODULE_FLT               BIT(6)
+#define CIFISP_MODULE_BDM               BIT(7)
+#define CIFISP_MODULE_CTK               BIT(8)
+#define CIFISP_MODULE_GOC               BIT(9)
+#define CIFISP_MODULE_CPROC             BIT(10)
+#define CIFISP_MODULE_AFC               BIT(11)
+#define CIFISP_MODULE_AWB               BIT(12)
+#define CIFISP_MODULE_IE                BIT(13)
+#define CIFISP_MODULE_AEC               BIT(14)
+#define CIFISP_MODULE_WDR               BIT(15)
+#define CIFISP_MODULE_DPF               BIT(16)
+#define CIFISP_MODULE_DPF_STRENGTH      BIT(17)
+
+#define CIFISP_CTK_COEFF_MAX            0x100
+#define CIFISP_CTK_OFFSET_MAX           0x800
+
+#define CIFISP_AE_MEAN_MAX              25
+#define CIFISP_HIST_BIN_N_MAX           16
+#define CIFISP_AFM_MAX_WINDOWS          3
+#define CIFISP_DEGAMMA_CURVE_SIZE       17
+
+#define CIFISP_BDM_MAX_TH               0xFF
+
+/* maximum value for horizontal start address */
+#define CIFISP_BLS_START_H_MAX             (0x00000FFF)
+/* maximum value for horizontal stop address */
+#define CIFISP_BLS_STOP_H_MAX              (0x00000FFF)
+/* maximum value for vertical start address */
+#define CIFISP_BLS_START_V_MAX             (0x00000FFF)
+/* maximum value for vertical stop address */
+#define CIFISP_BLS_STOP_V_MAX              (0x00000FFF)
+/* maximum is 2^18 = 262144*/
+#define CIFISP_BLS_SAMPLES_MAX             (0x00000012)
+/* maximum value for fixed black level */
+#define CIFISP_BLS_FIX_SUB_MAX             (0x00000FFF)
+/* minimum value for fixed black level */
+#define CIFISP_BLS_FIX_SUB_MIN             (0xFFFFF000)
+/* 13 bit range (signed)*/
+#define CIFISP_BLS_FIX_MASK                (0x00001FFF)
+/* AWB */
+#define CIFISP_AWB_MAX_GRID                1
+#define CIFISP_AWB_MAX_FRAMES              7
+
+/* Gamma out*/
+/* Maximum number of color samples supported */
+#define CIFISP_GAMMA_OUT_MAX_SAMPLES       17
+
+/* LSC */
+#define CIFISP_LSC_GRAD_TBL_SIZE           8
+#define CIFISP_LSC_SIZE_TBL_SIZE           8
+/*
+ * The following matches the tuning process,
+ * not the max capabilities of the chip.
+ */
+#define        CIFISP_LSC_DATA_TBL_SIZE           289
+/* HIST */
+#define CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE 25
+
+/* DPCC */
+#define CIFISP_DPCC_METHODS_MAX       (3)
+
+/* DPF */
+#define CIFISP_DPF_MAX_NLF_COEFFS      17
+#define CIFISP_DPF_MAX_SPATIAL_COEFFS  6
+
+#define CIFISP_STAT_AWB           BIT(0)
+#define CIFISP_STAT_AUTOEXP       BIT(1)
+#define CIFISP_STAT_AFM_FIN       BIT(2)
+#define CIFISP_STAT_HIST          BIT(3)
+
+enum cifisp_histogram_mode {
+       CIFISP_HISTOGRAM_MODE_DISABLE         = 0,
+       CIFISP_HISTOGRAM_MODE_RGB_COMBINED    = 1,
+       CIFISP_HISTOGRAM_MODE_R_HISTOGRAM     = 2,
+       CIFISP_HISTOGRAM_MODE_G_HISTOGRAM     = 3,
+       CIFISP_HISTOGRAM_MODE_B_HISTOGRAM     = 4,
+       CIFISP_HISTOGRAM_MODE_Y_HISTOGRAM     = 5
+};
+
+enum cifisp_exp_ctrl_autostop {
+       CIFISP_EXP_CTRL_AUTOSTOP_0 = 0,
+       CIFISP_EXP_CTRL_AUTOSTOP_1 = 1
+};
+
+enum cifisp_exp_meas_mode {
+/* < Y = 16 + 0.25R + 0.5G + 0.1094B */
+       CIFISP_EXP_MEASURING_MODE_0 = 0,
+/* < Y = (R + G + B) x (85/256) */
+       CIFISP_EXP_MEASURING_MODE_1 = 1,
+};
+
+struct cifisp_window {
+       unsigned short h_offs;
+       unsigned short v_offs;
+       unsigned short h_size;
+       unsigned short v_size;
+};
+
+enum cifisp_awb_mode_type {
+       CIFISP_AWB_MODE_MANUAL  = 0,
+       CIFISP_AWB_MODE_RGB     = 1,
+       CIFISP_AWB_MODE_YCBCR   = 2
+};
+
+enum cifisp_bls_win_enable {
+       ISP_BLS_CTRL_WINDOW_ENABLE_0 = 0,
+       ISP_BLS_CTRL_WINDOW_ENABLE_1 = 1,
+       ISP_BLS_CTRL_WINDOW_ENABLE_2 = 2,
+       ISP_BLS_CTRL_WINDOW_ENABLE_3 = 3
+};
+
+enum cifisp_flt_mode {
+       CIFISP_FLT_STATIC_MODE,
+       CIFISP_FLT_DYNAMIC_MODE
+};
+
+struct cifisp_awb_meas {
+       unsigned int cnt;
+       unsigned char mean_y;
+       unsigned char mean_cb;
+       unsigned char mean_cr;
+       unsigned short mean_r;
+       unsigned short mean_b;
+       unsigned short mean_g;
+};
+
+struct cifisp_awb_stat {
+       struct cifisp_awb_meas awb_mean[CIFISP_AWB_MAX_GRID];
+};
+
+struct cifisp_hist_stat {
+       unsigned short hist_bins[CIFISP_HIST_BIN_N_MAX];
+};
+
+/*! BLS mean measured values */
+struct cifisp_bls_meas_val {
+       /*! Mean measured value for Bayer pattern R.*/
+       unsigned short meas_r;
+       /*! Mean measured value for Bayer pattern Gr.*/
+       unsigned short meas_gr;
+       /*! Mean measured value for Bayer pattern Gb.*/
+       unsigned short meas_gb;
+       /*! Mean measured value for Bayer pattern B.*/
+       unsigned short meas_b;
+};
+
+/*
+ * BLS fixed subtraction values. The values will be subtracted from the sensor
+ * values. Therefore a negative value means addition instead of subtraction!
+ */
+struct cifisp_bls_fixed_val {
+       /*! Fixed (signed!) subtraction value for Bayer pattern R. */
+       signed short r;
+       /*! Fixed (signed!) subtraction value for Bayer pattern Gr. */
+       signed short gr;
+       /*! Fixed (signed!) subtraction value for Bayer pattern Gb. */
+       signed short gb;
+       /*! Fixed (signed!) subtraction value for Bayer pattern B. */
+       signed short b;
+};
+
+/* Configuration used by black level subtraction */
+struct cifisp_bls_config {
+       /*
+        * Automatic mode activated means that the measured values
+        * are subtracted.Otherwise the fixed subtraction
+        * values will be subtracted.
+        */
+       bool enable_auto;
+       unsigned char en_windows;
+       struct cifisp_window bls_window1;      /* < Measurement window 1. */
+       struct cifisp_window bls_window2;      /* !< Measurement window 2 */
+       /*
+        * Set amount of measured pixels for each Bayer position
+        * (A, B,C and D) to 2^bls_samples.
+        */
+       unsigned char bls_samples;
+       /* !< Fixed subtraction values. */
+       struct cifisp_bls_fixed_val fixed_val;
+};
+
+struct cifisp_ae_stat {
+       unsigned char exp_mean[CIFISP_AE_MEAN_MAX];
+       struct cifisp_bls_meas_val bls_val; /* available wit exposure results */
+};
+
+struct cifisp_af_meas_val {
+       unsigned int sum;
+       unsigned int lum;
+};
+
+struct cifisp_af_stat {
+       struct cifisp_af_meas_val window[CIFISP_AFM_MAX_WINDOWS];
+};
+
+struct cifisp_stat {
+       struct cifisp_awb_stat awb;
+       struct cifisp_ae_stat ae;
+       struct cifisp_af_stat af;
+       struct cifisp_hist_stat hist;
+};
+
+struct cifisp_stat_buffer {
+       unsigned int meas_type;
+       struct cifisp_stat params;
+       struct isp_supplemental_sensor_mode_data sensor_mode;
+};
+
+struct cifisp_dpcc_methods_config {
+       unsigned int method;
+       unsigned int  line_thresh;
+       unsigned int  line_mad_fac;
+       unsigned int  pg_fac;
+       unsigned int  rnd_thresh;
+       unsigned int  rg_fac;
+};
+
+struct cifisp_dpcc_config {
+       unsigned int  mode;
+       unsigned int  output_mode;
+       unsigned int  set_use;
+       struct cifisp_dpcc_methods_config methods[CIFISP_DPCC_METHODS_MAX];
+       unsigned int  ro_limits;
+       unsigned int  rnd_offs;
+};
+
+struct cifisp_gamma_corr_curve {
+       unsigned short gamma_y[CIFISP_DEGAMMA_CURVE_SIZE];
+};
+
+struct cifisp_gamma_curve_x_axis_pnts {
+       unsigned int  gamma_dx0;
+       unsigned int  gamma_dx1;
+};
+
+/* Configuration used by sensor degamma */
+struct cifisp_sdg_config {
+       struct cifisp_gamma_corr_curve curve_r;
+       struct cifisp_gamma_corr_curve curve_g;
+       struct cifisp_gamma_corr_curve curve_b;
+       struct cifisp_gamma_curve_x_axis_pnts xa_pnts;
+};
+
+/* Configuration used by Lens shading correction */
+struct cifisp_lsc_config {
+       unsigned int r_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
+       unsigned int gr_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
+       unsigned int gb_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
+       unsigned int b_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
+
+       unsigned int x_grad_tbl[CIFISP_LSC_GRAD_TBL_SIZE];
+       unsigned int y_grad_tbl[CIFISP_LSC_GRAD_TBL_SIZE];
+
+       unsigned int x_size_tbl[CIFISP_LSC_SIZE_TBL_SIZE];
+       unsigned int y_size_tbl[CIFISP_LSC_SIZE_TBL_SIZE];
+       unsigned short config_width;
+       unsigned short config_height;
+};
+
+struct cifisp_ie_config {
+       enum v4l2_colorfx effect;
+       unsigned short color_sel;
+       /* 3x3 Matrix Coefficients for Emboss Effect 1 */
+       unsigned short eff_mat_1;
+       /* 3x3 Matrix Coefficients for Emboss Effect 2 */
+       unsigned short eff_mat_2;
+       /* 3x3 Matrix Coefficients for Emboss 3/Sketch 1 */
+       unsigned short eff_mat_3;
+       /* 3x3 Matrix Coefficients for Sketch Effect 2 */
+       unsigned short eff_mat_4;
+       /* 3x3 Matrix Coefficients for Sketch Effect 3 */
+       unsigned short eff_mat_5;
+       /* Chrominance increment values of tint (used for sepia effect) */
+       unsigned short eff_tint;
+};
+
+/* Configuration used by auto white balance */
+struct cifisp_awb_meas_config {
+       /*
+        * white balance measurement window (in pixels)
+        * Note: currently the h and v offsets are mapped to grid offsets
+        */
+       struct cifisp_window awb_wnd;
+       enum cifisp_awb_mode_type awb_mode;
+       /*
+        * only pixels values < max_y contribute to awb measurement
+        * (set to 0 to disable this feature)
+        */
+       unsigned char    max_y;
+       /* only pixels values > min_y contribute to awb measurement */
+       unsigned char    min_y;
+       /*
+        * Chrominance sum maximum value, only consider pixels with Cb+Cr
+        * smaller than threshold for awb measurements
+        */
+       unsigned char    max_csum;
+       /*
+        * Chrominance minimum value, only consider pixels with Cb/Cr
+        * each greater than threshold value for awb measurements
+        */
+       unsigned char    min_c;
+       /*
+        * number of frames - 1 used for mean value calculation
+        * (ucFrames=0 means 1 Frame)
+        */
+       unsigned char    frames;
+       /* reference Cr value for AWB regulation, target for AWB */
+       unsigned char    awb_ref_cr;
+       /* reference Cb value for AWB regulation, target for AWB */
+       unsigned char    awb_ref_cb;
+       bool enable_ymax_cmp;
+};
+
+struct cifisp_awb_gain_config {
+       unsigned short  gain_red;
+       unsigned short  gain_green_r;
+       unsigned short  gain_blue;
+       unsigned short  gain_green_b;
+};
+
+/* Configuration used by ISP filtering */
+struct cifisp_flt_config {
+       enum cifisp_flt_mode  mode;    /* ISP_FILT_MODE register fields */
+       unsigned char grn_stage1;    /* ISP_FILT_MODE register fields */
+       unsigned char chr_h_mode;    /* ISP_FILT_MODE register fields */
+       unsigned char chr_v_mode;    /* ISP_FILT_MODE register fields */
+       unsigned int  thresh_bl0;
+       unsigned int  thresh_bl1;
+       unsigned int  thresh_sh0;
+       unsigned int  thresh_sh1;
+       unsigned int  lum_weight;
+       unsigned int  fac_sh1;
+       unsigned int  fac_sh0;
+       unsigned int  fac_mid;
+       unsigned int  fac_bl0;
+       unsigned int  fac_bl1;
+};
+
+/* Configuration used by Bayer DeMosaic */
+struct cifisp_bdm_config {
+       unsigned char demosaic_th;
+};
+
+/* Configuration used by Cross Talk correction */
+struct cifisp_ctk_config {
+       unsigned short coeff0;
+       unsigned short coeff1;
+       unsigned short coeff2;
+       unsigned short coeff3;
+       unsigned short coeff4;
+       unsigned short coeff5;
+       unsigned short coeff6;
+       unsigned short coeff7;
+       unsigned short coeff8;
+       /* offset for the crosstalk correction matrix */
+       unsigned short ct_offset_r;
+       unsigned short ct_offset_g;
+       unsigned short ct_offset_b;
+};
+
+enum cifisp_goc_mode {
+       CIFISP_GOC_MODE_LOGARITHMIC,
+       CIFISP_GOC_MODE_EQUIDISTANT
+};
+
+/* Configuration used by Gamma Out correction */
+struct cifisp_goc_config {
+       enum cifisp_goc_mode mode;
+       unsigned short gamma_y[CIFISP_GAMMA_OUT_MAX_SAMPLES];
+};
+
+/* CCM (Color Correction) */
+struct cifisp_cproc_config {
+       unsigned char c_out_range;
+       unsigned char y_in_range;
+       unsigned char y_out_range;
+       unsigned char contrast;
+       unsigned char brightness;
+       unsigned char sat;
+       unsigned char hue;
+};
+
+/* Configuration used by Histogram */
+struct cifisp_hst_config {
+       enum cifisp_histogram_mode mode;
+       unsigned char histogram_predivider;
+       struct cifisp_window meas_window;
+       unsigned char hist_weight[CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE];
+};
+
+/* Configuration used by Auto Exposure Control */
+struct cifisp_aec_config {
+       enum cifisp_exp_meas_mode mode;
+       enum cifisp_exp_ctrl_autostop autostop;
+       struct cifisp_window meas_window;
+};
+
+struct cifisp_afc_config {
+       unsigned char num_afm_win;      /* max CIFISP_AFM_MAX_WINDOWS */
+       struct cifisp_window afm_win[CIFISP_AFM_MAX_WINDOWS];
+       unsigned int thres;
+       unsigned int var_shift;
+};
+
+enum cifisp_dpf_gain_usage {
+/* don't use any gains in preprocessing stage */
+       CIFISP_DPF_GAIN_USAGE_DISABLED      = 1,
+/* use only the noise function gains  from registers DPF_NF_GAIN_R, ... */
+       CIFISP_DPF_GAIN_USAGE_NF_GAINS      = 2,
+/* use only the gains from LSC module */
+       CIFISP_DPF_GAIN_USAGE_LSC_GAINS     = 3,
+/* use the moise function gains and the gains from LSC module */
+       CIFISP_DPF_GAIN_USAGE_NF_LSC_GAINS  = 4,
+/* use only the gains from AWB module */
+       CIFISP_DPF_GAIN_USAGE_AWB_GAINS     = 5,
+/* use the gains from AWB and LSC module */
+       CIFISP_DPF_GAIN_USAGE_AWB_LSC_GAINS = 6,
+/* upper border (only for an internal evaluation) */
+       CIFISP_DPF_GAIN_USAGE_MAX
+};
+
+enum cifisp_dpf_rb_filtersize {
+/* red and blue filter kernel size 13x9 (means 7x5 active pixel) */
+       CIFISP_DPF_RB_FILTERSIZE_13x9      = 0,
+/* red and blue filter kernel size 9x9 (means 5x5 active pixel) */
+       CIFISP_DPF_RB_FILTERSIZE_9x9       = 1,
+};
+
+enum cifisp_dpf_nll_scale_mode {
+/* use a linear scaling */
+       CIFISP_NLL_SCALE_LINEAR        = 0,
+/* use a logarithmic scaling */
+       CIFISP_NLL_SCALE_LOGARITHMIC   = 1,
+};
+
+struct cifisp_dpf_nll {
+       unsigned short coeff[CIFISP_DPF_MAX_NLF_COEFFS];
+       enum cifisp_dpf_nll_scale_mode scale_mode;
+};
+
+struct cifisp_dpf_rb_flt {
+       enum cifisp_dpf_rb_filtersize fltsize;
+       unsigned char spatial_coeff[CIFISP_DPF_MAX_SPATIAL_COEFFS];
+       bool r_enable;
+       bool b_enable;
+};
+
+struct cifisp_dpf_g_flt {
+       unsigned char spatial_coeff[CIFISP_DPF_MAX_SPATIAL_COEFFS];
+       bool gr_enable;
+       bool gb_enable;
+};
+
+struct cifisp_dpf_gain {
+       enum cifisp_dpf_gain_usage mode;
+       unsigned short nf_r_gain;
+       unsigned short nf_b_gain;
+       unsigned short nf_gr_gain;
+       unsigned short nf_gb_gain;
+};
+
+struct cifisp_dpf_config {
+       struct cifisp_dpf_gain gain;
+       struct cifisp_dpf_g_flt g_flt;
+       struct cifisp_dpf_rb_flt rb_flt;
+       struct cifisp_dpf_nll nll;
+};
+
+struct cifisp_dpf_strength_config {
+       unsigned char r;
+       unsigned char g;
+       unsigned char b;
+};
+
+struct cifisp_last_capture_config {
+       struct cifisp_cproc_config cproc;
+       struct cifisp_goc_config   goc;
+       struct cifisp_ctk_config   ctk;
+       struct cifisp_bdm_config   bdm;
+       struct cifisp_flt_config   flt;
+       struct cifisp_awb_gain_config awb_gain;
+       struct cifisp_awb_meas_config awb_meas;
+       struct cifisp_lsc_config lsc;
+       struct cifisp_sdg_config sdg;
+       struct cifisp_bls_config bls;
+};
+
+struct cifisp_isp_other_cfg {
+       unsigned int s_frame_id;/* Set isp hardware frame id */
+
+       unsigned int module_ens;
+
+       struct cifisp_dpcc_config dpcc_config;
+       struct cifisp_bls_config bls_config;
+       struct cifisp_sdg_config sdg_config;
+       struct cifisp_lsc_config lsc_config;
+       struct cifisp_awb_gain_config awb_gain_config;
+       struct cifisp_flt_config flt_config;
+       struct cifisp_bdm_config bdm_config;
+       struct cifisp_ctk_config ctk_config;
+       struct cifisp_goc_config goc_config;
+       struct cifisp_cproc_config cproc_config;
+       struct cifisp_ie_config ie_config;
+       struct cifisp_dpf_config dpf_config;
+       struct cifisp_dpf_strength_config dpf_strength_config;
+};
+
+struct cifisp_isp_meas_cfg {
+       unsigned int s_frame_id;                /* Set isp hardware frame id */
+
+       unsigned int module_ens;
+
+       struct cifisp_awb_meas_config awb_meas_config;
+       struct cifisp_hst_config hst_config;
+       struct cifisp_aec_config aec_config;
+       struct cifisp_afc_config afc_config;
+};
+
+struct cifisp_isp_metadata {
+       struct cifisp_isp_other_cfg other_cfg;
+       struct cifisp_isp_meas_cfg meas_cfg;
+       struct cifisp_stat_buffer meas_stat;
+};
+#endif
diff --git a/include/media/rk-isp10-ioctl.h b/include/media/rk-isp10-ioctl.h
new file mode 100644 (file)
index 0000000..22e2e6e
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+#include <linux/v4l2-controls.h>
+#include <media/rk-isp10-config.h>
+#include <media/v4l2-controls_rockchip.h>
+
+#ifndef _RK_ISP10_IOCTL_H
+#define _RK_ISP10_IOCTL_H
+
+/* Private IOCTLs */
+/* DPCC */
+#define CIFISP_IOC_G_DPCC \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 0, struct cifisp_dpcc_config)
+#define CIFISP_IOC_S_DPCC \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 1, struct cifisp_dpcc_config)
+/* Black Level Subtraction */
+#define CIFISP_IOC_G_BLS \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 2, struct cifisp_bls_config)
+#define CIFISP_IOC_S_BLS \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 3, struct cifisp_bls_config)
+/* Sensor DeGamma */
+#define CIFISP_IOC_G_SDG \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 4, struct cifisp_sdg_config)
+#define CIFISP_IOC_S_SDG \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 5, struct cifisp_sdg_config)
+/* Lens Shading Correction */
+#define CIFISP_IOC_G_LSC \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 6, struct cifisp_lsc_config)
+#define CIFISP_IOC_S_LSC \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 7, struct cifisp_lsc_config)
+/* Auto White Balance */
+#define CIFISP_IOC_G_AWB_MEAS \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 8, struct cifisp_awb_meas_config)
+#define CIFISP_IOC_S_AWB_MEAS \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 9, struct cifisp_awb_meas_config)
+/* ISP Filtering( Sharpening & Noise reduction */
+#define CIFISP_IOC_G_FLT \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 10, struct cifisp_flt_config)
+#define CIFISP_IOC_S_FLT \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 11, struct cifisp_flt_config)
+/* Bayer Demosaic */
+#define CIFISP_IOC_G_BDM \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 12, struct cifisp_bdm_config)
+#define CIFISP_IOC_S_BDM \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 13, struct cifisp_bdm_config)
+/* Cross Talk correction */
+#define CIFISP_IOC_G_CTK \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 14, struct cifisp_ctk_config)
+#define CIFISP_IOC_S_CTK \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 15, struct cifisp_ctk_config)
+/* Gamma Out Correction */
+#define CIFISP_IOC_G_GOC \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 16, struct cifisp_goc_config)
+#define CIFISP_IOC_S_GOC \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 17, struct cifisp_goc_config)
+/* Histogram Measurement */
+#define CIFISP_IOC_G_HST \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 18, struct cifisp_hst_config)
+#define CIFISP_IOC_S_HST \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 19, struct cifisp_hst_config)
+/* Auto Exposure Measurements */
+#define CIFISP_IOC_G_AEC \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 20, struct cifisp_aec_config)
+#define CIFISP_IOC_S_AEC \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 21, struct cifisp_aec_config)
+#define CIFISP_IOC_G_BPL \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 22, struct cifisp_aec_config)
+#define CIFISP_IOC_G_AWB_GAIN \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 23, struct cifisp_awb_gain_config)
+#define CIFISP_IOC_S_AWB_GAIN \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 24, struct cifisp_awb_gain_config)
+#define CIFISP_IOC_G_CPROC \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 25, struct cifisp_cproc_config)
+#define CIFISP_IOC_S_CPROC \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 26, struct cifisp_cproc_config)
+#define CIFISP_IOC_G_AFC \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 27, struct cifisp_afc_config)
+#define CIFISP_IOC_S_AFC \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 28, struct cifisp_afc_config)
+#define CIFISP_IOC_G_IE \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 29, struct cifisp_ie_config)
+#define CIFISP_IOC_S_IE \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 30, struct cifisp_ie_config)
+#define CIFISP_IOC_G_DPF \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 31, struct cifisp_dpf_config)
+#define CIFISP_IOC_S_DPF \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct cifisp_dpf_config)
+#define CIFISP_IOC_G_DPF_STRENGTH \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 33, struct cifisp_dpf_strength_config)
+#define CIFISP_IOC_S_DPF_STRENGTH \
+       _IOW('v', BASE_VIDIOC_PRIVATE + 34, struct cifisp_dpf_strength_config)
+#define CIFISP_IOC_G_LAST_CONFIG \
+       _IOR('v', BASE_VIDIOC_PRIVATE + 35, struct cifisp_last_capture_config)
+
+/* CIF-ISP Private control IDs */
+#define V4L2_CID_CIFISP_DPCC    (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_CIFISP_BLS    (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_CIFISP_SDG    (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_CIFISP_LSC    (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_CIFISP_AWB_MEAS    (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_CIFISP_FLT    (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_CIFISP_BDM    (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_CIFISP_CTK    (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_CIFISP_GOC    (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_CIFISP_HST    (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_CIFISP_AEC    (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_CIFISP_AWB_GAIN    (V4L2_CID_PRIVATE_BASE + 11)
+#define V4L2_CID_CIFISP_CPROC    (V4L2_CID_PRIVATE_BASE + 12)
+#define V4L2_CID_CIFISP_AFC    (V4L2_CID_PRIVATE_BASE + 13)
+#define V4L2_CID_CIFISP_IE    (V4L2_CID_PRIVATE_BASE + 14)
+#define V4L2_CID_CIFISP_DPF    (V4L2_CID_PRIVATE_BASE + 15)
+
+/* Camera Sensors' running modes */
+#define CI_MODE_PREVIEW        0x8000
+#define CI_MODE_VIDEO  0x4000
+#define CI_MODE_STILL_CAPTURE  0x2000
+#define CI_MODE_CONTINUOUS     0x1000
+#define CI_MODE_NONE   0x0000
+
+#endif
diff --git a/include/media/v4l2-config_rockchip.h b/include/media/v4l2-config_rockchip.h
new file mode 100644 (file)
index 0000000..fb66802
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _V4L2_CONFIG_ROCKCHIP_H
+#define _V4L2_CONFIG_ROCKCHIP_H
+
+#define CAMERA_STRLEN         32
+#define CAMERA_METADATA_LEN   (2 * PAGE_SIZE)
+
+/* Sensor resolution specific data for AE calculation.*/
+struct isp_supplemental_sensor_mode_data {
+       unsigned int coarse_integration_time_min;
+       unsigned int coarse_integration_time_max_margin;
+       unsigned int fine_integration_time_min;
+       unsigned int fine_integration_time_max_margin;
+       unsigned int frame_length_lines;
+       unsigned int line_length_pck;
+       unsigned int vt_pix_clk_freq_hz;
+       unsigned int crop_horizontal_start; /* Sensor crop start cord. (x0,y0)*/
+       unsigned int crop_vertical_start;
+       unsigned int crop_horizontal_end; /* Sensor crop end cord. (x1,y1)*/
+       unsigned int crop_vertical_end;
+       unsigned int sensor_output_width; /* input size to ISP */
+       unsigned int sensor_output_height;
+       unsigned int isp_input_horizontal_start;        /* cif isp input */
+       unsigned int isp_input_vertical_start;
+       unsigned int isp_input_width;
+       unsigned int isp_input_height;
+       unsigned int isp_output_width;  /* cif isp output */
+       unsigned int isp_output_height;
+       unsigned char binning_factor_x; /* horizontal binning factor used */
+       unsigned char binning_factor_y; /* vertical binning factor used */
+       unsigned char exposure_valid_frame;
+       int exp_time;
+       unsigned short gain;
+};
+
+struct camera_module_info_s {
+       char sensor_name[CAMERA_STRLEN];
+       char module_name[CAMERA_STRLEN];
+       char len_name[CAMERA_STRLEN];
+       char fov_h[CAMERA_STRLEN];
+       char fov_v[CAMERA_STRLEN];
+       char focal_length[CAMERA_STRLEN];
+       char focus_distance[CAMERA_STRLEN];
+       int facing;
+       int orientation;
+       bool iq_mirror;
+       bool iq_flip;
+       int flash_support;
+       int flash_exp_percent;
+};
+
+struct flash_timeinfo_s {
+       struct timeval preflash_start_t;
+       struct timeval preflash_end_t;
+       struct timeval mainflash_start_t;
+       struct timeval mainflash_end_t;
+       int flash_turn_on_time;
+       int flash_on_timeout;
+};
+
+struct frame_timeinfo_s {
+       struct timeval vs_t;
+       struct timeval fi_t;
+};
+
+struct sensor_metadata_s {
+       unsigned int exp_time;
+       unsigned int gain;
+};
+
+struct v4l2_buffer_metadata_s {
+       unsigned int frame_id;
+       struct frame_timeinfo_s frame_t;
+       struct flash_timeinfo_s flash_t;
+       struct sensor_metadata_s sensor;
+       unsigned char isp[CAMERA_METADATA_LEN - 512];
+};
+
+#endif
+
diff --git a/include/media/v4l2-controls_rockchip.h b/include/media/v4l2-controls_rockchip.h
new file mode 100644 (file)
index 0000000..a30d156
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _V4L2_CONTROLS_ROCKCHIP_H
+#define _V4L2_CONTROLS_ROCKCHIP_H
+
+#include <linux/videodev2.h>
+#include <media/v4l2-config_rockchip.h>
+
+#define RK_VIDIOC_CAMERA_MODULEINFO \
+       _IOWR('v', BASE_VIDIOC_PRIVATE + 10, struct camera_module_info_s)
+#define RK_VIDIOC_SENSOR_MODE_DATA \
+       _IOR('v', BASE_VIDIOC_PRIVATE, struct isp_supplemental_sensor_mode_data)
+
+#define V4L2_CID_USER_RK_BASE (V4L2_CID_USER_BASE + 0x1080)
+#define RK_V4L2_CID_VBLANKING (V4L2_CID_USER_RK_BASE + 1)
+#define RK_V4L2_CID_GAIN_PERCENT (V4L2_CID_USER_RK_BASE + 2)
+#define RK_V4L2_CID_AUTO_FPS (V4L2_CID_USER_RK_BASE + 3)
+#endif