MLK-15048-1: media: v4l: capture: Move mxc/subdev/ drivers to mxc/capture
authorCristina Ciocan <cristina-mihaela.ciocan@nxp.com>
Thu, 22 Jun 2017 14:41:36 +0000 (17:41 +0300)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:33:36 +0000 (15:33 -0500)
All drivers in mxc/subdev are capture devices, so move them to their
rightful place, in mxc/capture to avoid confusion.

Two of the drivers, ov5640 and ov5640_mipi are in both locations, having
the same configs: CONFIG_MXC_CAMERA_OV5640 and CONFIG_MXC_CAMERA_OV5640_MIPI.
After moving all to mxc/capture/ directory, add a _v2 suffix to those
drivers moved from mxc/subdev to allow a clean compile process. As a next
step, the 2 versions of drivers should be merged, since they represent the
same device and functionality.

Signed-off-by: Cristina Ciocan <cristina-mihaela.ciocan@nxp.com>
21 files changed:
arch/arm/configs/imx_v7_defconfig
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/mxc/capture/Kconfig
drivers/media/platform/mxc/capture/Makefile
drivers/media/platform/mxc/capture/mx6s_capture.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/mxc_mipi_csi.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/mxc_vadc.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/mxc_vadc.h [new file with mode: 0644]
drivers/media/platform/mxc/capture/ov5640_mipi_v2.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ov5640_v2.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ov5647_mipi.c [new file with mode: 0644]
drivers/media/platform/mxc/subdev/Kconfig [deleted file]
drivers/media/platform/mxc/subdev/Makefile [deleted file]
drivers/media/platform/mxc/subdev/mx6s_capture.c [deleted file]
drivers/media/platform/mxc/subdev/mxc_mipi_csi.c [deleted file]
drivers/media/platform/mxc/subdev/mxc_vadc.c [deleted file]
drivers/media/platform/mxc/subdev/mxc_vadc.h [deleted file]
drivers/media/platform/mxc/subdev/ov5640.c [deleted file]
drivers/media/platform/mxc/subdev/ov5640_mipi.c [deleted file]
drivers/media/platform/mxc/subdev/ov5647_mipi.c [deleted file]

index a179765..5ac3c03 100644 (file)
@@ -245,17 +245,19 @@ CONFIG_USB_VIDEO_CLASS=m
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_VIDEO_MXC_OUTPUT=y
 CONFIG_VIDEO_MXC_CAPTURE=m
+CONFIG_VIDEO_MXC_CSI_CAMERA=m
+CONFIG_MXC_VADC=m
+CONFIG_MXC_MIPI_CSI=m
 CONFIG_MXC_CAMERA_OV5640=m
+CONFIG_MXC_CAMERA_OV5640_V2=m
 CONFIG_MXC_CAMERA_OV5642=m
 CONFIG_MXC_CAMERA_OV5640_MIPI=m
+CONFIG_MXC_CAMERA_OV5640_MIPI_V2=m
+CONFIG_MXC_CAMERA_OV5647_MIPI=m
 CONFIG_MXC_TVIN_ADV7180=m
 CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
 CONFIG_VIDEO_MXC_IPU_OUTPUT=y
 CONFIG_VIDEO_MXC_PXP_V4L2=y
-CONFIG_VIDEO_MXC_CSI_CAMERA=m
-CONFIG_MXC_VADC=m
-CONFIG_MXC_MIPI_CSI=m
-CONFIG_MXC_CAMERA_OV5647_MIPI=m
 CONFIG_SOC_CAMERA=y
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_CODA=y
index 28d268b..fef1147 100644 (file)
@@ -136,7 +136,6 @@ config VIDEO_MX8_CAPTURE
 source "drivers/media/platform/imx8/Kconfig"
 source "drivers/media/platform/mxc/capture/Kconfig"
 source "drivers/media/platform/mxc/output/Kconfig"
-source "drivers/media/platform/mxc/subdev/Kconfig"
 source "drivers/media/platform/soc_camera/Kconfig"
 source "drivers/media/platform/exynos4-is/Kconfig"
 source "drivers/media/platform/am437x/Kconfig"
index 744edd8..ce35b45 100644 (file)
@@ -64,7 +64,6 @@ obj-$(CONFIG_VIDEO_ATMEL_ISC)         += atmel/
 obj-$(CONFIG_VIDEO_MXC_OUTPUT)         += mxc/output/
 
 obj-$(CONFIG_VIDEO_MXC_CAPTURE)        += mxc/capture/
-obj-$(CONFIG_VIDEO_MXC_CAPTURE)        += mxc/subdev/
 obj-$(CONFIG_VIDEO_MXC_OUTPUT)  += mxc/output/
 obj-$(CONFIG_VIDEO_MX8_CAPTURE)        += imx8/
 
index 1edd5bd..6671b69 100644 (file)
@@ -1,7 +1,26 @@
 if VIDEO_MXC_CAPTURE
+
 config VIDEO_V4L2_MXC_INT_DEVICE
        tristate
 
+config VIDEO_MXC_CSI_CAMERA
+       tristate "CSI camera support"
+       depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
+       ---help---
+               This is the video4linux2 capture driver based on CSI module.
+
+config MXC_VADC
+       tristate "mxc VADC support"
+       depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
+       ---help---
+               If you plan to use the VADC with your MXC system, say Y here.
+
+config MXC_MIPI_CSI
+       tristate "mxc mipi csi driver"
+       depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
+       ---help---
+               This is a V4L2 driver for i.MX7D SoC MIPI-CSI2 receiver devices.
+
 menu "MXC Camera/V4L2 PRP Features support"
 config VIDEO_MXC_IPU_CAMERA
        bool
@@ -15,6 +34,12 @@ config MXC_CAMERA_OV5640
         ---help---
           If you plan to use the ov5640 Camera with your MXC system, say Y here.
 
+config MXC_CAMERA_OV5640_V2
+       tristate "OmniVision ov5640 camera support"
+       depends on VIDEO_MXC_CAPTURE && I2C
+       ---help---
+         If you plan to use the ov5640 Camera with your MXC system, say Y here.
+
 config MXC_CAMERA_OV5642
        tristate "OmniVision ov5642 camera support"
        depends on !VIDEO_MXC_EMMA_CAMERA && I2C
@@ -27,6 +52,18 @@ config MXC_CAMERA_OV5640_MIPI
        ---help---
          If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here.
 
+config MXC_CAMERA_OV5640_MIPI_V2
+       tristate "OmniVision ov5640 camera support using mipi"
+       depends on MXC_MIPI_CSI && I2C
+       ---help---
+         If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here.
+
+config MXC_CAMERA_OV5647_MIPI
+       tristate "OmniVision ov5647 camera support using mipi"
+       depends on MXC_MIPI_CSI && I2C
+       ---help---
+         If you plan to use the ov5647 Camera with mipi interface in your MXC system, say Y here.
+
 config MXC_TVIN_ADV7180
        tristate "Analog Device adv7180 TV Decoder Input support"
        depends on !VIDEO_MXC_EMMA_CAMERA && I2C
index 6c04faf..e6e4b99 100644 (file)
@@ -6,15 +6,32 @@ ifeq ($(CONFIG_VIDEO_MXC_IPU_CAMERA),y)
        obj-$(CONFIG_MXC_IPU_CSI_ENC) += ipu_csi_enc.o ipu_still.o
 endif
 
+obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += mx6s_capture.o
+obj-$(CONFIG_MXC_VADC) += mxc_vadc.o
+obj-$(CONFIG_MXC_MIPI_CSI) += mxc_mipi_csi.o
+
+# Used for iMX 6QDL
 ov5640_camera_int-objs := ov5640.o
 obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera_int.o
 
+# Used for iMX 6UL/ULL/SX/SL/SLL
+ov5640_camera_v2-objs := ov5640_v2.o
+obj-$(CONFIG_MXC_CAMERA_OV5640_V2) += ov5640_camera_v2.o
+
 ov5642_camera-objs := ov5642.o
 obj-$(CONFIG_MXC_CAMERA_OV5642) += ov5642_camera.o
 
+# Used for iMX 6QDL/DQSCM
 ov5640_camera_mipi_int-objs := ov5640_mipi.o
 obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi_int.o
 
+# Used for iMX 7D
+ov5640_camera_mipi_v2-objs := ov5640_mipi_v2.o
+obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI_V2) += ov5640_camera_mipi_v2.o
+
+ov5647_camera_mipi-objs := ov5647_mipi.o
+obj-$(CONFIG_MXC_CAMERA_OV5647_MIPI) += ov5647_camera_mipi.o
+
 adv7180_tvin-objs := adv7180.o
 obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o
 
diff --git a/drivers/media/platform/mxc/capture/mx6s_capture.c b/drivers/media/platform/mxc/capture/mx6s_capture.c
new file mode 100644 (file)
index 0000000..63eb549
--- /dev/null
@@ -0,0 +1,1970 @@
+/*
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file mx6s_csi.c
+ *
+ * @brief mx6sx CMOS Sensor interface functions
+ *
+ * @ingroup CSI
+ */
+#include <asm/dma.h>
+#include <linux/busfreq-imx.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/gcd.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/media-bus-format.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-of.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define MX6S_CAM_DRV_NAME "mx6s-csi"
+#define MX6S_CAM_VERSION "0.0.1"
+#define MX6S_CAM_DRIVER_DESCRIPTION "i.MX6S_CSI"
+
+#define MAX_VIDEO_MEM 64
+
+/* reset values */
+#define CSICR1_RESET_VAL       0x40000800
+#define CSICR2_RESET_VAL       0x0
+#define CSICR3_RESET_VAL       0x0
+
+/* csi control reg 1 */
+#define BIT_SWAP16_EN          (0x1 << 31)
+#define BIT_EXT_VSYNC          (0x1 << 30)
+#define BIT_EOF_INT_EN         (0x1 << 29)
+#define BIT_PRP_IF_EN          (0x1 << 28)
+#define BIT_CCIR_MODE          (0x1 << 27)
+#define BIT_COF_INT_EN         (0x1 << 26)
+#define BIT_SF_OR_INTEN                (0x1 << 25)
+#define BIT_RF_OR_INTEN                (0x1 << 24)
+#define BIT_SFF_DMA_DONE_INTEN  (0x1 << 22)
+#define BIT_STATFF_INTEN       (0x1 << 21)
+#define BIT_FB2_DMA_DONE_INTEN  (0x1 << 20)
+#define BIT_FB1_DMA_DONE_INTEN  (0x1 << 19)
+#define BIT_RXFF_INTEN         (0x1 << 18)
+#define BIT_SOF_POL            (0x1 << 17)
+#define BIT_SOF_INTEN          (0x1 << 16)
+#define BIT_MCLKDIV            (0xF << 12)
+#define BIT_HSYNC_POL          (0x1 << 11)
+#define BIT_CCIR_EN            (0x1 << 10)
+#define BIT_MCLKEN             (0x1 << 9)
+#define BIT_FCC                        (0x1 << 8)
+#define BIT_PACK_DIR           (0x1 << 7)
+#define BIT_CLR_STATFIFO       (0x1 << 6)
+#define BIT_CLR_RXFIFO         (0x1 << 5)
+#define BIT_GCLK_MODE          (0x1 << 4)
+#define BIT_INV_DATA           (0x1 << 3)
+#define BIT_INV_PCLK           (0x1 << 2)
+#define BIT_REDGE              (0x1 << 1)
+#define BIT_PIXEL_BIT          (0x1 << 0)
+
+#define SHIFT_MCLKDIV          12
+
+/* control reg 3 */
+#define BIT_FRMCNT             (0xFFFF << 16)
+#define BIT_FRMCNT_RST         (0x1 << 15)
+#define BIT_DMA_REFLASH_RFF    (0x1 << 14)
+#define BIT_DMA_REFLASH_SFF    (0x1 << 13)
+#define BIT_DMA_REQ_EN_RFF     (0x1 << 12)
+#define BIT_DMA_REQ_EN_SFF     (0x1 << 11)
+#define BIT_STATFF_LEVEL       (0x7 << 8)
+#define BIT_HRESP_ERR_EN       (0x1 << 7)
+#define BIT_RXFF_LEVEL         (0x7 << 4)
+#define BIT_TWO_8BIT_SENSOR    (0x1 << 3)
+#define BIT_ZERO_PACK_EN       (0x1 << 2)
+#define BIT_ECC_INT_EN         (0x1 << 1)
+#define BIT_ECC_AUTO_EN                (0x1 << 0)
+
+#define SHIFT_FRMCNT           16
+#define SHIFT_RXFIFO_LEVEL     4
+
+/* csi status reg */
+#define BIT_ADDR_CH_ERR_INT (0x1 << 28)
+#define BIT_FIELD0_INT      (0x1 << 27)
+#define BIT_FIELD1_INT      (0x1 << 26)
+#define BIT_SFF_OR_INT         (0x1 << 25)
+#define BIT_RFF_OR_INT         (0x1 << 24)
+#define BIT_DMA_TSF_DONE_SFF   (0x1 << 22)
+#define BIT_STATFF_INT         (0x1 << 21)
+#define BIT_DMA_TSF_DONE_FB2   (0x1 << 20)
+#define BIT_DMA_TSF_DONE_FB1   (0x1 << 19)
+#define BIT_RXFF_INT           (0x1 << 18)
+#define BIT_EOF_INT            (0x1 << 17)
+#define BIT_SOF_INT            (0x1 << 16)
+#define BIT_F2_INT             (0x1 << 15)
+#define BIT_F1_INT             (0x1 << 14)
+#define BIT_COF_INT            (0x1 << 13)
+#define BIT_HRESP_ERR_INT      (0x1 << 7)
+#define BIT_ECC_INT            (0x1 << 1)
+#define BIT_DRDY               (0x1 << 0)
+
+/* csi control reg 18 */
+#define BIT_CSI_ENABLE                 (0x1 << 31)
+#define BIT_MIPI_DATA_FORMAT_RAW8              (0x2a << 25)
+#define BIT_MIPI_DATA_FORMAT_RAW10             (0x2b << 25)
+#define BIT_MIPI_DATA_FORMAT_YUV422_8B (0x1e << 25)
+#define BIT_MIPI_DATA_FORMAT_MASK      (0x3F << 25)
+#define BIT_MIPI_DATA_FORMAT_OFFSET    25
+#define BIT_DATA_FROM_MIPI             (0x1 << 22)
+#define BIT_MIPI_YU_SWAP               (0x1 << 21)
+#define BIT_MIPI_DOUBLE_CMPNT  (0x1 << 20)
+#define BIT_BASEADDR_CHG_ERR_EN        (0x1 << 9)
+#define BIT_BASEADDR_SWITCH_SEL        (0x1 << 5)
+#define BIT_BASEADDR_SWITCH_EN (0x1 << 4)
+#define BIT_PARALLEL24_EN              (0x1 << 3)
+#define BIT_DEINTERLACE_EN             (0x1 << 2)
+#define BIT_TVDECODER_IN_EN            (0x1 << 1)
+#define BIT_NTSC_EN                            (0x1 << 0)
+
+#define CSI_MCLK_VF            1
+#define CSI_MCLK_ENC           2
+#define CSI_MCLK_RAW           4
+#define CSI_MCLK_I2C           8
+
+#define CSI_CSICR1             0x0
+#define CSI_CSICR2             0x4
+#define CSI_CSICR3             0x8
+#define CSI_STATFIFO           0xC
+#define CSI_CSIRXFIFO          0x10
+#define CSI_CSIRXCNT           0x14
+#define CSI_CSISR              0x18
+
+#define CSI_CSIDBG             0x1C
+#define CSI_CSIDMASA_STATFIFO  0x20
+#define CSI_CSIDMATS_STATFIFO  0x24
+#define CSI_CSIDMASA_FB1       0x28
+#define CSI_CSIDMASA_FB2       0x2C
+#define CSI_CSIFBUF_PARA       0x30
+#define CSI_CSIIMAG_PARA       0x34
+
+#define CSI_CSICR18            0x48
+#define CSI_CSICR19            0x4c
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+#define MX6SX_MAX_SENSORS    1
+
+struct csi_signal_cfg_t {
+       unsigned data_width:3;
+       unsigned clk_mode:2;
+       unsigned ext_vsync:1;
+       unsigned Vsync_pol:1;
+       unsigned Hsync_pol:1;
+       unsigned pixclk_pol:1;
+       unsigned data_pol:1;
+       unsigned sens_clksrc:1;
+};
+
+struct csi_config_t {
+       /* control reg 1 */
+       unsigned int swap16_en:1;
+       unsigned int ext_vsync:1;
+       unsigned int eof_int_en:1;
+       unsigned int prp_if_en:1;
+       unsigned int ccir_mode:1;
+       unsigned int cof_int_en:1;
+       unsigned int sf_or_inten:1;
+       unsigned int rf_or_inten:1;
+       unsigned int sff_dma_done_inten:1;
+       unsigned int statff_inten:1;
+       unsigned int fb2_dma_done_inten:1;
+       unsigned int fb1_dma_done_inten:1;
+       unsigned int rxff_inten:1;
+       unsigned int sof_pol:1;
+       unsigned int sof_inten:1;
+       unsigned int mclkdiv:4;
+       unsigned int hsync_pol:1;
+       unsigned int ccir_en:1;
+       unsigned int mclken:1;
+       unsigned int fcc:1;
+       unsigned int pack_dir:1;
+       unsigned int gclk_mode:1;
+       unsigned int inv_data:1;
+       unsigned int inv_pclk:1;
+       unsigned int redge:1;
+       unsigned int pixel_bit:1;
+
+       /* control reg 3 */
+       unsigned int frmcnt:16;
+       unsigned int frame_reset:1;
+       unsigned int dma_reflash_rff:1;
+       unsigned int dma_reflash_sff:1;
+       unsigned int dma_req_en_rff:1;
+       unsigned int dma_req_en_sff:1;
+       unsigned int statff_level:3;
+       unsigned int hresp_err_en:1;
+       unsigned int rxff_level:3;
+       unsigned int two_8bit_sensor:1;
+       unsigned int zero_pack_en:1;
+       unsigned int ecc_int_en:1;
+       unsigned int ecc_auto_en:1;
+       /* fifo counter */
+       unsigned int rxcnt;
+};
+
+/*
+ * Basic structures
+ */
+struct mx6s_fmt {
+       char  name[32];
+       u32   fourcc;           /* v4l2 format id */
+       u32   pixelformat;
+       u32   mbus_code;
+       int   bpp;
+};
+
+static struct mx6s_fmt formats[] = {
+       {
+               .name           = "UYVY-16",
+               .fourcc         = V4L2_PIX_FMT_UYVY,
+               .pixelformat    = V4L2_PIX_FMT_UYVY,
+               .mbus_code      = MEDIA_BUS_FMT_UYVY8_2X8,
+               .bpp            = 2,
+       }, {
+               .name           = "YUYV-16",
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .pixelformat    = V4L2_PIX_FMT_YUYV,
+               .mbus_code      = MEDIA_BUS_FMT_YUYV8_2X8,
+               .bpp            = 2,
+       }, {
+               .name           = "YUV32 (X-Y-U-V)",
+               .fourcc         = V4L2_PIX_FMT_YUV32,
+               .pixelformat    = V4L2_PIX_FMT_YUV32,
+               .mbus_code      = MEDIA_BUS_FMT_AYUV8_1X32,
+               .bpp            = 4,
+       }, {
+               .name           = "RAWRGB8 (SBGGR8)",
+               .fourcc         = V4L2_PIX_FMT_SBGGR8,
+               .pixelformat    = V4L2_PIX_FMT_SBGGR8,
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .bpp            = 1,
+       }
+};
+
+struct mx6s_buf_internal {
+       struct list_head        queue;
+       int                                     bufnum;
+       bool                            discard;
+};
+
+/* buffer for one video frame */
+struct mx6s_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct vb2_v4l2_buffer                  vb;
+       struct mx6s_buf_internal        internal;
+};
+
+struct mx6s_csi_mux {
+       struct regmap *gpr;
+       u8 req_gpr;
+       u8 req_bit;
+};
+
+struct mx6s_csi_dev {
+       struct device           *dev;
+       struct video_device *vdev;
+       struct v4l2_subdev      *sd;
+       struct v4l2_device      v4l2_dev;
+
+       struct vb2_queue                        vb2_vidq;
+       struct v4l2_ctrl_handler        ctrl_handler;
+
+       struct mutex            lock;
+       spinlock_t                      slock;
+
+       /* clock */
+       struct clk      *clk_disp_axi;
+       struct clk      *clk_disp_dcic;
+       struct clk      *clk_csi_mclk;
+
+       void __iomem *regbase;
+       int irq;
+
+       u32      type;
+       u32 bytesperline;
+       v4l2_std_id std;
+       struct mx6s_fmt         *fmt;
+       struct v4l2_pix_format pix;
+       u32 mbus_code;
+
+       unsigned int frame_count;
+
+       struct list_head        capture;
+       struct list_head        active_bufs;
+       struct list_head        discard;
+
+       void                                            *discard_buffer;
+       dma_addr_t                                      discard_buffer_dma;
+       size_t                                          discard_size;
+       struct mx6s_buf_internal        buf_discard[2];
+
+       struct v4l2_async_subdev        asd;
+       struct v4l2_async_notifier      subdev_notifier;
+       struct v4l2_async_subdev        *async_subdevs[2];
+
+       bool csi_mux_mipi;
+       const bool *rx_fifo_rst;
+       struct mx6s_csi_mux csi_mux;
+};
+
+static const struct of_device_id mx6s_csi_dt_ids[];
+
+static inline int csi_read(struct mx6s_csi_dev *csi, unsigned int offset)
+{
+       return __raw_readl(csi->regbase + offset);
+}
+static inline void csi_write(struct mx6s_csi_dev *csi, unsigned int value,
+                            unsigned int offset)
+{
+       __raw_writel(value, csi->regbase + offset);
+}
+
+static inline struct mx6s_csi_dev
+                               *notifier_to_mx6s_dev(struct v4l2_async_notifier *n)
+{
+       return container_of(n, struct mx6s_csi_dev, subdev_notifier);
+}
+
+struct mx6s_fmt *format_by_fourcc(int fourcc)
+{
+       int i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (formats[i].pixelformat == fourcc)
+                       return formats + i;
+       }
+
+       pr_err("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
+       return NULL;
+}
+
+struct mx6s_fmt *format_by_mbus(u32 code)
+{
+       int i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (formats[i].mbus_code == code)
+                       return formats + i;
+       }
+
+       pr_err("unknown mbus:0x%x\n", code);
+       return NULL;
+}
+
+static struct mx6s_buffer *mx6s_ibuf_to_buf(struct mx6s_buf_internal *int_buf)
+{
+       return container_of(int_buf, struct mx6s_buffer, internal);
+}
+
+void csi_clk_enable(struct mx6s_csi_dev *csi_dev)
+{
+       clk_prepare_enable(csi_dev->clk_disp_axi);
+       clk_prepare_enable(csi_dev->clk_disp_dcic);
+       clk_prepare_enable(csi_dev->clk_csi_mclk);
+}
+
+void csi_clk_disable(struct mx6s_csi_dev *csi_dev)
+{
+       clk_disable_unprepare(csi_dev->clk_csi_mclk);
+       clk_disable_unprepare(csi_dev->clk_disp_dcic);
+       clk_disable_unprepare(csi_dev->clk_disp_axi);
+}
+
+static void csihw_reset(struct mx6s_csi_dev *csi_dev)
+{
+       __raw_writel(__raw_readl(csi_dev->regbase + CSI_CSICR3)
+                       | BIT_FRMCNT_RST,
+                       csi_dev->regbase + CSI_CSICR3);
+
+       __raw_writel(CSICR1_RESET_VAL, csi_dev->regbase + CSI_CSICR1);
+       __raw_writel(CSICR2_RESET_VAL, csi_dev->regbase + CSI_CSICR2);
+       __raw_writel(CSICR3_RESET_VAL, csi_dev->regbase + CSI_CSICR3);
+}
+
+static void csisw_reset(struct mx6s_csi_dev *csi_dev)
+{
+       int cr1, cr3, cr18, isr;
+
+       /* Disable csi  */
+       cr18 = csi_read(csi_dev, CSI_CSICR18);
+       cr18 &= ~BIT_CSI_ENABLE;
+       csi_write(csi_dev, cr18, CSI_CSICR18);
+
+       /* Clear RX FIFO */
+       cr1 = csi_read(csi_dev, CSI_CSICR1);
+       csi_write(csi_dev, cr1 & ~BIT_FCC, CSI_CSICR1);
+       cr1 = csi_read(csi_dev, CSI_CSICR1);
+       csi_write(csi_dev, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1);
+
+       /* DMA reflash */
+       cr3 = csi_read(csi_dev, CSI_CSICR3);
+       cr3 |= BIT_DMA_REFLASH_RFF | BIT_FRMCNT_RST;
+       csi_write(csi_dev, cr3, CSI_CSICR3);
+
+       msleep(2);
+
+       cr1 = csi_read(csi_dev, CSI_CSICR1);
+       csi_write(csi_dev, cr1 | BIT_FCC, CSI_CSICR1);
+
+       isr = csi_read(csi_dev, CSI_CSISR);
+       csi_write(csi_dev, isr, CSI_CSISR);
+
+       /* Ensable csi  */
+       cr18 |= BIT_CSI_ENABLE;
+       csi_write(csi_dev, cr18, CSI_CSICR18);
+}
+
+/*!
+ * csi_init_interface
+ *    Init csi interface
+ */
+static void csi_init_interface(struct mx6s_csi_dev *csi_dev)
+{
+       unsigned int val = 0;
+       unsigned int imag_para;
+
+       val |= BIT_SOF_POL;
+       val |= BIT_REDGE;
+       val |= BIT_GCLK_MODE;
+       val |= BIT_HSYNC_POL;
+       val |= BIT_FCC;
+       val |= 1 << SHIFT_MCLKDIV;
+       val |= BIT_MCLKEN;
+       __raw_writel(val, csi_dev->regbase + CSI_CSICR1);
+
+       imag_para = (640 << 16) | 960;
+       __raw_writel(imag_para, csi_dev->regbase + CSI_CSIIMAG_PARA);
+
+       val = BIT_DMA_REFLASH_RFF;
+       __raw_writel(val, csi_dev->regbase + CSI_CSICR3);
+}
+
+static void csi_enable_int(struct mx6s_csi_dev *csi_dev, int arg)
+{
+       unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
+
+       cr1 |= BIT_SOF_INTEN;
+       cr1 |= BIT_RFF_OR_INT;
+       if (arg == 1) {
+               /* still capture needs DMA intterrupt */
+               cr1 |= BIT_FB1_DMA_DONE_INTEN;
+               cr1 |= BIT_FB2_DMA_DONE_INTEN;
+       }
+       __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
+}
+
+static void csi_disable_int(struct mx6s_csi_dev *csi_dev)
+{
+       unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
+
+       cr1 &= ~BIT_SOF_INTEN;
+       cr1 &= ~BIT_RFF_OR_INT;
+       cr1 &= ~BIT_FB1_DMA_DONE_INTEN;
+       cr1 &= ~BIT_FB2_DMA_DONE_INTEN;
+       __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
+}
+
+static void csi_enable(struct mx6s_csi_dev *csi_dev, int arg)
+{
+       unsigned long cr = __raw_readl(csi_dev->regbase + CSI_CSICR18);
+
+       if (arg == 1)
+               cr |= BIT_CSI_ENABLE;
+       else
+               cr &= ~BIT_CSI_ENABLE;
+       __raw_writel(cr, csi_dev->regbase + CSI_CSICR18);
+}
+
+static void csi_buf_stride_set(struct mx6s_csi_dev *csi_dev, u32 stride)
+{
+       __raw_writel(stride, csi_dev->regbase + CSI_CSIFBUF_PARA);
+}
+
+static void csi_deinterlace_enable(struct mx6s_csi_dev *csi_dev, bool enable)
+{
+       unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
+
+       if (enable == true)
+               cr18 |= BIT_DEINTERLACE_EN;
+       else
+               cr18 &= ~BIT_DEINTERLACE_EN;
+
+       __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
+}
+
+static void csi_deinterlace_mode(struct mx6s_csi_dev *csi_dev, int mode)
+{
+       unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
+
+       if (mode == V4L2_STD_NTSC)
+               cr18 |= BIT_NTSC_EN;
+       else
+               cr18 &= ~BIT_NTSC_EN;
+
+       __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
+}
+
+static void csi_tvdec_enable(struct mx6s_csi_dev *csi_dev, bool enable)
+{
+       unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
+       unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
+
+       if (enable == true) {
+               cr18 |= (BIT_TVDECODER_IN_EN |
+                               BIT_BASEADDR_SWITCH_EN |
+                               BIT_BASEADDR_SWITCH_SEL |
+                               BIT_BASEADDR_CHG_ERR_EN);
+               cr1 |= BIT_CCIR_MODE;
+               cr1 &= ~(BIT_SOF_POL | BIT_REDGE);
+       } else {
+               cr18 &= ~(BIT_TVDECODER_IN_EN |
+                               BIT_BASEADDR_SWITCH_EN |
+                               BIT_BASEADDR_SWITCH_SEL |
+                               BIT_BASEADDR_CHG_ERR_EN);
+               cr1 &= ~BIT_CCIR_MODE;
+               cr1 |= BIT_SOF_POL | BIT_REDGE;
+       }
+
+       __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
+       __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
+}
+
+static void csi_dmareq_rff_enable(struct mx6s_csi_dev *csi_dev)
+{
+       unsigned long cr3 = __raw_readl(csi_dev->regbase + CSI_CSICR3);
+       unsigned long cr2 = __raw_readl(csi_dev->regbase + CSI_CSICR2);
+
+       /* Burst Type of DMA Transfer from RxFIFO. INCR16 */
+       cr2 |= 0xC0000000;
+
+       cr3 |= BIT_DMA_REQ_EN_RFF;
+       cr3 |= BIT_HRESP_ERR_EN;
+       cr3 &= ~BIT_RXFF_LEVEL;
+       cr3 |= 0x2 << 4;
+
+       __raw_writel(cr3, csi_dev->regbase + CSI_CSICR3);
+       __raw_writel(cr2, csi_dev->regbase + CSI_CSICR2);
+}
+
+static void csi_dmareq_rff_disable(struct mx6s_csi_dev *csi_dev)
+{
+       unsigned long cr3 = __raw_readl(csi_dev->regbase + CSI_CSICR3);
+
+       cr3 &= ~BIT_DMA_REQ_EN_RFF;
+       cr3 &= ~BIT_HRESP_ERR_EN;
+       __raw_writel(cr3, csi_dev->regbase + CSI_CSICR3);
+}
+
+static void csi_set_imagpara(struct mx6s_csi_dev *csi,
+                                       int width, int height)
+{
+       int imag_para = 0;
+       unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3);
+
+       imag_para = (width << 16) | height;
+       __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA);
+
+       /* reflash the embeded DMA controller */
+       __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3);
+}
+
+static void csi_error_recovery(struct mx6s_csi_dev *csi_dev)
+{
+       u32 cr1, cr3, cr18;
+       /* software reset */
+
+       /* Disable csi  */
+       cr18 = csi_read(csi_dev, CSI_CSICR18);
+       cr18 &= ~BIT_CSI_ENABLE;
+       csi_write(csi_dev, cr18, CSI_CSICR18);
+
+       /* Clear RX FIFO */
+       cr1 = csi_read(csi_dev, CSI_CSICR1);
+       csi_write(csi_dev, cr1 & ~BIT_FCC, CSI_CSICR1);
+       cr1 = csi_read(csi_dev, CSI_CSICR1);
+       csi_write(csi_dev, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1);
+
+       cr1 = csi_read(csi_dev, CSI_CSICR1);
+       csi_write(csi_dev, cr1 | BIT_FCC, CSI_CSICR1);
+
+       /* DMA reflash */
+       cr3 = csi_read(csi_dev, CSI_CSICR3);
+       cr3 |= BIT_DMA_REFLASH_RFF;
+       csi_write(csi_dev, cr3, CSI_CSICR3);
+
+       /* Ensable csi  */
+       cr18 |= BIT_CSI_ENABLE;
+       csi_write(csi_dev, cr18, CSI_CSICR18);
+}
+
+/*
+ *  Videobuf operations
+ */
+static int mx6s_videobuf_setup(struct vb2_queue *vq,
+                       unsigned int *count, unsigned int *num_planes,
+                       unsigned int sizes[], struct device *alloc_devs[])
+{
+       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
+
+       dev_dbg(csi_dev->dev, "count=%d, size=%d\n", *count, sizes[0]);
+
+       alloc_devs[0] = csi_dev->dev;
+
+       sizes[0] = csi_dev->pix.sizeimage;
+
+       pr_debug("size=%d\n", sizes[0]);
+       if (0 == *count)
+               *count = 32;
+       if (!*num_planes &&
+           sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
+               *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0];
+
+       *num_planes = 1;
+
+       return 0;
+}
+
+static int mx6s_videobuf_prepare(struct vb2_buffer *vb)
+{
+       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vb->vb2_queue);
+       int ret = 0;
+
+       dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+
+#ifdef DEBUG
+       /*
+        * This can be useful if you want to see if we actually fill
+        * the buffer with something
+        */
+       if (vb2_plane_vaddr(vb, 0))
+               memset((void *)vb2_plane_vaddr(vb, 0),
+                      0xaa, vb2_get_plane_payload(vb, 0));
+#endif
+
+       vb2_set_plane_payload(vb, 0, csi_dev->pix.sizeimage);
+       if (vb2_plane_vaddr(vb, 0) &&
+           vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       return 0;
+
+out:
+       return ret;
+}
+
+static void mx6s_videobuf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct mx6s_buffer *buf = container_of(vbuf, struct mx6s_buffer, vb);
+       unsigned long flags;
+
+       dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+
+       spin_lock_irqsave(&csi_dev->slock, flags);
+
+       list_add_tail(&buf->internal.queue, &csi_dev->capture);
+
+       spin_unlock_irqrestore(&csi_dev->slock, flags);
+}
+
+static void mx6s_update_csi_buf(struct mx6s_csi_dev *csi_dev,
+                                unsigned long phys, int bufnum)
+{
+       if (bufnum == 1)
+               csi_write(csi_dev, phys, CSI_CSIDMASA_FB2);
+       else
+               csi_write(csi_dev, phys, CSI_CSIDMASA_FB1);
+}
+
+static void mx6s_csi_init(struct mx6s_csi_dev *csi_dev)
+{
+       csi_clk_enable(csi_dev);
+       csihw_reset(csi_dev);
+       csi_init_interface(csi_dev);
+       csi_dmareq_rff_disable(csi_dev);
+}
+
+static void mx6s_csi_deinit(struct mx6s_csi_dev *csi_dev)
+{
+       csihw_reset(csi_dev);
+       csi_init_interface(csi_dev);
+       csi_dmareq_rff_disable(csi_dev);
+       csi_clk_disable(csi_dev);
+}
+
+static int mx6s_csi_enable(struct mx6s_csi_dev *csi_dev)
+{
+       struct v4l2_pix_format *pix = &csi_dev->pix;
+       unsigned long flags;
+       unsigned long val;
+       int timeout, timeout2;
+
+       csisw_reset(csi_dev);
+
+       if (pix->field == V4L2_FIELD_INTERLACED)
+               csi_tvdec_enable(csi_dev, true);
+
+       /* For mipi csi input only */
+       if (csi_dev->csi_mux_mipi == true) {
+               csi_dmareq_rff_enable(csi_dev);
+               csi_enable_int(csi_dev, 1);
+               csi_enable(csi_dev, 1);
+               return 0;
+       }
+
+       local_irq_save(flags);
+       for (timeout = 10000000; timeout > 0; timeout--) {
+               if (csi_read(csi_dev, CSI_CSISR) & BIT_SOF_INT) {
+                       val = csi_read(csi_dev, CSI_CSICR3);
+                       csi_write(csi_dev, val | BIT_DMA_REFLASH_RFF,
+                                       CSI_CSICR3);
+                       /* Wait DMA reflash done */
+                       for (timeout2 = 1000000; timeout2 > 0; timeout2--) {
+                               if (csi_read(csi_dev, CSI_CSICR3) &
+                                       BIT_DMA_REFLASH_RFF)
+                                       cpu_relax();
+                               else
+                                       break;
+                       }
+                       if (timeout2 <= 0) {
+                               pr_err("timeout when wait for reflash done.\n");
+                               local_irq_restore(flags);
+                               return -ETIME;
+                       }
+                       /* For imx6sl csi, DMA FIFO will auto start when sensor ready to work,
+                        * so DMA should enable right after FIFO reset, otherwise dma will lost data
+                        * and image will split.
+                        */
+                       csi_dmareq_rff_enable(csi_dev);
+                       csi_enable_int(csi_dev, 1);
+                       csi_enable(csi_dev, 1);
+                       break;
+               } else
+                       cpu_relax();
+       }
+       if (timeout <= 0) {
+               pr_err("timeout when wait for SOF\n");
+               local_irq_restore(flags);
+               return -ETIME;
+       }
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static void mx6s_csi_disable(struct mx6s_csi_dev *csi_dev)
+{
+       struct v4l2_pix_format *pix = &csi_dev->pix;
+
+       csi_dmareq_rff_disable(csi_dev);
+       csi_disable_int(csi_dev);
+
+       /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */
+       csi_write(csi_dev, 0, CSI_CSIDMASA_FB1);
+       csi_write(csi_dev, 0, CSI_CSIDMASA_FB2);
+
+       csi_buf_stride_set(csi_dev, 0);
+
+       if (pix->field == V4L2_FIELD_INTERLACED) {
+               csi_deinterlace_enable(csi_dev, false);
+               csi_tvdec_enable(csi_dev, false);
+       }
+
+       csi_enable(csi_dev, 0);
+}
+
+static int mx6s_configure_csi(struct mx6s_csi_dev *csi_dev)
+{
+       struct v4l2_pix_format *pix = &csi_dev->pix;
+       u32 cr1, cr18;
+       u32 width;
+
+       if (pix->field == V4L2_FIELD_INTERLACED) {
+               csi_deinterlace_enable(csi_dev, true);
+               csi_buf_stride_set(csi_dev, csi_dev->pix.width);
+               csi_deinterlace_mode(csi_dev, csi_dev->std);
+       } else {
+               csi_deinterlace_enable(csi_dev, false);
+               csi_buf_stride_set(csi_dev, 0);
+       }
+
+       switch (csi_dev->fmt->pixelformat) {
+       case V4L2_PIX_FMT_YUV32:
+       case V4L2_PIX_FMT_SBGGR8:
+               width = pix->width;
+               break;
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_YUYV:
+               if (csi_dev->csi_mux_mipi == true)
+                       width = pix->width;
+               else
+                       /* For parallel 8-bit sensor input */
+                       width = pix->width * 2;
+               break;
+       default:
+               pr_debug("   case not supported\n");
+               return -EINVAL;
+       }
+       csi_set_imagpara(csi_dev, width, pix->height);
+
+       if (csi_dev->csi_mux_mipi == true) {
+               cr1 = csi_read(csi_dev, CSI_CSICR1);
+               cr1 &= ~BIT_GCLK_MODE;
+               csi_write(csi_dev, cr1, CSI_CSICR1);
+
+               cr18 = csi_read(csi_dev, CSI_CSICR18);
+               cr18 &= BIT_MIPI_DATA_FORMAT_MASK;
+               cr18 |= BIT_DATA_FROM_MIPI;
+
+               switch (csi_dev->fmt->pixelformat) {
+               case V4L2_PIX_FMT_UYVY:
+               case V4L2_PIX_FMT_YUYV:
+                       cr18 |= BIT_MIPI_DATA_FORMAT_YUV422_8B;
+                       break;
+               case V4L2_PIX_FMT_SBGGR8:
+                       cr18 |= BIT_MIPI_DATA_FORMAT_RAW8;
+                       break;
+               default:
+                       pr_debug("   fmt not supported\n");
+                       return -EINVAL;
+               }
+
+               csi_write(csi_dev, cr18, CSI_CSICR18);
+       }
+       return 0;
+}
+
+static int mx6s_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
+       struct vb2_buffer *vb;
+       struct mx6s_buffer *buf;
+       unsigned long phys;
+       unsigned long flags;
+
+       if (count < 2)
+               return -ENOBUFS;
+
+       /*
+        * I didn't manage to properly enable/disable
+        * a per frame basis during running transfers,
+        * thus we allocate a buffer here and use it to
+        * discard frames when no buffer is available.
+        * Feel free to work on this ;)
+        */
+       csi_dev->discard_size = csi_dev->pix.sizeimage;
+       csi_dev->discard_buffer = dma_alloc_coherent(csi_dev->v4l2_dev.dev,
+                                       PAGE_ALIGN(csi_dev->discard_size),
+                                       &csi_dev->discard_buffer_dma,
+                                       GFP_DMA | GFP_KERNEL);
+       if (!csi_dev->discard_buffer)
+               return -ENOMEM;
+
+       spin_lock_irqsave(&csi_dev->slock, flags);
+
+       csi_dev->buf_discard[0].discard = true;
+       list_add_tail(&csi_dev->buf_discard[0].queue,
+                     &csi_dev->discard);
+
+       csi_dev->buf_discard[1].discard = true;
+       list_add_tail(&csi_dev->buf_discard[1].queue,
+                     &csi_dev->discard);
+
+       /* csi buf 0 */
+       buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
+                              internal.queue);
+       buf->internal.bufnum = 0;
+       vb = &buf->vb.vb2_buf;
+       vb->state = VB2_BUF_STATE_ACTIVE;
+
+       phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+       mx6s_update_csi_buf(csi_dev, phys, buf->internal.bufnum);
+       list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
+
+       /* csi buf 1 */
+       buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
+                              internal.queue);
+       buf->internal.bufnum = 1;
+       vb = &buf->vb.vb2_buf;
+       vb->state = VB2_BUF_STATE_ACTIVE;
+
+       phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+       mx6s_update_csi_buf(csi_dev, phys, buf->internal.bufnum);
+       list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
+
+       spin_unlock_irqrestore(&csi_dev->slock, flags);
+
+       return mx6s_csi_enable(csi_dev);
+}
+
+static void mx6s_stop_streaming(struct vb2_queue *vq)
+{
+       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
+       unsigned long flags;
+       struct mx6s_buffer *buf, *tmp;
+       void *b;
+
+       mx6s_csi_disable(csi_dev);
+
+       spin_lock_irqsave(&csi_dev->slock, flags);
+
+       list_for_each_entry_safe(buf, tmp,
+                               &csi_dev->active_bufs, internal.queue) {
+               list_del_init(&buf->internal.queue);
+               if (buf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+       }
+
+       list_for_each_entry_safe(buf, tmp,
+                               &csi_dev->capture, internal.queue) {
+               list_del_init(&buf->internal.queue);
+               if (buf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+       }
+
+       INIT_LIST_HEAD(&csi_dev->capture);
+       INIT_LIST_HEAD(&csi_dev->active_bufs);
+       INIT_LIST_HEAD(&csi_dev->discard);
+
+       b = csi_dev->discard_buffer;
+       csi_dev->discard_buffer = NULL;
+
+       spin_unlock_irqrestore(&csi_dev->slock, flags);
+
+       dma_free_coherent(csi_dev->v4l2_dev.dev,
+                               csi_dev->discard_size, b,
+                               csi_dev->discard_buffer_dma);
+}
+
+static struct vb2_ops mx6s_videobuf_ops = {
+       .queue_setup     = mx6s_videobuf_setup,
+       .buf_prepare     = mx6s_videobuf_prepare,
+       .buf_queue       = mx6s_videobuf_queue,
+       .wait_prepare    = vb2_ops_wait_prepare,
+       .wait_finish     = vb2_ops_wait_finish,
+       .start_streaming = mx6s_start_streaming,
+       .stop_streaming  = mx6s_stop_streaming,
+};
+
+static void mx6s_csi_frame_done(struct mx6s_csi_dev *csi_dev,
+               int bufnum, bool err)
+{
+       struct mx6s_buf_internal *ibuf;
+       struct mx6s_buffer *buf;
+       struct vb2_buffer *vb;
+       unsigned long phys;
+
+       ibuf = list_first_entry(&csi_dev->active_bufs, struct mx6s_buf_internal,
+                              queue);
+
+       if (ibuf->discard) {
+               /*
+                * Discard buffer must not be returned to user space.
+                * Just return it to the discard queue.
+                */
+               list_move_tail(csi_dev->active_bufs.next, &csi_dev->discard);
+       } else {
+               buf = mx6s_ibuf_to_buf(ibuf);
+
+               vb = &buf->vb.vb2_buf;
+               phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+               if (bufnum == 1) {
+                       if (csi_read(csi_dev, CSI_CSIDMASA_FB2) != phys) {
+                               dev_err(csi_dev->dev, "%lx != %x\n", phys,
+                                       csi_read(csi_dev, CSI_CSIDMASA_FB2));
+                       }
+               } else {
+                       if (csi_read(csi_dev, CSI_CSIDMASA_FB1) != phys) {
+                               dev_err(csi_dev->dev, "%lx != %x\n", phys,
+                                       csi_read(csi_dev, CSI_CSIDMASA_FB1));
+                       }
+               }
+               dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb,
+                               vb2_plane_vaddr(vb, 0),
+                               vb2_get_plane_payload(vb, 0));
+
+               list_del_init(&buf->internal.queue);
+               vb->timestamp =ktime_get_ns();
+               to_vb2_v4l2_buffer(vb)->sequence = csi_dev->frame_count;
+               if (err)
+                       vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+               else
+                       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+       }
+
+       csi_dev->frame_count++;
+
+       /* Config discard buffer to active_bufs */
+       if (list_empty(&csi_dev->capture)) {
+               if (list_empty(&csi_dev->discard)) {
+                       dev_warn(csi_dev->dev,
+                                       "%s: trying to access empty discard list\n",
+                                       __func__);
+                       return;
+               }
+
+               ibuf = list_first_entry(&csi_dev->discard,
+                                       struct mx6s_buf_internal, queue);
+               ibuf->bufnum = bufnum;
+
+               list_move_tail(csi_dev->discard.next, &csi_dev->active_bufs);
+
+               mx6s_update_csi_buf(csi_dev,
+                                       csi_dev->discard_buffer_dma, bufnum);
+               return;
+       }
+
+       buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
+                              internal.queue);
+
+       buf->internal.bufnum = bufnum;
+
+       list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
+
+       vb = &buf->vb.vb2_buf;
+       vb->state = VB2_BUF_STATE_ACTIVE;
+
+       phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+       mx6s_update_csi_buf(csi_dev, phys, bufnum);
+}
+
+static irqreturn_t mx6s_csi_irq_handler(int irq, void *data)
+{
+       struct mx6s_csi_dev *csi_dev =  data;
+       unsigned long status;
+       u32 cr3, cr18;
+
+       spin_lock(&csi_dev->slock);
+
+       status = csi_read(csi_dev, CSI_CSISR);
+       csi_write(csi_dev, status, CSI_CSISR);
+
+       if (list_empty(&csi_dev->active_bufs)) {
+               dev_warn(csi_dev->dev,
+                               "%s: called while active list is empty\n",
+                               __func__);
+
+               spin_unlock(&csi_dev->slock);
+               return IRQ_HANDLED;
+       }
+
+       if (status & BIT_RFF_OR_INT) {
+               dev_warn(csi_dev->dev, "%s Rx fifo overflow\n", __func__);
+               if (*csi_dev->rx_fifo_rst)
+                       csi_error_recovery(csi_dev);
+       }
+
+       if (status & BIT_HRESP_ERR_INT) {
+               dev_warn(csi_dev->dev, "%s Hresponse error detected\n",
+                       __func__);
+               csi_error_recovery(csi_dev);
+       }
+
+       if (status & BIT_ADDR_CH_ERR_INT) {
+               /* Disable csi  */
+               cr18 = csi_read(csi_dev, CSI_CSICR18);
+               cr18 &= ~BIT_CSI_ENABLE;
+               csi_write(csi_dev, cr18, CSI_CSICR18);
+
+               /* DMA reflash */
+               cr3 = csi_read(csi_dev, CSI_CSICR3);
+               cr3 |= BIT_DMA_REFLASH_RFF;
+               csi_write(csi_dev, cr3, CSI_CSICR3);
+
+               /* Ensable csi  */
+               cr18 |= BIT_CSI_ENABLE;
+               csi_write(csi_dev, cr18, CSI_CSICR18);
+
+               pr_debug("base address switching Change Err.\n");
+       }
+
+       if ((status & BIT_DMA_TSF_DONE_FB1) &&
+               (status & BIT_DMA_TSF_DONE_FB2)) {
+               /* For both FB1 and FB2 interrupter bits set case,
+                * CSI DMA is work in one of FB1 and FB2 buffer,
+                * but software can not know the state.
+                * Skip it to avoid base address updated
+                * when csi work in field0 and field1 will write to
+                * new base address.
+                * PDM TKT230775 */
+               pr_debug("Skip two frames\n");
+       } else if (status & BIT_DMA_TSF_DONE_FB1) {
+               mx6s_csi_frame_done(csi_dev, 0, false);
+       } else if (status & BIT_DMA_TSF_DONE_FB2) {
+               mx6s_csi_frame_done(csi_dev, 1, false);
+       }
+
+       spin_unlock(&csi_dev->slock);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * File operations for the device
+ */
+static int mx6s_csi_open(struct file *file)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+       struct vb2_queue *q = &csi_dev->vb2_vidq;
+       int ret = 0;
+
+       file->private_data = csi_dev;
+
+       if (mutex_lock_interruptible(&csi_dev->lock))
+               return -ERESTARTSYS;
+
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_MMAP | VB2_USERPTR;
+       q->drv_priv = csi_dev;
+       q->ops = &mx6s_videobuf_ops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->buf_struct_size = sizeof(struct mx6s_buffer);
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       q->lock = &csi_dev->lock;
+
+       ret = vb2_queue_init(q);
+       if (ret < 0)
+               goto unlock;
+
+       pm_runtime_get_sync(csi_dev->dev);
+
+       request_bus_freq(BUS_FREQ_HIGH);
+
+       v4l2_subdev_call(sd, core, s_power, 1);
+       mx6s_csi_init(csi_dev);
+
+       mutex_unlock(&csi_dev->lock);
+
+       return ret;
+unlock:
+       mutex_unlock(&csi_dev->lock);
+       return ret;
+}
+
+static int mx6s_csi_close(struct file *file)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+
+       mutex_lock(&csi_dev->lock);
+
+       vb2_queue_release(&csi_dev->vb2_vidq);
+
+       mx6s_csi_deinit(csi_dev);
+       v4l2_subdev_call(sd, core, s_power, 0);
+
+       mutex_unlock(&csi_dev->lock);
+
+       file->private_data = NULL;
+
+       release_bus_freq(BUS_FREQ_HIGH);
+
+       pm_runtime_put_sync_suspend(csi_dev->dev);
+       return 0;
+}
+
+static ssize_t mx6s_csi_read(struct file *file, char __user *buf,
+                              size_t count, loff_t *ppos)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       int ret;
+
+       dev_dbg(csi_dev->dev, "read called, buf %p\n", buf);
+
+       mutex_lock(&csi_dev->lock);
+       ret = vb2_read(&csi_dev->vb2_vidq, buf, count, ppos,
+                               file->f_flags & O_NONBLOCK);
+       mutex_unlock(&csi_dev->lock);
+       return ret;
+}
+
+static int mx6s_csi_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       int ret;
+
+       if (mutex_lock_interruptible(&csi_dev->lock))
+               return -ERESTARTSYS;
+       ret = vb2_mmap(&csi_dev->vb2_vidq, vma);
+       mutex_unlock(&csi_dev->lock);
+
+       pr_debug("vma start=0x%08lx, size=%ld, ret=%d\n",
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+               ret);
+
+       return ret;
+}
+
+static struct v4l2_file_operations mx6s_csi_fops = {
+       .owner          = THIS_MODULE,
+       .open           = mx6s_csi_open,
+       .release        = mx6s_csi_close,
+       .read           = mx6s_csi_read,
+       .poll           = vb2_fop_poll,
+       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+       .mmap           = mx6s_csi_mmap,
+};
+
+/*
+ * Video node IOCTLs
+ */
+static int mx6s_vidioc_enum_input(struct file *file, void *priv,
+                                struct v4l2_input *inp)
+{
+       if (inp->index != 0)
+               return -EINVAL;
+
+       /* default is camera */
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       strcpy(inp->name, "Camera");
+
+       return 0;
+}
+
+static int mx6s_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+
+       return 0;
+}
+
+static int mx6s_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       if (i > 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int mx6s_vidioc_querystd(struct file *file, void *priv, v4l2_std_id *a)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+
+       return v4l2_subdev_call(sd, video, querystd, a);
+}
+
+static int mx6s_vidioc_s_std(struct file *file, void *priv, v4l2_std_id a)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+
+       return v4l2_subdev_call(sd, video, s_std, a);
+}
+
+static int mx6s_vidioc_g_std(struct file *file, void *priv, v4l2_std_id *a)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+
+       return v4l2_subdev_call(sd, video, g_std, a);
+}
+
+static int mx6s_vidioc_reqbufs(struct file *file, void *priv,
+                             struct v4l2_requestbuffers *p)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+       WARN_ON(priv != file->private_data);
+
+       return vb2_reqbufs(&csi_dev->vb2_vidq, p);
+}
+
+static int mx6s_vidioc_querybuf(struct file *file, void *priv,
+                              struct v4l2_buffer *p)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       int ret;
+
+       WARN_ON(priv != file->private_data);
+
+       ret = vb2_querybuf(&csi_dev->vb2_vidq, p);
+
+       if (!ret) {
+               /* return physical address */
+               struct vb2_buffer *vb = csi_dev->vb2_vidq.bufs[p->index];
+               if (p->flags & V4L2_BUF_FLAG_MAPPED)
+                       p->m.offset = vb2_dma_contig_plane_dma_addr(vb, 0);
+       }
+       return ret;
+}
+
+static int mx6s_vidioc_qbuf(struct file *file, void *priv,
+                          struct v4l2_buffer *p)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+       WARN_ON(priv != file->private_data);
+
+       return vb2_qbuf(&csi_dev->vb2_vidq, p);
+}
+
+static int mx6s_vidioc_dqbuf(struct file *file, void *priv,
+                           struct v4l2_buffer *p)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+       WARN_ON(priv != file->private_data);
+
+       return vb2_dqbuf(&csi_dev->vb2_vidq, p, file->f_flags & O_NONBLOCK);
+}
+
+static int mx6s_vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                      struct v4l2_fmtdesc *f)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+       struct v4l2_subdev_mbus_code_enum code = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .index = f->index,
+       };
+       struct mx6s_fmt *fmt;
+       int ret;
+
+       WARN_ON(priv != file->private_data);
+
+       ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
+       if (ret < 0) {
+               /* no more formats */
+               dev_dbg(csi_dev->dev, "No more fmt\n");
+               return -EINVAL;
+       }
+
+       fmt = format_by_mbus(code.code);
+       if (!fmt) {
+               dev_err(csi_dev->dev, "mbus (0x%08x) invalid.\n", code.code);
+               return -EINVAL;
+       }
+
+       strlcpy(f->description, fmt->name, sizeof(f->description));
+       f->pixelformat = fmt->pixelformat;
+
+       return 0;
+}
+
+static int mx6s_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                     struct v4l2_format *f)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
+       struct mx6s_fmt *fmt;
+       int ret;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (!fmt) {
+               dev_err(csi_dev->dev, "Fourcc format (0x%08x) invalid.",
+                       f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       if (f->fmt.pix.width == 0 || f->fmt.pix.height == 0) {
+               dev_err(csi_dev->dev, "width %d, height %d is too small.\n",
+                       f->fmt.pix.width, f->fmt.pix.height);
+               return -EINVAL;
+       }
+
+       v4l2_fill_mbus_format(&format.format, pix, fmt->mbus_code);
+       ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
+       v4l2_fill_pix_format(pix, &format.format);
+
+       if (pix->field != V4L2_FIELD_INTERLACED)
+               pix->field = V4L2_FIELD_NONE;
+
+       pix->sizeimage = fmt->bpp * pix->height * pix->width;
+       pix->bytesperline = fmt->bpp * pix->width;
+
+       return ret;
+}
+
+/*
+ * The real work of figuring out a workable format.
+ */
+
+static int mx6s_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                                   struct v4l2_format *f)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       int ret;
+
+       ret = mx6s_vidioc_try_fmt_vid_cap(file, csi_dev, f);
+       if (ret < 0)
+               return ret;
+
+       csi_dev->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
+       csi_dev->mbus_code     = csi_dev->fmt->mbus_code;
+       csi_dev->pix.width     = f->fmt.pix.width;
+       csi_dev->pix.height    = f->fmt.pix.height;
+       csi_dev->pix.sizeimage = f->fmt.pix.sizeimage;
+       csi_dev->pix.field     = f->fmt.pix.field;
+       csi_dev->type          = f->type;
+       dev_dbg(csi_dev->dev, "set to pixelformat '%4.6s'\n",
+                       (char *)&csi_dev->fmt->name);
+
+       /* Config csi */
+       mx6s_configure_csi(csi_dev);
+
+       return 0;
+}
+
+static int mx6s_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                   struct v4l2_format *f)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+       WARN_ON(priv != file->private_data);
+
+       f->fmt.pix = csi_dev->pix;
+
+       return 0;
+}
+
+static int mx6s_vidioc_querycap(struct file *file, void  *priv,
+                              struct v4l2_capability *cap)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+       WARN_ON(priv != file->private_data);
+
+       /* cap->name is set by the friendly caller:-> */
+       strlcpy(cap->driver, MX6S_CAM_DRV_NAME, sizeof(cap->driver));
+       strlcpy(cap->card, MX6S_CAM_DRIVER_DESCRIPTION, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(csi_dev->dev));
+
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int mx6s_vidioc_streamon(struct file *file, void *priv,
+                              enum v4l2_buf_type i)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+       int ret;
+
+       WARN_ON(priv != file->private_data);
+
+       if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       ret = vb2_streamon(&csi_dev->vb2_vidq, i);
+       if (!ret)
+               v4l2_subdev_call(sd, video, s_stream, 1);
+
+       return ret;
+}
+
+static int mx6s_vidioc_streamoff(struct file *file, void *priv,
+                               enum v4l2_buf_type i)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+
+       WARN_ON(priv != file->private_data);
+
+       if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       /*
+        * This calls buf_release from host driver's videobuf_queue_ops for all
+        * remaining buffers. When the last buffer is freed, stop capture
+        */
+       vb2_streamoff(&csi_dev->vb2_vidq, i);
+
+       v4l2_subdev_call(sd, video, s_stream, 0);
+
+       return 0;
+}
+
+static int mx6s_vidioc_cropcap(struct file *file, void *fh,
+                             struct v4l2_cropcap *a)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       dev_dbg(csi_dev->dev, "VIDIOC_CROPCAP not implemented\n");
+
+       return 0;
+}
+
+static int mx6s_vidioc_g_crop(struct file *file, void *priv,
+                            struct v4l2_crop *a)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       dev_dbg(csi_dev->dev, "VIDIOC_G_CROP not implemented\n");
+
+       return 0;
+}
+
+static int mx6s_vidioc_s_crop(struct file *file, void *priv,
+                            const struct v4l2_crop *a)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       dev_dbg(csi_dev->dev, "VIDIOC_S_CROP not implemented\n");
+
+       return 0;
+}
+
+static int mx6s_vidioc_g_parm(struct file *file, void *priv,
+                            struct v4l2_streamparm *a)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+
+       return v4l2_subdev_call(sd, video, g_parm, a);
+}
+
+static int mx6s_vidioc_s_parm(struct file *file, void *priv,
+                               struct v4l2_streamparm *a)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+
+       return v4l2_subdev_call(sd, video, s_parm, a);
+}
+
+static int mx6s_vidioc_enum_framesizes(struct file *file, void *priv,
+                                        struct v4l2_frmsizeenum *fsize)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+       struct mx6s_fmt *fmt;
+       struct v4l2_subdev_frame_size_enum fse = {
+               .index = fsize->index,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
+       int ret;
+
+       fmt = format_by_fourcc(fsize->pixel_format);
+       if (fmt->pixelformat != fsize->pixel_format)
+               return -EINVAL;
+       fse.code = fmt->mbus_code;
+
+       ret = v4l2_subdev_call(sd, pad, enum_frame_size, NULL, &fse);
+       if (ret)
+               return ret;
+
+       if (fse.min_width == fse.max_width &&
+           fse.min_height == fse.max_height) {
+               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               fsize->discrete.width = fse.min_width;
+               fsize->discrete.height = fse.min_height;
+               return 0;
+       }
+
+       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+       fsize->stepwise.min_width = fse.min_width;
+       fsize->stepwise.max_width = fse.max_width;
+       fsize->stepwise.min_height = fse.min_height;
+       fsize->stepwise.max_height = fse.max_height;
+       fsize->stepwise.step_width = 1;
+       fsize->stepwise.step_height = 1;
+
+       return 0;
+}
+
+static int mx6s_vidioc_enum_frameintervals(struct file *file, void *priv,
+               struct v4l2_frmivalenum *interval)
+{
+       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+       struct v4l2_subdev *sd = csi_dev->sd;
+       struct mx6s_fmt *fmt;
+       struct v4l2_subdev_frame_interval_enum fie = {
+               .index = interval->index,
+               .width = interval->width,
+               .height = interval->height,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
+       int ret;
+
+       fmt = format_by_fourcc(interval->pixel_format);
+       if (fmt->pixelformat != interval->pixel_format)
+               return -EINVAL;
+       fie.code = fmt->mbus_code;
+
+       ret = v4l2_subdev_call(sd, pad, enum_frame_interval, NULL, &fie);
+       if (ret)
+               return ret;
+       interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       interval->discrete = fie.interval;
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops mx6s_csi_ioctl_ops = {
+       .vidioc_querycap          = mx6s_vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = mx6s_vidioc_enum_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = mx6s_vidioc_try_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = mx6s_vidioc_g_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = mx6s_vidioc_s_fmt_vid_cap,
+       .vidioc_cropcap       = mx6s_vidioc_cropcap,
+       .vidioc_s_crop        = mx6s_vidioc_s_crop,
+       .vidioc_g_crop        = mx6s_vidioc_g_crop,
+       .vidioc_reqbufs       = mx6s_vidioc_reqbufs,
+       .vidioc_querybuf      = mx6s_vidioc_querybuf,
+       .vidioc_qbuf          = mx6s_vidioc_qbuf,
+       .vidioc_dqbuf         = mx6s_vidioc_dqbuf,
+       .vidioc_g_std         = mx6s_vidioc_g_std,
+       .vidioc_s_std         = mx6s_vidioc_s_std,
+       .vidioc_querystd      = mx6s_vidioc_querystd,
+       .vidioc_enum_input    = mx6s_vidioc_enum_input,
+       .vidioc_g_input       = mx6s_vidioc_g_input,
+       .vidioc_s_input       = mx6s_vidioc_s_input,
+       .vidioc_streamon      = mx6s_vidioc_streamon,
+       .vidioc_streamoff     = mx6s_vidioc_streamoff,
+       .vidioc_g_parm        = mx6s_vidioc_g_parm,
+       .vidioc_s_parm        = mx6s_vidioc_s_parm,
+       .vidioc_enum_framesizes = mx6s_vidioc_enum_framesizes,
+       .vidioc_enum_frameintervals = mx6s_vidioc_enum_frameintervals,
+};
+
+static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
+                           struct v4l2_subdev *subdev,
+                           struct v4l2_async_subdev *asd)
+{
+       struct mx6s_csi_dev *csi_dev = notifier_to_mx6s_dev(notifier);
+
+       /* Find platform data for this sensor subdev */
+       if (csi_dev->asd.match.of.node == subdev->dev->of_node)
+               csi_dev->sd = subdev;
+
+       if (subdev == NULL)
+               return -EINVAL;
+
+       v4l2_info(&csi_dev->v4l2_dev, "Registered sensor subdevice: %s\n",
+                 subdev->name);
+
+       return 0;
+}
+
+static int mx6s_csi_mux_sel(struct mx6s_csi_dev *csi_dev)
+{
+       struct device_node *np = csi_dev->dev->of_node;
+       struct device_node *node;
+       phandle phandle;
+       u32 out_val[3];
+       int ret;
+
+       ret = of_property_read_u32_array(np, "csi-mux-mipi", out_val, 3);
+       if (ret) {
+               dev_dbg(csi_dev->dev, "no csi-mux-mipi property found\n");
+               csi_dev->csi_mux_mipi = false;
+       } else {
+               phandle = *out_val;
+
+               node = of_find_node_by_phandle(phandle);
+               if (!node) {
+                       dev_dbg(csi_dev->dev, "not find gpr node by phandle\n");
+                       ret = PTR_ERR(node);
+               }
+               csi_dev->csi_mux.gpr = syscon_node_to_regmap(node);
+               if (IS_ERR(csi_dev->csi_mux.gpr)) {
+                       dev_err(csi_dev->dev, "failed to get gpr regmap\n");
+                       ret = PTR_ERR(csi_dev->csi_mux.gpr);
+               }
+               of_node_put(node);
+               if (ret < 0)
+                       return ret;
+
+               csi_dev->csi_mux.req_gpr = out_val[1];
+               csi_dev->csi_mux.req_bit = out_val[2];
+
+               regmap_update_bits(csi_dev->csi_mux.gpr, csi_dev->csi_mux.req_gpr,
+                       1 << csi_dev->csi_mux.req_bit, 1 << csi_dev->csi_mux.req_bit);
+
+               csi_dev->csi_mux_mipi = true;
+       }
+       return ret;
+}
+
+static int mx6sx_register_subdevs(struct mx6s_csi_dev *csi_dev)
+{
+       struct device_node *parent = csi_dev->dev->of_node;
+       struct device_node *node, *port, *rem;
+       int ret;
+
+       /* Attach sensors linked to csi receivers */
+       for_each_available_child_of_node(parent, node) {
+               if (of_node_cmp(node->name, "port"))
+                       continue;
+
+               /* The csi node can have only port subnode. */
+               port = of_get_next_child(node, NULL);
+               if (!port)
+                       continue;
+               rem = of_graph_get_remote_port_parent(port);
+               of_node_put(port);
+               if (rem == NULL) {
+                       v4l2_info(&csi_dev->v4l2_dev,
+                                               "Remote device at %s not found\n",
+                                               port->full_name);
+                       return -1;
+               }
+
+               csi_dev->asd.match_type = V4L2_ASYNC_MATCH_OF;
+               csi_dev->asd.match.of.node = rem;
+               csi_dev->async_subdevs[0] = &csi_dev->asd;
+
+               of_node_put(rem);
+               break;
+       }
+
+       csi_dev->subdev_notifier.subdevs = csi_dev->async_subdevs;
+       csi_dev->subdev_notifier.num_subdevs = 1;
+       csi_dev->subdev_notifier.bound = subdev_notifier_bound;
+
+       ret = v4l2_async_notifier_register(&csi_dev->v4l2_dev,
+                                       &csi_dev->subdev_notifier);
+       if (ret)
+               dev_err(csi_dev->dev,
+                                       "Error register async notifier regoster\n");
+
+       return ret;
+}
+
+static int mx6s_csi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id;
+       struct mx6s_csi_dev *csi_dev;
+       struct video_device *vdev;
+       struct resource *res;
+       int ret = 0;
+
+       dev_dbg(dev, "initialising\n");
+
+       /* Prepare our private structure */
+       csi_dev = devm_kzalloc(dev, sizeof(struct mx6s_csi_dev), GFP_ATOMIC);
+       if (!csi_dev) {
+               dev_err(dev, "Can't allocate private structure\n");
+               return -ENODEV;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       csi_dev->irq = platform_get_irq(pdev, 0);
+       if (res == NULL || csi_dev->irq < 0) {
+               dev_err(dev, "Missing platform resources data\n");
+               return -ENODEV;
+       }
+
+       csi_dev->regbase = devm_ioremap_resource(dev, res);
+       if (IS_ERR(csi_dev->regbase)) {
+               dev_err(dev, "Failed platform resources map\n");
+               return -ENODEV;
+       }
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&csi_dev->capture);
+       INIT_LIST_HEAD(&csi_dev->active_bufs);
+       INIT_LIST_HEAD(&csi_dev->discard);
+
+       csi_dev->clk_disp_axi = devm_clk_get(dev, "disp-axi");
+       if (IS_ERR(csi_dev->clk_disp_axi)) {
+               dev_err(dev, "Could not get csi axi clock\n");
+               return -ENODEV;
+       }
+
+       csi_dev->clk_disp_dcic = devm_clk_get(dev, "disp_dcic");
+       if (IS_ERR(csi_dev->clk_disp_dcic)) {
+               dev_err(dev, "Could not get disp dcic clock\n");
+               return -ENODEV;
+       }
+
+       csi_dev->clk_csi_mclk = devm_clk_get(dev, "csi_mclk");
+       if (IS_ERR(csi_dev->clk_csi_mclk)) {
+               dev_err(dev, "Could not get csi mclk clock\n");
+               return -ENODEV;
+       }
+
+       csi_dev->dev = dev;
+
+       mx6s_csi_mux_sel(csi_dev);
+
+       of_id = of_match_node(mx6s_csi_dt_ids, csi_dev->dev->of_node);
+       if (!of_id)
+               return -EINVAL;
+       csi_dev->rx_fifo_rst = of_id->data;
+
+       snprintf(csi_dev->v4l2_dev.name,
+                sizeof(csi_dev->v4l2_dev.name), "CSI");
+
+       ret = v4l2_device_register(dev, &csi_dev->v4l2_dev);
+       if (ret < 0) {
+               dev_err(dev, "v4l2_device_register() failed: %d\n", ret);
+               return -ENODEV;
+       }
+
+       /* initialize locks */
+       mutex_init(&csi_dev->lock);
+       spin_lock_init(&csi_dev->slock);
+
+       /* Allocate memory for video device */
+       vdev = video_device_alloc();
+       if (vdev == NULL) {
+               ret = -ENOMEM;
+               goto err_vdev;
+       }
+
+       snprintf(vdev->name, sizeof(vdev->name), "mx6s-csi");
+
+       vdev->v4l2_dev          = &csi_dev->v4l2_dev;
+       vdev->fops                      = &mx6s_csi_fops;
+       vdev->ioctl_ops         = &mx6s_csi_ioctl_ops;
+       vdev->release           = video_device_release;
+       vdev->lock                      = &csi_dev->lock;
+
+       vdev->queue = &csi_dev->vb2_vidq;
+
+       csi_dev->vdev = vdev;
+
+       video_set_drvdata(csi_dev->vdev, csi_dev);
+       mutex_lock(&csi_dev->lock);
+
+       ret = video_register_device(csi_dev->vdev, VFL_TYPE_GRABBER, -1);
+       if (ret < 0) {
+               video_device_release(csi_dev->vdev);
+               mutex_unlock(&csi_dev->lock);
+               goto err_vdev;
+       }
+
+       /* install interrupt handler */
+       if (devm_request_irq(dev, csi_dev->irq, mx6s_csi_irq_handler,
+                               0, "csi", (void *)csi_dev)) {
+               mutex_unlock(&csi_dev->lock);
+               dev_err(dev, "Request CSI IRQ failed.\n");
+               ret = -ENODEV;
+               goto err_irq;
+       }
+
+       mutex_unlock(&csi_dev->lock);
+
+       ret = mx6sx_register_subdevs(csi_dev);
+       if (ret < 0)
+               goto err_irq;
+
+       pm_runtime_enable(csi_dev->dev);
+       return 0;
+
+err_irq:
+       video_unregister_device(csi_dev->vdev);
+err_vdev:
+       v4l2_device_unregister(&csi_dev->v4l2_dev);
+       return ret;
+}
+
+static int mx6s_csi_remove(struct platform_device *pdev)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+       struct mx6s_csi_dev *csi_dev =
+                               container_of(v4l2_dev, struct mx6s_csi_dev, v4l2_dev);
+
+       v4l2_async_notifier_unregister(&csi_dev->subdev_notifier);
+
+       video_unregister_device(csi_dev->vdev);
+       v4l2_device_unregister(&csi_dev->v4l2_dev);
+
+       pm_runtime_disable(csi_dev->dev);
+       return 0;
+}
+
+static int mx6s_csi_runtime_suspend(struct device *dev)
+{
+       dev_dbg(dev, "csi v4l2 busfreq high release.\n");
+       return 0;
+}
+
+static int mx6s_csi_runtime_resume(struct device *dev)
+{
+       dev_dbg(dev, "csi v4l2 busfreq high request.\n");
+       return 0;
+}
+
+static const struct dev_pm_ops mx6s_csi_pm_ops = {
+       SET_RUNTIME_PM_OPS(mx6s_csi_runtime_suspend, mx6s_csi_runtime_resume, NULL)
+};
+
+static const u8 mx6s_fifo_rst = true;
+static const u8 mx6sl_fifo_rst = false;
+
+static const struct of_device_id mx6s_csi_dt_ids[] = {
+       { .compatible = "fsl,imx6s-csi",
+         .data = &mx6s_fifo_rst,
+       },
+       { .compatible = "fsl,imx6sl-csi",
+         .data = &mx6sl_fifo_rst,
+       },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mx6s_csi_dt_ids);
+
+static struct platform_driver mx6s_csi_driver = {
+       .driver         = {
+               .name   = MX6S_CAM_DRV_NAME,
+               .of_match_table = of_match_ptr(mx6s_csi_dt_ids),
+               .pm = &mx6s_csi_pm_ops,
+       },
+       .probe  = mx6s_csi_probe,
+       .remove = mx6s_csi_remove,
+};
+
+module_platform_driver(mx6s_csi_driver);
+
+MODULE_DESCRIPTION("i.MX6Sx SoC Camera Host driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MX6S_CAM_VERSION);
diff --git a/drivers/media/platform/mxc/capture/mxc_mipi_csi.c b/drivers/media/platform/mxc/capture/mxc_mipi_csi.c
new file mode 100644 (file)
index 0000000..4371d65
--- /dev/null
@@ -0,0 +1,1248 @@
+/*
+ * Freescale i.MX7 SoC series MIPI-CSI V3.3 receiver driver
+ *
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/*
+ * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver
+ *
+ * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-of.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-device.h>
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+#define CSIS_DRIVER_NAME       "mxc_mipi-csi"
+#define CSIS_SUBDEV_NAME       CSIS_DRIVER_NAME
+#define CSIS_MAX_ENTITIES      2
+#define CSIS0_MAX_LANES                4
+#define CSIS1_MAX_LANES                2
+
+#define MIPI_CSIS_DEF_PIX_WIDTH        640
+#define MIPI_CSIS_DEF_PIX_HEIGHT       480
+
+/* Register map definition */
+
+/* CSIS version */
+#define MIPI_CSIS_VERSION              0x00
+
+/* CSIS common control */
+#define MIPI_CSIS_CMN_CTRL                     0x04
+#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW       (1 << 16)
+#define MIPI_CSIS_CMN_CTRL_INTER_MODE          (1 << 10)
+#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET      8
+#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK                (3 << 8)
+#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL  (1 << 2)
+#define MIPI_CSIS_CMN_CTRL_RESET               (1 << 1)
+#define MIPI_CSIS_CMN_CTRL_ENABLE              (1 << 0)
+
+/* CSIS clock control */
+#define MIPI_CSIS_CLK_CTRL             0x08
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x)        (x << 28)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x)        (x << 24)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x)        (x << 20)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x)        (x << 16)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK      (0xf << 4)
+#define MIPI_CSIS_CLK_CTRL_WCLK_SRC            (1 << 0)
+
+/* CSIS Interrupt mask */
+#define MIPI_CSIS_INTMSK                       0x10
+#define MIPI_CSIS_INTMSK_EVEN_BEFORE   (1 << 31)
+#define MIPI_CSIS_INTMSK_EVEN_AFTER    (1 << 30)
+#define MIPI_CSIS_INTMSK_ODD_BEFORE    (1 << 29)
+#define MIPI_CSIS_INTMSK_ODD_AFTER     (1 << 28)
+#define MIPI_CSIS_INTMSK_FRAME_START   (1 << 24)
+#define MIPI_CSIS_INTMSK_FRAME_END     (1 << 20)
+#define MIPI_CSIS_INTMSK_ERR_SOT_HS    (1 << 16)
+#define MIPI_CSIS_INTMSK_ERR_LOST_FS   (1 << 12)
+#define MIPI_CSIS_INTMSK_ERR_LOST_FE   (1 << 8)
+#define MIPI_CSIS_INTMSK_ERR_OVER              (1 << 4)
+#define MIPI_CSIS_INTMSK_ERR_WRONG_CFG (1 << 3)
+#define MIPI_CSIS_INTMSK_ERR_ECC               (1 << 2)
+#define MIPI_CSIS_INTMSK_ERR_CRC               (1 << 1)
+#define MIPI_CSIS_INTMSK_ERR_UNKNOWN   (1 << 0)
+
+/* CSIS Interrupt source */
+#define MIPI_CSIS_INTSRC                       0x14
+#define MIPI_CSIS_INTSRC_EVEN_BEFORE   (1 << 31)
+#define MIPI_CSIS_INTSRC_EVEN_AFTER    (1 << 30)
+#define MIPI_CSIS_INTSRC_EVEN          (0x3 << 30)
+#define MIPI_CSIS_INTSRC_ODD_BEFORE    (1 << 29)
+#define MIPI_CSIS_INTSRC_ODD_AFTER     (1 << 28)
+#define MIPI_CSIS_INTSRC_ODD                   (0x3 << 28)
+#define MIPI_CSIS_INTSRC_NON_IMAGE_DATA        (0xf << 28)
+#define MIPI_CSIS_INTSRC_FRAME_START   (1 << 24)
+#define MIPI_CSIS_INTSRC_FRAME_END     (1 << 20)
+#define MIPI_CSIS_INTSRC_ERR_SOT_HS    (1 << 16)
+#define MIPI_CSIS_INTSRC_ERR_LOST_FS   (1 << 12)
+#define MIPI_CSIS_INTSRC_ERR_LOST_FE   (1 << 8)
+#define MIPI_CSIS_INTSRC_ERR_OVER              (1 << 4)
+#define MIPI_CSIS_INTSRC_ERR_WRONG_CFG (1 << 3)
+#define MIPI_CSIS_INTSRC_ERR_ECC               (1 << 2)
+#define MIPI_CSIS_INTSRC_ERR_CRC               (1 << 1)
+#define MIPI_CSIS_INTSRC_ERR_UNKNOWN   (1 << 0)
+#define MIPI_CSIS_INTSRC_ERRORS                0xfffff
+
+/* D-PHY status control */
+#define MIPI_CSIS_DPHYSTATUS           0x20
+#define MIPI_CSIS_DPHYSTATUS_ULPS_DAT                  (1 << 8)
+#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_DAT             (1 << 4)
+#define MIPI_CSIS_DPHYSTATUS_ULPS_CLK                  (1 << 1)
+#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_CLK             (1 << 0)
+
+/* D-PHY common control */
+#define MIPI_CSIS_DPHYCTRL             0x24
+#define MIPI_CSIS_DPHYCTRL_HSS_MASK                    (0xff << 24)
+#define MIPI_CSIS_DPHYCTRL_HSS_OFFSET          24
+#define MIPI_CSIS_DPHYCTRL_SCLKS_MASK          (0x3 << 22)
+#define MIPI_CSIS_DPHYCTRL_SCLKS_OFFSET                22
+#define MIPI_CSIS_DPHYCTRL_DPDN_SWAP_CLK       (1 << 6)
+#define MIPI_CSIS_DPHYCTRL_DPDN_SWAP_DAT       (1 << 5)
+#define MIPI_CSIS_DPHYCTRL_ENABLE_DAT          (1 << 1)
+#define MIPI_CSIS_DPHYCTRL_ENABLE_CLK          (1 << 0)
+#define MIPI_CSIS_DPHYCTRL_ENABLE                      (0x1f << 0)
+
+/* D-PHY Master and Slave Control register Low */
+#define MIPI_CSIS_DPHYBCTRL_L          0x30
+/* D-PHY Master and Slave Control register High */
+#define MIPI_CSIS_DPHYBCTRL_H          0x34
+/* D-PHY Slave Control register Low */
+#define MIPI_CSIS_DPHYSCTRL_L          0x38
+/* D-PHY Slave Control register High */
+#define MIPI_CSIS_DPHYSCTRL_H          0x3c
+
+
+/* ISP Configuration register */
+#define MIPI_CSIS_ISPCONFIG_CH0                        0x40
+#define MIPI_CSIS_ISPCONFIG_CH1                        0x50
+#define MIPI_CSIS_ISPCONFIG_CH2                        0x60
+#define MIPI_CSIS_ISPCONFIG_CH3                        0x70
+
+#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK    (0xff << 24)
+#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x)     (x << 24)
+#define MIPI_CSIS_ISPCFG_DOUBLE_CMPNT        (1 << 12)
+#define MIPI_CSIS_ISPCFG_ALIGN_32BIT         (1 << 11)
+#define MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT   (0x1e << 2)
+#define MIPI_CSIS_ISPCFG_FMT_RAW8              (0x2a << 2)
+#define MIPI_CSIS_ISPCFG_FMT_RAW10             (0x2b << 2)
+#define MIPI_CSIS_ISPCFG_FMT_RAW12             (0x2c << 2)
+/* User defined formats, x = 1...4 */
+#define MIPI_CSIS_ISPCFG_FMT_USER(x)   ((0x30 + x - 1) << 2)
+#define MIPI_CSIS_ISPCFG_FMT_MASK              (0x3f << 2)
+
+/* ISP Image Resolution register */
+#define MIPI_CSIS_ISPRESOL_CH0                 0x44
+#define MIPI_CSIS_ISPRESOL_CH1                 0x54
+#define MIPI_CSIS_ISPRESOL_CH2                 0x64
+#define MIPI_CSIS_ISPRESOL_CH3                 0x74
+#define CSIS_MAX_PIX_WIDTH             0xffff
+#define CSIS_MAX_PIX_HEIGHT            0xffff
+
+/* ISP SYNC register */
+#define MIPI_CSIS_ISPSYNC_CH0                  0x48
+#define MIPI_CSIS_ISPSYNC_CH1                  0x58
+#define MIPI_CSIS_ISPSYNC_CH2                  0x68
+#define MIPI_CSIS_ISPSYNC_CH3                  0x78
+
+#define MIPI_CSIS_ISPSYNC_HSYNC_LINTV_OFFSET   18
+#define MIPI_CSIS_ISPSYNC_VSYNC_SINTV_OFFSET   12
+#define MIPI_CSIS_ISPSYNC_VSYNC_EINTV_OFFSET   0
+
+/* Non-image packet data buffers */
+#define MIPI_CSIS_PKTDATA_ODD          0x2000
+#define MIPI_CSIS_PKTDATA_EVEN         0x3000
+#define MIPI_CSIS_PKTDATA_SIZE         SZ_4K
+
+#define DEFAULT_SCLK_CSIS_FREQ 166000000UL
+
+enum {
+       ST_POWERED      = 1,
+       ST_STREAMING    = 2,
+       ST_SUSPENDED    = 4,
+};
+
+struct mipi_csis_event {
+       u32 mask;
+       const char * const name;
+       unsigned int counter;
+};
+
+static const struct mipi_csis_event mipi_csis_events[] = {
+       /* Errors */
+       { MIPI_CSIS_INTSRC_ERR_SOT_HS,  "SOT Error" },
+       { MIPI_CSIS_INTSRC_ERR_LOST_FS, "Lost Frame Start Error" },
+       { MIPI_CSIS_INTSRC_ERR_LOST_FE, "Lost Frame End Error" },
+       { MIPI_CSIS_INTSRC_ERR_OVER,    "FIFO Overflow Error" },
+       { MIPI_CSIS_INTSRC_ERR_ECC,     "ECC Error" },
+       { MIPI_CSIS_INTSRC_ERR_CRC,     "CRC Error" },
+       { MIPI_CSIS_INTSRC_ERR_UNKNOWN, "Unknown Error" },
+       /* Non-image data receive events */
+       { MIPI_CSIS_INTSRC_EVEN_BEFORE, "Non-image data before even frame" },
+       { MIPI_CSIS_INTSRC_EVEN_AFTER,  "Non-image data after even frame" },
+       { MIPI_CSIS_INTSRC_ODD_BEFORE,  "Non-image data before odd frame" },
+       { MIPI_CSIS_INTSRC_ODD_AFTER,   "Non-image data after odd frame" },
+       /* Frame start/end */
+       { MIPI_CSIS_INTSRC_FRAME_START, "Frame Start" },
+       { MIPI_CSIS_INTSRC_FRAME_END,   "Frame End" },
+};
+#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events)
+
+struct csis_pktbuf {
+       u32 *data;
+       unsigned int len;
+};
+
+struct csis_hw_reset {
+       struct regmap *src;
+       u8 req_src;
+       u8 rst_bit;
+};
+
+/**
+ * struct csi_state - the driver's internal state data structure
+ * @lock: mutex serializing the subdev and power management operations,
+ *        protecting @format and @flags members
+ * @sd: v4l2_subdev associated with CSIS device instance
+ * @index: the hardware instance index
+ * @pdev: CSIS platform device
+ * @phy: pointer to the CSIS generic PHY
+ * @regs: mmaped I/O registers memory
+ * @supplies: CSIS regulator supplies
+ * @clock: CSIS clocks
+ * @irq: requested s5p-mipi-csis irq number
+ * @flags: the state variable for power and streaming control
+ * @clock_frequency: device bus clock frequency
+ * @hs_settle: HS-RX settle time
+ * @clk_settle: Clk settle time
+ * @num_lanes: number of MIPI-CSI data lanes used
+ * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
+ * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
+ * @csis_fmt: current CSIS pixel format
+ * @format: common media bus format for the source and sink pad
+ * @slock: spinlock protecting structure members below
+ * @pkt_buf: the frame embedded (non-image) data buffer
+ * @events: MIPI-CSIS event (error) counters
+ */
+struct csi_state {
+       struct mutex lock;
+       struct device           *dev;
+       struct v4l2_subdev mipi_sd;
+       struct v4l2_subdev *sensor_sd;
+       struct v4l2_device      v4l2_dev;
+
+       u8 index;
+       struct platform_device *pdev;
+       struct phy *phy;
+       void __iomem *regs;
+       struct clk *mipi_clk;
+       struct clk *phy_clk;
+       int irq;
+       u32 flags;
+
+       u32 clk_frequency;
+       u32 hs_settle;
+       u32 clk_settle;
+       u32 num_lanes;
+       u32 max_num_lanes;
+       u8 wclk_ext;
+
+       const struct csis_pix_format *csis_fmt;
+       struct v4l2_mbus_framefmt format;
+
+       spinlock_t slock;
+       struct csis_pktbuf pkt_buf;
+       struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
+
+       struct v4l2_async_subdev    asd;
+       struct v4l2_async_notifier  subdev_notifier;
+       struct v4l2_async_subdev    *async_subdevs[2];
+
+       struct csis_hw_reset hw_reset;
+       struct regulator     *mipi_phy_regulator;
+};
+
+/**
+ * struct csis_pix_format - CSIS pixel format description
+ * @pix_width_alignment: horizontal pixel alignment, width will be
+ *                       multiple of 2^pix_width_alignment
+ * @code: corresponding media bus code
+ * @fmt_reg: MIPI_CSIS_CONFIG register value
+ * @data_alignment: MIPI-CSI data alignment in bits
+ */
+struct csis_pix_format {
+       unsigned int pix_width_alignment;
+       u32 code;
+       u32 fmt_reg;
+       u8 data_alignment;
+};
+
+static const struct csis_pix_format mipi_csis_formats[] = {
+       {
+               .code = MEDIA_BUS_FMT_YUYV8_2X8,
+               .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT,
+               .data_alignment = 16,
+       }, {
+               .code = MEDIA_BUS_FMT_VYUY8_2X8,
+               .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT,
+               .data_alignment = 16,
+       }, {
+               .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8,
+               .data_alignment = 8,
+       }
+};
+
+#define mipi_csis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
+#define mipi_csis_read(__csis, __r) readl(__csis->regs + __r)
+
+static struct csi_state *mipi_sd_to_csi_state(struct v4l2_subdev *sdev)
+{
+       return container_of(sdev, struct csi_state, mipi_sd);
+}
+
+static inline struct csi_state
+                               *notifier_to_mipi_dev(struct v4l2_async_notifier *n)
+{
+       return container_of(n, struct csi_state, subdev_notifier);
+}
+
+static const struct csis_pix_format *find_csis_format(u32 code)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++)
+               if (code == mipi_csis_formats[i].code)
+                       return &mipi_csis_formats[i];
+       return NULL;
+}
+
+static void mipi_csis_enable_interrupts(struct csi_state *state, bool on)
+{
+       u32 val = mipi_csis_read(state, MIPI_CSIS_INTMSK);
+       if (on)
+               val |= 0xf00fffff;
+       else
+               val &= ~0xf00fffff;
+       mipi_csis_write(state, MIPI_CSIS_INTMSK, val);
+}
+
+static void mipi_csis_sw_reset(struct csi_state *state)
+{
+       u32 val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+
+       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val | MIPI_CSIS_CMN_CTRL_RESET);
+       udelay(10);
+}
+
+static int mipi_csis_phy_init(struct csi_state *state)
+{
+       int ret;
+
+       state->mipi_phy_regulator = devm_regulator_get(state->dev,
+                               "mipi-phy");
+
+       ret = regulator_set_voltage(state->mipi_phy_regulator,
+                       1000000, 1000000);
+
+       return ret;
+}
+
+static int mipi_csis_phy_reset(struct csi_state *state)
+{
+       struct device_node *np = state->dev->of_node;
+       struct device_node *node;
+       phandle phandle;
+       u32 out_val[3];
+       int ret;
+
+       ret = of_property_read_u32_array(np, "csis-phy-reset", out_val, 3);
+       if (ret) {
+               dev_dbg(state->dev, "no csis-hw-reset property found\n");
+       } else {
+               phandle = *out_val;
+
+               node = of_find_node_by_phandle(phandle);
+               if (!node) {
+                       dev_dbg(state->dev, "not find src node by phandle\n");
+                       ret = PTR_ERR(node);
+               }
+               state->hw_reset.src = syscon_node_to_regmap(node);
+               if (IS_ERR(state->hw_reset.src)) {
+                       dev_err(state->dev, "failed to get src regmap\n");
+                       ret = PTR_ERR(state->hw_reset.src);
+               }
+               of_node_put(node);
+               if (ret < 0)
+                       return ret;
+
+               state->hw_reset.req_src = out_val[1];
+               state->hw_reset.rst_bit = out_val[2];
+
+               /* reset mipi phy */
+               regmap_update_bits(state->hw_reset.src, state->hw_reset.req_src,
+                       1 << state->hw_reset.rst_bit, 1 << state->hw_reset.rst_bit);
+               msleep(20);
+               regmap_update_bits(state->hw_reset.src, state->hw_reset.req_src,
+                       1 << state->hw_reset.rst_bit, 0);
+
+       }
+       return ret;
+}
+
+static void mipi_csis_system_enable(struct csi_state *state, int on)
+{
+       u32 val, mask;
+
+       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+       if (on)
+               val |= MIPI_CSIS_CMN_CTRL_ENABLE;
+       else
+               val &= ~MIPI_CSIS_CMN_CTRL_ENABLE;
+       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
+
+       val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL);
+       val &= ~MIPI_CSIS_DPHYCTRL_ENABLE;
+       if (on) {
+               mask = (1 << (state->num_lanes + 1)) - 1;
+               val |= (mask & MIPI_CSIS_DPHYCTRL_ENABLE);
+       }
+       mipi_csis_write(state, MIPI_CSIS_DPHYCTRL, val);
+}
+
+/* Called with the state.lock mutex held */
+static void __mipi_csis_set_format(struct csi_state *state)
+{
+       struct v4l2_mbus_framefmt *mf = &state->format;
+       u32 val;
+
+       v4l2_dbg(1, debug, &state->mipi_sd, "fmt: %#x, %d x %d\n",
+                mf->code, mf->width, mf->height);
+
+       /* Color format */
+       val = mipi_csis_read(state, MIPI_CSIS_ISPCONFIG_CH0);
+       val = (val & ~MIPI_CSIS_ISPCFG_FMT_MASK) | state->csis_fmt->fmt_reg;
+       mipi_csis_write(state, MIPI_CSIS_ISPCONFIG_CH0, val);
+
+       /* Pixel resolution */
+       val = mf->width | (mf->height << 16);
+       mipi_csis_write(state, MIPI_CSIS_ISPRESOL_CH0, val);
+}
+
+static void mipi_csis_set_hsync_settle(struct csi_state *state,
+                                                               int hs_settle, int clk_settle)
+{
+       u32 val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL);
+
+       val = (val & ~MIPI_CSIS_DPHYCTRL_HSS_MASK) |
+                               (hs_settle << 24) | (clk_settle << 22);
+
+       mipi_csis_write(state, MIPI_CSIS_DPHYCTRL, val);
+}
+
+static void mipi_csis_set_params(struct csi_state *state)
+{
+       u32 val;
+
+       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+       val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
+       val |= (state->num_lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
+       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
+
+       __mipi_csis_set_format(state);
+
+       mipi_csis_set_hsync_settle(state, state->hs_settle, state->clk_settle);
+
+       val = mipi_csis_read(state, MIPI_CSIS_ISPCONFIG_CH0);
+       if (state->csis_fmt->data_alignment == 32)
+               val |= MIPI_CSIS_ISPCFG_ALIGN_32BIT;
+       else /* Normal output */
+               val &= ~MIPI_CSIS_ISPCFG_ALIGN_32BIT;
+       mipi_csis_write(state, MIPI_CSIS_ISPCONFIG_CH0, val);
+
+       val = (0 << MIPI_CSIS_ISPSYNC_HSYNC_LINTV_OFFSET) |
+               (0 << MIPI_CSIS_ISPSYNC_VSYNC_SINTV_OFFSET) |
+               (0 << MIPI_CSIS_ISPSYNC_VSYNC_EINTV_OFFSET);
+       mipi_csis_write(state, MIPI_CSIS_ISPSYNC_CH0, val);
+
+       val = mipi_csis_read(state, MIPI_CSIS_CLK_CTRL);
+       val &= ~MIPI_CSIS_CLK_CTRL_WCLK_SRC;
+       if (state->wclk_ext)
+               val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC;
+       val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15);
+       val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK;
+       mipi_csis_write(state, MIPI_CSIS_CLK_CTRL, val);
+
+       mipi_csis_write(state, MIPI_CSIS_DPHYBCTRL_L, 0x1f4);
+       mipi_csis_write(state, MIPI_CSIS_DPHYBCTRL_H, 0);
+
+       /* Update the shadow register. */
+       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW |
+                                       MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL);
+}
+
+static void mipi_csis_clk_enable(struct csi_state *state)
+{
+       clk_prepare_enable(state->mipi_clk);
+       clk_prepare_enable(state->phy_clk);
+}
+
+static void mipi_csis_clk_disable(struct csi_state *state)
+{
+       clk_disable_unprepare(state->mipi_clk);
+       clk_disable_unprepare(state->phy_clk);
+}
+
+static int mipi_csis_clk_get(struct csi_state *state)
+{
+       struct device *dev = &state->pdev->dev;
+       int ret = true;
+
+       state->mipi_clk = devm_clk_get(dev, "mipi_clk");
+       if (IS_ERR(state->mipi_clk)) {
+               dev_err(dev, "Could not get mipi csi clock\n");
+               return -ENODEV;
+       }
+
+       state->phy_clk = devm_clk_get(dev, "phy_clk");
+       if (IS_ERR(state->phy_clk)) {
+               dev_err(dev, "Could not get mipi phy clock\n");
+               return -ENODEV;
+       }
+
+       /* Set clock rate */
+       if (state->clk_frequency)
+               ret = clk_set_rate(state->mipi_clk,
+                                  state->clk_frequency);
+       else
+               dev_WARN(dev, "No clock frequency specified!\n");
+       if (ret < 0) {
+               dev_err(dev, "set rate filed, rate=%d\n", state->clk_frequency);
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static void dump_regs(struct csi_state *state, const char *label)
+{
+       struct {
+               u32 offset;
+               const char * const name;
+       } registers[] = {
+               { 0x00, "CTRL" },
+               { 0x04, "DPHYCTRL" },
+               { 0x08, "CONFIG" },
+               { 0x0c, "DPHYSTS" },
+               { 0x10, "INTMSK" },
+               { 0x2c, "RESOL" },
+               { 0x38, "SDW_CONFIG" },
+       };
+       u32 i;
+
+       v4l2_info(&state->mipi_sd, "--- %s ---\n", label);
+
+       for (i = 0; i < ARRAY_SIZE(registers); i++) {
+               u32 cfg = mipi_csis_read(state, registers[i].offset);
+               v4l2_info(&state->mipi_sd, "%10s: 0x%08x\n", registers[i].name, cfg);
+       }
+}
+
+static void mipi_csis_start_stream(struct csi_state *state)
+{
+       mipi_csis_sw_reset(state);
+       mipi_csis_set_params(state);
+       mipi_csis_system_enable(state, true);
+       mipi_csis_enable_interrupts(state, true);
+}
+
+static void mipi_csis_stop_stream(struct csi_state *state)
+{
+       mipi_csis_enable_interrupts(state, false);
+       mipi_csis_system_enable(state, false);
+}
+
+static void mipi_csis_clear_counters(struct csi_state *state)
+{
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&state->slock, flags);
+       for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++)
+               state->events[i].counter = 0;
+       spin_unlock_irqrestore(&state->slock, flags);
+}
+
+static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
+{
+       int i = non_errors ? MIPI_CSIS_NUM_EVENTS : MIPI_CSIS_NUM_EVENTS - 4;
+       unsigned long flags;
+
+       spin_lock_irqsave(&state->slock, flags);
+
+       for (i--; i >= 0; i--) {
+               if (state->events[i].counter > 0 || debug)
+                       v4l2_info(&state->mipi_sd, "%s events: %d\n",
+                                 state->events[i].name,
+                                 state->events[i].counter);
+       }
+       spin_unlock_irqrestore(&state->slock, flags);
+}
+
+/*
+ * V4L2 subdev operations
+ */
+static int mipi_csis_s_power(struct v4l2_subdev *mipi_sd, int on)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       struct device *dev = &state->pdev->dev;
+
+       v4l2_subdev_call(state->sensor_sd, core, s_power, on);
+
+       if (on)
+               return pm_runtime_get_sync(dev);
+
+       return pm_runtime_put_sync(dev);
+}
+
+static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       int ret = 0;
+
+       v4l2_dbg(1, debug, mipi_sd, "%s: %d, state: 0x%x\n",
+                __func__, enable, state->flags);
+
+       if (enable) {
+               mipi_csis_clear_counters(state);
+               ret = pm_runtime_get_sync(&state->pdev->dev);
+               if (ret && ret != 1)
+                       return ret;
+       }
+
+       mutex_lock(&state->lock);
+       if (enable) {
+               if (state->flags & ST_SUSPENDED) {
+                       ret = -EBUSY;
+                       goto unlock;
+               }
+               mipi_csis_start_stream(state);
+               v4l2_subdev_call(state->sensor_sd, video, s_stream, true);
+               state->flags |= ST_STREAMING;
+       } else {
+               v4l2_subdev_call(state->sensor_sd, video, s_stream, false);
+               mipi_csis_stop_stream(state);
+               state->flags &= ~ST_STREAMING;
+               if (debug > 0)
+                       mipi_csis_log_counters(state, true);
+       }
+unlock:
+       mutex_unlock(&state->lock);
+       if (!enable)
+               pm_runtime_put(&state->pdev->dev);
+
+       return ret == 1 ? 0 : ret;
+}
+
+static int mipi_csis_enum_mbus_code(struct v4l2_subdev *mipi_sd,
+                                   struct v4l2_subdev_pad_config *cfg,
+                                   struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       struct v4l2_subdev *sensor_sd = state->sensor_sd;
+       struct csis_pix_format const *csis_fmt;
+       int ret;
+
+       ret = v4l2_subdev_call(sensor_sd, pad, enum_mbus_code, NULL, code);
+       if (ret < 0)
+               return -EINVAL;
+
+       csis_fmt = find_csis_format(code->code);
+       if (csis_fmt == NULL) {
+               dev_err(state->dev, "format not match\n");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
+                            struct v4l2_subdev_pad_config *cfg,
+                            struct v4l2_subdev_format *format)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       struct v4l2_subdev *sensor_sd = state->sensor_sd;
+       struct csis_pix_format const *csis_fmt;
+       struct v4l2_mbus_framefmt *mf  = &format->format;
+
+       if (format->pad)
+               return -EINVAL;
+
+       csis_fmt = find_csis_format(mf->code);
+       if (csis_fmt == NULL)
+               csis_fmt = &mipi_csis_formats[0];
+
+       v4l2_subdev_call(sensor_sd, pad, set_fmt, NULL, format);
+
+       mf->code = csis_fmt->code;
+       v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
+                             csis_fmt->pix_width_alignment,
+                             &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
+                             0);
+
+       if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+               return 0;
+
+       state->format.code = mf->code;
+       state->format.width = mf->width;
+       state->format.height = mf->height;
+
+       mutex_lock(&state->lock);
+       state->csis_fmt = csis_fmt;
+       mutex_unlock(&state->lock);
+
+       return 0;
+}
+
+static int mipi_csis_get_fmt(struct v4l2_subdev *mipi_sd,
+                            struct v4l2_subdev_pad_config *cfg,
+                            struct v4l2_subdev_format *format)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+       if (format->pad)
+               return -EINVAL;
+
+       return v4l2_subdev_call(sensor_sd, pad, get_fmt, NULL, format);
+}
+
+static int mipi_csis_s_rx_buffer(struct v4l2_subdev *mipi_sd, void *buf,
+                              unsigned int *size)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       unsigned long flags;
+
+       *size = min_t(unsigned int, *size, MIPI_CSIS_PKTDATA_SIZE);
+
+       spin_lock_irqsave(&state->slock, flags);
+       state->pkt_buf.data = buf;
+       state->pkt_buf.len = *size;
+       spin_unlock_irqrestore(&state->slock, flags);
+
+       return 0;
+}
+
+static int mipi_csis_s_parm(struct v4l2_subdev *mipi_sd, struct v4l2_streamparm *a)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+       return v4l2_subdev_call(sensor_sd, video, s_parm, a);
+}
+
+static int mipi_csis_g_parm(struct v4l2_subdev *mipi_sd, struct v4l2_streamparm *a)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+       return v4l2_subdev_call(sensor_sd, video, g_parm, a);
+}
+
+static int mipi_csis_enum_framesizes(struct v4l2_subdev *mipi_sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+       return v4l2_subdev_call(sensor_sd, pad, enum_frame_size, NULL, fse);
+}
+
+static int mipi_csis_enum_frameintervals(struct v4l2_subdev *mipi_sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_frame_interval_enum *fie)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+       struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+       return v4l2_subdev_call(sensor_sd, pad, enum_frame_interval, NULL, fie);
+}
+
+static int mipi_csis_log_status(struct v4l2_subdev *mipi_sd)
+{
+       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+
+       mutex_lock(&state->lock);
+       mipi_csis_log_counters(state, true);
+       if (debug && (state->flags & ST_POWERED))
+               dump_regs(state, __func__);
+       mutex_unlock(&state->lock);
+       return 0;
+}
+
+static struct v4l2_subdev_core_ops mipi_csis_core_ops = {
+       .s_power = mipi_csis_s_power,
+       .log_status = mipi_csis_log_status,
+};
+
+static struct v4l2_subdev_video_ops mipi_csis_video_ops = {
+       .s_rx_buffer = mipi_csis_s_rx_buffer,
+       .s_stream = mipi_csis_s_stream,
+
+       .s_parm = mipi_csis_s_parm,
+       .g_parm = mipi_csis_g_parm,
+};
+
+static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = {
+       .enum_frame_size       = mipi_csis_enum_framesizes,
+       .enum_frame_interval   = mipi_csis_enum_frameintervals,
+       .enum_mbus_code        = mipi_csis_enum_mbus_code,
+       .get_fmt               = mipi_csis_get_fmt,
+       .set_fmt               = mipi_csis_set_fmt,
+};
+
+static struct v4l2_subdev_ops mipi_csis_subdev_ops = {
+       .core = &mipi_csis_core_ops,
+       .video = &mipi_csis_video_ops,
+       .pad = &mipi_csis_pad_ops,
+};
+
+static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
+{
+       struct csi_state *state = dev_id;
+       struct csis_pktbuf *pktbuf = &state->pkt_buf;
+       unsigned long flags;
+       u32 status;
+
+       status = mipi_csis_read(state, MIPI_CSIS_INTSRC);
+
+       spin_lock_irqsave(&state->slock, flags);
+
+       if ((status & MIPI_CSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
+               u32 offset;
+
+               if (status & MIPI_CSIS_INTSRC_EVEN)
+                       offset = MIPI_CSIS_PKTDATA_EVEN;
+               else
+                       offset = MIPI_CSIS_PKTDATA_ODD;
+
+               memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
+               pktbuf->data = NULL;
+               rmb();
+       }
+
+       /* Update the event/error counters */
+       if ((status & MIPI_CSIS_INTSRC_ERRORS) || debug) {
+               int i;
+               for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) {
+                       if (!(status & state->events[i].mask))
+                               continue;
+                       state->events[i].counter++;
+                       v4l2_dbg(2, debug, &state->mipi_sd, "%s: %d\n",
+                                state->events[i].name,
+                                state->events[i].counter);
+               }
+               v4l2_dbg(2, debug, &state->mipi_sd, "status: %08x\n", status);
+       }
+       spin_unlock_irqrestore(&state->slock, flags);
+
+       mipi_csis_write(state, MIPI_CSIS_INTSRC, status);
+       return IRQ_HANDLED;
+}
+
+static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
+                           struct v4l2_subdev *subdev,
+                           struct v4l2_async_subdev *asd)
+{
+       struct csi_state *state = notifier_to_mipi_dev(notifier);
+
+       /* Find platform data for this sensor subdev */
+       if (state->asd.match.of.node == subdev->dev->of_node)
+               state->sensor_sd = subdev;
+
+       if (subdev == NULL)
+               return -EINVAL;
+
+       v4l2_info(&state->v4l2_dev, "Registered sensor subdevice: %s\n",
+                 subdev->name);
+
+       return 0;
+}
+
+static int mipi_csis_parse_dt(struct platform_device *pdev,
+                           struct csi_state *state)
+{
+       struct device_node *node = pdev->dev.of_node;
+
+       if (of_property_read_u32(node, "clock-frequency",
+                                &state->clk_frequency))
+               state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
+       if (of_property_read_u32(node, "bus-width",
+                                &state->max_num_lanes))
+               return -EINVAL;
+
+       node = of_graph_get_next_endpoint(node, NULL);
+       if (!node) {
+               dev_err(&pdev->dev, "No port node at %s\n",
+                               pdev->dev.of_node->full_name);
+               return -EINVAL;
+       }
+
+       /* Get MIPI CSI-2 bus configration from the endpoint node. */
+       of_property_read_u32(node, "csis-hs-settle",
+                                       &state->hs_settle);
+
+       of_property_read_u32(node, "csis-clk-settle",
+                                       &state->clk_settle);
+       state->wclk_ext = of_property_read_bool(node,
+                                       "csis-wclk");
+
+       of_property_read_u32(node, "data-lanes",
+                                       &state->num_lanes);
+       of_node_put(node);
+
+       return 0;
+}
+
+static int mipi_csis_pm_resume(struct device *dev, bool runtime);
+static const struct of_device_id mipi_csis_of_match[];
+
+/* register parent dev */
+static int mipi_csis_subdev_host(struct csi_state *state)
+{
+       struct device_node *parent = state->dev->of_node;
+       struct device_node *node, *port, *rem;
+       int ret;
+
+       /* Attach sensors linked to csi receivers */
+       for_each_available_child_of_node(parent, node) {
+               if (of_node_cmp(node->name, "port"))
+                       continue;
+
+               /* The csi node can have only port subnode. */
+               port = of_get_next_child(node, NULL);
+               if (!port)
+                       continue;
+               rem = of_graph_get_remote_port_parent(port);
+               of_node_put(port);
+               if (rem == NULL) {
+                       v4l2_info(&state->v4l2_dev,
+                                               "Remote device at %s not found\n",
+                                               port->full_name);
+                       return -1;
+               }
+
+               state->asd.match_type = V4L2_ASYNC_MATCH_OF;
+               state->asd.match.of.node = rem;
+               state->async_subdevs[0] = &state->asd;
+
+               of_node_put(rem);
+               break;
+       }
+
+       state->subdev_notifier.subdevs = state->async_subdevs;
+       state->subdev_notifier.num_subdevs = 1;
+       state->subdev_notifier.bound = subdev_notifier_bound;
+
+       ret = v4l2_async_notifier_register(&state->v4l2_dev,
+                                       &state->subdev_notifier);
+       if (ret)
+               dev_err(state->dev,
+                                       "Error register async notifier regoster\n");
+
+       return ret;
+}
+
+/* init subdev */
+static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
+               struct platform_device *pdev,
+               const struct v4l2_subdev_ops *ops)
+{
+       struct csi_state *state = platform_get_drvdata(pdev);
+       int ret = 0;
+
+       v4l2_subdev_init(mipi_sd, ops);
+       mipi_sd->owner = THIS_MODULE;
+       snprintf(mipi_sd->name, sizeof(mipi_sd->name), "%s.%d",
+                CSIS_SUBDEV_NAME, state->index);
+       mipi_sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       mipi_sd->dev = &pdev->dev;
+
+       state->csis_fmt = &mipi_csis_formats[0];
+       state->format.code = mipi_csis_formats[0].code;
+       state->format.width = MIPI_CSIS_DEF_PIX_WIDTH;
+       state->format.height = MIPI_CSIS_DEF_PIX_HEIGHT;
+
+       /* This allows to retrieve the platform device id by the host driver */
+       v4l2_set_subdevdata(mipi_sd, pdev);
+
+       ret = v4l2_async_register_subdev(mipi_sd);
+       if (ret < 0)
+               dev_err(&pdev->dev, "%s--Async register faialed, ret=%d\n", __func__, ret);
+
+       return ret;
+}
+
+static int mipi_csis_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct v4l2_subdev *mipi_sd;
+       struct resource *mem_res;
+       struct csi_state *state;
+       int ret = -ENOMEM;
+
+       state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return -ENOMEM;
+
+       mutex_init(&state->lock);
+       spin_lock_init(&state->slock);
+
+       state->pdev = pdev;
+       mipi_sd = &state->mipi_sd;
+       state->dev = dev;
+
+       ret = mipi_csis_parse_dt(pdev, state);
+       if (ret < 0)
+               return ret;
+
+       if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
+               dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
+                       state->num_lanes, state->max_num_lanes);
+               return -EINVAL;
+       }
+
+       mipi_csis_phy_init(state);
+       mipi_csis_phy_reset(state);
+
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       state->regs = devm_ioremap_resource(dev, mem_res);
+       if (IS_ERR(state->regs))
+               return PTR_ERR(state->regs);
+
+       state->irq = platform_get_irq(pdev, 0);
+       if (state->irq < 0) {
+               dev_err(dev, "Failed to get irq\n");
+               return state->irq;
+       }
+
+       ret = mipi_csis_clk_get(state);
+       if (ret < 0)
+               return ret;
+
+       mipi_csis_clk_enable(state);
+
+       ret = devm_request_irq(dev, state->irq, mipi_csis_irq_handler,
+                              0, dev_name(dev), state);
+       if (ret) {
+               dev_err(dev, "Interrupt request failed\n");
+               goto e_clkdis;
+       }
+
+       /* First register a v4l2 device */
+       ret = v4l2_device_register(dev, &state->v4l2_dev);
+       if (ret) {
+               v4l2_err(dev->driver,
+                       "Unable to register v4l2 device.\n");
+               goto e_clkdis;
+       }
+       v4l2_info(&state->v4l2_dev, "mipi csi v4l2 device registered\n");
+
+       /* .. and a pointer to the subdev. */
+       platform_set_drvdata(pdev, state);
+
+       ret = mipi_csis_subdev_init(&state->mipi_sd, pdev, &mipi_csis_subdev_ops);
+       if (ret < 0)
+               goto e_sd_mipi;
+
+       memcpy(state->events, mipi_csis_events, sizeof(state->events));
+
+       /* subdev host register */
+       ret = mipi_csis_subdev_host(state);
+       if (ret < 0)
+               goto e_sd_host;
+
+       pm_runtime_enable(dev);
+       if (!pm_runtime_enabled(dev)) {
+               ret = mipi_csis_pm_resume(dev, true);
+               if (ret < 0)
+                       goto e_sd_host;
+       }
+
+       dev_info(&pdev->dev,
+                       "lanes: %d, hs_settle: %d, clk_settle: %d, wclk: %d, freq: %u\n",
+                state->num_lanes, state->hs_settle, state->clk_settle,
+                state->wclk_ext, state->clk_frequency);
+       return 0;
+
+e_sd_host:
+       v4l2_async_notifier_unregister(&state->subdev_notifier);
+       v4l2_device_unregister(&state->v4l2_dev);
+e_sd_mipi:
+       v4l2_async_unregister_subdev(&state->mipi_sd);
+e_clkdis:
+       mipi_csis_clk_disable(state);
+       return ret;
+}
+
+static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct csi_state *state = platform_get_drvdata(pdev);
+       struct v4l2_subdev *mipi_sd = &state->mipi_sd;
+       int ret = 0;
+
+       v4l2_dbg(1, debug, mipi_sd, "%s: flags: 0x%x\n",
+                __func__, state->flags);
+
+       mutex_lock(&state->lock);
+       if (state->flags & ST_POWERED) {
+               mipi_csis_stop_stream(state);
+               ret = regulator_disable(state->mipi_phy_regulator);
+               if (ret)
+                       goto unlock;
+               mipi_csis_clk_disable(state);
+               state->flags &= ~ST_POWERED;
+               if (!runtime)
+                       state->flags |= ST_SUSPENDED;
+       }
+ unlock:
+       mutex_unlock(&state->lock);
+       return ret ? -EAGAIN : 0;
+}
+
+static int mipi_csis_pm_resume(struct device *dev, bool runtime)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct csi_state *state = platform_get_drvdata(pdev);
+       struct v4l2_subdev *mipi_sd = &state->mipi_sd;
+       int ret = 0;
+
+       v4l2_dbg(1, debug, mipi_sd, "%s: flags: 0x%x\n",
+                __func__, state->flags);
+
+       mutex_lock(&state->lock);
+       if (!runtime && !(state->flags & ST_SUSPENDED))
+               goto unlock;
+
+       if (!(state->flags & ST_POWERED)) {
+               ret = regulator_enable(state->mipi_phy_regulator);
+               if (!ret) {
+                       state->flags |= ST_POWERED;
+               } else {
+                       goto unlock;
+               }
+               mipi_csis_clk_enable(state);
+       }
+       if (state->flags & ST_STREAMING)
+               mipi_csis_start_stream(state);
+
+       state->flags &= ~ST_SUSPENDED;
+ unlock:
+       mutex_unlock(&state->lock);
+       return ret ? -EAGAIN : 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mipi_csis_suspend(struct device *dev)
+{
+       return mipi_csis_pm_suspend(dev, false);
+}
+
+static int mipi_csis_resume(struct device *dev)
+{
+       return mipi_csis_pm_resume(dev, false);
+}
+#endif
+
+static int mipi_csis_runtime_suspend(struct device *dev)
+{
+       return mipi_csis_pm_suspend(dev, true);
+}
+
+static int mipi_csis_runtime_resume(struct device *dev)
+{
+       return mipi_csis_pm_resume(dev, true);
+}
+
+static int mipi_csis_remove(struct platform_device *pdev)
+{
+       struct csi_state *state = platform_get_drvdata(pdev);
+
+       v4l2_async_unregister_subdev(&state->mipi_sd);
+       v4l2_async_notifier_unregister(&state->subdev_notifier);
+       v4l2_device_unregister(&state->v4l2_dev);
+
+       pm_runtime_disable(&pdev->dev);
+       mipi_csis_pm_suspend(&pdev->dev, true);
+       mipi_csis_clk_disable(state);
+       pm_runtime_set_suspended(&pdev->dev);
+
+       return 0;
+}
+
+static const struct dev_pm_ops mipi_csis_pm_ops = {
+       SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume,
+                          NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume)
+};
+
+static const struct of_device_id mipi_csis_of_match[] = {
+       {       .compatible = "fsl,imx7d-mipi-csi",},
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
+
+static struct platform_driver mipi_csis_driver = {
+       .probe          = mipi_csis_probe,
+       .remove         = mipi_csis_remove,
+       .driver         = {
+               .of_match_table = mipi_csis_of_match,
+               .name           = CSIS_DRIVER_NAME,
+               .owner          = THIS_MODULE,
+               .pm             = &mipi_csis_pm_ops,
+       },
+};
+
+module_platform_driver(mipi_csis_driver);
+
+MODULE_DESCRIPTION("Freescale MIPI-CSI2 receiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/mxc_vadc.c b/drivers/media/platform/mxc/capture/mxc_vadc.c
new file mode 100644 (file)
index 0000000..2a844ca
--- /dev/null
@@ -0,0 +1,830 @@
+/*
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * 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.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/media-bus-format.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include "mxc_vadc.h"
+
+/* Resource names for the VADC driver. */
+#define VAFE_REGS_ADDR_RES_NAME "vadc-vafe"
+#define VDEC_REGS_ADDR_RES_NAME "vadc-vdec"
+
+#define reg32_write(addr, val) __raw_writel(val, addr)
+#define reg32_read(addr)       __raw_readl(addr)
+#define reg32setbit(addr, bitpos) \
+       reg32_write((addr), (reg32_read((addr)) | (1<<(bitpos))))
+
+#define reg32clrbit(addr, bitpos) \
+       reg32_write((addr), (reg32_read((addr)) & (0xFFFFFFFF ^ (1<<(bitpos)))))
+
+#define GPC_CNTR               0x00
+#define IMX6SX_GPC_CNTR_VADC_ANALOG_OFF_MASK   BIT(17)
+#define IMX6SX_GPC_CNTR_VADC_POWER_DOWN_MASK   BIT(18)
+
+void __iomem *vafe_regbase;
+void __iomem *vdec_regbase;
+
+
+/* List of input video formats supported. The video formats is corresponding
+ * with v4l2 id in video_fmt
+ */
+enum video_fmt_idx {
+       VADC_NTSC = 0,  /* Locked on (M) NTSC video signal. */
+       VADC_PAL,               /* (B, G, H, I, N)PAL video signal. */
+};
+
+/* Number of video standards supported (including 'not locked' signal). */
+#define VADC_STD_MAX           (VADC_PAL + 1)
+
+/* Video format structure. */
+struct video_fmt{
+       v4l2_std_id  v4l2_std;  /* Video for linux ID. */
+       char name[16];          /* Name (e.g., "NTSC", "PAL", etc.) */
+       u16 raw_width;          /* Raw width. */
+       u16 raw_height;         /* Raw height. */
+       u16 active_width;       /* Active width. */
+       u16 active_height;      /* Active height. */
+       u16 framerates;
+};
+
+/*
+ * Maintains the information on the current state of the sensor.
+ */
+struct vadc_state {
+       struct v4l2_device v4l2_dev;
+       struct v4l2_subdev sd;
+       struct video_fmt *fmt;
+
+       struct clk *vadc_clk;
+       struct clk *csi_clk;
+       struct regmap *gpr;
+       void __iomem *gpc_reg;
+
+       u32 vadc_in;
+       u32 csi_id;
+};
+
+static int vadc_querystd(struct v4l2_subdev *sd, v4l2_std_id *std);
+
+/* Description of video formats supported.
+ *
+ *  PAL: raw=720x625, active=720x576.
+ *  NTSC: raw=720x525, active=720x480.
+ */
+static struct video_fmt video_fmts[] = {
+       /* NTSC */
+       {
+        .v4l2_std = V4L2_STD_NTSC,
+        .name = "NTSC",
+        .raw_width = 720,
+        .raw_height = 525,
+        .active_width = 720,
+        .active_height = 480,
+        .framerates = 30,
+        },
+       /* (B, G, H, I, N) PAL */
+       {
+        .v4l2_std = V4L2_STD_PAL,
+        .name = "PAL",
+        .raw_width = 720,
+        .raw_height = 625,
+        .active_width = 720,
+        .active_height = 576,
+        .framerates = 25,
+        },
+};
+
+static void afe_voltage_clampingmode(void)
+{
+       reg32_write(AFE_CLAMP, 0x07);
+       reg32_write(AFE_CLMPAMP, 0x60);
+       reg32_write(AFE_CLMPDAT, 0xF0);
+}
+
+static void afe_alwayson_clampingmode(void)
+{
+       reg32_write(AFE_CLAMP, 0x15);
+       reg32_write(AFE_CLMPDAT, 0x08);
+       reg32_write(AFE_CLMPAMP, 0x00);
+}
+
+static void afe_init(void)
+{
+       pr_debug("%s\n", __func__);
+
+       reg32_write(AFE_PDBUF, 0x1f);
+       reg32_write(AFE_PDADC, 0x0f);
+       reg32_write(AFE_PDSARH, 0x01);
+       reg32_write(AFE_PDSARL, 0xff);
+       reg32_write(AFE_PDADCRFH, 0x01);
+       reg32_write(AFE_PDADCRFL, 0xff);
+       reg32_write(AFE_ICTRL, 0x3a);
+       reg32_write(AFE_ICTLSTG, 0x1e);
+
+       reg32_write(AFE_RCTRLSTG, 0x1e);
+       reg32_write(AFE_INPBUF, 0x035);
+       reg32_write(AFE_INPFLT, 0x02);
+       reg32_write(AFE_ADCDGN, 0x40);
+       reg32_write(AFE_TSTSEL, 0x10);
+
+       reg32_write(AFE_ACCTST, 0x07);
+
+       reg32_write(AFE_BGREG, 0x08);
+
+       reg32_write(AFE_ADCGN, 0x09);
+
+       /* set current controlled clamping
+       * always on, low current */
+       reg32_write(AFE_CLAMP, 0x11);
+       reg32_write(AFE_CLMPAMP, 0x08);
+}
+
+static void vdec_mode_timing_init(int std)
+{
+       if (std == V4L2_STD_NTSC) {
+               /* NTSC 720x480 */
+               reg32_write(VDEC_HACTS, 0x66);
+               reg32_write(VDEC_HACTE, 0x24);
+
+               reg32_write(VDEC_VACTS, 0x29);
+               reg32_write(VDEC_VACTE, 0x04);
+
+               /* set V Position */
+               reg32_write(VDEC_VRTPOS, 0x2);
+       } else if (std == V4L2_STD_PAL) {
+               /* PAL 720x576 */
+               reg32_write(VDEC_HACTS, 0x66);
+               reg32_write(VDEC_HACTE, 0x24);
+
+               reg32_write(VDEC_VACTS, 0x29);
+               reg32_write(VDEC_VACTE, 0x04);
+
+               /* set V Position */
+               reg32_write(VDEC_VRTPOS, 0x6);
+       } else
+               pr_debug("Error not support video mode\n");
+
+       /* set H Position */
+       reg32_write(VDEC_HZPOS, 0x60);
+
+       /* set H ignore start */
+       reg32_write(VDEC_HSIGS, 0xf8);
+
+       /* set H ignore end */
+       reg32_write(VDEC_HSIGE, 0x18);
+}
+
+/*
+* vdec_init()
+* Initialises the VDEC registers
+* Returns: nothing
+*/
+static void vdec_init(struct vadc_state *vadc)
+{
+       v4l2_std_id std;
+
+       pr_debug("%s\n", __func__);
+
+       /* Get work mode PAL or NTSC */
+       vadc_querystd(&vadc->sd, &std);
+
+       vdec_mode_timing_init(std);
+
+       /* vcr detect threshold high, automatic detections */
+       reg32_write(VDEC_VSCON2, 0);
+
+       reg32_write(VDEC_BASE + 0x110, 0x01);
+
+       /* set the noramp mode on the Hloop PLL. */
+       reg32_write(VDEC_BASE+(0x14*4), 0x10);
+
+       /* set the YC relative delay.*/
+       reg32_write(VDEC_YCDEL, 0x90);
+
+       /* setup the Hpll */
+       reg32_write(VDEC_BASE+(0x13*4), 0x13);
+
+       /* setup the 2d comb */
+       /* set the gain of the Hdetail output to 3
+        * set the notch alpha gain to 1 */
+       reg32_write(VDEC_CFC2, 0x34);
+
+       /* setup various 2d comb bits.*/
+       reg32_write(VDEC_BASE+(0x02*4), 0x01);
+       reg32_write(VDEC_BASE+(0x03*4), 0x18);
+       reg32_write(VDEC_BASE+(0x04*4), 0x34);
+
+       /* set the start of the burst gate */
+       reg32_write(VDEC_BRSTGT, 0x30);
+
+       /* set 1f motion gain */
+       reg32_write(VDEC_BASE+(0x0f*4), 0x20);
+
+       /* set the 1F chroma motion detector thresh
+        * for colour reverse detection */
+       reg32_write(VDEC_THSH1, 0x02);
+       reg32_write(VDEC_BASE+(0x4a*4), 0x20);
+       reg32_write(VDEC_BASE+(0x4b*4), 0x08);
+
+       reg32_write(VDEC_BASE+(0x4c*4), 0x08);
+
+       /* set the threshold for the narrow/wide adaptive chroma BW */
+       reg32_write(VDEC_BASE+(0x20*4), 0x20);
+
+       /* turn up the colour with the new colour gain reg */
+       /* hue: */
+       reg32_write(VDEC_HUE, 0x00);
+
+       /* cbgain: 22 B4 */
+       reg32_write(VDEC_CBGN, 0xb4);
+       /* cr gain 80 */
+       reg32_write(VDEC_CRGN, 0x80);
+       /* luma gain (contrast) */
+       reg32_write(VDEC_CNTR, 0x80);
+
+       /* setup the signed black level register, brightness */
+       reg32_write(VDEC_BRT, 0x00);
+
+       /* filter the standard detection
+        * enable the comb for the ntsc443 */
+       reg32_write(VDEC_STDDBG, 0x20);
+
+       /* setup chroma kill thresh for no chroma */
+       reg32_write(VDEC_CHBTH, 0x0);
+
+       /* set chroma loop to wider BW
+        * no set it to normal BW. i fixed the bw problem.*/
+       reg32_write(VDEC_YCDEL, 0x00);
+
+       /* set the compensation in the chroma loop for the Hloop
+        * set the ratio for the nonarithmetic 3d comb modes.*/
+       reg32_write(VDEC_BASE + (0x1d*4), 0x90);
+
+       /* set the threshold for the nonarithmetic mode for the 2d comb
+        * the higher the value the more Fc Fh offset
+        * we will tolerate before turning off the comb. */
+       reg32_write(VDEC_BASE + (0x33*4), 0xa0);
+
+       /* setup the bluescreen output colour */
+       reg32_write(VDEC_BASE + (0x3d*4), 35);
+       reg32_write(VDEC_BLSCRCR, 114);
+       reg32_write(VDEC_BLSCRCB, 212);
+
+       /* disable the active blanking */
+       reg32_write(VDEC_BASE + (0x15*4), 0x02);
+
+       /* setup the luma agc for automatic gain. */
+       reg32_write(VDEC_LMAGC2, 0x5e);
+       reg32_write(VDEC_LMAGC1, 0x81);
+
+       /* setup chroma agc */
+       reg32_write(VDEC_CHAGC2, 0xa0);
+       reg32_write(VDEC_CHAGC1, 0x01);
+
+       /* setup the MV thresh lower nibble
+        * setup the sync top cap, upper nibble */
+       reg32_write(VDEC_BASE + (0x3a*4), 0x80);
+       reg32_write(VDEC_SHPIMP, 0x00);
+
+       /* setup the vsync block */
+       reg32_write(VDEC_VSCON1, 0x87);
+
+       /* set the nosignal threshold
+        * set the vsync threshold */
+       reg32_write(VDEC_VSSGTH, 0x35);
+
+       /* set length for min hphase filter
+        * (or saturate limit if saturate is chosen) */
+       reg32_write(VDEC_BASE + (0x45*4), 0x40);
+
+       /* enable the internal resampler,
+        * select min filter not saturate for
+        * hphase noise filter for vcr detect.
+        * enable vcr pause mode different field lengths */
+       reg32_write(VDEC_BASE + (0x46*4), 0x90);
+
+       /* disable VCR detection, lock to the Hsync rather than the Vsync */
+       reg32_write(VDEC_VSCON2, 0x04);
+
+       /* set tiplevel goal for dc clamp. */
+       reg32_write(VDEC_BASE + (0x3c*4), 0xB0);
+
+       /* override SECAM detection and force SECAM off */
+       reg32_write(VDEC_BASE + (0x2f*4), 0x20);
+
+       /* Set r3d_hardblend in 3D control2 reg */
+       reg32_write(VDEC_BASE + (0x0c*4), 0x04);
+}
+
+/* set Input selector & input pull-downs */
+static void vadc_s_routing(int vadc_in)
+{
+       switch (vadc_in) {
+       case 0:
+               reg32_write(AFE_INPFLT, 0x02);
+               reg32_write(AFE_OFFDRV, 0x00);
+               reg32_write(AFE_INPCONFIG, 0x1e);
+               break;
+       case 1:
+               reg32_write(AFE_INPFLT, 0x02);
+               reg32_write(AFE_OFFDRV, 0x00);
+               reg32_write(AFE_INPCONFIG, 0x2d);
+               break;
+       case 2:
+               reg32_write(AFE_INPFLT, 0x02);
+               reg32_write(AFE_OFFDRV, 0x00);
+               reg32_write(AFE_INPCONFIG, 0x4b);
+               break;
+       case 3:
+               reg32_write(AFE_INPFLT, 0x02);
+               reg32_write(AFE_OFFDRV, 0x00);
+               reg32_write(AFE_INPCONFIG, 0x87);
+               break;
+       default:
+               pr_debug("error video input %d\n", vadc_in);
+       }
+}
+
+static void vadc_power_up(struct vadc_state *state)
+{
+       /* Power on vadc analog */
+       reg32clrbit(state->gpc_reg + GPC_CNTR, 17);
+
+       /* Power down vadc ext power */
+       reg32clrbit(state->gpc_reg + GPC_CNTR, 18);
+
+       /* software reset afe  */
+       regmap_update_bits(state->gpr, IOMUXC_GPR1,
+                       IMX6SX_GPR1_VADC_SW_RST_MASK,
+                       IMX6SX_GPR1_VADC_SW_RST_RESET);
+
+       msleep(10);
+
+       /* clock config for vadc */
+       reg32_write(VDEC_BASE + 0x320, 0xe3);
+       reg32_write(VDEC_BASE + 0x324, 0x38);
+       reg32_write(VDEC_BASE + 0x328, 0x8e);
+       reg32_write(VDEC_BASE + 0x32c, 0x23);
+
+       /* Release reset bit  */
+       regmap_update_bits(state->gpr, IOMUXC_GPR1,
+                       IMX6SX_GPR1_VADC_SW_RST_MASK,
+                       IMX6SX_GPR1_VADC_SW_RST_RELEASE);
+
+       /* Power on vadc ext power */
+       reg32setbit(state->gpc_reg + GPC_CNTR, 18);
+}
+
+static void vadc_power_down(struct vadc_state *state)
+{
+       /* Power down vadc analog */
+       reg32setbit(state->gpc_reg + GPC_CNTR, 17);
+
+       /* Power down vadc ext power */
+       reg32clrbit(state->gpc_reg + GPC_CNTR, 18);
+
+}
+static void vadc_init(struct vadc_state *vadc)
+{
+       pr_debug("%s\n", __func__);
+
+       vadc_power_up(vadc);
+
+       afe_init();
+
+       /* select Video Input 0-3 */
+       vadc_s_routing(vadc->vadc_in);
+
+       afe_voltage_clampingmode();
+
+       vdec_init(vadc);
+
+       /*
+       * current control loop will move sinewave input off below
+       * the bottom of the signal range visible
+       * when the testbus is viewed as magnitude,
+       * so have to break before this point while capturing ENOB data:
+       */
+       afe_alwayson_clampingmode();
+}
+
+static inline struct vadc_state *to_state(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct vadc_state, sd);
+}
+
+static int vadc_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+       struct vadc_state *state = to_state(sd);
+
+       *std = state->fmt->v4l2_std;
+       return 0;
+}
+
+/*!
+ * Return attributes of current video standard.
+ * Since this device autodetects the current standard, this function also
+ * sets the values that need to be changed if the standard changes.
+ * There is no set std equivalent function.
+ *
+ *  @return            None.
+ */
+static int vadc_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+       struct vadc_state *state = to_state(sd);
+       int mod;
+       int idx;
+       int i;
+
+       /* Read auto mode detected result */
+       printk(KERN_INFO"wait vadc auto detect video mode....\n");
+       for (i = 0; i < 10; i++) {
+               msleep(200);
+               mod = reg32_read(VDEC_VIDMOD);
+               /* Check video signal states */
+               if ((mod & VDEC_VIDMOD_SIGNAL_MASK)
+                               == VDEC_VIDMOD_SIGNAL_DETECT)
+                       break;
+       }
+       if (i == 10)
+               printk(KERN_INFO"Timeout detect video signal mod=0x%x\n", mod);
+
+       if ((mod & VDEC_VIDMOD_PAL_MASK) || (mod & VDEC_VIDMOD_M625_MASK))
+               idx = VADC_PAL;
+       else
+               idx = VADC_NTSC;
+
+       *std = video_fmts[idx].v4l2_std;
+       state->fmt = &video_fmts[idx];
+
+       printk(KERN_INFO"video mode %s\n", video_fmts[idx].name);
+       return 0;
+}
+
+static int vadc_enum_mbus_code(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_pad_config *cfg,
+                              struct v4l2_subdev_mbus_code_enum *code)
+{
+       /* support only one format  */
+       if (code->pad || code->index >= 1)
+               return -EINVAL;
+
+       code->code = MEDIA_BUS_FMT_AYUV8_1X32;
+       return 0;
+}
+
+static int vadc_get_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_subdev_pad_config *cfg,
+                       struct v4l2_subdev_format *format)
+{
+       struct vadc_state *state = to_state(sd);
+       struct v4l2_mbus_framefmt *fmt = &format->format;
+
+       if (format->pad)
+               return -EINVAL;
+
+       fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+       fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       fmt->field = V4L2_FIELD_INTERLACED;
+       fmt->width = 720;
+       fmt->height = state->fmt->v4l2_std & V4L2_STD_NTSC ? 480 : 576;
+
+       return 0;
+}
+
+static int vadc_set_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_subdev_pad_config *cfg,
+                       struct v4l2_subdev_format *format)
+{
+       return vadc_get_fmt(sd, cfg, format);
+}
+
+static int vadc_enum_framesizes(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_pad_config *cfg,
+                              struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct vadc_state *state = to_state(sd);
+       if (fse->index >= 1)
+               return -EINVAL;
+
+       fse->min_width = state->fmt->active_width;
+       fse->max_width = state->fmt->active_width;
+       fse->min_height  = state->fmt->active_height;
+       fse->max_height  = state->fmt->active_height;
+
+       return 0;
+}
+static int vadc_enum_frameintervals(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_frame_interval_enum *fie)
+{
+       struct vadc_state *state = to_state(sd);
+
+       if (fie->index < 0 || fie->index >= 1)
+               return -EINVAL;
+
+       fie->interval.numerator = 1;
+
+       fie->interval.denominator = state->fmt->framerates;
+
+       return 0;
+}
+
+static int vadc_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+       struct vadc_state *state = to_state(sd);
+
+       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (parms->parm.capture.timeperframe.denominator
+                               != state->fmt->framerates)
+               parms->parm.capture.timeperframe.denominator
+                               = state->fmt->framerates;
+
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops vadc_video_ops = {
+       .querystd              = vadc_querystd,
+       .s_parm                = vadc_s_parm,
+       .g_std                 = vadc_g_std,
+};
+
+
+static const struct v4l2_subdev_pad_ops vadc_pad_ops = {
+       .get_fmt               = vadc_get_fmt,
+       .set_fmt               = vadc_set_fmt,
+       .enum_mbus_code        = vadc_enum_mbus_code,
+       .enum_frame_size       = vadc_enum_framesizes,
+       .enum_frame_interval   = vadc_enum_frameintervals,
+};
+
+static const struct v4l2_subdev_ops vadc_ops = {
+       .video = &vadc_video_ops,
+       .pad = &vadc_pad_ops,
+};
+
+static const struct of_device_id fsl_vadc_dt_ids[] = {
+       { .compatible = "fsl,imx6sx-vadc", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_vadc_dt_ids);
+
+static int vadc_of_init(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *gpc_np;
+       struct vadc_state *state = platform_get_drvdata(pdev);
+       int csi_id;
+       int ret;
+
+       /* Get csi_id to setting vadc to csi mux in gpr */
+       ret = of_property_read_u32(np, "csi_id", &csi_id);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to read of property csi_id\n");
+               return ret;
+       }
+
+       state->csi_id = csi_id;
+
+       /* remap GPR register */
+       state->gpr = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                       "gpr");
+       if (IS_ERR(state->gpr)) {
+               dev_dbg(&pdev->dev, "can not get gpr\n");
+               return -ENOMEM;
+       }
+
+       /* Configuration vadc-to-csi 0 or 1 */
+       if (csi_id) {
+               regmap_update_bits(state->gpr, IOMUXC_GPR5,
+                               IMX6SX_GPR5_CSI2_MUX_CTRL_MASK,
+                               IMX6SX_GPR5_CSI2_MUX_CTRL_CVD);
+       } else {
+               regmap_update_bits(state->gpr, IOMUXC_GPR5,
+                               IMX6SX_GPR5_CSI1_MUX_CTRL_MASK,
+                               IMX6SX_GPR5_CSI1_MUX_CTRL_CVD);
+       }
+
+       /* Get default vadc_in number  */
+       ret = of_property_read_u32(np, "vadc_in", &state->vadc_in);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to read of property vadc_in\n");
+               return ret;
+       }
+
+       /* map GPC register  */
+       gpc_np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+       state->gpc_reg = of_iomap(gpc_np, 0);
+       if (!state->gpc_reg) {
+               dev_err(&pdev->dev, "ioremap failed with gpc base\n");
+               goto error;
+       }
+
+       return ret;
+
+error:
+       iounmap(state->gpc_reg);
+       return ret;
+}
+
+static void vadc_v4l2_subdev_init(struct v4l2_subdev *sd,
+               struct platform_device *pdev,
+               const struct v4l2_subdev_ops *ops)
+{
+       struct vadc_state *state = platform_get_drvdata(pdev);
+       int ret = 0;
+
+       v4l2_subdev_init(sd, ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       sd->owner = pdev->dev.driver->owner;
+       sd->dev = &pdev->dev;
+
+       /* initialize name */
+       snprintf(sd->name, sizeof(sd->name), "%s",
+               pdev->dev.driver->name);
+
+       v4l2_set_subdevdata(sd, state);
+
+       ret = v4l2_async_register_subdev(sd);
+       if (ret < 0)
+               dev_err(&pdev->dev, "%s--Async register faialed, ret=%d\n", __func__, ret);
+}
+
+static int vadc_probe(struct platform_device *pdev)
+{
+       struct vadc_state *state;
+       struct v4l2_subdev *sd;
+       struct resource *res;
+       int ret = 0;
+
+       state = devm_kzalloc(&pdev->dev, sizeof(struct vadc_state), GFP_KERNEL);
+       if (!state) {
+               dev_err(&pdev->dev, "Cannot allocate device data\n");
+               return -ENOMEM;
+       }
+
+       /* Set initial values for the sensor struct. */
+       state->fmt = &video_fmts[VADC_NTSC];
+
+       sd = &state->sd;
+
+       /* map vafe address  */
+       res = platform_get_resource_byname(pdev,
+                               IORESOURCE_MEM, VAFE_REGS_ADDR_RES_NAME);
+       if (!res) {
+               dev_err(&pdev->dev, "No vafe base address found.\n");
+               return -ENOMEM;
+       }
+       vafe_regbase = devm_ioremap_resource(&pdev->dev, res);
+       if (!vafe_regbase) {
+               dev_err(&pdev->dev, "ioremap failed with vafe base\n");
+               return -ENOMEM;
+       }
+
+       /* map vdec address  */
+       res = platform_get_resource_byname(pdev,
+                               IORESOURCE_MEM, VDEC_REGS_ADDR_RES_NAME);
+       if (!res) {
+               dev_err(&pdev->dev, "No vdec base address found.\n");
+               return -ENODEV;
+       }
+       vdec_regbase = devm_ioremap_resource(&pdev->dev, res);
+       if (!vdec_regbase) {
+               dev_err(&pdev->dev, "ioremap failed with vdec base\n");
+               return -ENOMEM;
+       }
+
+       /* Get clock */
+       state->vadc_clk = devm_clk_get(&pdev->dev, "vadc");
+       if (IS_ERR(state->vadc_clk)) {
+               ret = PTR_ERR(state->vadc_clk);
+               return ret;
+       }
+
+       state->csi_clk = devm_clk_get(&pdev->dev, "csi");
+       if (IS_ERR(state->csi_clk)) {
+               ret = PTR_ERR(state->csi_clk);
+               return ret;
+       }
+
+       /* clock  */
+       clk_prepare_enable(state->csi_clk);
+       clk_prepare_enable(state->vadc_clk);
+
+       platform_set_drvdata(pdev, state);
+
+       vadc_v4l2_subdev_init(sd, pdev, &vadc_ops);
+
+       pm_runtime_enable(&pdev->dev);
+
+       pm_runtime_get_sync(&pdev->dev);
+       /* Init VADC */
+       ret = vadc_of_init(pdev);
+       if (ret < 0)
+               goto err;
+       vadc_init(state);
+
+       pr_info("vadc driver loaded\n");
+
+       return 0;
+err:
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       v4l2_async_unregister_subdev(&state->sd);
+       clk_disable_unprepare(state->csi_clk);
+       clk_disable_unprepare(state->vadc_clk);
+       return ret;
+}
+
+static int vadc_remove(struct platform_device *pdev)
+{
+       struct vadc_state *state = platform_get_drvdata(pdev);
+
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       v4l2_async_unregister_subdev(&state->sd);
+       clk_disable_unprepare(state->csi_clk);
+       clk_disable_unprepare(state->vadc_clk);
+
+       vadc_power_down(state);
+       return true;
+}
+
+static int vadc_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct vadc_state *state = platform_get_drvdata(pdev);
+
+       clk_disable(state->csi_clk);
+       clk_disable(state->vadc_clk);
+
+       vadc_power_down(state);
+
+       return 0;
+}
+
+static int vadc_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct vadc_state *state = platform_get_drvdata(pdev);
+
+       clk_enable(state->csi_clk);
+       clk_enable(state->vadc_clk);
+
+       vadc_init(state);
+       return 0;
+}
+
+static const struct dev_pm_ops vadc_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(vadc_suspend, vadc_resume)
+};
+
+static struct platform_driver vadc_driver = {
+       .driver = {
+               .name = "fsl_vadc",
+               .of_match_table = of_match_ptr(fsl_vadc_dt_ids),
+               .pm     = &vadc_pm_ops,
+       },
+       .probe = vadc_probe,
+       .remove = vadc_remove,
+};
+
+module_platform_driver(vadc_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("fsl VADC/VDEC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/mxc_vadc.h b/drivers/media/platform/mxc/capture/mxc_vadc.h
new file mode 100644 (file)
index 0000000..d5c1389
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef MXC_VDEC_H
+#define MXC_VDEC_H
+
+/*** define base address ***/
+#define VDEC_BASE vdec_regbase
+#define AFE_BASE vafe_regbase
+
+/* AFE - Register offsets */
+#define AFE_BLOCK_ID_OFFSET                            0x00000000
+#define AFE_PDBUF_OFFSET                               0x00000004
+#define AFE_SWRST_OFFSET                               0x00000008
+#define AFE_TSTSEL_OFFSET                              0x0000000c
+#define AFE_TSTMSC_OFFSET                              0x00000010
+#define AFE_ENPADIO_OFFSET                             0x00000014
+#define AFE_BGREG_OFFSET                               0x00000018
+#define AFE_ACCESSAR_ID_OFFSET                 0x00000400
+#define AFE_PDADC_OFFSET                               0x00000404
+#define AFE_PDSARH_OFFSET                              0x00000408
+#define AFE_PDSARL_OFFSET                              0x0000040C
+#define AFE_PDADCRFH_OFFSET                            0x00000410
+#define AFE_PDADCRFL_OFFSET                            0x00000414
+#define AFE_ACCTST_OFFSET                              0x00000418
+#define AFE_ADCGN_OFFSET                               0x0000041C
+#define AFE_ICTRL_OFFSET                               0x00000420
+#define AFE_ICTLSTG_OFFSET                             0x00000424
+#define AFE_RCTRLSTG_OFFSET                            0x00000428
+#define AFE_TCTRLSTG_OFFSET                            0x0000042c
+#define AFE_REFMOD_OFFSET                              0x00000430
+#define AFE_REFTRIML_OFFSET                            0x00000434
+#define AFE_REFTRIMH_OFFSET                            0x00000438
+#define AFE_ADCR_OFFSET                                        0x0000043c
+#define AFE_DUMMY0_OFFSET                              0x00000440
+#define AFE_DUMMY1_OFFSET                              0x00000444
+#define AFE_DUMMY2_OFFSET                              0x00000448
+#define AFE_DACAMP_OFFSET                              0x0000044c
+#define AFE_CLMPTST_OFFSET                             0x00000450
+#define AFE_CLMPDAT_OFFSET                             0x00000454
+#define AFE_CLMPAMP_OFFSET                             0x00000458
+#define AFE_CLAMP_OFFSET                               0x0000045c
+#define AFE_INPBUF_OFFSET                              0x00000460
+#define AFE_INPFLT_OFFSET                              0x00000464
+#define AFE_ADCDGN_OFFSET                              0x00000468
+#define AFE_OFFDRV_OFFSET                              0x0000046c
+#define AFE_INPCONFIG_OFFSET                   0x00000470
+#define AFE_PROGDELAY_OFFSET                   0x00000474
+#define AFE_ADCOMT_OFFSET                              0x00000478
+#define AFE_ALGDELAY_OFFSET                            0x0000047c
+#define AFE_ACC_ID_OFFSET                              0x00000800
+#define AFE_ACCSTA_OFFSET                              0x00000804
+#define AFE_ACCNOSLI_OFFSET                            0x00000808
+#define AFE_ACCCALCON_OFFSET                   0x0000080c
+#define AFE_BWEWRICTRL_OFFSET                  0x00000810
+#define AFE_SELSLI_OFFSET                              0x00000814
+#define AFE_SELBYT_OFFSET                              0x00000818
+#define AFE_REDVAL_OFFSET                              0x00000820
+#define AFE_WRIBYT_OFFSET                              0x00000824
+
+/* AFE Register per module */
+#define AFE_BLOCK_ID                   (AFE_BASE + AFE_BLOCK_ID_OFFSET)
+#define AFE_PDBUF                              (AFE_BASE + AFE_PDBUF_OFFSET)
+#define AFE_SWRST                              (AFE_BASE + AFE_SWRST_OFFSET)
+#define AFE_TSTSEL                             (AFE_BASE + AFE_TSTSEL_OFFSET)
+#define AFE_TSTMSC                             (AFE_BASE + AFE_TSTMSC_OFFSET)
+#define AFE_ENPADIO                            (AFE_BASE + AFE_ENPADIO_OFFSET)
+#define AFE_BGREG                              (AFE_BASE + AFE_BGREG_OFFSET)
+#define AFE_ACCESSAR_ID                        (AFE_BASE + AFE_ACCESSAR_ID_OFFSET)
+#define AFE_PDADC                              (AFE_BASE + AFE_PDADC_OFFSET)
+#define AFE_PDSARH                         (AFE_BASE + AFE_PDSARH_OFFSET)
+#define AFE_PDSARL                         (AFE_BASE + AFE_PDSARL_OFFSET)
+#define AFE_PDADCRFH                   (AFE_BASE + AFE_PDADCRFH_OFFSET)
+#define AFE_PDADCRFL                   (AFE_BASE + AFE_PDADCRFL_OFFSET)
+#define AFE_ACCTST                             (AFE_BASE + AFE_ACCTST_OFFSET)
+#define AFE_ADCGN                              (AFE_BASE + AFE_ADCGN_OFFSET)
+#define AFE_ICTRL                              (AFE_BASE + AFE_ICTRL_OFFSET)
+#define AFE_ICTLSTG                            (AFE_BASE + AFE_ICTLSTG_OFFSET)
+#define AFE_RCTRLSTG                   (AFE_BASE + AFE_RCTRLSTG_OFFSET)
+#define AFE_TCTRLSTG                   (AFE_BASE + AFE_TCTRLSTG_OFFSET)
+#define AFE_REFMOD                             (AFE_BASE + AFE_REFMOD_OFFSET)
+#define AFE_REFTRIML                   (AFE_BASE + AFE_REFTRIML_OFFSET)
+#define AFE_REFTRIMH                   (AFE_BASE + AFE_REFTRIMH_OFFSET)
+#define AFE_ADCR                               (AFE_BASE + AFE_ADCR_OFFSET)
+#define AFE_DUMMY0                             (AFE_BASE + AFE_DUMMY0_OFFSET)
+#define AFE_DUMMY1                             (AFE_BASE + AFE_DUMMY1_OFFSET)
+#define AFE_DUMMY2                             (AFE_BASE + AFE_DUMMY2_OFFSET)
+#define AFE_DACAMP                             (AFE_BASE + AFE_DACAMP_OFFSET)
+#define AFE_CLMPTST                            (AFE_BASE + AFE_CLMPTST_OFFSET)
+#define AFE_CLMPDAT                            (AFE_BASE + AFE_CLMPDAT_OFFSET)
+#define AFE_CLMPAMP                            (AFE_BASE + AFE_CLMPAMP_OFFSET)
+#define AFE_CLAMP                              (AFE_BASE + AFE_CLAMP_OFFSET)
+#define AFE_INPBUF                             (AFE_BASE + AFE_INPBUF_OFFSET)
+#define AFE_INPFLT                             (AFE_BASE + AFE_INPFLT_OFFSET)
+#define AFE_ADCDGN                             (AFE_BASE + AFE_ADCDGN_OFFSET)
+#define AFE_OFFDRV                             (AFE_BASE + AFE_OFFDRV_OFFSET)
+#define AFE_INPCONFIG                  (AFE_BASE + AFE_INPCONFIG_OFFSET)
+#define AFE_PROGDELAY                  (AFE_BASE + AFE_PROGDELAY_OFFSET)
+#define AFE_ADCOMT                             (AFE_BASE + AFE_ADCOMT_OFFSET)
+#define AFE_ALGDELAY                   (AFE_BASE + AFE_ALGDELAY_OFFSET)
+#define AFE_ACC_ID                             (AFE_BASE + AFE_ACC_ID_OFFSET)
+#define AFE_ACCSTA                             (AFE_BASE + AFE_ACCSTA_OFFSET)
+#define AFE_ACCNOSLI                   (AFE_BASE + AFE_ACCNOSLI_OFFSET)
+#define AFE_ACCCALCON                  (AFE_BASE + AFE_ACCCALCON_OFFSET)
+#define AFE_BWEWRICTRL                 (AFE_BASE + AFE_BWEWRICTRL_OFFSET)
+#define AFE_SELSLI                             (AFE_BASE + AFE_SELSLI_OFFSET)
+#define AFE_SELBYT                             (AFE_BASE + AFE_SELBYT_OFFSET)
+#define AFE_REDVAL                             (AFE_BASE + AFE_REDVAL_OFFSET)
+#define AFE_WRIBYT                             (AFE_BASE + AFE_WRIBYT_OFFSET)
+
+/* VDEC - Register offsets */
+#define VDEC_CFC1_OFFSET                0x00000000
+#define VDEC_CFC2_OFFSET                0x00000004
+#define VDEC_BRSTGT_OFFSET              0x00000024
+#define VDEC_HZPOS_OFFSET               0x00000040
+#define VDEC_VRTPOS_OFFSET              0x00000044
+#define VDEC_HVSHIFT_OFFSET             0x00000054
+#define VDEC_HSIGS_OFFSET               0x00000058
+#define VDEC_HSIGE_OFFSET               0x0000005C
+#define VDEC_VSCON1_OFFSET              0x00000060
+#define VDEC_VSCON2_OFFSET              0x00000064
+#define VDEC_YCDEL_OFFSET               0x0000006C
+#define VDEC_AFTCLP_OFFSET              0x00000070
+#define VDEC_DCOFF_OFFSET               0x00000078
+#define VDEC_CSID_OFFSET                0x00000084
+#define VDEC_CBGN_OFFSET                0x00000088
+#define VDEC_CRGN_OFFSET                0x0000008C
+#define VDEC_CNTR_OFFSET                0x00000090
+#define VDEC_BRT_OFFSET                 0x00000094
+#define VDEC_HUE_OFFSET                 0x00000098
+#define VDEC_CHBTH_OFFSET               0x0000009C
+#define VDEC_SHPIMP_OFFSET              0x000000A4
+#define VDEC_CHPLLIM_OFFSET             0x000000A8
+#define VDEC_VIDMOD_OFFSET              0x000000AC
+#define VDEC_VIDSTS_OFFSET              0x000000B0
+#define VDEC_NOISE_OFFSET               0x000000B4
+#define VDEC_STDDBG_OFFSET              0x000000B8
+#define VDEC_MANOVR_OFFSET              0x000000BC
+#define VDEC_VSSGTH_OFFSET              0x000000C8
+#define VDEC_DBGFBH_OFFSET              0x000000D0
+#define VDEC_DBGFBL_OFFSET              0x000000D4
+#define VDEC_HACTS_OFFSET               0x000000D8
+#define VDEC_HACTE_OFFSET               0x000000DC
+#define VDEC_VACTS_OFFSET               0x000000E0
+#define VDEC_VACTE_OFFSET               0x000000E4
+#define VDEC_HSTIP_OFFSET               0x000000EC
+#define VDEC_BLSCRY_OFFSET              0x000000F4
+#define VDEC_BLSCRCR_OFFSET             0x000000F8
+#define VDEC_BLSCRCB_OFFSET             0x000000FC
+#define VDEC_LMAGC1_OFFSET              0x00000100
+#define VDEC_LMAGC2_OFFSET              0x00000104
+#define VDEC_CHAGC1_OFFSET              0x00000108
+#define VDEC_CHAGC2_OFFSET              0x0000010C
+#define VDEC_MINTH_OFFSET               0x00000114
+#define VDEC_VFRQOH_OFFSET              0x0000011C
+#define VDEC_VFRQOL_OFFSET              0x00000120
+#define VDEC_THSH1_OFFSET               0x00000124
+#define VDEC_THSH2_OFFSET               0x00000128
+#define VDEC_NCHTH_OFFSET               0x0000012C
+#define VDEC_TH1F_OFFSET                0x00000130
+
+/* VDEC Register per module */
+#define VDEC_CFC1                        (VDEC_BASE + VDEC_CFC1_OFFSET)
+#define VDEC_CFC2                        (VDEC_BASE + VDEC_CFC2_OFFSET)
+#define VDEC_BRSTGT                      (VDEC_BASE + VDEC_BRSTGT_OFFSET)
+#define VDEC_HZPOS                       (VDEC_BASE + VDEC_HZPOS_OFFSET)
+#define VDEC_VRTPOS                      (VDEC_BASE + VDEC_VRTPOS_OFFSET)
+#define VDEC_HVSHIFT                     (VDEC_BASE + VDEC_HVSHIFT_OFFSET)
+#define VDEC_HSIGS                       (VDEC_BASE + VDEC_HSIGS_OFFSET)
+#define VDEC_HSIGE                       (VDEC_BASE + VDEC_HSIGE_OFFSET)
+#define VDEC_VSCON1                      (VDEC_BASE + VDEC_VSCON1_OFFSET)
+#define VDEC_VSCON2                      (VDEC_BASE + VDEC_VSCON2_OFFSET)
+#define VDEC_YCDEL                       (VDEC_BASE + VDEC_YCDEL_OFFSET)
+#define VDEC_AFTCLP                      (VDEC_BASE + VDEC_AFTCLP_OFFSET)
+#define VDEC_DCOFF                       (VDEC_BASE + VDEC_DCOFF_OFFSET)
+#define VDEC_CSID                        (VDEC_BASE + VDEC_CSID_OFFSET)
+#define VDEC_CBGN                        (VDEC_BASE + VDEC_CBGN_OFFSET)
+#define VDEC_CRGN                        (VDEC_BASE + VDEC_CRGN_OFFSET)
+#define VDEC_CNTR                        (VDEC_BASE + VDEC_CNTR_OFFSET)
+#define VDEC_BRT                         (VDEC_BASE + VDEC_BRT_OFFSET)
+#define VDEC_HUE                         (VDEC_BASE + VDEC_HUE_OFFSET)
+#define VDEC_CHBTH                       (VDEC_BASE + VDEC_CHBTH_OFFSET)
+#define VDEC_SHPIMP                      (VDEC_BASE + VDEC_SHPIMP_OFFSET)
+#define VDEC_CHPLLIM                     (VDEC_BASE + VDEC_CHPLLIM_OFFSET)
+#define VDEC_VIDMOD                      (VDEC_BASE + VDEC_VIDMOD_OFFSET)
+#define VDEC_VIDSTS                      (VDEC_BASE + VDEC_VIDSTS_OFFSET)
+#define VDEC_NOISE                       (VDEC_BASE + VDEC_NOISE_OFFSET)
+#define VDEC_STDDBG                      (VDEC_BASE + VDEC_STDDBG_OFFSET)
+#define VDEC_MANOVR                      (VDEC_BASE + VDEC_MANOVR_OFFSET)
+#define VDEC_VSSGTH                      (VDEC_BASE + VDEC_VSSGTH_OFFSET)
+#define VDEC_DBGFBH                      (VDEC_BASE + VDEC_DBGFBH_OFFSET)
+#define VDEC_DBGFBL                      (VDEC_BASE + VDEC_DBGFBL_OFFSET)
+#define VDEC_HACTS                       (VDEC_BASE + VDEC_HACTS_OFFSET)
+#define VDEC_HACTE                       (VDEC_BASE + VDEC_HACTE_OFFSET)
+#define VDEC_VACTS                       (VDEC_BASE + VDEC_VACTS_OFFSET)
+#define VDEC_VACTE                       (VDEC_BASE + VDEC_VACTE_OFFSET)
+#define VDEC_HSTIP                       (VDEC_BASE + VDEC_HSTIP_OFFSET)
+#define VDEC_BLSCRY                      (VDEC_BASE + VDEC_BLSCRY_OFFSET)
+#define VDEC_BLSCRCR                     (VDEC_BASE + VDEC_BLSCRCR_OFFSET)
+#define VDEC_BLSCRCB                     (VDEC_BASE + VDEC_BLSCRCB_OFFSET)
+#define VDEC_LMAGC1                      (VDEC_BASE + VDEC_LMAGC1_OFFSET)
+#define VDEC_LMAGC2                      (VDEC_BASE + VDEC_LMAGC2_OFFSET)
+#define VDEC_CHAGC1                      (VDEC_BASE + VDEC_CHAGC1_OFFSET)
+#define VDEC_CHAGC2                      (VDEC_BASE + VDEC_CHAGC2_OFFSET)
+#define VDEC_MINTH                       (VDEC_BASE + VDEC_MINTH_OFFSET)
+#define VDEC_VFRQOH                      (VDEC_BASE + VDEC_VFRQOH_OFFSET)
+#define VDEC_VFRQOL                      (VDEC_BASE + VDEC_VFRQOL_OFFSET)
+#define VDEC_THSH1                       (VDEC_BASE + VDEC_THSH1_OFFSET)
+#define VDEC_THSH2                       (VDEC_BASE + VDEC_THSH2_OFFSET)
+#define VDEC_NCHTH                       (VDEC_BASE + VDEC_NCHTH_OFFSET)
+#define VDEC_TH1F                        (VDEC_BASE + VDEC_TH1F_OFFSET)
+
+#define VDEC_VIDMOD_SIGNAL_MASK           0x0F
+#define VDEC_VIDMOD_SIGNAL_DETECT         0x0F
+
+#define VDEC_VIDMOD_M625_SHIFT            4
+#define VDEC_VIDMOD_M625_MASK             (1 << VDEC_VIDMOD_M625_SHIFT)
+
+#define VDEC_VIDMOD_PAL_SHIFT             7
+#define VDEC_VIDMOD_PAL_MASK              (1 << VDEC_VIDMOD_PAL_SHIFT)
+/*** define base address ***/
+
+#endif
diff --git a/drivers/media/platform/mxc/capture/ov5640_mipi_v2.c b/drivers/media/platform/mxc/capture/ov5640_mipi_v2.c
new file mode 100644 (file)
index 0000000..4ea4f6a
--- /dev/null
@@ -0,0 +1,1660 @@
+/*
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define OV5640_VOLTAGE_ANALOG               2800000
+#define OV5640_VOLTAGE_DIGITAL_CORE         1500000
+#define OV5640_VOLTAGE_DIGITAL_IO           1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5640_XCLK_MIN 6000000
+#define OV5640_XCLK_MAX 24000000
+
+#define OV5640_CHIP_ID_HIGH_BYTE       0x300A
+#define OV5640_CHIP_ID_LOW_BYTE                0x300B
+
+enum ov5640_mode {
+       ov5640_mode_MIN = 0,
+       ov5640_mode_VGA_640_480 = 0,
+       ov5640_mode_NTSC_720_480 = 1,
+       ov5640_mode_720P_1280_720 = 2,
+       ov5640_mode_1080P_1920_1080 = 3,
+       ov5640_mode_QSXGA_2592_1944 = 4,
+       ov5640_mode_MAX = 5,
+       ov5640_mode_INIT = 0xff, /*only for sensor init*/
+};
+
+enum ov5640_frame_rate {
+       ov5640_15_fps,
+       ov5640_30_fps
+};
+
+static int ov5640_framerates[] = {
+       [ov5640_15_fps] = 15,
+       [ov5640_30_fps] = 30,
+};
+
+struct ov5640_datafmt {
+       u32     code;
+       enum v4l2_colorspace            colorspace;
+};
+
+/* image size under 1280 * 960 are SUBSAMPLING
+ * image size upper 1280 * 960 are SCALING
+ */
+enum ov5640_downsize_mode {
+       SUBSAMPLING,
+       SCALING,
+};
+
+struct reg_value {
+       u16 u16RegAddr;
+       u8 u8Val;
+       u8 u8Mask;
+       u32 u32Delay_ms;
+};
+
+struct ov5640_mode_info {
+       enum ov5640_mode mode;
+       enum ov5640_downsize_mode dn_mode;
+       u32 width;
+       u32 height;
+       struct reg_value *init_data_ptr;
+       u32 init_data_size;
+};
+
+struct ov5640 {
+       struct v4l2_subdev              subdev;
+       struct i2c_client *i2c_client;
+       struct v4l2_pix_format pix;
+       const struct ov5640_datafmt     *fmt;
+       struct v4l2_captureparm streamcap;
+       bool on;
+
+       /* control settings */
+       int brightness;
+       int hue;
+       int contrast;
+       int saturation;
+       int red;
+       int green;
+       int blue;
+       int ae_mode;
+
+       u32 mclk;
+       u8 mclk_source;
+       struct clk *sensor_clk;
+       int csi;
+
+       void (*io_init)(void);
+};
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct ov5640 ov5640_data;
+static int pwn_gpio, rst_gpio;
+
+static struct reg_value ov5640_init_setting_30fps_VGA[] = {
+
+       {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
+       {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
+       {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
+       {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
+       {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
+       {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+       {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
+       {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
+       {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
+       {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
+       {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
+       {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
+       {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
+       {0x3c01, 0xa4, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
+       {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
+       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+       {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x30, 0, 0},
+       {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
+       {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
+       {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
+       {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
+       {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0},
+       {0x518a, 0x54, 0, 0}, {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0},
+       {0x518d, 0x50, 0, 0}, {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0},
+       {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0},
+       {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0},
+       {0x5199, 0x6c, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0},
+       {0x519c, 0x09, 0, 0}, {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0},
+       {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0},
+       {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0},
+       {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0},
+       {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0},
+       {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0},
+       {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0},
+       {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0},
+       {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0},
+       {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0},
+       {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0},
+       {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0},
+       {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0},
+       {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0},
+       {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0},
+       {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0},
+       {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0},
+       {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0},
+       {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0},
+       {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0},
+       {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0},
+       {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0},
+       {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0},
+       {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0},
+       {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0},
+       {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0},
+       {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0},
+       {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0},
+       {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0},
+       {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0},
+       {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0},
+       {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0},
+       {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0},
+       {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0},
+       {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0},
+       {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0},
+       {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0},
+       {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0},
+       {0x3a1f, 0x14, 0, 0}, {0x3008, 0x42, 0, 0}, {0x3c00, 0x04, 0, 300},
+};
+
+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
+       {0x3008, 0x42, 0, 0},
+       {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+       {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
+       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+       {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
+       {0x3008, 0x42, 0, 0},
+       {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+       {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
+       {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+       {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
+       {0x3008, 0x42, 0, 0},
+       {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
+       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+       {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+       {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
+       {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
+       {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
+       {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
+       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+       {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, {0x4005, 0x1a, 0, 0},
+       {0x3008, 0x02, 0, 0}, {0x3503, 0,    0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
+       {0x3008, 0x42, 0, 0},
+       {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
+       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+       {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
+       {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+       {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+       {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+       {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
+       {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
+       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+       {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
+       {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
+       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+       {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
+       {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
+       {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
+       {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
+       {0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
+       {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
+       {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
+       {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
+       {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
+       {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
+       {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0},
+       {0x3503, 0, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
+       {0x3008, 0x42, 0, 0},
+       {0x4202, 0x0f, 0, 0},   /* stream off the sensor */
+       {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, /*disable flip*/
+       {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
+       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+       {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
+       {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+       {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+       {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+       {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
+       {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
+       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+       {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70}, {0x3008, 0x02, 0, 0},
+       {0x4202, 0x00, 0, 0},   /* stream on the sensor */
+};
+
+static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
+       {
+               {ov5640_mode_VGA_640_480, -1, 0, 0, NULL, 0},
+               {ov5640_mode_NTSC_720_480, -1, 0, 0, NULL, 0},
+               {ov5640_mode_720P_1280_720, -1, 0, 0, NULL, 0},
+               {ov5640_mode_1080P_1920_1080, -1, 0, 0, NULL, 0},
+               {ov5640_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
+               ov5640_setting_15fps_QSXGA_2592_1944,
+               ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
+       },
+       {
+               {ov5640_mode_VGA_640_480, SUBSAMPLING, 640,  480,
+               ov5640_setting_30fps_VGA_640_480,
+               ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
+               {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
+               ov5640_setting_30fps_NTSC_720_480,
+               ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
+               {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
+               ov5640_setting_30fps_720P_1280_720,
+               ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
+               {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
+               ov5640_setting_30fps_1080P_1920_1080,
+               ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
+               {ov5640_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
+       },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+static struct regulator *gpo_regulator;
+
+static int ov5640_probe(struct i2c_client *adapter,
+                               const struct i2c_device_id *device_id);
+static int ov5640_remove(struct i2c_client *client);
+
+static s32 ov5640_read_reg(u16 reg, u8 *val);
+static s32 ov5640_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5640_id[] = {
+       {"ov5640_mipi", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+       .driver = {
+                 .owner = THIS_MODULE,
+                 .name  = "ov5640_mipi",
+                 },
+       .probe  = ov5640_probe,
+       .remove = ov5640_remove,
+       .id_table = ov5640_id,
+};
+
+static const struct ov5640_datafmt ov5640_colour_fmts[] = {
+       {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+};
+
+static struct ov5640 *to_ov5640(const struct i2c_client *client)
+{
+       return container_of(i2c_get_clientdata(client), struct ov5640, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct ov5640_datafmt
+                       *ov5640_find_datafmt(u32 code)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ov5640_colour_fmts); i++)
+               if (ov5640_colour_fmts[i].code == code)
+                       return ov5640_colour_fmts + i;
+
+       return NULL;
+}
+
+static inline void ov5640_power_down(int enable)
+{
+       if (pwn_gpio < 0)
+               return;
+
+       if (!enable)
+               gpio_set_value_cansleep(pwn_gpio, 0);
+       else
+               gpio_set_value_cansleep(pwn_gpio, 1);
+
+       msleep(2);
+}
+
+static void ov5640_reset(void)
+{
+       if (rst_gpio < 0 || pwn_gpio < 0)
+               return;
+
+       /* camera reset */
+       gpio_set_value(rst_gpio, 1);
+
+       /* camera power dowmn */
+       gpio_set_value(pwn_gpio, 1);
+       msleep(5);
+
+       gpio_set_value(pwn_gpio, 0);
+       msleep(5);
+
+       gpio_set_value(rst_gpio, 0);
+       msleep(1);
+
+       gpio_set_value(rst_gpio, 1);
+       msleep(5);
+
+       gpio_set_value(pwn_gpio, 1);
+}
+
+static int ov5640_regulator_enable(struct device *dev)
+{
+       int ret = 0;
+
+       io_regulator = devm_regulator_get(dev, "DOVDD");
+       if (!IS_ERR(io_regulator)) {
+               regulator_set_voltage(io_regulator,
+                                     OV5640_VOLTAGE_DIGITAL_IO,
+                                     OV5640_VOLTAGE_DIGITAL_IO);
+               ret = regulator_enable(io_regulator);
+               if (ret) {
+                       pr_err("%s:io set voltage error\n", __func__);
+                       return ret;
+               } else {
+                       dev_dbg(dev,
+                               "%s:io set voltage ok\n", __func__);
+               }
+       } else {
+               pr_err("%s: cannot get io voltage error\n", __func__);
+               io_regulator = NULL;
+       }
+
+       core_regulator = devm_regulator_get(dev, "DVDD");
+       if (!IS_ERR(core_regulator)) {
+               regulator_set_voltage(core_regulator,
+                                     OV5640_VOLTAGE_DIGITAL_CORE,
+                                     OV5640_VOLTAGE_DIGITAL_CORE);
+               ret = regulator_enable(core_regulator);
+               if (ret) {
+                       pr_err("%s:core set voltage error\n", __func__);
+                       return ret;
+               } else {
+                       dev_dbg(dev,
+                               "%s:core set voltage ok\n", __func__);
+               }
+       } else {
+               core_regulator = NULL;
+               pr_err("%s: cannot get core voltage error\n", __func__);
+       }
+
+       analog_regulator = devm_regulator_get(dev, "AVDD");
+       if (!IS_ERR(analog_regulator)) {
+               regulator_set_voltage(analog_regulator,
+                                     OV5640_VOLTAGE_ANALOG,
+                                     OV5640_VOLTAGE_ANALOG);
+               ret = regulator_enable(analog_regulator);
+               if (ret) {
+                       pr_err("%s:analog set voltage error\n",
+                               __func__);
+                       return ret;
+               } else {
+                       dev_dbg(dev,
+                               "%s:analog set voltage ok\n", __func__);
+               }
+       } else {
+               analog_regulator = NULL;
+               pr_err("%s: cannot get analog voltage error\n", __func__);
+       }
+
+       return ret;
+}
+
+static s32 ov5640_write_reg(u16 reg, u8 val)
+{
+       u8 au8Buf[3] = {0};
+
+       au8Buf[0] = reg >> 8;
+       au8Buf[1] = reg & 0xff;
+       au8Buf[2] = val;
+
+       if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
+               pr_err("%s:write reg error:reg=%x,val=%x\n",
+                       __func__, reg, val);
+               return -1;
+       }
+
+       return 0;
+}
+
+static s32 ov5640_read_reg(u16 reg, u8 *val)
+{
+       u8 au8RegBuf[2] = {0};
+       u8 u8RdVal = 0;
+
+       au8RegBuf[0] = reg >> 8;
+       au8RegBuf[1] = reg & 0xff;
+
+       if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
+               pr_err("%s:write reg error:reg=%x\n",
+                               __func__, reg);
+               return -1;
+       }
+
+       if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
+               pr_err("%s:read reg error:reg=%x,val=%x\n",
+                               __func__, reg, u8RdVal);
+               return -1;
+       }
+
+       *val = u8RdVal;
+
+       return u8RdVal;
+}
+
+static int prev_sysclk, prev_HTS;
+static int AE_low, AE_high, AE_Target = 52;
+
+static void OV5640_stream_on(void)
+{
+       ov5640_write_reg(0x4202, 0x00);
+}
+
+static void OV5640_stream_off(void)
+{
+       ov5640_write_reg(0x4202, 0x0f);
+       ov5640_write_reg(0x3008, 0x42);
+}
+
+static int OV5640_get_sysclk(void)
+{
+        /* calculate sysclk */
+       int xvclk = ov5640_data.mclk / 10000;
+       int temp1, temp2;
+       int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv;
+       int Bit_div2x = 1, sclk_rdiv, sysclk;
+       u8 temp;
+
+       int sclk_rdiv_map[] = {1, 2, 4, 8};
+
+       temp1 = ov5640_read_reg(0x3034, &temp);
+       temp2 = temp1 & 0x0f;
+       if (temp2 == 8 || temp2 == 10)
+               Bit_div2x = temp2 / 2;
+
+       temp1 = ov5640_read_reg(0x3035, &temp);
+       SysDiv = temp1>>4;
+       if (SysDiv == 0)
+               SysDiv = 16;
+
+       temp1 = ov5640_read_reg(0x3036, &temp);
+       Multiplier = temp1;
+
+       temp1 = ov5640_read_reg(0x3037, &temp);
+       PreDiv = temp1 & 0x0f;
+       Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
+
+       temp1 = ov5640_read_reg(0x3108, &temp);
+       temp2 = temp1 & 0x03;
+       sclk_rdiv = sclk_rdiv_map[temp2];
+
+       VCO = xvclk * Multiplier / PreDiv;
+
+       sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
+
+       return sysclk;
+}
+
+static void OV5640_set_night_mode(void)
+{
+        /* read HTS from register settings */
+       u8 mode;
+
+       ov5640_read_reg(0x3a00, &mode);
+       mode &= 0xfb;
+       ov5640_write_reg(0x3a00, mode);
+}
+
+static int OV5640_get_HTS(void)
+{
+        /* read HTS from register settings */
+       int HTS;
+       u8 temp;
+
+       HTS = ov5640_read_reg(0x380c, &temp);
+       HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
+
+       return HTS;
+}
+
+static int OV5640_get_VTS(void)
+{
+        /* read VTS from register settings */
+       int VTS;
+       u8 temp;
+
+       /* total vertical size[15:8] high byte */
+       VTS = ov5640_read_reg(0x380e, &temp);
+
+       VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
+
+       return VTS;
+}
+
+static int OV5640_set_VTS(int VTS)
+{
+        /* write VTS to registers */
+        int temp;
+
+        temp = VTS & 0xff;
+        ov5640_write_reg(0x380f, temp);
+
+        temp = VTS>>8;
+        ov5640_write_reg(0x380e, temp);
+
+        return 0;
+}
+
+static int OV5640_get_shutter(void)
+{
+        /* read shutter, in number of line period */
+       int shutter;
+       u8 temp;
+
+       shutter = (ov5640_read_reg(0x03500, &temp) & 0x0f);
+       shutter = (shutter<<8) + ov5640_read_reg(0x3501, &temp);
+       shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &temp)>>4);
+
+        return shutter;
+}
+
+static int OV5640_set_shutter(int shutter)
+{
+        /* write shutter, in number of line period */
+        int temp;
+
+        shutter = shutter & 0xffff;
+
+        temp = shutter & 0x0f;
+        temp = temp<<4;
+        ov5640_write_reg(0x3502, temp);
+
+        temp = shutter & 0xfff;
+        temp = temp>>4;
+        ov5640_write_reg(0x3501, temp);
+
+        temp = shutter>>12;
+        ov5640_write_reg(0x3500, temp);
+
+        return 0;
+}
+
+static int OV5640_get_gain16(void)
+{
+        /* read gain, 16 = 1x */
+       int gain16;
+       u8 temp;
+
+       gain16 = ov5640_read_reg(0x350a, &temp) & 0x03;
+       gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &temp);
+
+       return gain16;
+}
+
+static int OV5640_set_gain16(int gain16)
+{
+       /* write gain, 16 = 1x */
+       u8 temp;
+       gain16 = gain16 & 0x3ff;
+
+       temp = gain16 & 0xff;
+       ov5640_write_reg(0x350b, temp);
+
+       temp = gain16>>8;
+       ov5640_write_reg(0x350a, temp);
+
+       return 0;
+}
+
+static int OV5640_get_light_freq(void)
+{
+       /* get banding filter value */
+       int temp, temp1, light_freq = 0;
+       u8 tmp;
+
+       temp = ov5640_read_reg(0x3c01, &tmp);
+
+       if (temp & 0x80) {
+               /* manual */
+               temp1 = ov5640_read_reg(0x3c00, &tmp);
+               if (temp1 & 0x04) {
+                       /* 50Hz */
+                       light_freq = 50;
+               } else {
+                       /* 60Hz */
+                       light_freq = 60;
+               }
+       } else {
+               /* auto */
+               temp1 = ov5640_read_reg(0x3c0c, &tmp);
+               if (temp1 & 0x01) {
+                       /* 50Hz */
+                       light_freq = 50;
+               } else {
+                       /* 60Hz */
+               }
+       }
+       return light_freq;
+}
+
+static void OV5640_set_bandingfilter(void)
+{
+       int prev_VTS;
+       int band_step60, max_band60, band_step50, max_band50;
+
+       /* read preview PCLK */
+       prev_sysclk = OV5640_get_sysclk();
+       /* read preview HTS */
+       prev_HTS = OV5640_get_HTS();
+
+       /* read preview VTS */
+       prev_VTS = OV5640_get_VTS();
+
+       /* calculate banding filter */
+       /* 60Hz */
+       band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
+       ov5640_write_reg(0x3a0a, (band_step60 >> 8));
+       ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
+
+       max_band60 = (int)((prev_VTS-4)/band_step60);
+       ov5640_write_reg(0x3a0d, max_band60);
+
+       /* 50Hz */
+       band_step50 = prev_sysclk * 100/prev_HTS;
+       ov5640_write_reg(0x3a08, (band_step50 >> 8));
+       ov5640_write_reg(0x3a09, (band_step50 & 0xff));
+
+       max_band50 = (int)((prev_VTS-4)/band_step50);
+       ov5640_write_reg(0x3a0e, max_band50);
+}
+
+static int OV5640_set_AE_target(int target)
+{
+       /* stable in high */
+       int fast_high, fast_low;
+       AE_low = target * 23 / 25;      /* 0.92 */
+       AE_high = target * 27 / 25;     /* 1.08 */
+
+       fast_high = AE_high<<1;
+       if (fast_high > 255)
+               fast_high = 255;
+
+       fast_low = AE_low >> 1;
+
+       ov5640_write_reg(0x3a0f, AE_high);
+       ov5640_write_reg(0x3a10, AE_low);
+       ov5640_write_reg(0x3a1b, AE_high);
+       ov5640_write_reg(0x3a1e, AE_low);
+       ov5640_write_reg(0x3a11, fast_high);
+       ov5640_write_reg(0x3a1f, fast_low);
+
+       return 0;
+}
+
+static void OV5640_turn_on_AE_AG(int enable)
+{
+       u8 ae_ag_ctrl;
+
+       ov5640_read_reg(0x3503, &ae_ag_ctrl);
+       if (enable) {
+               /* turn on auto AE/AG */
+               ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
+       } else {
+               /* turn off AE/AG */
+               ae_ag_ctrl = ae_ag_ctrl | 0x03;
+       }
+       ov5640_write_reg(0x3503, ae_ag_ctrl);
+}
+
+static bool binning_on(void)
+{
+       u8 temp;
+       ov5640_read_reg(0x3821, &temp);
+       temp &= 0xfe;
+       if (temp)
+               return true;
+       else
+               return false;
+}
+
+static void ov5640_set_virtual_channel(int channel)
+{
+       u8 channel_id;
+
+       ov5640_read_reg(0x4814, &channel_id);
+       channel_id &= ~(3 << 6);
+       ov5640_write_reg(0x4814, channel_id | (channel << 6));
+}
+
+/* download ov5640 settings to sensor through i2c */
+static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+{
+       register u32 Delay_ms = 0;
+       register u16 RegAddr = 0;
+       register u8 Mask = 0;
+       register u8 Val = 0;
+       u8 RegVal = 0;
+       int i, retval = 0;
+
+       for (i = 0; i < ArySize; ++i, ++pModeSetting) {
+               Delay_ms = pModeSetting->u32Delay_ms;
+               RegAddr = pModeSetting->u16RegAddr;
+               Val = pModeSetting->u8Val;
+               Mask = pModeSetting->u8Mask;
+
+               if (Mask) {
+                       retval = ov5640_read_reg(RegAddr, &RegVal);
+                       if (retval < 0)
+                               goto err;
+
+                       RegVal &= ~(u8)Mask;
+                       Val &= Mask;
+                       Val |= RegVal;
+               }
+
+               retval = ov5640_write_reg(RegAddr, Val);
+               if (retval < 0)
+                       goto err;
+
+               if (Delay_ms)
+                       msleep(Delay_ms);
+       }
+err:
+       return retval;
+}
+
+/* sensor changes between scaling and subsampling
+ * go through exposure calcualtion
+ */
+static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
+                               enum ov5640_mode mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 ArySize = 0;
+       u8 average;
+       int prev_shutter, prev_gain16;
+       int cap_shutter, cap_gain16;
+       int cap_sysclk, cap_HTS, cap_VTS;
+       int light_freq, cap_bandfilt, cap_maxband;
+       long cap_gain16_shutter;
+       int retval = 0;
+
+       /* check if the input mode and frame rate is valid */
+       pModeSetting =
+               ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+       ArySize =
+               ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+       ov5640_data.pix.width =
+               ov5640_mode_info_data[frame_rate][mode].width;
+       ov5640_data.pix.height =
+               ov5640_mode_info_data[frame_rate][mode].height;
+
+       if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+               pModeSetting == NULL || ArySize == 0)
+               return -EINVAL;
+
+       /* auto focus */
+       /* OV5640_auto_focus();//if no af function, just skip it */
+
+       /* turn off AE/AG */
+       OV5640_turn_on_AE_AG(0);
+
+       /* read preview shutter */
+       prev_shutter = OV5640_get_shutter();
+       if ((binning_on()) && (mode != ov5640_mode_720P_1280_720)
+                       && (mode != ov5640_mode_1080P_1920_1080))
+               prev_shutter *= 2;
+
+       /* read preview gain */
+       prev_gain16 = OV5640_get_gain16();
+
+       /* get average */
+       ov5640_read_reg(0x56a1, &average);
+
+       /* turn off night mode for capture */
+       OV5640_set_night_mode();
+
+       /* turn off overlay */
+       /* ov5640_write_reg(0x3022, 0x06);//if no af function, just skip it */
+
+       OV5640_stream_off();
+
+       /* Write capture setting */
+       retval = ov5640_download_firmware(pModeSetting, ArySize);
+       if (retval < 0)
+               goto err;
+
+       /* read capture VTS */
+       cap_VTS = OV5640_get_VTS();
+       cap_HTS = OV5640_get_HTS();
+       cap_sysclk = OV5640_get_sysclk();
+
+       /* calculate capture banding filter */
+       light_freq = OV5640_get_light_freq();
+       if (light_freq == 60) {
+               /* 60Hz */
+               cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
+       } else {
+               /* 50Hz */
+               cap_bandfilt = cap_sysclk * 100 / cap_HTS;
+       }
+       cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
+
+       /* calculate capture shutter/gain16 */
+       if (average > AE_low && average < AE_high) {
+               /* in stable range */
+               cap_gain16_shutter =
+                 prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
+                 * prev_HTS/cap_HTS * AE_Target / average;
+       } else {
+               cap_gain16_shutter =
+                 prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
+                 * prev_HTS/cap_HTS;
+       }
+
+       /* gain to shutter */
+       if (cap_gain16_shutter < (cap_bandfilt * 16)) {
+               /* shutter < 1/100 */
+               cap_shutter = cap_gain16_shutter/16;
+               if (cap_shutter < 1)
+                       cap_shutter = 1;
+
+               cap_gain16 = cap_gain16_shutter/cap_shutter;
+               if (cap_gain16 < 16)
+                       cap_gain16 = 16;
+       } else {
+               if (cap_gain16_shutter >
+                               (cap_bandfilt * cap_maxband * 16)) {
+                       /* exposure reach max */
+                       cap_shutter = cap_bandfilt * cap_maxband;
+                       cap_gain16 = cap_gain16_shutter / cap_shutter;
+               } else {
+                       /* 1/100 < (cap_shutter = n/100) =< max */
+                       cap_shutter =
+                         ((int) (cap_gain16_shutter/16 / cap_bandfilt))
+                         *cap_bandfilt;
+                       cap_gain16 = cap_gain16_shutter / cap_shutter;
+               }
+       }
+
+       /* write capture gain */
+       OV5640_set_gain16(cap_gain16);
+
+       /* write capture shutter */
+       if (cap_shutter > (cap_VTS - 4)) {
+               cap_VTS = cap_shutter + 4;
+               OV5640_set_VTS(cap_VTS);
+       }
+       OV5640_set_shutter(cap_shutter);
+
+err:
+       return retval;
+}
+
+/* if sensor changes inside scaling or subsampling
+ * change mode directly
+ * */
+static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
+                               enum ov5640_mode mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 ArySize = 0;
+       int retval = 0;
+
+       /* check if the input mode and frame rate is valid */
+       pModeSetting =
+               ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+       ArySize =
+               ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+       ov5640_data.pix.width =
+               ov5640_mode_info_data[frame_rate][mode].width;
+       ov5640_data.pix.height =
+               ov5640_mode_info_data[frame_rate][mode].height;
+
+       if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+               pModeSetting == NULL || ArySize == 0)
+               return -EINVAL;
+
+       /* turn off AE/AG */
+       OV5640_turn_on_AE_AG(0);
+
+       OV5640_stream_off();
+
+       /* Write capture setting */
+       retval = ov5640_download_firmware(pModeSetting, ArySize);
+       if (retval < 0)
+               goto err;
+
+       OV5640_turn_on_AE_AG(1);
+
+err:
+       return retval;
+}
+
+static int ov5640_init_mode(enum ov5640_frame_rate frame_rate,
+                           enum ov5640_mode mode, enum ov5640_mode orig_mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 ArySize = 0;
+       int retval = 0;
+       u32 msec_wait4stable = 0;
+       enum ov5640_downsize_mode dn_mode, orig_dn_mode;
+
+       if ((mode > ov5640_mode_MAX || mode < ov5640_mode_MIN)
+               && (mode != ov5640_mode_INIT)) {
+               pr_err("Wrong ov5640 mode detected!\n");
+               return -1;
+       }
+
+       dn_mode = ov5640_mode_info_data[frame_rate][mode].dn_mode;
+       orig_dn_mode = ov5640_mode_info_data[frame_rate][orig_mode].dn_mode;
+       if (mode == ov5640_mode_INIT) {
+               pModeSetting = ov5640_init_setting_30fps_VGA;
+               ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
+
+               ov5640_data.pix.width = 640;
+               ov5640_data.pix.height = 480;
+               retval = ov5640_download_firmware(pModeSetting, ArySize);
+               if (retval < 0)
+                       goto err;
+
+               pModeSetting = ov5640_setting_30fps_VGA_640_480;
+               ArySize = ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480);
+               retval = ov5640_download_firmware(pModeSetting, ArySize);
+       } else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
+                       (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
+               /* change between subsampling and scaling
+                * go through exposure calucation */
+               retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
+       } else {
+               /* change inside subsampling or scaling
+                * download firmware directly */
+               retval = ov5640_change_mode_direct(frame_rate, mode);
+       }
+
+       if (retval < 0)
+               goto err;
+
+       OV5640_set_AE_target(AE_Target);
+       OV5640_get_light_freq();
+       OV5640_set_bandingfilter();
+       ov5640_set_virtual_channel(ov5640_data.csi);
+
+       /* add delay to wait for sensor stable */
+       if (mode == ov5640_mode_QSXGA_2592_1944) {
+               /* dump the first two frames: 1/7.5*2
+                * the frame rate of QSXGA is 7.5fps */
+               msec_wait4stable = 267;
+       } else {
+               /* dump the first eighteen frames: 1/30*18 */
+               msec_wait4stable = 600;
+       }
+       msleep(msec_wait4stable);
+
+err:
+       return retval;
+}
+
+/*!
+ * ov5640_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ov5640_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+
+       if (on && !sensor->on) {
+               if (io_regulator)
+                       if (regulator_enable(io_regulator) != 0)
+                               return -EIO;
+               if (core_regulator)
+                       if (regulator_enable(core_regulator) != 0)
+                               return -EIO;
+               if (gpo_regulator)
+                       if (regulator_enable(gpo_regulator) != 0)
+                               return -EIO;
+               if (analog_regulator)
+                       if (regulator_enable(analog_regulator) != 0)
+                               return -EIO;
+       } else if (!on && sensor->on) {
+               if (analog_regulator)
+                       regulator_disable(analog_regulator);
+               if (core_regulator)
+                       regulator_disable(core_regulator);
+               if (io_regulator)
+                       regulator_disable(io_regulator);
+               if (gpo_regulator)
+                       regulator_disable(gpo_regulator);
+       }
+
+       sensor->on = on;
+
+       return 0;
+}
+
+/*!
+ * ov5640_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ov5640_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+       struct v4l2_captureparm *cparm = &a->parm.capture;
+       int ret = 0;
+
+       switch (a->type) {
+       /* This is the only case currently handled. */
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               memset(a, 0, sizeof(*a));
+               a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               cparm->capability = sensor->streamcap.capability;
+               cparm->timeperframe = sensor->streamcap.timeperframe;
+               cparm->capturemode = sensor->streamcap.capturemode;
+               ret = 0;
+               break;
+
+       /* These are all the possible cases. */
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_VBI_OUTPUT:
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+               ret = -EINVAL;
+               break;
+
+       default:
+               pr_debug("   type is unknown - %d\n", a->type);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+/*!
+ * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible.  If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ov5640_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+       u32 tgt_fps;    /* target frames per secound */
+       enum ov5640_frame_rate frame_rate;
+       enum ov5640_mode orig_mode;
+       int ret = 0;
+
+       switch (a->type) {
+       /* This is the only case currently handled. */
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               /* Check that the new frame rate is allowed. */
+               if ((timeperframe->numerator == 0) ||
+                   (timeperframe->denominator == 0)) {
+                       timeperframe->denominator = DEFAULT_FPS;
+                       timeperframe->numerator = 1;
+               }
+
+               tgt_fps = timeperframe->denominator /
+                         timeperframe->numerator;
+
+               if (tgt_fps > MAX_FPS) {
+                       timeperframe->denominator = MAX_FPS;
+                       timeperframe->numerator = 1;
+               } else if (tgt_fps < MIN_FPS) {
+                       timeperframe->denominator = MIN_FPS;
+                       timeperframe->numerator = 1;
+               }
+
+               /* Actual frame rate we use */
+               tgt_fps = timeperframe->denominator /
+                         timeperframe->numerator;
+
+               if (tgt_fps == 15)
+                       frame_rate = ov5640_15_fps;
+               else if (tgt_fps == 30)
+                       frame_rate = ov5640_30_fps;
+               else {
+                       pr_err(" The camera frame rate is not supported!\n");
+                       return -EINVAL;
+               }
+
+               orig_mode = sensor->streamcap.capturemode;
+               ret = ov5640_init_mode(frame_rate,
+                               (u32)a->parm.capture.capturemode, orig_mode);
+               if (ret < 0)
+                       return ret;
+
+               sensor->streamcap.timeperframe = *timeperframe;
+               sensor->streamcap.capturemode =
+                               (u32)a->parm.capture.capturemode;
+
+               break;
+
+       /* These are all the possible cases. */
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_VBI_OUTPUT:
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+               pr_debug("   type is not " \
+                       "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+                       a->type);
+               ret = -EINVAL;
+               break;
+
+       default:
+               pr_debug("   type is unknown - %d\n", a->type);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int ov5640_set_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_subdev_pad_config *cfg,
+                       struct v4l2_subdev_format *format)
+{
+       struct v4l2_mbus_framefmt *mf = &format->format;
+       const struct ov5640_datafmt *fmt = ov5640_find_datafmt(mf->code);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+
+       if (!fmt) {
+               mf->code        = ov5640_colour_fmts[0].code;
+               mf->colorspace  = ov5640_colour_fmts[0].colorspace;
+       }
+
+       mf->field       = V4L2_FIELD_NONE;
+
+       if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+               return 0;
+
+       sensor->fmt = fmt;
+
+       return 0;
+}
+
+
+static int ov5640_get_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *format)
+{
+       struct v4l2_mbus_framefmt *mf = &format->format;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+       const struct ov5640_datafmt *fmt = sensor->fmt;
+
+       if (format->pad)
+               return -EINVAL;
+
+       mf->code        = fmt->code;
+       mf->colorspace  = fmt->colorspace;
+       mf->field       = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static int ov5640_enum_mbus_code(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_mbus_code_enum *code)
+{
+       if (code->pad || code->index >= ARRAY_SIZE(ov5640_colour_fmts))
+               return -EINVAL;
+
+       code->code = ov5640_colour_fmts[code->index].code;
+       return 0;
+}
+
+/*!
+ * ov5640_enum_framesizes - V4L2 sensor interface handler for
+ *                        VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5640_enum_framesizes(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_pad_config *cfg,
+                              struct v4l2_subdev_frame_size_enum *fse)
+{
+       if (fse->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       fse->max_width =
+                       max(ov5640_mode_info_data[0][fse->index].width,
+                           ov5640_mode_info_data[1][fse->index].width);
+       fse->min_width = fse->max_width;
+       fse->max_height =
+                       max(ov5640_mode_info_data[0][fse->index].height,
+                           ov5640_mode_info_data[1][fse->index].height);
+       fse->min_height = fse->max_height;
+       return 0;
+}
+
+/*!
+ * ov5640_enum_frameintervals - V4L2 sensor interface handler for
+ *                            VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5640_enum_frameintervals(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_frame_interval_enum *fie)
+{
+       int i, j, count = 0;
+
+       if (fie->index < 0 || fie->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       if (fie->width == 0 || fie->height == 0 ||
+           fie->code == 0) {
+               pr_warning("Please assign pixel format, width and height.\n");
+               return -EINVAL;
+       }
+
+       fie->interval.numerator = 1;
+
+       count = 0;
+       for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
+               for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
+                       if (fie->width == ov5640_mode_info_data[i][j].width
+                        && fie->height == ov5640_mode_info_data[i][j].height
+                        && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
+                               count++;
+                       }
+                       if (fie->index == (count - 1)) {
+                               fie->interval.denominator =
+                                               ov5640_framerates[i];
+                               return 0;
+                       }
+               }
+       }
+
+       return -EINVAL;
+}
+
+/*!
+ * dev_init - V4L2 sensor init
+ * @s: pointer to standard V4L2 device structure
+ *
+ */
+static int init_device(void)
+{
+       u32 tgt_xclk;   /* target xclk */
+       u32 tgt_fps;    /* target frames per secound */
+       enum ov5640_frame_rate frame_rate;
+       int ret;
+
+       ov5640_data.on = true;
+
+       /* mclk */
+       tgt_xclk = ov5640_data.mclk;
+       tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
+       tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
+       ov5640_data.mclk = tgt_xclk;
+
+       pr_debug("   Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+
+       /* Default camera frame rate is set in probe */
+       tgt_fps = ov5640_data.streamcap.timeperframe.denominator /
+                 ov5640_data.streamcap.timeperframe.numerator;
+
+       if (tgt_fps == 15)
+               frame_rate = ov5640_15_fps;
+       else if (tgt_fps == 30)
+               frame_rate = ov5640_30_fps;
+       else
+               return -EINVAL; /* Only support 15fps or 30fps now. */
+
+       ret = ov5640_init_mode(frame_rate, ov5640_mode_INIT, ov5640_mode_INIT);
+
+       return ret;
+}
+
+static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       if (enable)
+               OV5640_stream_on();
+       else
+               OV5640_stream_off();
+       return 0;
+}
+
+static struct v4l2_subdev_video_ops ov5640_subdev_video_ops = {
+       .g_parm = ov5640_g_parm,
+       .s_parm = ov5640_s_parm,
+       .s_stream = ov5640_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops ov5640_subdev_pad_ops = {
+       .enum_frame_size       = ov5640_enum_framesizes,
+       .enum_frame_interval   = ov5640_enum_frameintervals,
+       .enum_mbus_code        = ov5640_enum_mbus_code,
+       .set_fmt               = ov5640_set_fmt,
+       .get_fmt               = ov5640_get_fmt,
+};
+
+static struct v4l2_subdev_core_ops ov5640_subdev_core_ops = {
+       .s_power        = ov5640_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register     = ov5640_get_register,
+       .s_register     = ov5640_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5640_subdev_ops = {
+       .core   = &ov5640_subdev_core_ops,
+       .video  = &ov5640_subdev_video_ops,
+       .pad    = &ov5640_subdev_pad_ops,
+};
+
+
+/*!
+ * ov5640 I2C probe function
+ *
+ * @param adapter            struct i2c_adapter *
+ * @return  Error code indicating success or failure
+ */
+static int ov5640_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct pinctrl *pinctrl;
+       struct device *dev = &client->dev;
+       int retval;
+       u8 chip_id_high, chip_id_low;
+
+       /* ov5640 pinctrl */
+       pinctrl = devm_pinctrl_get_select_default(dev);
+       if (IS_ERR(pinctrl))
+               dev_warn(dev, "no pin available\n");
+
+       /* request power down pin */
+       pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+       if (!gpio_is_valid(pwn_gpio))
+               dev_warn(dev, "no sensor pwdn pin available");
+       else {
+               retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+                                               "ov5640_mipi_pwdn");
+               if (retval < 0) {
+                       dev_warn(dev, "Failed to set power pin\n");
+                       dev_warn(dev, "retval=%d\n", retval);
+                       return retval;
+               }
+       }
+
+       /* request reset pin */
+       rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+       if (!gpio_is_valid(rst_gpio))
+               dev_warn(dev, "no sensor reset pin available");
+       else {
+               retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+                                               "ov5640_mipi_reset");
+               if (retval < 0) {
+                       dev_warn(dev, "Failed to set reset pin\n");
+                       return retval;
+               }
+       }
+
+       /* Set initial values for the sensor struct. */
+       memset(&ov5640_data, 0, sizeof(ov5640_data));
+       ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+       if (IS_ERR(ov5640_data.sensor_clk)) {
+               /* assuming clock enabled by default */
+               ov5640_data.sensor_clk = NULL;
+               dev_err(dev, "clock-frequency missing or invalid\n");
+               return PTR_ERR(ov5640_data.sensor_clk);
+       }
+
+       retval = of_property_read_u32(dev->of_node, "mclk",
+                                       &(ov5640_data.mclk));
+       if (retval) {
+               dev_err(dev, "mclk missing or invalid\n");
+               return retval;
+       }
+
+       retval = of_property_read_u32(dev->of_node, "mclk_source",
+                                       (u32 *) &(ov5640_data.mclk_source));
+       if (retval) {
+               dev_err(dev, "mclk_source missing or invalid\n");
+               return retval;
+       }
+
+       retval = of_property_read_u32(dev->of_node, "csi_id",
+                                       &(ov5640_data.csi));
+       if (retval) {
+               dev_err(dev, "csi id missing or invalid\n");
+               return retval;
+       }
+
+       clk_prepare_enable(ov5640_data.sensor_clk);
+
+       ov5640_data.io_init = ov5640_reset;
+       ov5640_data.i2c_client = client;
+       ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+       ov5640_data.pix.width = 640;
+       ov5640_data.pix.height = 480;
+       ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+                                          V4L2_CAP_TIMEPERFRAME;
+       ov5640_data.streamcap.capturemode = 0;
+       ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+       ov5640_data.streamcap.timeperframe.numerator = 1;
+
+       ov5640_regulator_enable(&client->dev);
+
+       ov5640_reset();
+
+       ov5640_power_down(0);
+
+       retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
+       if (retval < 0 || chip_id_high != 0x56) {
+               pr_warning("camera ov5640_mipi is not found\n");
+               clk_disable_unprepare(ov5640_data.sensor_clk);
+               return -ENODEV;
+       }
+       retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
+       if (retval < 0 || chip_id_low != 0x40) {
+               pr_warning("camera ov5640_mipi is not found\n");
+               clk_disable_unprepare(ov5640_data.sensor_clk);
+               return -ENODEV;
+       }
+
+       retval = init_device();
+       if (retval < 0) {
+               clk_disable_unprepare(ov5640_data.sensor_clk);
+               pr_warning("camera ov5640 init failed\n");
+               ov5640_power_down(1);
+               return retval;
+       }
+
+       v4l2_i2c_subdev_init(&ov5640_data.subdev, client, &ov5640_subdev_ops);
+
+       ov5640_data.subdev.grp_id = 678;
+       retval = v4l2_async_register_subdev(&ov5640_data.subdev);
+       if (retval < 0)
+               dev_err(&client->dev,
+                                       "%s--Async register failed, ret=%d\n", __func__, retval);
+
+       OV5640_stream_off();
+       pr_info("camera ov5640_mipi is found\n");
+       return retval;
+}
+
+/*!
+ * ov5640 I2C detach function
+ *
+ * @param client            struct i2c_client *
+ * @return  Error code indicating success or failure
+ */
+static int ov5640_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+       v4l2_async_unregister_subdev(sd);
+
+       clk_disable_unprepare(ov5640_data.sensor_clk);
+
+       ov5640_power_down(1);
+
+       if (gpo_regulator)
+               regulator_disable(gpo_regulator);
+
+       if (analog_regulator)
+               regulator_disable(analog_regulator);
+
+       if (core_regulator)
+               regulator_disable(core_regulator);
+
+       if (io_regulator)
+               regulator_disable(io_regulator);
+
+       return 0;
+}
+
+module_i2c_driver(ov5640_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5640 MIPI Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/capture/ov5640_v2.c b/drivers/media/platform/mxc/capture/ov5640_v2.c
new file mode 100644 (file)
index 0000000..70e2a83
--- /dev/null
@@ -0,0 +1,1895 @@
+/*
+ * Copyright (C) 2012-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * 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.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define OV5640_VOLTAGE_ANALOG               2800000
+#define OV5640_VOLTAGE_DIGITAL_CORE         1500000
+#define OV5640_VOLTAGE_DIGITAL_IO           1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5640_XCLK_MIN 6000000
+#define OV5640_XCLK_MAX 24000000
+
+#define OV5640_CHIP_ID_HIGH_BYTE        0x300A
+#define OV5640_CHIP_ID_LOW_BYTE         0x300B
+
+enum ov5640_mode {
+       ov5640_mode_MIN = 0,
+       ov5640_mode_VGA_640_480 = 0,
+       ov5640_mode_QVGA_320_240 = 1,
+       ov5640_mode_NTSC_720_480 = 2,
+       ov5640_mode_PAL_720_576 = 3,
+       ov5640_mode_720P_1280_720 = 4,
+       ov5640_mode_1080P_1920_1080 = 5,
+       ov5640_mode_QSXGA_2592_1944 = 6,
+       ov5640_mode_QCIF_176_144 = 7,
+       ov5640_mode_XGA_1024_768 = 8,
+       ov5640_mode_MAX = 8
+};
+
+enum ov5640_frame_rate {
+       ov5640_15_fps,
+       ov5640_30_fps
+};
+
+static int ov5640_framerates[] = {
+       [ov5640_15_fps] = 15,
+       [ov5640_30_fps] = 30,
+};
+
+struct ov5640_datafmt {
+       u32     code;
+       enum v4l2_colorspace            colorspace;
+};
+
+struct reg_value {
+       u16 u16RegAddr;
+       u8 u8Val;
+       u8 u8Mask;
+       u32 u32Delay_ms;
+};
+
+struct ov5640_mode_info {
+       enum ov5640_mode mode;
+       u32 width;
+       u32 height;
+       struct reg_value *init_data_ptr;
+       u32 init_data_size;
+};
+
+struct ov5640 {
+       struct v4l2_subdev              subdev;
+       struct i2c_client *i2c_client;
+       struct v4l2_pix_format pix;
+       const struct ov5640_datafmt     *fmt;
+       struct v4l2_captureparm streamcap;
+       bool on;
+
+       /* control settings */
+       int brightness;
+       int hue;
+       int contrast;
+       int saturation;
+       int red;
+       int green;
+       int blue;
+       int ae_mode;
+
+       u32 mclk;
+       u8 mclk_source;
+       struct clk *sensor_clk;
+       int csi;
+
+       void (*io_init)(void);
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct ov5640 ov5640_data;
+static int pwn_gpio, rst_gpio;
+static int prev_sysclk;
+static int AE_Target = 52, night_mode;
+static int prev_HTS;
+static int AE_high, AE_low;
+
+static struct reg_value ov5640_global_init_setting[] = {
+       {0x3008, 0x42, 0, 0},
+       {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
+       {0x3034, 0x1a, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0},
+       {0x3630, 0x36, 0, 0}, {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0},
+       {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0},
+       {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0},
+       {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0},
+       {0x3906, 0x10, 0, 0}, {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0},
+       {0x3600, 0x08, 0, 0}, {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0},
+       {0x3620, 0x52, 0, 0}, {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0},
+       {0x3a13, 0x43, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+       {0x3635, 0x13, 0, 0}, {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0},
+       {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0},
+       {0x3c05, 0x98, 0, 0}, {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0},
+       {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0},
+       {0x3c0b, 0x40, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0},
+       {0x3812, 0x00, 0, 0}, {0x3708, 0x64, 0, 0}, {0x4001, 0x02, 0, 0},
+       {0x4005, 0x1a, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
+       {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
+       {0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x5000, 0xa7, 0, 0},
+       {0x3008, 0x02, 0, 0},
+};
+
+static struct reg_value ov5640_init_setting_30fps_VGA[] = {
+       {0x3008, 0x42, 0, 0},
+       {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
+       {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x46, 0, 0},
+       {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
+       {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
+       {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+       {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
+       {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
+       {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
+       {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
+       {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
+       {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
+       {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
+       {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
+       {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
+       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+       {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
+       {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
+       {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, {0x5000, 0xa7, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0},
+       {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0},
+       {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0}, {0x518a, 0x54, 0, 0},
+       {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x50, 0, 0},
+       {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0}, {0x5190, 0x46, 0, 0},
+       {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+       {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+       {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x6c, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x09, 0, 0},
+       {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0}, {0x5381, 0x1e, 0, 0},
+       {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, {0x5384, 0x0a, 0, 0},
+       {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0},
+       {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0},
+       {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0},
+       {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0},
+       {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0},
+       {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0},
+       {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, {0x5481, 0x08, 0, 0},
+       {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, {0x5484, 0x51, 0, 0},
+       {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, {0x5487, 0x7d, 0, 0},
+       {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, {0x548a, 0x9a, 0, 0},
+       {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, {0x548d, 0xcd, 0, 0},
+       {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, {0x5490, 0x1d, 0, 0},
+       {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x10, 0, 0},
+       {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, {0x558b, 0xf8, 0, 0},
+       {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, {0x5802, 0x0f, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, {0x5805, 0x26, 0, 0},
+       {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, {0x5808, 0x05, 0, 0},
+       {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, {0x580b, 0x0d, 0, 0},
+       {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, {0x580e, 0x00, 0, 0},
+       {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, {0x5811, 0x09, 0, 0},
+       {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x00, 0, 0},
+       {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, {0x5817, 0x08, 0, 0},
+       {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, {0x581a, 0x05, 0, 0},
+       {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, {0x581d, 0x0e, 0, 0},
+       {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, {0x5820, 0x11, 0, 0},
+       {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, {0x5823, 0x28, 0, 0},
+       {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, {0x5829, 0x26, 0, 0},
+       {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, {0x582c, 0x24, 0, 0},
+       {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, {0x582f, 0x22, 0, 0},
+       {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, {0x5832, 0x24, 0, 0},
+       {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, {0x5835, 0x22, 0, 0},
+       {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, {0x5838, 0x44, 0, 0},
+       {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, {0x583b, 0x28, 0, 0},
+       {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, {0x5025, 0x00, 0, 0},
+       {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0},
+       {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0},
+       {0x3008, 0x02, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
+       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
+       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
+       {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
+       {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
+       {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
+       {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+       {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+       {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
+       {0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+       {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+       {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
+       {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
+       {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
+       {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+       {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
+       {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
+       {0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+       {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+       {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
+       {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
+       {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
+       {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+       {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
+       {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
+       {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
+       {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
+       {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
+       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
+       {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
+       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+       {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
+       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+
+static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
+       {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
+       {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0xee, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x05, 0, 0},
+       {0x3807, 0xc3, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0},
+       {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x0b, 0, 0},
+       {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
+       {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
+       {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
+       {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
+       {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
+       {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
+       {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
+       {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
+       {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
+       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0},
+       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+       {0x3807, 0x9f, 0, 0}, {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0},
+       {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0},
+       {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
+       {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
+       {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
+       {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
+       {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+       {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
+       {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
+       {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
+       {
+               {ov5640_mode_VGA_640_480,      640,  480,
+               ov5640_setting_15fps_VGA_640_480,
+               ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
+               {ov5640_mode_QVGA_320_240,     320,  240,
+               ov5640_setting_15fps_QVGA_320_240,
+               ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
+               {ov5640_mode_NTSC_720_480,     720,  480,
+               ov5640_setting_15fps_NTSC_720_480,
+               ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
+               {ov5640_mode_PAL_720_576,      720,  576,
+               ov5640_setting_15fps_PAL_720_576,
+               ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
+               {ov5640_mode_720P_1280_720,   1280,  720,
+               ov5640_setting_15fps_720P_1280_720,
+               ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
+               {ov5640_mode_1080P_1920_1080, 1920, 1080,
+               ov5640_setting_15fps_1080P_1920_1080,
+               ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
+               {ov5640_mode_QSXGA_2592_1944, 2592, 1944,
+               ov5640_setting_15fps_QSXGA_2592_1944,
+               ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
+               {ov5640_mode_QCIF_176_144,     176,  144,
+               ov5640_setting_15fps_QCIF_176_144,
+               ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
+               {ov5640_mode_XGA_1024_768,    1024,  768,
+               ov5640_setting_15fps_XGA_1024_768,
+               ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
+       },
+       {
+               {ov5640_mode_VGA_640_480,      640,  480,
+               ov5640_setting_30fps_VGA_640_480,
+               ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
+               {ov5640_mode_QVGA_320_240,     320,  240,
+               ov5640_setting_30fps_QVGA_320_240,
+               ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
+               {ov5640_mode_NTSC_720_480,     720,  480,
+               ov5640_setting_30fps_NTSC_720_480,
+               ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
+               {ov5640_mode_PAL_720_576,      720,  576,
+               ov5640_setting_30fps_PAL_720_576,
+               ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
+               {ov5640_mode_720P_1280_720,   1280,  720,
+               ov5640_setting_30fps_720P_1280_720,
+               ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
+               {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0},
+               {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
+               {ov5640_mode_QCIF_176_144,     176,  144,
+               ov5640_setting_30fps_QCIF_176_144,
+               ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
+               {ov5640_mode_XGA_1024_768,    1024,  768,
+               ov5640_setting_30fps_XGA_1024_768,
+               ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
+       },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+
+static int ov5640_probe(struct i2c_client *adapter,
+                               const struct i2c_device_id *device_id);
+static int ov5640_remove(struct i2c_client *client);
+
+static s32 ov5640_read_reg(u16 reg, u8 *val);
+static s32 ov5640_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5640_id[] = {
+       {"ov5640", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+       .driver = {
+                 .owner = THIS_MODULE,
+                 .name  = "ov5640",
+                 },
+       .probe  = ov5640_probe,
+       .remove = ov5640_remove,
+       .id_table = ov5640_id,
+};
+
+static const struct ov5640_datafmt ov5640_colour_fmts[] = {
+       {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+};
+
+static struct ov5640 *to_ov5640(const struct i2c_client *client)
+{
+       return container_of(i2c_get_clientdata(client), struct ov5640, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct ov5640_datafmt
+                       *ov5640_find_datafmt(u32 code)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ov5640_colour_fmts); i++)
+               if (ov5640_colour_fmts[i].code == code)
+                       return ov5640_colour_fmts + i;
+
+       return NULL;
+}
+
+static inline void ov5640_power_down(int enable)
+{
+       gpio_set_value_cansleep(pwn_gpio, enable);
+
+       msleep(2);
+}
+
+static inline void ov5640_reset(void)
+{
+       /* camera reset */
+       gpio_set_value_cansleep(rst_gpio, 1);
+
+       /* camera power down */
+       gpio_set_value_cansleep(pwn_gpio, 1);
+       msleep(5);
+       gpio_set_value_cansleep(pwn_gpio, 0);
+       msleep(5);
+       gpio_set_value_cansleep(rst_gpio, 0);
+       msleep(1);
+       gpio_set_value_cansleep(rst_gpio, 1);
+       msleep(5);
+       gpio_set_value_cansleep(pwn_gpio, 1);
+}
+
+static int ov5640_regulator_enable(struct device *dev)
+{
+       int ret = 0;
+
+       io_regulator = devm_regulator_get(dev, "DOVDD");
+       if (!IS_ERR(io_regulator)) {
+               regulator_set_voltage(io_regulator,
+                                     OV5640_VOLTAGE_DIGITAL_IO,
+                                     OV5640_VOLTAGE_DIGITAL_IO);
+               ret = regulator_enable(io_regulator);
+               if (ret) {
+                       dev_err(dev, "set io voltage failed\n");
+                       return ret;
+               } else {
+                       dev_dbg(dev, "set io voltage ok\n");
+               }
+       } else {
+               io_regulator = NULL;
+               dev_warn(dev, "cannot get io voltage\n");
+       }
+
+       core_regulator = devm_regulator_get(dev, "DVDD");
+       if (!IS_ERR(core_regulator)) {
+               regulator_set_voltage(core_regulator,
+                                     OV5640_VOLTAGE_DIGITAL_CORE,
+                                     OV5640_VOLTAGE_DIGITAL_CORE);
+               ret = regulator_enable(core_regulator);
+               if (ret) {
+                       dev_err(dev, "set core voltage failed\n");
+                       return ret;
+               } else {
+                       dev_dbg(dev, "set core voltage ok\n");
+               }
+       } else {
+               core_regulator = NULL;
+               dev_warn(dev, "cannot get core voltage\n");
+       }
+
+       analog_regulator = devm_regulator_get(dev, "AVDD");
+       if (!IS_ERR(analog_regulator)) {
+               regulator_set_voltage(analog_regulator,
+                                     OV5640_VOLTAGE_ANALOG,
+                                     OV5640_VOLTAGE_ANALOG);
+               ret = regulator_enable(analog_regulator);
+               if (ret) {
+                       dev_err(dev, "set analog voltage failed\n");
+                       return ret;
+               } else {
+                       dev_dbg(dev, "set analog voltage ok\n");
+               }
+       } else {
+               analog_regulator = NULL;
+               dev_warn(dev, "cannot get analog voltage\n");
+       }
+
+       return ret;
+}
+
+static s32 ov5640_write_reg(u16 reg, u8 val)
+{
+       u8 au8Buf[3] = {0};
+
+       au8Buf[0] = reg >> 8;
+       au8Buf[1] = reg & 0xff;
+       au8Buf[2] = val;
+
+       if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
+               pr_err("%s:write reg error:reg=%x,val=%x\n",
+                       __func__, reg, val);
+               return -1;
+       }
+
+       return 0;
+}
+
+static s32 ov5640_read_reg(u16 reg, u8 *val)
+{
+       u8 au8RegBuf[2] = {0};
+       u8 u8RdVal = 0;
+
+       au8RegBuf[0] = reg >> 8;
+       au8RegBuf[1] = reg & 0xff;
+
+       if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
+               pr_err("%s:write reg error:reg=%x\n",
+                               __func__, reg);
+               return -1;
+       }
+
+       if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
+               pr_err("%s:read reg error:reg=%x,val=%x\n",
+                               __func__, reg, u8RdVal);
+               return -1;
+       }
+
+       *val = u8RdVal;
+
+       return u8RdVal;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov5640_get_register(struct v4l2_subdev *sd,
+                                       struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret;
+       u8 val;
+
+       if (reg->reg & ~0xffff)
+               return -EINVAL;
+
+       reg->size = 1;
+
+       ret = ov5640_read_reg(reg->reg, &val);
+       if (!ret)
+               reg->val = (__u64)val;
+
+       return ret;
+}
+
+static int ov5640_set_register(struct v4l2_subdev *sd,
+                                       const struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (reg->reg & ~0xffff || reg->val & ~0xff)
+               return -EINVAL;
+
+       return ov5640_write_reg(reg->reg, reg->val);
+}
+#endif
+
+static void ov5640_soft_reset(void)
+{
+       /* sysclk from pad */
+       ov5640_write_reg(0x3103, 0x11);
+
+       /* software reset */
+       ov5640_write_reg(0x3008, 0x82);
+
+       /* delay at least 5ms */
+       msleep(10);
+}
+
+/* set sensor driver capability
+ * 0x302c[7:6] - strength
+       00     - 1x
+       01     - 2x
+       10     - 3x
+       11     - 4x
+ */
+static int ov5640_driver_capability(int strength)
+{
+       u8 temp = 0;
+
+       if (strength > 4 || strength < 1) {
+               pr_err("The valid driver capability of ov5640 is 1x~4x\n");
+               return -EINVAL;
+       }
+
+       ov5640_read_reg(0x302c, &temp);
+
+       temp &= ~0xc0;  /* clear [7:6] */
+       temp |= ((strength - 1) << 6);  /* set [7:6] */
+
+       ov5640_write_reg(0x302c, temp);
+
+       return 0;
+}
+
+/* calculate sysclk */
+static int ov5640_get_sysclk(void)
+{
+       int xvclk = ov5640_data.mclk / 10000;
+       int sysclk;
+       int temp1, temp2;
+       int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv;
+       int sclk_rdiv_map[] = {1, 2, 4, 8};
+       u8 regval = 0;
+
+       temp1 = ov5640_read_reg(0x3034, &regval);
+       temp2 = temp1 & 0x0f;
+       if (temp2 == 8 || temp2 == 10) {
+               Bit_div2x = temp2 / 2;
+       } else {
+               pr_err("ov5640: unsupported bit mode %d\n", temp2);
+               return -1;
+       }
+
+       temp1 = ov5640_read_reg(0x3035, &regval);
+       SysDiv = temp1 >> 4;
+       if (SysDiv == 0)
+               SysDiv = 16;
+
+       temp1 = ov5640_read_reg(0x3036, &regval);
+       Multiplier = temp1;
+       temp1 = ov5640_read_reg(0x3037, &regval);
+       PreDiv = temp1 & 0x0f;
+       Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
+
+       temp1 = ov5640_read_reg(0x3108, &regval);
+       temp2 = temp1 & 0x03;
+
+       sclk_rdiv = sclk_rdiv_map[temp2];
+       VCO = xvclk * Multiplier / PreDiv;
+       sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
+
+       return sysclk;
+}
+
+/* read HTS from register settings */
+static int ov5640_get_HTS(void)
+{
+       int HTS;
+       u8 temp = 0;
+
+       HTS = ov5640_read_reg(0x380c, &temp);
+       HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
+       return HTS;
+}
+
+/* read VTS from register settings */
+static int ov5640_get_VTS(void)
+{
+       int VTS;
+       u8 temp = 0;
+
+       VTS = ov5640_read_reg(0x380e, &temp);
+       VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
+
+       return VTS;
+}
+
+/* write VTS to registers */
+static int ov5640_set_VTS(int VTS)
+{
+       int temp;
+
+       temp = VTS & 0xff;
+       ov5640_write_reg(0x380f, temp);
+
+       temp = VTS>>8;
+       ov5640_write_reg(0x380e, temp);
+       return 0;
+}
+
+/* read shutter, in number of line period */
+static int ov5640_get_shutter(void)
+{
+       int shutter;
+       u8 regval;
+
+       shutter = (ov5640_read_reg(0x03500, &regval) & 0x0f);
+
+       shutter = (shutter<<8) + ov5640_read_reg(0x3501, &regval);
+       shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &regval)>>4);
+
+       return shutter;
+}
+
+/* write shutter, in number of line period */
+static int ov5640_set_shutter(int shutter)
+{
+       int temp;
+
+       shutter = shutter & 0xffff;
+       temp = shutter & 0x0f;
+       temp = temp<<4;
+       ov5640_write_reg(0x3502, temp);
+
+       temp = shutter & 0xfff;
+       temp = temp>>4;
+       ov5640_write_reg(0x3501, temp);
+
+       temp = shutter>>12;
+       ov5640_write_reg(0x3500, temp);
+
+       return 0;
+}
+
+/* read gain, 16 = 1x */
+static int ov5640_get_gain16(void)
+{
+       int gain16;
+       u8 regval;
+
+       gain16 = ov5640_read_reg(0x350a, &regval) & 0x03;
+       gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &regval);
+
+       return gain16;
+}
+
+/* write gain, 16 = 1x */
+static int ov5640_set_gain16(int gain16)
+{
+       int temp;
+
+       gain16 = gain16 & 0x3ff;
+       temp = gain16 & 0xff;
+
+       ov5640_write_reg(0x350b, temp);
+       temp = gain16>>8;
+
+       ov5640_write_reg(0x350a, temp);
+       return 0;
+}
+
+/* get banding filter value */
+static int ov5640_get_light_freq(void)
+{
+       int temp, temp1, light_frequency;
+       u8 regval;
+
+       temp = ov5640_read_reg(0x3c01, &regval);
+       if (temp & 0x80) {
+               /* manual */
+               temp1 = ov5640_read_reg(0x3c00, &regval);
+               if (temp1 & 0x04) {
+                       /* 50Hz */
+                       light_frequency = 50;
+               } else {
+                       /* 60Hz */
+                       light_frequency = 60;
+               }
+       } else {
+               /* auto */
+               temp1 = ov5640_read_reg(0x3c0c, &regval);
+               if (temp1 & 0x01) {
+                       /* 50Hz */
+                       light_frequency = 50;
+               } else {
+                       /* 60Hz */
+                       light_frequency = 60;
+               }
+       }
+
+       return light_frequency;
+}
+
+static void ov5640_set_bandingfilter(void)
+{
+       int prev_VTS;
+       int band_step60, max_band60, band_step50, max_band50;
+
+       /* read preview PCLK */
+       prev_sysclk = ov5640_get_sysclk();
+
+       /* read preview HTS */
+       prev_HTS = ov5640_get_HTS();
+
+       /* read preview VTS */
+       prev_VTS = ov5640_get_VTS();
+
+       /* calculate banding filter */
+       /* 60Hz */
+       band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
+       ov5640_write_reg(0x3a0a, (band_step60 >> 8));
+       ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
+
+       max_band60 = (int)((prev_VTS-4)/band_step60);
+       ov5640_write_reg(0x3a0d, max_band60);
+
+       /* 50Hz */
+       band_step50 = prev_sysclk * 100/prev_HTS;
+       ov5640_write_reg(0x3a08, (band_step50 >> 8));
+       ov5640_write_reg(0x3a09, (band_step50 & 0xff));
+
+       max_band50 = (int)((prev_VTS-4)/band_step50);
+       ov5640_write_reg(0x3a0e, max_band50);
+}
+
+/* stable in high */
+static int ov5640_set_AE_target(int target)
+{
+       int fast_high, fast_low;
+
+       AE_low = target * 23 / 25; /* 0.92 */
+       AE_high = target * 27 / 25; /* 1.08 */
+       fast_high = AE_high << 1;
+
+       if (fast_high > 255)
+               fast_high = 255;
+       fast_low = AE_low >> 1;
+
+       ov5640_write_reg(0x3a0f, AE_high);
+       ov5640_write_reg(0x3a10, AE_low);
+       ov5640_write_reg(0x3a1b, AE_high);
+       ov5640_write_reg(0x3a1e, AE_low);
+       ov5640_write_reg(0x3a11, fast_high);
+       ov5640_write_reg(0x3a1f, fast_low);
+
+       return 0;
+}
+
+/* enable = 0 to turn off night mode
+   enable = 1 to turn on night mode */
+static int ov5640_set_night_mode(int enable)
+{
+       u8 mode;
+
+       ov5640_read_reg(0x3a00, &mode);
+
+       if (enable) {
+               /* night mode on */
+               mode |= 0x04;
+               ov5640_write_reg(0x3a00, mode);
+       } else {
+               /* night mode off */
+               mode &= 0xfb;
+               ov5640_write_reg(0x3a00, mode);
+       }
+
+       return 0;
+}
+
+/* enable = 0 to turn off AEC/AGC
+   enable = 1 to turn on AEC/AGC */
+static void ov5640_turn_on_AE_AG(int enable)
+{
+       u8 ae_ag_ctrl;
+
+       ov5640_read_reg(0x3503, &ae_ag_ctrl);
+       if (enable) {
+               /* turn on auto AE/AG */
+               ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
+       } else {
+               /* turn off AE/AG */
+               ae_ag_ctrl = ae_ag_ctrl | 0x03;
+       }
+       ov5640_write_reg(0x3503, ae_ag_ctrl);
+}
+
+/* download ov5640 settings to sensor through i2c */
+static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+{
+       register u32 Delay_ms = 0;
+       register u16 RegAddr = 0;
+       register u8 Mask = 0;
+       register u8 Val = 0;
+       u8 RegVal = 0;
+       int i, retval = 0;
+
+       for (i = 0; i < ArySize; ++i, ++pModeSetting) {
+               Delay_ms = pModeSetting->u32Delay_ms;
+               RegAddr = pModeSetting->u16RegAddr;
+               Val = pModeSetting->u8Val;
+               Mask = pModeSetting->u8Mask;
+
+               if (Mask) {
+                       retval = ov5640_read_reg(RegAddr, &RegVal);
+                       if (retval < 0)
+                               goto err;
+
+                       RegVal &= ~(u8)Mask;
+                       Val &= Mask;
+                       Val |= RegVal;
+               }
+
+               retval = ov5640_write_reg(RegAddr, Val);
+               if (retval < 0)
+                       goto err;
+
+               if (Delay_ms)
+                       msleep(Delay_ms);
+       }
+err:
+       return retval;
+}
+
+static int ov5640_init_mode(void)
+{
+       struct reg_value *pModeSetting = NULL;
+       int ArySize = 0, retval = 0;
+
+       ov5640_soft_reset();
+
+       pModeSetting = ov5640_global_init_setting;
+       ArySize = ARRAY_SIZE(ov5640_global_init_setting);
+       retval = ov5640_download_firmware(pModeSetting, ArySize);
+       if (retval < 0)
+               goto err;
+
+       pModeSetting = ov5640_init_setting_30fps_VGA;
+       ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
+       retval = ov5640_download_firmware(pModeSetting, ArySize);
+       if (retval < 0)
+               goto err;
+
+       /* change driver capability to 2x according to validation board.
+        * if the image is not stable, please increase the driver strength.
+        */
+       ov5640_driver_capability(2);
+       ov5640_set_bandingfilter();
+       ov5640_set_AE_target(AE_Target);
+       ov5640_set_night_mode(night_mode);
+
+       /* skip 9 vysnc: start capture at 10th vsync */
+       msleep(300);
+
+       /* turn off night mode */
+       night_mode = 0;
+       ov5640_data.pix.width = 640;
+       ov5640_data.pix.height = 480;
+err:
+       return retval;
+}
+
+/* change to or back to subsampling mode set the mode directly
+ * image size below 1280 * 960 is subsampling mode */
+static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
+                           enum ov5640_mode mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 ArySize = 0;
+       int retval = 0;
+
+       if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
+               pr_err("Wrong ov5640 mode detected!\n");
+               return -1;
+       }
+
+       pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+       ArySize =
+               ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+       ov5640_data.pix.width = ov5640_mode_info_data[frame_rate][mode].width;
+       ov5640_data.pix.height = ov5640_mode_info_data[frame_rate][mode].height;
+
+       if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+           pModeSetting == NULL || ArySize == 0)
+               return -EINVAL;
+
+       /* set ov5640 to subsampling mode */
+       retval = ov5640_download_firmware(pModeSetting, ArySize);
+
+       /* turn on AE AG for subsampling mode, in case the firmware didn't */
+       ov5640_turn_on_AE_AG(1);
+
+       /* calculate banding filter */
+       ov5640_set_bandingfilter();
+
+       /* set AE target */
+       ov5640_set_AE_target(AE_Target);
+
+       /* update night mode setting */
+       ov5640_set_night_mode(night_mode);
+
+       /* skip 9 vysnc: start capture at 10th vsync */
+       if (mode == ov5640_mode_XGA_1024_768 && frame_rate == ov5640_30_fps) {
+               pr_warning("ov5640: actual frame rate of XGA is 22.5fps\n");
+               /* 1/22.5 * 9*/
+               msleep(400);
+               return retval;
+       }
+
+       if (frame_rate == ov5640_15_fps) {
+               /* 1/15 * 9*/
+               msleep(600);
+       } else if (frame_rate == ov5640_30_fps) {
+               /* 1/30 * 9*/
+               msleep(300);
+       }
+
+       return retval;
+}
+
+/* change to scaling mode go through exposure calucation
+ * image size above 1280 * 960 is scaling mode */
+static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
+                           enum ov5640_mode mode)
+{
+       int prev_shutter, prev_gain16, average;
+       int cap_shutter, cap_gain16;
+       int cap_sysclk, cap_HTS, cap_VTS;
+       int light_freq, cap_bandfilt, cap_maxband;
+       long cap_gain16_shutter;
+       u8 temp;
+       struct reg_value *pModeSetting = NULL;
+       s32 ArySize = 0;
+       int retval = 0;
+
+       /* check if the input mode and frame rate is valid */
+       pModeSetting =
+               ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+       ArySize =
+               ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+       ov5640_data.pix.width =
+               ov5640_mode_info_data[frame_rate][mode].width;
+       ov5640_data.pix.height =
+               ov5640_mode_info_data[frame_rate][mode].height;
+
+       if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+               pModeSetting == NULL || ArySize == 0)
+               return -EINVAL;
+
+       /* read preview shutter */
+       prev_shutter = ov5640_get_shutter();
+
+       /* read preview gain */
+       prev_gain16 = ov5640_get_gain16();
+
+       /* get average */
+       average = ov5640_read_reg(0x56a1, &temp);
+
+       /* turn off night mode for capture */
+       ov5640_set_night_mode(0);
+
+       /* turn off overlay */
+       ov5640_write_reg(0x3022, 0x06);
+
+       /* Write capture setting */
+       retval = ov5640_download_firmware(pModeSetting, ArySize);
+       if (retval < 0)
+               goto err;
+
+       /* turn off AE AG when capture image. */
+       ov5640_turn_on_AE_AG(0);
+
+       /* read capture VTS */
+       cap_VTS = ov5640_get_VTS();
+       cap_HTS = ov5640_get_HTS();
+       cap_sysclk = ov5640_get_sysclk();
+
+       /* calculate capture banding filter */
+       light_freq = ov5640_get_light_freq();
+       if (light_freq == 60) {
+               /* 60Hz */
+               cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
+       } else {
+               /* 50Hz */
+               cap_bandfilt = cap_sysclk * 100 / cap_HTS;
+       }
+       cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
+       /* calculate capture shutter/gain16 */
+       if (average > AE_low && average < AE_high) {
+               /* in stable range */
+               cap_gain16_shutter =
+                       prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
+                       prev_HTS/cap_HTS * AE_Target / average;
+       } else {
+               cap_gain16_shutter =
+                       prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
+                       prev_HTS/cap_HTS;
+       }
+
+       /* gain to shutter */
+       if (cap_gain16_shutter < (cap_bandfilt * 16)) {
+               /* shutter < 1/100 */
+               cap_shutter = cap_gain16_shutter/16;
+               if (cap_shutter < 1)
+                       cap_shutter = 1;
+               cap_gain16 = cap_gain16_shutter/cap_shutter;
+               if (cap_gain16 < 16)
+                       cap_gain16 = 16;
+       } else {
+               if (cap_gain16_shutter > (cap_bandfilt*cap_maxband*16)) {
+                       /* exposure reach max */
+                       cap_shutter = cap_bandfilt*cap_maxband;
+                       cap_gain16 = cap_gain16_shutter / cap_shutter;
+               } else {
+                       /* 1/100 < cap_shutter =< max, cap_shutter = n/100 */
+                       cap_shutter =
+                               ((int)(cap_gain16_shutter/16/cap_bandfilt))
+                               * cap_bandfilt;
+                       cap_gain16 = cap_gain16_shutter / cap_shutter;
+               }
+       }
+
+       /* write capture gain */
+       ov5640_set_gain16(cap_gain16);
+
+       /* write capture shutter */
+       if (cap_shutter > (cap_VTS - 4)) {
+               cap_VTS = cap_shutter + 4;
+               ov5640_set_VTS(cap_VTS);
+       }
+
+       ov5640_set_shutter(cap_shutter);
+
+       /* skip 2 vysnc: start capture at 3rd vsync
+        * frame rate of QSXGA and 1080P is 7.5fps: 1/7.5 * 2
+        */
+       pr_warning("ov5640: the actual frame rate of %s is 7.5fps\n",
+               mode == ov5640_mode_1080P_1920_1080 ? "1080P" : "QSXGA");
+       msleep(267);
+err:
+       return retval;
+}
+
+static int ov5640_change_mode(enum ov5640_frame_rate frame_rate,
+                           enum ov5640_mode mode)
+{
+       int retval = 0;
+
+       if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
+               pr_err("Wrong ov5640 mode detected!\n");
+               return -1;
+       }
+
+       if (mode == ov5640_mode_1080P_1920_1080 ||
+                       mode == ov5640_mode_QSXGA_2592_1944) {
+               /* change to scaling mode go through exposure calucation
+                * image size above 1280 * 960 is scaling mode */
+               retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
+       } else {
+               /* change back to subsampling modem download firmware directly
+                * image size below 1280 * 960 is subsampling mode */
+               retval = ov5640_change_mode_direct(frame_rate, mode);
+       }
+
+       return retval;
+}
+
+/*!
+ * ov5640_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ov5640_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+
+       if (on)
+               clk_enable(ov5640_data.sensor_clk);
+       else
+               clk_disable(ov5640_data.sensor_clk);
+
+       sensor->on = on;
+
+       return 0;
+}
+
+/*!
+ * ov5640_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ov5640_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+       struct v4l2_captureparm *cparm = &a->parm.capture;
+       int ret = 0;
+
+       switch (a->type) {
+       /* This is the only case currently handled. */
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               memset(a, 0, sizeof(*a));
+               a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               cparm->capability = sensor->streamcap.capability;
+               cparm->timeperframe = sensor->streamcap.timeperframe;
+               cparm->capturemode = sensor->streamcap.capturemode;
+               ret = 0;
+               break;
+
+       /* These are all the possible cases. */
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_VBI_OUTPUT:
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+               ret = -EINVAL;
+               break;
+
+       default:
+               pr_debug("   type is unknown - %d\n", a->type);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+/*!
+ * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible.  If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ov5640_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+       u32 tgt_fps;    /* target frames per secound */
+       enum ov5640_frame_rate frame_rate;
+       int ret = 0;
+
+       switch (a->type) {
+       /* This is the only case currently handled. */
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               /* Check that the new frame rate is allowed. */
+               if ((timeperframe->numerator == 0) ||
+                   (timeperframe->denominator == 0)) {
+                       timeperframe->denominator = DEFAULT_FPS;
+                       timeperframe->numerator = 1;
+               }
+
+               tgt_fps = timeperframe->denominator /
+                         timeperframe->numerator;
+
+               if (tgt_fps > MAX_FPS) {
+                       timeperframe->denominator = MAX_FPS;
+                       timeperframe->numerator = 1;
+               } else if (tgt_fps < MIN_FPS) {
+                       timeperframe->denominator = MIN_FPS;
+                       timeperframe->numerator = 1;
+               }
+
+               /* Actual frame rate we use */
+               tgt_fps = timeperframe->denominator /
+                         timeperframe->numerator;
+
+               if (tgt_fps == 15)
+                       frame_rate = ov5640_15_fps;
+               else if (tgt_fps == 30)
+                       frame_rate = ov5640_30_fps;
+               else {
+                       pr_err(" The camera frame rate is not supported!\n");
+                       goto error;
+               }
+
+               ret = ov5640_change_mode(frame_rate,
+                               a->parm.capture.capturemode);
+               if (ret < 0)
+                       goto error;
+
+               sensor->streamcap.timeperframe = *timeperframe;
+               sensor->streamcap.capturemode = a->parm.capture.capturemode;
+
+               break;
+
+       /* These are all the possible cases. */
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_VBI_OUTPUT:
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+               pr_debug("   type is not " \
+                       "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+                       a->type);
+               ret = -EINVAL;
+               break;
+
+       default:
+               pr_debug("   type is unknown - %d\n", a->type);
+               ret = -EINVAL;
+               break;
+       }
+
+error:
+       return ret;
+}
+
+static int ov5640_set_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *format)
+{
+       struct v4l2_mbus_framefmt *mf = &format->format;
+       const struct ov5640_datafmt *fmt = ov5640_find_datafmt(mf->code);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+
+       if (format->pad)
+               return -EINVAL;
+
+       if (!fmt) {
+               mf->code        = ov5640_colour_fmts[0].code;
+               mf->colorspace  = ov5640_colour_fmts[0].colorspace;
+       }
+
+       mf->field       = V4L2_FIELD_NONE;
+
+       if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+               return 0;
+
+       sensor->fmt = fmt;
+
+       return 0;
+}
+
+static int ov5640_get_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *format)
+{
+       struct v4l2_mbus_framefmt *mf = &format->format;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5640 *sensor = to_ov5640(client);
+       const struct ov5640_datafmt *fmt = sensor->fmt;
+
+       if (format->pad)
+               return -EINVAL;
+
+       mf->code        = fmt->code;
+       mf->colorspace  = fmt->colorspace;
+       mf->field       = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static int ov5640_enum_code(struct v4l2_subdev *sd,
+                           struct v4l2_subdev_pad_config *cfg,
+                           struct v4l2_subdev_mbus_code_enum *code)
+{
+       if (code->pad || code->index >= ARRAY_SIZE(ov5640_colour_fmts))
+               return -EINVAL;
+
+       code->code = ov5640_colour_fmts[code->index].code;
+       return 0;
+}
+
+/*!
+ * ov5640_enum_framesizes - V4L2 sensor interface handler for
+ *                        VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5640_enum_framesizes(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_pad_config *cfg,
+                              struct v4l2_subdev_frame_size_enum *fse)
+{
+       if (fse->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       fse->max_width =
+                       max(ov5640_mode_info_data[0][fse->index].width,
+                           ov5640_mode_info_data[1][fse->index].width);
+       fse->min_width = fse->max_width;
+       fse->max_height =
+                       max(ov5640_mode_info_data[0][fse->index].height,
+                           ov5640_mode_info_data[1][fse->index].height);
+       fse->min_height = fse->max_height;
+       return 0;
+}
+
+/*!
+ * ov5640_enum_frameintervals - V4L2 sensor interface handler for
+ *                            VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5640_enum_frameintervals(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_frame_interval_enum *fie)
+{
+       int i, j, count;
+
+       if (fie->index < 0 || fie->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       if (fie->width == 0 || fie->height == 0 ||
+           fie->code == 0) {
+               pr_warning("Please assign pixel format, width and height.\n");
+               return -EINVAL;
+       }
+
+       fie->interval.numerator = 1;
+
+       count = 0;
+       for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
+               for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
+                       if (fie->width == ov5640_mode_info_data[i][j].width
+                        && fie->height == ov5640_mode_info_data[i][j].height
+                        && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
+                               count++;
+                       }
+                       if (fie->index == (count - 1)) {
+                               fie->interval.denominator =
+                                               ov5640_framerates[i];
+                               return 0;
+                       }
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int ov5640_set_clk_rate(void)
+{
+       u32 tgt_xclk;   /* target xclk */
+       int ret;
+
+       /* mclk */
+       tgt_xclk = ov5640_data.mclk;
+       tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
+       tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
+       ov5640_data.mclk = tgt_xclk;
+
+       pr_debug("   Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+       ret = clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk);
+       if (ret < 0)
+               pr_debug("set rate filed, rate=%d\n", ov5640_data.mclk);
+       return ret;
+}
+
+/*!
+ * dev_init - V4L2 sensor init
+ * @s: pointer to standard V4L2 device structure
+ *
+ */
+static int init_device(void)
+{
+       u32 tgt_xclk;   /* target xclk */
+       u32 tgt_fps;    /* target frames per secound */
+       enum ov5640_frame_rate frame_rate;
+       int ret;
+
+       ov5640_data.on = true;
+
+       /* mclk */
+       tgt_xclk = ov5640_data.mclk;
+
+       /* Default camera frame rate is set in probe */
+       tgt_fps = ov5640_data.streamcap.timeperframe.denominator /
+                 ov5640_data.streamcap.timeperframe.numerator;
+
+       if (tgt_fps == 15)
+               frame_rate = ov5640_15_fps;
+       else if (tgt_fps == 30)
+               frame_rate = ov5640_30_fps;
+       else
+               return -EINVAL; /* Only support 15fps or 30fps now. */
+
+       ret = ov5640_init_mode();
+
+       return ret;
+}
+
+static struct v4l2_subdev_video_ops ov5640_subdev_video_ops = {
+       .g_parm = ov5640_g_parm,
+       .s_parm = ov5640_s_parm,
+};
+
+static const struct v4l2_subdev_pad_ops ov5640_subdev_pad_ops = {
+       .enum_frame_size       = ov5640_enum_framesizes,
+       .enum_frame_interval   = ov5640_enum_frameintervals,
+       .enum_mbus_code        = ov5640_enum_code,
+       .set_fmt               = ov5640_set_fmt,
+       .get_fmt               = ov5640_get_fmt,
+};
+
+static struct v4l2_subdev_core_ops ov5640_subdev_core_ops = {
+       .s_power        = ov5640_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register     = ov5640_get_register,
+       .s_register     = ov5640_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5640_subdev_ops = {
+       .core   = &ov5640_subdev_core_ops,
+       .video  = &ov5640_subdev_video_ops,
+       .pad    = &ov5640_subdev_pad_ops,
+};
+
+/*!
+ * ov5640 I2C probe function
+ *
+ * @param adapter            struct i2c_adapter *
+ * @return  Error code indicating success or failure
+ */
+static int ov5640_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct pinctrl *pinctrl;
+       struct device *dev = &client->dev;
+       int retval;
+       u8 chip_id_high, chip_id_low;
+
+       /* ov5640 pinctrl */
+       pinctrl = devm_pinctrl_get_select_default(dev);
+       if (IS_ERR(pinctrl)) {
+               dev_err(dev, "setup pinctrl failed\n");
+               return PTR_ERR(pinctrl);
+       }
+
+       /* request power down pin */
+       pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+       if (!gpio_is_valid(pwn_gpio)) {
+               dev_err(dev, "no sensor pwdn pin available\n");
+               return -ENODEV;
+       }
+       retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "ov5640_pwdn");
+       if (retval < 0)
+               return retval;
+
+       /* request reset pin */
+       rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+       if (!gpio_is_valid(rst_gpio)) {
+               dev_err(dev, "no sensor reset pin available\n");
+               return -EINVAL;
+       }
+       retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "ov5640_reset");
+       if (retval < 0)
+               return retval;
+
+       /* Set initial values for the sensor struct. */
+       memset(&ov5640_data, 0, sizeof(ov5640_data));
+       ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+       if (IS_ERR(ov5640_data.sensor_clk)) {
+               dev_err(dev, "get mclk failed\n");
+               return PTR_ERR(ov5640_data.sensor_clk);
+       }
+
+       retval = of_property_read_u32(dev->of_node, "mclk",
+                                       &ov5640_data.mclk);
+       if (retval) {
+               dev_err(dev, "mclk frequency is invalid\n");
+               return retval;
+       }
+
+       retval = of_property_read_u32(dev->of_node, "mclk_source",
+                                       (u32 *) &(ov5640_data.mclk_source));
+       if (retval) {
+               dev_err(dev, "mclk_source invalid\n");
+               return retval;
+       }
+
+       retval = of_property_read_u32(dev->of_node, "csi_id",
+                                       &(ov5640_data.csi));
+       if (retval) {
+               dev_err(dev, "csi_id invalid\n");
+               return retval;
+       }
+
+       /* Set mclk rate before clk on */
+       ov5640_set_clk_rate();
+
+       clk_prepare_enable(ov5640_data.sensor_clk);
+
+       ov5640_data.io_init = ov5640_reset;
+       ov5640_data.i2c_client = client;
+       ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+       ov5640_data.pix.width = 640;
+       ov5640_data.pix.height = 480;
+       ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+                                          V4L2_CAP_TIMEPERFRAME;
+       ov5640_data.streamcap.capturemode = 0;
+       ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+       ov5640_data.streamcap.timeperframe.numerator = 1;
+
+       ov5640_regulator_enable(&client->dev);
+
+       ov5640_reset();
+
+       ov5640_power_down(0);
+
+       retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
+       if (retval < 0 || chip_id_high != 0x56) {
+               clk_disable_unprepare(ov5640_data.sensor_clk);
+               pr_warning("camera ov5640 is not found\n");
+               return -ENODEV;
+       }
+       retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
+       if (retval < 0 || chip_id_low != 0x40) {
+               clk_disable_unprepare(ov5640_data.sensor_clk);
+               pr_warning("camera ov5640 is not found\n");
+               return -ENODEV;
+       }
+
+       retval = init_device();
+       if (retval < 0) {
+               clk_disable_unprepare(ov5640_data.sensor_clk);
+               pr_warning("camera ov5640 init failed\n");
+               ov5640_power_down(1);
+               return retval;
+       }
+
+       clk_disable(ov5640_data.sensor_clk);
+
+       v4l2_i2c_subdev_init(&ov5640_data.subdev, client, &ov5640_subdev_ops);
+
+       retval = v4l2_async_register_subdev(&ov5640_data.subdev);
+       if (retval < 0)
+               dev_err(&client->dev,
+                                       "%s--Async register failed, ret=%d\n", __func__, retval);
+
+       pr_info("camera ov5640, is found\n");
+       return retval;
+}
+
+/*!
+ * ov5640 I2C detach function
+ *
+ * @param client            struct i2c_client *
+ * @return  Error code indicating success or failure
+ */
+static int ov5640_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+       v4l2_async_unregister_subdev(sd);
+
+       clk_unprepare(ov5640_data.sensor_clk);
+
+       ov5640_power_down(1);
+
+       if (analog_regulator)
+               regulator_disable(analog_regulator);
+
+       if (core_regulator)
+               regulator_disable(core_regulator);
+
+       if (io_regulator)
+               regulator_disable(io_regulator);
+
+       return 0;
+}
+
+module_i2c_driver(ov5640_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5640 Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/capture/ov5647_mipi.c b/drivers/media/platform/mxc/capture/ov5647_mipi.c
new file mode 100644 (file)
index 0000000..109f774
--- /dev/null
@@ -0,0 +1,1721 @@
+/*
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define OV5647_VOLTAGE_ANALOG               2800000
+#define OV5647_VOLTAGE_DIGITAL_CORE         1500000
+#define OV5647_VOLTAGE_DIGITAL_IO           1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5647_XCLK_MIN 6000000
+#define OV5647_XCLK_MAX 24000000
+
+#define OV5647_CHIP_ID_HIGH_BYTE       0x300A
+#define OV5647_CHIP_ID_LOW_BYTE                0x300B
+
+enum ov5647_mode {
+       ov5647_mode_MIN = 0,
+       ov5647_mode_VGA_640_480 = 0,
+       ov5647_mode_720P_1280_720 = 1,
+       ov5647_mode_1080P_1920_1080 = 2,
+       ov5647_mode_QSXGA_2592_1944 = 3,
+       ov5647_mode_MAX = 3,
+       ov5647_mode_INIT = 0xff, /*only for sensor init*/
+};
+
+enum ov5647_frame_rate {
+       ov5647_15_fps,
+       ov5647_30_fps
+};
+
+static int ov5647_framerates[] = {
+       [ov5647_15_fps] = 15,
+       [ov5647_30_fps] = 30,
+};
+
+struct ov5647_datafmt {
+       u32     code;
+       enum v4l2_colorspace            colorspace;
+};
+
+/* image size under 1280 * 960 are SUBSAMPLING
+ * image size upper 1280 * 960 are SCALING
+ */
+enum ov5647_downsize_mode {
+       SUBSAMPLING,
+       SCALING,
+};
+
+struct reg_value {
+       u16 u16RegAddr;
+       u8 u8Val;
+       u8 u8Mask;
+       u32 u32Delay_ms;
+};
+
+struct ov5647_mode_info {
+       enum ov5647_mode mode;
+       enum ov5647_downsize_mode dn_mode;
+       u32 width;
+       u32 height;
+       struct reg_value *init_data_ptr;
+       u32 init_data_size;
+};
+
+struct otp_struct {
+       int customer_id;
+       int module_integrator_id;
+       int lens_id;
+       int rg_ratio;
+       int bg_ratio;
+       int user_data[3];
+       int light_rg;
+       int light_bg;
+};
+
+struct ov5647 {
+       struct v4l2_subdev              subdev;
+       struct i2c_client *i2c_client;
+       struct v4l2_pix_format pix;
+       const struct ov5647_datafmt     *fmt;
+       struct v4l2_captureparm streamcap;
+       bool on;
+
+       /* control settings */
+       int brightness;
+       int hue;
+       int contrast;
+       int saturation;
+       int red;
+       int green;
+       int blue;
+       int ae_mode;
+
+       u32 mclk;
+       u8 mclk_source;
+       struct clk *sensor_clk;
+       int csi;
+
+       void (*io_init)(void);
+};
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct ov5647 ov5647_data;
+static int pwn_gpio, rst_gpio;
+static int prev_sysclk, prev_HTS;
+static int AE_low, AE_high, AE_Target = 52;
+
+/* R/G and B/G of typical camera module is defined here,
+ * the typical camera module is selected by CameraAnalyzer. */
+static int RG_Ratio_Typical = 0x70;
+static int BG_Ratio_Typical = 0x70;
+
+
+static struct reg_value ov5647_init_setting[] = {
+
+       {0x0100, 0x00, 0, 0},                       {0x3035, 0x11, 0, 0},
+       {0x3036, 0x69, 0, 0}, {0x303c, 0x11, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x370c, 0x0f, 0, 0}, {0x3612, 0x59, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x5000, 0x06, 0, 0}, {0x5002, 0x40, 0, 0},
+       {0x5003, 0x08, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x3000, 0xff, 0, 0},
+       {0x3001, 0xff, 0, 0}, {0x3002, 0xff, 0, 0}, {0x301d, 0xf0, 0, 0},
+       {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3c01, 0x80, 0, 0},
+       {0x3b07, 0x0c, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3814, 0x31, 0, 0},
+       {0x3815, 0x31, 0, 0}, {0x3708, 0x64, 0, 0}, {0x3709, 0x52, 0, 0},
+       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+       {0x380b, 0xc0, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x18, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0x0e, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x27, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x95, 0, 0},
+       {0x3630, 0x2e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0},
+       {0x3634, 0x44, 0, 0}, {0x3620, 0x64, 0, 0}, {0x3621, 0xe0, 0, 0},
+       {0x3600, 0x37, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+       {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x3731, 0x02, 0, 0},
+       {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3f05, 0x02, 0, 0},
+       {0x3f06, 0x10, 0, 0}, {0x3f01, 0x0a, 0, 0}, {0x3a08, 0x01, 0, 0},
+       {0x3a09, 0x27, 0, 0}, {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0f, 0x58, 0, 0},
+       {0x3a10, 0x50, 0, 0}, {0x3a1b, 0x58, 0, 0}, {0x3a1e, 0x50, 0, 0},
+       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x28, 0, 0}, {0x4001, 0x02, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x4000, 0x09, 0, 0}, {0x4050, 0x6e, 0, 0},
+       {0x4051, 0x8f, 0, 0}, {0x4837, 0x17, 0, 0}, {0x3503, 0x03, 0, 0},
+       {0x3501, 0x44, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350a, 0x00, 0, 0},
+       {0x350b, 0x7f, 0, 0}, {0x5001, 0x01, 0, 0}, {0x5002, 0x41, 0, 0},
+       {0x5180, 0x08, 0, 0}, {0x5186, 0x04, 0, 0}, {0x5187, 0x00, 0, 0},
+       {0x5188, 0x04, 0, 0}, {0x5189, 0x00, 0, 0}, {0x518a, 0x04, 0, 0},
+       {0x518b, 0x00, 0, 0}, {0x5000, 0x86, 0, 0}, {0x5800, 0x11, 0, 0},
+       {0x5801, 0x0a, 0, 0}, {0x5802, 0x09, 0, 0}, {0x5803, 0x09, 0, 0},
+       {0x5804, 0x0a, 0, 0}, {0x5805, 0x0f, 0, 0}, {0x5806, 0x07, 0, 0},
+       {0x5807, 0x05, 0, 0}, {0x5808, 0x03, 0, 0}, {0x5809, 0x03, 0, 0},
+       {0x580a, 0x05, 0, 0}, {0x580b, 0x07, 0, 0}, {0x580c, 0x05, 0, 0},
+       {0x580d, 0x02, 0, 0}, {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0},
+       {0x5810, 0x02, 0, 0}, {0x5811, 0x05, 0, 0}, {0x5812, 0x05, 0, 0},
+       {0x5813, 0x02, 0, 0}, {0x5814, 0x00, 0, 0}, {0x5815, 0x00, 0, 0},
+       {0x5816, 0x01, 0, 0}, {0x5817, 0x05, 0, 0}, {0x5818, 0x08, 0, 0},
+       {0x5819, 0x05, 0, 0}, {0x581a, 0x03, 0, 0}, {0x581b, 0x03, 0, 0},
+       {0x581c, 0x04, 0, 0}, {0x581d, 0x07, 0, 0}, {0x581e, 0x10, 0, 0},
+       {0x581f, 0x0b, 0, 0}, {0x5820, 0x09, 0, 0}, {0x5821, 0x09, 0, 0},
+       {0x5822, 0x09, 0, 0}, {0x5823, 0x0e, 0, 0}, {0x5824, 0x28, 0, 0},
+       {0x5825, 0x1a, 0, 0}, {0x5826, 0x1a, 0, 0}, {0x5827, 0x1a, 0, 0},
+       {0x5828, 0x46, 0, 0}, {0x5829, 0x2a, 0, 0}, {0x582a, 0x26, 0, 0},
+       {0x582b, 0x44, 0, 0}, {0x582c, 0x26, 0, 0}, {0x582d, 0x2a, 0, 0},
+       {0x582e, 0x28, 0, 0}, {0x582f, 0x42, 0, 0}, {0x5830, 0x40, 0, 0},
+       {0x5831, 0x42, 0, 0}, {0x5832, 0x28, 0, 0}, {0x5833, 0x0a, 0, 0},
+       {0x5834, 0x16, 0, 0}, {0x5835, 0x44, 0, 0}, {0x5836, 0x26, 0, 0},
+       {0x5837, 0x2a, 0, 0}, {0x5838, 0x28, 0, 0}, {0x5839, 0x0a, 0, 0},
+       {0x583a, 0x0a, 0, 0}, {0x583b, 0x0a, 0, 0}, {0x583c, 0x26, 0, 0},
+       {0x583d, 0xbe, 0, 0}, {0x0100, 0x01, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, {0x3017, 0xe0, 0, 0},
+       {0x301c, 0xfc, 0, 0}, {0x3636, 0x06, 0, 0}, {0x3016, 0x08, 0, 0},
+       {0x3827, 0xec, 0, 0}, {0x3018, 0x44, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3106, 0xf5, 0, 0}, {0x3034, 0x18, 0, 0}, {0x301c, 0xf8, 0, 0},
+};
+
+static struct reg_value ov5647_setting_60fps_VGA_640_480[] = {
+       {0x0100, 0x00, 0, 0},                        {0x3035, 0x11, 0, 0},
+       {0x3036, 0x46, 0, 0}, {0x303c, 0x11, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3820, 0x41, 0, 0}, {0x370c, 0x0f, 0, 0}, {0x3612, 0x59, 0, 0},
+       {0x3618, 0x00, 0, 0}, {0x5000, 0x06, 0, 0}, {0x5002, 0x40, 0, 0},
+       {0x5003, 0x08, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x3000, 0xff, 0, 0},
+       {0x3001, 0xff, 0, 0}, {0x3002, 0xff, 0, 0}, {0x301d, 0xf0, 0, 0},
+       {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3c01, 0x80, 0, 0},
+       {0x3b07, 0x0c, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x3c, 0, 0},
+       {0x380e, 0x01, 0, 0}, {0x380f, 0xf8, 0, 0}, {0x3814, 0x71, 0, 0},
+       {0x3815, 0x71, 0, 0}, {0x3708, 0x64, 0, 0}, {0x3709, 0x52, 0, 0},
+       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+       {0x380b, 0xe0, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x10, 0, 0},
+       {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+       {0x3805, 0x2f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+       {0x3630, 0x2e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0},
+       {0x3634, 0x44, 0, 0}, {0x3620, 0x64, 0, 0}, {0x3621, 0xe0, 0, 0},
+       {0x3600, 0x37, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+       {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x3731, 0x02, 0, 0},
+       {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3f05, 0x02, 0, 0},
+       {0x3f06, 0x10, 0, 0}, {0x3f01, 0x0a, 0, 0}, {0x3a08, 0x01, 0, 0},
+       {0x3a09, 0x2e, 0, 0}, {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xfb, 0, 0},
+       {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x3a0f, 0x58, 0, 0},
+       {0x3a10, 0x50, 0, 0}, {0x3a1b, 0x58, 0, 0}, {0x3a1e, 0x50, 0, 0},
+       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x28, 0, 0}, {0x4001, 0x02, 0, 0},
+       {0x4004, 0x02, 0, 0}, {0x4000, 0x09, 0, 0}, {0x4050, 0x6e, 0, 0},
+       {0x4051, 0x8f, 0, 0}, {0x0100, 0x01, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, {0x3017, 0xe0, 0, 0},
+       {0x301c, 0xfc, 0, 0}, {0x3636, 0x06, 0, 0}, {0x3016, 0x08, 0, 0},
+       {0x3827, 0xec, 0, 0}, {0x3018, 0x44, 0, 0}, {0x3035, 0x21, 0, 0},
+       {0x3106, 0xf5, 0, 0}, {0x3034, 0x18, 0, 0}, {0x301c, 0xf8, 0, 0},
+};
+
+static struct reg_value ov5647_setting_30fps_720P_1280_720[] = {
+       {0x0100, 0x00, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+       {0x3612, 0x59, 0, 0}, {0x3618, 0x00, 0, 0}, {0x380c, 0x09, 0, 0},
+       {0x380d, 0xe8, 0, 0}, {0x380e, 0x04, 0, 0}, {0x380f, 0x50, 0, 0},
+       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3709, 0x52, 0, 0},
+       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+       {0x380b, 0xd0, 0, 0}, {0x3801, 0x18, 0, 0}, {0x3802, 0x00, 0, 0},
+       {0x3803, 0xf8, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x27, 0, 0},
+       {0x3806, 0x06, 0, 0}, {0x3807, 0xa7, 0, 0}, {0x3a09, 0xbe, 0, 0},
+       {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x74, 0, 0}, {0x3a0d, 0x02, 0, 0},
+       {0x3a0e, 0x01, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4005, 0x18, 0, 0},
+       {0x0100, 0x01, 0, 0},
+};
+
+static struct reg_value ov5647_setting_30fps_1080P_1920_1080[] = {
+       {0x0100, 0x00, 0, 0}, {0x3820, 0x00, 0, 0}, {0x3821, 0x06, 0, 0},
+       {0x3612, 0x5b, 0, 0}, {0x3618, 0x04, 0, 0}, {0x380c, 0x09, 0, 0},
+       {0x380d, 0xe8, 0, 0}, {0x380e, 0x04, 0, 0}, {0x380f, 0x50, 0, 0},
+       {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3709, 0x12, 0, 0},
+       {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0},
+       {0x380b, 0x38, 0, 0}, {0x3801, 0x5c, 0, 0}, {0x3802, 0x01, 0, 0},
+       {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xe3, 0, 0},
+       {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3a09, 0x4b, 0, 0},
+       {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x13, 0, 0}, {0x3a0d, 0x04, 0, 0},
+       {0x3a0e, 0x03, 0, 0}, {0x4004, 0x04, 0, 0}, {0x4005, 0x18, 0, 0},
+       {0x0100, 0x01, 0, 0},
+};
+
+static struct reg_value ov5647_setting_15fps_QSXGA_2592_1944[] = {
+       {0x0100, 0x00, 0, 0}, {0x3820, 0x00, 0, 0}, {0x3821, 0x06, 0, 0},
+       {0x3612, 0x5b, 0, 0}, {0x3618, 0x04, 0, 0}, {0x380c, 0x0b, 0, 0},
+       {0x380d, 0x10, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb8, 0, 0},
+       {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3709, 0x12, 0, 0},
+       {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+       {0x380b, 0x98, 0, 0}, {0x3801, 0x0c, 0, 0}, {0x3802, 0x00, 0, 0},
+       {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x33, 0, 0},
+       {0x3806, 0x07, 0, 0}, {0x3807, 0xa3, 0, 0}, {0x3a09, 0x28, 0, 0},
+       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0d, 0x08, 0, 0},
+       {0x3a0e, 0x06, 0, 0}, {0x4004, 0x04, 0, 0}, {0x4005, 0x1a, 0, 0},
+       {0x0100, 0x01, 0, 0},
+};
+
+static struct ov5647_mode_info ov5647_mode_info_data[2][ov5647_mode_MAX + 1] = {
+       {
+               {ov5647_mode_VGA_640_480, -1, 0, 0, NULL, 0},
+               {ov5647_mode_720P_1280_720, -1, 0, 0, NULL, 0},
+               {ov5647_mode_1080P_1920_1080, -1, 0, 0, NULL, 0},
+               {ov5647_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
+               ov5647_setting_15fps_QSXGA_2592_1944,
+               ARRAY_SIZE(ov5647_setting_15fps_QSXGA_2592_1944)},
+       },
+       {
+               /* Actually VGA working in 60fps mode */
+               {ov5647_mode_VGA_640_480, SUBSAMPLING, 640,  480,
+               ov5647_setting_60fps_VGA_640_480,
+               ARRAY_SIZE(ov5647_setting_60fps_VGA_640_480)},
+               {ov5647_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
+               ov5647_setting_30fps_720P_1280_720,
+               ARRAY_SIZE(ov5647_setting_30fps_720P_1280_720)},
+               {ov5647_mode_1080P_1920_1080, SCALING, 1920, 1080,
+               ov5647_setting_30fps_1080P_1920_1080,
+               ARRAY_SIZE(ov5647_setting_30fps_1080P_1920_1080)},
+               {ov5647_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
+       },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+static struct regulator *gpo_regulator;
+
+static int ov5647_probe(struct i2c_client *adapter,
+                               const struct i2c_device_id *device_id);
+static int ov5647_remove(struct i2c_client *client);
+
+static s32 ov5647_read_reg(u16 reg, u8 *val);
+static s32 ov5647_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5647_id[] = {
+       {"ov5647_mipi", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5647_id);
+
+static struct i2c_driver ov5647_i2c_driver = {
+       .driver = {
+                 .owner = THIS_MODULE,
+                 .name  = "ov5647_mipi",
+                 },
+       .probe  = ov5647_probe,
+       .remove = ov5647_remove,
+       .id_table = ov5647_id,
+};
+
+static const struct ov5647_datafmt ov5647_colour_fmts[] = {
+       {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_JPEG},
+};
+
+static struct ov5647 *to_ov5647(const struct i2c_client *client)
+{
+       return container_of(i2c_get_clientdata(client), struct ov5647, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct ov5647_datafmt
+                       *ov5647_find_datafmt(u32 code)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ov5647_colour_fmts); i++)
+               if (ov5647_colour_fmts[i].code == code)
+                       return ov5647_colour_fmts + i;
+
+       return NULL;
+}
+
+static inline void ov5647_power_down(int enable)
+{
+       if (pwn_gpio < 0)
+               return;
+
+       /* 19x19 pwdn pin invert by mipi daughter card */
+       if (!enable)
+               gpio_set_value_cansleep(pwn_gpio, 1);
+       else
+               gpio_set_value_cansleep(pwn_gpio, 0);
+
+       msleep(2);
+}
+
+static void ov5647_reset(void)
+{
+       if (rst_gpio < 0 || pwn_gpio < 0)
+               return;
+
+       /* camera reset */
+       gpio_set_value_cansleep(rst_gpio, 1);
+
+       /* camera power dowmn */
+       gpio_set_value_cansleep(pwn_gpio, 1);
+       msleep(5);
+
+       gpio_set_value_cansleep(pwn_gpio, 0);
+       msleep(5);
+
+       gpio_set_value_cansleep(rst_gpio, 0);
+       msleep(1);
+
+       gpio_set_value_cansleep(rst_gpio, 1);
+       msleep(5);
+
+       gpio_set_value_cansleep(pwn_gpio, 1);
+}
+
+static int ov5647_regulator_enable(struct device *dev)
+{
+       int ret = 0;
+
+       io_regulator = devm_regulator_get(dev, "DOVDD");
+       if (!IS_ERR(io_regulator)) {
+               regulator_set_voltage(io_regulator,
+                                     OV5647_VOLTAGE_DIGITAL_IO,
+                                     OV5647_VOLTAGE_DIGITAL_IO);
+               ret = regulator_enable(io_regulator);
+               if (ret) {
+                       pr_err("%s:io set voltage error\n", __func__);
+                       return ret;
+               } else {
+                       dev_dbg(dev,
+                               "%s:io set voltage ok\n", __func__);
+               }
+       } else {
+               pr_err("%s: cannot get io voltage error\n", __func__);
+               io_regulator = NULL;
+       }
+
+       core_regulator = devm_regulator_get(dev, "DVDD");
+       if (!IS_ERR(core_regulator)) {
+               regulator_set_voltage(core_regulator,
+                                     OV5647_VOLTAGE_DIGITAL_CORE,
+                                     OV5647_VOLTAGE_DIGITAL_CORE);
+               ret = regulator_enable(core_regulator);
+               if (ret) {
+                       pr_err("%s:core set voltage error\n", __func__);
+                       return ret;
+               } else {
+                       dev_dbg(dev,
+                               "%s:core set voltage ok\n", __func__);
+               }
+       } else {
+               core_regulator = NULL;
+               pr_err("%s: cannot get core voltage error\n", __func__);
+       }
+
+       analog_regulator = devm_regulator_get(dev, "AVDD");
+       if (!IS_ERR(analog_regulator)) {
+               regulator_set_voltage(analog_regulator,
+                                     OV5647_VOLTAGE_ANALOG,
+                                     OV5647_VOLTAGE_ANALOG);
+               ret = regulator_enable(analog_regulator);
+               if (ret) {
+                       pr_err("%s:analog set voltage error\n",
+                               __func__);
+                       return ret;
+               } else {
+                       dev_dbg(dev,
+                               "%s:analog set voltage ok\n", __func__);
+               }
+       } else {
+               analog_regulator = NULL;
+               pr_err("%s: cannot get analog voltage error\n", __func__);
+       }
+
+       return ret;
+}
+
+static s32 ov5647_write_reg(u16 reg, u8 val)
+{
+       u8 au8Buf[3] = {0};
+
+       au8Buf[0] = reg >> 8;
+       au8Buf[1] = reg & 0xff;
+       au8Buf[2] = val;
+
+       if (i2c_master_send(ov5647_data.i2c_client, au8Buf, 3) < 0) {
+               pr_err("%s:write reg error:reg=%x,val=%x\n",
+                       __func__, reg, val);
+               return -1;
+       }
+
+       return 0;
+}
+
+static s32 ov5647_read_reg(u16 reg, u8 *val)
+{
+       u8 au8RegBuf[2] = {0};
+       u8 u8RdVal = 0;
+
+       au8RegBuf[0] = reg >> 8;
+       au8RegBuf[1] = reg & 0xff;
+
+       if (2 != i2c_master_send(ov5647_data.i2c_client, au8RegBuf, 2)) {
+               pr_err("%s:write reg error:reg=%x\n",
+                               __func__, reg);
+               return -1;
+       }
+
+       if (1 != i2c_master_recv(ov5647_data.i2c_client, &u8RdVal, 1)) {
+               pr_err("%s:read reg error:reg=%x,val=%x\n",
+                               __func__, reg, u8RdVal);
+               return -1;
+       }
+
+       *val = u8RdVal;
+
+       return u8RdVal;
+}
+
+/* index: index of otp group. (0, 1, 2)
+ * return:
+ * 0, group index is empty
+ * 1, group index has invalid data
+ * 2, group index has valid data */
+static int ov5647_check_otp(int index)
+{
+       int i;
+       int address;
+       u8 temp;
+
+       /* read otp into buffer */
+       ov5647_write_reg(0x3d21, 0x01);
+       msleep(20);
+       address = 0x3d05 + index * 9;
+       temp = ov5647_read_reg(address, &temp);
+
+       /* disable otp read */
+       ov5647_write_reg(0x3d21, 0x00);
+
+       /* clear otp buffer */
+       for (i = 0; i < 32; i++)
+               ov5647_write_reg(0x3d00 + i, 0x00);
+
+       if (!temp)
+               return 0;
+       else if ((!(temp & 0x80)) && (temp & 0x7f))
+               return 2;
+       else
+               return 1;
+}
+
+/* index: index of otp group. (0, 1, 2)
+ * return: 0 */
+static int ov5647_read_otp(int index, struct otp_struct *otp_ptr)
+{
+       int i;
+       int address;
+       u8 temp;
+
+       /* read otp into buffer */
+       ov5647_write_reg(0x3d21, 0x01);
+       msleep(2);
+       address = 0x3d05 + index * 9;
+       temp = ov5647_read_reg(address, &temp);
+       (*otp_ptr).customer_id = temp & 0x7f;
+
+       (*otp_ptr).module_integrator_id = ov5647_read_reg(address, &temp);
+       (*otp_ptr).lens_id = ov5647_read_reg(address + 1, &temp);
+       (*otp_ptr).rg_ratio = ov5647_read_reg(address + 2, &temp);
+       (*otp_ptr).bg_ratio = ov5647_read_reg(address + 3, &temp);
+       (*otp_ptr).user_data[0] = ov5647_read_reg(address + 4, &temp);
+       (*otp_ptr).user_data[1] = ov5647_read_reg(address + 5, &temp);
+       (*otp_ptr).user_data[2] = ov5647_read_reg(address + 6, &temp);
+       (*otp_ptr).light_rg = ov5647_read_reg(address + 7, &temp);
+       (*otp_ptr).light_bg = ov5647_read_reg(address + 8, &temp);
+
+       /* disable otp read */
+       ov5647_write_reg(0x3d21, 0x00);
+
+       /* clear otp buffer */
+       for (i = 0; i < 32; i++)
+               ov5647_write_reg(0x3d00 + i, 0x00);
+
+       return 0;
+}
+
+/* R_gain, sensor red gain of AWB, 0x400 =1
+ * G_gain, sensor green gain of AWB, 0x400 =1
+ * B_gain, sensor blue gain of AWB, 0x400 =1
+ * return 0 */
+static int ov5647_update_awb_gain(int R_gain, int G_gain, int B_gain)
+{
+       if (R_gain > 0x400) {
+               ov5647_write_reg(0x5186, R_gain >> 8);
+               ov5647_write_reg(0x5187, R_gain & 0x00ff);
+       }
+       if (G_gain > 0x400) {
+               ov5647_write_reg(0x5188, G_gain >> 8);
+               ov5647_write_reg(0x5189, G_gain & 0x00ff);
+       }
+       if (B_gain > 0x400) {
+               ov5647_write_reg(0x518a, B_gain >> 8);
+               ov5647_write_reg(0x518b, B_gain & 0x00ff);
+       }
+
+       return 0;
+}
+
+/* call this function after OV5647 initialization
+ * return value:
+ * 0 update success
+ * 1 no OTP */
+static int ov5647_update_otp(void)
+{
+       struct otp_struct current_otp;
+       int i;
+       int otp_index;
+       int temp;
+       int R_gain, G_gain, B_gain, G_gain_R, G_gain_B;
+       int rg, bg;
+
+       /* R/G and B/G of current camera module is read out from sensor OTP
+        * check first OTP with valid data */
+       for (i = 0; i < 3; i++) {
+               temp = ov5647_check_otp(i);
+               if (temp == 2) {
+                       otp_index = i;
+                       break;
+               }
+       }
+       if (i == 3) {
+               /* no valid wb OTP data */
+               printk(KERN_WARNING "No valid wb otp data\n");
+               return 1;
+       }
+
+       ov5647_read_otp(otp_index, &current_otp);
+       if (current_otp.light_rg == 0)
+               rg = current_otp.rg_ratio;
+       else
+               rg = current_otp.rg_ratio * (current_otp.light_rg + 128) / 256;
+
+       if (current_otp.light_bg == 0)
+               bg = current_otp.bg_ratio;
+       else
+               bg = current_otp.bg_ratio * (current_otp.light_bg + 128) / 256;
+
+       /* calculate G gain
+        * 0x400 = 1x gain */
+       if (bg < BG_Ratio_Typical) {
+               if (rg < RG_Ratio_Typical) {
+                       /* current_otp.bg_ratio < BG_Ratio_typical &&
+                        * current_otp.rg_ratio < RG_Ratio_typical */
+                       G_gain = 0x400;
+                       B_gain = 0x400 * BG_Ratio_Typical / bg;
+                       R_gain = 0x400 * RG_Ratio_Typical / rg;
+               } else {
+                       /* current_otp.bg_ratio < BG_Ratio_typical &&
+                        * current_otp.rg_ratio >= RG_Ratio_typical */
+                       R_gain = 0x400;
+                       G_gain = 0x400 * rg / RG_Ratio_Typical;
+                       B_gain = G_gain * BG_Ratio_Typical / bg;
+               }
+       } else {
+               if (rg < RG_Ratio_Typical) {
+                       /* current_otp.bg_ratio >= BG_Ratio_typical &&
+                        * current_otp.rg_ratio < RG_Ratio_typical */
+                       B_gain = 0x400;
+                       G_gain = 0x400 * bg / BG_Ratio_Typical;
+                       R_gain = G_gain * RG_Ratio_Typical / rg;
+               } else {
+                       /* current_otp.bg_ratio >= BG_Ratio_typical &&
+                        * current_otp.rg_ratio >= RG_Ratio_typical */
+                       G_gain_B = 0x400 * bg / BG_Ratio_Typical;
+                       G_gain_R = 0x400 * rg / RG_Ratio_Typical;
+                       if (G_gain_B > G_gain_R) {
+                               B_gain = 0x400;
+                               G_gain = G_gain_B;
+                               R_gain = G_gain * RG_Ratio_Typical / rg;
+                       } else {
+                               R_gain = 0x400;
+                               G_gain = G_gain_R;
+                               B_gain = G_gain * BG_Ratio_Typical / bg;
+                       }
+               }
+       }
+       ov5647_update_awb_gain(R_gain, G_gain, B_gain);
+       return 0;
+}
+
+static void ov5647_stream_on(void)
+{
+       ov5647_write_reg(0x4202, 0x00);
+}
+
+static void ov5647_stream_off(void)
+{
+       ov5647_write_reg(0x4202, 0x0f);
+       /* both clock and data lane in LP00 */
+       ov5647_write_reg(0x0100, 0x00);
+}
+
+static int ov5647_get_sysclk(void)
+{
+       /* calculate sysclk */
+       int xvclk = ov5647_data.mclk / 10000;
+       int sysclk, temp1, temp2;
+       int pre_div02x, div_cnt7b, sdiv0, pll_rdiv, bit_div2x, sclk_div, VCO;
+       int pre_div02x_map[] = {2, 2, 4, 6, 8, 3, 12, 5, 16, 2, 2, 2, 2, 2, 2, 2};
+       int sdiv0_map[] = {16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+       int pll_rdiv_map[] = {1, 2};
+       int bit_div2x_map[] = {2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 5, 2, 2, 2, 2, 2};
+       int sclk_div_map[] = {1, 2, 4, 1};
+       u8 temp;
+
+       temp1 = ov5647_read_reg(0x3037, &temp);
+       temp2 = temp1 & 0x0f;
+       pre_div02x = pre_div02x_map[temp2];
+       temp2 = (temp1 >> 4) & 0x01;
+       pll_rdiv = pll_rdiv_map[temp2];
+       temp1 = ov5647_read_reg(0x3036, &temp);
+
+       div_cnt7b = temp1;
+
+       VCO = xvclk * 2 / pre_div02x * div_cnt7b;
+       temp1 = ov5647_read_reg(0x3035, &temp);
+       temp2 = temp1 >> 4;
+       sdiv0 = sdiv0_map[temp2];
+       temp1 = ov5647_read_reg(0x3034, &temp);
+       temp2 = temp1 & 0x0f;
+       bit_div2x = bit_div2x_map[temp2];
+       temp1 = ov5647_read_reg(0x3106, &temp);
+       temp2 = (temp1 >> 2) & 0x03;
+       sclk_div = sclk_div_map[temp2];
+       sysclk = VCO * 2 / sdiv0 / pll_rdiv / bit_div2x / sclk_div;
+       return sysclk;
+}
+
+static void ov5647_set_night_mode(void)
+{
+        /* read HTS from register settings */
+       u8 mode;
+
+       ov5647_read_reg(0x3a00, &mode);
+       mode &= 0xfb;
+       ov5647_write_reg(0x3a00, mode);
+}
+
+static int ov5647_get_HTS(void)
+{
+        /* read HTS from register settings */
+       int HTS;
+       u8 temp;
+
+       HTS = ov5647_read_reg(0x380c, &temp);
+       HTS = (HTS << 8) + ov5647_read_reg(0x380d, &temp);
+
+       return HTS;
+}
+
+static int ov5647_soft_reset(void)
+{
+       /* soft reset ov5647 */
+
+       ov5647_write_reg(0x0103, 0x1);
+       msleep(5);
+
+       return 0;
+}
+
+static int ov5647_get_VTS(void)
+{
+        /* read VTS from register settings */
+       int VTS;
+       u8 temp;
+
+       /* total vertical size[15:8] high byte */
+       VTS = ov5647_read_reg(0x380e, &temp);
+
+       VTS = (VTS << 8) + ov5647_read_reg(0x380f, &temp);
+
+       return VTS;
+}
+
+static int ov5647_set_VTS(int VTS)
+{
+        /* write VTS to registers */
+        int temp;
+
+        temp = VTS & 0xff;
+        ov5647_write_reg(0x380f, temp);
+
+        temp = VTS >> 8;
+        ov5647_write_reg(0x380e, temp);
+
+        return 0;
+}
+
+static int ov5647_get_shutter(void)
+{
+        /* read shutter, in number of line period */
+       int shutter;
+       u8 temp;
+
+       shutter = (ov5647_read_reg(0x03500, &temp) & 0x0f);
+       shutter = (shutter << 8) + ov5647_read_reg(0x3501, &temp);
+       shutter = (shutter << 4) + (ov5647_read_reg(0x3502, &temp)>>4);
+
+        return shutter;
+}
+
+static int ov5647_set_shutter(int shutter)
+{
+        /* write shutter, in number of line period */
+        int temp;
+
+        shutter = shutter & 0xffff;
+
+        temp = shutter & 0x0f;
+        temp = temp << 4;
+        ov5647_write_reg(0x3502, temp);
+
+        temp = shutter & 0xfff;
+        temp = temp >> 4;
+        ov5647_write_reg(0x3501, temp);
+
+        temp = shutter >> 12;
+        ov5647_write_reg(0x3500, temp);
+
+        return 0;
+}
+
+static int ov5647_get_gain16(void)
+{
+        /* read gain, 16 = 1x */
+       int gain16;
+       u8 temp;
+
+       gain16 = ov5647_read_reg(0x350a, &temp) & 0x03;
+       gain16 = (gain16 << 8) + ov5647_read_reg(0x350b, &temp);
+
+       return gain16;
+}
+
+static int ov5647_set_gain16(int gain16)
+{
+       /* write gain, 16 = 1x */
+       u8 temp;
+       gain16 = gain16 & 0x3ff;
+
+       temp = gain16 & 0xff;
+       ov5647_write_reg(0x350b, temp);
+
+       temp = gain16 >> 8;
+       ov5647_write_reg(0x350a, temp);
+
+       return 0;
+}
+
+static int ov5647_get_light_freq(void)
+{
+       /* get banding filter value */
+       int temp, temp1, light_freq = 0;
+       u8 tmp;
+
+       temp = ov5647_read_reg(0x3c01, &tmp);
+
+       if (temp & 0x80) {
+               /* manual */
+               temp1 = ov5647_read_reg(0x3c00, &tmp);
+               if (temp1 & 0x04) {
+                       /* 50Hz */
+                       light_freq = 50;
+               } else {
+                       /* 60Hz */
+                       light_freq = 60;
+               }
+       } else {
+               /* auto */
+               temp1 = ov5647_read_reg(0x3c0c, &tmp);
+               if (temp1 & 0x01) {
+                       /* 50Hz */
+                       light_freq = 50;
+               } else {
+                       /* 60Hz */
+               }
+       }
+       return light_freq;
+}
+
+static void ov5647_set_bandingfilter(void)
+{
+       int prev_VTS;
+       int band_step60, max_band60, band_step50, max_band50;
+
+       /* read preview PCLK */
+       prev_sysclk = ov5647_get_sysclk();
+       /* read preview HTS */
+       prev_HTS = ov5647_get_HTS();
+
+       /* read preview VTS */
+       prev_VTS = ov5647_get_VTS();
+
+       /* calculate banding filter */
+       /* 60Hz */
+       band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
+       ov5647_write_reg(0x3a0a, (band_step60 >> 8));
+       ov5647_write_reg(0x3a0b, (band_step60 & 0xff));
+
+       max_band60 = (int)((prev_VTS-4)/band_step60);
+       ov5647_write_reg(0x3a0d, max_band60);
+
+       /* 50Hz */
+       band_step50 = prev_sysclk * 100/prev_HTS;
+       ov5647_write_reg(0x3a08, (band_step50 >> 8));
+       ov5647_write_reg(0x3a09, (band_step50 & 0xff));
+
+       max_band50 = (int)((prev_VTS-4)/band_step50);
+       ov5647_write_reg(0x3a0e, max_band50);
+}
+
+static int ov5647_set_AE_target(int target)
+{
+       /* stable in high */
+       int fast_high, fast_low;
+       AE_low = target * 23 / 25;      /* 0.92 */
+       AE_high = target * 27 / 25;     /* 1.08 */
+
+       fast_high = AE_high<<1;
+       if (fast_high > 255)
+               fast_high = 255;
+
+       fast_low = AE_low >> 1;
+
+       ov5647_write_reg(0x3a0f, AE_high);
+       ov5647_write_reg(0x3a10, AE_low);
+       ov5647_write_reg(0x3a1b, AE_high);
+       ov5647_write_reg(0x3a1e, AE_low);
+       ov5647_write_reg(0x3a11, fast_high);
+       ov5647_write_reg(0x3a1f, fast_low);
+
+       return 0;
+}
+
+static void ov5647_turn_on_AE_AG(int enable)
+{
+       u8 ae_ag_ctrl;
+
+       ov5647_read_reg(0x3503, &ae_ag_ctrl);
+       if (enable) {
+               /* turn on auto AE/AG */
+               ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
+       } else {
+               /* turn off AE/AG */
+               ae_ag_ctrl = ae_ag_ctrl | 0x03;
+       }
+       ov5647_write_reg(0x3503, ae_ag_ctrl);
+}
+
+static void ov5647_set_virtual_channel(int channel)
+{
+       u8 channel_id;
+
+       ov5647_read_reg(0x4814, &channel_id);
+       channel_id &= ~(3 << 6);
+       ov5647_write_reg(0x4814, channel_id | (channel << 6));
+}
+
+/* download ov5647 settings to sensor through i2c */
+static int ov5647_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+{
+       register u32 Delay_ms = 0;
+       register u16 RegAddr = 0;
+       register u8 Mask = 0;
+       register u8 Val = 0;
+       u8 RegVal = 0;
+       int i, retval = 0;
+
+       for (i = 0; i < ArySize; ++i, ++pModeSetting) {
+               Delay_ms = pModeSetting->u32Delay_ms;
+               RegAddr = pModeSetting->u16RegAddr;
+               Val = pModeSetting->u8Val;
+               Mask = pModeSetting->u8Mask;
+
+               if (Mask) {
+                       retval = ov5647_read_reg(RegAddr, &RegVal);
+                       if (retval < 0)
+                               goto err;
+
+                       RegVal &= ~(u8)Mask;
+                       Val &= Mask;
+                       Val |= RegVal;
+               }
+
+               retval = ov5647_write_reg(RegAddr, Val);
+               if (retval < 0)
+                       goto err;
+
+               if (Delay_ms)
+                       msleep(Delay_ms);
+       }
+err:
+       return retval;
+}
+
+/* sensor changes between scaling and subsampling
+ * go through exposure calcualtion
+ */
+static int ov5647_change_mode_exposure_calc(enum ov5647_frame_rate frame_rate,
+                               enum ov5647_mode mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 ArySize = 0;
+       int pre_shutter, pre_gain16;
+       int cap_shutter, cap_gain16;
+       int pre_sysclk, pre_HTS;
+       int cap_sysclk, cap_HTS, cap_VTS;
+       long cap_gain16_shutter;
+       int retval = 0;
+
+       /* check if the input mode and frame rate is valid */
+       pModeSetting =
+               ov5647_mode_info_data[frame_rate][mode].init_data_ptr;
+       ArySize =
+               ov5647_mode_info_data[frame_rate][mode].init_data_size;
+
+       ov5647_data.pix.width =
+               ov5647_mode_info_data[frame_rate][mode].width;
+       ov5647_data.pix.height =
+               ov5647_mode_info_data[frame_rate][mode].height;
+
+       if (ov5647_data.pix.width == 0 || ov5647_data.pix.height == 0 ||
+               pModeSetting == NULL || ArySize == 0)
+               return -EINVAL;
+
+       ov5647_stream_off();
+
+       /* turn off night mode for capture */
+       ov5647_set_night_mode();
+
+       pre_shutter = ov5647_get_shutter();
+       pre_gain16 = ov5647_get_gain16();
+       pre_HTS = ov5647_get_HTS();
+       pre_sysclk = ov5647_get_sysclk();
+
+       /* Write capture setting */
+       retval = ov5647_download_firmware(pModeSetting, ArySize);
+       if (retval < 0)
+               goto err;
+
+       /* read capture VTS */
+       cap_VTS = ov5647_get_VTS();
+       cap_HTS = ov5647_get_HTS();
+       cap_sysclk = ov5647_get_sysclk();
+
+       /* calculate capture shutter/gain16 */
+       cap_shutter = pre_shutter * cap_sysclk/pre_sysclk * pre_HTS / cap_HTS;
+
+       if (cap_shutter < 16) {
+               cap_gain16_shutter = pre_shutter * pre_gain16 *
+                               cap_sysclk / pre_sysclk * pre_HTS / cap_HTS;
+               cap_shutter = ((int)(cap_gain16_shutter / 16));
+               if (cap_shutter < 1)
+                       cap_shutter = 1;
+               cap_gain16 = ((int)(cap_gain16_shutter / cap_shutter));
+               if (cap_gain16 < 16)
+                       cap_gain16 = 16;
+       } else
+               cap_gain16 = pre_gain16;
+
+       /* gain to shutter */
+       while ((cap_gain16 > 32) &&
+                       (cap_shutter < ((int)((cap_VTS - 4) / 2)))) {
+               cap_gain16 = cap_gain16 / 2;
+               cap_shutter = cap_shutter * 2;
+       }
+       /* write capture gain */
+       ov5647_set_gain16(cap_gain16);
+
+       /* write capture shutter */
+       if (cap_shutter > (cap_VTS - 4)) {
+               cap_VTS = cap_shutter + 4;
+               ov5647_set_VTS(cap_VTS);
+       }
+       ov5647_set_shutter(cap_shutter);
+
+err:
+       return retval;
+}
+
+/* if sensor changes inside scaling or subsampling
+ * change mode directly
+ * */
+static int ov5647_change_mode_direct(enum ov5647_frame_rate frame_rate,
+                               enum ov5647_mode mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 ArySize = 0;
+       int retval = 0;
+
+       /* check if the input mode and frame rate is valid */
+       pModeSetting =
+               ov5647_mode_info_data[frame_rate][mode].init_data_ptr;
+       ArySize =
+               ov5647_mode_info_data[frame_rate][mode].init_data_size;
+
+       ov5647_data.pix.width =
+               ov5647_mode_info_data[frame_rate][mode].width;
+       ov5647_data.pix.height =
+               ov5647_mode_info_data[frame_rate][mode].height;
+
+       if (ov5647_data.pix.width == 0 || ov5647_data.pix.height == 0 ||
+               pModeSetting == NULL || ArySize == 0)
+               return -EINVAL;
+
+       /* turn off AE/AG */
+       ov5647_turn_on_AE_AG(0);
+
+       ov5647_stream_off();
+
+       /* Write capture setting */
+       retval = ov5647_download_firmware(pModeSetting, ArySize);
+       if (retval < 0)
+               goto err;
+
+       ov5647_turn_on_AE_AG(1);
+
+err:
+       return retval;
+}
+
+static int ov5647_init_mode(enum ov5647_frame_rate frame_rate,
+                           enum ov5647_mode mode, enum ov5647_mode orig_mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 ArySize = 0;
+       int retval = 0;
+       u32 msec_wait4stable = 0;
+       enum ov5647_downsize_mode dn_mode, orig_dn_mode;
+
+       if ((mode > ov5647_mode_MAX || mode < ov5647_mode_MIN)
+               && (mode != ov5647_mode_INIT)) {
+               pr_err("Wrong ov5647 mode detected!\n");
+               return -1;
+       }
+
+       dn_mode = ov5647_mode_info_data[frame_rate][mode].dn_mode;
+       orig_dn_mode = ov5647_mode_info_data[frame_rate][orig_mode].dn_mode;
+       if (mode == ov5647_mode_INIT) {
+               ov5647_soft_reset();
+               pModeSetting = ov5647_init_setting;
+               ArySize = ARRAY_SIZE(ov5647_init_setting);
+               retval = ov5647_download_firmware(pModeSetting, ArySize);
+               if (retval < 0)
+                       goto err;
+               pModeSetting = ov5647_setting_60fps_VGA_640_480;
+               ArySize = ARRAY_SIZE(ov5647_setting_60fps_VGA_640_480);
+               retval = ov5647_download_firmware(pModeSetting, ArySize);
+
+               ov5647_data.pix.width = 640;
+               ov5647_data.pix.height = 480;
+       } else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
+                       (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
+               /* change between subsampling and scaling
+                * go through exposure calucation */
+               retval = ov5647_change_mode_exposure_calc(frame_rate, mode);
+       } else {
+               /* change inside subsampling or scaling
+                * download firmware directly */
+               retval = ov5647_change_mode_direct(frame_rate, mode);
+       }
+
+       if (retval < 0)
+               goto err;
+
+       ov5647_set_AE_target(AE_Target);
+       ov5647_get_light_freq();
+       ov5647_set_bandingfilter();
+       ov5647_set_virtual_channel(ov5647_data.csi);
+
+       /* add delay to wait for sensor stable */
+       if (mode == ov5647_mode_QSXGA_2592_1944) {
+               /* dump the first two frames: 1/7.5*2
+                * the frame rate of QSXGA is 7.5fps */
+               msec_wait4stable = 267;
+       } else if (frame_rate == ov5647_15_fps) {
+               /* dump the first nine frames: 1/15*9 */
+               msec_wait4stable = 600;
+       } else if (frame_rate == ov5647_30_fps) {
+               /* dump the first nine frames: 1/30*9 */
+               msec_wait4stable = 300;
+       }
+       msleep(msec_wait4stable);
+
+err:
+       return retval;
+}
+
+/*!
+ * ov5647_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ov5647_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5647 *sensor = to_ov5647(client);
+
+       if (on && !sensor->on) {
+               if (io_regulator)
+                       if (regulator_enable(io_regulator) != 0)
+                               return -EIO;
+               if (core_regulator)
+                       if (regulator_enable(core_regulator) != 0)
+                               return -EIO;
+               if (gpo_regulator)
+                       if (regulator_enable(gpo_regulator) != 0)
+                               return -EIO;
+               if (analog_regulator)
+                       if (regulator_enable(analog_regulator) != 0)
+                               return -EIO;
+       } else if (!on && sensor->on) {
+               if (analog_regulator)
+                       regulator_disable(analog_regulator);
+               if (core_regulator)
+                       regulator_disable(core_regulator);
+               if (io_regulator)
+                       regulator_disable(io_regulator);
+               if (gpo_regulator)
+                       regulator_disable(gpo_regulator);
+       }
+
+       sensor->on = on;
+
+       return 0;
+}
+
+/*!
+ * ov5647_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ov5647_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5647 *sensor = to_ov5647(client);
+       struct v4l2_captureparm *cparm = &a->parm.capture;
+       int ret = 0;
+
+       switch (a->type) {
+       /* This is the only case currently handled. */
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               memset(a, 0, sizeof(*a));
+               a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               cparm->capability = sensor->streamcap.capability;
+               cparm->timeperframe = sensor->streamcap.timeperframe;
+               cparm->capturemode = sensor->streamcap.capturemode;
+               ret = 0;
+               break;
+
+       /* These are all the possible cases. */
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_VBI_OUTPUT:
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+               ret = -EINVAL;
+               break;
+
+       default:
+               pr_debug("   type is unknown - %d\n", a->type);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+/*!
+ * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible.  If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ov5647_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5647 *sensor = to_ov5647(client);
+       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+       u32 tgt_fps;    /* target frames per secound */
+       enum ov5647_frame_rate frame_rate;
+       enum ov5647_mode orig_mode;
+       int ret = 0;
+
+       /* Make sure power on */
+       ov5647_power_down(0);
+
+       switch (a->type) {
+       /* This is the only case currently handled. */
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               /* Check that the new frame rate is allowed. */
+               if ((timeperframe->numerator == 0) ||
+                   (timeperframe->denominator == 0)) {
+                       timeperframe->denominator = DEFAULT_FPS;
+                       timeperframe->numerator = 1;
+               }
+
+               tgt_fps = timeperframe->denominator /
+                         timeperframe->numerator;
+
+               if (tgt_fps > MAX_FPS) {
+                       timeperframe->denominator = MAX_FPS;
+                       timeperframe->numerator = 1;
+               } else if (tgt_fps < MIN_FPS) {
+                       timeperframe->denominator = MIN_FPS;
+                       timeperframe->numerator = 1;
+               }
+
+               /* Actual frame rate we use */
+               tgt_fps = timeperframe->denominator /
+                         timeperframe->numerator;
+
+               if (tgt_fps == 15)
+                       frame_rate = ov5647_15_fps;
+               else if (tgt_fps == 30)
+                       frame_rate = ov5647_30_fps;
+               else {
+                       pr_err(" The camera frame rate is not supported!\n");
+                       return -EINVAL;
+               }
+
+               orig_mode = sensor->streamcap.capturemode;
+               ret = ov5647_init_mode(frame_rate,
+                               (u32)a->parm.capture.capturemode, orig_mode);
+               if (ret < 0)
+                       return ret;
+
+               sensor->streamcap.timeperframe = *timeperframe;
+               sensor->streamcap.capturemode =
+                               (u32)a->parm.capture.capturemode;
+
+               break;
+
+       /* These are all the possible cases. */
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_VBI_OUTPUT:
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+               pr_debug("type is not " \
+                       "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+                       a->type);
+               ret = -EINVAL;
+               break;
+
+       default:
+               pr_debug("type is unknown - %d\n", a->type);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int ov5647_set_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *format)
+{
+       struct v4l2_mbus_framefmt *mf = &format->format;
+       const struct ov5647_datafmt *fmt = ov5647_find_datafmt(mf->code);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5647 *sensor = to_ov5647(client);
+
+       if (!fmt) {
+               mf->code        = ov5647_colour_fmts[0].code;
+               mf->colorspace  = ov5647_colour_fmts[0].colorspace;
+       }
+
+       mf->field       = V4L2_FIELD_NONE;
+
+       if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+               return 0;
+
+       sensor->fmt = fmt;
+
+       return 0;
+}
+
+static int ov5647_get_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *format)
+{
+       struct v4l2_mbus_framefmt *mf = &format->format;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5647 *sensor = to_ov5647(client);
+       const struct ov5647_datafmt *fmt = sensor->fmt;
+
+       if (format->pad)
+               return -EINVAL;
+
+       mf->code        = fmt->code;
+       mf->colorspace  = fmt->colorspace;
+       mf->field       = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static int ov5647_enum_mbus_code(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_mbus_code_enum *code)
+{
+       if (code->pad || code->index >= ARRAY_SIZE(ov5647_colour_fmts))
+               return -EINVAL;
+
+       code->code = ov5647_colour_fmts[code->index].code;
+       return 0;
+}
+
+/*!
+ * ov5647_enum_framesizes - V4L2 sensor interface handler for
+ *                        VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5647_enum_framesizes(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_pad_config *cfg,
+                              struct v4l2_subdev_frame_size_enum *fse)
+{
+       if (fse->index > ov5647_mode_MAX)
+               return -EINVAL;
+
+       fse->max_width =
+                       max(ov5647_mode_info_data[0][fse->index].width,
+                           ov5647_mode_info_data[1][fse->index].width);
+       fse->min_width = fse->max_width;
+       fse->max_height =
+                       max(ov5647_mode_info_data[0][fse->index].height,
+                           ov5647_mode_info_data[1][fse->index].height);
+       fse->min_height = fse->max_height;
+       return 0;
+}
+
+/*!
+ * ov5647_enum_frameintervals - V4L2 sensor interface handler for
+ *                            VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5647_enum_frameintervals(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_frame_interval_enum *fie)
+{
+       int i, j, count;
+
+       if (fie->index < 0 || fie->index > ov5647_mode_MAX)
+               return -EINVAL;
+
+       if (fie->width == 0 || fie->height == 0 ||
+           fie->code == 0) {
+               pr_warning("Please assign pixel format, width and height.\n");
+               return -EINVAL;
+       }
+
+       fie->interval.numerator = 1;
+
+       count = 0;
+       for (i = 0; i < ARRAY_SIZE(ov5647_mode_info_data); i++) {
+               for (j = 0; j < (ov5647_mode_MAX + 1); j++) {
+                       if (fie->width == ov5647_mode_info_data[i][j].width
+                        && fie->height == ov5647_mode_info_data[i][j].height
+                        && ov5647_mode_info_data[i][j].init_data_ptr != NULL) {
+                               count++;
+                       }
+                       if (fie->index == (count - 1)) {
+                               fie->interval.denominator =
+                                               ov5647_framerates[i];
+                               return 0;
+                       }
+               }
+       }
+
+       return -EINVAL;
+}
+
+/*!
+ * dev_init - V4L2 sensor init
+ * @s: pointer to standard V4L2 device structure
+ *
+ */
+static int init_device(void)
+{
+       u32 tgt_xclk;   /* target xclk */
+       u32 tgt_fps;    /* target frames per secound */
+       enum ov5647_frame_rate frame_rate;
+       int ret;
+
+       ov5647_data.on = true;
+
+       /* mclk */
+       tgt_xclk = ov5647_data.mclk;
+       tgt_xclk = min(tgt_xclk, (u32)OV5647_XCLK_MAX);
+       tgt_xclk = max(tgt_xclk, (u32)OV5647_XCLK_MIN);
+       ov5647_data.mclk = tgt_xclk;
+
+       pr_debug("   Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+
+       /* Default camera frame rate is set in probe */
+       tgt_fps = ov5647_data.streamcap.timeperframe.denominator /
+                 ov5647_data.streamcap.timeperframe.numerator;
+
+       if (tgt_fps == 15)
+               frame_rate = ov5647_15_fps;
+       else if (tgt_fps == 30)
+               frame_rate = ov5647_30_fps;
+       else
+               return -EINVAL; /* Only support 15fps or 30fps now. */
+
+       ret = ov5647_init_mode(frame_rate, ov5647_mode_INIT, ov5647_mode_INIT);
+
+       ov5647_update_otp();
+       return ret;
+}
+
+static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       if (enable)
+               ov5647_stream_on();
+       else
+               ov5647_stream_off();
+       return 0;
+}
+
+static struct v4l2_subdev_video_ops ov5647_subdev_video_ops = {
+       .g_parm = ov5647_g_parm,
+       .s_parm = ov5647_s_parm,
+       .s_stream = ov5647_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops ov5647_subdev_pad_ops = {
+       .enum_frame_size       = ov5647_enum_framesizes,
+       .enum_frame_interval   = ov5647_enum_frameintervals,
+       .enum_mbus_code        = ov5647_enum_mbus_code,
+       .set_fmt               = ov5647_set_fmt,
+       .get_fmt               = ov5647_get_fmt,
+};
+
+static struct v4l2_subdev_core_ops ov5647_subdev_core_ops = {
+       .s_power        = ov5647_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register     = ov5647_get_register,
+       .s_register     = ov5647_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5647_subdev_ops = {
+       .core   = &ov5647_subdev_core_ops,
+       .video  = &ov5647_subdev_video_ops,
+       .pad    = &ov5647_subdev_pad_ops,
+};
+
+
+/*!
+ * ov5647 I2C probe function
+ *
+ * @param adapter            struct i2c_adapter *
+ * @return  Error code indicating success or failure
+ */
+static int ov5647_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct pinctrl *pinctrl;
+       struct device *dev = &client->dev;
+       int retval;
+       u8 chip_id_high, chip_id_low;
+
+       /* ov5647 pinctrl */
+       pinctrl = devm_pinctrl_get_select_default(dev);
+       if (IS_ERR(pinctrl)) {
+               dev_warn(dev, "no  pin available\n");
+       }
+
+
+       /* request power down pin */
+       pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+       if (!gpio_is_valid(pwn_gpio)) {
+               dev_warn(dev, "no sensor pwdn pin available\n");
+               pwn_gpio = -1;
+       } else {
+               retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+                                               "ov5647_mipi_pwdn");
+               if (retval < 0) {
+                       dev_warn(dev, "Failed to set power pin\n");
+                       return retval;
+               }
+       }
+
+       /* request reset pin */
+       rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+       if (!gpio_is_valid(rst_gpio)) {
+               dev_warn(dev, "no sensor reset pin available\n");
+               rst_gpio = -1;
+       } else {
+               retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+                                               "ov5647_mipi_reset");
+               if (retval < 0) {
+                       dev_warn(dev, "Failed to set reset pin\n");
+                       return retval;
+               }
+       }
+
+       /* Set initial values for the sensor struct. */
+       memset(&ov5647_data, 0, sizeof(ov5647_data));
+       ov5647_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+       if (IS_ERR(ov5647_data.sensor_clk)) {
+               /* assuming clock enabled by default */
+               ov5647_data.sensor_clk = NULL;
+               dev_err(dev, "clock-frequency missing or invalid\n");
+               return PTR_ERR(ov5647_data.sensor_clk);
+       }
+
+       retval = of_property_read_u32(dev->of_node, "mclk",
+                                       &(ov5647_data.mclk));
+       if (retval) {
+               dev_err(dev, "mclk missing or invalid\n");
+               return retval;
+       }
+
+       retval = of_property_read_u32(dev->of_node, "mclk_source",
+                                       (u32 *) &(ov5647_data.mclk_source));
+       if (retval) {
+               dev_err(dev, "mclk_source missing or invalid\n");
+               return retval;
+       }
+
+       retval = of_property_read_u32(dev->of_node, "csi_id",
+                                       &(ov5647_data.csi));
+       if (retval) {
+               dev_err(dev, "csi id missing or invalid\n");
+               return retval;
+       }
+
+       clk_prepare_enable(ov5647_data.sensor_clk);
+
+       ov5647_data.io_init = ov5647_reset;
+       ov5647_data.i2c_client = client;
+       ov5647_data.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
+       ov5647_data.pix.width = 640;
+       ov5647_data.pix.height = 480;
+       ov5647_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+                                          V4L2_CAP_TIMEPERFRAME;
+       ov5647_data.streamcap.capturemode = 0;
+       ov5647_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+       ov5647_data.streamcap.timeperframe.numerator = 1;
+
+       ov5647_regulator_enable(&client->dev);
+
+       ov5647_reset();
+
+       ov5647_power_down(0);
+
+       retval = ov5647_read_reg(OV5647_CHIP_ID_HIGH_BYTE, &chip_id_high);
+       if (retval < 0 || chip_id_high != 0x56) {
+               pr_warning("camera ov5647_mipi is not found\n");
+               clk_disable_unprepare(ov5647_data.sensor_clk);
+               return -ENODEV;
+       }
+       retval = ov5647_read_reg(OV5647_CHIP_ID_LOW_BYTE, &chip_id_low);
+       if (retval < 0 || chip_id_low != 0x47) {
+               pr_warning("camera ov5647_mipi is not found\n");
+               clk_disable_unprepare(ov5647_data.sensor_clk);
+               return -ENODEV;
+       }
+
+       retval = init_device();
+       if (retval < 0) {
+               clk_disable_unprepare(ov5647_data.sensor_clk);
+               pr_warning("camera ov5647 init failed\n");
+               ov5647_power_down(1);
+               return retval;
+       }
+
+       v4l2_i2c_subdev_init(&ov5647_data.subdev, client, &ov5647_subdev_ops);
+
+       ov5647_data.subdev.grp_id = 678;
+       retval = v4l2_async_register_subdev(&ov5647_data.subdev);
+       if (retval < 0)
+               dev_err(&client->dev,
+                                       "%s--Async register failed, ret=%d\n", __func__, retval);
+
+       ov5647_stream_off();
+       pr_info("camera ov5647_mipi is found\n");
+       return retval;
+}
+
+/*!
+ * ov5647 I2C detach function
+ *
+ * @param client            struct i2c_client *
+ * @return  Error code indicating success or failure
+ */
+static int ov5647_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+       v4l2_async_unregister_subdev(sd);
+
+       clk_disable_unprepare(ov5647_data.sensor_clk);
+
+       ov5647_power_down(1);
+
+       if (gpo_regulator)
+               regulator_disable(gpo_regulator);
+
+       if (analog_regulator)
+               regulator_disable(analog_regulator);
+
+       if (core_regulator)
+               regulator_disable(core_regulator);
+
+       if (io_regulator)
+               regulator_disable(io_regulator);
+
+       return 0;
+}
+
+module_i2c_driver(ov5647_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5647 MIPI Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/subdev/Kconfig b/drivers/media/platform/mxc/subdev/Kconfig
deleted file mode 100644 (file)
index b8e0ebb..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-if VIDEO_MXC_CAPTURE
-
-config VIDEO_MXC_CSI_CAMERA
-       tristate "CSI camera support"
-       depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
-       ---help---
-         This is the video4linux2 capture driver based on CSI module.
-
-config MXC_CAMERA_OV5640
-        tristate "OmniVision ov5640 camera support"
-        depends on VIDEO_MXC_CAPTURE && I2C
-        ---help---
-          If you plan to use the ov5640 Camera with your MXC system, say Y here.
-
-config MXC_VADC
-       tristate "mxc VADC support"
-       depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
-       ---help---
-               If you plan to use the VADC with your MXC system, say Y here.
-
-config MXC_MIPI_CSI
-       tristate "mxc mipi csi driver"
-       depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
-       ---help---
-         This is a V4L2 driver for i.MX7D SoC MIPI-CSI2 receiver devices.
-
-config MXC_CAMERA_OV5640_MIPI
-       tristate "OmniVision ov5640 camera support using mipi"
-       depends on MXC_MIPI_CSI && I2C
-       ---help---
-         If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here.
-
-config MXC_CAMERA_OV5647_MIPI
-       tristate "OmniVision ov5647 camera support using mipi"
-       depends on MXC_MIPI_CSI && I2C
-       ---help---
-         If you plan to use the ov5647 Camera with mipi interface in your MXC system, say Y here.
-endif
diff --git a/drivers/media/platform/mxc/subdev/Makefile b/drivers/media/platform/mxc/subdev/Makefile
deleted file mode 100644 (file)
index 25b0d64..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#Makefile for mxc csi driver
-
-obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA)     += mx6s_capture.o
-obj-$(CONFIG_MXC_VADC) += mxc_vadc.o
-obj-$(CONFIG_MXC_MIPI_CSI) += mxc_mipi_csi.o
-
-ov5640_camera-objs := ov5640.o
-obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera.o
-
-ov5640_camera_mipi-objs := ov5640_mipi.o
-obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi.o
-
-ov5647_camera_mipi-objs := ov5647_mipi.o
-obj-$(CONFIG_MXC_CAMERA_OV5647_MIPI) += ov5647_camera_mipi.o
diff --git a/drivers/media/platform/mxc/subdev/mx6s_capture.c b/drivers/media/platform/mxc/subdev/mx6s_capture.c
deleted file mode 100644 (file)
index 63eb549..0000000
+++ /dev/null
@@ -1,1970 +0,0 @@
-/*
- * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/*!
- * @file mx6s_csi.c
- *
- * @brief mx6sx CMOS Sensor interface functions
- *
- * @ingroup CSI
- */
-#include <asm/dma.h>
-#include <linux/busfreq-imx.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/gcd.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/math64.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/media-bus-format.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-of.h>
-#include <media/videobuf2-core.h>
-#include <media/videobuf2-dma-contig.h>
-
-#define MX6S_CAM_DRV_NAME "mx6s-csi"
-#define MX6S_CAM_VERSION "0.0.1"
-#define MX6S_CAM_DRIVER_DESCRIPTION "i.MX6S_CSI"
-
-#define MAX_VIDEO_MEM 64
-
-/* reset values */
-#define CSICR1_RESET_VAL       0x40000800
-#define CSICR2_RESET_VAL       0x0
-#define CSICR3_RESET_VAL       0x0
-
-/* csi control reg 1 */
-#define BIT_SWAP16_EN          (0x1 << 31)
-#define BIT_EXT_VSYNC          (0x1 << 30)
-#define BIT_EOF_INT_EN         (0x1 << 29)
-#define BIT_PRP_IF_EN          (0x1 << 28)
-#define BIT_CCIR_MODE          (0x1 << 27)
-#define BIT_COF_INT_EN         (0x1 << 26)
-#define BIT_SF_OR_INTEN                (0x1 << 25)
-#define BIT_RF_OR_INTEN                (0x1 << 24)
-#define BIT_SFF_DMA_DONE_INTEN  (0x1 << 22)
-#define BIT_STATFF_INTEN       (0x1 << 21)
-#define BIT_FB2_DMA_DONE_INTEN  (0x1 << 20)
-#define BIT_FB1_DMA_DONE_INTEN  (0x1 << 19)
-#define BIT_RXFF_INTEN         (0x1 << 18)
-#define BIT_SOF_POL            (0x1 << 17)
-#define BIT_SOF_INTEN          (0x1 << 16)
-#define BIT_MCLKDIV            (0xF << 12)
-#define BIT_HSYNC_POL          (0x1 << 11)
-#define BIT_CCIR_EN            (0x1 << 10)
-#define BIT_MCLKEN             (0x1 << 9)
-#define BIT_FCC                        (0x1 << 8)
-#define BIT_PACK_DIR           (0x1 << 7)
-#define BIT_CLR_STATFIFO       (0x1 << 6)
-#define BIT_CLR_RXFIFO         (0x1 << 5)
-#define BIT_GCLK_MODE          (0x1 << 4)
-#define BIT_INV_DATA           (0x1 << 3)
-#define BIT_INV_PCLK           (0x1 << 2)
-#define BIT_REDGE              (0x1 << 1)
-#define BIT_PIXEL_BIT          (0x1 << 0)
-
-#define SHIFT_MCLKDIV          12
-
-/* control reg 3 */
-#define BIT_FRMCNT             (0xFFFF << 16)
-#define BIT_FRMCNT_RST         (0x1 << 15)
-#define BIT_DMA_REFLASH_RFF    (0x1 << 14)
-#define BIT_DMA_REFLASH_SFF    (0x1 << 13)
-#define BIT_DMA_REQ_EN_RFF     (0x1 << 12)
-#define BIT_DMA_REQ_EN_SFF     (0x1 << 11)
-#define BIT_STATFF_LEVEL       (0x7 << 8)
-#define BIT_HRESP_ERR_EN       (0x1 << 7)
-#define BIT_RXFF_LEVEL         (0x7 << 4)
-#define BIT_TWO_8BIT_SENSOR    (0x1 << 3)
-#define BIT_ZERO_PACK_EN       (0x1 << 2)
-#define BIT_ECC_INT_EN         (0x1 << 1)
-#define BIT_ECC_AUTO_EN                (0x1 << 0)
-
-#define SHIFT_FRMCNT           16
-#define SHIFT_RXFIFO_LEVEL     4
-
-/* csi status reg */
-#define BIT_ADDR_CH_ERR_INT (0x1 << 28)
-#define BIT_FIELD0_INT      (0x1 << 27)
-#define BIT_FIELD1_INT      (0x1 << 26)
-#define BIT_SFF_OR_INT         (0x1 << 25)
-#define BIT_RFF_OR_INT         (0x1 << 24)
-#define BIT_DMA_TSF_DONE_SFF   (0x1 << 22)
-#define BIT_STATFF_INT         (0x1 << 21)
-#define BIT_DMA_TSF_DONE_FB2   (0x1 << 20)
-#define BIT_DMA_TSF_DONE_FB1   (0x1 << 19)
-#define BIT_RXFF_INT           (0x1 << 18)
-#define BIT_EOF_INT            (0x1 << 17)
-#define BIT_SOF_INT            (0x1 << 16)
-#define BIT_F2_INT             (0x1 << 15)
-#define BIT_F1_INT             (0x1 << 14)
-#define BIT_COF_INT            (0x1 << 13)
-#define BIT_HRESP_ERR_INT      (0x1 << 7)
-#define BIT_ECC_INT            (0x1 << 1)
-#define BIT_DRDY               (0x1 << 0)
-
-/* csi control reg 18 */
-#define BIT_CSI_ENABLE                 (0x1 << 31)
-#define BIT_MIPI_DATA_FORMAT_RAW8              (0x2a << 25)
-#define BIT_MIPI_DATA_FORMAT_RAW10             (0x2b << 25)
-#define BIT_MIPI_DATA_FORMAT_YUV422_8B (0x1e << 25)
-#define BIT_MIPI_DATA_FORMAT_MASK      (0x3F << 25)
-#define BIT_MIPI_DATA_FORMAT_OFFSET    25
-#define BIT_DATA_FROM_MIPI             (0x1 << 22)
-#define BIT_MIPI_YU_SWAP               (0x1 << 21)
-#define BIT_MIPI_DOUBLE_CMPNT  (0x1 << 20)
-#define BIT_BASEADDR_CHG_ERR_EN        (0x1 << 9)
-#define BIT_BASEADDR_SWITCH_SEL        (0x1 << 5)
-#define BIT_BASEADDR_SWITCH_EN (0x1 << 4)
-#define BIT_PARALLEL24_EN              (0x1 << 3)
-#define BIT_DEINTERLACE_EN             (0x1 << 2)
-#define BIT_TVDECODER_IN_EN            (0x1 << 1)
-#define BIT_NTSC_EN                            (0x1 << 0)
-
-#define CSI_MCLK_VF            1
-#define CSI_MCLK_ENC           2
-#define CSI_MCLK_RAW           4
-#define CSI_MCLK_I2C           8
-
-#define CSI_CSICR1             0x0
-#define CSI_CSICR2             0x4
-#define CSI_CSICR3             0x8
-#define CSI_STATFIFO           0xC
-#define CSI_CSIRXFIFO          0x10
-#define CSI_CSIRXCNT           0x14
-#define CSI_CSISR              0x18
-
-#define CSI_CSIDBG             0x1C
-#define CSI_CSIDMASA_STATFIFO  0x20
-#define CSI_CSIDMATS_STATFIFO  0x24
-#define CSI_CSIDMASA_FB1       0x28
-#define CSI_CSIDMASA_FB2       0x2C
-#define CSI_CSIFBUF_PARA       0x30
-#define CSI_CSIIMAG_PARA       0x34
-
-#define CSI_CSICR18            0x48
-#define CSI_CSICR19            0x4c
-
-#define NUM_FORMATS ARRAY_SIZE(formats)
-#define MX6SX_MAX_SENSORS    1
-
-struct csi_signal_cfg_t {
-       unsigned data_width:3;
-       unsigned clk_mode:2;
-       unsigned ext_vsync:1;
-       unsigned Vsync_pol:1;
-       unsigned Hsync_pol:1;
-       unsigned pixclk_pol:1;
-       unsigned data_pol:1;
-       unsigned sens_clksrc:1;
-};
-
-struct csi_config_t {
-       /* control reg 1 */
-       unsigned int swap16_en:1;
-       unsigned int ext_vsync:1;
-       unsigned int eof_int_en:1;
-       unsigned int prp_if_en:1;
-       unsigned int ccir_mode:1;
-       unsigned int cof_int_en:1;
-       unsigned int sf_or_inten:1;
-       unsigned int rf_or_inten:1;
-       unsigned int sff_dma_done_inten:1;
-       unsigned int statff_inten:1;
-       unsigned int fb2_dma_done_inten:1;
-       unsigned int fb1_dma_done_inten:1;
-       unsigned int rxff_inten:1;
-       unsigned int sof_pol:1;
-       unsigned int sof_inten:1;
-       unsigned int mclkdiv:4;
-       unsigned int hsync_pol:1;
-       unsigned int ccir_en:1;
-       unsigned int mclken:1;
-       unsigned int fcc:1;
-       unsigned int pack_dir:1;
-       unsigned int gclk_mode:1;
-       unsigned int inv_data:1;
-       unsigned int inv_pclk:1;
-       unsigned int redge:1;
-       unsigned int pixel_bit:1;
-
-       /* control reg 3 */
-       unsigned int frmcnt:16;
-       unsigned int frame_reset:1;
-       unsigned int dma_reflash_rff:1;
-       unsigned int dma_reflash_sff:1;
-       unsigned int dma_req_en_rff:1;
-       unsigned int dma_req_en_sff:1;
-       unsigned int statff_level:3;
-       unsigned int hresp_err_en:1;
-       unsigned int rxff_level:3;
-       unsigned int two_8bit_sensor:1;
-       unsigned int zero_pack_en:1;
-       unsigned int ecc_int_en:1;
-       unsigned int ecc_auto_en:1;
-       /* fifo counter */
-       unsigned int rxcnt;
-};
-
-/*
- * Basic structures
- */
-struct mx6s_fmt {
-       char  name[32];
-       u32   fourcc;           /* v4l2 format id */
-       u32   pixelformat;
-       u32   mbus_code;
-       int   bpp;
-};
-
-static struct mx6s_fmt formats[] = {
-       {
-               .name           = "UYVY-16",
-               .fourcc         = V4L2_PIX_FMT_UYVY,
-               .pixelformat    = V4L2_PIX_FMT_UYVY,
-               .mbus_code      = MEDIA_BUS_FMT_UYVY8_2X8,
-               .bpp            = 2,
-       }, {
-               .name           = "YUYV-16",
-               .fourcc         = V4L2_PIX_FMT_YUYV,
-               .pixelformat    = V4L2_PIX_FMT_YUYV,
-               .mbus_code      = MEDIA_BUS_FMT_YUYV8_2X8,
-               .bpp            = 2,
-       }, {
-               .name           = "YUV32 (X-Y-U-V)",
-               .fourcc         = V4L2_PIX_FMT_YUV32,
-               .pixelformat    = V4L2_PIX_FMT_YUV32,
-               .mbus_code      = MEDIA_BUS_FMT_AYUV8_1X32,
-               .bpp            = 4,
-       }, {
-               .name           = "RAWRGB8 (SBGGR8)",
-               .fourcc         = V4L2_PIX_FMT_SBGGR8,
-               .pixelformat    = V4L2_PIX_FMT_SBGGR8,
-               .mbus_code      = MEDIA_BUS_FMT_SBGGR8_1X8,
-               .bpp            = 1,
-       }
-};
-
-struct mx6s_buf_internal {
-       struct list_head        queue;
-       int                                     bufnum;
-       bool                            discard;
-};
-
-/* buffer for one video frame */
-struct mx6s_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct vb2_v4l2_buffer                  vb;
-       struct mx6s_buf_internal        internal;
-};
-
-struct mx6s_csi_mux {
-       struct regmap *gpr;
-       u8 req_gpr;
-       u8 req_bit;
-};
-
-struct mx6s_csi_dev {
-       struct device           *dev;
-       struct video_device *vdev;
-       struct v4l2_subdev      *sd;
-       struct v4l2_device      v4l2_dev;
-
-       struct vb2_queue                        vb2_vidq;
-       struct v4l2_ctrl_handler        ctrl_handler;
-
-       struct mutex            lock;
-       spinlock_t                      slock;
-
-       /* clock */
-       struct clk      *clk_disp_axi;
-       struct clk      *clk_disp_dcic;
-       struct clk      *clk_csi_mclk;
-
-       void __iomem *regbase;
-       int irq;
-
-       u32      type;
-       u32 bytesperline;
-       v4l2_std_id std;
-       struct mx6s_fmt         *fmt;
-       struct v4l2_pix_format pix;
-       u32 mbus_code;
-
-       unsigned int frame_count;
-
-       struct list_head        capture;
-       struct list_head        active_bufs;
-       struct list_head        discard;
-
-       void                                            *discard_buffer;
-       dma_addr_t                                      discard_buffer_dma;
-       size_t                                          discard_size;
-       struct mx6s_buf_internal        buf_discard[2];
-
-       struct v4l2_async_subdev        asd;
-       struct v4l2_async_notifier      subdev_notifier;
-       struct v4l2_async_subdev        *async_subdevs[2];
-
-       bool csi_mux_mipi;
-       const bool *rx_fifo_rst;
-       struct mx6s_csi_mux csi_mux;
-};
-
-static const struct of_device_id mx6s_csi_dt_ids[];
-
-static inline int csi_read(struct mx6s_csi_dev *csi, unsigned int offset)
-{
-       return __raw_readl(csi->regbase + offset);
-}
-static inline void csi_write(struct mx6s_csi_dev *csi, unsigned int value,
-                            unsigned int offset)
-{
-       __raw_writel(value, csi->regbase + offset);
-}
-
-static inline struct mx6s_csi_dev
-                               *notifier_to_mx6s_dev(struct v4l2_async_notifier *n)
-{
-       return container_of(n, struct mx6s_csi_dev, subdev_notifier);
-}
-
-struct mx6s_fmt *format_by_fourcc(int fourcc)
-{
-       int i;
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (formats[i].pixelformat == fourcc)
-                       return formats + i;
-       }
-
-       pr_err("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
-       return NULL;
-}
-
-struct mx6s_fmt *format_by_mbus(u32 code)
-{
-       int i;
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (formats[i].mbus_code == code)
-                       return formats + i;
-       }
-
-       pr_err("unknown mbus:0x%x\n", code);
-       return NULL;
-}
-
-static struct mx6s_buffer *mx6s_ibuf_to_buf(struct mx6s_buf_internal *int_buf)
-{
-       return container_of(int_buf, struct mx6s_buffer, internal);
-}
-
-void csi_clk_enable(struct mx6s_csi_dev *csi_dev)
-{
-       clk_prepare_enable(csi_dev->clk_disp_axi);
-       clk_prepare_enable(csi_dev->clk_disp_dcic);
-       clk_prepare_enable(csi_dev->clk_csi_mclk);
-}
-
-void csi_clk_disable(struct mx6s_csi_dev *csi_dev)
-{
-       clk_disable_unprepare(csi_dev->clk_csi_mclk);
-       clk_disable_unprepare(csi_dev->clk_disp_dcic);
-       clk_disable_unprepare(csi_dev->clk_disp_axi);
-}
-
-static void csihw_reset(struct mx6s_csi_dev *csi_dev)
-{
-       __raw_writel(__raw_readl(csi_dev->regbase + CSI_CSICR3)
-                       | BIT_FRMCNT_RST,
-                       csi_dev->regbase + CSI_CSICR3);
-
-       __raw_writel(CSICR1_RESET_VAL, csi_dev->regbase + CSI_CSICR1);
-       __raw_writel(CSICR2_RESET_VAL, csi_dev->regbase + CSI_CSICR2);
-       __raw_writel(CSICR3_RESET_VAL, csi_dev->regbase + CSI_CSICR3);
-}
-
-static void csisw_reset(struct mx6s_csi_dev *csi_dev)
-{
-       int cr1, cr3, cr18, isr;
-
-       /* Disable csi  */
-       cr18 = csi_read(csi_dev, CSI_CSICR18);
-       cr18 &= ~BIT_CSI_ENABLE;
-       csi_write(csi_dev, cr18, CSI_CSICR18);
-
-       /* Clear RX FIFO */
-       cr1 = csi_read(csi_dev, CSI_CSICR1);
-       csi_write(csi_dev, cr1 & ~BIT_FCC, CSI_CSICR1);
-       cr1 = csi_read(csi_dev, CSI_CSICR1);
-       csi_write(csi_dev, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1);
-
-       /* DMA reflash */
-       cr3 = csi_read(csi_dev, CSI_CSICR3);
-       cr3 |= BIT_DMA_REFLASH_RFF | BIT_FRMCNT_RST;
-       csi_write(csi_dev, cr3, CSI_CSICR3);
-
-       msleep(2);
-
-       cr1 = csi_read(csi_dev, CSI_CSICR1);
-       csi_write(csi_dev, cr1 | BIT_FCC, CSI_CSICR1);
-
-       isr = csi_read(csi_dev, CSI_CSISR);
-       csi_write(csi_dev, isr, CSI_CSISR);
-
-       /* Ensable csi  */
-       cr18 |= BIT_CSI_ENABLE;
-       csi_write(csi_dev, cr18, CSI_CSICR18);
-}
-
-/*!
- * csi_init_interface
- *    Init csi interface
- */
-static void csi_init_interface(struct mx6s_csi_dev *csi_dev)
-{
-       unsigned int val = 0;
-       unsigned int imag_para;
-
-       val |= BIT_SOF_POL;
-       val |= BIT_REDGE;
-       val |= BIT_GCLK_MODE;
-       val |= BIT_HSYNC_POL;
-       val |= BIT_FCC;
-       val |= 1 << SHIFT_MCLKDIV;
-       val |= BIT_MCLKEN;
-       __raw_writel(val, csi_dev->regbase + CSI_CSICR1);
-
-       imag_para = (640 << 16) | 960;
-       __raw_writel(imag_para, csi_dev->regbase + CSI_CSIIMAG_PARA);
-
-       val = BIT_DMA_REFLASH_RFF;
-       __raw_writel(val, csi_dev->regbase + CSI_CSICR3);
-}
-
-static void csi_enable_int(struct mx6s_csi_dev *csi_dev, int arg)
-{
-       unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
-
-       cr1 |= BIT_SOF_INTEN;
-       cr1 |= BIT_RFF_OR_INT;
-       if (arg == 1) {
-               /* still capture needs DMA intterrupt */
-               cr1 |= BIT_FB1_DMA_DONE_INTEN;
-               cr1 |= BIT_FB2_DMA_DONE_INTEN;
-       }
-       __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
-}
-
-static void csi_disable_int(struct mx6s_csi_dev *csi_dev)
-{
-       unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
-
-       cr1 &= ~BIT_SOF_INTEN;
-       cr1 &= ~BIT_RFF_OR_INT;
-       cr1 &= ~BIT_FB1_DMA_DONE_INTEN;
-       cr1 &= ~BIT_FB2_DMA_DONE_INTEN;
-       __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
-}
-
-static void csi_enable(struct mx6s_csi_dev *csi_dev, int arg)
-{
-       unsigned long cr = __raw_readl(csi_dev->regbase + CSI_CSICR18);
-
-       if (arg == 1)
-               cr |= BIT_CSI_ENABLE;
-       else
-               cr &= ~BIT_CSI_ENABLE;
-       __raw_writel(cr, csi_dev->regbase + CSI_CSICR18);
-}
-
-static void csi_buf_stride_set(struct mx6s_csi_dev *csi_dev, u32 stride)
-{
-       __raw_writel(stride, csi_dev->regbase + CSI_CSIFBUF_PARA);
-}
-
-static void csi_deinterlace_enable(struct mx6s_csi_dev *csi_dev, bool enable)
-{
-       unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
-
-       if (enable == true)
-               cr18 |= BIT_DEINTERLACE_EN;
-       else
-               cr18 &= ~BIT_DEINTERLACE_EN;
-
-       __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
-}
-
-static void csi_deinterlace_mode(struct mx6s_csi_dev *csi_dev, int mode)
-{
-       unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
-
-       if (mode == V4L2_STD_NTSC)
-               cr18 |= BIT_NTSC_EN;
-       else
-               cr18 &= ~BIT_NTSC_EN;
-
-       __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
-}
-
-static void csi_tvdec_enable(struct mx6s_csi_dev *csi_dev, bool enable)
-{
-       unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
-       unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
-
-       if (enable == true) {
-               cr18 |= (BIT_TVDECODER_IN_EN |
-                               BIT_BASEADDR_SWITCH_EN |
-                               BIT_BASEADDR_SWITCH_SEL |
-                               BIT_BASEADDR_CHG_ERR_EN);
-               cr1 |= BIT_CCIR_MODE;
-               cr1 &= ~(BIT_SOF_POL | BIT_REDGE);
-       } else {
-               cr18 &= ~(BIT_TVDECODER_IN_EN |
-                               BIT_BASEADDR_SWITCH_EN |
-                               BIT_BASEADDR_SWITCH_SEL |
-                               BIT_BASEADDR_CHG_ERR_EN);
-               cr1 &= ~BIT_CCIR_MODE;
-               cr1 |= BIT_SOF_POL | BIT_REDGE;
-       }
-
-       __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
-       __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
-}
-
-static void csi_dmareq_rff_enable(struct mx6s_csi_dev *csi_dev)
-{
-       unsigned long cr3 = __raw_readl(csi_dev->regbase + CSI_CSICR3);
-       unsigned long cr2 = __raw_readl(csi_dev->regbase + CSI_CSICR2);
-
-       /* Burst Type of DMA Transfer from RxFIFO. INCR16 */
-       cr2 |= 0xC0000000;
-
-       cr3 |= BIT_DMA_REQ_EN_RFF;
-       cr3 |= BIT_HRESP_ERR_EN;
-       cr3 &= ~BIT_RXFF_LEVEL;
-       cr3 |= 0x2 << 4;
-
-       __raw_writel(cr3, csi_dev->regbase + CSI_CSICR3);
-       __raw_writel(cr2, csi_dev->regbase + CSI_CSICR2);
-}
-
-static void csi_dmareq_rff_disable(struct mx6s_csi_dev *csi_dev)
-{
-       unsigned long cr3 = __raw_readl(csi_dev->regbase + CSI_CSICR3);
-
-       cr3 &= ~BIT_DMA_REQ_EN_RFF;
-       cr3 &= ~BIT_HRESP_ERR_EN;
-       __raw_writel(cr3, csi_dev->regbase + CSI_CSICR3);
-}
-
-static void csi_set_imagpara(struct mx6s_csi_dev *csi,
-                                       int width, int height)
-{
-       int imag_para = 0;
-       unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3);
-
-       imag_para = (width << 16) | height;
-       __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA);
-
-       /* reflash the embeded DMA controller */
-       __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3);
-}
-
-static void csi_error_recovery(struct mx6s_csi_dev *csi_dev)
-{
-       u32 cr1, cr3, cr18;
-       /* software reset */
-
-       /* Disable csi  */
-       cr18 = csi_read(csi_dev, CSI_CSICR18);
-       cr18 &= ~BIT_CSI_ENABLE;
-       csi_write(csi_dev, cr18, CSI_CSICR18);
-
-       /* Clear RX FIFO */
-       cr1 = csi_read(csi_dev, CSI_CSICR1);
-       csi_write(csi_dev, cr1 & ~BIT_FCC, CSI_CSICR1);
-       cr1 = csi_read(csi_dev, CSI_CSICR1);
-       csi_write(csi_dev, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1);
-
-       cr1 = csi_read(csi_dev, CSI_CSICR1);
-       csi_write(csi_dev, cr1 | BIT_FCC, CSI_CSICR1);
-
-       /* DMA reflash */
-       cr3 = csi_read(csi_dev, CSI_CSICR3);
-       cr3 |= BIT_DMA_REFLASH_RFF;
-       csi_write(csi_dev, cr3, CSI_CSICR3);
-
-       /* Ensable csi  */
-       cr18 |= BIT_CSI_ENABLE;
-       csi_write(csi_dev, cr18, CSI_CSICR18);
-}
-
-/*
- *  Videobuf operations
- */
-static int mx6s_videobuf_setup(struct vb2_queue *vq,
-                       unsigned int *count, unsigned int *num_planes,
-                       unsigned int sizes[], struct device *alloc_devs[])
-{
-       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
-
-       dev_dbg(csi_dev->dev, "count=%d, size=%d\n", *count, sizes[0]);
-
-       alloc_devs[0] = csi_dev->dev;
-
-       sizes[0] = csi_dev->pix.sizeimage;
-
-       pr_debug("size=%d\n", sizes[0]);
-       if (0 == *count)
-               *count = 32;
-       if (!*num_planes &&
-           sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
-               *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0];
-
-       *num_planes = 1;
-
-       return 0;
-}
-
-static int mx6s_videobuf_prepare(struct vb2_buffer *vb)
-{
-       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vb->vb2_queue);
-       int ret = 0;
-
-       dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
-               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
-
-#ifdef DEBUG
-       /*
-        * This can be useful if you want to see if we actually fill
-        * the buffer with something
-        */
-       if (vb2_plane_vaddr(vb, 0))
-               memset((void *)vb2_plane_vaddr(vb, 0),
-                      0xaa, vb2_get_plane_payload(vb, 0));
-#endif
-
-       vb2_set_plane_payload(vb, 0, csi_dev->pix.sizeimage);
-       if (vb2_plane_vaddr(vb, 0) &&
-           vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       return 0;
-
-out:
-       return ret;
-}
-
-static void mx6s_videobuf_queue(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vb->vb2_queue);
-       struct mx6s_buffer *buf = container_of(vbuf, struct mx6s_buffer, vb);
-       unsigned long flags;
-
-       dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
-               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
-
-       spin_lock_irqsave(&csi_dev->slock, flags);
-
-       list_add_tail(&buf->internal.queue, &csi_dev->capture);
-
-       spin_unlock_irqrestore(&csi_dev->slock, flags);
-}
-
-static void mx6s_update_csi_buf(struct mx6s_csi_dev *csi_dev,
-                                unsigned long phys, int bufnum)
-{
-       if (bufnum == 1)
-               csi_write(csi_dev, phys, CSI_CSIDMASA_FB2);
-       else
-               csi_write(csi_dev, phys, CSI_CSIDMASA_FB1);
-}
-
-static void mx6s_csi_init(struct mx6s_csi_dev *csi_dev)
-{
-       csi_clk_enable(csi_dev);
-       csihw_reset(csi_dev);
-       csi_init_interface(csi_dev);
-       csi_dmareq_rff_disable(csi_dev);
-}
-
-static void mx6s_csi_deinit(struct mx6s_csi_dev *csi_dev)
-{
-       csihw_reset(csi_dev);
-       csi_init_interface(csi_dev);
-       csi_dmareq_rff_disable(csi_dev);
-       csi_clk_disable(csi_dev);
-}
-
-static int mx6s_csi_enable(struct mx6s_csi_dev *csi_dev)
-{
-       struct v4l2_pix_format *pix = &csi_dev->pix;
-       unsigned long flags;
-       unsigned long val;
-       int timeout, timeout2;
-
-       csisw_reset(csi_dev);
-
-       if (pix->field == V4L2_FIELD_INTERLACED)
-               csi_tvdec_enable(csi_dev, true);
-
-       /* For mipi csi input only */
-       if (csi_dev->csi_mux_mipi == true) {
-               csi_dmareq_rff_enable(csi_dev);
-               csi_enable_int(csi_dev, 1);
-               csi_enable(csi_dev, 1);
-               return 0;
-       }
-
-       local_irq_save(flags);
-       for (timeout = 10000000; timeout > 0; timeout--) {
-               if (csi_read(csi_dev, CSI_CSISR) & BIT_SOF_INT) {
-                       val = csi_read(csi_dev, CSI_CSICR3);
-                       csi_write(csi_dev, val | BIT_DMA_REFLASH_RFF,
-                                       CSI_CSICR3);
-                       /* Wait DMA reflash done */
-                       for (timeout2 = 1000000; timeout2 > 0; timeout2--) {
-                               if (csi_read(csi_dev, CSI_CSICR3) &
-                                       BIT_DMA_REFLASH_RFF)
-                                       cpu_relax();
-                               else
-                                       break;
-                       }
-                       if (timeout2 <= 0) {
-                               pr_err("timeout when wait for reflash done.\n");
-                               local_irq_restore(flags);
-                               return -ETIME;
-                       }
-                       /* For imx6sl csi, DMA FIFO will auto start when sensor ready to work,
-                        * so DMA should enable right after FIFO reset, otherwise dma will lost data
-                        * and image will split.
-                        */
-                       csi_dmareq_rff_enable(csi_dev);
-                       csi_enable_int(csi_dev, 1);
-                       csi_enable(csi_dev, 1);
-                       break;
-               } else
-                       cpu_relax();
-       }
-       if (timeout <= 0) {
-               pr_err("timeout when wait for SOF\n");
-               local_irq_restore(flags);
-               return -ETIME;
-       }
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-static void mx6s_csi_disable(struct mx6s_csi_dev *csi_dev)
-{
-       struct v4l2_pix_format *pix = &csi_dev->pix;
-
-       csi_dmareq_rff_disable(csi_dev);
-       csi_disable_int(csi_dev);
-
-       /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */
-       csi_write(csi_dev, 0, CSI_CSIDMASA_FB1);
-       csi_write(csi_dev, 0, CSI_CSIDMASA_FB2);
-
-       csi_buf_stride_set(csi_dev, 0);
-
-       if (pix->field == V4L2_FIELD_INTERLACED) {
-               csi_deinterlace_enable(csi_dev, false);
-               csi_tvdec_enable(csi_dev, false);
-       }
-
-       csi_enable(csi_dev, 0);
-}
-
-static int mx6s_configure_csi(struct mx6s_csi_dev *csi_dev)
-{
-       struct v4l2_pix_format *pix = &csi_dev->pix;
-       u32 cr1, cr18;
-       u32 width;
-
-       if (pix->field == V4L2_FIELD_INTERLACED) {
-               csi_deinterlace_enable(csi_dev, true);
-               csi_buf_stride_set(csi_dev, csi_dev->pix.width);
-               csi_deinterlace_mode(csi_dev, csi_dev->std);
-       } else {
-               csi_deinterlace_enable(csi_dev, false);
-               csi_buf_stride_set(csi_dev, 0);
-       }
-
-       switch (csi_dev->fmt->pixelformat) {
-       case V4L2_PIX_FMT_YUV32:
-       case V4L2_PIX_FMT_SBGGR8:
-               width = pix->width;
-               break;
-       case V4L2_PIX_FMT_UYVY:
-       case V4L2_PIX_FMT_YUYV:
-               if (csi_dev->csi_mux_mipi == true)
-                       width = pix->width;
-               else
-                       /* For parallel 8-bit sensor input */
-                       width = pix->width * 2;
-               break;
-       default:
-               pr_debug("   case not supported\n");
-               return -EINVAL;
-       }
-       csi_set_imagpara(csi_dev, width, pix->height);
-
-       if (csi_dev->csi_mux_mipi == true) {
-               cr1 = csi_read(csi_dev, CSI_CSICR1);
-               cr1 &= ~BIT_GCLK_MODE;
-               csi_write(csi_dev, cr1, CSI_CSICR1);
-
-               cr18 = csi_read(csi_dev, CSI_CSICR18);
-               cr18 &= BIT_MIPI_DATA_FORMAT_MASK;
-               cr18 |= BIT_DATA_FROM_MIPI;
-
-               switch (csi_dev->fmt->pixelformat) {
-               case V4L2_PIX_FMT_UYVY:
-               case V4L2_PIX_FMT_YUYV:
-                       cr18 |= BIT_MIPI_DATA_FORMAT_YUV422_8B;
-                       break;
-               case V4L2_PIX_FMT_SBGGR8:
-                       cr18 |= BIT_MIPI_DATA_FORMAT_RAW8;
-                       break;
-               default:
-                       pr_debug("   fmt not supported\n");
-                       return -EINVAL;
-               }
-
-               csi_write(csi_dev, cr18, CSI_CSICR18);
-       }
-       return 0;
-}
-
-static int mx6s_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
-       struct vb2_buffer *vb;
-       struct mx6s_buffer *buf;
-       unsigned long phys;
-       unsigned long flags;
-
-       if (count < 2)
-               return -ENOBUFS;
-
-       /*
-        * I didn't manage to properly enable/disable
-        * a per frame basis during running transfers,
-        * thus we allocate a buffer here and use it to
-        * discard frames when no buffer is available.
-        * Feel free to work on this ;)
-        */
-       csi_dev->discard_size = csi_dev->pix.sizeimage;
-       csi_dev->discard_buffer = dma_alloc_coherent(csi_dev->v4l2_dev.dev,
-                                       PAGE_ALIGN(csi_dev->discard_size),
-                                       &csi_dev->discard_buffer_dma,
-                                       GFP_DMA | GFP_KERNEL);
-       if (!csi_dev->discard_buffer)
-               return -ENOMEM;
-
-       spin_lock_irqsave(&csi_dev->slock, flags);
-
-       csi_dev->buf_discard[0].discard = true;
-       list_add_tail(&csi_dev->buf_discard[0].queue,
-                     &csi_dev->discard);
-
-       csi_dev->buf_discard[1].discard = true;
-       list_add_tail(&csi_dev->buf_discard[1].queue,
-                     &csi_dev->discard);
-
-       /* csi buf 0 */
-       buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
-                              internal.queue);
-       buf->internal.bufnum = 0;
-       vb = &buf->vb.vb2_buf;
-       vb->state = VB2_BUF_STATE_ACTIVE;
-
-       phys = vb2_dma_contig_plane_dma_addr(vb, 0);
-
-       mx6s_update_csi_buf(csi_dev, phys, buf->internal.bufnum);
-       list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
-
-       /* csi buf 1 */
-       buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
-                              internal.queue);
-       buf->internal.bufnum = 1;
-       vb = &buf->vb.vb2_buf;
-       vb->state = VB2_BUF_STATE_ACTIVE;
-
-       phys = vb2_dma_contig_plane_dma_addr(vb, 0);
-       mx6s_update_csi_buf(csi_dev, phys, buf->internal.bufnum);
-       list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
-
-       spin_unlock_irqrestore(&csi_dev->slock, flags);
-
-       return mx6s_csi_enable(csi_dev);
-}
-
-static void mx6s_stop_streaming(struct vb2_queue *vq)
-{
-       struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
-       unsigned long flags;
-       struct mx6s_buffer *buf, *tmp;
-       void *b;
-
-       mx6s_csi_disable(csi_dev);
-
-       spin_lock_irqsave(&csi_dev->slock, flags);
-
-       list_for_each_entry_safe(buf, tmp,
-                               &csi_dev->active_bufs, internal.queue) {
-               list_del_init(&buf->internal.queue);
-               if (buf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE)
-                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-       }
-
-       list_for_each_entry_safe(buf, tmp,
-                               &csi_dev->capture, internal.queue) {
-               list_del_init(&buf->internal.queue);
-               if (buf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE)
-                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-       }
-
-       INIT_LIST_HEAD(&csi_dev->capture);
-       INIT_LIST_HEAD(&csi_dev->active_bufs);
-       INIT_LIST_HEAD(&csi_dev->discard);
-
-       b = csi_dev->discard_buffer;
-       csi_dev->discard_buffer = NULL;
-
-       spin_unlock_irqrestore(&csi_dev->slock, flags);
-
-       dma_free_coherent(csi_dev->v4l2_dev.dev,
-                               csi_dev->discard_size, b,
-                               csi_dev->discard_buffer_dma);
-}
-
-static struct vb2_ops mx6s_videobuf_ops = {
-       .queue_setup     = mx6s_videobuf_setup,
-       .buf_prepare     = mx6s_videobuf_prepare,
-       .buf_queue       = mx6s_videobuf_queue,
-       .wait_prepare    = vb2_ops_wait_prepare,
-       .wait_finish     = vb2_ops_wait_finish,
-       .start_streaming = mx6s_start_streaming,
-       .stop_streaming  = mx6s_stop_streaming,
-};
-
-static void mx6s_csi_frame_done(struct mx6s_csi_dev *csi_dev,
-               int bufnum, bool err)
-{
-       struct mx6s_buf_internal *ibuf;
-       struct mx6s_buffer *buf;
-       struct vb2_buffer *vb;
-       unsigned long phys;
-
-       ibuf = list_first_entry(&csi_dev->active_bufs, struct mx6s_buf_internal,
-                              queue);
-
-       if (ibuf->discard) {
-               /*
-                * Discard buffer must not be returned to user space.
-                * Just return it to the discard queue.
-                */
-               list_move_tail(csi_dev->active_bufs.next, &csi_dev->discard);
-       } else {
-               buf = mx6s_ibuf_to_buf(ibuf);
-
-               vb = &buf->vb.vb2_buf;
-               phys = vb2_dma_contig_plane_dma_addr(vb, 0);
-               if (bufnum == 1) {
-                       if (csi_read(csi_dev, CSI_CSIDMASA_FB2) != phys) {
-                               dev_err(csi_dev->dev, "%lx != %x\n", phys,
-                                       csi_read(csi_dev, CSI_CSIDMASA_FB2));
-                       }
-               } else {
-                       if (csi_read(csi_dev, CSI_CSIDMASA_FB1) != phys) {
-                               dev_err(csi_dev->dev, "%lx != %x\n", phys,
-                                       csi_read(csi_dev, CSI_CSIDMASA_FB1));
-                       }
-               }
-               dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb,
-                               vb2_plane_vaddr(vb, 0),
-                               vb2_get_plane_payload(vb, 0));
-
-               list_del_init(&buf->internal.queue);
-               vb->timestamp =ktime_get_ns();
-               to_vb2_v4l2_buffer(vb)->sequence = csi_dev->frame_count;
-               if (err)
-                       vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
-               else
-                       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
-       }
-
-       csi_dev->frame_count++;
-
-       /* Config discard buffer to active_bufs */
-       if (list_empty(&csi_dev->capture)) {
-               if (list_empty(&csi_dev->discard)) {
-                       dev_warn(csi_dev->dev,
-                                       "%s: trying to access empty discard list\n",
-                                       __func__);
-                       return;
-               }
-
-               ibuf = list_first_entry(&csi_dev->discard,
-                                       struct mx6s_buf_internal, queue);
-               ibuf->bufnum = bufnum;
-
-               list_move_tail(csi_dev->discard.next, &csi_dev->active_bufs);
-
-               mx6s_update_csi_buf(csi_dev,
-                                       csi_dev->discard_buffer_dma, bufnum);
-               return;
-       }
-
-       buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
-                              internal.queue);
-
-       buf->internal.bufnum = bufnum;
-
-       list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
-
-       vb = &buf->vb.vb2_buf;
-       vb->state = VB2_BUF_STATE_ACTIVE;
-
-       phys = vb2_dma_contig_plane_dma_addr(vb, 0);
-       mx6s_update_csi_buf(csi_dev, phys, bufnum);
-}
-
-static irqreturn_t mx6s_csi_irq_handler(int irq, void *data)
-{
-       struct mx6s_csi_dev *csi_dev =  data;
-       unsigned long status;
-       u32 cr3, cr18;
-
-       spin_lock(&csi_dev->slock);
-
-       status = csi_read(csi_dev, CSI_CSISR);
-       csi_write(csi_dev, status, CSI_CSISR);
-
-       if (list_empty(&csi_dev->active_bufs)) {
-               dev_warn(csi_dev->dev,
-                               "%s: called while active list is empty\n",
-                               __func__);
-
-               spin_unlock(&csi_dev->slock);
-               return IRQ_HANDLED;
-       }
-
-       if (status & BIT_RFF_OR_INT) {
-               dev_warn(csi_dev->dev, "%s Rx fifo overflow\n", __func__);
-               if (*csi_dev->rx_fifo_rst)
-                       csi_error_recovery(csi_dev);
-       }
-
-       if (status & BIT_HRESP_ERR_INT) {
-               dev_warn(csi_dev->dev, "%s Hresponse error detected\n",
-                       __func__);
-               csi_error_recovery(csi_dev);
-       }
-
-       if (status & BIT_ADDR_CH_ERR_INT) {
-               /* Disable csi  */
-               cr18 = csi_read(csi_dev, CSI_CSICR18);
-               cr18 &= ~BIT_CSI_ENABLE;
-               csi_write(csi_dev, cr18, CSI_CSICR18);
-
-               /* DMA reflash */
-               cr3 = csi_read(csi_dev, CSI_CSICR3);
-               cr3 |= BIT_DMA_REFLASH_RFF;
-               csi_write(csi_dev, cr3, CSI_CSICR3);
-
-               /* Ensable csi  */
-               cr18 |= BIT_CSI_ENABLE;
-               csi_write(csi_dev, cr18, CSI_CSICR18);
-
-               pr_debug("base address switching Change Err.\n");
-       }
-
-       if ((status & BIT_DMA_TSF_DONE_FB1) &&
-               (status & BIT_DMA_TSF_DONE_FB2)) {
-               /* For both FB1 and FB2 interrupter bits set case,
-                * CSI DMA is work in one of FB1 and FB2 buffer,
-                * but software can not know the state.
-                * Skip it to avoid base address updated
-                * when csi work in field0 and field1 will write to
-                * new base address.
-                * PDM TKT230775 */
-               pr_debug("Skip two frames\n");
-       } else if (status & BIT_DMA_TSF_DONE_FB1) {
-               mx6s_csi_frame_done(csi_dev, 0, false);
-       } else if (status & BIT_DMA_TSF_DONE_FB2) {
-               mx6s_csi_frame_done(csi_dev, 1, false);
-       }
-
-       spin_unlock(&csi_dev->slock);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * File operations for the device
- */
-static int mx6s_csi_open(struct file *file)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-       struct vb2_queue *q = &csi_dev->vb2_vidq;
-       int ret = 0;
-
-       file->private_data = csi_dev;
-
-       if (mutex_lock_interruptible(&csi_dev->lock))
-               return -ERESTARTSYS;
-
-       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       q->io_modes = VB2_MMAP | VB2_USERPTR;
-       q->drv_priv = csi_dev;
-       q->ops = &mx6s_videobuf_ops;
-       q->mem_ops = &vb2_dma_contig_memops;
-       q->buf_struct_size = sizeof(struct mx6s_buffer);
-       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-       q->lock = &csi_dev->lock;
-
-       ret = vb2_queue_init(q);
-       if (ret < 0)
-               goto unlock;
-
-       pm_runtime_get_sync(csi_dev->dev);
-
-       request_bus_freq(BUS_FREQ_HIGH);
-
-       v4l2_subdev_call(sd, core, s_power, 1);
-       mx6s_csi_init(csi_dev);
-
-       mutex_unlock(&csi_dev->lock);
-
-       return ret;
-unlock:
-       mutex_unlock(&csi_dev->lock);
-       return ret;
-}
-
-static int mx6s_csi_close(struct file *file)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-
-       mutex_lock(&csi_dev->lock);
-
-       vb2_queue_release(&csi_dev->vb2_vidq);
-
-       mx6s_csi_deinit(csi_dev);
-       v4l2_subdev_call(sd, core, s_power, 0);
-
-       mutex_unlock(&csi_dev->lock);
-
-       file->private_data = NULL;
-
-       release_bus_freq(BUS_FREQ_HIGH);
-
-       pm_runtime_put_sync_suspend(csi_dev->dev);
-       return 0;
-}
-
-static ssize_t mx6s_csi_read(struct file *file, char __user *buf,
-                              size_t count, loff_t *ppos)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       int ret;
-
-       dev_dbg(csi_dev->dev, "read called, buf %p\n", buf);
-
-       mutex_lock(&csi_dev->lock);
-       ret = vb2_read(&csi_dev->vb2_vidq, buf, count, ppos,
-                               file->f_flags & O_NONBLOCK);
-       mutex_unlock(&csi_dev->lock);
-       return ret;
-}
-
-static int mx6s_csi_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       int ret;
-
-       if (mutex_lock_interruptible(&csi_dev->lock))
-               return -ERESTARTSYS;
-       ret = vb2_mmap(&csi_dev->vb2_vidq, vma);
-       mutex_unlock(&csi_dev->lock);
-
-       pr_debug("vma start=0x%08lx, size=%ld, ret=%d\n",
-               (unsigned long)vma->vm_start,
-               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
-               ret);
-
-       return ret;
-}
-
-static struct v4l2_file_operations mx6s_csi_fops = {
-       .owner          = THIS_MODULE,
-       .open           = mx6s_csi_open,
-       .release        = mx6s_csi_close,
-       .read           = mx6s_csi_read,
-       .poll           = vb2_fop_poll,
-       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
-       .mmap           = mx6s_csi_mmap,
-};
-
-/*
- * Video node IOCTLs
- */
-static int mx6s_vidioc_enum_input(struct file *file, void *priv,
-                                struct v4l2_input *inp)
-{
-       if (inp->index != 0)
-               return -EINVAL;
-
-       /* default is camera */
-       inp->type = V4L2_INPUT_TYPE_CAMERA;
-       strcpy(inp->name, "Camera");
-
-       return 0;
-}
-
-static int mx6s_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       *i = 0;
-
-       return 0;
-}
-
-static int mx6s_vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       if (i > 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int mx6s_vidioc_querystd(struct file *file, void *priv, v4l2_std_id *a)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-
-       return v4l2_subdev_call(sd, video, querystd, a);
-}
-
-static int mx6s_vidioc_s_std(struct file *file, void *priv, v4l2_std_id a)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-
-       return v4l2_subdev_call(sd, video, s_std, a);
-}
-
-static int mx6s_vidioc_g_std(struct file *file, void *priv, v4l2_std_id *a)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-
-       return v4l2_subdev_call(sd, video, g_std, a);
-}
-
-static int mx6s_vidioc_reqbufs(struct file *file, void *priv,
-                             struct v4l2_requestbuffers *p)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-
-       WARN_ON(priv != file->private_data);
-
-       return vb2_reqbufs(&csi_dev->vb2_vidq, p);
-}
-
-static int mx6s_vidioc_querybuf(struct file *file, void *priv,
-                              struct v4l2_buffer *p)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       int ret;
-
-       WARN_ON(priv != file->private_data);
-
-       ret = vb2_querybuf(&csi_dev->vb2_vidq, p);
-
-       if (!ret) {
-               /* return physical address */
-               struct vb2_buffer *vb = csi_dev->vb2_vidq.bufs[p->index];
-               if (p->flags & V4L2_BUF_FLAG_MAPPED)
-                       p->m.offset = vb2_dma_contig_plane_dma_addr(vb, 0);
-       }
-       return ret;
-}
-
-static int mx6s_vidioc_qbuf(struct file *file, void *priv,
-                          struct v4l2_buffer *p)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-
-       WARN_ON(priv != file->private_data);
-
-       return vb2_qbuf(&csi_dev->vb2_vidq, p);
-}
-
-static int mx6s_vidioc_dqbuf(struct file *file, void *priv,
-                           struct v4l2_buffer *p)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-
-       WARN_ON(priv != file->private_data);
-
-       return vb2_dqbuf(&csi_dev->vb2_vidq, p, file->f_flags & O_NONBLOCK);
-}
-
-static int mx6s_vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                      struct v4l2_fmtdesc *f)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-       struct v4l2_subdev_mbus_code_enum code = {
-               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-               .index = f->index,
-       };
-       struct mx6s_fmt *fmt;
-       int ret;
-
-       WARN_ON(priv != file->private_data);
-
-       ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
-       if (ret < 0) {
-               /* no more formats */
-               dev_dbg(csi_dev->dev, "No more fmt\n");
-               return -EINVAL;
-       }
-
-       fmt = format_by_mbus(code.code);
-       if (!fmt) {
-               dev_err(csi_dev->dev, "mbus (0x%08x) invalid.\n", code.code);
-               return -EINVAL;
-       }
-
-       strlcpy(f->description, fmt->name, sizeof(f->description));
-       f->pixelformat = fmt->pixelformat;
-
-       return 0;
-}
-
-static int mx6s_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                                     struct v4l2_format *f)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-       struct v4l2_pix_format *pix = &f->fmt.pix;
-       struct v4l2_subdev_format format = {
-               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-       };
-       struct mx6s_fmt *fmt;
-       int ret;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (!fmt) {
-               dev_err(csi_dev->dev, "Fourcc format (0x%08x) invalid.",
-                       f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       if (f->fmt.pix.width == 0 || f->fmt.pix.height == 0) {
-               dev_err(csi_dev->dev, "width %d, height %d is too small.\n",
-                       f->fmt.pix.width, f->fmt.pix.height);
-               return -EINVAL;
-       }
-
-       v4l2_fill_mbus_format(&format.format, pix, fmt->mbus_code);
-       ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
-       v4l2_fill_pix_format(pix, &format.format);
-
-       if (pix->field != V4L2_FIELD_INTERLACED)
-               pix->field = V4L2_FIELD_NONE;
-
-       pix->sizeimage = fmt->bpp * pix->height * pix->width;
-       pix->bytesperline = fmt->bpp * pix->width;
-
-       return ret;
-}
-
-/*
- * The real work of figuring out a workable format.
- */
-
-static int mx6s_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                                   struct v4l2_format *f)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       int ret;
-
-       ret = mx6s_vidioc_try_fmt_vid_cap(file, csi_dev, f);
-       if (ret < 0)
-               return ret;
-
-       csi_dev->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
-       csi_dev->mbus_code     = csi_dev->fmt->mbus_code;
-       csi_dev->pix.width     = f->fmt.pix.width;
-       csi_dev->pix.height    = f->fmt.pix.height;
-       csi_dev->pix.sizeimage = f->fmt.pix.sizeimage;
-       csi_dev->pix.field     = f->fmt.pix.field;
-       csi_dev->type          = f->type;
-       dev_dbg(csi_dev->dev, "set to pixelformat '%4.6s'\n",
-                       (char *)&csi_dev->fmt->name);
-
-       /* Config csi */
-       mx6s_configure_csi(csi_dev);
-
-       return 0;
-}
-
-static int mx6s_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                   struct v4l2_format *f)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-
-       WARN_ON(priv != file->private_data);
-
-       f->fmt.pix = csi_dev->pix;
-
-       return 0;
-}
-
-static int mx6s_vidioc_querycap(struct file *file, void  *priv,
-                              struct v4l2_capability *cap)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-
-       WARN_ON(priv != file->private_data);
-
-       /* cap->name is set by the friendly caller:-> */
-       strlcpy(cap->driver, MX6S_CAM_DRV_NAME, sizeof(cap->driver));
-       strlcpy(cap->card, MX6S_CAM_DRIVER_DESCRIPTION, sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-                dev_name(csi_dev->dev));
-
-       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-       return 0;
-}
-
-static int mx6s_vidioc_streamon(struct file *file, void *priv,
-                              enum v4l2_buf_type i)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-       int ret;
-
-       WARN_ON(priv != file->private_data);
-
-       if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       ret = vb2_streamon(&csi_dev->vb2_vidq, i);
-       if (!ret)
-               v4l2_subdev_call(sd, video, s_stream, 1);
-
-       return ret;
-}
-
-static int mx6s_vidioc_streamoff(struct file *file, void *priv,
-                               enum v4l2_buf_type i)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-
-       WARN_ON(priv != file->private_data);
-
-       if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       /*
-        * This calls buf_release from host driver's videobuf_queue_ops for all
-        * remaining buffers. When the last buffer is freed, stop capture
-        */
-       vb2_streamoff(&csi_dev->vb2_vidq, i);
-
-       v4l2_subdev_call(sd, video, s_stream, 0);
-
-       return 0;
-}
-
-static int mx6s_vidioc_cropcap(struct file *file, void *fh,
-                             struct v4l2_cropcap *a)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       dev_dbg(csi_dev->dev, "VIDIOC_CROPCAP not implemented\n");
-
-       return 0;
-}
-
-static int mx6s_vidioc_g_crop(struct file *file, void *priv,
-                            struct v4l2_crop *a)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       dev_dbg(csi_dev->dev, "VIDIOC_G_CROP not implemented\n");
-
-       return 0;
-}
-
-static int mx6s_vidioc_s_crop(struct file *file, void *priv,
-                            const struct v4l2_crop *a)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       dev_dbg(csi_dev->dev, "VIDIOC_S_CROP not implemented\n");
-
-       return 0;
-}
-
-static int mx6s_vidioc_g_parm(struct file *file, void *priv,
-                            struct v4l2_streamparm *a)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-
-       return v4l2_subdev_call(sd, video, g_parm, a);
-}
-
-static int mx6s_vidioc_s_parm(struct file *file, void *priv,
-                               struct v4l2_streamparm *a)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-
-       return v4l2_subdev_call(sd, video, s_parm, a);
-}
-
-static int mx6s_vidioc_enum_framesizes(struct file *file, void *priv,
-                                        struct v4l2_frmsizeenum *fsize)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-       struct mx6s_fmt *fmt;
-       struct v4l2_subdev_frame_size_enum fse = {
-               .index = fsize->index,
-               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-       };
-       int ret;
-
-       fmt = format_by_fourcc(fsize->pixel_format);
-       if (fmt->pixelformat != fsize->pixel_format)
-               return -EINVAL;
-       fse.code = fmt->mbus_code;
-
-       ret = v4l2_subdev_call(sd, pad, enum_frame_size, NULL, &fse);
-       if (ret)
-               return ret;
-
-       if (fse.min_width == fse.max_width &&
-           fse.min_height == fse.max_height) {
-               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-               fsize->discrete.width = fse.min_width;
-               fsize->discrete.height = fse.min_height;
-               return 0;
-       }
-
-       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-       fsize->stepwise.min_width = fse.min_width;
-       fsize->stepwise.max_width = fse.max_width;
-       fsize->stepwise.min_height = fse.min_height;
-       fsize->stepwise.max_height = fse.max_height;
-       fsize->stepwise.step_width = 1;
-       fsize->stepwise.step_height = 1;
-
-       return 0;
-}
-
-static int mx6s_vidioc_enum_frameintervals(struct file *file, void *priv,
-               struct v4l2_frmivalenum *interval)
-{
-       struct mx6s_csi_dev *csi_dev = video_drvdata(file);
-       struct v4l2_subdev *sd = csi_dev->sd;
-       struct mx6s_fmt *fmt;
-       struct v4l2_subdev_frame_interval_enum fie = {
-               .index = interval->index,
-               .width = interval->width,
-               .height = interval->height,
-               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-       };
-       int ret;
-
-       fmt = format_by_fourcc(interval->pixel_format);
-       if (fmt->pixelformat != interval->pixel_format)
-               return -EINVAL;
-       fie.code = fmt->mbus_code;
-
-       ret = v4l2_subdev_call(sd, pad, enum_frame_interval, NULL, &fie);
-       if (ret)
-               return ret;
-       interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-       interval->discrete = fie.interval;
-       return 0;
-}
-
-static const struct v4l2_ioctl_ops mx6s_csi_ioctl_ops = {
-       .vidioc_querycap          = mx6s_vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = mx6s_vidioc_enum_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap   = mx6s_vidioc_try_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap     = mx6s_vidioc_g_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap     = mx6s_vidioc_s_fmt_vid_cap,
-       .vidioc_cropcap       = mx6s_vidioc_cropcap,
-       .vidioc_s_crop        = mx6s_vidioc_s_crop,
-       .vidioc_g_crop        = mx6s_vidioc_g_crop,
-       .vidioc_reqbufs       = mx6s_vidioc_reqbufs,
-       .vidioc_querybuf      = mx6s_vidioc_querybuf,
-       .vidioc_qbuf          = mx6s_vidioc_qbuf,
-       .vidioc_dqbuf         = mx6s_vidioc_dqbuf,
-       .vidioc_g_std         = mx6s_vidioc_g_std,
-       .vidioc_s_std         = mx6s_vidioc_s_std,
-       .vidioc_querystd      = mx6s_vidioc_querystd,
-       .vidioc_enum_input    = mx6s_vidioc_enum_input,
-       .vidioc_g_input       = mx6s_vidioc_g_input,
-       .vidioc_s_input       = mx6s_vidioc_s_input,
-       .vidioc_streamon      = mx6s_vidioc_streamon,
-       .vidioc_streamoff     = mx6s_vidioc_streamoff,
-       .vidioc_g_parm        = mx6s_vidioc_g_parm,
-       .vidioc_s_parm        = mx6s_vidioc_s_parm,
-       .vidioc_enum_framesizes = mx6s_vidioc_enum_framesizes,
-       .vidioc_enum_frameintervals = mx6s_vidioc_enum_frameintervals,
-};
-
-static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
-                           struct v4l2_subdev *subdev,
-                           struct v4l2_async_subdev *asd)
-{
-       struct mx6s_csi_dev *csi_dev = notifier_to_mx6s_dev(notifier);
-
-       /* Find platform data for this sensor subdev */
-       if (csi_dev->asd.match.of.node == subdev->dev->of_node)
-               csi_dev->sd = subdev;
-
-       if (subdev == NULL)
-               return -EINVAL;
-
-       v4l2_info(&csi_dev->v4l2_dev, "Registered sensor subdevice: %s\n",
-                 subdev->name);
-
-       return 0;
-}
-
-static int mx6s_csi_mux_sel(struct mx6s_csi_dev *csi_dev)
-{
-       struct device_node *np = csi_dev->dev->of_node;
-       struct device_node *node;
-       phandle phandle;
-       u32 out_val[3];
-       int ret;
-
-       ret = of_property_read_u32_array(np, "csi-mux-mipi", out_val, 3);
-       if (ret) {
-               dev_dbg(csi_dev->dev, "no csi-mux-mipi property found\n");
-               csi_dev->csi_mux_mipi = false;
-       } else {
-               phandle = *out_val;
-
-               node = of_find_node_by_phandle(phandle);
-               if (!node) {
-                       dev_dbg(csi_dev->dev, "not find gpr node by phandle\n");
-                       ret = PTR_ERR(node);
-               }
-               csi_dev->csi_mux.gpr = syscon_node_to_regmap(node);
-               if (IS_ERR(csi_dev->csi_mux.gpr)) {
-                       dev_err(csi_dev->dev, "failed to get gpr regmap\n");
-                       ret = PTR_ERR(csi_dev->csi_mux.gpr);
-               }
-               of_node_put(node);
-               if (ret < 0)
-                       return ret;
-
-               csi_dev->csi_mux.req_gpr = out_val[1];
-               csi_dev->csi_mux.req_bit = out_val[2];
-
-               regmap_update_bits(csi_dev->csi_mux.gpr, csi_dev->csi_mux.req_gpr,
-                       1 << csi_dev->csi_mux.req_bit, 1 << csi_dev->csi_mux.req_bit);
-
-               csi_dev->csi_mux_mipi = true;
-       }
-       return ret;
-}
-
-static int mx6sx_register_subdevs(struct mx6s_csi_dev *csi_dev)
-{
-       struct device_node *parent = csi_dev->dev->of_node;
-       struct device_node *node, *port, *rem;
-       int ret;
-
-       /* Attach sensors linked to csi receivers */
-       for_each_available_child_of_node(parent, node) {
-               if (of_node_cmp(node->name, "port"))
-                       continue;
-
-               /* The csi node can have only port subnode. */
-               port = of_get_next_child(node, NULL);
-               if (!port)
-                       continue;
-               rem = of_graph_get_remote_port_parent(port);
-               of_node_put(port);
-               if (rem == NULL) {
-                       v4l2_info(&csi_dev->v4l2_dev,
-                                               "Remote device at %s not found\n",
-                                               port->full_name);
-                       return -1;
-               }
-
-               csi_dev->asd.match_type = V4L2_ASYNC_MATCH_OF;
-               csi_dev->asd.match.of.node = rem;
-               csi_dev->async_subdevs[0] = &csi_dev->asd;
-
-               of_node_put(rem);
-               break;
-       }
-
-       csi_dev->subdev_notifier.subdevs = csi_dev->async_subdevs;
-       csi_dev->subdev_notifier.num_subdevs = 1;
-       csi_dev->subdev_notifier.bound = subdev_notifier_bound;
-
-       ret = v4l2_async_notifier_register(&csi_dev->v4l2_dev,
-                                       &csi_dev->subdev_notifier);
-       if (ret)
-               dev_err(csi_dev->dev,
-                                       "Error register async notifier regoster\n");
-
-       return ret;
-}
-
-static int mx6s_csi_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       const struct of_device_id *of_id;
-       struct mx6s_csi_dev *csi_dev;
-       struct video_device *vdev;
-       struct resource *res;
-       int ret = 0;
-
-       dev_dbg(dev, "initialising\n");
-
-       /* Prepare our private structure */
-       csi_dev = devm_kzalloc(dev, sizeof(struct mx6s_csi_dev), GFP_ATOMIC);
-       if (!csi_dev) {
-               dev_err(dev, "Can't allocate private structure\n");
-               return -ENODEV;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       csi_dev->irq = platform_get_irq(pdev, 0);
-       if (res == NULL || csi_dev->irq < 0) {
-               dev_err(dev, "Missing platform resources data\n");
-               return -ENODEV;
-       }
-
-       csi_dev->regbase = devm_ioremap_resource(dev, res);
-       if (IS_ERR(csi_dev->regbase)) {
-               dev_err(dev, "Failed platform resources map\n");
-               return -ENODEV;
-       }
-
-       /* init video dma queues */
-       INIT_LIST_HEAD(&csi_dev->capture);
-       INIT_LIST_HEAD(&csi_dev->active_bufs);
-       INIT_LIST_HEAD(&csi_dev->discard);
-
-       csi_dev->clk_disp_axi = devm_clk_get(dev, "disp-axi");
-       if (IS_ERR(csi_dev->clk_disp_axi)) {
-               dev_err(dev, "Could not get csi axi clock\n");
-               return -ENODEV;
-       }
-
-       csi_dev->clk_disp_dcic = devm_clk_get(dev, "disp_dcic");
-       if (IS_ERR(csi_dev->clk_disp_dcic)) {
-               dev_err(dev, "Could not get disp dcic clock\n");
-               return -ENODEV;
-       }
-
-       csi_dev->clk_csi_mclk = devm_clk_get(dev, "csi_mclk");
-       if (IS_ERR(csi_dev->clk_csi_mclk)) {
-               dev_err(dev, "Could not get csi mclk clock\n");
-               return -ENODEV;
-       }
-
-       csi_dev->dev = dev;
-
-       mx6s_csi_mux_sel(csi_dev);
-
-       of_id = of_match_node(mx6s_csi_dt_ids, csi_dev->dev->of_node);
-       if (!of_id)
-               return -EINVAL;
-       csi_dev->rx_fifo_rst = of_id->data;
-
-       snprintf(csi_dev->v4l2_dev.name,
-                sizeof(csi_dev->v4l2_dev.name), "CSI");
-
-       ret = v4l2_device_register(dev, &csi_dev->v4l2_dev);
-       if (ret < 0) {
-               dev_err(dev, "v4l2_device_register() failed: %d\n", ret);
-               return -ENODEV;
-       }
-
-       /* initialize locks */
-       mutex_init(&csi_dev->lock);
-       spin_lock_init(&csi_dev->slock);
-
-       /* Allocate memory for video device */
-       vdev = video_device_alloc();
-       if (vdev == NULL) {
-               ret = -ENOMEM;
-               goto err_vdev;
-       }
-
-       snprintf(vdev->name, sizeof(vdev->name), "mx6s-csi");
-
-       vdev->v4l2_dev          = &csi_dev->v4l2_dev;
-       vdev->fops                      = &mx6s_csi_fops;
-       vdev->ioctl_ops         = &mx6s_csi_ioctl_ops;
-       vdev->release           = video_device_release;
-       vdev->lock                      = &csi_dev->lock;
-
-       vdev->queue = &csi_dev->vb2_vidq;
-
-       csi_dev->vdev = vdev;
-
-       video_set_drvdata(csi_dev->vdev, csi_dev);
-       mutex_lock(&csi_dev->lock);
-
-       ret = video_register_device(csi_dev->vdev, VFL_TYPE_GRABBER, -1);
-       if (ret < 0) {
-               video_device_release(csi_dev->vdev);
-               mutex_unlock(&csi_dev->lock);
-               goto err_vdev;
-       }
-
-       /* install interrupt handler */
-       if (devm_request_irq(dev, csi_dev->irq, mx6s_csi_irq_handler,
-                               0, "csi", (void *)csi_dev)) {
-               mutex_unlock(&csi_dev->lock);
-               dev_err(dev, "Request CSI IRQ failed.\n");
-               ret = -ENODEV;
-               goto err_irq;
-       }
-
-       mutex_unlock(&csi_dev->lock);
-
-       ret = mx6sx_register_subdevs(csi_dev);
-       if (ret < 0)
-               goto err_irq;
-
-       pm_runtime_enable(csi_dev->dev);
-       return 0;
-
-err_irq:
-       video_unregister_device(csi_dev->vdev);
-err_vdev:
-       v4l2_device_unregister(&csi_dev->v4l2_dev);
-       return ret;
-}
-
-static int mx6s_csi_remove(struct platform_device *pdev)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
-       struct mx6s_csi_dev *csi_dev =
-                               container_of(v4l2_dev, struct mx6s_csi_dev, v4l2_dev);
-
-       v4l2_async_notifier_unregister(&csi_dev->subdev_notifier);
-
-       video_unregister_device(csi_dev->vdev);
-       v4l2_device_unregister(&csi_dev->v4l2_dev);
-
-       pm_runtime_disable(csi_dev->dev);
-       return 0;
-}
-
-static int mx6s_csi_runtime_suspend(struct device *dev)
-{
-       dev_dbg(dev, "csi v4l2 busfreq high release.\n");
-       return 0;
-}
-
-static int mx6s_csi_runtime_resume(struct device *dev)
-{
-       dev_dbg(dev, "csi v4l2 busfreq high request.\n");
-       return 0;
-}
-
-static const struct dev_pm_ops mx6s_csi_pm_ops = {
-       SET_RUNTIME_PM_OPS(mx6s_csi_runtime_suspend, mx6s_csi_runtime_resume, NULL)
-};
-
-static const u8 mx6s_fifo_rst = true;
-static const u8 mx6sl_fifo_rst = false;
-
-static const struct of_device_id mx6s_csi_dt_ids[] = {
-       { .compatible = "fsl,imx6s-csi",
-         .data = &mx6s_fifo_rst,
-       },
-       { .compatible = "fsl,imx6sl-csi",
-         .data = &mx6sl_fifo_rst,
-       },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, mx6s_csi_dt_ids);
-
-static struct platform_driver mx6s_csi_driver = {
-       .driver         = {
-               .name   = MX6S_CAM_DRV_NAME,
-               .of_match_table = of_match_ptr(mx6s_csi_dt_ids),
-               .pm = &mx6s_csi_pm_ops,
-       },
-       .probe  = mx6s_csi_probe,
-       .remove = mx6s_csi_remove,
-};
-
-module_platform_driver(mx6s_csi_driver);
-
-MODULE_DESCRIPTION("i.MX6Sx SoC Camera Host driver");
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MX6S_CAM_VERSION);
diff --git a/drivers/media/platform/mxc/subdev/mxc_mipi_csi.c b/drivers/media/platform/mxc/subdev/mxc_mipi_csi.c
deleted file mode 100644 (file)
index 4371d65..0000000
+++ /dev/null
@@ -1,1248 +0,0 @@
-/*
- * Freescale i.MX7 SoC series MIPI-CSI V3.3 receiver driver
- *
- * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-/*
- * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver
- *
- * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
- * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_graph.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-of.h>
-#include <media/v4l2-subdev.h>
-#include <media/v4l2-device.h>
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-2)");
-
-#define CSIS_DRIVER_NAME       "mxc_mipi-csi"
-#define CSIS_SUBDEV_NAME       CSIS_DRIVER_NAME
-#define CSIS_MAX_ENTITIES      2
-#define CSIS0_MAX_LANES                4
-#define CSIS1_MAX_LANES                2
-
-#define MIPI_CSIS_DEF_PIX_WIDTH        640
-#define MIPI_CSIS_DEF_PIX_HEIGHT       480
-
-/* Register map definition */
-
-/* CSIS version */
-#define MIPI_CSIS_VERSION              0x00
-
-/* CSIS common control */
-#define MIPI_CSIS_CMN_CTRL                     0x04
-#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW       (1 << 16)
-#define MIPI_CSIS_CMN_CTRL_INTER_MODE          (1 << 10)
-#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET      8
-#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK                (3 << 8)
-#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL  (1 << 2)
-#define MIPI_CSIS_CMN_CTRL_RESET               (1 << 1)
-#define MIPI_CSIS_CMN_CTRL_ENABLE              (1 << 0)
-
-/* CSIS clock control */
-#define MIPI_CSIS_CLK_CTRL             0x08
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x)        (x << 28)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x)        (x << 24)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x)        (x << 20)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x)        (x << 16)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK      (0xf << 4)
-#define MIPI_CSIS_CLK_CTRL_WCLK_SRC            (1 << 0)
-
-/* CSIS Interrupt mask */
-#define MIPI_CSIS_INTMSK                       0x10
-#define MIPI_CSIS_INTMSK_EVEN_BEFORE   (1 << 31)
-#define MIPI_CSIS_INTMSK_EVEN_AFTER    (1 << 30)
-#define MIPI_CSIS_INTMSK_ODD_BEFORE    (1 << 29)
-#define MIPI_CSIS_INTMSK_ODD_AFTER     (1 << 28)
-#define MIPI_CSIS_INTMSK_FRAME_START   (1 << 24)
-#define MIPI_CSIS_INTMSK_FRAME_END     (1 << 20)
-#define MIPI_CSIS_INTMSK_ERR_SOT_HS    (1 << 16)
-#define MIPI_CSIS_INTMSK_ERR_LOST_FS   (1 << 12)
-#define MIPI_CSIS_INTMSK_ERR_LOST_FE   (1 << 8)
-#define MIPI_CSIS_INTMSK_ERR_OVER              (1 << 4)
-#define MIPI_CSIS_INTMSK_ERR_WRONG_CFG (1 << 3)
-#define MIPI_CSIS_INTMSK_ERR_ECC               (1 << 2)
-#define MIPI_CSIS_INTMSK_ERR_CRC               (1 << 1)
-#define MIPI_CSIS_INTMSK_ERR_UNKNOWN   (1 << 0)
-
-/* CSIS Interrupt source */
-#define MIPI_CSIS_INTSRC                       0x14
-#define MIPI_CSIS_INTSRC_EVEN_BEFORE   (1 << 31)
-#define MIPI_CSIS_INTSRC_EVEN_AFTER    (1 << 30)
-#define MIPI_CSIS_INTSRC_EVEN          (0x3 << 30)
-#define MIPI_CSIS_INTSRC_ODD_BEFORE    (1 << 29)
-#define MIPI_CSIS_INTSRC_ODD_AFTER     (1 << 28)
-#define MIPI_CSIS_INTSRC_ODD                   (0x3 << 28)
-#define MIPI_CSIS_INTSRC_NON_IMAGE_DATA        (0xf << 28)
-#define MIPI_CSIS_INTSRC_FRAME_START   (1 << 24)
-#define MIPI_CSIS_INTSRC_FRAME_END     (1 << 20)
-#define MIPI_CSIS_INTSRC_ERR_SOT_HS    (1 << 16)
-#define MIPI_CSIS_INTSRC_ERR_LOST_FS   (1 << 12)
-#define MIPI_CSIS_INTSRC_ERR_LOST_FE   (1 << 8)
-#define MIPI_CSIS_INTSRC_ERR_OVER              (1 << 4)
-#define MIPI_CSIS_INTSRC_ERR_WRONG_CFG (1 << 3)
-#define MIPI_CSIS_INTSRC_ERR_ECC               (1 << 2)
-#define MIPI_CSIS_INTSRC_ERR_CRC               (1 << 1)
-#define MIPI_CSIS_INTSRC_ERR_UNKNOWN   (1 << 0)
-#define MIPI_CSIS_INTSRC_ERRORS                0xfffff
-
-/* D-PHY status control */
-#define MIPI_CSIS_DPHYSTATUS           0x20
-#define MIPI_CSIS_DPHYSTATUS_ULPS_DAT                  (1 << 8)
-#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_DAT             (1 << 4)
-#define MIPI_CSIS_DPHYSTATUS_ULPS_CLK                  (1 << 1)
-#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_CLK             (1 << 0)
-
-/* D-PHY common control */
-#define MIPI_CSIS_DPHYCTRL             0x24
-#define MIPI_CSIS_DPHYCTRL_HSS_MASK                    (0xff << 24)
-#define MIPI_CSIS_DPHYCTRL_HSS_OFFSET          24
-#define MIPI_CSIS_DPHYCTRL_SCLKS_MASK          (0x3 << 22)
-#define MIPI_CSIS_DPHYCTRL_SCLKS_OFFSET                22
-#define MIPI_CSIS_DPHYCTRL_DPDN_SWAP_CLK       (1 << 6)
-#define MIPI_CSIS_DPHYCTRL_DPDN_SWAP_DAT       (1 << 5)
-#define MIPI_CSIS_DPHYCTRL_ENABLE_DAT          (1 << 1)
-#define MIPI_CSIS_DPHYCTRL_ENABLE_CLK          (1 << 0)
-#define MIPI_CSIS_DPHYCTRL_ENABLE                      (0x1f << 0)
-
-/* D-PHY Master and Slave Control register Low */
-#define MIPI_CSIS_DPHYBCTRL_L          0x30
-/* D-PHY Master and Slave Control register High */
-#define MIPI_CSIS_DPHYBCTRL_H          0x34
-/* D-PHY Slave Control register Low */
-#define MIPI_CSIS_DPHYSCTRL_L          0x38
-/* D-PHY Slave Control register High */
-#define MIPI_CSIS_DPHYSCTRL_H          0x3c
-
-
-/* ISP Configuration register */
-#define MIPI_CSIS_ISPCONFIG_CH0                        0x40
-#define MIPI_CSIS_ISPCONFIG_CH1                        0x50
-#define MIPI_CSIS_ISPCONFIG_CH2                        0x60
-#define MIPI_CSIS_ISPCONFIG_CH3                        0x70
-
-#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK    (0xff << 24)
-#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x)     (x << 24)
-#define MIPI_CSIS_ISPCFG_DOUBLE_CMPNT        (1 << 12)
-#define MIPI_CSIS_ISPCFG_ALIGN_32BIT         (1 << 11)
-#define MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT   (0x1e << 2)
-#define MIPI_CSIS_ISPCFG_FMT_RAW8              (0x2a << 2)
-#define MIPI_CSIS_ISPCFG_FMT_RAW10             (0x2b << 2)
-#define MIPI_CSIS_ISPCFG_FMT_RAW12             (0x2c << 2)
-/* User defined formats, x = 1...4 */
-#define MIPI_CSIS_ISPCFG_FMT_USER(x)   ((0x30 + x - 1) << 2)
-#define MIPI_CSIS_ISPCFG_FMT_MASK              (0x3f << 2)
-
-/* ISP Image Resolution register */
-#define MIPI_CSIS_ISPRESOL_CH0                 0x44
-#define MIPI_CSIS_ISPRESOL_CH1                 0x54
-#define MIPI_CSIS_ISPRESOL_CH2                 0x64
-#define MIPI_CSIS_ISPRESOL_CH3                 0x74
-#define CSIS_MAX_PIX_WIDTH             0xffff
-#define CSIS_MAX_PIX_HEIGHT            0xffff
-
-/* ISP SYNC register */
-#define MIPI_CSIS_ISPSYNC_CH0                  0x48
-#define MIPI_CSIS_ISPSYNC_CH1                  0x58
-#define MIPI_CSIS_ISPSYNC_CH2                  0x68
-#define MIPI_CSIS_ISPSYNC_CH3                  0x78
-
-#define MIPI_CSIS_ISPSYNC_HSYNC_LINTV_OFFSET   18
-#define MIPI_CSIS_ISPSYNC_VSYNC_SINTV_OFFSET   12
-#define MIPI_CSIS_ISPSYNC_VSYNC_EINTV_OFFSET   0
-
-/* Non-image packet data buffers */
-#define MIPI_CSIS_PKTDATA_ODD          0x2000
-#define MIPI_CSIS_PKTDATA_EVEN         0x3000
-#define MIPI_CSIS_PKTDATA_SIZE         SZ_4K
-
-#define DEFAULT_SCLK_CSIS_FREQ 166000000UL
-
-enum {
-       ST_POWERED      = 1,
-       ST_STREAMING    = 2,
-       ST_SUSPENDED    = 4,
-};
-
-struct mipi_csis_event {
-       u32 mask;
-       const char * const name;
-       unsigned int counter;
-};
-
-static const struct mipi_csis_event mipi_csis_events[] = {
-       /* Errors */
-       { MIPI_CSIS_INTSRC_ERR_SOT_HS,  "SOT Error" },
-       { MIPI_CSIS_INTSRC_ERR_LOST_FS, "Lost Frame Start Error" },
-       { MIPI_CSIS_INTSRC_ERR_LOST_FE, "Lost Frame End Error" },
-       { MIPI_CSIS_INTSRC_ERR_OVER,    "FIFO Overflow Error" },
-       { MIPI_CSIS_INTSRC_ERR_ECC,     "ECC Error" },
-       { MIPI_CSIS_INTSRC_ERR_CRC,     "CRC Error" },
-       { MIPI_CSIS_INTSRC_ERR_UNKNOWN, "Unknown Error" },
-       /* Non-image data receive events */
-       { MIPI_CSIS_INTSRC_EVEN_BEFORE, "Non-image data before even frame" },
-       { MIPI_CSIS_INTSRC_EVEN_AFTER,  "Non-image data after even frame" },
-       { MIPI_CSIS_INTSRC_ODD_BEFORE,  "Non-image data before odd frame" },
-       { MIPI_CSIS_INTSRC_ODD_AFTER,   "Non-image data after odd frame" },
-       /* Frame start/end */
-       { MIPI_CSIS_INTSRC_FRAME_START, "Frame Start" },
-       { MIPI_CSIS_INTSRC_FRAME_END,   "Frame End" },
-};
-#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events)
-
-struct csis_pktbuf {
-       u32 *data;
-       unsigned int len;
-};
-
-struct csis_hw_reset {
-       struct regmap *src;
-       u8 req_src;
-       u8 rst_bit;
-};
-
-/**
- * struct csi_state - the driver's internal state data structure
- * @lock: mutex serializing the subdev and power management operations,
- *        protecting @format and @flags members
- * @sd: v4l2_subdev associated with CSIS device instance
- * @index: the hardware instance index
- * @pdev: CSIS platform device
- * @phy: pointer to the CSIS generic PHY
- * @regs: mmaped I/O registers memory
- * @supplies: CSIS regulator supplies
- * @clock: CSIS clocks
- * @irq: requested s5p-mipi-csis irq number
- * @flags: the state variable for power and streaming control
- * @clock_frequency: device bus clock frequency
- * @hs_settle: HS-RX settle time
- * @clk_settle: Clk settle time
- * @num_lanes: number of MIPI-CSI data lanes used
- * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
- * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
- * @csis_fmt: current CSIS pixel format
- * @format: common media bus format for the source and sink pad
- * @slock: spinlock protecting structure members below
- * @pkt_buf: the frame embedded (non-image) data buffer
- * @events: MIPI-CSIS event (error) counters
- */
-struct csi_state {
-       struct mutex lock;
-       struct device           *dev;
-       struct v4l2_subdev mipi_sd;
-       struct v4l2_subdev *sensor_sd;
-       struct v4l2_device      v4l2_dev;
-
-       u8 index;
-       struct platform_device *pdev;
-       struct phy *phy;
-       void __iomem *regs;
-       struct clk *mipi_clk;
-       struct clk *phy_clk;
-       int irq;
-       u32 flags;
-
-       u32 clk_frequency;
-       u32 hs_settle;
-       u32 clk_settle;
-       u32 num_lanes;
-       u32 max_num_lanes;
-       u8 wclk_ext;
-
-       const struct csis_pix_format *csis_fmt;
-       struct v4l2_mbus_framefmt format;
-
-       spinlock_t slock;
-       struct csis_pktbuf pkt_buf;
-       struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
-
-       struct v4l2_async_subdev    asd;
-       struct v4l2_async_notifier  subdev_notifier;
-       struct v4l2_async_subdev    *async_subdevs[2];
-
-       struct csis_hw_reset hw_reset;
-       struct regulator     *mipi_phy_regulator;
-};
-
-/**
- * struct csis_pix_format - CSIS pixel format description
- * @pix_width_alignment: horizontal pixel alignment, width will be
- *                       multiple of 2^pix_width_alignment
- * @code: corresponding media bus code
- * @fmt_reg: MIPI_CSIS_CONFIG register value
- * @data_alignment: MIPI-CSI data alignment in bits
- */
-struct csis_pix_format {
-       unsigned int pix_width_alignment;
-       u32 code;
-       u32 fmt_reg;
-       u8 data_alignment;
-};
-
-static const struct csis_pix_format mipi_csis_formats[] = {
-       {
-               .code = MEDIA_BUS_FMT_YUYV8_2X8,
-               .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT,
-               .data_alignment = 16,
-       }, {
-               .code = MEDIA_BUS_FMT_VYUY8_2X8,
-               .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT,
-               .data_alignment = 16,
-       }, {
-               .code = MEDIA_BUS_FMT_SBGGR8_1X8,
-               .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8,
-               .data_alignment = 8,
-       }
-};
-
-#define mipi_csis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
-#define mipi_csis_read(__csis, __r) readl(__csis->regs + __r)
-
-static struct csi_state *mipi_sd_to_csi_state(struct v4l2_subdev *sdev)
-{
-       return container_of(sdev, struct csi_state, mipi_sd);
-}
-
-static inline struct csi_state
-                               *notifier_to_mipi_dev(struct v4l2_async_notifier *n)
-{
-       return container_of(n, struct csi_state, subdev_notifier);
-}
-
-static const struct csis_pix_format *find_csis_format(u32 code)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++)
-               if (code == mipi_csis_formats[i].code)
-                       return &mipi_csis_formats[i];
-       return NULL;
-}
-
-static void mipi_csis_enable_interrupts(struct csi_state *state, bool on)
-{
-       u32 val = mipi_csis_read(state, MIPI_CSIS_INTMSK);
-       if (on)
-               val |= 0xf00fffff;
-       else
-               val &= ~0xf00fffff;
-       mipi_csis_write(state, MIPI_CSIS_INTMSK, val);
-}
-
-static void mipi_csis_sw_reset(struct csi_state *state)
-{
-       u32 val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-
-       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val | MIPI_CSIS_CMN_CTRL_RESET);
-       udelay(10);
-}
-
-static int mipi_csis_phy_init(struct csi_state *state)
-{
-       int ret;
-
-       state->mipi_phy_regulator = devm_regulator_get(state->dev,
-                               "mipi-phy");
-
-       ret = regulator_set_voltage(state->mipi_phy_regulator,
-                       1000000, 1000000);
-
-       return ret;
-}
-
-static int mipi_csis_phy_reset(struct csi_state *state)
-{
-       struct device_node *np = state->dev->of_node;
-       struct device_node *node;
-       phandle phandle;
-       u32 out_val[3];
-       int ret;
-
-       ret = of_property_read_u32_array(np, "csis-phy-reset", out_val, 3);
-       if (ret) {
-               dev_dbg(state->dev, "no csis-hw-reset property found\n");
-       } else {
-               phandle = *out_val;
-
-               node = of_find_node_by_phandle(phandle);
-               if (!node) {
-                       dev_dbg(state->dev, "not find src node by phandle\n");
-                       ret = PTR_ERR(node);
-               }
-               state->hw_reset.src = syscon_node_to_regmap(node);
-               if (IS_ERR(state->hw_reset.src)) {
-                       dev_err(state->dev, "failed to get src regmap\n");
-                       ret = PTR_ERR(state->hw_reset.src);
-               }
-               of_node_put(node);
-               if (ret < 0)
-                       return ret;
-
-               state->hw_reset.req_src = out_val[1];
-               state->hw_reset.rst_bit = out_val[2];
-
-               /* reset mipi phy */
-               regmap_update_bits(state->hw_reset.src, state->hw_reset.req_src,
-                       1 << state->hw_reset.rst_bit, 1 << state->hw_reset.rst_bit);
-               msleep(20);
-               regmap_update_bits(state->hw_reset.src, state->hw_reset.req_src,
-                       1 << state->hw_reset.rst_bit, 0);
-
-       }
-       return ret;
-}
-
-static void mipi_csis_system_enable(struct csi_state *state, int on)
-{
-       u32 val, mask;
-
-       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-       if (on)
-               val |= MIPI_CSIS_CMN_CTRL_ENABLE;
-       else
-               val &= ~MIPI_CSIS_CMN_CTRL_ENABLE;
-       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
-
-       val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL);
-       val &= ~MIPI_CSIS_DPHYCTRL_ENABLE;
-       if (on) {
-               mask = (1 << (state->num_lanes + 1)) - 1;
-               val |= (mask & MIPI_CSIS_DPHYCTRL_ENABLE);
-       }
-       mipi_csis_write(state, MIPI_CSIS_DPHYCTRL, val);
-}
-
-/* Called with the state.lock mutex held */
-static void __mipi_csis_set_format(struct csi_state *state)
-{
-       struct v4l2_mbus_framefmt *mf = &state->format;
-       u32 val;
-
-       v4l2_dbg(1, debug, &state->mipi_sd, "fmt: %#x, %d x %d\n",
-                mf->code, mf->width, mf->height);
-
-       /* Color format */
-       val = mipi_csis_read(state, MIPI_CSIS_ISPCONFIG_CH0);
-       val = (val & ~MIPI_CSIS_ISPCFG_FMT_MASK) | state->csis_fmt->fmt_reg;
-       mipi_csis_write(state, MIPI_CSIS_ISPCONFIG_CH0, val);
-
-       /* Pixel resolution */
-       val = mf->width | (mf->height << 16);
-       mipi_csis_write(state, MIPI_CSIS_ISPRESOL_CH0, val);
-}
-
-static void mipi_csis_set_hsync_settle(struct csi_state *state,
-                                                               int hs_settle, int clk_settle)
-{
-       u32 val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL);
-
-       val = (val & ~MIPI_CSIS_DPHYCTRL_HSS_MASK) |
-                               (hs_settle << 24) | (clk_settle << 22);
-
-       mipi_csis_write(state, MIPI_CSIS_DPHYCTRL, val);
-}
-
-static void mipi_csis_set_params(struct csi_state *state)
-{
-       u32 val;
-
-       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-       val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
-       val |= (state->num_lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
-       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
-
-       __mipi_csis_set_format(state);
-
-       mipi_csis_set_hsync_settle(state, state->hs_settle, state->clk_settle);
-
-       val = mipi_csis_read(state, MIPI_CSIS_ISPCONFIG_CH0);
-       if (state->csis_fmt->data_alignment == 32)
-               val |= MIPI_CSIS_ISPCFG_ALIGN_32BIT;
-       else /* Normal output */
-               val &= ~MIPI_CSIS_ISPCFG_ALIGN_32BIT;
-       mipi_csis_write(state, MIPI_CSIS_ISPCONFIG_CH0, val);
-
-       val = (0 << MIPI_CSIS_ISPSYNC_HSYNC_LINTV_OFFSET) |
-               (0 << MIPI_CSIS_ISPSYNC_VSYNC_SINTV_OFFSET) |
-               (0 << MIPI_CSIS_ISPSYNC_VSYNC_EINTV_OFFSET);
-       mipi_csis_write(state, MIPI_CSIS_ISPSYNC_CH0, val);
-
-       val = mipi_csis_read(state, MIPI_CSIS_CLK_CTRL);
-       val &= ~MIPI_CSIS_CLK_CTRL_WCLK_SRC;
-       if (state->wclk_ext)
-               val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC;
-       val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15);
-       val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK;
-       mipi_csis_write(state, MIPI_CSIS_CLK_CTRL, val);
-
-       mipi_csis_write(state, MIPI_CSIS_DPHYBCTRL_L, 0x1f4);
-       mipi_csis_write(state, MIPI_CSIS_DPHYBCTRL_H, 0);
-
-       /* Update the shadow register. */
-       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW |
-                                       MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL);
-}
-
-static void mipi_csis_clk_enable(struct csi_state *state)
-{
-       clk_prepare_enable(state->mipi_clk);
-       clk_prepare_enable(state->phy_clk);
-}
-
-static void mipi_csis_clk_disable(struct csi_state *state)
-{
-       clk_disable_unprepare(state->mipi_clk);
-       clk_disable_unprepare(state->phy_clk);
-}
-
-static int mipi_csis_clk_get(struct csi_state *state)
-{
-       struct device *dev = &state->pdev->dev;
-       int ret = true;
-
-       state->mipi_clk = devm_clk_get(dev, "mipi_clk");
-       if (IS_ERR(state->mipi_clk)) {
-               dev_err(dev, "Could not get mipi csi clock\n");
-               return -ENODEV;
-       }
-
-       state->phy_clk = devm_clk_get(dev, "phy_clk");
-       if (IS_ERR(state->phy_clk)) {
-               dev_err(dev, "Could not get mipi phy clock\n");
-               return -ENODEV;
-       }
-
-       /* Set clock rate */
-       if (state->clk_frequency)
-               ret = clk_set_rate(state->mipi_clk,
-                                  state->clk_frequency);
-       else
-               dev_WARN(dev, "No clock frequency specified!\n");
-       if (ret < 0) {
-               dev_err(dev, "set rate filed, rate=%d\n", state->clk_frequency);
-               return -EINVAL;
-       }
-
-       return ret;
-}
-
-static void dump_regs(struct csi_state *state, const char *label)
-{
-       struct {
-               u32 offset;
-               const char * const name;
-       } registers[] = {
-               { 0x00, "CTRL" },
-               { 0x04, "DPHYCTRL" },
-               { 0x08, "CONFIG" },
-               { 0x0c, "DPHYSTS" },
-               { 0x10, "INTMSK" },
-               { 0x2c, "RESOL" },
-               { 0x38, "SDW_CONFIG" },
-       };
-       u32 i;
-
-       v4l2_info(&state->mipi_sd, "--- %s ---\n", label);
-
-       for (i = 0; i < ARRAY_SIZE(registers); i++) {
-               u32 cfg = mipi_csis_read(state, registers[i].offset);
-               v4l2_info(&state->mipi_sd, "%10s: 0x%08x\n", registers[i].name, cfg);
-       }
-}
-
-static void mipi_csis_start_stream(struct csi_state *state)
-{
-       mipi_csis_sw_reset(state);
-       mipi_csis_set_params(state);
-       mipi_csis_system_enable(state, true);
-       mipi_csis_enable_interrupts(state, true);
-}
-
-static void mipi_csis_stop_stream(struct csi_state *state)
-{
-       mipi_csis_enable_interrupts(state, false);
-       mipi_csis_system_enable(state, false);
-}
-
-static void mipi_csis_clear_counters(struct csi_state *state)
-{
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&state->slock, flags);
-       for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++)
-               state->events[i].counter = 0;
-       spin_unlock_irqrestore(&state->slock, flags);
-}
-
-static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
-{
-       int i = non_errors ? MIPI_CSIS_NUM_EVENTS : MIPI_CSIS_NUM_EVENTS - 4;
-       unsigned long flags;
-
-       spin_lock_irqsave(&state->slock, flags);
-
-       for (i--; i >= 0; i--) {
-               if (state->events[i].counter > 0 || debug)
-                       v4l2_info(&state->mipi_sd, "%s events: %d\n",
-                                 state->events[i].name,
-                                 state->events[i].counter);
-       }
-       spin_unlock_irqrestore(&state->slock, flags);
-}
-
-/*
- * V4L2 subdev operations
- */
-static int mipi_csis_s_power(struct v4l2_subdev *mipi_sd, int on)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       struct device *dev = &state->pdev->dev;
-
-       v4l2_subdev_call(state->sensor_sd, core, s_power, on);
-
-       if (on)
-               return pm_runtime_get_sync(dev);
-
-       return pm_runtime_put_sync(dev);
-}
-
-static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       int ret = 0;
-
-       v4l2_dbg(1, debug, mipi_sd, "%s: %d, state: 0x%x\n",
-                __func__, enable, state->flags);
-
-       if (enable) {
-               mipi_csis_clear_counters(state);
-               ret = pm_runtime_get_sync(&state->pdev->dev);
-               if (ret && ret != 1)
-                       return ret;
-       }
-
-       mutex_lock(&state->lock);
-       if (enable) {
-               if (state->flags & ST_SUSPENDED) {
-                       ret = -EBUSY;
-                       goto unlock;
-               }
-               mipi_csis_start_stream(state);
-               v4l2_subdev_call(state->sensor_sd, video, s_stream, true);
-               state->flags |= ST_STREAMING;
-       } else {
-               v4l2_subdev_call(state->sensor_sd, video, s_stream, false);
-               mipi_csis_stop_stream(state);
-               state->flags &= ~ST_STREAMING;
-               if (debug > 0)
-                       mipi_csis_log_counters(state, true);
-       }
-unlock:
-       mutex_unlock(&state->lock);
-       if (!enable)
-               pm_runtime_put(&state->pdev->dev);
-
-       return ret == 1 ? 0 : ret;
-}
-
-static int mipi_csis_enum_mbus_code(struct v4l2_subdev *mipi_sd,
-                                   struct v4l2_subdev_pad_config *cfg,
-                                   struct v4l2_subdev_mbus_code_enum *code)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       struct v4l2_subdev *sensor_sd = state->sensor_sd;
-       struct csis_pix_format const *csis_fmt;
-       int ret;
-
-       ret = v4l2_subdev_call(sensor_sd, pad, enum_mbus_code, NULL, code);
-       if (ret < 0)
-               return -EINVAL;
-
-       csis_fmt = find_csis_format(code->code);
-       if (csis_fmt == NULL) {
-               dev_err(state->dev, "format not match\n");
-               return -EINVAL;
-       }
-
-       return ret;
-}
-
-static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
-                            struct v4l2_subdev_pad_config *cfg,
-                            struct v4l2_subdev_format *format)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       struct v4l2_subdev *sensor_sd = state->sensor_sd;
-       struct csis_pix_format const *csis_fmt;
-       struct v4l2_mbus_framefmt *mf  = &format->format;
-
-       if (format->pad)
-               return -EINVAL;
-
-       csis_fmt = find_csis_format(mf->code);
-       if (csis_fmt == NULL)
-               csis_fmt = &mipi_csis_formats[0];
-
-       v4l2_subdev_call(sensor_sd, pad, set_fmt, NULL, format);
-
-       mf->code = csis_fmt->code;
-       v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
-                             csis_fmt->pix_width_alignment,
-                             &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
-                             0);
-
-       if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-               return 0;
-
-       state->format.code = mf->code;
-       state->format.width = mf->width;
-       state->format.height = mf->height;
-
-       mutex_lock(&state->lock);
-       state->csis_fmt = csis_fmt;
-       mutex_unlock(&state->lock);
-
-       return 0;
-}
-
-static int mipi_csis_get_fmt(struct v4l2_subdev *mipi_sd,
-                            struct v4l2_subdev_pad_config *cfg,
-                            struct v4l2_subdev_format *format)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       struct v4l2_subdev *sensor_sd = state->sensor_sd;
-
-       if (format->pad)
-               return -EINVAL;
-
-       return v4l2_subdev_call(sensor_sd, pad, get_fmt, NULL, format);
-}
-
-static int mipi_csis_s_rx_buffer(struct v4l2_subdev *mipi_sd, void *buf,
-                              unsigned int *size)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       unsigned long flags;
-
-       *size = min_t(unsigned int, *size, MIPI_CSIS_PKTDATA_SIZE);
-
-       spin_lock_irqsave(&state->slock, flags);
-       state->pkt_buf.data = buf;
-       state->pkt_buf.len = *size;
-       spin_unlock_irqrestore(&state->slock, flags);
-
-       return 0;
-}
-
-static int mipi_csis_s_parm(struct v4l2_subdev *mipi_sd, struct v4l2_streamparm *a)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       struct v4l2_subdev *sensor_sd = state->sensor_sd;
-
-       return v4l2_subdev_call(sensor_sd, video, s_parm, a);
-}
-
-static int mipi_csis_g_parm(struct v4l2_subdev *mipi_sd, struct v4l2_streamparm *a)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       struct v4l2_subdev *sensor_sd = state->sensor_sd;
-
-       return v4l2_subdev_call(sensor_sd, video, g_parm, a);
-}
-
-static int mipi_csis_enum_framesizes(struct v4l2_subdev *mipi_sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_frame_size_enum *fse)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       struct v4l2_subdev *sensor_sd = state->sensor_sd;
-
-       return v4l2_subdev_call(sensor_sd, pad, enum_frame_size, NULL, fse);
-}
-
-static int mipi_csis_enum_frameintervals(struct v4l2_subdev *mipi_sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_frame_interval_enum *fie)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-       struct v4l2_subdev *sensor_sd = state->sensor_sd;
-
-       return v4l2_subdev_call(sensor_sd, pad, enum_frame_interval, NULL, fie);
-}
-
-static int mipi_csis_log_status(struct v4l2_subdev *mipi_sd)
-{
-       struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
-
-       mutex_lock(&state->lock);
-       mipi_csis_log_counters(state, true);
-       if (debug && (state->flags & ST_POWERED))
-               dump_regs(state, __func__);
-       mutex_unlock(&state->lock);
-       return 0;
-}
-
-static struct v4l2_subdev_core_ops mipi_csis_core_ops = {
-       .s_power = mipi_csis_s_power,
-       .log_status = mipi_csis_log_status,
-};
-
-static struct v4l2_subdev_video_ops mipi_csis_video_ops = {
-       .s_rx_buffer = mipi_csis_s_rx_buffer,
-       .s_stream = mipi_csis_s_stream,
-
-       .s_parm = mipi_csis_s_parm,
-       .g_parm = mipi_csis_g_parm,
-};
-
-static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = {
-       .enum_frame_size       = mipi_csis_enum_framesizes,
-       .enum_frame_interval   = mipi_csis_enum_frameintervals,
-       .enum_mbus_code        = mipi_csis_enum_mbus_code,
-       .get_fmt               = mipi_csis_get_fmt,
-       .set_fmt               = mipi_csis_set_fmt,
-};
-
-static struct v4l2_subdev_ops mipi_csis_subdev_ops = {
-       .core = &mipi_csis_core_ops,
-       .video = &mipi_csis_video_ops,
-       .pad = &mipi_csis_pad_ops,
-};
-
-static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
-{
-       struct csi_state *state = dev_id;
-       struct csis_pktbuf *pktbuf = &state->pkt_buf;
-       unsigned long flags;
-       u32 status;
-
-       status = mipi_csis_read(state, MIPI_CSIS_INTSRC);
-
-       spin_lock_irqsave(&state->slock, flags);
-
-       if ((status & MIPI_CSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
-               u32 offset;
-
-               if (status & MIPI_CSIS_INTSRC_EVEN)
-                       offset = MIPI_CSIS_PKTDATA_EVEN;
-               else
-                       offset = MIPI_CSIS_PKTDATA_ODD;
-
-               memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
-               pktbuf->data = NULL;
-               rmb();
-       }
-
-       /* Update the event/error counters */
-       if ((status & MIPI_CSIS_INTSRC_ERRORS) || debug) {
-               int i;
-               for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) {
-                       if (!(status & state->events[i].mask))
-                               continue;
-                       state->events[i].counter++;
-                       v4l2_dbg(2, debug, &state->mipi_sd, "%s: %d\n",
-                                state->events[i].name,
-                                state->events[i].counter);
-               }
-               v4l2_dbg(2, debug, &state->mipi_sd, "status: %08x\n", status);
-       }
-       spin_unlock_irqrestore(&state->slock, flags);
-
-       mipi_csis_write(state, MIPI_CSIS_INTSRC, status);
-       return IRQ_HANDLED;
-}
-
-static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
-                           struct v4l2_subdev *subdev,
-                           struct v4l2_async_subdev *asd)
-{
-       struct csi_state *state = notifier_to_mipi_dev(notifier);
-
-       /* Find platform data for this sensor subdev */
-       if (state->asd.match.of.node == subdev->dev->of_node)
-               state->sensor_sd = subdev;
-
-       if (subdev == NULL)
-               return -EINVAL;
-
-       v4l2_info(&state->v4l2_dev, "Registered sensor subdevice: %s\n",
-                 subdev->name);
-
-       return 0;
-}
-
-static int mipi_csis_parse_dt(struct platform_device *pdev,
-                           struct csi_state *state)
-{
-       struct device_node *node = pdev->dev.of_node;
-
-       if (of_property_read_u32(node, "clock-frequency",
-                                &state->clk_frequency))
-               state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
-       if (of_property_read_u32(node, "bus-width",
-                                &state->max_num_lanes))
-               return -EINVAL;
-
-       node = of_graph_get_next_endpoint(node, NULL);
-       if (!node) {
-               dev_err(&pdev->dev, "No port node at %s\n",
-                               pdev->dev.of_node->full_name);
-               return -EINVAL;
-       }
-
-       /* Get MIPI CSI-2 bus configration from the endpoint node. */
-       of_property_read_u32(node, "csis-hs-settle",
-                                       &state->hs_settle);
-
-       of_property_read_u32(node, "csis-clk-settle",
-                                       &state->clk_settle);
-       state->wclk_ext = of_property_read_bool(node,
-                                       "csis-wclk");
-
-       of_property_read_u32(node, "data-lanes",
-                                       &state->num_lanes);
-       of_node_put(node);
-
-       return 0;
-}
-
-static int mipi_csis_pm_resume(struct device *dev, bool runtime);
-static const struct of_device_id mipi_csis_of_match[];
-
-/* register parent dev */
-static int mipi_csis_subdev_host(struct csi_state *state)
-{
-       struct device_node *parent = state->dev->of_node;
-       struct device_node *node, *port, *rem;
-       int ret;
-
-       /* Attach sensors linked to csi receivers */
-       for_each_available_child_of_node(parent, node) {
-               if (of_node_cmp(node->name, "port"))
-                       continue;
-
-               /* The csi node can have only port subnode. */
-               port = of_get_next_child(node, NULL);
-               if (!port)
-                       continue;
-               rem = of_graph_get_remote_port_parent(port);
-               of_node_put(port);
-               if (rem == NULL) {
-                       v4l2_info(&state->v4l2_dev,
-                                               "Remote device at %s not found\n",
-                                               port->full_name);
-                       return -1;
-               }
-
-               state->asd.match_type = V4L2_ASYNC_MATCH_OF;
-               state->asd.match.of.node = rem;
-               state->async_subdevs[0] = &state->asd;
-
-               of_node_put(rem);
-               break;
-       }
-
-       state->subdev_notifier.subdevs = state->async_subdevs;
-       state->subdev_notifier.num_subdevs = 1;
-       state->subdev_notifier.bound = subdev_notifier_bound;
-
-       ret = v4l2_async_notifier_register(&state->v4l2_dev,
-                                       &state->subdev_notifier);
-       if (ret)
-               dev_err(state->dev,
-                                       "Error register async notifier regoster\n");
-
-       return ret;
-}
-
-/* init subdev */
-static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
-               struct platform_device *pdev,
-               const struct v4l2_subdev_ops *ops)
-{
-       struct csi_state *state = platform_get_drvdata(pdev);
-       int ret = 0;
-
-       v4l2_subdev_init(mipi_sd, ops);
-       mipi_sd->owner = THIS_MODULE;
-       snprintf(mipi_sd->name, sizeof(mipi_sd->name), "%s.%d",
-                CSIS_SUBDEV_NAME, state->index);
-       mipi_sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-       mipi_sd->dev = &pdev->dev;
-
-       state->csis_fmt = &mipi_csis_formats[0];
-       state->format.code = mipi_csis_formats[0].code;
-       state->format.width = MIPI_CSIS_DEF_PIX_WIDTH;
-       state->format.height = MIPI_CSIS_DEF_PIX_HEIGHT;
-
-       /* This allows to retrieve the platform device id by the host driver */
-       v4l2_set_subdevdata(mipi_sd, pdev);
-
-       ret = v4l2_async_register_subdev(mipi_sd);
-       if (ret < 0)
-               dev_err(&pdev->dev, "%s--Async register faialed, ret=%d\n", __func__, ret);
-
-       return ret;
-}
-
-static int mipi_csis_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct v4l2_subdev *mipi_sd;
-       struct resource *mem_res;
-       struct csi_state *state;
-       int ret = -ENOMEM;
-
-       state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
-       if (!state)
-               return -ENOMEM;
-
-       mutex_init(&state->lock);
-       spin_lock_init(&state->slock);
-
-       state->pdev = pdev;
-       mipi_sd = &state->mipi_sd;
-       state->dev = dev;
-
-       ret = mipi_csis_parse_dt(pdev, state);
-       if (ret < 0)
-               return ret;
-
-       if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
-               dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
-                       state->num_lanes, state->max_num_lanes);
-               return -EINVAL;
-       }
-
-       mipi_csis_phy_init(state);
-       mipi_csis_phy_reset(state);
-
-       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       state->regs = devm_ioremap_resource(dev, mem_res);
-       if (IS_ERR(state->regs))
-               return PTR_ERR(state->regs);
-
-       state->irq = platform_get_irq(pdev, 0);
-       if (state->irq < 0) {
-               dev_err(dev, "Failed to get irq\n");
-               return state->irq;
-       }
-
-       ret = mipi_csis_clk_get(state);
-       if (ret < 0)
-               return ret;
-
-       mipi_csis_clk_enable(state);
-
-       ret = devm_request_irq(dev, state->irq, mipi_csis_irq_handler,
-                              0, dev_name(dev), state);
-       if (ret) {
-               dev_err(dev, "Interrupt request failed\n");
-               goto e_clkdis;
-       }
-
-       /* First register a v4l2 device */
-       ret = v4l2_device_register(dev, &state->v4l2_dev);
-       if (ret) {
-               v4l2_err(dev->driver,
-                       "Unable to register v4l2 device.\n");
-               goto e_clkdis;
-       }
-       v4l2_info(&state->v4l2_dev, "mipi csi v4l2 device registered\n");
-
-       /* .. and a pointer to the subdev. */
-       platform_set_drvdata(pdev, state);
-
-       ret = mipi_csis_subdev_init(&state->mipi_sd, pdev, &mipi_csis_subdev_ops);
-       if (ret < 0)
-               goto e_sd_mipi;
-
-       memcpy(state->events, mipi_csis_events, sizeof(state->events));
-
-       /* subdev host register */
-       ret = mipi_csis_subdev_host(state);
-       if (ret < 0)
-               goto e_sd_host;
-
-       pm_runtime_enable(dev);
-       if (!pm_runtime_enabled(dev)) {
-               ret = mipi_csis_pm_resume(dev, true);
-               if (ret < 0)
-                       goto e_sd_host;
-       }
-
-       dev_info(&pdev->dev,
-                       "lanes: %d, hs_settle: %d, clk_settle: %d, wclk: %d, freq: %u\n",
-                state->num_lanes, state->hs_settle, state->clk_settle,
-                state->wclk_ext, state->clk_frequency);
-       return 0;
-
-e_sd_host:
-       v4l2_async_notifier_unregister(&state->subdev_notifier);
-       v4l2_device_unregister(&state->v4l2_dev);
-e_sd_mipi:
-       v4l2_async_unregister_subdev(&state->mipi_sd);
-e_clkdis:
-       mipi_csis_clk_disable(state);
-       return ret;
-}
-
-static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct csi_state *state = platform_get_drvdata(pdev);
-       struct v4l2_subdev *mipi_sd = &state->mipi_sd;
-       int ret = 0;
-
-       v4l2_dbg(1, debug, mipi_sd, "%s: flags: 0x%x\n",
-                __func__, state->flags);
-
-       mutex_lock(&state->lock);
-       if (state->flags & ST_POWERED) {
-               mipi_csis_stop_stream(state);
-               ret = regulator_disable(state->mipi_phy_regulator);
-               if (ret)
-                       goto unlock;
-               mipi_csis_clk_disable(state);
-               state->flags &= ~ST_POWERED;
-               if (!runtime)
-                       state->flags |= ST_SUSPENDED;
-       }
- unlock:
-       mutex_unlock(&state->lock);
-       return ret ? -EAGAIN : 0;
-}
-
-static int mipi_csis_pm_resume(struct device *dev, bool runtime)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct csi_state *state = platform_get_drvdata(pdev);
-       struct v4l2_subdev *mipi_sd = &state->mipi_sd;
-       int ret = 0;
-
-       v4l2_dbg(1, debug, mipi_sd, "%s: flags: 0x%x\n",
-                __func__, state->flags);
-
-       mutex_lock(&state->lock);
-       if (!runtime && !(state->flags & ST_SUSPENDED))
-               goto unlock;
-
-       if (!(state->flags & ST_POWERED)) {
-               ret = regulator_enable(state->mipi_phy_regulator);
-               if (!ret) {
-                       state->flags |= ST_POWERED;
-               } else {
-                       goto unlock;
-               }
-               mipi_csis_clk_enable(state);
-       }
-       if (state->flags & ST_STREAMING)
-               mipi_csis_start_stream(state);
-
-       state->flags &= ~ST_SUSPENDED;
- unlock:
-       mutex_unlock(&state->lock);
-       return ret ? -EAGAIN : 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int mipi_csis_suspend(struct device *dev)
-{
-       return mipi_csis_pm_suspend(dev, false);
-}
-
-static int mipi_csis_resume(struct device *dev)
-{
-       return mipi_csis_pm_resume(dev, false);
-}
-#endif
-
-static int mipi_csis_runtime_suspend(struct device *dev)
-{
-       return mipi_csis_pm_suspend(dev, true);
-}
-
-static int mipi_csis_runtime_resume(struct device *dev)
-{
-       return mipi_csis_pm_resume(dev, true);
-}
-
-static int mipi_csis_remove(struct platform_device *pdev)
-{
-       struct csi_state *state = platform_get_drvdata(pdev);
-
-       v4l2_async_unregister_subdev(&state->mipi_sd);
-       v4l2_async_notifier_unregister(&state->subdev_notifier);
-       v4l2_device_unregister(&state->v4l2_dev);
-
-       pm_runtime_disable(&pdev->dev);
-       mipi_csis_pm_suspend(&pdev->dev, true);
-       mipi_csis_clk_disable(state);
-       pm_runtime_set_suspended(&pdev->dev);
-
-       return 0;
-}
-
-static const struct dev_pm_ops mipi_csis_pm_ops = {
-       SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume,
-                          NULL)
-       SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume)
-};
-
-static const struct of_device_id mipi_csis_of_match[] = {
-       {       .compatible = "fsl,imx7d-mipi-csi",},
-       { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
-
-static struct platform_driver mipi_csis_driver = {
-       .probe          = mipi_csis_probe,
-       .remove         = mipi_csis_remove,
-       .driver         = {
-               .of_match_table = mipi_csis_of_match,
-               .name           = CSIS_DRIVER_NAME,
-               .owner          = THIS_MODULE,
-               .pm             = &mipi_csis_pm_ops,
-       },
-};
-
-module_platform_driver(mipi_csis_driver);
-
-MODULE_DESCRIPTION("Freescale MIPI-CSI2 receiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/subdev/mxc_vadc.c b/drivers/media/platform/mxc/subdev/mxc_vadc.c
deleted file mode 100644 (file)
index 2a844ca..0000000
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * 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.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/media-bus-format.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include "mxc_vadc.h"
-
-/* Resource names for the VADC driver. */
-#define VAFE_REGS_ADDR_RES_NAME "vadc-vafe"
-#define VDEC_REGS_ADDR_RES_NAME "vadc-vdec"
-
-#define reg32_write(addr, val) __raw_writel(val, addr)
-#define reg32_read(addr)       __raw_readl(addr)
-#define reg32setbit(addr, bitpos) \
-       reg32_write((addr), (reg32_read((addr)) | (1<<(bitpos))))
-
-#define reg32clrbit(addr, bitpos) \
-       reg32_write((addr), (reg32_read((addr)) & (0xFFFFFFFF ^ (1<<(bitpos)))))
-
-#define GPC_CNTR               0x00
-#define IMX6SX_GPC_CNTR_VADC_ANALOG_OFF_MASK   BIT(17)
-#define IMX6SX_GPC_CNTR_VADC_POWER_DOWN_MASK   BIT(18)
-
-void __iomem *vafe_regbase;
-void __iomem *vdec_regbase;
-
-
-/* List of input video formats supported. The video formats is corresponding
- * with v4l2 id in video_fmt
- */
-enum video_fmt_idx {
-       VADC_NTSC = 0,  /* Locked on (M) NTSC video signal. */
-       VADC_PAL,               /* (B, G, H, I, N)PAL video signal. */
-};
-
-/* Number of video standards supported (including 'not locked' signal). */
-#define VADC_STD_MAX           (VADC_PAL + 1)
-
-/* Video format structure. */
-struct video_fmt{
-       v4l2_std_id  v4l2_std;  /* Video for linux ID. */
-       char name[16];          /* Name (e.g., "NTSC", "PAL", etc.) */
-       u16 raw_width;          /* Raw width. */
-       u16 raw_height;         /* Raw height. */
-       u16 active_width;       /* Active width. */
-       u16 active_height;      /* Active height. */
-       u16 framerates;
-};
-
-/*
- * Maintains the information on the current state of the sensor.
- */
-struct vadc_state {
-       struct v4l2_device v4l2_dev;
-       struct v4l2_subdev sd;
-       struct video_fmt *fmt;
-
-       struct clk *vadc_clk;
-       struct clk *csi_clk;
-       struct regmap *gpr;
-       void __iomem *gpc_reg;
-
-       u32 vadc_in;
-       u32 csi_id;
-};
-
-static int vadc_querystd(struct v4l2_subdev *sd, v4l2_std_id *std);
-
-/* Description of video formats supported.
- *
- *  PAL: raw=720x625, active=720x576.
- *  NTSC: raw=720x525, active=720x480.
- */
-static struct video_fmt video_fmts[] = {
-       /* NTSC */
-       {
-        .v4l2_std = V4L2_STD_NTSC,
-        .name = "NTSC",
-        .raw_width = 720,
-        .raw_height = 525,
-        .active_width = 720,
-        .active_height = 480,
-        .framerates = 30,
-        },
-       /* (B, G, H, I, N) PAL */
-       {
-        .v4l2_std = V4L2_STD_PAL,
-        .name = "PAL",
-        .raw_width = 720,
-        .raw_height = 625,
-        .active_width = 720,
-        .active_height = 576,
-        .framerates = 25,
-        },
-};
-
-static void afe_voltage_clampingmode(void)
-{
-       reg32_write(AFE_CLAMP, 0x07);
-       reg32_write(AFE_CLMPAMP, 0x60);
-       reg32_write(AFE_CLMPDAT, 0xF0);
-}
-
-static void afe_alwayson_clampingmode(void)
-{
-       reg32_write(AFE_CLAMP, 0x15);
-       reg32_write(AFE_CLMPDAT, 0x08);
-       reg32_write(AFE_CLMPAMP, 0x00);
-}
-
-static void afe_init(void)
-{
-       pr_debug("%s\n", __func__);
-
-       reg32_write(AFE_PDBUF, 0x1f);
-       reg32_write(AFE_PDADC, 0x0f);
-       reg32_write(AFE_PDSARH, 0x01);
-       reg32_write(AFE_PDSARL, 0xff);
-       reg32_write(AFE_PDADCRFH, 0x01);
-       reg32_write(AFE_PDADCRFL, 0xff);
-       reg32_write(AFE_ICTRL, 0x3a);
-       reg32_write(AFE_ICTLSTG, 0x1e);
-
-       reg32_write(AFE_RCTRLSTG, 0x1e);
-       reg32_write(AFE_INPBUF, 0x035);
-       reg32_write(AFE_INPFLT, 0x02);
-       reg32_write(AFE_ADCDGN, 0x40);
-       reg32_write(AFE_TSTSEL, 0x10);
-
-       reg32_write(AFE_ACCTST, 0x07);
-
-       reg32_write(AFE_BGREG, 0x08);
-
-       reg32_write(AFE_ADCGN, 0x09);
-
-       /* set current controlled clamping
-       * always on, low current */
-       reg32_write(AFE_CLAMP, 0x11);
-       reg32_write(AFE_CLMPAMP, 0x08);
-}
-
-static void vdec_mode_timing_init(int std)
-{
-       if (std == V4L2_STD_NTSC) {
-               /* NTSC 720x480 */
-               reg32_write(VDEC_HACTS, 0x66);
-               reg32_write(VDEC_HACTE, 0x24);
-
-               reg32_write(VDEC_VACTS, 0x29);
-               reg32_write(VDEC_VACTE, 0x04);
-
-               /* set V Position */
-               reg32_write(VDEC_VRTPOS, 0x2);
-       } else if (std == V4L2_STD_PAL) {
-               /* PAL 720x576 */
-               reg32_write(VDEC_HACTS, 0x66);
-               reg32_write(VDEC_HACTE, 0x24);
-
-               reg32_write(VDEC_VACTS, 0x29);
-               reg32_write(VDEC_VACTE, 0x04);
-
-               /* set V Position */
-               reg32_write(VDEC_VRTPOS, 0x6);
-       } else
-               pr_debug("Error not support video mode\n");
-
-       /* set H Position */
-       reg32_write(VDEC_HZPOS, 0x60);
-
-       /* set H ignore start */
-       reg32_write(VDEC_HSIGS, 0xf8);
-
-       /* set H ignore end */
-       reg32_write(VDEC_HSIGE, 0x18);
-}
-
-/*
-* vdec_init()
-* Initialises the VDEC registers
-* Returns: nothing
-*/
-static void vdec_init(struct vadc_state *vadc)
-{
-       v4l2_std_id std;
-
-       pr_debug("%s\n", __func__);
-
-       /* Get work mode PAL or NTSC */
-       vadc_querystd(&vadc->sd, &std);
-
-       vdec_mode_timing_init(std);
-
-       /* vcr detect threshold high, automatic detections */
-       reg32_write(VDEC_VSCON2, 0);
-
-       reg32_write(VDEC_BASE + 0x110, 0x01);
-
-       /* set the noramp mode on the Hloop PLL. */
-       reg32_write(VDEC_BASE+(0x14*4), 0x10);
-
-       /* set the YC relative delay.*/
-       reg32_write(VDEC_YCDEL, 0x90);
-
-       /* setup the Hpll */
-       reg32_write(VDEC_BASE+(0x13*4), 0x13);
-
-       /* setup the 2d comb */
-       /* set the gain of the Hdetail output to 3
-        * set the notch alpha gain to 1 */
-       reg32_write(VDEC_CFC2, 0x34);
-
-       /* setup various 2d comb bits.*/
-       reg32_write(VDEC_BASE+(0x02*4), 0x01);
-       reg32_write(VDEC_BASE+(0x03*4), 0x18);
-       reg32_write(VDEC_BASE+(0x04*4), 0x34);
-
-       /* set the start of the burst gate */
-       reg32_write(VDEC_BRSTGT, 0x30);
-
-       /* set 1f motion gain */
-       reg32_write(VDEC_BASE+(0x0f*4), 0x20);
-
-       /* set the 1F chroma motion detector thresh
-        * for colour reverse detection */
-       reg32_write(VDEC_THSH1, 0x02);
-       reg32_write(VDEC_BASE+(0x4a*4), 0x20);
-       reg32_write(VDEC_BASE+(0x4b*4), 0x08);
-
-       reg32_write(VDEC_BASE+(0x4c*4), 0x08);
-
-       /* set the threshold for the narrow/wide adaptive chroma BW */
-       reg32_write(VDEC_BASE+(0x20*4), 0x20);
-
-       /* turn up the colour with the new colour gain reg */
-       /* hue: */
-       reg32_write(VDEC_HUE, 0x00);
-
-       /* cbgain: 22 B4 */
-       reg32_write(VDEC_CBGN, 0xb4);
-       /* cr gain 80 */
-       reg32_write(VDEC_CRGN, 0x80);
-       /* luma gain (contrast) */
-       reg32_write(VDEC_CNTR, 0x80);
-
-       /* setup the signed black level register, brightness */
-       reg32_write(VDEC_BRT, 0x00);
-
-       /* filter the standard detection
-        * enable the comb for the ntsc443 */
-       reg32_write(VDEC_STDDBG, 0x20);
-
-       /* setup chroma kill thresh for no chroma */
-       reg32_write(VDEC_CHBTH, 0x0);
-
-       /* set chroma loop to wider BW
-        * no set it to normal BW. i fixed the bw problem.*/
-       reg32_write(VDEC_YCDEL, 0x00);
-
-       /* set the compensation in the chroma loop for the Hloop
-        * set the ratio for the nonarithmetic 3d comb modes.*/
-       reg32_write(VDEC_BASE + (0x1d*4), 0x90);
-
-       /* set the threshold for the nonarithmetic mode for the 2d comb
-        * the higher the value the more Fc Fh offset
-        * we will tolerate before turning off the comb. */
-       reg32_write(VDEC_BASE + (0x33*4), 0xa0);
-
-       /* setup the bluescreen output colour */
-       reg32_write(VDEC_BASE + (0x3d*4), 35);
-       reg32_write(VDEC_BLSCRCR, 114);
-       reg32_write(VDEC_BLSCRCB, 212);
-
-       /* disable the active blanking */
-       reg32_write(VDEC_BASE + (0x15*4), 0x02);
-
-       /* setup the luma agc for automatic gain. */
-       reg32_write(VDEC_LMAGC2, 0x5e);
-       reg32_write(VDEC_LMAGC1, 0x81);
-
-       /* setup chroma agc */
-       reg32_write(VDEC_CHAGC2, 0xa0);
-       reg32_write(VDEC_CHAGC1, 0x01);
-
-       /* setup the MV thresh lower nibble
-        * setup the sync top cap, upper nibble */
-       reg32_write(VDEC_BASE + (0x3a*4), 0x80);
-       reg32_write(VDEC_SHPIMP, 0x00);
-
-       /* setup the vsync block */
-       reg32_write(VDEC_VSCON1, 0x87);
-
-       /* set the nosignal threshold
-        * set the vsync threshold */
-       reg32_write(VDEC_VSSGTH, 0x35);
-
-       /* set length for min hphase filter
-        * (or saturate limit if saturate is chosen) */
-       reg32_write(VDEC_BASE + (0x45*4), 0x40);
-
-       /* enable the internal resampler,
-        * select min filter not saturate for
-        * hphase noise filter for vcr detect.
-        * enable vcr pause mode different field lengths */
-       reg32_write(VDEC_BASE + (0x46*4), 0x90);
-
-       /* disable VCR detection, lock to the Hsync rather than the Vsync */
-       reg32_write(VDEC_VSCON2, 0x04);
-
-       /* set tiplevel goal for dc clamp. */
-       reg32_write(VDEC_BASE + (0x3c*4), 0xB0);
-
-       /* override SECAM detection and force SECAM off */
-       reg32_write(VDEC_BASE + (0x2f*4), 0x20);
-
-       /* Set r3d_hardblend in 3D control2 reg */
-       reg32_write(VDEC_BASE + (0x0c*4), 0x04);
-}
-
-/* set Input selector & input pull-downs */
-static void vadc_s_routing(int vadc_in)
-{
-       switch (vadc_in) {
-       case 0:
-               reg32_write(AFE_INPFLT, 0x02);
-               reg32_write(AFE_OFFDRV, 0x00);
-               reg32_write(AFE_INPCONFIG, 0x1e);
-               break;
-       case 1:
-               reg32_write(AFE_INPFLT, 0x02);
-               reg32_write(AFE_OFFDRV, 0x00);
-               reg32_write(AFE_INPCONFIG, 0x2d);
-               break;
-       case 2:
-               reg32_write(AFE_INPFLT, 0x02);
-               reg32_write(AFE_OFFDRV, 0x00);
-               reg32_write(AFE_INPCONFIG, 0x4b);
-               break;
-       case 3:
-               reg32_write(AFE_INPFLT, 0x02);
-               reg32_write(AFE_OFFDRV, 0x00);
-               reg32_write(AFE_INPCONFIG, 0x87);
-               break;
-       default:
-               pr_debug("error video input %d\n", vadc_in);
-       }
-}
-
-static void vadc_power_up(struct vadc_state *state)
-{
-       /* Power on vadc analog */
-       reg32clrbit(state->gpc_reg + GPC_CNTR, 17);
-
-       /* Power down vadc ext power */
-       reg32clrbit(state->gpc_reg + GPC_CNTR, 18);
-
-       /* software reset afe  */
-       regmap_update_bits(state->gpr, IOMUXC_GPR1,
-                       IMX6SX_GPR1_VADC_SW_RST_MASK,
-                       IMX6SX_GPR1_VADC_SW_RST_RESET);
-
-       msleep(10);
-
-       /* clock config for vadc */
-       reg32_write(VDEC_BASE + 0x320, 0xe3);
-       reg32_write(VDEC_BASE + 0x324, 0x38);
-       reg32_write(VDEC_BASE + 0x328, 0x8e);
-       reg32_write(VDEC_BASE + 0x32c, 0x23);
-
-       /* Release reset bit  */
-       regmap_update_bits(state->gpr, IOMUXC_GPR1,
-                       IMX6SX_GPR1_VADC_SW_RST_MASK,
-                       IMX6SX_GPR1_VADC_SW_RST_RELEASE);
-
-       /* Power on vadc ext power */
-       reg32setbit(state->gpc_reg + GPC_CNTR, 18);
-}
-
-static void vadc_power_down(struct vadc_state *state)
-{
-       /* Power down vadc analog */
-       reg32setbit(state->gpc_reg + GPC_CNTR, 17);
-
-       /* Power down vadc ext power */
-       reg32clrbit(state->gpc_reg + GPC_CNTR, 18);
-
-}
-static void vadc_init(struct vadc_state *vadc)
-{
-       pr_debug("%s\n", __func__);
-
-       vadc_power_up(vadc);
-
-       afe_init();
-
-       /* select Video Input 0-3 */
-       vadc_s_routing(vadc->vadc_in);
-
-       afe_voltage_clampingmode();
-
-       vdec_init(vadc);
-
-       /*
-       * current control loop will move sinewave input off below
-       * the bottom of the signal range visible
-       * when the testbus is viewed as magnitude,
-       * so have to break before this point while capturing ENOB data:
-       */
-       afe_alwayson_clampingmode();
-}
-
-static inline struct vadc_state *to_state(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct vadc_state, sd);
-}
-
-static int vadc_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
-{
-       struct vadc_state *state = to_state(sd);
-
-       *std = state->fmt->v4l2_std;
-       return 0;
-}
-
-/*!
- * Return attributes of current video standard.
- * Since this device autodetects the current standard, this function also
- * sets the values that need to be changed if the standard changes.
- * There is no set std equivalent function.
- *
- *  @return            None.
- */
-static int vadc_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
-{
-       struct vadc_state *state = to_state(sd);
-       int mod;
-       int idx;
-       int i;
-
-       /* Read auto mode detected result */
-       printk(KERN_INFO"wait vadc auto detect video mode....\n");
-       for (i = 0; i < 10; i++) {
-               msleep(200);
-               mod = reg32_read(VDEC_VIDMOD);
-               /* Check video signal states */
-               if ((mod & VDEC_VIDMOD_SIGNAL_MASK)
-                               == VDEC_VIDMOD_SIGNAL_DETECT)
-                       break;
-       }
-       if (i == 10)
-               printk(KERN_INFO"Timeout detect video signal mod=0x%x\n", mod);
-
-       if ((mod & VDEC_VIDMOD_PAL_MASK) || (mod & VDEC_VIDMOD_M625_MASK))
-               idx = VADC_PAL;
-       else
-               idx = VADC_NTSC;
-
-       *std = video_fmts[idx].v4l2_std;
-       state->fmt = &video_fmts[idx];
-
-       printk(KERN_INFO"video mode %s\n", video_fmts[idx].name);
-       return 0;
-}
-
-static int vadc_enum_mbus_code(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_pad_config *cfg,
-                              struct v4l2_subdev_mbus_code_enum *code)
-{
-       /* support only one format  */
-       if (code->pad || code->index >= 1)
-               return -EINVAL;
-
-       code->code = MEDIA_BUS_FMT_AYUV8_1X32;
-       return 0;
-}
-
-static int vadc_get_fmt(struct v4l2_subdev *sd,
-                       struct v4l2_subdev_pad_config *cfg,
-                       struct v4l2_subdev_format *format)
-{
-       struct vadc_state *state = to_state(sd);
-       struct v4l2_mbus_framefmt *fmt = &format->format;
-
-       if (format->pad)
-               return -EINVAL;
-
-       fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
-       fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       fmt->field = V4L2_FIELD_INTERLACED;
-       fmt->width = 720;
-       fmt->height = state->fmt->v4l2_std & V4L2_STD_NTSC ? 480 : 576;
-
-       return 0;
-}
-
-static int vadc_set_fmt(struct v4l2_subdev *sd,
-                       struct v4l2_subdev_pad_config *cfg,
-                       struct v4l2_subdev_format *format)
-{
-       return vadc_get_fmt(sd, cfg, format);
-}
-
-static int vadc_enum_framesizes(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_pad_config *cfg,
-                              struct v4l2_subdev_frame_size_enum *fse)
-{
-       struct vadc_state *state = to_state(sd);
-       if (fse->index >= 1)
-               return -EINVAL;
-
-       fse->min_width = state->fmt->active_width;
-       fse->max_width = state->fmt->active_width;
-       fse->min_height  = state->fmt->active_height;
-       fse->max_height  = state->fmt->active_height;
-
-       return 0;
-}
-static int vadc_enum_frameintervals(struct v4l2_subdev *sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_frame_interval_enum *fie)
-{
-       struct vadc_state *state = to_state(sd);
-
-       if (fie->index < 0 || fie->index >= 1)
-               return -EINVAL;
-
-       fie->interval.numerator = 1;
-
-       fie->interval.denominator = state->fmt->framerates;
-
-       return 0;
-}
-
-static int vadc_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
-{
-       struct vadc_state *state = to_state(sd);
-
-       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (parms->parm.capture.timeperframe.denominator
-                               != state->fmt->framerates)
-               parms->parm.capture.timeperframe.denominator
-                               = state->fmt->framerates;
-
-       return 0;
-}
-
-static const struct v4l2_subdev_video_ops vadc_video_ops = {
-       .querystd              = vadc_querystd,
-       .s_parm                = vadc_s_parm,
-       .g_std                 = vadc_g_std,
-};
-
-
-static const struct v4l2_subdev_pad_ops vadc_pad_ops = {
-       .get_fmt               = vadc_get_fmt,
-       .set_fmt               = vadc_set_fmt,
-       .enum_mbus_code        = vadc_enum_mbus_code,
-       .enum_frame_size       = vadc_enum_framesizes,
-       .enum_frame_interval   = vadc_enum_frameintervals,
-};
-
-static const struct v4l2_subdev_ops vadc_ops = {
-       .video = &vadc_video_ops,
-       .pad = &vadc_pad_ops,
-};
-
-static const struct of_device_id fsl_vadc_dt_ids[] = {
-       { .compatible = "fsl,imx6sx-vadc", },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, fsl_vadc_dt_ids);
-
-static int vadc_of_init(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-       struct device_node *gpc_np;
-       struct vadc_state *state = platform_get_drvdata(pdev);
-       int csi_id;
-       int ret;
-
-       /* Get csi_id to setting vadc to csi mux in gpr */
-       ret = of_property_read_u32(np, "csi_id", &csi_id);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to read of property csi_id\n");
-               return ret;
-       }
-
-       state->csi_id = csi_id;
-
-       /* remap GPR register */
-       state->gpr = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-                       "gpr");
-       if (IS_ERR(state->gpr)) {
-               dev_dbg(&pdev->dev, "can not get gpr\n");
-               return -ENOMEM;
-       }
-
-       /* Configuration vadc-to-csi 0 or 1 */
-       if (csi_id) {
-               regmap_update_bits(state->gpr, IOMUXC_GPR5,
-                               IMX6SX_GPR5_CSI2_MUX_CTRL_MASK,
-                               IMX6SX_GPR5_CSI2_MUX_CTRL_CVD);
-       } else {
-               regmap_update_bits(state->gpr, IOMUXC_GPR5,
-                               IMX6SX_GPR5_CSI1_MUX_CTRL_MASK,
-                               IMX6SX_GPR5_CSI1_MUX_CTRL_CVD);
-       }
-
-       /* Get default vadc_in number  */
-       ret = of_property_read_u32(np, "vadc_in", &state->vadc_in);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to read of property vadc_in\n");
-               return ret;
-       }
-
-       /* map GPC register  */
-       gpc_np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
-       state->gpc_reg = of_iomap(gpc_np, 0);
-       if (!state->gpc_reg) {
-               dev_err(&pdev->dev, "ioremap failed with gpc base\n");
-               goto error;
-       }
-
-       return ret;
-
-error:
-       iounmap(state->gpc_reg);
-       return ret;
-}
-
-static void vadc_v4l2_subdev_init(struct v4l2_subdev *sd,
-               struct platform_device *pdev,
-               const struct v4l2_subdev_ops *ops)
-{
-       struct vadc_state *state = platform_get_drvdata(pdev);
-       int ret = 0;
-
-       v4l2_subdev_init(sd, ops);
-       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-       sd->owner = pdev->dev.driver->owner;
-       sd->dev = &pdev->dev;
-
-       /* initialize name */
-       snprintf(sd->name, sizeof(sd->name), "%s",
-               pdev->dev.driver->name);
-
-       v4l2_set_subdevdata(sd, state);
-
-       ret = v4l2_async_register_subdev(sd);
-       if (ret < 0)
-               dev_err(&pdev->dev, "%s--Async register faialed, ret=%d\n", __func__, ret);
-}
-
-static int vadc_probe(struct platform_device *pdev)
-{
-       struct vadc_state *state;
-       struct v4l2_subdev *sd;
-       struct resource *res;
-       int ret = 0;
-
-       state = devm_kzalloc(&pdev->dev, sizeof(struct vadc_state), GFP_KERNEL);
-       if (!state) {
-               dev_err(&pdev->dev, "Cannot allocate device data\n");
-               return -ENOMEM;
-       }
-
-       /* Set initial values for the sensor struct. */
-       state->fmt = &video_fmts[VADC_NTSC];
-
-       sd = &state->sd;
-
-       /* map vafe address  */
-       res = platform_get_resource_byname(pdev,
-                               IORESOURCE_MEM, VAFE_REGS_ADDR_RES_NAME);
-       if (!res) {
-               dev_err(&pdev->dev, "No vafe base address found.\n");
-               return -ENOMEM;
-       }
-       vafe_regbase = devm_ioremap_resource(&pdev->dev, res);
-       if (!vafe_regbase) {
-               dev_err(&pdev->dev, "ioremap failed with vafe base\n");
-               return -ENOMEM;
-       }
-
-       /* map vdec address  */
-       res = platform_get_resource_byname(pdev,
-                               IORESOURCE_MEM, VDEC_REGS_ADDR_RES_NAME);
-       if (!res) {
-               dev_err(&pdev->dev, "No vdec base address found.\n");
-               return -ENODEV;
-       }
-       vdec_regbase = devm_ioremap_resource(&pdev->dev, res);
-       if (!vdec_regbase) {
-               dev_err(&pdev->dev, "ioremap failed with vdec base\n");
-               return -ENOMEM;
-       }
-
-       /* Get clock */
-       state->vadc_clk = devm_clk_get(&pdev->dev, "vadc");
-       if (IS_ERR(state->vadc_clk)) {
-               ret = PTR_ERR(state->vadc_clk);
-               return ret;
-       }
-
-       state->csi_clk = devm_clk_get(&pdev->dev, "csi");
-       if (IS_ERR(state->csi_clk)) {
-               ret = PTR_ERR(state->csi_clk);
-               return ret;
-       }
-
-       /* clock  */
-       clk_prepare_enable(state->csi_clk);
-       clk_prepare_enable(state->vadc_clk);
-
-       platform_set_drvdata(pdev, state);
-
-       vadc_v4l2_subdev_init(sd, pdev, &vadc_ops);
-
-       pm_runtime_enable(&pdev->dev);
-
-       pm_runtime_get_sync(&pdev->dev);
-       /* Init VADC */
-       ret = vadc_of_init(pdev);
-       if (ret < 0)
-               goto err;
-       vadc_init(state);
-
-       pr_info("vadc driver loaded\n");
-
-       return 0;
-err:
-       pm_runtime_put_sync(&pdev->dev);
-       pm_runtime_disable(&pdev->dev);
-       v4l2_async_unregister_subdev(&state->sd);
-       clk_disable_unprepare(state->csi_clk);
-       clk_disable_unprepare(state->vadc_clk);
-       return ret;
-}
-
-static int vadc_remove(struct platform_device *pdev)
-{
-       struct vadc_state *state = platform_get_drvdata(pdev);
-
-       pm_runtime_put_sync(&pdev->dev);
-       pm_runtime_disable(&pdev->dev);
-       v4l2_async_unregister_subdev(&state->sd);
-       clk_disable_unprepare(state->csi_clk);
-       clk_disable_unprepare(state->vadc_clk);
-
-       vadc_power_down(state);
-       return true;
-}
-
-static int vadc_suspend(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct vadc_state *state = platform_get_drvdata(pdev);
-
-       clk_disable(state->csi_clk);
-       clk_disable(state->vadc_clk);
-
-       vadc_power_down(state);
-
-       return 0;
-}
-
-static int vadc_resume(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct vadc_state *state = platform_get_drvdata(pdev);
-
-       clk_enable(state->csi_clk);
-       clk_enable(state->vadc_clk);
-
-       vadc_init(state);
-       return 0;
-}
-
-static const struct dev_pm_ops vadc_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(vadc_suspend, vadc_resume)
-};
-
-static struct platform_driver vadc_driver = {
-       .driver = {
-               .name = "fsl_vadc",
-               .of_match_table = of_match_ptr(fsl_vadc_dt_ids),
-               .pm     = &vadc_pm_ops,
-       },
-       .probe = vadc_probe,
-       .remove = vadc_remove,
-};
-
-module_platform_driver(vadc_driver);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("fsl VADC/VDEC driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/subdev/mxc_vadc.h b/drivers/media/platform/mxc/subdev/mxc_vadc.h
deleted file mode 100644 (file)
index d5c1389..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2011-2015 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#ifndef MXC_VDEC_H
-#define MXC_VDEC_H
-
-/*** define base address ***/
-#define VDEC_BASE vdec_regbase
-#define AFE_BASE vafe_regbase
-
-/* AFE - Register offsets */
-#define AFE_BLOCK_ID_OFFSET                            0x00000000
-#define AFE_PDBUF_OFFSET                               0x00000004
-#define AFE_SWRST_OFFSET                               0x00000008
-#define AFE_TSTSEL_OFFSET                              0x0000000c
-#define AFE_TSTMSC_OFFSET                              0x00000010
-#define AFE_ENPADIO_OFFSET                             0x00000014
-#define AFE_BGREG_OFFSET                               0x00000018
-#define AFE_ACCESSAR_ID_OFFSET                 0x00000400
-#define AFE_PDADC_OFFSET                               0x00000404
-#define AFE_PDSARH_OFFSET                              0x00000408
-#define AFE_PDSARL_OFFSET                              0x0000040C
-#define AFE_PDADCRFH_OFFSET                            0x00000410
-#define AFE_PDADCRFL_OFFSET                            0x00000414
-#define AFE_ACCTST_OFFSET                              0x00000418
-#define AFE_ADCGN_OFFSET                               0x0000041C
-#define AFE_ICTRL_OFFSET                               0x00000420
-#define AFE_ICTLSTG_OFFSET                             0x00000424
-#define AFE_RCTRLSTG_OFFSET                            0x00000428
-#define AFE_TCTRLSTG_OFFSET                            0x0000042c
-#define AFE_REFMOD_OFFSET                              0x00000430
-#define AFE_REFTRIML_OFFSET                            0x00000434
-#define AFE_REFTRIMH_OFFSET                            0x00000438
-#define AFE_ADCR_OFFSET                                        0x0000043c
-#define AFE_DUMMY0_OFFSET                              0x00000440
-#define AFE_DUMMY1_OFFSET                              0x00000444
-#define AFE_DUMMY2_OFFSET                              0x00000448
-#define AFE_DACAMP_OFFSET                              0x0000044c
-#define AFE_CLMPTST_OFFSET                             0x00000450
-#define AFE_CLMPDAT_OFFSET                             0x00000454
-#define AFE_CLMPAMP_OFFSET                             0x00000458
-#define AFE_CLAMP_OFFSET                               0x0000045c
-#define AFE_INPBUF_OFFSET                              0x00000460
-#define AFE_INPFLT_OFFSET                              0x00000464
-#define AFE_ADCDGN_OFFSET                              0x00000468
-#define AFE_OFFDRV_OFFSET                              0x0000046c
-#define AFE_INPCONFIG_OFFSET                   0x00000470
-#define AFE_PROGDELAY_OFFSET                   0x00000474
-#define AFE_ADCOMT_OFFSET                              0x00000478
-#define AFE_ALGDELAY_OFFSET                            0x0000047c
-#define AFE_ACC_ID_OFFSET                              0x00000800
-#define AFE_ACCSTA_OFFSET                              0x00000804
-#define AFE_ACCNOSLI_OFFSET                            0x00000808
-#define AFE_ACCCALCON_OFFSET                   0x0000080c
-#define AFE_BWEWRICTRL_OFFSET                  0x00000810
-#define AFE_SELSLI_OFFSET                              0x00000814
-#define AFE_SELBYT_OFFSET                              0x00000818
-#define AFE_REDVAL_OFFSET                              0x00000820
-#define AFE_WRIBYT_OFFSET                              0x00000824
-
-/* AFE Register per module */
-#define AFE_BLOCK_ID                   (AFE_BASE + AFE_BLOCK_ID_OFFSET)
-#define AFE_PDBUF                              (AFE_BASE + AFE_PDBUF_OFFSET)
-#define AFE_SWRST                              (AFE_BASE + AFE_SWRST_OFFSET)
-#define AFE_TSTSEL                             (AFE_BASE + AFE_TSTSEL_OFFSET)
-#define AFE_TSTMSC                             (AFE_BASE + AFE_TSTMSC_OFFSET)
-#define AFE_ENPADIO                            (AFE_BASE + AFE_ENPADIO_OFFSET)
-#define AFE_BGREG                              (AFE_BASE + AFE_BGREG_OFFSET)
-#define AFE_ACCESSAR_ID                        (AFE_BASE + AFE_ACCESSAR_ID_OFFSET)
-#define AFE_PDADC                              (AFE_BASE + AFE_PDADC_OFFSET)
-#define AFE_PDSARH                         (AFE_BASE + AFE_PDSARH_OFFSET)
-#define AFE_PDSARL                         (AFE_BASE + AFE_PDSARL_OFFSET)
-#define AFE_PDADCRFH                   (AFE_BASE + AFE_PDADCRFH_OFFSET)
-#define AFE_PDADCRFL                   (AFE_BASE + AFE_PDADCRFL_OFFSET)
-#define AFE_ACCTST                             (AFE_BASE + AFE_ACCTST_OFFSET)
-#define AFE_ADCGN                              (AFE_BASE + AFE_ADCGN_OFFSET)
-#define AFE_ICTRL                              (AFE_BASE + AFE_ICTRL_OFFSET)
-#define AFE_ICTLSTG                            (AFE_BASE + AFE_ICTLSTG_OFFSET)
-#define AFE_RCTRLSTG                   (AFE_BASE + AFE_RCTRLSTG_OFFSET)
-#define AFE_TCTRLSTG                   (AFE_BASE + AFE_TCTRLSTG_OFFSET)
-#define AFE_REFMOD                             (AFE_BASE + AFE_REFMOD_OFFSET)
-#define AFE_REFTRIML                   (AFE_BASE + AFE_REFTRIML_OFFSET)
-#define AFE_REFTRIMH                   (AFE_BASE + AFE_REFTRIMH_OFFSET)
-#define AFE_ADCR                               (AFE_BASE + AFE_ADCR_OFFSET)
-#define AFE_DUMMY0                             (AFE_BASE + AFE_DUMMY0_OFFSET)
-#define AFE_DUMMY1                             (AFE_BASE + AFE_DUMMY1_OFFSET)
-#define AFE_DUMMY2                             (AFE_BASE + AFE_DUMMY2_OFFSET)
-#define AFE_DACAMP                             (AFE_BASE + AFE_DACAMP_OFFSET)
-#define AFE_CLMPTST                            (AFE_BASE + AFE_CLMPTST_OFFSET)
-#define AFE_CLMPDAT                            (AFE_BASE + AFE_CLMPDAT_OFFSET)
-#define AFE_CLMPAMP                            (AFE_BASE + AFE_CLMPAMP_OFFSET)
-#define AFE_CLAMP                              (AFE_BASE + AFE_CLAMP_OFFSET)
-#define AFE_INPBUF                             (AFE_BASE + AFE_INPBUF_OFFSET)
-#define AFE_INPFLT                             (AFE_BASE + AFE_INPFLT_OFFSET)
-#define AFE_ADCDGN                             (AFE_BASE + AFE_ADCDGN_OFFSET)
-#define AFE_OFFDRV                             (AFE_BASE + AFE_OFFDRV_OFFSET)
-#define AFE_INPCONFIG                  (AFE_BASE + AFE_INPCONFIG_OFFSET)
-#define AFE_PROGDELAY                  (AFE_BASE + AFE_PROGDELAY_OFFSET)
-#define AFE_ADCOMT                             (AFE_BASE + AFE_ADCOMT_OFFSET)
-#define AFE_ALGDELAY                   (AFE_BASE + AFE_ALGDELAY_OFFSET)
-#define AFE_ACC_ID                             (AFE_BASE + AFE_ACC_ID_OFFSET)
-#define AFE_ACCSTA                             (AFE_BASE + AFE_ACCSTA_OFFSET)
-#define AFE_ACCNOSLI                   (AFE_BASE + AFE_ACCNOSLI_OFFSET)
-#define AFE_ACCCALCON                  (AFE_BASE + AFE_ACCCALCON_OFFSET)
-#define AFE_BWEWRICTRL                 (AFE_BASE + AFE_BWEWRICTRL_OFFSET)
-#define AFE_SELSLI                             (AFE_BASE + AFE_SELSLI_OFFSET)
-#define AFE_SELBYT                             (AFE_BASE + AFE_SELBYT_OFFSET)
-#define AFE_REDVAL                             (AFE_BASE + AFE_REDVAL_OFFSET)
-#define AFE_WRIBYT                             (AFE_BASE + AFE_WRIBYT_OFFSET)
-
-/* VDEC - Register offsets */
-#define VDEC_CFC1_OFFSET                0x00000000
-#define VDEC_CFC2_OFFSET                0x00000004
-#define VDEC_BRSTGT_OFFSET              0x00000024
-#define VDEC_HZPOS_OFFSET               0x00000040
-#define VDEC_VRTPOS_OFFSET              0x00000044
-#define VDEC_HVSHIFT_OFFSET             0x00000054
-#define VDEC_HSIGS_OFFSET               0x00000058
-#define VDEC_HSIGE_OFFSET               0x0000005C
-#define VDEC_VSCON1_OFFSET              0x00000060
-#define VDEC_VSCON2_OFFSET              0x00000064
-#define VDEC_YCDEL_OFFSET               0x0000006C
-#define VDEC_AFTCLP_OFFSET              0x00000070
-#define VDEC_DCOFF_OFFSET               0x00000078
-#define VDEC_CSID_OFFSET                0x00000084
-#define VDEC_CBGN_OFFSET                0x00000088
-#define VDEC_CRGN_OFFSET                0x0000008C
-#define VDEC_CNTR_OFFSET                0x00000090
-#define VDEC_BRT_OFFSET                 0x00000094
-#define VDEC_HUE_OFFSET                 0x00000098
-#define VDEC_CHBTH_OFFSET               0x0000009C
-#define VDEC_SHPIMP_OFFSET              0x000000A4
-#define VDEC_CHPLLIM_OFFSET             0x000000A8
-#define VDEC_VIDMOD_OFFSET              0x000000AC
-#define VDEC_VIDSTS_OFFSET              0x000000B0
-#define VDEC_NOISE_OFFSET               0x000000B4
-#define VDEC_STDDBG_OFFSET              0x000000B8
-#define VDEC_MANOVR_OFFSET              0x000000BC
-#define VDEC_VSSGTH_OFFSET              0x000000C8
-#define VDEC_DBGFBH_OFFSET              0x000000D0
-#define VDEC_DBGFBL_OFFSET              0x000000D4
-#define VDEC_HACTS_OFFSET               0x000000D8
-#define VDEC_HACTE_OFFSET               0x000000DC
-#define VDEC_VACTS_OFFSET               0x000000E0
-#define VDEC_VACTE_OFFSET               0x000000E4
-#define VDEC_HSTIP_OFFSET               0x000000EC
-#define VDEC_BLSCRY_OFFSET              0x000000F4
-#define VDEC_BLSCRCR_OFFSET             0x000000F8
-#define VDEC_BLSCRCB_OFFSET             0x000000FC
-#define VDEC_LMAGC1_OFFSET              0x00000100
-#define VDEC_LMAGC2_OFFSET              0x00000104
-#define VDEC_CHAGC1_OFFSET              0x00000108
-#define VDEC_CHAGC2_OFFSET              0x0000010C
-#define VDEC_MINTH_OFFSET               0x00000114
-#define VDEC_VFRQOH_OFFSET              0x0000011C
-#define VDEC_VFRQOL_OFFSET              0x00000120
-#define VDEC_THSH1_OFFSET               0x00000124
-#define VDEC_THSH2_OFFSET               0x00000128
-#define VDEC_NCHTH_OFFSET               0x0000012C
-#define VDEC_TH1F_OFFSET                0x00000130
-
-/* VDEC Register per module */
-#define VDEC_CFC1                        (VDEC_BASE + VDEC_CFC1_OFFSET)
-#define VDEC_CFC2                        (VDEC_BASE + VDEC_CFC2_OFFSET)
-#define VDEC_BRSTGT                      (VDEC_BASE + VDEC_BRSTGT_OFFSET)
-#define VDEC_HZPOS                       (VDEC_BASE + VDEC_HZPOS_OFFSET)
-#define VDEC_VRTPOS                      (VDEC_BASE + VDEC_VRTPOS_OFFSET)
-#define VDEC_HVSHIFT                     (VDEC_BASE + VDEC_HVSHIFT_OFFSET)
-#define VDEC_HSIGS                       (VDEC_BASE + VDEC_HSIGS_OFFSET)
-#define VDEC_HSIGE                       (VDEC_BASE + VDEC_HSIGE_OFFSET)
-#define VDEC_VSCON1                      (VDEC_BASE + VDEC_VSCON1_OFFSET)
-#define VDEC_VSCON2                      (VDEC_BASE + VDEC_VSCON2_OFFSET)
-#define VDEC_YCDEL                       (VDEC_BASE + VDEC_YCDEL_OFFSET)
-#define VDEC_AFTCLP                      (VDEC_BASE + VDEC_AFTCLP_OFFSET)
-#define VDEC_DCOFF                       (VDEC_BASE + VDEC_DCOFF_OFFSET)
-#define VDEC_CSID                        (VDEC_BASE + VDEC_CSID_OFFSET)
-#define VDEC_CBGN                        (VDEC_BASE + VDEC_CBGN_OFFSET)
-#define VDEC_CRGN                        (VDEC_BASE + VDEC_CRGN_OFFSET)
-#define VDEC_CNTR                        (VDEC_BASE + VDEC_CNTR_OFFSET)
-#define VDEC_BRT                         (VDEC_BASE + VDEC_BRT_OFFSET)
-#define VDEC_HUE                         (VDEC_BASE + VDEC_HUE_OFFSET)
-#define VDEC_CHBTH                       (VDEC_BASE + VDEC_CHBTH_OFFSET)
-#define VDEC_SHPIMP                      (VDEC_BASE + VDEC_SHPIMP_OFFSET)
-#define VDEC_CHPLLIM                     (VDEC_BASE + VDEC_CHPLLIM_OFFSET)
-#define VDEC_VIDMOD                      (VDEC_BASE + VDEC_VIDMOD_OFFSET)
-#define VDEC_VIDSTS                      (VDEC_BASE + VDEC_VIDSTS_OFFSET)
-#define VDEC_NOISE                       (VDEC_BASE + VDEC_NOISE_OFFSET)
-#define VDEC_STDDBG                      (VDEC_BASE + VDEC_STDDBG_OFFSET)
-#define VDEC_MANOVR                      (VDEC_BASE + VDEC_MANOVR_OFFSET)
-#define VDEC_VSSGTH                      (VDEC_BASE + VDEC_VSSGTH_OFFSET)
-#define VDEC_DBGFBH                      (VDEC_BASE + VDEC_DBGFBH_OFFSET)
-#define VDEC_DBGFBL                      (VDEC_BASE + VDEC_DBGFBL_OFFSET)
-#define VDEC_HACTS                       (VDEC_BASE + VDEC_HACTS_OFFSET)
-#define VDEC_HACTE                       (VDEC_BASE + VDEC_HACTE_OFFSET)
-#define VDEC_VACTS                       (VDEC_BASE + VDEC_VACTS_OFFSET)
-#define VDEC_VACTE                       (VDEC_BASE + VDEC_VACTE_OFFSET)
-#define VDEC_HSTIP                       (VDEC_BASE + VDEC_HSTIP_OFFSET)
-#define VDEC_BLSCRY                      (VDEC_BASE + VDEC_BLSCRY_OFFSET)
-#define VDEC_BLSCRCR                     (VDEC_BASE + VDEC_BLSCRCR_OFFSET)
-#define VDEC_BLSCRCB                     (VDEC_BASE + VDEC_BLSCRCB_OFFSET)
-#define VDEC_LMAGC1                      (VDEC_BASE + VDEC_LMAGC1_OFFSET)
-#define VDEC_LMAGC2                      (VDEC_BASE + VDEC_LMAGC2_OFFSET)
-#define VDEC_CHAGC1                      (VDEC_BASE + VDEC_CHAGC1_OFFSET)
-#define VDEC_CHAGC2                      (VDEC_BASE + VDEC_CHAGC2_OFFSET)
-#define VDEC_MINTH                       (VDEC_BASE + VDEC_MINTH_OFFSET)
-#define VDEC_VFRQOH                      (VDEC_BASE + VDEC_VFRQOH_OFFSET)
-#define VDEC_VFRQOL                      (VDEC_BASE + VDEC_VFRQOL_OFFSET)
-#define VDEC_THSH1                       (VDEC_BASE + VDEC_THSH1_OFFSET)
-#define VDEC_THSH2                       (VDEC_BASE + VDEC_THSH2_OFFSET)
-#define VDEC_NCHTH                       (VDEC_BASE + VDEC_NCHTH_OFFSET)
-#define VDEC_TH1F                        (VDEC_BASE + VDEC_TH1F_OFFSET)
-
-#define VDEC_VIDMOD_SIGNAL_MASK           0x0F
-#define VDEC_VIDMOD_SIGNAL_DETECT         0x0F
-
-#define VDEC_VIDMOD_M625_SHIFT            4
-#define VDEC_VIDMOD_M625_MASK             (1 << VDEC_VIDMOD_M625_SHIFT)
-
-#define VDEC_VIDMOD_PAL_SHIFT             7
-#define VDEC_VIDMOD_PAL_MASK              (1 << VDEC_VIDMOD_PAL_SHIFT)
-/*** define base address ***/
-
-#endif
diff --git a/drivers/media/platform/mxc/subdev/ov5640.c b/drivers/media/platform/mxc/subdev/ov5640.c
deleted file mode 100644 (file)
index 70e2a83..0000000
+++ /dev/null
@@ -1,1895 +0,0 @@
-/*
- * Copyright (C) 2012-2015 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * 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.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/regulator/consumer.h>
-#include <linux/v4l2-mediabus.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-#define OV5640_VOLTAGE_ANALOG               2800000
-#define OV5640_VOLTAGE_DIGITAL_CORE         1500000
-#define OV5640_VOLTAGE_DIGITAL_IO           1800000
-
-#define MIN_FPS 15
-#define MAX_FPS 30
-#define DEFAULT_FPS 30
-
-#define OV5640_XCLK_MIN 6000000
-#define OV5640_XCLK_MAX 24000000
-
-#define OV5640_CHIP_ID_HIGH_BYTE        0x300A
-#define OV5640_CHIP_ID_LOW_BYTE         0x300B
-
-enum ov5640_mode {
-       ov5640_mode_MIN = 0,
-       ov5640_mode_VGA_640_480 = 0,
-       ov5640_mode_QVGA_320_240 = 1,
-       ov5640_mode_NTSC_720_480 = 2,
-       ov5640_mode_PAL_720_576 = 3,
-       ov5640_mode_720P_1280_720 = 4,
-       ov5640_mode_1080P_1920_1080 = 5,
-       ov5640_mode_QSXGA_2592_1944 = 6,
-       ov5640_mode_QCIF_176_144 = 7,
-       ov5640_mode_XGA_1024_768 = 8,
-       ov5640_mode_MAX = 8
-};
-
-enum ov5640_frame_rate {
-       ov5640_15_fps,
-       ov5640_30_fps
-};
-
-static int ov5640_framerates[] = {
-       [ov5640_15_fps] = 15,
-       [ov5640_30_fps] = 30,
-};
-
-struct ov5640_datafmt {
-       u32     code;
-       enum v4l2_colorspace            colorspace;
-};
-
-struct reg_value {
-       u16 u16RegAddr;
-       u8 u8Val;
-       u8 u8Mask;
-       u32 u32Delay_ms;
-};
-
-struct ov5640_mode_info {
-       enum ov5640_mode mode;
-       u32 width;
-       u32 height;
-       struct reg_value *init_data_ptr;
-       u32 init_data_size;
-};
-
-struct ov5640 {
-       struct v4l2_subdev              subdev;
-       struct i2c_client *i2c_client;
-       struct v4l2_pix_format pix;
-       const struct ov5640_datafmt     *fmt;
-       struct v4l2_captureparm streamcap;
-       bool on;
-
-       /* control settings */
-       int brightness;
-       int hue;
-       int contrast;
-       int saturation;
-       int red;
-       int green;
-       int blue;
-       int ae_mode;
-
-       u32 mclk;
-       u8 mclk_source;
-       struct clk *sensor_clk;
-       int csi;
-
-       void (*io_init)(void);
-};
-
-/*!
- * Maintains the information on the current state of the sesor.
- */
-static struct ov5640 ov5640_data;
-static int pwn_gpio, rst_gpio;
-static int prev_sysclk;
-static int AE_Target = 52, night_mode;
-static int prev_HTS;
-static int AE_high, AE_low;
-
-static struct reg_value ov5640_global_init_setting[] = {
-       {0x3008, 0x42, 0, 0},
-       {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
-       {0x3034, 0x1a, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0},
-       {0x3630, 0x36, 0, 0}, {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0},
-       {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0},
-       {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0},
-       {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0},
-       {0x3906, 0x10, 0, 0}, {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0},
-       {0x3600, 0x08, 0, 0}, {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0},
-       {0x3620, 0x52, 0, 0}, {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0},
-       {0x3a13, 0x43, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
-       {0x3635, 0x13, 0, 0}, {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0},
-       {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0},
-       {0x3c05, 0x98, 0, 0}, {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0},
-       {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0},
-       {0x3c0b, 0x40, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0},
-       {0x3812, 0x00, 0, 0}, {0x3708, 0x64, 0, 0}, {0x4001, 0x02, 0, 0},
-       {0x4005, 0x1a, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
-       {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
-       {0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x5000, 0xa7, 0, 0},
-       {0x3008, 0x02, 0, 0},
-};
-
-static struct reg_value ov5640_init_setting_30fps_VGA[] = {
-       {0x3008, 0x42, 0, 0},
-       {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
-       {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x46, 0, 0},
-       {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
-       {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
-       {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
-       {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
-       {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
-       {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
-       {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
-       {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
-       {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
-       {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
-       {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
-       {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
-       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
-       {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
-       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
-       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
-       {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
-       {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
-       {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-       {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, {0x5000, 0xa7, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0},
-       {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
-       {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0},
-       {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0}, {0x518a, 0x54, 0, 0},
-       {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x50, 0, 0},
-       {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0}, {0x5190, 0x46, 0, 0},
-       {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
-       {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
-       {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x6c, 0, 0},
-       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x09, 0, 0},
-       {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0}, {0x5381, 0x1e, 0, 0},
-       {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, {0x5384, 0x0a, 0, 0},
-       {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0},
-       {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0},
-       {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0},
-       {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0},
-       {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0},
-       {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0},
-       {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, {0x5481, 0x08, 0, 0},
-       {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, {0x5484, 0x51, 0, 0},
-       {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, {0x5487, 0x7d, 0, 0},
-       {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, {0x548a, 0x9a, 0, 0},
-       {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, {0x548d, 0xcd, 0, 0},
-       {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, {0x5490, 0x1d, 0, 0},
-       {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x10, 0, 0},
-       {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, {0x558b, 0xf8, 0, 0},
-       {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, {0x5802, 0x0f, 0, 0},
-       {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, {0x5805, 0x26, 0, 0},
-       {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, {0x5808, 0x05, 0, 0},
-       {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, {0x580b, 0x0d, 0, 0},
-       {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, {0x580e, 0x00, 0, 0},
-       {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, {0x5811, 0x09, 0, 0},
-       {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x00, 0, 0},
-       {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, {0x5817, 0x08, 0, 0},
-       {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, {0x581a, 0x05, 0, 0},
-       {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, {0x581d, 0x0e, 0, 0},
-       {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, {0x5820, 0x11, 0, 0},
-       {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, {0x5823, 0x28, 0, 0},
-       {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, {0x5826, 0x08, 0, 0},
-       {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, {0x5829, 0x26, 0, 0},
-       {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, {0x582c, 0x24, 0, 0},
-       {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, {0x582f, 0x22, 0, 0},
-       {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, {0x5832, 0x24, 0, 0},
-       {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, {0x5835, 0x22, 0, 0},
-       {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, {0x5838, 0x44, 0, 0},
-       {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, {0x583b, 0x28, 0, 0},
-       {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, {0x5025, 0x00, 0, 0},
-       {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0},
-       {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0},
-       {0x3008, 0x02, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
-       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
-       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
-       {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
-       {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
-       {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
-       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
-       {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
-       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
-       {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
-       {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
-       {0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
-       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
-       {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
-       {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
-       {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
-       {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
-       {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
-       {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
-       {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
-       {0x3503, 0x00, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
-       {0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
-       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
-       {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
-       {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
-       {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
-       {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
-       {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
-       {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
-       {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
-       {0x3503, 0x00, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
-       {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
-       {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
-       {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
-       {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
-       {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
-       {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
-       {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
-       {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
-       {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
-       {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-
-static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
-       {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
-       {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0xee, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x05, 0, 0},
-       {0x3807, 0xc3, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0},
-       {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x0b, 0, 0},
-       {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
-       {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
-       {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
-       {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
-       {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
-       {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
-       {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
-       {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
-       {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
-       {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0},
-       {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
-       {0x3807, 0x9f, 0, 0}, {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0},
-       {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0},
-       {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
-       {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
-       {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
-       {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
-       {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
-       {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
-       {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
-};
-
-static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
-       {
-               {ov5640_mode_VGA_640_480,      640,  480,
-               ov5640_setting_15fps_VGA_640_480,
-               ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
-               {ov5640_mode_QVGA_320_240,     320,  240,
-               ov5640_setting_15fps_QVGA_320_240,
-               ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
-               {ov5640_mode_NTSC_720_480,     720,  480,
-               ov5640_setting_15fps_NTSC_720_480,
-               ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
-               {ov5640_mode_PAL_720_576,      720,  576,
-               ov5640_setting_15fps_PAL_720_576,
-               ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
-               {ov5640_mode_720P_1280_720,   1280,  720,
-               ov5640_setting_15fps_720P_1280_720,
-               ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
-               {ov5640_mode_1080P_1920_1080, 1920, 1080,
-               ov5640_setting_15fps_1080P_1920_1080,
-               ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
-               {ov5640_mode_QSXGA_2592_1944, 2592, 1944,
-               ov5640_setting_15fps_QSXGA_2592_1944,
-               ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
-               {ov5640_mode_QCIF_176_144,     176,  144,
-               ov5640_setting_15fps_QCIF_176_144,
-               ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
-               {ov5640_mode_XGA_1024_768,    1024,  768,
-               ov5640_setting_15fps_XGA_1024_768,
-               ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
-       },
-       {
-               {ov5640_mode_VGA_640_480,      640,  480,
-               ov5640_setting_30fps_VGA_640_480,
-               ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
-               {ov5640_mode_QVGA_320_240,     320,  240,
-               ov5640_setting_30fps_QVGA_320_240,
-               ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
-               {ov5640_mode_NTSC_720_480,     720,  480,
-               ov5640_setting_30fps_NTSC_720_480,
-               ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
-               {ov5640_mode_PAL_720_576,      720,  576,
-               ov5640_setting_30fps_PAL_720_576,
-               ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
-               {ov5640_mode_720P_1280_720,   1280,  720,
-               ov5640_setting_30fps_720P_1280_720,
-               ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
-               {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0},
-               {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
-               {ov5640_mode_QCIF_176_144,     176,  144,
-               ov5640_setting_30fps_QCIF_176_144,
-               ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
-               {ov5640_mode_XGA_1024_768,    1024,  768,
-               ov5640_setting_30fps_XGA_1024_768,
-               ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
-       },
-};
-
-static struct regulator *io_regulator;
-static struct regulator *core_regulator;
-static struct regulator *analog_regulator;
-
-static int ov5640_probe(struct i2c_client *adapter,
-                               const struct i2c_device_id *device_id);
-static int ov5640_remove(struct i2c_client *client);
-
-static s32 ov5640_read_reg(u16 reg, u8 *val);
-static s32 ov5640_write_reg(u16 reg, u8 val);
-
-static const struct i2c_device_id ov5640_id[] = {
-       {"ov5640", 0},
-       {},
-};
-
-MODULE_DEVICE_TABLE(i2c, ov5640_id);
-
-static struct i2c_driver ov5640_i2c_driver = {
-       .driver = {
-                 .owner = THIS_MODULE,
-                 .name  = "ov5640",
-                 },
-       .probe  = ov5640_probe,
-       .remove = ov5640_remove,
-       .id_table = ov5640_id,
-};
-
-static const struct ov5640_datafmt ov5640_colour_fmts[] = {
-       {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
-};
-
-static struct ov5640 *to_ov5640(const struct i2c_client *client)
-{
-       return container_of(i2c_get_clientdata(client), struct ov5640, subdev);
-}
-
-/* Find a data format by a pixel code in an array */
-static const struct ov5640_datafmt
-                       *ov5640_find_datafmt(u32 code)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ov5640_colour_fmts); i++)
-               if (ov5640_colour_fmts[i].code == code)
-                       return ov5640_colour_fmts + i;
-
-       return NULL;
-}
-
-static inline void ov5640_power_down(int enable)
-{
-       gpio_set_value_cansleep(pwn_gpio, enable);
-
-       msleep(2);
-}
-
-static inline void ov5640_reset(void)
-{
-       /* camera reset */
-       gpio_set_value_cansleep(rst_gpio, 1);
-
-       /* camera power down */
-       gpio_set_value_cansleep(pwn_gpio, 1);
-       msleep(5);
-       gpio_set_value_cansleep(pwn_gpio, 0);
-       msleep(5);
-       gpio_set_value_cansleep(rst_gpio, 0);
-       msleep(1);
-       gpio_set_value_cansleep(rst_gpio, 1);
-       msleep(5);
-       gpio_set_value_cansleep(pwn_gpio, 1);
-}
-
-static int ov5640_regulator_enable(struct device *dev)
-{
-       int ret = 0;
-
-       io_regulator = devm_regulator_get(dev, "DOVDD");
-       if (!IS_ERR(io_regulator)) {
-               regulator_set_voltage(io_regulator,
-                                     OV5640_VOLTAGE_DIGITAL_IO,
-                                     OV5640_VOLTAGE_DIGITAL_IO);
-               ret = regulator_enable(io_regulator);
-               if (ret) {
-                       dev_err(dev, "set io voltage failed\n");
-                       return ret;
-               } else {
-                       dev_dbg(dev, "set io voltage ok\n");
-               }
-       } else {
-               io_regulator = NULL;
-               dev_warn(dev, "cannot get io voltage\n");
-       }
-
-       core_regulator = devm_regulator_get(dev, "DVDD");
-       if (!IS_ERR(core_regulator)) {
-               regulator_set_voltage(core_regulator,
-                                     OV5640_VOLTAGE_DIGITAL_CORE,
-                                     OV5640_VOLTAGE_DIGITAL_CORE);
-               ret = regulator_enable(core_regulator);
-               if (ret) {
-                       dev_err(dev, "set core voltage failed\n");
-                       return ret;
-               } else {
-                       dev_dbg(dev, "set core voltage ok\n");
-               }
-       } else {
-               core_regulator = NULL;
-               dev_warn(dev, "cannot get core voltage\n");
-       }
-
-       analog_regulator = devm_regulator_get(dev, "AVDD");
-       if (!IS_ERR(analog_regulator)) {
-               regulator_set_voltage(analog_regulator,
-                                     OV5640_VOLTAGE_ANALOG,
-                                     OV5640_VOLTAGE_ANALOG);
-               ret = regulator_enable(analog_regulator);
-               if (ret) {
-                       dev_err(dev, "set analog voltage failed\n");
-                       return ret;
-               } else {
-                       dev_dbg(dev, "set analog voltage ok\n");
-               }
-       } else {
-               analog_regulator = NULL;
-               dev_warn(dev, "cannot get analog voltage\n");
-       }
-
-       return ret;
-}
-
-static s32 ov5640_write_reg(u16 reg, u8 val)
-{
-       u8 au8Buf[3] = {0};
-
-       au8Buf[0] = reg >> 8;
-       au8Buf[1] = reg & 0xff;
-       au8Buf[2] = val;
-
-       if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
-               pr_err("%s:write reg error:reg=%x,val=%x\n",
-                       __func__, reg, val);
-               return -1;
-       }
-
-       return 0;
-}
-
-static s32 ov5640_read_reg(u16 reg, u8 *val)
-{
-       u8 au8RegBuf[2] = {0};
-       u8 u8RdVal = 0;
-
-       au8RegBuf[0] = reg >> 8;
-       au8RegBuf[1] = reg & 0xff;
-
-       if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
-               pr_err("%s:write reg error:reg=%x\n",
-                               __func__, reg);
-               return -1;
-       }
-
-       if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
-               pr_err("%s:read reg error:reg=%x,val=%x\n",
-                               __func__, reg, u8RdVal);
-               return -1;
-       }
-
-       *val = u8RdVal;
-
-       return u8RdVal;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int ov5640_get_register(struct v4l2_subdev *sd,
-                                       struct v4l2_dbg_register *reg)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret;
-       u8 val;
-
-       if (reg->reg & ~0xffff)
-               return -EINVAL;
-
-       reg->size = 1;
-
-       ret = ov5640_read_reg(reg->reg, &val);
-       if (!ret)
-               reg->val = (__u64)val;
-
-       return ret;
-}
-
-static int ov5640_set_register(struct v4l2_subdev *sd,
-                                       const struct v4l2_dbg_register *reg)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-       if (reg->reg & ~0xffff || reg->val & ~0xff)
-               return -EINVAL;
-
-       return ov5640_write_reg(reg->reg, reg->val);
-}
-#endif
-
-static void ov5640_soft_reset(void)
-{
-       /* sysclk from pad */
-       ov5640_write_reg(0x3103, 0x11);
-
-       /* software reset */
-       ov5640_write_reg(0x3008, 0x82);
-
-       /* delay at least 5ms */
-       msleep(10);
-}
-
-/* set sensor driver capability
- * 0x302c[7:6] - strength
-       00     - 1x
-       01     - 2x
-       10     - 3x
-       11     - 4x
- */
-static int ov5640_driver_capability(int strength)
-{
-       u8 temp = 0;
-
-       if (strength > 4 || strength < 1) {
-               pr_err("The valid driver capability of ov5640 is 1x~4x\n");
-               return -EINVAL;
-       }
-
-       ov5640_read_reg(0x302c, &temp);
-
-       temp &= ~0xc0;  /* clear [7:6] */
-       temp |= ((strength - 1) << 6);  /* set [7:6] */
-
-       ov5640_write_reg(0x302c, temp);
-
-       return 0;
-}
-
-/* calculate sysclk */
-static int ov5640_get_sysclk(void)
-{
-       int xvclk = ov5640_data.mclk / 10000;
-       int sysclk;
-       int temp1, temp2;
-       int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv;
-       int sclk_rdiv_map[] = {1, 2, 4, 8};
-       u8 regval = 0;
-
-       temp1 = ov5640_read_reg(0x3034, &regval);
-       temp2 = temp1 & 0x0f;
-       if (temp2 == 8 || temp2 == 10) {
-               Bit_div2x = temp2 / 2;
-       } else {
-               pr_err("ov5640: unsupported bit mode %d\n", temp2);
-               return -1;
-       }
-
-       temp1 = ov5640_read_reg(0x3035, &regval);
-       SysDiv = temp1 >> 4;
-       if (SysDiv == 0)
-               SysDiv = 16;
-
-       temp1 = ov5640_read_reg(0x3036, &regval);
-       Multiplier = temp1;
-       temp1 = ov5640_read_reg(0x3037, &regval);
-       PreDiv = temp1 & 0x0f;
-       Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
-
-       temp1 = ov5640_read_reg(0x3108, &regval);
-       temp2 = temp1 & 0x03;
-
-       sclk_rdiv = sclk_rdiv_map[temp2];
-       VCO = xvclk * Multiplier / PreDiv;
-       sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
-
-       return sysclk;
-}
-
-/* read HTS from register settings */
-static int ov5640_get_HTS(void)
-{
-       int HTS;
-       u8 temp = 0;
-
-       HTS = ov5640_read_reg(0x380c, &temp);
-       HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
-       return HTS;
-}
-
-/* read VTS from register settings */
-static int ov5640_get_VTS(void)
-{
-       int VTS;
-       u8 temp = 0;
-
-       VTS = ov5640_read_reg(0x380e, &temp);
-       VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
-
-       return VTS;
-}
-
-/* write VTS to registers */
-static int ov5640_set_VTS(int VTS)
-{
-       int temp;
-
-       temp = VTS & 0xff;
-       ov5640_write_reg(0x380f, temp);
-
-       temp = VTS>>8;
-       ov5640_write_reg(0x380e, temp);
-       return 0;
-}
-
-/* read shutter, in number of line period */
-static int ov5640_get_shutter(void)
-{
-       int shutter;
-       u8 regval;
-
-       shutter = (ov5640_read_reg(0x03500, &regval) & 0x0f);
-
-       shutter = (shutter<<8) + ov5640_read_reg(0x3501, &regval);
-       shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &regval)>>4);
-
-       return shutter;
-}
-
-/* write shutter, in number of line period */
-static int ov5640_set_shutter(int shutter)
-{
-       int temp;
-
-       shutter = shutter & 0xffff;
-       temp = shutter & 0x0f;
-       temp = temp<<4;
-       ov5640_write_reg(0x3502, temp);
-
-       temp = shutter & 0xfff;
-       temp = temp>>4;
-       ov5640_write_reg(0x3501, temp);
-
-       temp = shutter>>12;
-       ov5640_write_reg(0x3500, temp);
-
-       return 0;
-}
-
-/* read gain, 16 = 1x */
-static int ov5640_get_gain16(void)
-{
-       int gain16;
-       u8 regval;
-
-       gain16 = ov5640_read_reg(0x350a, &regval) & 0x03;
-       gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &regval);
-
-       return gain16;
-}
-
-/* write gain, 16 = 1x */
-static int ov5640_set_gain16(int gain16)
-{
-       int temp;
-
-       gain16 = gain16 & 0x3ff;
-       temp = gain16 & 0xff;
-
-       ov5640_write_reg(0x350b, temp);
-       temp = gain16>>8;
-
-       ov5640_write_reg(0x350a, temp);
-       return 0;
-}
-
-/* get banding filter value */
-static int ov5640_get_light_freq(void)
-{
-       int temp, temp1, light_frequency;
-       u8 regval;
-
-       temp = ov5640_read_reg(0x3c01, &regval);
-       if (temp & 0x80) {
-               /* manual */
-               temp1 = ov5640_read_reg(0x3c00, &regval);
-               if (temp1 & 0x04) {
-                       /* 50Hz */
-                       light_frequency = 50;
-               } else {
-                       /* 60Hz */
-                       light_frequency = 60;
-               }
-       } else {
-               /* auto */
-               temp1 = ov5640_read_reg(0x3c0c, &regval);
-               if (temp1 & 0x01) {
-                       /* 50Hz */
-                       light_frequency = 50;
-               } else {
-                       /* 60Hz */
-                       light_frequency = 60;
-               }
-       }
-
-       return light_frequency;
-}
-
-static void ov5640_set_bandingfilter(void)
-{
-       int prev_VTS;
-       int band_step60, max_band60, band_step50, max_band50;
-
-       /* read preview PCLK */
-       prev_sysclk = ov5640_get_sysclk();
-
-       /* read preview HTS */
-       prev_HTS = ov5640_get_HTS();
-
-       /* read preview VTS */
-       prev_VTS = ov5640_get_VTS();
-
-       /* calculate banding filter */
-       /* 60Hz */
-       band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
-       ov5640_write_reg(0x3a0a, (band_step60 >> 8));
-       ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
-
-       max_band60 = (int)((prev_VTS-4)/band_step60);
-       ov5640_write_reg(0x3a0d, max_band60);
-
-       /* 50Hz */
-       band_step50 = prev_sysclk * 100/prev_HTS;
-       ov5640_write_reg(0x3a08, (band_step50 >> 8));
-       ov5640_write_reg(0x3a09, (band_step50 & 0xff));
-
-       max_band50 = (int)((prev_VTS-4)/band_step50);
-       ov5640_write_reg(0x3a0e, max_band50);
-}
-
-/* stable in high */
-static int ov5640_set_AE_target(int target)
-{
-       int fast_high, fast_low;
-
-       AE_low = target * 23 / 25; /* 0.92 */
-       AE_high = target * 27 / 25; /* 1.08 */
-       fast_high = AE_high << 1;
-
-       if (fast_high > 255)
-               fast_high = 255;
-       fast_low = AE_low >> 1;
-
-       ov5640_write_reg(0x3a0f, AE_high);
-       ov5640_write_reg(0x3a10, AE_low);
-       ov5640_write_reg(0x3a1b, AE_high);
-       ov5640_write_reg(0x3a1e, AE_low);
-       ov5640_write_reg(0x3a11, fast_high);
-       ov5640_write_reg(0x3a1f, fast_low);
-
-       return 0;
-}
-
-/* enable = 0 to turn off night mode
-   enable = 1 to turn on night mode */
-static int ov5640_set_night_mode(int enable)
-{
-       u8 mode;
-
-       ov5640_read_reg(0x3a00, &mode);
-
-       if (enable) {
-               /* night mode on */
-               mode |= 0x04;
-               ov5640_write_reg(0x3a00, mode);
-       } else {
-               /* night mode off */
-               mode &= 0xfb;
-               ov5640_write_reg(0x3a00, mode);
-       }
-
-       return 0;
-}
-
-/* enable = 0 to turn off AEC/AGC
-   enable = 1 to turn on AEC/AGC */
-static void ov5640_turn_on_AE_AG(int enable)
-{
-       u8 ae_ag_ctrl;
-
-       ov5640_read_reg(0x3503, &ae_ag_ctrl);
-       if (enable) {
-               /* turn on auto AE/AG */
-               ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
-       } else {
-               /* turn off AE/AG */
-               ae_ag_ctrl = ae_ag_ctrl | 0x03;
-       }
-       ov5640_write_reg(0x3503, ae_ag_ctrl);
-}
-
-/* download ov5640 settings to sensor through i2c */
-static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
-{
-       register u32 Delay_ms = 0;
-       register u16 RegAddr = 0;
-       register u8 Mask = 0;
-       register u8 Val = 0;
-       u8 RegVal = 0;
-       int i, retval = 0;
-
-       for (i = 0; i < ArySize; ++i, ++pModeSetting) {
-               Delay_ms = pModeSetting->u32Delay_ms;
-               RegAddr = pModeSetting->u16RegAddr;
-               Val = pModeSetting->u8Val;
-               Mask = pModeSetting->u8Mask;
-
-               if (Mask) {
-                       retval = ov5640_read_reg(RegAddr, &RegVal);
-                       if (retval < 0)
-                               goto err;
-
-                       RegVal &= ~(u8)Mask;
-                       Val &= Mask;
-                       Val |= RegVal;
-               }
-
-               retval = ov5640_write_reg(RegAddr, Val);
-               if (retval < 0)
-                       goto err;
-
-               if (Delay_ms)
-                       msleep(Delay_ms);
-       }
-err:
-       return retval;
-}
-
-static int ov5640_init_mode(void)
-{
-       struct reg_value *pModeSetting = NULL;
-       int ArySize = 0, retval = 0;
-
-       ov5640_soft_reset();
-
-       pModeSetting = ov5640_global_init_setting;
-       ArySize = ARRAY_SIZE(ov5640_global_init_setting);
-       retval = ov5640_download_firmware(pModeSetting, ArySize);
-       if (retval < 0)
-               goto err;
-
-       pModeSetting = ov5640_init_setting_30fps_VGA;
-       ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
-       retval = ov5640_download_firmware(pModeSetting, ArySize);
-       if (retval < 0)
-               goto err;
-
-       /* change driver capability to 2x according to validation board.
-        * if the image is not stable, please increase the driver strength.
-        */
-       ov5640_driver_capability(2);
-       ov5640_set_bandingfilter();
-       ov5640_set_AE_target(AE_Target);
-       ov5640_set_night_mode(night_mode);
-
-       /* skip 9 vysnc: start capture at 10th vsync */
-       msleep(300);
-
-       /* turn off night mode */
-       night_mode = 0;
-       ov5640_data.pix.width = 640;
-       ov5640_data.pix.height = 480;
-err:
-       return retval;
-}
-
-/* change to or back to subsampling mode set the mode directly
- * image size below 1280 * 960 is subsampling mode */
-static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
-                           enum ov5640_mode mode)
-{
-       struct reg_value *pModeSetting = NULL;
-       s32 ArySize = 0;
-       int retval = 0;
-
-       if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
-               pr_err("Wrong ov5640 mode detected!\n");
-               return -1;
-       }
-
-       pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
-       ArySize =
-               ov5640_mode_info_data[frame_rate][mode].init_data_size;
-
-       ov5640_data.pix.width = ov5640_mode_info_data[frame_rate][mode].width;
-       ov5640_data.pix.height = ov5640_mode_info_data[frame_rate][mode].height;
-
-       if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
-           pModeSetting == NULL || ArySize == 0)
-               return -EINVAL;
-
-       /* set ov5640 to subsampling mode */
-       retval = ov5640_download_firmware(pModeSetting, ArySize);
-
-       /* turn on AE AG for subsampling mode, in case the firmware didn't */
-       ov5640_turn_on_AE_AG(1);
-
-       /* calculate banding filter */
-       ov5640_set_bandingfilter();
-
-       /* set AE target */
-       ov5640_set_AE_target(AE_Target);
-
-       /* update night mode setting */
-       ov5640_set_night_mode(night_mode);
-
-       /* skip 9 vysnc: start capture at 10th vsync */
-       if (mode == ov5640_mode_XGA_1024_768 && frame_rate == ov5640_30_fps) {
-               pr_warning("ov5640: actual frame rate of XGA is 22.5fps\n");
-               /* 1/22.5 * 9*/
-               msleep(400);
-               return retval;
-       }
-
-       if (frame_rate == ov5640_15_fps) {
-               /* 1/15 * 9*/
-               msleep(600);
-       } else if (frame_rate == ov5640_30_fps) {
-               /* 1/30 * 9*/
-               msleep(300);
-       }
-
-       return retval;
-}
-
-/* change to scaling mode go through exposure calucation
- * image size above 1280 * 960 is scaling mode */
-static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
-                           enum ov5640_mode mode)
-{
-       int prev_shutter, prev_gain16, average;
-       int cap_shutter, cap_gain16;
-       int cap_sysclk, cap_HTS, cap_VTS;
-       int light_freq, cap_bandfilt, cap_maxband;
-       long cap_gain16_shutter;
-       u8 temp;
-       struct reg_value *pModeSetting = NULL;
-       s32 ArySize = 0;
-       int retval = 0;
-
-       /* check if the input mode and frame rate is valid */
-       pModeSetting =
-               ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
-       ArySize =
-               ov5640_mode_info_data[frame_rate][mode].init_data_size;
-
-       ov5640_data.pix.width =
-               ov5640_mode_info_data[frame_rate][mode].width;
-       ov5640_data.pix.height =
-               ov5640_mode_info_data[frame_rate][mode].height;
-
-       if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
-               pModeSetting == NULL || ArySize == 0)
-               return -EINVAL;
-
-       /* read preview shutter */
-       prev_shutter = ov5640_get_shutter();
-
-       /* read preview gain */
-       prev_gain16 = ov5640_get_gain16();
-
-       /* get average */
-       average = ov5640_read_reg(0x56a1, &temp);
-
-       /* turn off night mode for capture */
-       ov5640_set_night_mode(0);
-
-       /* turn off overlay */
-       ov5640_write_reg(0x3022, 0x06);
-
-       /* Write capture setting */
-       retval = ov5640_download_firmware(pModeSetting, ArySize);
-       if (retval < 0)
-               goto err;
-
-       /* turn off AE AG when capture image. */
-       ov5640_turn_on_AE_AG(0);
-
-       /* read capture VTS */
-       cap_VTS = ov5640_get_VTS();
-       cap_HTS = ov5640_get_HTS();
-       cap_sysclk = ov5640_get_sysclk();
-
-       /* calculate capture banding filter */
-       light_freq = ov5640_get_light_freq();
-       if (light_freq == 60) {
-               /* 60Hz */
-               cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
-       } else {
-               /* 50Hz */
-               cap_bandfilt = cap_sysclk * 100 / cap_HTS;
-       }
-       cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
-       /* calculate capture shutter/gain16 */
-       if (average > AE_low && average < AE_high) {
-               /* in stable range */
-               cap_gain16_shutter =
-                       prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
-                       prev_HTS/cap_HTS * AE_Target / average;
-       } else {
-               cap_gain16_shutter =
-                       prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
-                       prev_HTS/cap_HTS;
-       }
-
-       /* gain to shutter */
-       if (cap_gain16_shutter < (cap_bandfilt * 16)) {
-               /* shutter < 1/100 */
-               cap_shutter = cap_gain16_shutter/16;
-               if (cap_shutter < 1)
-                       cap_shutter = 1;
-               cap_gain16 = cap_gain16_shutter/cap_shutter;
-               if (cap_gain16 < 16)
-                       cap_gain16 = 16;
-       } else {
-               if (cap_gain16_shutter > (cap_bandfilt*cap_maxband*16)) {
-                       /* exposure reach max */
-                       cap_shutter = cap_bandfilt*cap_maxband;
-                       cap_gain16 = cap_gain16_shutter / cap_shutter;
-               } else {
-                       /* 1/100 < cap_shutter =< max, cap_shutter = n/100 */
-                       cap_shutter =
-                               ((int)(cap_gain16_shutter/16/cap_bandfilt))
-                               * cap_bandfilt;
-                       cap_gain16 = cap_gain16_shutter / cap_shutter;
-               }
-       }
-
-       /* write capture gain */
-       ov5640_set_gain16(cap_gain16);
-
-       /* write capture shutter */
-       if (cap_shutter > (cap_VTS - 4)) {
-               cap_VTS = cap_shutter + 4;
-               ov5640_set_VTS(cap_VTS);
-       }
-
-       ov5640_set_shutter(cap_shutter);
-
-       /* skip 2 vysnc: start capture at 3rd vsync
-        * frame rate of QSXGA and 1080P is 7.5fps: 1/7.5 * 2
-        */
-       pr_warning("ov5640: the actual frame rate of %s is 7.5fps\n",
-               mode == ov5640_mode_1080P_1920_1080 ? "1080P" : "QSXGA");
-       msleep(267);
-err:
-       return retval;
-}
-
-static int ov5640_change_mode(enum ov5640_frame_rate frame_rate,
-                           enum ov5640_mode mode)
-{
-       int retval = 0;
-
-       if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
-               pr_err("Wrong ov5640 mode detected!\n");
-               return -1;
-       }
-
-       if (mode == ov5640_mode_1080P_1920_1080 ||
-                       mode == ov5640_mode_QSXGA_2592_1944) {
-               /* change to scaling mode go through exposure calucation
-                * image size above 1280 * 960 is scaling mode */
-               retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
-       } else {
-               /* change back to subsampling modem download firmware directly
-                * image size below 1280 * 960 is subsampling mode */
-               retval = ov5640_change_mode_direct(frame_rate, mode);
-       }
-
-       return retval;
-}
-
-/*!
- * ov5640_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
- * @s: pointer to standard V4L2 device structure
- * @on: indicates power mode (on or off)
- *
- * Turns the power on or off, depending on the value of on and returns the
- * appropriate error code.
- */
-static int ov5640_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-
-       if (on)
-               clk_enable(ov5640_data.sensor_clk);
-       else
-               clk_disable(ov5640_data.sensor_clk);
-
-       sensor->on = on;
-
-       return 0;
-}
-
-/*!
- * ov5640_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
- * @s: pointer to standard V4L2 sub device structure
- * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
- *
- * Returns the sensor's video CAPTURE parameters.
- */
-static int ov5640_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-       struct v4l2_captureparm *cparm = &a->parm.capture;
-       int ret = 0;
-
-       switch (a->type) {
-       /* This is the only case currently handled. */
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               memset(a, 0, sizeof(*a));
-               a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               cparm->capability = sensor->streamcap.capability;
-               cparm->timeperframe = sensor->streamcap.timeperframe;
-               cparm->capturemode = sensor->streamcap.capturemode;
-               ret = 0;
-               break;
-
-       /* These are all the possible cases. */
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_VBI_OUTPUT:
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               ret = -EINVAL;
-               break;
-
-       default:
-               pr_debug("   type is unknown - %d\n", a->type);
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
-}
-
-/*!
- * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
- * @s: pointer to standard V4L2 sub device structure
- * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
- *
- * Configures the sensor to use the input parameters, if possible.  If
- * not possible, reverts to the old parameters and returns the
- * appropriate error code.
- */
-static int ov5640_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
-       u32 tgt_fps;    /* target frames per secound */
-       enum ov5640_frame_rate frame_rate;
-       int ret = 0;
-
-       switch (a->type) {
-       /* This is the only case currently handled. */
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               /* Check that the new frame rate is allowed. */
-               if ((timeperframe->numerator == 0) ||
-                   (timeperframe->denominator == 0)) {
-                       timeperframe->denominator = DEFAULT_FPS;
-                       timeperframe->numerator = 1;
-               }
-
-               tgt_fps = timeperframe->denominator /
-                         timeperframe->numerator;
-
-               if (tgt_fps > MAX_FPS) {
-                       timeperframe->denominator = MAX_FPS;
-                       timeperframe->numerator = 1;
-               } else if (tgt_fps < MIN_FPS) {
-                       timeperframe->denominator = MIN_FPS;
-                       timeperframe->numerator = 1;
-               }
-
-               /* Actual frame rate we use */
-               tgt_fps = timeperframe->denominator /
-                         timeperframe->numerator;
-
-               if (tgt_fps == 15)
-                       frame_rate = ov5640_15_fps;
-               else if (tgt_fps == 30)
-                       frame_rate = ov5640_30_fps;
-               else {
-                       pr_err(" The camera frame rate is not supported!\n");
-                       goto error;
-               }
-
-               ret = ov5640_change_mode(frame_rate,
-                               a->parm.capture.capturemode);
-               if (ret < 0)
-                       goto error;
-
-               sensor->streamcap.timeperframe = *timeperframe;
-               sensor->streamcap.capturemode = a->parm.capture.capturemode;
-
-               break;
-
-       /* These are all the possible cases. */
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_VBI_OUTPUT:
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               pr_debug("   type is not " \
-                       "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
-                       a->type);
-               ret = -EINVAL;
-               break;
-
-       default:
-               pr_debug("   type is unknown - %d\n", a->type);
-               ret = -EINVAL;
-               break;
-       }
-
-error:
-       return ret;
-}
-
-static int ov5640_set_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_pad_config *cfg,
-                         struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf = &format->format;
-       const struct ov5640_datafmt *fmt = ov5640_find_datafmt(mf->code);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-
-       if (format->pad)
-               return -EINVAL;
-
-       if (!fmt) {
-               mf->code        = ov5640_colour_fmts[0].code;
-               mf->colorspace  = ov5640_colour_fmts[0].colorspace;
-       }
-
-       mf->field       = V4L2_FIELD_NONE;
-
-       if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-               return 0;
-
-       sensor->fmt = fmt;
-
-       return 0;
-}
-
-static int ov5640_get_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_pad_config *cfg,
-                         struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf = &format->format;
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-       const struct ov5640_datafmt *fmt = sensor->fmt;
-
-       if (format->pad)
-               return -EINVAL;
-
-       mf->code        = fmt->code;
-       mf->colorspace  = fmt->colorspace;
-       mf->field       = V4L2_FIELD_NONE;
-
-       return 0;
-}
-
-static int ov5640_enum_code(struct v4l2_subdev *sd,
-                           struct v4l2_subdev_pad_config *cfg,
-                           struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->pad || code->index >= ARRAY_SIZE(ov5640_colour_fmts))
-               return -EINVAL;
-
-       code->code = ov5640_colour_fmts[code->index].code;
-       return 0;
-}
-
-/*!
- * ov5640_enum_framesizes - V4L2 sensor interface handler for
- *                        VIDIOC_ENUM_FRAMESIZES ioctl
- * @s: pointer to standard V4L2 device structure
- * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
- *
- * Return 0 if successful, otherwise -EINVAL.
- */
-static int ov5640_enum_framesizes(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_pad_config *cfg,
-                              struct v4l2_subdev_frame_size_enum *fse)
-{
-       if (fse->index > ov5640_mode_MAX)
-               return -EINVAL;
-
-       fse->max_width =
-                       max(ov5640_mode_info_data[0][fse->index].width,
-                           ov5640_mode_info_data[1][fse->index].width);
-       fse->min_width = fse->max_width;
-       fse->max_height =
-                       max(ov5640_mode_info_data[0][fse->index].height,
-                           ov5640_mode_info_data[1][fse->index].height);
-       fse->min_height = fse->max_height;
-       return 0;
-}
-
-/*!
- * ov5640_enum_frameintervals - V4L2 sensor interface handler for
- *                            VIDIOC_ENUM_FRAMEINTERVALS ioctl
- * @s: pointer to standard V4L2 device structure
- * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
- *
- * Return 0 if successful, otherwise -EINVAL.
- */
-static int ov5640_enum_frameintervals(struct v4l2_subdev *sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_frame_interval_enum *fie)
-{
-       int i, j, count;
-
-       if (fie->index < 0 || fie->index > ov5640_mode_MAX)
-               return -EINVAL;
-
-       if (fie->width == 0 || fie->height == 0 ||
-           fie->code == 0) {
-               pr_warning("Please assign pixel format, width and height.\n");
-               return -EINVAL;
-       }
-
-       fie->interval.numerator = 1;
-
-       count = 0;
-       for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
-               for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
-                       if (fie->width == ov5640_mode_info_data[i][j].width
-                        && fie->height == ov5640_mode_info_data[i][j].height
-                        && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
-                               count++;
-                       }
-                       if (fie->index == (count - 1)) {
-                               fie->interval.denominator =
-                                               ov5640_framerates[i];
-                               return 0;
-                       }
-               }
-       }
-
-       return -EINVAL;
-}
-
-static int ov5640_set_clk_rate(void)
-{
-       u32 tgt_xclk;   /* target xclk */
-       int ret;
-
-       /* mclk */
-       tgt_xclk = ov5640_data.mclk;
-       tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
-       tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
-       ov5640_data.mclk = tgt_xclk;
-
-       pr_debug("   Setting mclk to %d MHz\n", tgt_xclk / 1000000);
-       ret = clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk);
-       if (ret < 0)
-               pr_debug("set rate filed, rate=%d\n", ov5640_data.mclk);
-       return ret;
-}
-
-/*!
- * dev_init - V4L2 sensor init
- * @s: pointer to standard V4L2 device structure
- *
- */
-static int init_device(void)
-{
-       u32 tgt_xclk;   /* target xclk */
-       u32 tgt_fps;    /* target frames per secound */
-       enum ov5640_frame_rate frame_rate;
-       int ret;
-
-       ov5640_data.on = true;
-
-       /* mclk */
-       tgt_xclk = ov5640_data.mclk;
-
-       /* Default camera frame rate is set in probe */
-       tgt_fps = ov5640_data.streamcap.timeperframe.denominator /
-                 ov5640_data.streamcap.timeperframe.numerator;
-
-       if (tgt_fps == 15)
-               frame_rate = ov5640_15_fps;
-       else if (tgt_fps == 30)
-               frame_rate = ov5640_30_fps;
-       else
-               return -EINVAL; /* Only support 15fps or 30fps now. */
-
-       ret = ov5640_init_mode();
-
-       return ret;
-}
-
-static struct v4l2_subdev_video_ops ov5640_subdev_video_ops = {
-       .g_parm = ov5640_g_parm,
-       .s_parm = ov5640_s_parm,
-};
-
-static const struct v4l2_subdev_pad_ops ov5640_subdev_pad_ops = {
-       .enum_frame_size       = ov5640_enum_framesizes,
-       .enum_frame_interval   = ov5640_enum_frameintervals,
-       .enum_mbus_code        = ov5640_enum_code,
-       .set_fmt               = ov5640_set_fmt,
-       .get_fmt               = ov5640_get_fmt,
-};
-
-static struct v4l2_subdev_core_ops ov5640_subdev_core_ops = {
-       .s_power        = ov5640_s_power,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register     = ov5640_get_register,
-       .s_register     = ov5640_set_register,
-#endif
-};
-
-static struct v4l2_subdev_ops ov5640_subdev_ops = {
-       .core   = &ov5640_subdev_core_ops,
-       .video  = &ov5640_subdev_video_ops,
-       .pad    = &ov5640_subdev_pad_ops,
-};
-
-/*!
- * ov5640 I2C probe function
- *
- * @param adapter            struct i2c_adapter *
- * @return  Error code indicating success or failure
- */
-static int ov5640_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
-{
-       struct pinctrl *pinctrl;
-       struct device *dev = &client->dev;
-       int retval;
-       u8 chip_id_high, chip_id_low;
-
-       /* ov5640 pinctrl */
-       pinctrl = devm_pinctrl_get_select_default(dev);
-       if (IS_ERR(pinctrl)) {
-               dev_err(dev, "setup pinctrl failed\n");
-               return PTR_ERR(pinctrl);
-       }
-
-       /* request power down pin */
-       pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
-       if (!gpio_is_valid(pwn_gpio)) {
-               dev_err(dev, "no sensor pwdn pin available\n");
-               return -ENODEV;
-       }
-       retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
-                                       "ov5640_pwdn");
-       if (retval < 0)
-               return retval;
-
-       /* request reset pin */
-       rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
-       if (!gpio_is_valid(rst_gpio)) {
-               dev_err(dev, "no sensor reset pin available\n");
-               return -EINVAL;
-       }
-       retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
-                                       "ov5640_reset");
-       if (retval < 0)
-               return retval;
-
-       /* Set initial values for the sensor struct. */
-       memset(&ov5640_data, 0, sizeof(ov5640_data));
-       ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
-       if (IS_ERR(ov5640_data.sensor_clk)) {
-               dev_err(dev, "get mclk failed\n");
-               return PTR_ERR(ov5640_data.sensor_clk);
-       }
-
-       retval = of_property_read_u32(dev->of_node, "mclk",
-                                       &ov5640_data.mclk);
-       if (retval) {
-               dev_err(dev, "mclk frequency is invalid\n");
-               return retval;
-       }
-
-       retval = of_property_read_u32(dev->of_node, "mclk_source",
-                                       (u32 *) &(ov5640_data.mclk_source));
-       if (retval) {
-               dev_err(dev, "mclk_source invalid\n");
-               return retval;
-       }
-
-       retval = of_property_read_u32(dev->of_node, "csi_id",
-                                       &(ov5640_data.csi));
-       if (retval) {
-               dev_err(dev, "csi_id invalid\n");
-               return retval;
-       }
-
-       /* Set mclk rate before clk on */
-       ov5640_set_clk_rate();
-
-       clk_prepare_enable(ov5640_data.sensor_clk);
-
-       ov5640_data.io_init = ov5640_reset;
-       ov5640_data.i2c_client = client;
-       ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-       ov5640_data.pix.width = 640;
-       ov5640_data.pix.height = 480;
-       ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
-                                          V4L2_CAP_TIMEPERFRAME;
-       ov5640_data.streamcap.capturemode = 0;
-       ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
-       ov5640_data.streamcap.timeperframe.numerator = 1;
-
-       ov5640_regulator_enable(&client->dev);
-
-       ov5640_reset();
-
-       ov5640_power_down(0);
-
-       retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
-       if (retval < 0 || chip_id_high != 0x56) {
-               clk_disable_unprepare(ov5640_data.sensor_clk);
-               pr_warning("camera ov5640 is not found\n");
-               return -ENODEV;
-       }
-       retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
-       if (retval < 0 || chip_id_low != 0x40) {
-               clk_disable_unprepare(ov5640_data.sensor_clk);
-               pr_warning("camera ov5640 is not found\n");
-               return -ENODEV;
-       }
-
-       retval = init_device();
-       if (retval < 0) {
-               clk_disable_unprepare(ov5640_data.sensor_clk);
-               pr_warning("camera ov5640 init failed\n");
-               ov5640_power_down(1);
-               return retval;
-       }
-
-       clk_disable(ov5640_data.sensor_clk);
-
-       v4l2_i2c_subdev_init(&ov5640_data.subdev, client, &ov5640_subdev_ops);
-
-       retval = v4l2_async_register_subdev(&ov5640_data.subdev);
-       if (retval < 0)
-               dev_err(&client->dev,
-                                       "%s--Async register failed, ret=%d\n", __func__, retval);
-
-       pr_info("camera ov5640, is found\n");
-       return retval;
-}
-
-/*!
- * ov5640 I2C detach function
- *
- * @param client            struct i2c_client *
- * @return  Error code indicating success or failure
- */
-static int ov5640_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-       v4l2_async_unregister_subdev(sd);
-
-       clk_unprepare(ov5640_data.sensor_clk);
-
-       ov5640_power_down(1);
-
-       if (analog_regulator)
-               regulator_disable(analog_regulator);
-
-       if (core_regulator)
-               regulator_disable(core_regulator);
-
-       if (io_regulator)
-               regulator_disable(io_regulator);
-
-       return 0;
-}
-
-module_i2c_driver(ov5640_i2c_driver);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("OV5640 Camera Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/subdev/ov5640_mipi.c b/drivers/media/platform/mxc/subdev/ov5640_mipi.c
deleted file mode 100644 (file)
index 4ea4f6a..0000000
+++ /dev/null
@@ -1,1660 +0,0 @@
-/*
- * Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/of_device.h>
-#include <linux/i2c.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/regulator/consumer.h>
-#include <linux/v4l2-mediabus.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-#define OV5640_VOLTAGE_ANALOG               2800000
-#define OV5640_VOLTAGE_DIGITAL_CORE         1500000
-#define OV5640_VOLTAGE_DIGITAL_IO           1800000
-
-#define MIN_FPS 15
-#define MAX_FPS 30
-#define DEFAULT_FPS 30
-
-#define OV5640_XCLK_MIN 6000000
-#define OV5640_XCLK_MAX 24000000
-
-#define OV5640_CHIP_ID_HIGH_BYTE       0x300A
-#define OV5640_CHIP_ID_LOW_BYTE                0x300B
-
-enum ov5640_mode {
-       ov5640_mode_MIN = 0,
-       ov5640_mode_VGA_640_480 = 0,
-       ov5640_mode_NTSC_720_480 = 1,
-       ov5640_mode_720P_1280_720 = 2,
-       ov5640_mode_1080P_1920_1080 = 3,
-       ov5640_mode_QSXGA_2592_1944 = 4,
-       ov5640_mode_MAX = 5,
-       ov5640_mode_INIT = 0xff, /*only for sensor init*/
-};
-
-enum ov5640_frame_rate {
-       ov5640_15_fps,
-       ov5640_30_fps
-};
-
-static int ov5640_framerates[] = {
-       [ov5640_15_fps] = 15,
-       [ov5640_30_fps] = 30,
-};
-
-struct ov5640_datafmt {
-       u32     code;
-       enum v4l2_colorspace            colorspace;
-};
-
-/* image size under 1280 * 960 are SUBSAMPLING
- * image size upper 1280 * 960 are SCALING
- */
-enum ov5640_downsize_mode {
-       SUBSAMPLING,
-       SCALING,
-};
-
-struct reg_value {
-       u16 u16RegAddr;
-       u8 u8Val;
-       u8 u8Mask;
-       u32 u32Delay_ms;
-};
-
-struct ov5640_mode_info {
-       enum ov5640_mode mode;
-       enum ov5640_downsize_mode dn_mode;
-       u32 width;
-       u32 height;
-       struct reg_value *init_data_ptr;
-       u32 init_data_size;
-};
-
-struct ov5640 {
-       struct v4l2_subdev              subdev;
-       struct i2c_client *i2c_client;
-       struct v4l2_pix_format pix;
-       const struct ov5640_datafmt     *fmt;
-       struct v4l2_captureparm streamcap;
-       bool on;
-
-       /* control settings */
-       int brightness;
-       int hue;
-       int contrast;
-       int saturation;
-       int red;
-       int green;
-       int blue;
-       int ae_mode;
-
-       u32 mclk;
-       u8 mclk_source;
-       struct clk *sensor_clk;
-       int csi;
-
-       void (*io_init)(void);
-};
-/*!
- * Maintains the information on the current state of the sesor.
- */
-static struct ov5640 ov5640_data;
-static int pwn_gpio, rst_gpio;
-
-static struct reg_value ov5640_init_setting_30fps_VGA[] = {
-
-       {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
-       {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
-       {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
-       {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
-       {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
-       {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
-       {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
-       {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
-       {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
-       {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
-       {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
-       {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
-       {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
-       {0x3c01, 0xa4, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
-       {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
-       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
-       {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
-       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
-       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
-       {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
-       {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x30, 0, 0},
-       {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
-       {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-       {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0},
-       {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
-       {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
-       {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
-       {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0},
-       {0x518a, 0x54, 0, 0}, {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0},
-       {0x518d, 0x50, 0, 0}, {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0},
-       {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0},
-       {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0},
-       {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0},
-       {0x5199, 0x6c, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0},
-       {0x519c, 0x09, 0, 0}, {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0},
-       {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0},
-       {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0},
-       {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0},
-       {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0},
-       {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0},
-       {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0},
-       {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0},
-       {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0},
-       {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0},
-       {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0},
-       {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0},
-       {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0},
-       {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0},
-       {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0},
-       {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0},
-       {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0},
-       {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0},
-       {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0},
-       {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0},
-       {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0},
-       {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0},
-       {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0},
-       {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0},
-       {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0},
-       {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0},
-       {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0},
-       {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0},
-       {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0},
-       {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0},
-       {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0},
-       {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0},
-       {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0},
-       {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0},
-       {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0},
-       {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0},
-       {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0},
-       {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0},
-       {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0},
-       {0x3a1f, 0x14, 0, 0}, {0x3008, 0x42, 0, 0}, {0x3c00, 0x04, 0, 300},
-};
-
-static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
-       {0x3008, 0x42, 0, 0},
-       {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
-       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
-       {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
-       {0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
-       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
-       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
-       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
-       {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0x00, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
-       {0x3008, 0x42, 0, 0},
-       {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
-       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-       {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
-       {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
-       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
-       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
-       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
-       {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
-       {0x3008, 0x42, 0, 0},
-       {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
-       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-       {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
-       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
-       {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
-       {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
-       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-       {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
-       {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
-       {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
-       {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
-       {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
-       {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
-       {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, {0x4005, 0x1a, 0, 0},
-       {0x3008, 0x02, 0, 0}, {0x3503, 0,    0, 0},
-};
-
-static struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
-       {0x3008, 0x42, 0, 0},
-       {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
-       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-       {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
-       {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
-       {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
-       {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
-       {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
-       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
-       {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
-       {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
-       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-       {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
-       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-       {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
-       {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
-       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-       {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
-       {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
-       {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
-       {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
-       {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
-       {0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
-       {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
-       {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
-       {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
-       {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
-       {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
-       {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0},
-       {0x3503, 0, 0, 0},
-};
-
-static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
-       {0x3008, 0x42, 0, 0},
-       {0x4202, 0x0f, 0, 0},   /* stream off the sensor */
-       {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, /*disable flip*/
-       {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
-       {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-       {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
-       {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
-       {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
-       {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
-       {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
-       {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
-       {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
-       {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
-       {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-       {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-       {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
-       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-       {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70}, {0x3008, 0x02, 0, 0},
-       {0x4202, 0x00, 0, 0},   /* stream on the sensor */
-};
-
-static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
-       {
-               {ov5640_mode_VGA_640_480, -1, 0, 0, NULL, 0},
-               {ov5640_mode_NTSC_720_480, -1, 0, 0, NULL, 0},
-               {ov5640_mode_720P_1280_720, -1, 0, 0, NULL, 0},
-               {ov5640_mode_1080P_1920_1080, -1, 0, 0, NULL, 0},
-               {ov5640_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
-               ov5640_setting_15fps_QSXGA_2592_1944,
-               ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
-       },
-       {
-               {ov5640_mode_VGA_640_480, SUBSAMPLING, 640,  480,
-               ov5640_setting_30fps_VGA_640_480,
-               ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
-               {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
-               ov5640_setting_30fps_NTSC_720_480,
-               ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
-               {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
-               ov5640_setting_30fps_720P_1280_720,
-               ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
-               {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
-               ov5640_setting_30fps_1080P_1920_1080,
-               ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
-               {ov5640_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
-       },
-};
-
-static struct regulator *io_regulator;
-static struct regulator *core_regulator;
-static struct regulator *analog_regulator;
-static struct regulator *gpo_regulator;
-
-static int ov5640_probe(struct i2c_client *adapter,
-                               const struct i2c_device_id *device_id);
-static int ov5640_remove(struct i2c_client *client);
-
-static s32 ov5640_read_reg(u16 reg, u8 *val);
-static s32 ov5640_write_reg(u16 reg, u8 val);
-
-static const struct i2c_device_id ov5640_id[] = {
-       {"ov5640_mipi", 0},
-       {},
-};
-
-MODULE_DEVICE_TABLE(i2c, ov5640_id);
-
-static struct i2c_driver ov5640_i2c_driver = {
-       .driver = {
-                 .owner = THIS_MODULE,
-                 .name  = "ov5640_mipi",
-                 },
-       .probe  = ov5640_probe,
-       .remove = ov5640_remove,
-       .id_table = ov5640_id,
-};
-
-static const struct ov5640_datafmt ov5640_colour_fmts[] = {
-       {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
-};
-
-static struct ov5640 *to_ov5640(const struct i2c_client *client)
-{
-       return container_of(i2c_get_clientdata(client), struct ov5640, subdev);
-}
-
-/* Find a data format by a pixel code in an array */
-static const struct ov5640_datafmt
-                       *ov5640_find_datafmt(u32 code)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ov5640_colour_fmts); i++)
-               if (ov5640_colour_fmts[i].code == code)
-                       return ov5640_colour_fmts + i;
-
-       return NULL;
-}
-
-static inline void ov5640_power_down(int enable)
-{
-       if (pwn_gpio < 0)
-               return;
-
-       if (!enable)
-               gpio_set_value_cansleep(pwn_gpio, 0);
-       else
-               gpio_set_value_cansleep(pwn_gpio, 1);
-
-       msleep(2);
-}
-
-static void ov5640_reset(void)
-{
-       if (rst_gpio < 0 || pwn_gpio < 0)
-               return;
-
-       /* camera reset */
-       gpio_set_value(rst_gpio, 1);
-
-       /* camera power dowmn */
-       gpio_set_value(pwn_gpio, 1);
-       msleep(5);
-
-       gpio_set_value(pwn_gpio, 0);
-       msleep(5);
-
-       gpio_set_value(rst_gpio, 0);
-       msleep(1);
-
-       gpio_set_value(rst_gpio, 1);
-       msleep(5);
-
-       gpio_set_value(pwn_gpio, 1);
-}
-
-static int ov5640_regulator_enable(struct device *dev)
-{
-       int ret = 0;
-
-       io_regulator = devm_regulator_get(dev, "DOVDD");
-       if (!IS_ERR(io_regulator)) {
-               regulator_set_voltage(io_regulator,
-                                     OV5640_VOLTAGE_DIGITAL_IO,
-                                     OV5640_VOLTAGE_DIGITAL_IO);
-               ret = regulator_enable(io_regulator);
-               if (ret) {
-                       pr_err("%s:io set voltage error\n", __func__);
-                       return ret;
-               } else {
-                       dev_dbg(dev,
-                               "%s:io set voltage ok\n", __func__);
-               }
-       } else {
-               pr_err("%s: cannot get io voltage error\n", __func__);
-               io_regulator = NULL;
-       }
-
-       core_regulator = devm_regulator_get(dev, "DVDD");
-       if (!IS_ERR(core_regulator)) {
-               regulator_set_voltage(core_regulator,
-                                     OV5640_VOLTAGE_DIGITAL_CORE,
-                                     OV5640_VOLTAGE_DIGITAL_CORE);
-               ret = regulator_enable(core_regulator);
-               if (ret) {
-                       pr_err("%s:core set voltage error\n", __func__);
-                       return ret;
-               } else {
-                       dev_dbg(dev,
-                               "%s:core set voltage ok\n", __func__);
-               }
-       } else {
-               core_regulator = NULL;
-               pr_err("%s: cannot get core voltage error\n", __func__);
-       }
-
-       analog_regulator = devm_regulator_get(dev, "AVDD");
-       if (!IS_ERR(analog_regulator)) {
-               regulator_set_voltage(analog_regulator,
-                                     OV5640_VOLTAGE_ANALOG,
-                                     OV5640_VOLTAGE_ANALOG);
-               ret = regulator_enable(analog_regulator);
-               if (ret) {
-                       pr_err("%s:analog set voltage error\n",
-                               __func__);
-                       return ret;
-               } else {
-                       dev_dbg(dev,
-                               "%s:analog set voltage ok\n", __func__);
-               }
-       } else {
-               analog_regulator = NULL;
-               pr_err("%s: cannot get analog voltage error\n", __func__);
-       }
-
-       return ret;
-}
-
-static s32 ov5640_write_reg(u16 reg, u8 val)
-{
-       u8 au8Buf[3] = {0};
-
-       au8Buf[0] = reg >> 8;
-       au8Buf[1] = reg & 0xff;
-       au8Buf[2] = val;
-
-       if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
-               pr_err("%s:write reg error:reg=%x,val=%x\n",
-                       __func__, reg, val);
-               return -1;
-       }
-
-       return 0;
-}
-
-static s32 ov5640_read_reg(u16 reg, u8 *val)
-{
-       u8 au8RegBuf[2] = {0};
-       u8 u8RdVal = 0;
-
-       au8RegBuf[0] = reg >> 8;
-       au8RegBuf[1] = reg & 0xff;
-
-       if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
-               pr_err("%s:write reg error:reg=%x\n",
-                               __func__, reg);
-               return -1;
-       }
-
-       if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
-               pr_err("%s:read reg error:reg=%x,val=%x\n",
-                               __func__, reg, u8RdVal);
-               return -1;
-       }
-
-       *val = u8RdVal;
-
-       return u8RdVal;
-}
-
-static int prev_sysclk, prev_HTS;
-static int AE_low, AE_high, AE_Target = 52;
-
-static void OV5640_stream_on(void)
-{
-       ov5640_write_reg(0x4202, 0x00);
-}
-
-static void OV5640_stream_off(void)
-{
-       ov5640_write_reg(0x4202, 0x0f);
-       ov5640_write_reg(0x3008, 0x42);
-}
-
-static int OV5640_get_sysclk(void)
-{
-        /* calculate sysclk */
-       int xvclk = ov5640_data.mclk / 10000;
-       int temp1, temp2;
-       int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv;
-       int Bit_div2x = 1, sclk_rdiv, sysclk;
-       u8 temp;
-
-       int sclk_rdiv_map[] = {1, 2, 4, 8};
-
-       temp1 = ov5640_read_reg(0x3034, &temp);
-       temp2 = temp1 & 0x0f;
-       if (temp2 == 8 || temp2 == 10)
-               Bit_div2x = temp2 / 2;
-
-       temp1 = ov5640_read_reg(0x3035, &temp);
-       SysDiv = temp1>>4;
-       if (SysDiv == 0)
-               SysDiv = 16;
-
-       temp1 = ov5640_read_reg(0x3036, &temp);
-       Multiplier = temp1;
-
-       temp1 = ov5640_read_reg(0x3037, &temp);
-       PreDiv = temp1 & 0x0f;
-       Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
-
-       temp1 = ov5640_read_reg(0x3108, &temp);
-       temp2 = temp1 & 0x03;
-       sclk_rdiv = sclk_rdiv_map[temp2];
-
-       VCO = xvclk * Multiplier / PreDiv;
-
-       sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
-
-       return sysclk;
-}
-
-static void OV5640_set_night_mode(void)
-{
-        /* read HTS from register settings */
-       u8 mode;
-
-       ov5640_read_reg(0x3a00, &mode);
-       mode &= 0xfb;
-       ov5640_write_reg(0x3a00, mode);
-}
-
-static int OV5640_get_HTS(void)
-{
-        /* read HTS from register settings */
-       int HTS;
-       u8 temp;
-
-       HTS = ov5640_read_reg(0x380c, &temp);
-       HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
-
-       return HTS;
-}
-
-static int OV5640_get_VTS(void)
-{
-        /* read VTS from register settings */
-       int VTS;
-       u8 temp;
-
-       /* total vertical size[15:8] high byte */
-       VTS = ov5640_read_reg(0x380e, &temp);
-
-       VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
-
-       return VTS;
-}
-
-static int OV5640_set_VTS(int VTS)
-{
-        /* write VTS to registers */
-        int temp;
-
-        temp = VTS & 0xff;
-        ov5640_write_reg(0x380f, temp);
-
-        temp = VTS>>8;
-        ov5640_write_reg(0x380e, temp);
-
-        return 0;
-}
-
-static int OV5640_get_shutter(void)
-{
-        /* read shutter, in number of line period */
-       int shutter;
-       u8 temp;
-
-       shutter = (ov5640_read_reg(0x03500, &temp) & 0x0f);
-       shutter = (shutter<<8) + ov5640_read_reg(0x3501, &temp);
-       shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &temp)>>4);
-
-        return shutter;
-}
-
-static int OV5640_set_shutter(int shutter)
-{
-        /* write shutter, in number of line period */
-        int temp;
-
-        shutter = shutter & 0xffff;
-
-        temp = shutter & 0x0f;
-        temp = temp<<4;
-        ov5640_write_reg(0x3502, temp);
-
-        temp = shutter & 0xfff;
-        temp = temp>>4;
-        ov5640_write_reg(0x3501, temp);
-
-        temp = shutter>>12;
-        ov5640_write_reg(0x3500, temp);
-
-        return 0;
-}
-
-static int OV5640_get_gain16(void)
-{
-        /* read gain, 16 = 1x */
-       int gain16;
-       u8 temp;
-
-       gain16 = ov5640_read_reg(0x350a, &temp) & 0x03;
-       gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &temp);
-
-       return gain16;
-}
-
-static int OV5640_set_gain16(int gain16)
-{
-       /* write gain, 16 = 1x */
-       u8 temp;
-       gain16 = gain16 & 0x3ff;
-
-       temp = gain16 & 0xff;
-       ov5640_write_reg(0x350b, temp);
-
-       temp = gain16>>8;
-       ov5640_write_reg(0x350a, temp);
-
-       return 0;
-}
-
-static int OV5640_get_light_freq(void)
-{
-       /* get banding filter value */
-       int temp, temp1, light_freq = 0;
-       u8 tmp;
-
-       temp = ov5640_read_reg(0x3c01, &tmp);
-
-       if (temp & 0x80) {
-               /* manual */
-               temp1 = ov5640_read_reg(0x3c00, &tmp);
-               if (temp1 & 0x04) {
-                       /* 50Hz */
-                       light_freq = 50;
-               } else {
-                       /* 60Hz */
-                       light_freq = 60;
-               }
-       } else {
-               /* auto */
-               temp1 = ov5640_read_reg(0x3c0c, &tmp);
-               if (temp1 & 0x01) {
-                       /* 50Hz */
-                       light_freq = 50;
-               } else {
-                       /* 60Hz */
-               }
-       }
-       return light_freq;
-}
-
-static void OV5640_set_bandingfilter(void)
-{
-       int prev_VTS;
-       int band_step60, max_band60, band_step50, max_band50;
-
-       /* read preview PCLK */
-       prev_sysclk = OV5640_get_sysclk();
-       /* read preview HTS */
-       prev_HTS = OV5640_get_HTS();
-
-       /* read preview VTS */
-       prev_VTS = OV5640_get_VTS();
-
-       /* calculate banding filter */
-       /* 60Hz */
-       band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
-       ov5640_write_reg(0x3a0a, (band_step60 >> 8));
-       ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
-
-       max_band60 = (int)((prev_VTS-4)/band_step60);
-       ov5640_write_reg(0x3a0d, max_band60);
-
-       /* 50Hz */
-       band_step50 = prev_sysclk * 100/prev_HTS;
-       ov5640_write_reg(0x3a08, (band_step50 >> 8));
-       ov5640_write_reg(0x3a09, (band_step50 & 0xff));
-
-       max_band50 = (int)((prev_VTS-4)/band_step50);
-       ov5640_write_reg(0x3a0e, max_band50);
-}
-
-static int OV5640_set_AE_target(int target)
-{
-       /* stable in high */
-       int fast_high, fast_low;
-       AE_low = target * 23 / 25;      /* 0.92 */
-       AE_high = target * 27 / 25;     /* 1.08 */
-
-       fast_high = AE_high<<1;
-       if (fast_high > 255)
-               fast_high = 255;
-
-       fast_low = AE_low >> 1;
-
-       ov5640_write_reg(0x3a0f, AE_high);
-       ov5640_write_reg(0x3a10, AE_low);
-       ov5640_write_reg(0x3a1b, AE_high);
-       ov5640_write_reg(0x3a1e, AE_low);
-       ov5640_write_reg(0x3a11, fast_high);
-       ov5640_write_reg(0x3a1f, fast_low);
-
-       return 0;
-}
-
-static void OV5640_turn_on_AE_AG(int enable)
-{
-       u8 ae_ag_ctrl;
-
-       ov5640_read_reg(0x3503, &ae_ag_ctrl);
-       if (enable) {
-               /* turn on auto AE/AG */
-               ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
-       } else {
-               /* turn off AE/AG */
-               ae_ag_ctrl = ae_ag_ctrl | 0x03;
-       }
-       ov5640_write_reg(0x3503, ae_ag_ctrl);
-}
-
-static bool binning_on(void)
-{
-       u8 temp;
-       ov5640_read_reg(0x3821, &temp);
-       temp &= 0xfe;
-       if (temp)
-               return true;
-       else
-               return false;
-}
-
-static void ov5640_set_virtual_channel(int channel)
-{
-       u8 channel_id;
-
-       ov5640_read_reg(0x4814, &channel_id);
-       channel_id &= ~(3 << 6);
-       ov5640_write_reg(0x4814, channel_id | (channel << 6));
-}
-
-/* download ov5640 settings to sensor through i2c */
-static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
-{
-       register u32 Delay_ms = 0;
-       register u16 RegAddr = 0;
-       register u8 Mask = 0;
-       register u8 Val = 0;
-       u8 RegVal = 0;
-       int i, retval = 0;
-
-       for (i = 0; i < ArySize; ++i, ++pModeSetting) {
-               Delay_ms = pModeSetting->u32Delay_ms;
-               RegAddr = pModeSetting->u16RegAddr;
-               Val = pModeSetting->u8Val;
-               Mask = pModeSetting->u8Mask;
-
-               if (Mask) {
-                       retval = ov5640_read_reg(RegAddr, &RegVal);
-                       if (retval < 0)
-                               goto err;
-
-                       RegVal &= ~(u8)Mask;
-                       Val &= Mask;
-                       Val |= RegVal;
-               }
-
-               retval = ov5640_write_reg(RegAddr, Val);
-               if (retval < 0)
-                       goto err;
-
-               if (Delay_ms)
-                       msleep(Delay_ms);
-       }
-err:
-       return retval;
-}
-
-/* sensor changes between scaling and subsampling
- * go through exposure calcualtion
- */
-static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
-                               enum ov5640_mode mode)
-{
-       struct reg_value *pModeSetting = NULL;
-       s32 ArySize = 0;
-       u8 average;
-       int prev_shutter, prev_gain16;
-       int cap_shutter, cap_gain16;
-       int cap_sysclk, cap_HTS, cap_VTS;
-       int light_freq, cap_bandfilt, cap_maxband;
-       long cap_gain16_shutter;
-       int retval = 0;
-
-       /* check if the input mode and frame rate is valid */
-       pModeSetting =
-               ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
-       ArySize =
-               ov5640_mode_info_data[frame_rate][mode].init_data_size;
-
-       ov5640_data.pix.width =
-               ov5640_mode_info_data[frame_rate][mode].width;
-       ov5640_data.pix.height =
-               ov5640_mode_info_data[frame_rate][mode].height;
-
-       if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
-               pModeSetting == NULL || ArySize == 0)
-               return -EINVAL;
-
-       /* auto focus */
-       /* OV5640_auto_focus();//if no af function, just skip it */
-
-       /* turn off AE/AG */
-       OV5640_turn_on_AE_AG(0);
-
-       /* read preview shutter */
-       prev_shutter = OV5640_get_shutter();
-       if ((binning_on()) && (mode != ov5640_mode_720P_1280_720)
-                       && (mode != ov5640_mode_1080P_1920_1080))
-               prev_shutter *= 2;
-
-       /* read preview gain */
-       prev_gain16 = OV5640_get_gain16();
-
-       /* get average */
-       ov5640_read_reg(0x56a1, &average);
-
-       /* turn off night mode for capture */
-       OV5640_set_night_mode();
-
-       /* turn off overlay */
-       /* ov5640_write_reg(0x3022, 0x06);//if no af function, just skip it */
-
-       OV5640_stream_off();
-
-       /* Write capture setting */
-       retval = ov5640_download_firmware(pModeSetting, ArySize);
-       if (retval < 0)
-               goto err;
-
-       /* read capture VTS */
-       cap_VTS = OV5640_get_VTS();
-       cap_HTS = OV5640_get_HTS();
-       cap_sysclk = OV5640_get_sysclk();
-
-       /* calculate capture banding filter */
-       light_freq = OV5640_get_light_freq();
-       if (light_freq == 60) {
-               /* 60Hz */
-               cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
-       } else {
-               /* 50Hz */
-               cap_bandfilt = cap_sysclk * 100 / cap_HTS;
-       }
-       cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
-
-       /* calculate capture shutter/gain16 */
-       if (average > AE_low && average < AE_high) {
-               /* in stable range */
-               cap_gain16_shutter =
-                 prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
-                 * prev_HTS/cap_HTS * AE_Target / average;
-       } else {
-               cap_gain16_shutter =
-                 prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
-                 * prev_HTS/cap_HTS;
-       }
-
-       /* gain to shutter */
-       if (cap_gain16_shutter < (cap_bandfilt * 16)) {
-               /* shutter < 1/100 */
-               cap_shutter = cap_gain16_shutter/16;
-               if (cap_shutter < 1)
-                       cap_shutter = 1;
-
-               cap_gain16 = cap_gain16_shutter/cap_shutter;
-               if (cap_gain16 < 16)
-                       cap_gain16 = 16;
-       } else {
-               if (cap_gain16_shutter >
-                               (cap_bandfilt * cap_maxband * 16)) {
-                       /* exposure reach max */
-                       cap_shutter = cap_bandfilt * cap_maxband;
-                       cap_gain16 = cap_gain16_shutter / cap_shutter;
-               } else {
-                       /* 1/100 < (cap_shutter = n/100) =< max */
-                       cap_shutter =
-                         ((int) (cap_gain16_shutter/16 / cap_bandfilt))
-                         *cap_bandfilt;
-                       cap_gain16 = cap_gain16_shutter / cap_shutter;
-               }
-       }
-
-       /* write capture gain */
-       OV5640_set_gain16(cap_gain16);
-
-       /* write capture shutter */
-       if (cap_shutter > (cap_VTS - 4)) {
-               cap_VTS = cap_shutter + 4;
-               OV5640_set_VTS(cap_VTS);
-       }
-       OV5640_set_shutter(cap_shutter);
-
-err:
-       return retval;
-}
-
-/* if sensor changes inside scaling or subsampling
- * change mode directly
- * */
-static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
-                               enum ov5640_mode mode)
-{
-       struct reg_value *pModeSetting = NULL;
-       s32 ArySize = 0;
-       int retval = 0;
-
-       /* check if the input mode and frame rate is valid */
-       pModeSetting =
-               ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
-       ArySize =
-               ov5640_mode_info_data[frame_rate][mode].init_data_size;
-
-       ov5640_data.pix.width =
-               ov5640_mode_info_data[frame_rate][mode].width;
-       ov5640_data.pix.height =
-               ov5640_mode_info_data[frame_rate][mode].height;
-
-       if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
-               pModeSetting == NULL || ArySize == 0)
-               return -EINVAL;
-
-       /* turn off AE/AG */
-       OV5640_turn_on_AE_AG(0);
-
-       OV5640_stream_off();
-
-       /* Write capture setting */
-       retval = ov5640_download_firmware(pModeSetting, ArySize);
-       if (retval < 0)
-               goto err;
-
-       OV5640_turn_on_AE_AG(1);
-
-err:
-       return retval;
-}
-
-static int ov5640_init_mode(enum ov5640_frame_rate frame_rate,
-                           enum ov5640_mode mode, enum ov5640_mode orig_mode)
-{
-       struct reg_value *pModeSetting = NULL;
-       s32 ArySize = 0;
-       int retval = 0;
-       u32 msec_wait4stable = 0;
-       enum ov5640_downsize_mode dn_mode, orig_dn_mode;
-
-       if ((mode > ov5640_mode_MAX || mode < ov5640_mode_MIN)
-               && (mode != ov5640_mode_INIT)) {
-               pr_err("Wrong ov5640 mode detected!\n");
-               return -1;
-       }
-
-       dn_mode = ov5640_mode_info_data[frame_rate][mode].dn_mode;
-       orig_dn_mode = ov5640_mode_info_data[frame_rate][orig_mode].dn_mode;
-       if (mode == ov5640_mode_INIT) {
-               pModeSetting = ov5640_init_setting_30fps_VGA;
-               ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
-
-               ov5640_data.pix.width = 640;
-               ov5640_data.pix.height = 480;
-               retval = ov5640_download_firmware(pModeSetting, ArySize);
-               if (retval < 0)
-                       goto err;
-
-               pModeSetting = ov5640_setting_30fps_VGA_640_480;
-               ArySize = ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480);
-               retval = ov5640_download_firmware(pModeSetting, ArySize);
-       } else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
-                       (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
-               /* change between subsampling and scaling
-                * go through exposure calucation */
-               retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
-       } else {
-               /* change inside subsampling or scaling
-                * download firmware directly */
-               retval = ov5640_change_mode_direct(frame_rate, mode);
-       }
-
-       if (retval < 0)
-               goto err;
-
-       OV5640_set_AE_target(AE_Target);
-       OV5640_get_light_freq();
-       OV5640_set_bandingfilter();
-       ov5640_set_virtual_channel(ov5640_data.csi);
-
-       /* add delay to wait for sensor stable */
-       if (mode == ov5640_mode_QSXGA_2592_1944) {
-               /* dump the first two frames: 1/7.5*2
-                * the frame rate of QSXGA is 7.5fps */
-               msec_wait4stable = 267;
-       } else {
-               /* dump the first eighteen frames: 1/30*18 */
-               msec_wait4stable = 600;
-       }
-       msleep(msec_wait4stable);
-
-err:
-       return retval;
-}
-
-/*!
- * ov5640_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
- * @s: pointer to standard V4L2 device structure
- * @on: indicates power mode (on or off)
- *
- * Turns the power on or off, depending on the value of on and returns the
- * appropriate error code.
- */
-static int ov5640_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-
-       if (on && !sensor->on) {
-               if (io_regulator)
-                       if (regulator_enable(io_regulator) != 0)
-                               return -EIO;
-               if (core_regulator)
-                       if (regulator_enable(core_regulator) != 0)
-                               return -EIO;
-               if (gpo_regulator)
-                       if (regulator_enable(gpo_regulator) != 0)
-                               return -EIO;
-               if (analog_regulator)
-                       if (regulator_enable(analog_regulator) != 0)
-                               return -EIO;
-       } else if (!on && sensor->on) {
-               if (analog_regulator)
-                       regulator_disable(analog_regulator);
-               if (core_regulator)
-                       regulator_disable(core_regulator);
-               if (io_regulator)
-                       regulator_disable(io_regulator);
-               if (gpo_regulator)
-                       regulator_disable(gpo_regulator);
-       }
-
-       sensor->on = on;
-
-       return 0;
-}
-
-/*!
- * ov5640_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
- * @s: pointer to standard V4L2 sub device structure
- * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
- *
- * Returns the sensor's video CAPTURE parameters.
- */
-static int ov5640_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-       struct v4l2_captureparm *cparm = &a->parm.capture;
-       int ret = 0;
-
-       switch (a->type) {
-       /* This is the only case currently handled. */
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               memset(a, 0, sizeof(*a));
-               a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               cparm->capability = sensor->streamcap.capability;
-               cparm->timeperframe = sensor->streamcap.timeperframe;
-               cparm->capturemode = sensor->streamcap.capturemode;
-               ret = 0;
-               break;
-
-       /* These are all the possible cases. */
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_VBI_OUTPUT:
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               ret = -EINVAL;
-               break;
-
-       default:
-               pr_debug("   type is unknown - %d\n", a->type);
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
-}
-
-/*!
- * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
- * @s: pointer to standard V4L2 sub device structure
- * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
- *
- * Configures the sensor to use the input parameters, if possible.  If
- * not possible, reverts to the old parameters and returns the
- * appropriate error code.
- */
-static int ov5640_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
-       u32 tgt_fps;    /* target frames per secound */
-       enum ov5640_frame_rate frame_rate;
-       enum ov5640_mode orig_mode;
-       int ret = 0;
-
-       switch (a->type) {
-       /* This is the only case currently handled. */
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               /* Check that the new frame rate is allowed. */
-               if ((timeperframe->numerator == 0) ||
-                   (timeperframe->denominator == 0)) {
-                       timeperframe->denominator = DEFAULT_FPS;
-                       timeperframe->numerator = 1;
-               }
-
-               tgt_fps = timeperframe->denominator /
-                         timeperframe->numerator;
-
-               if (tgt_fps > MAX_FPS) {
-                       timeperframe->denominator = MAX_FPS;
-                       timeperframe->numerator = 1;
-               } else if (tgt_fps < MIN_FPS) {
-                       timeperframe->denominator = MIN_FPS;
-                       timeperframe->numerator = 1;
-               }
-
-               /* Actual frame rate we use */
-               tgt_fps = timeperframe->denominator /
-                         timeperframe->numerator;
-
-               if (tgt_fps == 15)
-                       frame_rate = ov5640_15_fps;
-               else if (tgt_fps == 30)
-                       frame_rate = ov5640_30_fps;
-               else {
-                       pr_err(" The camera frame rate is not supported!\n");
-                       return -EINVAL;
-               }
-
-               orig_mode = sensor->streamcap.capturemode;
-               ret = ov5640_init_mode(frame_rate,
-                               (u32)a->parm.capture.capturemode, orig_mode);
-               if (ret < 0)
-                       return ret;
-
-               sensor->streamcap.timeperframe = *timeperframe;
-               sensor->streamcap.capturemode =
-                               (u32)a->parm.capture.capturemode;
-
-               break;
-
-       /* These are all the possible cases. */
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_VBI_OUTPUT:
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               pr_debug("   type is not " \
-                       "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
-                       a->type);
-               ret = -EINVAL;
-               break;
-
-       default:
-               pr_debug("   type is unknown - %d\n", a->type);
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
-}
-
-static int ov5640_set_fmt(struct v4l2_subdev *sd,
-                       struct v4l2_subdev_pad_config *cfg,
-                       struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf = &format->format;
-       const struct ov5640_datafmt *fmt = ov5640_find_datafmt(mf->code);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-
-       if (!fmt) {
-               mf->code        = ov5640_colour_fmts[0].code;
-               mf->colorspace  = ov5640_colour_fmts[0].colorspace;
-       }
-
-       mf->field       = V4L2_FIELD_NONE;
-
-       if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-               return 0;
-
-       sensor->fmt = fmt;
-
-       return 0;
-}
-
-
-static int ov5640_get_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_pad_config *cfg,
-                         struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf = &format->format;
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5640 *sensor = to_ov5640(client);
-       const struct ov5640_datafmt *fmt = sensor->fmt;
-
-       if (format->pad)
-               return -EINVAL;
-
-       mf->code        = fmt->code;
-       mf->colorspace  = fmt->colorspace;
-       mf->field       = V4L2_FIELD_NONE;
-
-       return 0;
-}
-
-static int ov5640_enum_mbus_code(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_pad_config *cfg,
-                                struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->pad || code->index >= ARRAY_SIZE(ov5640_colour_fmts))
-               return -EINVAL;
-
-       code->code = ov5640_colour_fmts[code->index].code;
-       return 0;
-}
-
-/*!
- * ov5640_enum_framesizes - V4L2 sensor interface handler for
- *                        VIDIOC_ENUM_FRAMESIZES ioctl
- * @s: pointer to standard V4L2 device structure
- * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
- *
- * Return 0 if successful, otherwise -EINVAL.
- */
-static int ov5640_enum_framesizes(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_pad_config *cfg,
-                              struct v4l2_subdev_frame_size_enum *fse)
-{
-       if (fse->index > ov5640_mode_MAX)
-               return -EINVAL;
-
-       fse->max_width =
-                       max(ov5640_mode_info_data[0][fse->index].width,
-                           ov5640_mode_info_data[1][fse->index].width);
-       fse->min_width = fse->max_width;
-       fse->max_height =
-                       max(ov5640_mode_info_data[0][fse->index].height,
-                           ov5640_mode_info_data[1][fse->index].height);
-       fse->min_height = fse->max_height;
-       return 0;
-}
-
-/*!
- * ov5640_enum_frameintervals - V4L2 sensor interface handler for
- *                            VIDIOC_ENUM_FRAMEINTERVALS ioctl
- * @s: pointer to standard V4L2 device structure
- * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
- *
- * Return 0 if successful, otherwise -EINVAL.
- */
-static int ov5640_enum_frameintervals(struct v4l2_subdev *sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_frame_interval_enum *fie)
-{
-       int i, j, count = 0;
-
-       if (fie->index < 0 || fie->index > ov5640_mode_MAX)
-               return -EINVAL;
-
-       if (fie->width == 0 || fie->height == 0 ||
-           fie->code == 0) {
-               pr_warning("Please assign pixel format, width and height.\n");
-               return -EINVAL;
-       }
-
-       fie->interval.numerator = 1;
-
-       count = 0;
-       for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
-               for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
-                       if (fie->width == ov5640_mode_info_data[i][j].width
-                        && fie->height == ov5640_mode_info_data[i][j].height
-                        && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
-                               count++;
-                       }
-                       if (fie->index == (count - 1)) {
-                               fie->interval.denominator =
-                                               ov5640_framerates[i];
-                               return 0;
-                       }
-               }
-       }
-
-       return -EINVAL;
-}
-
-/*!
- * dev_init - V4L2 sensor init
- * @s: pointer to standard V4L2 device structure
- *
- */
-static int init_device(void)
-{
-       u32 tgt_xclk;   /* target xclk */
-       u32 tgt_fps;    /* target frames per secound */
-       enum ov5640_frame_rate frame_rate;
-       int ret;
-
-       ov5640_data.on = true;
-
-       /* mclk */
-       tgt_xclk = ov5640_data.mclk;
-       tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
-       tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
-       ov5640_data.mclk = tgt_xclk;
-
-       pr_debug("   Setting mclk to %d MHz\n", tgt_xclk / 1000000);
-
-       /* Default camera frame rate is set in probe */
-       tgt_fps = ov5640_data.streamcap.timeperframe.denominator /
-                 ov5640_data.streamcap.timeperframe.numerator;
-
-       if (tgt_fps == 15)
-               frame_rate = ov5640_15_fps;
-       else if (tgt_fps == 30)
-               frame_rate = ov5640_30_fps;
-       else
-               return -EINVAL; /* Only support 15fps or 30fps now. */
-
-       ret = ov5640_init_mode(frame_rate, ov5640_mode_INIT, ov5640_mode_INIT);
-
-       return ret;
-}
-
-static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
-{
-       if (enable)
-               OV5640_stream_on();
-       else
-               OV5640_stream_off();
-       return 0;
-}
-
-static struct v4l2_subdev_video_ops ov5640_subdev_video_ops = {
-       .g_parm = ov5640_g_parm,
-       .s_parm = ov5640_s_parm,
-       .s_stream = ov5640_s_stream,
-};
-
-static const struct v4l2_subdev_pad_ops ov5640_subdev_pad_ops = {
-       .enum_frame_size       = ov5640_enum_framesizes,
-       .enum_frame_interval   = ov5640_enum_frameintervals,
-       .enum_mbus_code        = ov5640_enum_mbus_code,
-       .set_fmt               = ov5640_set_fmt,
-       .get_fmt               = ov5640_get_fmt,
-};
-
-static struct v4l2_subdev_core_ops ov5640_subdev_core_ops = {
-       .s_power        = ov5640_s_power,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register     = ov5640_get_register,
-       .s_register     = ov5640_set_register,
-#endif
-};
-
-static struct v4l2_subdev_ops ov5640_subdev_ops = {
-       .core   = &ov5640_subdev_core_ops,
-       .video  = &ov5640_subdev_video_ops,
-       .pad    = &ov5640_subdev_pad_ops,
-};
-
-
-/*!
- * ov5640 I2C probe function
- *
- * @param adapter            struct i2c_adapter *
- * @return  Error code indicating success or failure
- */
-static int ov5640_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
-{
-       struct pinctrl *pinctrl;
-       struct device *dev = &client->dev;
-       int retval;
-       u8 chip_id_high, chip_id_low;
-
-       /* ov5640 pinctrl */
-       pinctrl = devm_pinctrl_get_select_default(dev);
-       if (IS_ERR(pinctrl))
-               dev_warn(dev, "no pin available\n");
-
-       /* request power down pin */
-       pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
-       if (!gpio_is_valid(pwn_gpio))
-               dev_warn(dev, "no sensor pwdn pin available");
-       else {
-               retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
-                                               "ov5640_mipi_pwdn");
-               if (retval < 0) {
-                       dev_warn(dev, "Failed to set power pin\n");
-                       dev_warn(dev, "retval=%d\n", retval);
-                       return retval;
-               }
-       }
-
-       /* request reset pin */
-       rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
-       if (!gpio_is_valid(rst_gpio))
-               dev_warn(dev, "no sensor reset pin available");
-       else {
-               retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
-                                               "ov5640_mipi_reset");
-               if (retval < 0) {
-                       dev_warn(dev, "Failed to set reset pin\n");
-                       return retval;
-               }
-       }
-
-       /* Set initial values for the sensor struct. */
-       memset(&ov5640_data, 0, sizeof(ov5640_data));
-       ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
-       if (IS_ERR(ov5640_data.sensor_clk)) {
-               /* assuming clock enabled by default */
-               ov5640_data.sensor_clk = NULL;
-               dev_err(dev, "clock-frequency missing or invalid\n");
-               return PTR_ERR(ov5640_data.sensor_clk);
-       }
-
-       retval = of_property_read_u32(dev->of_node, "mclk",
-                                       &(ov5640_data.mclk));
-       if (retval) {
-               dev_err(dev, "mclk missing or invalid\n");
-               return retval;
-       }
-
-       retval = of_property_read_u32(dev->of_node, "mclk_source",
-                                       (u32 *) &(ov5640_data.mclk_source));
-       if (retval) {
-               dev_err(dev, "mclk_source missing or invalid\n");
-               return retval;
-       }
-
-       retval = of_property_read_u32(dev->of_node, "csi_id",
-                                       &(ov5640_data.csi));
-       if (retval) {
-               dev_err(dev, "csi id missing or invalid\n");
-               return retval;
-       }
-
-       clk_prepare_enable(ov5640_data.sensor_clk);
-
-       ov5640_data.io_init = ov5640_reset;
-       ov5640_data.i2c_client = client;
-       ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-       ov5640_data.pix.width = 640;
-       ov5640_data.pix.height = 480;
-       ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
-                                          V4L2_CAP_TIMEPERFRAME;
-       ov5640_data.streamcap.capturemode = 0;
-       ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
-       ov5640_data.streamcap.timeperframe.numerator = 1;
-
-       ov5640_regulator_enable(&client->dev);
-
-       ov5640_reset();
-
-       ov5640_power_down(0);
-
-       retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
-       if (retval < 0 || chip_id_high != 0x56) {
-               pr_warning("camera ov5640_mipi is not found\n");
-               clk_disable_unprepare(ov5640_data.sensor_clk);
-               return -ENODEV;
-       }
-       retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
-       if (retval < 0 || chip_id_low != 0x40) {
-               pr_warning("camera ov5640_mipi is not found\n");
-               clk_disable_unprepare(ov5640_data.sensor_clk);
-               return -ENODEV;
-       }
-
-       retval = init_device();
-       if (retval < 0) {
-               clk_disable_unprepare(ov5640_data.sensor_clk);
-               pr_warning("camera ov5640 init failed\n");
-               ov5640_power_down(1);
-               return retval;
-       }
-
-       v4l2_i2c_subdev_init(&ov5640_data.subdev, client, &ov5640_subdev_ops);
-
-       ov5640_data.subdev.grp_id = 678;
-       retval = v4l2_async_register_subdev(&ov5640_data.subdev);
-       if (retval < 0)
-               dev_err(&client->dev,
-                                       "%s--Async register failed, ret=%d\n", __func__, retval);
-
-       OV5640_stream_off();
-       pr_info("camera ov5640_mipi is found\n");
-       return retval;
-}
-
-/*!
- * ov5640 I2C detach function
- *
- * @param client            struct i2c_client *
- * @return  Error code indicating success or failure
- */
-static int ov5640_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-       v4l2_async_unregister_subdev(sd);
-
-       clk_disable_unprepare(ov5640_data.sensor_clk);
-
-       ov5640_power_down(1);
-
-       if (gpo_regulator)
-               regulator_disable(gpo_regulator);
-
-       if (analog_regulator)
-               regulator_disable(analog_regulator);
-
-       if (core_regulator)
-               regulator_disable(core_regulator);
-
-       if (io_regulator)
-               regulator_disable(io_regulator);
-
-       return 0;
-}
-
-module_i2c_driver(ov5640_i2c_driver);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("OV5640 MIPI Camera Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/subdev/ov5647_mipi.c b/drivers/media/platform/mxc/subdev/ov5647_mipi.c
deleted file mode 100644 (file)
index 109f774..0000000
+++ /dev/null
@@ -1,1721 +0,0 @@
-/*
- * Copyright (C) 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/of_device.h>
-#include <linux/i2c.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/regulator/consumer.h>
-#include <linux/v4l2-mediabus.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-#define OV5647_VOLTAGE_ANALOG               2800000
-#define OV5647_VOLTAGE_DIGITAL_CORE         1500000
-#define OV5647_VOLTAGE_DIGITAL_IO           1800000
-
-#define MIN_FPS 15
-#define MAX_FPS 30
-#define DEFAULT_FPS 30
-
-#define OV5647_XCLK_MIN 6000000
-#define OV5647_XCLK_MAX 24000000
-
-#define OV5647_CHIP_ID_HIGH_BYTE       0x300A
-#define OV5647_CHIP_ID_LOW_BYTE                0x300B
-
-enum ov5647_mode {
-       ov5647_mode_MIN = 0,
-       ov5647_mode_VGA_640_480 = 0,
-       ov5647_mode_720P_1280_720 = 1,
-       ov5647_mode_1080P_1920_1080 = 2,
-       ov5647_mode_QSXGA_2592_1944 = 3,
-       ov5647_mode_MAX = 3,
-       ov5647_mode_INIT = 0xff, /*only for sensor init*/
-};
-
-enum ov5647_frame_rate {
-       ov5647_15_fps,
-       ov5647_30_fps
-};
-
-static int ov5647_framerates[] = {
-       [ov5647_15_fps] = 15,
-       [ov5647_30_fps] = 30,
-};
-
-struct ov5647_datafmt {
-       u32     code;
-       enum v4l2_colorspace            colorspace;
-};
-
-/* image size under 1280 * 960 are SUBSAMPLING
- * image size upper 1280 * 960 are SCALING
- */
-enum ov5647_downsize_mode {
-       SUBSAMPLING,
-       SCALING,
-};
-
-struct reg_value {
-       u16 u16RegAddr;
-       u8 u8Val;
-       u8 u8Mask;
-       u32 u32Delay_ms;
-};
-
-struct ov5647_mode_info {
-       enum ov5647_mode mode;
-       enum ov5647_downsize_mode dn_mode;
-       u32 width;
-       u32 height;
-       struct reg_value *init_data_ptr;
-       u32 init_data_size;
-};
-
-struct otp_struct {
-       int customer_id;
-       int module_integrator_id;
-       int lens_id;
-       int rg_ratio;
-       int bg_ratio;
-       int user_data[3];
-       int light_rg;
-       int light_bg;
-};
-
-struct ov5647 {
-       struct v4l2_subdev              subdev;
-       struct i2c_client *i2c_client;
-       struct v4l2_pix_format pix;
-       const struct ov5647_datafmt     *fmt;
-       struct v4l2_captureparm streamcap;
-       bool on;
-
-       /* control settings */
-       int brightness;
-       int hue;
-       int contrast;
-       int saturation;
-       int red;
-       int green;
-       int blue;
-       int ae_mode;
-
-       u32 mclk;
-       u8 mclk_source;
-       struct clk *sensor_clk;
-       int csi;
-
-       void (*io_init)(void);
-};
-/*!
- * Maintains the information on the current state of the sesor.
- */
-static struct ov5647 ov5647_data;
-static int pwn_gpio, rst_gpio;
-static int prev_sysclk, prev_HTS;
-static int AE_low, AE_high, AE_Target = 52;
-
-/* R/G and B/G of typical camera module is defined here,
- * the typical camera module is selected by CameraAnalyzer. */
-static int RG_Ratio_Typical = 0x70;
-static int BG_Ratio_Typical = 0x70;
-
-
-static struct reg_value ov5647_init_setting[] = {
-
-       {0x0100, 0x00, 0, 0},                       {0x3035, 0x11, 0, 0},
-       {0x3036, 0x69, 0, 0}, {0x303c, 0x11, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x370c, 0x0f, 0, 0}, {0x3612, 0x59, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x5000, 0x06, 0, 0}, {0x5002, 0x40, 0, 0},
-       {0x5003, 0x08, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x3000, 0xff, 0, 0},
-       {0x3001, 0xff, 0, 0}, {0x3002, 0xff, 0, 0}, {0x301d, 0xf0, 0, 0},
-       {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3c01, 0x80, 0, 0},
-       {0x3b07, 0x0c, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
-       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3814, 0x31, 0, 0},
-       {0x3815, 0x31, 0, 0}, {0x3708, 0x64, 0, 0}, {0x3709, 0x52, 0, 0},
-       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
-       {0x380b, 0xc0, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x18, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0x0e, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x27, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x95, 0, 0},
-       {0x3630, 0x2e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0},
-       {0x3634, 0x44, 0, 0}, {0x3620, 0x64, 0, 0}, {0x3621, 0xe0, 0, 0},
-       {0x3600, 0x37, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
-       {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x3731, 0x02, 0, 0},
-       {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3f05, 0x02, 0, 0},
-       {0x3f06, 0x10, 0, 0}, {0x3f01, 0x0a, 0, 0}, {0x3a08, 0x01, 0, 0},
-       {0x3a09, 0x27, 0, 0}, {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0},
-       {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0f, 0x58, 0, 0},
-       {0x3a10, 0x50, 0, 0}, {0x3a1b, 0x58, 0, 0}, {0x3a1e, 0x50, 0, 0},
-       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x28, 0, 0}, {0x4001, 0x02, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x4000, 0x09, 0, 0}, {0x4050, 0x6e, 0, 0},
-       {0x4051, 0x8f, 0, 0}, {0x4837, 0x17, 0, 0}, {0x3503, 0x03, 0, 0},
-       {0x3501, 0x44, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350a, 0x00, 0, 0},
-       {0x350b, 0x7f, 0, 0}, {0x5001, 0x01, 0, 0}, {0x5002, 0x41, 0, 0},
-       {0x5180, 0x08, 0, 0}, {0x5186, 0x04, 0, 0}, {0x5187, 0x00, 0, 0},
-       {0x5188, 0x04, 0, 0}, {0x5189, 0x00, 0, 0}, {0x518a, 0x04, 0, 0},
-       {0x518b, 0x00, 0, 0}, {0x5000, 0x86, 0, 0}, {0x5800, 0x11, 0, 0},
-       {0x5801, 0x0a, 0, 0}, {0x5802, 0x09, 0, 0}, {0x5803, 0x09, 0, 0},
-       {0x5804, 0x0a, 0, 0}, {0x5805, 0x0f, 0, 0}, {0x5806, 0x07, 0, 0},
-       {0x5807, 0x05, 0, 0}, {0x5808, 0x03, 0, 0}, {0x5809, 0x03, 0, 0},
-       {0x580a, 0x05, 0, 0}, {0x580b, 0x07, 0, 0}, {0x580c, 0x05, 0, 0},
-       {0x580d, 0x02, 0, 0}, {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0},
-       {0x5810, 0x02, 0, 0}, {0x5811, 0x05, 0, 0}, {0x5812, 0x05, 0, 0},
-       {0x5813, 0x02, 0, 0}, {0x5814, 0x00, 0, 0}, {0x5815, 0x00, 0, 0},
-       {0x5816, 0x01, 0, 0}, {0x5817, 0x05, 0, 0}, {0x5818, 0x08, 0, 0},
-       {0x5819, 0x05, 0, 0}, {0x581a, 0x03, 0, 0}, {0x581b, 0x03, 0, 0},
-       {0x581c, 0x04, 0, 0}, {0x581d, 0x07, 0, 0}, {0x581e, 0x10, 0, 0},
-       {0x581f, 0x0b, 0, 0}, {0x5820, 0x09, 0, 0}, {0x5821, 0x09, 0, 0},
-       {0x5822, 0x09, 0, 0}, {0x5823, 0x0e, 0, 0}, {0x5824, 0x28, 0, 0},
-       {0x5825, 0x1a, 0, 0}, {0x5826, 0x1a, 0, 0}, {0x5827, 0x1a, 0, 0},
-       {0x5828, 0x46, 0, 0}, {0x5829, 0x2a, 0, 0}, {0x582a, 0x26, 0, 0},
-       {0x582b, 0x44, 0, 0}, {0x582c, 0x26, 0, 0}, {0x582d, 0x2a, 0, 0},
-       {0x582e, 0x28, 0, 0}, {0x582f, 0x42, 0, 0}, {0x5830, 0x40, 0, 0},
-       {0x5831, 0x42, 0, 0}, {0x5832, 0x28, 0, 0}, {0x5833, 0x0a, 0, 0},
-       {0x5834, 0x16, 0, 0}, {0x5835, 0x44, 0, 0}, {0x5836, 0x26, 0, 0},
-       {0x5837, 0x2a, 0, 0}, {0x5838, 0x28, 0, 0}, {0x5839, 0x0a, 0, 0},
-       {0x583a, 0x0a, 0, 0}, {0x583b, 0x0a, 0, 0}, {0x583c, 0x26, 0, 0},
-       {0x583d, 0xbe, 0, 0}, {0x0100, 0x01, 0, 0}, {0x3000, 0x00, 0, 0},
-       {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, {0x3017, 0xe0, 0, 0},
-       {0x301c, 0xfc, 0, 0}, {0x3636, 0x06, 0, 0}, {0x3016, 0x08, 0, 0},
-       {0x3827, 0xec, 0, 0}, {0x3018, 0x44, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3106, 0xf5, 0, 0}, {0x3034, 0x18, 0, 0}, {0x301c, 0xf8, 0, 0},
-};
-
-static struct reg_value ov5647_setting_60fps_VGA_640_480[] = {
-       {0x0100, 0x00, 0, 0},                        {0x3035, 0x11, 0, 0},
-       {0x3036, 0x46, 0, 0}, {0x303c, 0x11, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3820, 0x41, 0, 0}, {0x370c, 0x0f, 0, 0}, {0x3612, 0x59, 0, 0},
-       {0x3618, 0x00, 0, 0}, {0x5000, 0x06, 0, 0}, {0x5002, 0x40, 0, 0},
-       {0x5003, 0x08, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x3000, 0xff, 0, 0},
-       {0x3001, 0xff, 0, 0}, {0x3002, 0xff, 0, 0}, {0x301d, 0xf0, 0, 0},
-       {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3c01, 0x80, 0, 0},
-       {0x3b07, 0x0c, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x3c, 0, 0},
-       {0x380e, 0x01, 0, 0}, {0x380f, 0xf8, 0, 0}, {0x3814, 0x71, 0, 0},
-       {0x3815, 0x71, 0, 0}, {0x3708, 0x64, 0, 0}, {0x3709, 0x52, 0, 0},
-       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
-       {0x380b, 0xe0, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x10, 0, 0},
-       {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
-       {0x3805, 0x2f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
-       {0x3630, 0x2e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0},
-       {0x3634, 0x44, 0, 0}, {0x3620, 0x64, 0, 0}, {0x3621, 0xe0, 0, 0},
-       {0x3600, 0x37, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
-       {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x3731, 0x02, 0, 0},
-       {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3f05, 0x02, 0, 0},
-       {0x3f06, 0x10, 0, 0}, {0x3f01, 0x0a, 0, 0}, {0x3a08, 0x01, 0, 0},
-       {0x3a09, 0x2e, 0, 0}, {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xfb, 0, 0},
-       {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x3a0f, 0x58, 0, 0},
-       {0x3a10, 0x50, 0, 0}, {0x3a1b, 0x58, 0, 0}, {0x3a1e, 0x50, 0, 0},
-       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x28, 0, 0}, {0x4001, 0x02, 0, 0},
-       {0x4004, 0x02, 0, 0}, {0x4000, 0x09, 0, 0}, {0x4050, 0x6e, 0, 0},
-       {0x4051, 0x8f, 0, 0}, {0x0100, 0x01, 0, 0}, {0x3000, 0x00, 0, 0},
-       {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, {0x3017, 0xe0, 0, 0},
-       {0x301c, 0xfc, 0, 0}, {0x3636, 0x06, 0, 0}, {0x3016, 0x08, 0, 0},
-       {0x3827, 0xec, 0, 0}, {0x3018, 0x44, 0, 0}, {0x3035, 0x21, 0, 0},
-       {0x3106, 0xf5, 0, 0}, {0x3034, 0x18, 0, 0}, {0x301c, 0xf8, 0, 0},
-};
-
-static struct reg_value ov5647_setting_30fps_720P_1280_720[] = {
-       {0x0100, 0x00, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
-       {0x3612, 0x59, 0, 0}, {0x3618, 0x00, 0, 0}, {0x380c, 0x09, 0, 0},
-       {0x380d, 0xe8, 0, 0}, {0x380e, 0x04, 0, 0}, {0x380f, 0x50, 0, 0},
-       {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3709, 0x52, 0, 0},
-       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
-       {0x380b, 0xd0, 0, 0}, {0x3801, 0x18, 0, 0}, {0x3802, 0x00, 0, 0},
-       {0x3803, 0xf8, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x27, 0, 0},
-       {0x3806, 0x06, 0, 0}, {0x3807, 0xa7, 0, 0}, {0x3a09, 0xbe, 0, 0},
-       {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x74, 0, 0}, {0x3a0d, 0x02, 0, 0},
-       {0x3a0e, 0x01, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4005, 0x18, 0, 0},
-       {0x0100, 0x01, 0, 0},
-};
-
-static struct reg_value ov5647_setting_30fps_1080P_1920_1080[] = {
-       {0x0100, 0x00, 0, 0}, {0x3820, 0x00, 0, 0}, {0x3821, 0x06, 0, 0},
-       {0x3612, 0x5b, 0, 0}, {0x3618, 0x04, 0, 0}, {0x380c, 0x09, 0, 0},
-       {0x380d, 0xe8, 0, 0}, {0x380e, 0x04, 0, 0}, {0x380f, 0x50, 0, 0},
-       {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3709, 0x12, 0, 0},
-       {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0},
-       {0x380b, 0x38, 0, 0}, {0x3801, 0x5c, 0, 0}, {0x3802, 0x01, 0, 0},
-       {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xe3, 0, 0},
-       {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3a09, 0x4b, 0, 0},
-       {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x13, 0, 0}, {0x3a0d, 0x04, 0, 0},
-       {0x3a0e, 0x03, 0, 0}, {0x4004, 0x04, 0, 0}, {0x4005, 0x18, 0, 0},
-       {0x0100, 0x01, 0, 0},
-};
-
-static struct reg_value ov5647_setting_15fps_QSXGA_2592_1944[] = {
-       {0x0100, 0x00, 0, 0}, {0x3820, 0x00, 0, 0}, {0x3821, 0x06, 0, 0},
-       {0x3612, 0x5b, 0, 0}, {0x3618, 0x04, 0, 0}, {0x380c, 0x0b, 0, 0},
-       {0x380d, 0x10, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb8, 0, 0},
-       {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3709, 0x12, 0, 0},
-       {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
-       {0x380b, 0x98, 0, 0}, {0x3801, 0x0c, 0, 0}, {0x3802, 0x00, 0, 0},
-       {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x33, 0, 0},
-       {0x3806, 0x07, 0, 0}, {0x3807, 0xa3, 0, 0}, {0x3a09, 0x28, 0, 0},
-       {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0d, 0x08, 0, 0},
-       {0x3a0e, 0x06, 0, 0}, {0x4004, 0x04, 0, 0}, {0x4005, 0x1a, 0, 0},
-       {0x0100, 0x01, 0, 0},
-};
-
-static struct ov5647_mode_info ov5647_mode_info_data[2][ov5647_mode_MAX + 1] = {
-       {
-               {ov5647_mode_VGA_640_480, -1, 0, 0, NULL, 0},
-               {ov5647_mode_720P_1280_720, -1, 0, 0, NULL, 0},
-               {ov5647_mode_1080P_1920_1080, -1, 0, 0, NULL, 0},
-               {ov5647_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
-               ov5647_setting_15fps_QSXGA_2592_1944,
-               ARRAY_SIZE(ov5647_setting_15fps_QSXGA_2592_1944)},
-       },
-       {
-               /* Actually VGA working in 60fps mode */
-               {ov5647_mode_VGA_640_480, SUBSAMPLING, 640,  480,
-               ov5647_setting_60fps_VGA_640_480,
-               ARRAY_SIZE(ov5647_setting_60fps_VGA_640_480)},
-               {ov5647_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
-               ov5647_setting_30fps_720P_1280_720,
-               ARRAY_SIZE(ov5647_setting_30fps_720P_1280_720)},
-               {ov5647_mode_1080P_1920_1080, SCALING, 1920, 1080,
-               ov5647_setting_30fps_1080P_1920_1080,
-               ARRAY_SIZE(ov5647_setting_30fps_1080P_1920_1080)},
-               {ov5647_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
-       },
-};
-
-static struct regulator *io_regulator;
-static struct regulator *core_regulator;
-static struct regulator *analog_regulator;
-static struct regulator *gpo_regulator;
-
-static int ov5647_probe(struct i2c_client *adapter,
-                               const struct i2c_device_id *device_id);
-static int ov5647_remove(struct i2c_client *client);
-
-static s32 ov5647_read_reg(u16 reg, u8 *val);
-static s32 ov5647_write_reg(u16 reg, u8 val);
-
-static const struct i2c_device_id ov5647_id[] = {
-       {"ov5647_mipi", 0},
-       {},
-};
-
-MODULE_DEVICE_TABLE(i2c, ov5647_id);
-
-static struct i2c_driver ov5647_i2c_driver = {
-       .driver = {
-                 .owner = THIS_MODULE,
-                 .name  = "ov5647_mipi",
-                 },
-       .probe  = ov5647_probe,
-       .remove = ov5647_remove,
-       .id_table = ov5647_id,
-};
-
-static const struct ov5647_datafmt ov5647_colour_fmts[] = {
-       {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_JPEG},
-};
-
-static struct ov5647 *to_ov5647(const struct i2c_client *client)
-{
-       return container_of(i2c_get_clientdata(client), struct ov5647, subdev);
-}
-
-/* Find a data format by a pixel code in an array */
-static const struct ov5647_datafmt
-                       *ov5647_find_datafmt(u32 code)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ov5647_colour_fmts); i++)
-               if (ov5647_colour_fmts[i].code == code)
-                       return ov5647_colour_fmts + i;
-
-       return NULL;
-}
-
-static inline void ov5647_power_down(int enable)
-{
-       if (pwn_gpio < 0)
-               return;
-
-       /* 19x19 pwdn pin invert by mipi daughter card */
-       if (!enable)
-               gpio_set_value_cansleep(pwn_gpio, 1);
-       else
-               gpio_set_value_cansleep(pwn_gpio, 0);
-
-       msleep(2);
-}
-
-static void ov5647_reset(void)
-{
-       if (rst_gpio < 0 || pwn_gpio < 0)
-               return;
-
-       /* camera reset */
-       gpio_set_value_cansleep(rst_gpio, 1);
-
-       /* camera power dowmn */
-       gpio_set_value_cansleep(pwn_gpio, 1);
-       msleep(5);
-
-       gpio_set_value_cansleep(pwn_gpio, 0);
-       msleep(5);
-
-       gpio_set_value_cansleep(rst_gpio, 0);
-       msleep(1);
-
-       gpio_set_value_cansleep(rst_gpio, 1);
-       msleep(5);
-
-       gpio_set_value_cansleep(pwn_gpio, 1);
-}
-
-static int ov5647_regulator_enable(struct device *dev)
-{
-       int ret = 0;
-
-       io_regulator = devm_regulator_get(dev, "DOVDD");
-       if (!IS_ERR(io_regulator)) {
-               regulator_set_voltage(io_regulator,
-                                     OV5647_VOLTAGE_DIGITAL_IO,
-                                     OV5647_VOLTAGE_DIGITAL_IO);
-               ret = regulator_enable(io_regulator);
-               if (ret) {
-                       pr_err("%s:io set voltage error\n", __func__);
-                       return ret;
-               } else {
-                       dev_dbg(dev,
-                               "%s:io set voltage ok\n", __func__);
-               }
-       } else {
-               pr_err("%s: cannot get io voltage error\n", __func__);
-               io_regulator = NULL;
-       }
-
-       core_regulator = devm_regulator_get(dev, "DVDD");
-       if (!IS_ERR(core_regulator)) {
-               regulator_set_voltage(core_regulator,
-                                     OV5647_VOLTAGE_DIGITAL_CORE,
-                                     OV5647_VOLTAGE_DIGITAL_CORE);
-               ret = regulator_enable(core_regulator);
-               if (ret) {
-                       pr_err("%s:core set voltage error\n", __func__);
-                       return ret;
-               } else {
-                       dev_dbg(dev,
-                               "%s:core set voltage ok\n", __func__);
-               }
-       } else {
-               core_regulator = NULL;
-               pr_err("%s: cannot get core voltage error\n", __func__);
-       }
-
-       analog_regulator = devm_regulator_get(dev, "AVDD");
-       if (!IS_ERR(analog_regulator)) {
-               regulator_set_voltage(analog_regulator,
-                                     OV5647_VOLTAGE_ANALOG,
-                                     OV5647_VOLTAGE_ANALOG);
-               ret = regulator_enable(analog_regulator);
-               if (ret) {
-                       pr_err("%s:analog set voltage error\n",
-                               __func__);
-                       return ret;
-               } else {
-                       dev_dbg(dev,
-                               "%s:analog set voltage ok\n", __func__);
-               }
-       } else {
-               analog_regulator = NULL;
-               pr_err("%s: cannot get analog voltage error\n", __func__);
-       }
-
-       return ret;
-}
-
-static s32 ov5647_write_reg(u16 reg, u8 val)
-{
-       u8 au8Buf[3] = {0};
-
-       au8Buf[0] = reg >> 8;
-       au8Buf[1] = reg & 0xff;
-       au8Buf[2] = val;
-
-       if (i2c_master_send(ov5647_data.i2c_client, au8Buf, 3) < 0) {
-               pr_err("%s:write reg error:reg=%x,val=%x\n",
-                       __func__, reg, val);
-               return -1;
-       }
-
-       return 0;
-}
-
-static s32 ov5647_read_reg(u16 reg, u8 *val)
-{
-       u8 au8RegBuf[2] = {0};
-       u8 u8RdVal = 0;
-
-       au8RegBuf[0] = reg >> 8;
-       au8RegBuf[1] = reg & 0xff;
-
-       if (2 != i2c_master_send(ov5647_data.i2c_client, au8RegBuf, 2)) {
-               pr_err("%s:write reg error:reg=%x\n",
-                               __func__, reg);
-               return -1;
-       }
-
-       if (1 != i2c_master_recv(ov5647_data.i2c_client, &u8RdVal, 1)) {
-               pr_err("%s:read reg error:reg=%x,val=%x\n",
-                               __func__, reg, u8RdVal);
-               return -1;
-       }
-
-       *val = u8RdVal;
-
-       return u8RdVal;
-}
-
-/* index: index of otp group. (0, 1, 2)
- * return:
- * 0, group index is empty
- * 1, group index has invalid data
- * 2, group index has valid data */
-static int ov5647_check_otp(int index)
-{
-       int i;
-       int address;
-       u8 temp;
-
-       /* read otp into buffer */
-       ov5647_write_reg(0x3d21, 0x01);
-       msleep(20);
-       address = 0x3d05 + index * 9;
-       temp = ov5647_read_reg(address, &temp);
-
-       /* disable otp read */
-       ov5647_write_reg(0x3d21, 0x00);
-
-       /* clear otp buffer */
-       for (i = 0; i < 32; i++)
-               ov5647_write_reg(0x3d00 + i, 0x00);
-
-       if (!temp)
-               return 0;
-       else if ((!(temp & 0x80)) && (temp & 0x7f))
-               return 2;
-       else
-               return 1;
-}
-
-/* index: index of otp group. (0, 1, 2)
- * return: 0 */
-static int ov5647_read_otp(int index, struct otp_struct *otp_ptr)
-{
-       int i;
-       int address;
-       u8 temp;
-
-       /* read otp into buffer */
-       ov5647_write_reg(0x3d21, 0x01);
-       msleep(2);
-       address = 0x3d05 + index * 9;
-       temp = ov5647_read_reg(address, &temp);
-       (*otp_ptr).customer_id = temp & 0x7f;
-
-       (*otp_ptr).module_integrator_id = ov5647_read_reg(address, &temp);
-       (*otp_ptr).lens_id = ov5647_read_reg(address + 1, &temp);
-       (*otp_ptr).rg_ratio = ov5647_read_reg(address + 2, &temp);
-       (*otp_ptr).bg_ratio = ov5647_read_reg(address + 3, &temp);
-       (*otp_ptr).user_data[0] = ov5647_read_reg(address + 4, &temp);
-       (*otp_ptr).user_data[1] = ov5647_read_reg(address + 5, &temp);
-       (*otp_ptr).user_data[2] = ov5647_read_reg(address + 6, &temp);
-       (*otp_ptr).light_rg = ov5647_read_reg(address + 7, &temp);
-       (*otp_ptr).light_bg = ov5647_read_reg(address + 8, &temp);
-
-       /* disable otp read */
-       ov5647_write_reg(0x3d21, 0x00);
-
-       /* clear otp buffer */
-       for (i = 0; i < 32; i++)
-               ov5647_write_reg(0x3d00 + i, 0x00);
-
-       return 0;
-}
-
-/* R_gain, sensor red gain of AWB, 0x400 =1
- * G_gain, sensor green gain of AWB, 0x400 =1
- * B_gain, sensor blue gain of AWB, 0x400 =1
- * return 0 */
-static int ov5647_update_awb_gain(int R_gain, int G_gain, int B_gain)
-{
-       if (R_gain > 0x400) {
-               ov5647_write_reg(0x5186, R_gain >> 8);
-               ov5647_write_reg(0x5187, R_gain & 0x00ff);
-       }
-       if (G_gain > 0x400) {
-               ov5647_write_reg(0x5188, G_gain >> 8);
-               ov5647_write_reg(0x5189, G_gain & 0x00ff);
-       }
-       if (B_gain > 0x400) {
-               ov5647_write_reg(0x518a, B_gain >> 8);
-               ov5647_write_reg(0x518b, B_gain & 0x00ff);
-       }
-
-       return 0;
-}
-
-/* call this function after OV5647 initialization
- * return value:
- * 0 update success
- * 1 no OTP */
-static int ov5647_update_otp(void)
-{
-       struct otp_struct current_otp;
-       int i;
-       int otp_index;
-       int temp;
-       int R_gain, G_gain, B_gain, G_gain_R, G_gain_B;
-       int rg, bg;
-
-       /* R/G and B/G of current camera module is read out from sensor OTP
-        * check first OTP with valid data */
-       for (i = 0; i < 3; i++) {
-               temp = ov5647_check_otp(i);
-               if (temp == 2) {
-                       otp_index = i;
-                       break;
-               }
-       }
-       if (i == 3) {
-               /* no valid wb OTP data */
-               printk(KERN_WARNING "No valid wb otp data\n");
-               return 1;
-       }
-
-       ov5647_read_otp(otp_index, &current_otp);
-       if (current_otp.light_rg == 0)
-               rg = current_otp.rg_ratio;
-       else
-               rg = current_otp.rg_ratio * (current_otp.light_rg + 128) / 256;
-
-       if (current_otp.light_bg == 0)
-               bg = current_otp.bg_ratio;
-       else
-               bg = current_otp.bg_ratio * (current_otp.light_bg + 128) / 256;
-
-       /* calculate G gain
-        * 0x400 = 1x gain */
-       if (bg < BG_Ratio_Typical) {
-               if (rg < RG_Ratio_Typical) {
-                       /* current_otp.bg_ratio < BG_Ratio_typical &&
-                        * current_otp.rg_ratio < RG_Ratio_typical */
-                       G_gain = 0x400;
-                       B_gain = 0x400 * BG_Ratio_Typical / bg;
-                       R_gain = 0x400 * RG_Ratio_Typical / rg;
-               } else {
-                       /* current_otp.bg_ratio < BG_Ratio_typical &&
-                        * current_otp.rg_ratio >= RG_Ratio_typical */
-                       R_gain = 0x400;
-                       G_gain = 0x400 * rg / RG_Ratio_Typical;
-                       B_gain = G_gain * BG_Ratio_Typical / bg;
-               }
-       } else {
-               if (rg < RG_Ratio_Typical) {
-                       /* current_otp.bg_ratio >= BG_Ratio_typical &&
-                        * current_otp.rg_ratio < RG_Ratio_typical */
-                       B_gain = 0x400;
-                       G_gain = 0x400 * bg / BG_Ratio_Typical;
-                       R_gain = G_gain * RG_Ratio_Typical / rg;
-               } else {
-                       /* current_otp.bg_ratio >= BG_Ratio_typical &&
-                        * current_otp.rg_ratio >= RG_Ratio_typical */
-                       G_gain_B = 0x400 * bg / BG_Ratio_Typical;
-                       G_gain_R = 0x400 * rg / RG_Ratio_Typical;
-                       if (G_gain_B > G_gain_R) {
-                               B_gain = 0x400;
-                               G_gain = G_gain_B;
-                               R_gain = G_gain * RG_Ratio_Typical / rg;
-                       } else {
-                               R_gain = 0x400;
-                               G_gain = G_gain_R;
-                               B_gain = G_gain * BG_Ratio_Typical / bg;
-                       }
-               }
-       }
-       ov5647_update_awb_gain(R_gain, G_gain, B_gain);
-       return 0;
-}
-
-static void ov5647_stream_on(void)
-{
-       ov5647_write_reg(0x4202, 0x00);
-}
-
-static void ov5647_stream_off(void)
-{
-       ov5647_write_reg(0x4202, 0x0f);
-       /* both clock and data lane in LP00 */
-       ov5647_write_reg(0x0100, 0x00);
-}
-
-static int ov5647_get_sysclk(void)
-{
-       /* calculate sysclk */
-       int xvclk = ov5647_data.mclk / 10000;
-       int sysclk, temp1, temp2;
-       int pre_div02x, div_cnt7b, sdiv0, pll_rdiv, bit_div2x, sclk_div, VCO;
-       int pre_div02x_map[] = {2, 2, 4, 6, 8, 3, 12, 5, 16, 2, 2, 2, 2, 2, 2, 2};
-       int sdiv0_map[] = {16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
-       int pll_rdiv_map[] = {1, 2};
-       int bit_div2x_map[] = {2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 5, 2, 2, 2, 2, 2};
-       int sclk_div_map[] = {1, 2, 4, 1};
-       u8 temp;
-
-       temp1 = ov5647_read_reg(0x3037, &temp);
-       temp2 = temp1 & 0x0f;
-       pre_div02x = pre_div02x_map[temp2];
-       temp2 = (temp1 >> 4) & 0x01;
-       pll_rdiv = pll_rdiv_map[temp2];
-       temp1 = ov5647_read_reg(0x3036, &temp);
-
-       div_cnt7b = temp1;
-
-       VCO = xvclk * 2 / pre_div02x * div_cnt7b;
-       temp1 = ov5647_read_reg(0x3035, &temp);
-       temp2 = temp1 >> 4;
-       sdiv0 = sdiv0_map[temp2];
-       temp1 = ov5647_read_reg(0x3034, &temp);
-       temp2 = temp1 & 0x0f;
-       bit_div2x = bit_div2x_map[temp2];
-       temp1 = ov5647_read_reg(0x3106, &temp);
-       temp2 = (temp1 >> 2) & 0x03;
-       sclk_div = sclk_div_map[temp2];
-       sysclk = VCO * 2 / sdiv0 / pll_rdiv / bit_div2x / sclk_div;
-       return sysclk;
-}
-
-static void ov5647_set_night_mode(void)
-{
-        /* read HTS from register settings */
-       u8 mode;
-
-       ov5647_read_reg(0x3a00, &mode);
-       mode &= 0xfb;
-       ov5647_write_reg(0x3a00, mode);
-}
-
-static int ov5647_get_HTS(void)
-{
-        /* read HTS from register settings */
-       int HTS;
-       u8 temp;
-
-       HTS = ov5647_read_reg(0x380c, &temp);
-       HTS = (HTS << 8) + ov5647_read_reg(0x380d, &temp);
-
-       return HTS;
-}
-
-static int ov5647_soft_reset(void)
-{
-       /* soft reset ov5647 */
-
-       ov5647_write_reg(0x0103, 0x1);
-       msleep(5);
-
-       return 0;
-}
-
-static int ov5647_get_VTS(void)
-{
-        /* read VTS from register settings */
-       int VTS;
-       u8 temp;
-
-       /* total vertical size[15:8] high byte */
-       VTS = ov5647_read_reg(0x380e, &temp);
-
-       VTS = (VTS << 8) + ov5647_read_reg(0x380f, &temp);
-
-       return VTS;
-}
-
-static int ov5647_set_VTS(int VTS)
-{
-        /* write VTS to registers */
-        int temp;
-
-        temp = VTS & 0xff;
-        ov5647_write_reg(0x380f, temp);
-
-        temp = VTS >> 8;
-        ov5647_write_reg(0x380e, temp);
-
-        return 0;
-}
-
-static int ov5647_get_shutter(void)
-{
-        /* read shutter, in number of line period */
-       int shutter;
-       u8 temp;
-
-       shutter = (ov5647_read_reg(0x03500, &temp) & 0x0f);
-       shutter = (shutter << 8) + ov5647_read_reg(0x3501, &temp);
-       shutter = (shutter << 4) + (ov5647_read_reg(0x3502, &temp)>>4);
-
-        return shutter;
-}
-
-static int ov5647_set_shutter(int shutter)
-{
-        /* write shutter, in number of line period */
-        int temp;
-
-        shutter = shutter & 0xffff;
-
-        temp = shutter & 0x0f;
-        temp = temp << 4;
-        ov5647_write_reg(0x3502, temp);
-
-        temp = shutter & 0xfff;
-        temp = temp >> 4;
-        ov5647_write_reg(0x3501, temp);
-
-        temp = shutter >> 12;
-        ov5647_write_reg(0x3500, temp);
-
-        return 0;
-}
-
-static int ov5647_get_gain16(void)
-{
-        /* read gain, 16 = 1x */
-       int gain16;
-       u8 temp;
-
-       gain16 = ov5647_read_reg(0x350a, &temp) & 0x03;
-       gain16 = (gain16 << 8) + ov5647_read_reg(0x350b, &temp);
-
-       return gain16;
-}
-
-static int ov5647_set_gain16(int gain16)
-{
-       /* write gain, 16 = 1x */
-       u8 temp;
-       gain16 = gain16 & 0x3ff;
-
-       temp = gain16 & 0xff;
-       ov5647_write_reg(0x350b, temp);
-
-       temp = gain16 >> 8;
-       ov5647_write_reg(0x350a, temp);
-
-       return 0;
-}
-
-static int ov5647_get_light_freq(void)
-{
-       /* get banding filter value */
-       int temp, temp1, light_freq = 0;
-       u8 tmp;
-
-       temp = ov5647_read_reg(0x3c01, &tmp);
-
-       if (temp & 0x80) {
-               /* manual */
-               temp1 = ov5647_read_reg(0x3c00, &tmp);
-               if (temp1 & 0x04) {
-                       /* 50Hz */
-                       light_freq = 50;
-               } else {
-                       /* 60Hz */
-                       light_freq = 60;
-               }
-       } else {
-               /* auto */
-               temp1 = ov5647_read_reg(0x3c0c, &tmp);
-               if (temp1 & 0x01) {
-                       /* 50Hz */
-                       light_freq = 50;
-               } else {
-                       /* 60Hz */
-               }
-       }
-       return light_freq;
-}
-
-static void ov5647_set_bandingfilter(void)
-{
-       int prev_VTS;
-       int band_step60, max_band60, band_step50, max_band50;
-
-       /* read preview PCLK */
-       prev_sysclk = ov5647_get_sysclk();
-       /* read preview HTS */
-       prev_HTS = ov5647_get_HTS();
-
-       /* read preview VTS */
-       prev_VTS = ov5647_get_VTS();
-
-       /* calculate banding filter */
-       /* 60Hz */
-       band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
-       ov5647_write_reg(0x3a0a, (band_step60 >> 8));
-       ov5647_write_reg(0x3a0b, (band_step60 & 0xff));
-
-       max_band60 = (int)((prev_VTS-4)/band_step60);
-       ov5647_write_reg(0x3a0d, max_band60);
-
-       /* 50Hz */
-       band_step50 = prev_sysclk * 100/prev_HTS;
-       ov5647_write_reg(0x3a08, (band_step50 >> 8));
-       ov5647_write_reg(0x3a09, (band_step50 & 0xff));
-
-       max_band50 = (int)((prev_VTS-4)/band_step50);
-       ov5647_write_reg(0x3a0e, max_band50);
-}
-
-static int ov5647_set_AE_target(int target)
-{
-       /* stable in high */
-       int fast_high, fast_low;
-       AE_low = target * 23 / 25;      /* 0.92 */
-       AE_high = target * 27 / 25;     /* 1.08 */
-
-       fast_high = AE_high<<1;
-       if (fast_high > 255)
-               fast_high = 255;
-
-       fast_low = AE_low >> 1;
-
-       ov5647_write_reg(0x3a0f, AE_high);
-       ov5647_write_reg(0x3a10, AE_low);
-       ov5647_write_reg(0x3a1b, AE_high);
-       ov5647_write_reg(0x3a1e, AE_low);
-       ov5647_write_reg(0x3a11, fast_high);
-       ov5647_write_reg(0x3a1f, fast_low);
-
-       return 0;
-}
-
-static void ov5647_turn_on_AE_AG(int enable)
-{
-       u8 ae_ag_ctrl;
-
-       ov5647_read_reg(0x3503, &ae_ag_ctrl);
-       if (enable) {
-               /* turn on auto AE/AG */
-               ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
-       } else {
-               /* turn off AE/AG */
-               ae_ag_ctrl = ae_ag_ctrl | 0x03;
-       }
-       ov5647_write_reg(0x3503, ae_ag_ctrl);
-}
-
-static void ov5647_set_virtual_channel(int channel)
-{
-       u8 channel_id;
-
-       ov5647_read_reg(0x4814, &channel_id);
-       channel_id &= ~(3 << 6);
-       ov5647_write_reg(0x4814, channel_id | (channel << 6));
-}
-
-/* download ov5647 settings to sensor through i2c */
-static int ov5647_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
-{
-       register u32 Delay_ms = 0;
-       register u16 RegAddr = 0;
-       register u8 Mask = 0;
-       register u8 Val = 0;
-       u8 RegVal = 0;
-       int i, retval = 0;
-
-       for (i = 0; i < ArySize; ++i, ++pModeSetting) {
-               Delay_ms = pModeSetting->u32Delay_ms;
-               RegAddr = pModeSetting->u16RegAddr;
-               Val = pModeSetting->u8Val;
-               Mask = pModeSetting->u8Mask;
-
-               if (Mask) {
-                       retval = ov5647_read_reg(RegAddr, &RegVal);
-                       if (retval < 0)
-                               goto err;
-
-                       RegVal &= ~(u8)Mask;
-                       Val &= Mask;
-                       Val |= RegVal;
-               }
-
-               retval = ov5647_write_reg(RegAddr, Val);
-               if (retval < 0)
-                       goto err;
-
-               if (Delay_ms)
-                       msleep(Delay_ms);
-       }
-err:
-       return retval;
-}
-
-/* sensor changes between scaling and subsampling
- * go through exposure calcualtion
- */
-static int ov5647_change_mode_exposure_calc(enum ov5647_frame_rate frame_rate,
-                               enum ov5647_mode mode)
-{
-       struct reg_value *pModeSetting = NULL;
-       s32 ArySize = 0;
-       int pre_shutter, pre_gain16;
-       int cap_shutter, cap_gain16;
-       int pre_sysclk, pre_HTS;
-       int cap_sysclk, cap_HTS, cap_VTS;
-       long cap_gain16_shutter;
-       int retval = 0;
-
-       /* check if the input mode and frame rate is valid */
-       pModeSetting =
-               ov5647_mode_info_data[frame_rate][mode].init_data_ptr;
-       ArySize =
-               ov5647_mode_info_data[frame_rate][mode].init_data_size;
-
-       ov5647_data.pix.width =
-               ov5647_mode_info_data[frame_rate][mode].width;
-       ov5647_data.pix.height =
-               ov5647_mode_info_data[frame_rate][mode].height;
-
-       if (ov5647_data.pix.width == 0 || ov5647_data.pix.height == 0 ||
-               pModeSetting == NULL || ArySize == 0)
-               return -EINVAL;
-
-       ov5647_stream_off();
-
-       /* turn off night mode for capture */
-       ov5647_set_night_mode();
-
-       pre_shutter = ov5647_get_shutter();
-       pre_gain16 = ov5647_get_gain16();
-       pre_HTS = ov5647_get_HTS();
-       pre_sysclk = ov5647_get_sysclk();
-
-       /* Write capture setting */
-       retval = ov5647_download_firmware(pModeSetting, ArySize);
-       if (retval < 0)
-               goto err;
-
-       /* read capture VTS */
-       cap_VTS = ov5647_get_VTS();
-       cap_HTS = ov5647_get_HTS();
-       cap_sysclk = ov5647_get_sysclk();
-
-       /* calculate capture shutter/gain16 */
-       cap_shutter = pre_shutter * cap_sysclk/pre_sysclk * pre_HTS / cap_HTS;
-
-       if (cap_shutter < 16) {
-               cap_gain16_shutter = pre_shutter * pre_gain16 *
-                               cap_sysclk / pre_sysclk * pre_HTS / cap_HTS;
-               cap_shutter = ((int)(cap_gain16_shutter / 16));
-               if (cap_shutter < 1)
-                       cap_shutter = 1;
-               cap_gain16 = ((int)(cap_gain16_shutter / cap_shutter));
-               if (cap_gain16 < 16)
-                       cap_gain16 = 16;
-       } else
-               cap_gain16 = pre_gain16;
-
-       /* gain to shutter */
-       while ((cap_gain16 > 32) &&
-                       (cap_shutter < ((int)((cap_VTS - 4) / 2)))) {
-               cap_gain16 = cap_gain16 / 2;
-               cap_shutter = cap_shutter * 2;
-       }
-       /* write capture gain */
-       ov5647_set_gain16(cap_gain16);
-
-       /* write capture shutter */
-       if (cap_shutter > (cap_VTS - 4)) {
-               cap_VTS = cap_shutter + 4;
-               ov5647_set_VTS(cap_VTS);
-       }
-       ov5647_set_shutter(cap_shutter);
-
-err:
-       return retval;
-}
-
-/* if sensor changes inside scaling or subsampling
- * change mode directly
- * */
-static int ov5647_change_mode_direct(enum ov5647_frame_rate frame_rate,
-                               enum ov5647_mode mode)
-{
-       struct reg_value *pModeSetting = NULL;
-       s32 ArySize = 0;
-       int retval = 0;
-
-       /* check if the input mode and frame rate is valid */
-       pModeSetting =
-               ov5647_mode_info_data[frame_rate][mode].init_data_ptr;
-       ArySize =
-               ov5647_mode_info_data[frame_rate][mode].init_data_size;
-
-       ov5647_data.pix.width =
-               ov5647_mode_info_data[frame_rate][mode].width;
-       ov5647_data.pix.height =
-               ov5647_mode_info_data[frame_rate][mode].height;
-
-       if (ov5647_data.pix.width == 0 || ov5647_data.pix.height == 0 ||
-               pModeSetting == NULL || ArySize == 0)
-               return -EINVAL;
-
-       /* turn off AE/AG */
-       ov5647_turn_on_AE_AG(0);
-
-       ov5647_stream_off();
-
-       /* Write capture setting */
-       retval = ov5647_download_firmware(pModeSetting, ArySize);
-       if (retval < 0)
-               goto err;
-
-       ov5647_turn_on_AE_AG(1);
-
-err:
-       return retval;
-}
-
-static int ov5647_init_mode(enum ov5647_frame_rate frame_rate,
-                           enum ov5647_mode mode, enum ov5647_mode orig_mode)
-{
-       struct reg_value *pModeSetting = NULL;
-       s32 ArySize = 0;
-       int retval = 0;
-       u32 msec_wait4stable = 0;
-       enum ov5647_downsize_mode dn_mode, orig_dn_mode;
-
-       if ((mode > ov5647_mode_MAX || mode < ov5647_mode_MIN)
-               && (mode != ov5647_mode_INIT)) {
-               pr_err("Wrong ov5647 mode detected!\n");
-               return -1;
-       }
-
-       dn_mode = ov5647_mode_info_data[frame_rate][mode].dn_mode;
-       orig_dn_mode = ov5647_mode_info_data[frame_rate][orig_mode].dn_mode;
-       if (mode == ov5647_mode_INIT) {
-               ov5647_soft_reset();
-               pModeSetting = ov5647_init_setting;
-               ArySize = ARRAY_SIZE(ov5647_init_setting);
-               retval = ov5647_download_firmware(pModeSetting, ArySize);
-               if (retval < 0)
-                       goto err;
-               pModeSetting = ov5647_setting_60fps_VGA_640_480;
-               ArySize = ARRAY_SIZE(ov5647_setting_60fps_VGA_640_480);
-               retval = ov5647_download_firmware(pModeSetting, ArySize);
-
-               ov5647_data.pix.width = 640;
-               ov5647_data.pix.height = 480;
-       } else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
-                       (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
-               /* change between subsampling and scaling
-                * go through exposure calucation */
-               retval = ov5647_change_mode_exposure_calc(frame_rate, mode);
-       } else {
-               /* change inside subsampling or scaling
-                * download firmware directly */
-               retval = ov5647_change_mode_direct(frame_rate, mode);
-       }
-
-       if (retval < 0)
-               goto err;
-
-       ov5647_set_AE_target(AE_Target);
-       ov5647_get_light_freq();
-       ov5647_set_bandingfilter();
-       ov5647_set_virtual_channel(ov5647_data.csi);
-
-       /* add delay to wait for sensor stable */
-       if (mode == ov5647_mode_QSXGA_2592_1944) {
-               /* dump the first two frames: 1/7.5*2
-                * the frame rate of QSXGA is 7.5fps */
-               msec_wait4stable = 267;
-       } else if (frame_rate == ov5647_15_fps) {
-               /* dump the first nine frames: 1/15*9 */
-               msec_wait4stable = 600;
-       } else if (frame_rate == ov5647_30_fps) {
-               /* dump the first nine frames: 1/30*9 */
-               msec_wait4stable = 300;
-       }
-       msleep(msec_wait4stable);
-
-err:
-       return retval;
-}
-
-/*!
- * ov5647_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
- * @s: pointer to standard V4L2 device structure
- * @on: indicates power mode (on or off)
- *
- * Turns the power on or off, depending on the value of on and returns the
- * appropriate error code.
- */
-static int ov5647_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5647 *sensor = to_ov5647(client);
-
-       if (on && !sensor->on) {
-               if (io_regulator)
-                       if (regulator_enable(io_regulator) != 0)
-                               return -EIO;
-               if (core_regulator)
-                       if (regulator_enable(core_regulator) != 0)
-                               return -EIO;
-               if (gpo_regulator)
-                       if (regulator_enable(gpo_regulator) != 0)
-                               return -EIO;
-               if (analog_regulator)
-                       if (regulator_enable(analog_regulator) != 0)
-                               return -EIO;
-       } else if (!on && sensor->on) {
-               if (analog_regulator)
-                       regulator_disable(analog_regulator);
-               if (core_regulator)
-                       regulator_disable(core_regulator);
-               if (io_regulator)
-                       regulator_disable(io_regulator);
-               if (gpo_regulator)
-                       regulator_disable(gpo_regulator);
-       }
-
-       sensor->on = on;
-
-       return 0;
-}
-
-/*!
- * ov5647_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
- * @s: pointer to standard V4L2 sub device structure
- * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
- *
- * Returns the sensor's video CAPTURE parameters.
- */
-static int ov5647_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5647 *sensor = to_ov5647(client);
-       struct v4l2_captureparm *cparm = &a->parm.capture;
-       int ret = 0;
-
-       switch (a->type) {
-       /* This is the only case currently handled. */
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               memset(a, 0, sizeof(*a));
-               a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               cparm->capability = sensor->streamcap.capability;
-               cparm->timeperframe = sensor->streamcap.timeperframe;
-               cparm->capturemode = sensor->streamcap.capturemode;
-               ret = 0;
-               break;
-
-       /* These are all the possible cases. */
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_VBI_OUTPUT:
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               ret = -EINVAL;
-               break;
-
-       default:
-               pr_debug("   type is unknown - %d\n", a->type);
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
-}
-
-/*!
- * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
- * @s: pointer to standard V4L2 sub device structure
- * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
- *
- * Configures the sensor to use the input parameters, if possible.  If
- * not possible, reverts to the old parameters and returns the
- * appropriate error code.
- */
-static int ov5647_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5647 *sensor = to_ov5647(client);
-       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
-       u32 tgt_fps;    /* target frames per secound */
-       enum ov5647_frame_rate frame_rate;
-       enum ov5647_mode orig_mode;
-       int ret = 0;
-
-       /* Make sure power on */
-       ov5647_power_down(0);
-
-       switch (a->type) {
-       /* This is the only case currently handled. */
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               /* Check that the new frame rate is allowed. */
-               if ((timeperframe->numerator == 0) ||
-                   (timeperframe->denominator == 0)) {
-                       timeperframe->denominator = DEFAULT_FPS;
-                       timeperframe->numerator = 1;
-               }
-
-               tgt_fps = timeperframe->denominator /
-                         timeperframe->numerator;
-
-               if (tgt_fps > MAX_FPS) {
-                       timeperframe->denominator = MAX_FPS;
-                       timeperframe->numerator = 1;
-               } else if (tgt_fps < MIN_FPS) {
-                       timeperframe->denominator = MIN_FPS;
-                       timeperframe->numerator = 1;
-               }
-
-               /* Actual frame rate we use */
-               tgt_fps = timeperframe->denominator /
-                         timeperframe->numerator;
-
-               if (tgt_fps == 15)
-                       frame_rate = ov5647_15_fps;
-               else if (tgt_fps == 30)
-                       frame_rate = ov5647_30_fps;
-               else {
-                       pr_err(" The camera frame rate is not supported!\n");
-                       return -EINVAL;
-               }
-
-               orig_mode = sensor->streamcap.capturemode;
-               ret = ov5647_init_mode(frame_rate,
-                               (u32)a->parm.capture.capturemode, orig_mode);
-               if (ret < 0)
-                       return ret;
-
-               sensor->streamcap.timeperframe = *timeperframe;
-               sensor->streamcap.capturemode =
-                               (u32)a->parm.capture.capturemode;
-
-               break;
-
-       /* These are all the possible cases. */
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_VBI_OUTPUT:
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               pr_debug("type is not " \
-                       "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
-                       a->type);
-               ret = -EINVAL;
-               break;
-
-       default:
-               pr_debug("type is unknown - %d\n", a->type);
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
-}
-
-static int ov5647_set_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_pad_config *cfg,
-                         struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf = &format->format;
-       const struct ov5647_datafmt *fmt = ov5647_find_datafmt(mf->code);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5647 *sensor = to_ov5647(client);
-
-       if (!fmt) {
-               mf->code        = ov5647_colour_fmts[0].code;
-               mf->colorspace  = ov5647_colour_fmts[0].colorspace;
-       }
-
-       mf->field       = V4L2_FIELD_NONE;
-
-       if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-               return 0;
-
-       sensor->fmt = fmt;
-
-       return 0;
-}
-
-static int ov5647_get_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_pad_config *cfg,
-                         struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf = &format->format;
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov5647 *sensor = to_ov5647(client);
-       const struct ov5647_datafmt *fmt = sensor->fmt;
-
-       if (format->pad)
-               return -EINVAL;
-
-       mf->code        = fmt->code;
-       mf->colorspace  = fmt->colorspace;
-       mf->field       = V4L2_FIELD_NONE;
-
-       return 0;
-}
-
-static int ov5647_enum_mbus_code(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_pad_config *cfg,
-                                struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->pad || code->index >= ARRAY_SIZE(ov5647_colour_fmts))
-               return -EINVAL;
-
-       code->code = ov5647_colour_fmts[code->index].code;
-       return 0;
-}
-
-/*!
- * ov5647_enum_framesizes - V4L2 sensor interface handler for
- *                        VIDIOC_ENUM_FRAMESIZES ioctl
- * @s: pointer to standard V4L2 device structure
- * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
- *
- * Return 0 if successful, otherwise -EINVAL.
- */
-static int ov5647_enum_framesizes(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_pad_config *cfg,
-                              struct v4l2_subdev_frame_size_enum *fse)
-{
-       if (fse->index > ov5647_mode_MAX)
-               return -EINVAL;
-
-       fse->max_width =
-                       max(ov5647_mode_info_data[0][fse->index].width,
-                           ov5647_mode_info_data[1][fse->index].width);
-       fse->min_width = fse->max_width;
-       fse->max_height =
-                       max(ov5647_mode_info_data[0][fse->index].height,
-                           ov5647_mode_info_data[1][fse->index].height);
-       fse->min_height = fse->max_height;
-       return 0;
-}
-
-/*!
- * ov5647_enum_frameintervals - V4L2 sensor interface handler for
- *                            VIDIOC_ENUM_FRAMEINTERVALS ioctl
- * @s: pointer to standard V4L2 device structure
- * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
- *
- * Return 0 if successful, otherwise -EINVAL.
- */
-static int ov5647_enum_frameintervals(struct v4l2_subdev *sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_frame_interval_enum *fie)
-{
-       int i, j, count;
-
-       if (fie->index < 0 || fie->index > ov5647_mode_MAX)
-               return -EINVAL;
-
-       if (fie->width == 0 || fie->height == 0 ||
-           fie->code == 0) {
-               pr_warning("Please assign pixel format, width and height.\n");
-               return -EINVAL;
-       }
-
-       fie->interval.numerator = 1;
-
-       count = 0;
-       for (i = 0; i < ARRAY_SIZE(ov5647_mode_info_data); i++) {
-               for (j = 0; j < (ov5647_mode_MAX + 1); j++) {
-                       if (fie->width == ov5647_mode_info_data[i][j].width
-                        && fie->height == ov5647_mode_info_data[i][j].height
-                        && ov5647_mode_info_data[i][j].init_data_ptr != NULL) {
-                               count++;
-                       }
-                       if (fie->index == (count - 1)) {
-                               fie->interval.denominator =
-                                               ov5647_framerates[i];
-                               return 0;
-                       }
-               }
-       }
-
-       return -EINVAL;
-}
-
-/*!
- * dev_init - V4L2 sensor init
- * @s: pointer to standard V4L2 device structure
- *
- */
-static int init_device(void)
-{
-       u32 tgt_xclk;   /* target xclk */
-       u32 tgt_fps;    /* target frames per secound */
-       enum ov5647_frame_rate frame_rate;
-       int ret;
-
-       ov5647_data.on = true;
-
-       /* mclk */
-       tgt_xclk = ov5647_data.mclk;
-       tgt_xclk = min(tgt_xclk, (u32)OV5647_XCLK_MAX);
-       tgt_xclk = max(tgt_xclk, (u32)OV5647_XCLK_MIN);
-       ov5647_data.mclk = tgt_xclk;
-
-       pr_debug("   Setting mclk to %d MHz\n", tgt_xclk / 1000000);
-
-       /* Default camera frame rate is set in probe */
-       tgt_fps = ov5647_data.streamcap.timeperframe.denominator /
-                 ov5647_data.streamcap.timeperframe.numerator;
-
-       if (tgt_fps == 15)
-               frame_rate = ov5647_15_fps;
-       else if (tgt_fps == 30)
-               frame_rate = ov5647_30_fps;
-       else
-               return -EINVAL; /* Only support 15fps or 30fps now. */
-
-       ret = ov5647_init_mode(frame_rate, ov5647_mode_INIT, ov5647_mode_INIT);
-
-       ov5647_update_otp();
-       return ret;
-}
-
-static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
-{
-       if (enable)
-               ov5647_stream_on();
-       else
-               ov5647_stream_off();
-       return 0;
-}
-
-static struct v4l2_subdev_video_ops ov5647_subdev_video_ops = {
-       .g_parm = ov5647_g_parm,
-       .s_parm = ov5647_s_parm,
-       .s_stream = ov5647_s_stream,
-};
-
-static const struct v4l2_subdev_pad_ops ov5647_subdev_pad_ops = {
-       .enum_frame_size       = ov5647_enum_framesizes,
-       .enum_frame_interval   = ov5647_enum_frameintervals,
-       .enum_mbus_code        = ov5647_enum_mbus_code,
-       .set_fmt               = ov5647_set_fmt,
-       .get_fmt               = ov5647_get_fmt,
-};
-
-static struct v4l2_subdev_core_ops ov5647_subdev_core_ops = {
-       .s_power        = ov5647_s_power,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register     = ov5647_get_register,
-       .s_register     = ov5647_set_register,
-#endif
-};
-
-static struct v4l2_subdev_ops ov5647_subdev_ops = {
-       .core   = &ov5647_subdev_core_ops,
-       .video  = &ov5647_subdev_video_ops,
-       .pad    = &ov5647_subdev_pad_ops,
-};
-
-
-/*!
- * ov5647 I2C probe function
- *
- * @param adapter            struct i2c_adapter *
- * @return  Error code indicating success or failure
- */
-static int ov5647_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
-{
-       struct pinctrl *pinctrl;
-       struct device *dev = &client->dev;
-       int retval;
-       u8 chip_id_high, chip_id_low;
-
-       /* ov5647 pinctrl */
-       pinctrl = devm_pinctrl_get_select_default(dev);
-       if (IS_ERR(pinctrl)) {
-               dev_warn(dev, "no  pin available\n");
-       }
-
-
-       /* request power down pin */
-       pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
-       if (!gpio_is_valid(pwn_gpio)) {
-               dev_warn(dev, "no sensor pwdn pin available\n");
-               pwn_gpio = -1;
-       } else {
-               retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
-                                               "ov5647_mipi_pwdn");
-               if (retval < 0) {
-                       dev_warn(dev, "Failed to set power pin\n");
-                       return retval;
-               }
-       }
-
-       /* request reset pin */
-       rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
-       if (!gpio_is_valid(rst_gpio)) {
-               dev_warn(dev, "no sensor reset pin available\n");
-               rst_gpio = -1;
-       } else {
-               retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
-                                               "ov5647_mipi_reset");
-               if (retval < 0) {
-                       dev_warn(dev, "Failed to set reset pin\n");
-                       return retval;
-               }
-       }
-
-       /* Set initial values for the sensor struct. */
-       memset(&ov5647_data, 0, sizeof(ov5647_data));
-       ov5647_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
-       if (IS_ERR(ov5647_data.sensor_clk)) {
-               /* assuming clock enabled by default */
-               ov5647_data.sensor_clk = NULL;
-               dev_err(dev, "clock-frequency missing or invalid\n");
-               return PTR_ERR(ov5647_data.sensor_clk);
-       }
-
-       retval = of_property_read_u32(dev->of_node, "mclk",
-                                       &(ov5647_data.mclk));
-       if (retval) {
-               dev_err(dev, "mclk missing or invalid\n");
-               return retval;
-       }
-
-       retval = of_property_read_u32(dev->of_node, "mclk_source",
-                                       (u32 *) &(ov5647_data.mclk_source));
-       if (retval) {
-               dev_err(dev, "mclk_source missing or invalid\n");
-               return retval;
-       }
-
-       retval = of_property_read_u32(dev->of_node, "csi_id",
-                                       &(ov5647_data.csi));
-       if (retval) {
-               dev_err(dev, "csi id missing or invalid\n");
-               return retval;
-       }
-
-       clk_prepare_enable(ov5647_data.sensor_clk);
-
-       ov5647_data.io_init = ov5647_reset;
-       ov5647_data.i2c_client = client;
-       ov5647_data.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
-       ov5647_data.pix.width = 640;
-       ov5647_data.pix.height = 480;
-       ov5647_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
-                                          V4L2_CAP_TIMEPERFRAME;
-       ov5647_data.streamcap.capturemode = 0;
-       ov5647_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
-       ov5647_data.streamcap.timeperframe.numerator = 1;
-
-       ov5647_regulator_enable(&client->dev);
-
-       ov5647_reset();
-
-       ov5647_power_down(0);
-
-       retval = ov5647_read_reg(OV5647_CHIP_ID_HIGH_BYTE, &chip_id_high);
-       if (retval < 0 || chip_id_high != 0x56) {
-               pr_warning("camera ov5647_mipi is not found\n");
-               clk_disable_unprepare(ov5647_data.sensor_clk);
-               return -ENODEV;
-       }
-       retval = ov5647_read_reg(OV5647_CHIP_ID_LOW_BYTE, &chip_id_low);
-       if (retval < 0 || chip_id_low != 0x47) {
-               pr_warning("camera ov5647_mipi is not found\n");
-               clk_disable_unprepare(ov5647_data.sensor_clk);
-               return -ENODEV;
-       }
-
-       retval = init_device();
-       if (retval < 0) {
-               clk_disable_unprepare(ov5647_data.sensor_clk);
-               pr_warning("camera ov5647 init failed\n");
-               ov5647_power_down(1);
-               return retval;
-       }
-
-       v4l2_i2c_subdev_init(&ov5647_data.subdev, client, &ov5647_subdev_ops);
-
-       ov5647_data.subdev.grp_id = 678;
-       retval = v4l2_async_register_subdev(&ov5647_data.subdev);
-       if (retval < 0)
-               dev_err(&client->dev,
-                                       "%s--Async register failed, ret=%d\n", __func__, retval);
-
-       ov5647_stream_off();
-       pr_info("camera ov5647_mipi is found\n");
-       return retval;
-}
-
-/*!
- * ov5647 I2C detach function
- *
- * @param client            struct i2c_client *
- * @return  Error code indicating success or failure
- */
-static int ov5647_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-       v4l2_async_unregister_subdev(sd);
-
-       clk_disable_unprepare(ov5647_data.sensor_clk);
-
-       ov5647_power_down(1);
-
-       if (gpo_regulator)
-               regulator_disable(gpo_regulator);
-
-       if (analog_regulator)
-               regulator_disable(analog_regulator);
-
-       if (core_regulator)
-               regulator_disable(core_regulator);
-
-       if (io_regulator)
-               regulator_disable(io_regulator);
-
-       return 0;
-}
-
-module_i2c_driver(ov5647_i2c_driver);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("OV5647 MIPI Camera Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("CSI");