MLK-11508-4: V4L2 Capture: Porting MXC V4L2 Capture from 3.14.y
authorSandor Yu <R01008@freescale.com>
Mon, 31 Aug 2015 10:15:43 +0000 (18:15 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:48:38 +0000 (14:48 -0500)
Initial port of the mxc V4L2 capture driver.
Baseline copied from imx_3.14.y branch:

Signed-off-by: Sandor Yu <R01008@freescale.com>
38 files changed:
arch/arm/configs/imx_v7_defconfig
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/mxc/capture/Kconfig [new file with mode: 0644]
drivers/media/platform/mxc/capture/Makefile [new file with mode: 0644]
drivers/media/platform/mxc/capture/adv7180.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ipu_csi_enc.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ipu_prp_enc.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ipu_prp_sw.h [new file with mode: 0644]
drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ipu_still.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/mxc_v4l2_capture.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/mxc_v4l2_capture.h [new file with mode: 0644]
drivers/media/platform/mxc/capture/ov5640.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ov5640_mipi.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/ov5642.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/v4l2-int-device.c [new file with mode: 0644]
drivers/media/platform/mxc/capture/v4l2-int-device.h [new file with mode: 0644]
drivers/media/platform/mxc/subdev/Kconfig [new file with mode: 0644]
drivers/media/platform/mxc/subdev/Makefile [new file with mode: 0644]
drivers/media/platform/mxc/subdev/mx6s_capture.c [new file with mode: 0644]
drivers/media/platform/mxc/subdev/mxc_mipi_csi.c [new file with mode: 0644]
drivers/media/platform/mxc/subdev/mxc_vadc.c [new file with mode: 0644]
drivers/media/platform/mxc/subdev/mxc_vadc.h [new file with mode: 0644]
drivers/media/platform/mxc/subdev/ov5640.c [new file with mode: 0644]
drivers/media/platform/mxc/subdev/ov5640_mipi.c [new file with mode: 0644]
drivers/media/platform/mxc/subdev/ov5647_mipi.c [new file with mode: 0644]
drivers/mxc/Kconfig
drivers/mxc/Makefile
drivers/mxc/mipi/Kconfig [new file with mode: 0644]
drivers/mxc/mipi/Makefile [new file with mode: 0644]
drivers/mxc/mipi/mxc_mipi_csi2.c [new file with mode: 0644]
drivers/mxc/mipi/mxc_mipi_csi2.h [new file with mode: 0644]
include/linux/mipi_csi2.h [new file with mode: 0644]
include/uapi/linux/mxc_v4l2.h

index 2682d55..7d4a7e5 100644 (file)
@@ -158,6 +158,7 @@ CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
 CONFIG_TOUCHSCREEN_EGALAX=y
 CONFIG_TOUCHSCREEN_ELAN=y
 CONFIG_TOUCHSCREEN_MAX11801=y
+CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
 CONFIG_TOUCHSCREEN_MC13783=y
 CONFIG_TOUCHSCREEN_TSC2007=y
 CONFIG_TOUCHSCREEN_STMPE=y
@@ -217,10 +218,20 @@ CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_VIDEO_MXC_OUTPUT=y
-CONFIG_SOC_CAMERA=y
-CONFIG_VIDEO_MX3=y
+CONFIG_VIDEO_MXC_CAPTURE=m
+CONFIG_MXC_CAMERA_OV5640=m
+CONFIG_MXC_CAMERA_OV5642=m
+CONFIG_MXC_CAMERA_OV5640_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_VIDEO_MX3=y
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_CODA=y
 CONFIG_RADIO_SI476X=y
@@ -303,6 +314,8 @@ CONFIG_MXC_MLB150=m
 CONFIG_MXC_IPU_V3_PRE=y
 CONFIG_MXC_GPU_VIV=y
 CONFIG_MXC_SIM=y
+CONFIG_MXC_MIPI_CSI2=y
+CONFIG_MXC_HDMI_CEC=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
index c503ed6..8579ec1 100644 (file)
@@ -121,6 +121,15 @@ config VIDEO_MXC_OUTPUT
        ---help---
        This is the video4linux2 output driver based on MXC module.
 
+config VIDEO_MXC_CAPTURE
+       tristate "MXC Video For Linux Video Capture"
+       depends on VIDEO_V4L2
+       ---help---
+         This is the video4linux2 capture driver based on i.MX video-in module.
+
+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"
@@ -141,7 +150,6 @@ config VIDEO_TI_CAL
          In TI Technical Reference Manual this module is referred as
          Camera Interface Subsystem (CAMSS).
 
-source "drivers/media/platform/mxc/output/Kconfig"
 
 endif # V4L_PLATFORM_DRIVERS
 
index 04829cc..b924520 100644 (file)
@@ -63,6 +63,10 @@ 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/
+
 ccflags-y += -I$(srctree)/drivers/media/i2c
 
 obj-$(CONFIG_VIDEO_MEDIATEK_VPU)       += mtk-vpu/
diff --git a/drivers/media/platform/mxc/capture/Kconfig b/drivers/media/platform/mxc/capture/Kconfig
new file mode 100644 (file)
index 0000000..e8728d9
--- /dev/null
@@ -0,0 +1,83 @@
+if VIDEO_MXC_CAPTURE
+config VIDEO_V4L2_MXC_INT_DEVICE
+       tristate
+
+menu "MXC Camera/V4L2 PRP Features support"
+config VIDEO_MXC_IPU_CAMERA
+       bool
+       select VIDEO_V4L2_MXC_INT_DEVICE
+       depends on VIDEO_MXC_CAPTURE && MXC_IPU
+       default y
+
+config MXC_CAMERA_OV5640
+        tristate "OmniVision ov5640 camera support"
+        depends on !VIDEO_MXC_EMMA_CAMERA && 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
+       ---help---
+         If you plan to use the ov5642 Camera with your MXC system, say Y here.
+
+config MXC_CAMERA_OV5640_MIPI
+       tristate "OmniVision ov5640 camera support using mipi"
+       depends on !VIDEO_MXC_EMMA_CAMERA && I2C
+       ---help---
+         If you plan to use the ov5640 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
+       ---help---
+         If you plan to use the adv7180 video decoder with your MXC system, say Y here.
+
+choice
+       prompt "Select Overlay Rounting"
+       default MXC_IPU_DEVICE_QUEUE_SDC
+       depends on VIDEO_MXC_IPU_CAMERA && FB_MXC_SYNC_PANEL
+
+config MXC_IPU_DEVICE_QUEUE_SDC
+       tristate "Queue ipu device for overlay library"
+       depends on VIDEO_MXC_IPU_CAMERA
+       ---help---
+         Use case CSI->MEM->IPU DEVICE->SDC:
+               Images from sensor will be frist recieved in memory,then
+               queue to ipu device for processing if needed, and displaying
+               it on synchronous display with SDC use case.
+
+config MXC_IPU_PRP_VF_SDC
+       bool "Pre-Processor VF SDC library"
+       depends on VIDEO_MXC_IPU_CAMERA
+       ---help---
+         Use case PRP_VF_SDC:
+               Preprocessing image from smart sensor for viewfinder and
+               displaying it on synchronous display with SDC use case.
+               If SDC BG is selected, Rotation will not be supported.
+               CSI -> IC (PRP VF) -> MEM
+               MEM -> IC (ROT) -> MEM
+               MEM -> SDC (FG/BG)
+
+endchoice
+
+config MXC_IPU_PRP_ENC
+       tristate "Pre-processor Encoder library"
+       depends on VIDEO_MXC_IPU_CAMERA
+       default y
+       ---help---
+         Use case PRP_ENC:
+               Preprocessing image from smart sensor for encoder.
+               CSI -> IC (PRP ENC) -> MEM
+
+config MXC_IPU_CSI_ENC
+       tristate "IPU CSI Encoder library"
+       depends on VIDEO_MXC_IPU_CAMERA
+       default y
+       ---help---
+         Use case IPU_CSI_ENC:
+               Get raw image with CSI from smart sensor for encoder.
+               CSI -> MEM
+endmenu
+
+endif
diff --git a/drivers/media/platform/mxc/capture/Makefile b/drivers/media/platform/mxc/capture/Makefile
new file mode 100644 (file)
index 0000000..6c04faf
--- /dev/null
@@ -0,0 +1,21 @@
+ifeq ($(CONFIG_VIDEO_MXC_IPU_CAMERA),y)
+       obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc_v4l2_capture.o
+       obj-$(CONFIG_MXC_IPU_PRP_VF_SDC) += ipu_prp_vf_sdc.o ipu_prp_vf_sdc_bg.o
+       obj-$(CONFIG_MXC_IPU_DEVICE_QUEUE_SDC) += ipu_fg_overlay_sdc.o ipu_bg_overlay_sdc.o
+       obj-$(CONFIG_MXC_IPU_PRP_ENC) += ipu_prp_enc.o ipu_still.o
+       obj-$(CONFIG_MXC_IPU_CSI_ENC) += ipu_csi_enc.o ipu_still.o
+endif
+
+ov5640_camera_int-objs := ov5640.o
+obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera_int.o
+
+ov5642_camera-objs := ov5642.o
+obj-$(CONFIG_MXC_CAMERA_OV5642) += ov5642_camera.o
+
+ov5640_camera_mipi_int-objs := ov5640_mipi.o
+obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi_int.o
+
+adv7180_tvin-objs := adv7180.o
+obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o
+
+obj-$(CONFIG_VIDEO_V4L2_MXC_INT_DEVICE) += v4l2-int-device.o
diff --git a/drivers/media/platform/mxc/capture/adv7180.c b/drivers/media/platform/mxc/capture/adv7180.c
new file mode 100644 (file)
index 0000000..abd6159
--- /dev/null
@@ -0,0 +1,1380 @@
+/*
+ * Copyright 2005-2014 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 adv7180.c
+ *
+ * @brief Analog Device ADV7180 video decoder functions
+ *
+ * @ingroup Camera
+ */
+
+#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 <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.h"
+
+#define ADV7180_VOLTAGE_ANALOG               1800000
+#define ADV7180_VOLTAGE_DIGITAL_CORE         1800000
+#define ADV7180_VOLTAGE_DIGITAL_IO           3300000
+#define ADV7180_VOLTAGE_PLL                  1800000
+
+static struct regulator *dvddio_regulator;
+static struct regulator *dvdd_regulator;
+static struct regulator *avdd_regulator;
+static struct regulator *pvdd_regulator;
+static int pwn_gpio;
+
+static int adv7180_probe(struct i2c_client *adapter,
+                        const struct i2c_device_id *id);
+static int adv7180_detach(struct i2c_client *client);
+
+static const struct i2c_device_id adv7180_id[] = {
+       {"adv7180", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, adv7180_id);
+
+static struct i2c_driver adv7180_i2c_driver = {
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "adv7180",
+                  },
+       .probe = adv7180_probe,
+       .remove = adv7180_detach,
+       .id_table = adv7180_id,
+};
+
+/*!
+ * Maintains the information on the current state of the sensor.
+ */
+struct sensor {
+       struct sensor_data sen;
+       v4l2_std_id std_id;
+} adv7180_data;
+
+
+/*! List of input video formats supported. The video formats is corresponding
+ * with v4l2 id in video_fmt_t
+ */
+typedef enum {
+       ADV7180_NTSC = 0,       /*!< Locked on (M) NTSC video signal. */
+       ADV7180_PAL,            /*!< (B, G, H, I, N)PAL video signal. */
+       ADV7180_NOT_LOCKED,     /*!< Not locked on a signal. */
+} video_fmt_idx;
+
+/*! Number of video standards supported (including 'not locked' signal). */
+#define ADV7180_STD_MAX                (ADV7180_PAL + 1)
+
+/*! Video format structure. */
+typedef struct {
+       int v4l2_id;            /*!< 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. */
+       int frame_rate;         /*!< Frame rate. */
+} video_fmt_t;
+
+/*! Description of video formats supported.
+ *
+ *  PAL: raw=720x625, active=720x576.
+ *  NTSC: raw=720x525, active=720x480.
+ */
+static video_fmt_t video_fmts[] = {
+       {                       /*! NTSC */
+        .v4l2_id = V4L2_STD_NTSC,
+        .name = "NTSC",
+        .raw_width = 720,      /* SENS_FRM_WIDTH */
+        .raw_height = 525,     /* SENS_FRM_HEIGHT */
+        .active_width = 720,   /* ACT_FRM_WIDTH plus 1 */
+        .active_height = 480,  /* ACT_FRM_WIDTH plus 1 */
+        .frame_rate = 30,
+        },
+       {                       /*! (B, G, H, I, N) PAL */
+        .v4l2_id = V4L2_STD_PAL,
+        .name = "PAL",
+        .raw_width = 720,
+        .raw_height = 625,
+        .active_width = 720,
+        .active_height = 576,
+        .frame_rate = 25,
+        },
+       {                       /*! Unlocked standard */
+        .v4l2_id = V4L2_STD_ALL,
+        .name = "Autodetect",
+        .raw_width = 720,
+        .raw_height = 625,
+        .active_width = 720,
+        .active_height = 576,
+        .frame_rate = 0,
+        },
+};
+
+/*!* Standard index of ADV7180. */
+static video_fmt_idx video_idx = ADV7180_PAL;
+
+/*! @brief This mutex is used to provide mutual exclusion.
+ *
+ *  Create a mutex that can be used to provide mutually exclusive
+ *  read/write access to the globally accessible data structures
+ *  and variables that were defined above.
+ */
+static DEFINE_MUTEX(mutex);
+
+#define IF_NAME                    "adv7180"
+#define ADV7180_INPUT_CTL              0x00    /* Input Control */
+#define ADV7180_STATUS_1               0x10    /* Status #1 */
+#define ADV7180_BRIGHTNESS             0x0a    /* Brightness */
+#define ADV7180_IDENT                  0x11    /* IDENT */
+#define ADV7180_VSYNC_FIELD_CTL_1      0x31    /* VSYNC Field Control #1 */
+#define ADV7180_MANUAL_WIN_CTL         0x3d    /* Manual Window Control */
+#define ADV7180_SD_SATURATION_CB       0xe3    /* SD Saturation Cb */
+#define ADV7180_SD_SATURATION_CR       0xe4    /* SD Saturation Cr */
+#define ADV7180_PWR_MNG                0x0f     /* Power Management */
+
+/* supported controls */
+/* This hasn't been fully implemented yet.
+ * This is how it should work, though. */
+static struct v4l2_queryctrl adv7180_qctrl[] = {
+       {
+       .id = V4L2_CID_BRIGHTNESS,
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .name = "Brightness",
+       .minimum = 0,           /* check this value */
+       .maximum = 255,         /* check this value */
+       .step = 1,              /* check this value */
+       .default_value = 127,   /* check this value */
+       .flags = 0,
+       }, {
+       .id = V4L2_CID_SATURATION,
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .name = "Saturation",
+       .minimum = 0,           /* check this value */
+       .maximum = 255,         /* check this value */
+       .step = 0x1,            /* check this value */
+       .default_value = 127,   /* check this value */
+       .flags = 0,
+       }
+};
+
+static inline void adv7180_power_down(int enable)
+{
+       gpio_set_value_cansleep(pwn_gpio, !enable);
+       msleep(2);
+}
+
+static int adv7180_regulator_enable(struct device *dev)
+{
+       int ret = 0;
+
+       dvddio_regulator = devm_regulator_get(dev, "DOVDD");
+
+       if (!IS_ERR(dvddio_regulator)) {
+               regulator_set_voltage(dvddio_regulator,
+                                     ADV7180_VOLTAGE_DIGITAL_IO,
+                                     ADV7180_VOLTAGE_DIGITAL_IO);
+               ret = regulator_enable(dvddio_regulator);
+               if (ret) {
+                       dev_err(dev, "set io voltage failed\n");
+                       return ret;
+               } else {
+                       dev_dbg(dev, "set io voltage ok\n");
+               }
+       } else {
+               dev_warn(dev, "cannot get io voltage\n");
+       }
+
+       dvdd_regulator = devm_regulator_get(dev, "DVDD");
+       if (!IS_ERR(dvdd_regulator)) {
+               regulator_set_voltage(dvdd_regulator,
+                                     ADV7180_VOLTAGE_DIGITAL_CORE,
+                                     ADV7180_VOLTAGE_DIGITAL_CORE);
+               ret = regulator_enable(dvdd_regulator);
+               if (ret) {
+                       dev_err(dev, "set core voltage failed\n");
+                       return ret;
+               } else {
+                       dev_dbg(dev, "set core voltage ok\n");
+               }
+       } else {
+               dev_warn(dev, "cannot get core voltage\n");
+       }
+
+       avdd_regulator = devm_regulator_get(dev, "AVDD");
+       if (!IS_ERR(avdd_regulator)) {
+               regulator_set_voltage(avdd_regulator,
+                                     ADV7180_VOLTAGE_ANALOG,
+                                     ADV7180_VOLTAGE_ANALOG);
+               ret = regulator_enable(avdd_regulator);
+               if (ret) {
+                       dev_err(dev, "set analog voltage failed\n");
+                       return ret;
+               } else {
+                       dev_dbg(dev, "set analog voltage ok\n");
+               }
+       } else {
+               dev_warn(dev, "cannot get analog voltage\n");
+       }
+
+       pvdd_regulator = devm_regulator_get(dev, "PVDD");
+       if (!IS_ERR(pvdd_regulator)) {
+               regulator_set_voltage(pvdd_regulator,
+                                     ADV7180_VOLTAGE_PLL,
+                                     ADV7180_VOLTAGE_PLL);
+               ret = regulator_enable(pvdd_regulator);
+               if (ret) {
+                       dev_err(dev, "set pll voltage failed\n");
+                       return ret;
+               } else {
+                       dev_dbg(dev, "set pll voltage ok\n");
+               }
+       } else {
+               dev_warn(dev, "cannot get pll voltage\n");
+       }
+
+       return ret;
+}
+
+
+/***********************************************************************
+ * I2C transfert.
+ ***********************************************************************/
+
+/*! Read one register from a ADV7180 i2c slave device.
+ *
+ *  @param *reg                register in the device we wish to access.
+ *
+ *  @return                   0 if success, an error code otherwise.
+ */
+static inline int adv7180_read(u8 reg)
+{
+       int val;
+
+       val = i2c_smbus_read_byte_data(adv7180_data.sen.i2c_client, reg);
+       if (val < 0) {
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "%s:read reg error: reg=%2x\n", __func__, reg);
+               return -1;
+       }
+       return val;
+}
+
+/*! Write one register of a ADV7180 i2c slave device.
+ *
+ *  @param *reg                register in the device we wish to access.
+ *
+ *  @return                   0 if success, an error code otherwise.
+ */
+static int adv7180_write_reg(u8 reg, u8 val)
+{
+       s32 ret;
+
+       ret = i2c_smbus_write_byte_data(adv7180_data.sen.i2c_client, reg, val);
+       if (ret < 0) {
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "%s:write reg error:reg=%2x,val=%2x\n", __func__,
+                       reg, val);
+               return -1;
+       }
+       return 0;
+}
+
+/***********************************************************************
+ * mxc_v4l2_capture interface.
+ ***********************************************************************/
+
+/*!
+ * 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 void adv7180_get_std(v4l2_std_id *std)
+{
+       int status_1, standard, idx;
+       bool locked;
+
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_get_std\n");
+
+       status_1 = adv7180_read(ADV7180_STATUS_1);
+       locked = status_1 & 0x1;
+       standard = status_1 & 0x70;
+
+       mutex_lock(&mutex);
+       *std = V4L2_STD_ALL;
+       idx = ADV7180_NOT_LOCKED;
+       if (locked) {
+               if (standard == 0x40) {
+                       *std = V4L2_STD_PAL;
+                       idx = ADV7180_PAL;
+               } else if (standard == 0) {
+                       *std = V4L2_STD_NTSC;
+                       idx = ADV7180_NTSC;
+               }
+       }
+       mutex_unlock(&mutex);
+
+       /* This assumes autodetect which this device uses. */
+       if (*std != adv7180_data.std_id) {
+               video_idx = idx;
+               adv7180_data.std_id = *std;
+               adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width;
+               adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height;
+       }
+}
+
+/***********************************************************************
+ * IOCTL Functions from v4l2_int_ioctl_desc.
+ ***********************************************************************/
+
+/*!
+ * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num
+ * s: pointer to standard V4L2 device structure
+ * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure
+ *
+ * Gets slave interface parameters.
+ * Calculates the required xclk value to support the requested
+ * clock parameters in p.  This value is returned in the p
+ * parameter.
+ *
+ * vidioc_int_g_ifparm returns platform-specific information about the
+ * interface settings used by the sensor.
+ *
+ * Called on open.
+ */
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_ifparm\n");
+
+       if (s == NULL) {
+               pr_err("   ERROR!! no slave device set!\n");
+               return -1;
+       }
+
+       /* Initialize structure to 0s then set any non-0 values. */
+       memset(p, 0, sizeof(*p));
+       p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */
+       p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+       p->u.bt656.nobt_hs_inv = 1;
+       p->u.bt656.bt_sync_correct = 1;
+
+       /* ADV7180 has a dedicated clock so no clock settings needed. */
+
+       return 0;
+}
+
+/*!
+ * Sets the camera power.
+ *
+ * s  pointer to the camera device
+ * on if 1, power is to be turned on.  0 means power is to be turned off
+ *
+ * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num
+ * @s: pointer to standard V4L2 device structure
+ * @on: power state to which device is to be set
+ *
+ * Sets devices power state to requrested state, if possible.
+ * This is called on open, close, suspend and resume.
+ */
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+       struct sensor *sensor = s->priv;
+
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_s_power\n");
+
+       if (on && !sensor->sen.on) {
+               if (adv7180_write_reg(ADV7180_PWR_MNG, 0x04) != 0)
+                       return -EIO;
+
+               /*
+                * FIXME:Additional 400ms to wait the chip to be stable?
+                * This is a workaround for preview scrolling issue.
+                */
+               msleep(400);
+       } else if (!on && sensor->sen.on) {
+               if (adv7180_write_reg(ADV7180_PWR_MNG, 0x24) != 0)
+                       return -EIO;
+       }
+
+       sensor->sen.on = on;
+
+       return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+       struct sensor *sensor = s->priv;
+       struct v4l2_captureparm *cparm = &a->parm.capture;
+
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_parm\n");
+
+       switch (a->type) {
+       /* These are all the possible cases. */
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               pr_debug("   type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+               memset(a, 0, sizeof(*a));
+               a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               cparm->capability = sensor->sen.streamcap.capability;
+               cparm->timeperframe = sensor->sen.streamcap.timeperframe;
+               cparm->capturemode = sensor->sen.streamcap.capturemode;
+               break;
+
+       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:
+               break;
+
+       default:
+               pr_debug("ioctl_g_parm:type is unknown %d\n", a->type);
+               break;
+       }
+
+       return 0;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 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.
+ *
+ * This driver cannot change these settings.
+ */
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_parm\n");
+
+       switch (a->type) {
+       /* These are all the possible cases. */
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+       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:
+               break;
+
+       default:
+               pr_debug("   type is unknown - %d\n", a->type);
+               break;
+       }
+
+       return 0;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+       struct sensor *sensor = s->priv;
+
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_fmt_cap\n");
+
+       switch (f->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               pr_debug("   Returning size of %dx%d\n",
+                        sensor->sen.pix.width, sensor->sen.pix.height);
+               f->fmt.pix = sensor->sen.pix;
+               break;
+
+       case V4L2_BUF_TYPE_PRIVATE: {
+               v4l2_std_id std;
+               adv7180_get_std(&std);
+               f->fmt.pix.pixelformat = (u32)std;
+               }
+               break;
+
+       default:
+               f->fmt.pix = sensor->sen.pix;
+               break;
+       }
+
+       return 0;
+}
+
+/*!
+ * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control information
+ * from the video_control[] array.  Otherwise, returns -EINVAL if the
+ * control is not supported.
+ */
+static int ioctl_queryctrl(struct v4l2_int_device *s,
+                          struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_queryctrl\n");
+
+       for (i = 0; i < ARRAY_SIZE(adv7180_qctrl); i++)
+               if (qc->id && qc->id == adv7180_qctrl[i].id) {
+                       memcpy(qc, &(adv7180_qctrl[i]),
+                               sizeof(*qc));
+                       return 0;
+               }
+
+       return -EINVAL;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array.  Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+       int ret = 0;
+       int sat = 0;
+
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n");
+
+       switch (vc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_BRIGHTNESS\n");
+               adv7180_data.sen.brightness = adv7180_read(ADV7180_BRIGHTNESS);
+               vc->value = adv7180_data.sen.brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_CONTRAST\n");
+               vc->value = adv7180_data.sen.contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_SATURATION\n");
+               sat = adv7180_read(ADV7180_SD_SATURATION_CB);
+               adv7180_data.sen.saturation = sat;
+               vc->value = adv7180_data.sen.saturation;
+               break;
+       case V4L2_CID_HUE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_HUE\n");
+               vc->value = adv7180_data.sen.hue;
+               break;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_AUTO_WHITE_BALANCE\n");
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_DO_WHITE_BALANCE\n");
+               break;
+       case V4L2_CID_RED_BALANCE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_RED_BALANCE\n");
+               vc->value = adv7180_data.sen.red;
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_BLUE_BALANCE\n");
+               vc->value = adv7180_data.sen.blue;
+               break;
+       case V4L2_CID_GAMMA:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_GAMMA\n");
+               break;
+       case V4L2_CID_EXPOSURE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_EXPOSURE\n");
+               vc->value = adv7180_data.sen.ae_mode;
+               break;
+       case V4L2_CID_AUTOGAIN:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_AUTOGAIN\n");
+               break;
+       case V4L2_CID_GAIN:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_GAIN\n");
+               break;
+       case V4L2_CID_HFLIP:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_HFLIP\n");
+               break;
+       case V4L2_CID_VFLIP:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_VFLIP\n");
+               break;
+       default:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   Default case\n");
+               vc->value = 0;
+               ret = -EPERM;
+               break;
+       }
+
+       return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array).  Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+       int retval = 0;
+       u8 tmp;
+
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n");
+
+       switch (vc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_BRIGHTNESS\n");
+               tmp = vc->value;
+               adv7180_write_reg(ADV7180_BRIGHTNESS, tmp);
+               adv7180_data.sen.brightness = vc->value;
+               break;
+       case V4L2_CID_CONTRAST:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_CONTRAST\n");
+               break;
+       case V4L2_CID_SATURATION:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_SATURATION\n");
+               tmp = vc->value;
+               adv7180_write_reg(ADV7180_SD_SATURATION_CB, tmp);
+               adv7180_write_reg(ADV7180_SD_SATURATION_CR, tmp);
+               adv7180_data.sen.saturation = vc->value;
+               break;
+       case V4L2_CID_HUE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_HUE\n");
+               break;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_AUTO_WHITE_BALANCE\n");
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_DO_WHITE_BALANCE\n");
+               break;
+       case V4L2_CID_RED_BALANCE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_RED_BALANCE\n");
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_BLUE_BALANCE\n");
+               break;
+       case V4L2_CID_GAMMA:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_GAMMA\n");
+               break;
+       case V4L2_CID_EXPOSURE:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_EXPOSURE\n");
+               break;
+       case V4L2_CID_AUTOGAIN:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_AUTOGAIN\n");
+               break;
+       case V4L2_CID_GAIN:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_GAIN\n");
+               break;
+       case V4L2_CID_HFLIP:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_HFLIP\n");
+               break;
+       case V4L2_CID_VFLIP:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   V4L2_CID_VFLIP\n");
+               break;
+       default:
+               dev_dbg(&adv7180_data.sen.i2c_client->dev,
+                       "   Default case\n");
+               retval = -EPERM;
+               break;
+       }
+
+       return retval;
+}
+
+/*!
+ * ioctl_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 ioctl_enum_framesizes(struct v4l2_int_device *s,
+                                struct v4l2_frmsizeenum *fsize)
+{
+       if (fsize->index >= 1)
+               return -EINVAL;
+
+       fsize->discrete.width = video_fmts[video_idx].active_width;
+       fsize->discrete.height  = video_fmts[video_idx].active_height;
+
+       return 0;
+}
+
+/*!
+ * ioctl_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 ioctl_enum_frameintervals(struct v4l2_int_device *s,
+                                        struct v4l2_frmivalenum *fival)
+{
+       video_fmt_t fmt;
+       int i;
+
+       if (fival->index != 0)
+               return -EINVAL;
+
+       for (i = 0; i < ARRAY_SIZE(video_fmts) - 1; i++) {
+               fmt = video_fmts[i];
+               if (fival->width  == fmt.active_width &&
+                   fival->height == fmt.active_height) {
+                       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+                       fival->discrete.numerator = 1;
+                       fival->discrete.denominator = fmt.frame_rate;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ *                     VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+       ((struct v4l2_dbg_chip_ident *)id)->match.type =
+                                       V4L2_CHIP_MATCH_I2C_DRIVER;
+       strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
+                                               "adv7180_decoder");
+       ((struct v4l2_dbg_chip_ident *)id)->ident = V4L2_IDENT_ADV7180;
+
+       return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_init\n");
+       return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_dev_init\n");
+       return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module.
+ */
+static struct v4l2_int_ioctl_desc adv7180_ioctl_desc[] = {
+
+       {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init},
+
+       /*!
+        * Delinitialise the dev. at slave detach.
+        * The complement of ioctl_dev_init.
+        */
+/*     {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *)ioctl_dev_exit}, */
+
+       {vidioc_int_s_power_num, (v4l2_int_ioctl_func*)ioctl_s_power},
+       {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*)ioctl_g_ifparm},
+/*     {vidioc_int_g_needs_reset_num,
+                               (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */
+/*     {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */
+       {vidioc_int_init_num, (v4l2_int_ioctl_func*)ioctl_init},
+
+       /*!
+        * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
+        */
+/*     {vidioc_int_enum_fmt_cap_num,
+                               (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap}, */
+
+       /*!
+        * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.
+        * This ioctl is used to negotiate the image capture size and
+        * pixel format without actually making it take effect.
+        */
+/*     {vidioc_int_try_fmt_cap_num,
+                               (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */
+
+       {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*)ioctl_g_fmt_cap},
+
+       /*!
+        * If the requested format is supported, configures the HW to use that
+        * format, returns error code if format not supported or HW can't be
+        * correctly configured.
+        */
+/*     {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */
+
+       {vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm},
+       {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm},
+       {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func*)ioctl_queryctrl},
+       {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*)ioctl_g_ctrl},
+       {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl},
+       {vidioc_int_enum_framesizes_num,
+                               (v4l2_int_ioctl_func *)ioctl_enum_framesizes},
+       {vidioc_int_enum_frameintervals_num,
+                               (v4l2_int_ioctl_func *)
+                               ioctl_enum_frameintervals},
+       {vidioc_int_g_chip_ident_num,
+                               (v4l2_int_ioctl_func *)ioctl_g_chip_ident},
+};
+
+static struct v4l2_int_slave adv7180_slave = {
+       .ioctls = adv7180_ioctl_desc,
+       .num_ioctls = ARRAY_SIZE(adv7180_ioctl_desc),
+};
+
+static struct v4l2_int_device adv7180_int_device = {
+       .module = THIS_MODULE,
+       .name = "adv7180",
+       .type = v4l2_int_type_slave,
+       .u = {
+               .slave = &adv7180_slave,
+       },
+};
+
+
+/***********************************************************************
+ * I2C client and driver.
+ ***********************************************************************/
+
+/*! ADV7180 Reset function.
+ *
+ *  @return            None.
+ */
+static void adv7180_hard_reset(bool cvbs)
+{
+       dev_dbg(&adv7180_data.sen.i2c_client->dev,
+               "In adv7180:adv7180_hard_reset\n");
+
+       if (cvbs) {
+               /* Set CVBS input on AIN1 */
+               adv7180_write_reg(ADV7180_INPUT_CTL, 0x00);
+       } else {
+               /*
+                * Set YPbPr input on AIN1,4,5 and normal
+                * operations(autodection of all stds).
+                */
+               adv7180_write_reg(ADV7180_INPUT_CTL, 0x09);
+       }
+
+       /* Datasheet recommends */
+       adv7180_write_reg(0x01, 0xc8);
+       adv7180_write_reg(0x02, 0x04);
+       adv7180_write_reg(0x03, 0x00);
+       adv7180_write_reg(0x04, 0x45);
+       adv7180_write_reg(0x05, 0x00);
+       adv7180_write_reg(0x06, 0x02);
+       adv7180_write_reg(0x07, 0x7F);
+       adv7180_write_reg(0x08, 0x80);
+       adv7180_write_reg(0x0A, 0x00);
+       adv7180_write_reg(0x0B, 0x00);
+       adv7180_write_reg(0x0C, 0x36);
+       adv7180_write_reg(0x0D, 0x7C);
+       adv7180_write_reg(0x0E, 0x00);
+       adv7180_write_reg(0x0F, 0x00);
+       adv7180_write_reg(0x13, 0x00);
+       adv7180_write_reg(0x14, 0x12);
+       adv7180_write_reg(0x15, 0x00);
+       adv7180_write_reg(0x16, 0x00);
+       adv7180_write_reg(0x17, 0x01);
+       adv7180_write_reg(0x18, 0x93);
+       adv7180_write_reg(0xF1, 0x19);
+       adv7180_write_reg(0x1A, 0x00);
+       adv7180_write_reg(0x1B, 0x00);
+       adv7180_write_reg(0x1C, 0x00);
+       adv7180_write_reg(0x1D, 0x40);
+       adv7180_write_reg(0x1E, 0x00);
+       adv7180_write_reg(0x1F, 0x00);
+       adv7180_write_reg(0x20, 0x00);
+       adv7180_write_reg(0x21, 0x00);
+       adv7180_write_reg(0x22, 0x00);
+       adv7180_write_reg(0x23, 0xC0);
+       adv7180_write_reg(0x24, 0x00);
+       adv7180_write_reg(0x25, 0x00);
+       adv7180_write_reg(0x26, 0x00);
+       adv7180_write_reg(0x27, 0x58);
+       adv7180_write_reg(0x28, 0x00);
+       adv7180_write_reg(0x29, 0x00);
+       adv7180_write_reg(0x2A, 0x00);
+       adv7180_write_reg(0x2B, 0xE1);
+       adv7180_write_reg(0x2C, 0xAE);
+       adv7180_write_reg(0x2D, 0xF4);
+       adv7180_write_reg(0x2E, 0x00);
+       adv7180_write_reg(0x2F, 0xF0);
+       adv7180_write_reg(0x30, 0x00);
+       adv7180_write_reg(0x31, 0x12);
+       adv7180_write_reg(0x32, 0x41);
+       adv7180_write_reg(0x33, 0x84);
+       adv7180_write_reg(0x34, 0x00);
+       adv7180_write_reg(0x35, 0x02);
+       adv7180_write_reg(0x36, 0x00);
+       adv7180_write_reg(0x37, 0x01);
+       adv7180_write_reg(0x38, 0x80);
+       adv7180_write_reg(0x39, 0xC0);
+       adv7180_write_reg(0x3A, 0x10);
+       adv7180_write_reg(0x3B, 0x05);
+       adv7180_write_reg(0x3C, 0x58);
+       adv7180_write_reg(0x3D, 0xB2);
+       adv7180_write_reg(0x3E, 0x64);
+       adv7180_write_reg(0x3F, 0xE4);
+       adv7180_write_reg(0x40, 0x90);
+       adv7180_write_reg(0x41, 0x01);
+       adv7180_write_reg(0x42, 0x7E);
+       adv7180_write_reg(0x43, 0xA4);
+       adv7180_write_reg(0x44, 0xFF);
+       adv7180_write_reg(0x45, 0xB6);
+       adv7180_write_reg(0x46, 0x12);
+       adv7180_write_reg(0x48, 0x00);
+       adv7180_write_reg(0x49, 0x00);
+       adv7180_write_reg(0x4A, 0x00);
+       adv7180_write_reg(0x4B, 0x00);
+       adv7180_write_reg(0x4C, 0x00);
+       adv7180_write_reg(0x4D, 0xEF);
+       adv7180_write_reg(0x4E, 0x08);
+       adv7180_write_reg(0x4F, 0x08);
+       adv7180_write_reg(0x50, 0x08);
+       adv7180_write_reg(0x51, 0x24);
+       adv7180_write_reg(0x52, 0x0B);
+       adv7180_write_reg(0x53, 0x4E);
+       adv7180_write_reg(0x54, 0x80);
+       adv7180_write_reg(0x55, 0x00);
+       adv7180_write_reg(0x56, 0x10);
+       adv7180_write_reg(0x57, 0x00);
+       adv7180_write_reg(0x58, 0x00);
+       adv7180_write_reg(0x59, 0x00);
+       adv7180_write_reg(0x5A, 0x00);
+       adv7180_write_reg(0x5B, 0x00);
+       adv7180_write_reg(0x5C, 0x00);
+       adv7180_write_reg(0x5D, 0x00);
+       adv7180_write_reg(0x5E, 0x00);
+       adv7180_write_reg(0x5F, 0x00);
+       adv7180_write_reg(0x60, 0x00);
+       adv7180_write_reg(0x61, 0x00);
+       adv7180_write_reg(0x62, 0x20);
+       adv7180_write_reg(0x63, 0x00);
+       adv7180_write_reg(0x64, 0x00);
+       adv7180_write_reg(0x65, 0x00);
+       adv7180_write_reg(0x66, 0x00);
+       adv7180_write_reg(0x67, 0x03);
+       adv7180_write_reg(0x68, 0x01);
+       adv7180_write_reg(0x69, 0x00);
+       adv7180_write_reg(0x6A, 0x00);
+       adv7180_write_reg(0x6B, 0xC0);
+       adv7180_write_reg(0x6C, 0x00);
+       adv7180_write_reg(0x6D, 0x00);
+       adv7180_write_reg(0x6E, 0x00);
+       adv7180_write_reg(0x6F, 0x00);
+       adv7180_write_reg(0x70, 0x00);
+       adv7180_write_reg(0x71, 0x00);
+       adv7180_write_reg(0x72, 0x00);
+       adv7180_write_reg(0x73, 0x10);
+       adv7180_write_reg(0x74, 0x04);
+       adv7180_write_reg(0x75, 0x01);
+       adv7180_write_reg(0x76, 0x00);
+       adv7180_write_reg(0x77, 0x3F);
+       adv7180_write_reg(0x78, 0xFF);
+       adv7180_write_reg(0x79, 0xFF);
+       adv7180_write_reg(0x7A, 0xFF);
+       adv7180_write_reg(0x7B, 0x1E);
+       adv7180_write_reg(0x7C, 0xC0);
+       adv7180_write_reg(0x7D, 0x00);
+       adv7180_write_reg(0x7E, 0x00);
+       adv7180_write_reg(0x7F, 0x00);
+       adv7180_write_reg(0x80, 0x00);
+       adv7180_write_reg(0x81, 0xC0);
+       adv7180_write_reg(0x82, 0x04);
+       adv7180_write_reg(0x83, 0x00);
+       adv7180_write_reg(0x84, 0x0C);
+       adv7180_write_reg(0x85, 0x02);
+       adv7180_write_reg(0x86, 0x03);
+       adv7180_write_reg(0x87, 0x63);
+       adv7180_write_reg(0x88, 0x5A);
+       adv7180_write_reg(0x89, 0x08);
+       adv7180_write_reg(0x8A, 0x10);
+       adv7180_write_reg(0x8B, 0x00);
+       adv7180_write_reg(0x8C, 0x40);
+       adv7180_write_reg(0x8D, 0x00);
+       adv7180_write_reg(0x8E, 0x40);
+       adv7180_write_reg(0x8F, 0x00);
+       adv7180_write_reg(0x90, 0x00);
+       adv7180_write_reg(0x91, 0x50);
+       adv7180_write_reg(0x92, 0x00);
+       adv7180_write_reg(0x93, 0x00);
+       adv7180_write_reg(0x94, 0x00);
+       adv7180_write_reg(0x95, 0x00);
+       adv7180_write_reg(0x96, 0x00);
+       adv7180_write_reg(0x97, 0xF0);
+       adv7180_write_reg(0x98, 0x00);
+       adv7180_write_reg(0x99, 0x00);
+       adv7180_write_reg(0x9A, 0x00);
+       adv7180_write_reg(0x9B, 0x00);
+       adv7180_write_reg(0x9C, 0x00);
+       adv7180_write_reg(0x9D, 0x00);
+       adv7180_write_reg(0x9E, 0x00);
+       adv7180_write_reg(0x9F, 0x00);
+       adv7180_write_reg(0xA0, 0x00);
+       adv7180_write_reg(0xA1, 0x00);
+       adv7180_write_reg(0xA2, 0x00);
+       adv7180_write_reg(0xA3, 0x00);
+       adv7180_write_reg(0xA4, 0x00);
+       adv7180_write_reg(0xA5, 0x00);
+       adv7180_write_reg(0xA6, 0x00);
+       adv7180_write_reg(0xA7, 0x00);
+       adv7180_write_reg(0xA8, 0x00);
+       adv7180_write_reg(0xA9, 0x00);
+       adv7180_write_reg(0xAA, 0x00);
+       adv7180_write_reg(0xAB, 0x00);
+       adv7180_write_reg(0xAC, 0x00);
+       adv7180_write_reg(0xAD, 0x00);
+       adv7180_write_reg(0xAE, 0x60);
+       adv7180_write_reg(0xAF, 0x00);
+       adv7180_write_reg(0xB0, 0x00);
+       adv7180_write_reg(0xB1, 0x60);
+       adv7180_write_reg(0xB2, 0x1C);
+       adv7180_write_reg(0xB3, 0x54);
+       adv7180_write_reg(0xB4, 0x00);
+       adv7180_write_reg(0xB5, 0x00);
+       adv7180_write_reg(0xB6, 0x00);
+       adv7180_write_reg(0xB7, 0x13);
+       adv7180_write_reg(0xB8, 0x03);
+       adv7180_write_reg(0xB9, 0x33);
+       adv7180_write_reg(0xBF, 0x02);
+       adv7180_write_reg(0xC0, 0x00);
+       adv7180_write_reg(0xC1, 0x00);
+       adv7180_write_reg(0xC2, 0x00);
+       adv7180_write_reg(0xC3, 0x00);
+       adv7180_write_reg(0xC4, 0x00);
+       adv7180_write_reg(0xC5, 0x81);
+       adv7180_write_reg(0xC6, 0x00);
+       adv7180_write_reg(0xC7, 0x00);
+       adv7180_write_reg(0xC8, 0x00);
+       adv7180_write_reg(0xC9, 0x04);
+       adv7180_write_reg(0xCC, 0x69);
+       adv7180_write_reg(0xCD, 0x00);
+       adv7180_write_reg(0xCE, 0x01);
+       adv7180_write_reg(0xCF, 0xB4);
+       adv7180_write_reg(0xD0, 0x00);
+       adv7180_write_reg(0xD1, 0x10);
+       adv7180_write_reg(0xD2, 0xFF);
+       adv7180_write_reg(0xD3, 0xFF);
+       adv7180_write_reg(0xD4, 0x7F);
+       adv7180_write_reg(0xD5, 0x7F);
+       adv7180_write_reg(0xD6, 0x3E);
+       adv7180_write_reg(0xD7, 0x08);
+       adv7180_write_reg(0xD8, 0x3C);
+       adv7180_write_reg(0xD9, 0x08);
+       adv7180_write_reg(0xDA, 0x3C);
+       adv7180_write_reg(0xDB, 0x9B);
+       adv7180_write_reg(0xDC, 0xAC);
+       adv7180_write_reg(0xDD, 0x4C);
+       adv7180_write_reg(0xDE, 0x00);
+       adv7180_write_reg(0xDF, 0x00);
+       adv7180_write_reg(0xE0, 0x14);
+       adv7180_write_reg(0xE1, 0x80);
+       adv7180_write_reg(0xE2, 0x80);
+       adv7180_write_reg(0xE3, 0x80);
+       adv7180_write_reg(0xE4, 0x80);
+       adv7180_write_reg(0xE5, 0x25);
+       adv7180_write_reg(0xE6, 0x44);
+       adv7180_write_reg(0xE7, 0x63);
+       adv7180_write_reg(0xE8, 0x65);
+       adv7180_write_reg(0xE9, 0x14);
+       adv7180_write_reg(0xEA, 0x63);
+       adv7180_write_reg(0xEB, 0x55);
+       adv7180_write_reg(0xEC, 0x55);
+       adv7180_write_reg(0xEE, 0x00);
+       adv7180_write_reg(0xEF, 0x4A);
+       adv7180_write_reg(0xF0, 0x44);
+       adv7180_write_reg(0xF1, 0x0C);
+       adv7180_write_reg(0xF2, 0x32);
+       adv7180_write_reg(0xF3, 0x00);
+       adv7180_write_reg(0xF4, 0x3F);
+       adv7180_write_reg(0xF5, 0xE0);
+       adv7180_write_reg(0xF6, 0x69);
+       adv7180_write_reg(0xF7, 0x10);
+       adv7180_write_reg(0xF8, 0x00);
+       adv7180_write_reg(0xF9, 0x03);
+       adv7180_write_reg(0xFA, 0xFA);
+       adv7180_write_reg(0xFB, 0x40);
+}
+
+/*! ADV7180 I2C attach function.
+ *
+ *  @param *adapter    struct i2c_adapter *.
+ *
+ *  @return            Error code indicating success or failure.
+ */
+
+/*!
+ * ADV7180 I2C probe function.
+ * Function set in i2c_driver struct.
+ * Called by insmod.
+ *
+ *  @param *adapter    I2C adapter descriptor.
+ *
+ *  @return            Error code indicating success or failure.
+ */
+static int adv7180_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       int rev_id;
+       int ret = 0;
+       u32 cvbs = true;
+       struct pinctrl *pinctrl;
+       struct device *dev = &client->dev;
+
+       printk(KERN_ERR"DBG sensor data is at %p\n", &adv7180_data);
+
+       /* 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;
+       }
+       ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "adv7180_pwdn");
+       if (ret < 0) {
+               dev_err(dev, "no power pin available!\n");
+               return ret;
+       }
+
+       adv7180_regulator_enable(dev);
+
+       adv7180_power_down(0);
+
+       msleep(1);
+
+       /* Set initial values for the sensor struct. */
+       memset(&adv7180_data, 0, sizeof(adv7180_data));
+       adv7180_data.sen.i2c_client = client;
+       adv7180_data.sen.streamcap.timeperframe.denominator = 30;
+       adv7180_data.sen.streamcap.timeperframe.numerator = 1;
+       adv7180_data.std_id = V4L2_STD_ALL;
+       video_idx = ADV7180_NOT_LOCKED;
+       adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width;
+       adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height;
+       adv7180_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY;  /* YUV422 */
+       adv7180_data.sen.pix.priv = 1;  /* 1 is used to indicate TV in */
+       adv7180_data.sen.on = true;
+
+       adv7180_data.sen.sensor_clk = devm_clk_get(dev, "csi_mclk");
+       if (IS_ERR(adv7180_data.sen.sensor_clk)) {
+               dev_err(dev, "get mclk failed\n");
+               return PTR_ERR(adv7180_data.sen.sensor_clk);
+       }
+
+       ret = of_property_read_u32(dev->of_node, "mclk",
+                                       &adv7180_data.sen.mclk);
+       if (ret) {
+               dev_err(dev, "mclk frequency is invalid\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(
+               dev->of_node, "mclk_source",
+               (u32 *) &(adv7180_data.sen.mclk_source));
+       if (ret) {
+               dev_err(dev, "mclk_source invalid\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(dev->of_node, "csi_id",
+                                       &(adv7180_data.sen.csi));
+       if (ret) {
+               dev_err(dev, "csi_id invalid\n");
+               return ret;
+       }
+
+       clk_prepare_enable(adv7180_data.sen.sensor_clk);
+
+       dev_dbg(&adv7180_data.sen.i2c_client->dev,
+               "%s:adv7180 probe i2c address is 0x%02X\n",
+               __func__, adv7180_data.sen.i2c_client->addr);
+
+       /*! Read the revision ID of the tvin chip */
+       rev_id = adv7180_read(ADV7180_IDENT);
+       dev_dbg(dev,
+               "%s:Analog Device adv7%2X0 detected!\n", __func__,
+               rev_id);
+
+       ret = of_property_read_u32(dev->of_node, "cvbs", &(cvbs));
+       if (ret) {
+               dev_err(dev, "cvbs setting is not found\n");
+               cvbs = true;
+       }
+
+       /*! ADV7180 initialization. */
+       adv7180_hard_reset(cvbs);
+
+       pr_debug("   type is %d (expect %d)\n",
+                adv7180_int_device.type, v4l2_int_type_slave);
+       pr_debug("   num ioctls is %d\n",
+                adv7180_int_device.u.slave->num_ioctls);
+
+       /* This function attaches this structure to the /dev/video0 device.
+        * The pointer in priv points to the adv7180_data structure here.*/
+       adv7180_int_device.priv = &adv7180_data;
+       ret = v4l2_int_device_register(&adv7180_int_device);
+
+       clk_disable_unprepare(adv7180_data.sen.sensor_clk);
+
+       return ret;
+}
+
+/*!
+ * ADV7180 I2C detach function.
+ * Called on rmmod.
+ *
+ *  @param *client     struct i2c_client*.
+ *
+ *  @return            Error code indicating success or failure.
+ */
+static int adv7180_detach(struct i2c_client *client)
+{
+       dev_dbg(&adv7180_data.sen.i2c_client->dev,
+               "%s:Removing %s video decoder @ 0x%02X from adapter %s\n",
+               __func__, IF_NAME, client->addr << 1, client->adapter->name);
+
+       /* Power down via i2c */
+       adv7180_write_reg(ADV7180_PWR_MNG, 0x24);
+
+       if (dvddio_regulator)
+               regulator_disable(dvddio_regulator);
+
+       if (dvdd_regulator)
+               regulator_disable(dvdd_regulator);
+
+       if (avdd_regulator)
+               regulator_disable(avdd_regulator);
+
+       if (pvdd_regulator)
+               regulator_disable(pvdd_regulator);
+
+       v4l2_int_device_unregister(&adv7180_int_device);
+
+       return 0;
+}
+
+/*!
+ * ADV7180 init function.
+ * Called on insmod.
+ *
+ * @return    Error code indicating success or failure.
+ */
+static __init int adv7180_init(void)
+{
+       u8 err = 0;
+
+       pr_debug("In adv7180_init\n");
+
+       /* Tells the i2c driver what functions to call for this driver. */
+       err = i2c_add_driver(&adv7180_i2c_driver);
+       if (err != 0)
+               pr_err("%s:driver registration failed, error=%d\n",
+                       __func__, err);
+
+       return err;
+}
+
+/*!
+ * ADV7180 cleanup function.
+ * Called on rmmod.
+ *
+ * @return   Error code indicating success or failure.
+ */
+static void __exit adv7180_clean(void)
+{
+       dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_clean\n");
+       i2c_del_driver(&adv7180_i2c_driver);
+}
+
+module_init(adv7180_init);
+module_exit(adv7180_clean);
+
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("Anolog Device ADV7180 video decoder driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c b/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c
new file mode 100644 (file)
index 0000000..193cbd5
--- /dev/null
@@ -0,0 +1,552 @@
+
+/*
+ * Copyright 2004-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
+ */
+
+/*!
+ * @file ipu_bg_overlay_sdc_bg.c
+ *
+ * @brief IPU Use case for PRP-VF back-ground
+ *
+ * @ingroup IPU
+ */
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/ipu.h>
+#include <linux/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+static int csi_buffer_num;
+static u32 bpp, csi_mem_bufsize = 3;
+static u32 out_format;
+static struct ipu_soc *disp_ipu;
+static u32 offset;
+
+static void csi_buf_work_func(struct work_struct *work)
+{
+       int err = 0;
+       cam_data *cam =
+               container_of(work, struct _cam_data, csi_work_struct);
+
+       struct ipu_task task;
+       memset(&task, 0, sizeof(task));
+
+       if (csi_buffer_num)
+               task.input.paddr = cam->vf_bufs[0];
+       else
+               task.input.paddr = cam->vf_bufs[1];
+       task.input.width = cam->crop_current.width;
+       task.input.height = cam->crop_current.height;
+       task.input.format = IPU_PIX_FMT_UYVY;
+
+       task.output.paddr = offset;
+       task.output.width = cam->overlay_fb->var.xres;
+       task.output.height = cam->overlay_fb->var.yres;
+       task.output.format = out_format;
+       task.output.rotate = cam->rotation;
+       task.output.crop.pos.x = cam->win.w.left;
+       task.output.crop.pos.y = cam->win.w.top;
+       if (cam->win.w.width > 1024 || cam->win.w.height > 1024) {
+               task.output.crop.w = cam->overlay_fb->var.xres;
+               task.output.crop.h = cam->overlay_fb->var.yres;
+       } else {
+               task.output.crop.w = cam->win.w.width;
+               task.output.crop.h = cam->win.w.height;
+       }
+again:
+       err = ipu_check_task(&task);
+       if (err != IPU_CHECK_OK) {
+               if (err > IPU_CHECK_ERR_MIN) {
+                       if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) {
+                               task.input.crop.w -= 8;
+                               goto again;
+                       }
+                       if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) {
+                               task.input.crop.h -= 8;
+                               goto again;
+                       }
+                       if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) {
+                                       task.output.width -= 8;
+                                       task.output.crop.w = task.output.width;
+                               goto again;
+                       }
+                       if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) {
+                                       task.output.height -= 8;
+                                       task.output.crop.h = task.output.height;
+                               goto again;
+                       }
+                       printk(KERN_ERR "check ipu taks fail\n");
+                       return;
+               }
+               printk(KERN_ERR "check ipu taks fail\n");
+               return;
+       }
+       err = ipu_queue_task(&task);
+       if (err < 0)
+               printk(KERN_ERR "queue ipu task error\n");
+}
+
+static void get_disp_ipu(cam_data *cam)
+{
+       if (cam->output > 2)
+               disp_ipu = ipu_get_soc(1); /* using DISP4 */
+       else
+               disp_ipu = ipu_get_soc(0);
+}
+
+
+/*!
+ * csi ENC callback function.
+ *
+ * @param irq       int irq line
+ * @param dev_id    void * device id
+ *
+ * @return status   IRQ_HANDLED for handled
+ */
+static irqreturn_t csi_enc_callback(int irq, void *dev_id)
+{
+       cam_data *cam = (cam_data *) dev_id;
+       ipu_channel_t chan = (irq == IPU_IRQ_CSI0_OUT_EOF) ?
+               CSI_MEM0 : CSI_MEM1;
+
+       ipu_select_buffer(cam->ipu, chan,
+                       IPU_OUTPUT_BUFFER, csi_buffer_num);
+       schedule_work(&cam->csi_work_struct);
+       csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0;
+       return IRQ_HANDLED;
+}
+
+static int csi_enc_setup(cam_data *cam)
+{
+       ipu_channel_params_t params;
+       u32 pixel_fmt;
+       int err = 0, sensor_protocol = 0;
+       ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       if (!cam) {
+               printk(KERN_ERR "cam private is NULL\n");
+               return -ENXIO;
+       }
+
+       memset(&params, 0, sizeof(ipu_channel_params_t));
+       params.csi_mem.csi = cam->csi;
+
+       sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
+       switch (sensor_protocol) {
+       case IPU_CSI_CLK_MODE_GATED_CLK:
+       case IPU_CSI_CLK_MODE_NONGATED_CLK:
+       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
+       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
+       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
+               params.csi_mem.interlaced = false;
+               break;
+       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
+       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
+       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
+               params.csi_mem.interlaced = true;
+               break;
+       default:
+               printk(KERN_ERR "sensor protocol unsupported\n");
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id) {
+                               params.csi_mem.mipi_en = true;
+                               params.csi_mem.mipi_vc =
+                               mipi_csi2_get_virtual_channel(mipi_csi2_info);
+                               params.csi_mem.mipi_id =
+                               mipi_csi2_get_datatype(mipi_csi2_info);
+
+                               mipi_csi2_pixelclk_enable(mipi_csi2_info);
+                       } else {
+                               params.csi_mem.mipi_en = false;
+                               params.csi_mem.mipi_vc = 0;
+                               params.csi_mem.mipi_id = 0;
+                       }
+               } else {
+                       params.csi_mem.mipi_en = false;
+                       params.csi_mem.mipi_vc = 0;
+                       params.csi_mem.mipi_id = 0;
+               }
+       }
+#endif
+
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0],
+                                 (dma_addr_t) cam->vf_bufs[0]);
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1],
+                                 (dma_addr_t) cam->vf_bufs[1]);
+       }
+       csi_mem_bufsize =
+               cam->crop_current.width * cam->crop_current.height * 2;
+       cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize);
+       cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
+                                                          cam->vf_bufs_size[0],
+                                                          (dma_addr_t *) &
+                                                          cam->vf_bufs[0],
+                                                          GFP_DMA |
+                                                          GFP_KERNEL);
+       if (cam->vf_bufs_vaddr[0] == NULL) {
+               printk(KERN_ERR "Error to allocate vf buffer\n");
+               err = -ENOMEM;
+               goto out_2;
+       }
+       cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize);
+       cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
+                                                          cam->vf_bufs_size[1],
+                                                          (dma_addr_t *) &
+                                                          cam->vf_bufs[1],
+                                                          GFP_DMA |
+                                                          GFP_KERNEL);
+       if (cam->vf_bufs_vaddr[1] == NULL) {
+               printk(KERN_ERR "Error to allocate vf buffer\n");
+               err = -ENOMEM;
+               goto out_1;
+       }
+       pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
+
+       err = ipu_init_channel(cam->ipu, chan, &params);
+       if (err != 0) {
+               printk(KERN_ERR "ipu_init_channel %d\n", err);
+               goto out_1;
+       }
+
+       pixel_fmt = IPU_PIX_FMT_UYVY;
+       err = ipu_init_channel_buffer(
+               cam->ipu, chan, IPU_OUTPUT_BUFFER, pixel_fmt,
+               cam->crop_current.width, cam->crop_current.height,
+               cam->crop_current.width, IPU_ROTATE_NONE,
+               cam->vf_bufs[0], cam->vf_bufs[1], 0,
+               cam->offset.u_offset, cam->offset.u_offset);
+       if (err != 0) {
+               printk(KERN_ERR "CSI_MEM output buffer\n");
+               goto out_1;
+       }
+       err = ipu_enable_channel(cam->ipu, chan);
+       if (err < 0) {
+               printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
+               goto out_1;
+       }
+
+       csi_buffer_num = 0;
+
+       ipu_select_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER, 0);
+       ipu_select_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER, 1);
+       return err;
+out_1:
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0],
+                                 (dma_addr_t) cam->vf_bufs[0]);
+               cam->vf_bufs_vaddr[0] = NULL;
+               cam->vf_bufs[0] = 0;
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1],
+                                 (dma_addr_t) cam->vf_bufs[1]);
+               cam->vf_bufs_vaddr[1] = NULL;
+               cam->vf_bufs[1] = 0;
+       }
+out_2:
+       return err;
+}
+
+/*!
+ * Enable encoder task
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int csi_enc_enabling_tasks(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+
+       ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi);
+       err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi,
+                       csi_enc_callback, 0, "Mxc Camera", cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error registering CSI_OUT_EOF irq\n");
+               return err;
+       }
+
+       INIT_WORK(&cam->csi_work_struct, csi_buf_work_func);
+
+       err = csi_enc_setup(cam);
+       if (err != 0) {
+               printk(KERN_ERR "csi_enc_setup %d\n", err);
+               goto out1;
+       }
+
+       return err;
+out1:
+       ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);
+       return err;
+}
+
+/*!
+ * bg_overlay_start - start the overlay task
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ */
+static int bg_overlay_start(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+
+       if (!cam) {
+               printk(KERN_ERR "private is NULL\n");
+               return -EIO;
+       }
+
+       if (cam->overlay_active == true) {
+               pr_debug("already start.\n");
+               return 0;
+       }
+
+       get_disp_ipu(cam);
+
+       out_format = cam->v4l2_fb.fmt.pixelformat;
+       if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) {
+               bpp = 3, csi_mem_bufsize = 3;
+               pr_info("BGR24\n");
+       } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) {
+               bpp = 2, csi_mem_bufsize = 2;
+               pr_info("RGB565\n");
+       } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) {
+               bpp = 4, csi_mem_bufsize = 4;
+               pr_info("BGR32\n");
+       } else {
+               printk(KERN_ERR
+                      "unsupported fix format from the framebuffer.\n");
+               return -EINVAL;
+       }
+
+       offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top +
+           csi_mem_bufsize * cam->win.w.left;
+
+       if (cam->v4l2_fb.base == 0)
+               printk(KERN_ERR "invalid frame buffer address.\n");
+       else
+               offset += (u32) cam->v4l2_fb.base;
+
+       csi_mem_bufsize = cam->win.w.width * cam->win.w.height
+                               * csi_mem_bufsize;
+
+       err = csi_enc_enabling_tasks(cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error csi enc enable fail\n");
+               return err;
+       }
+
+       cam->overlay_active = true;
+       return err;
+}
+
+/*!
+ * bg_overlay_stop - stop the overlay task
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ */
+static int bg_overlay_stop(void *private)
+{
+       int err = 0;
+       cam_data *cam = (cam_data *) private;
+       ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       if (cam->overlay_active == false)
+               return 0;
+
+       err = ipu_disable_channel(cam->ipu, chan, true);
+
+       ipu_uninit_channel(cam->ipu, chan);
+
+       csi_buffer_num = 0;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id)
+                               mipi_csi2_pixelclk_disable(mipi_csi2_info);
+               }
+       }
+#endif
+
+       flush_work(&cam->csi_work_struct);
+       cancel_work_sync(&cam->csi_work_struct);
+
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
+               cam->vf_bufs_vaddr[0] = NULL;
+               cam->vf_bufs[0] = 0;
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
+               cam->vf_bufs_vaddr[1] = NULL;
+               cam->vf_bufs[1] = 0;
+       }
+       if (cam->rot_vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->rot_vf_buf_size[0],
+                                 cam->rot_vf_bufs_vaddr[0],
+                                 cam->rot_vf_bufs[0]);
+               cam->rot_vf_bufs_vaddr[0] = NULL;
+               cam->rot_vf_bufs[0] = 0;
+       }
+       if (cam->rot_vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->rot_vf_buf_size[1],
+                                 cam->rot_vf_bufs_vaddr[1],
+                                 cam->rot_vf_bufs[1]);
+               cam->rot_vf_bufs_vaddr[1] = NULL;
+               cam->rot_vf_bufs[1] = 0;
+       }
+
+       cam->overlay_active = false;
+       return err;
+}
+
+/*!
+ * Enable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int bg_overlay_enable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int bg_overlay_disable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       /* free csi eof irq firstly.
+        * when disable csi, wait for idmac eof.
+        * it requests eof irq again */
+       ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);
+
+       return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select bg as the working path
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ * @return  status
+ */
+int bg_overlay_sdc_select(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       if (cam) {
+               cam->vf_start_sdc = bg_overlay_start;
+               cam->vf_stop_sdc = bg_overlay_stop;
+               cam->vf_enable_csi = bg_overlay_enable_csi;
+               cam->vf_disable_csi = bg_overlay_disable_csi;
+               cam->overlay_active = false;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(bg_overlay_sdc_select);
+
+/*!
+ * function to de-select bg as the working path
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ * @return  status
+ */
+int bg_overlay_sdc_deselect(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       if (cam) {
+               cam->vf_start_sdc = NULL;
+               cam->vf_stop_sdc = NULL;
+               cam->vf_enable_csi = NULL;
+               cam->vf_disable_csi = NULL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(bg_overlay_sdc_deselect);
+
+/*!
+ * Init background overlay task.
+ *
+ * @return  Error code indicating success or failure
+ */
+__init int bg_overlay_sdc_init(void)
+{
+       return 0;
+}
+
+/*!
+ * Deinit background overlay task.
+ *
+ * @return  Error code indicating success or failure
+ */
+void __exit bg_overlay_sdc_exit(void)
+{
+}
+
+module_init(bg_overlay_sdc_init);
+module_exit(bg_overlay_sdc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_csi_enc.c b/drivers/media/platform/mxc/capture/ipu_csi_enc.c
new file mode 100644 (file)
index 0000000..3a824a9
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2009-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
+ */
+
+/*!
+ * @file ipu_csi_enc.c
+ *
+ * @brief CSI Use case for video capture
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/ipu.h>
+#include <linux/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+#ifdef CAMERA_DBG
+       #define CAMERA_TRACE(x) (printk)x
+#else
+       #define CAMERA_TRACE(x)
+#endif
+
+/*
+ * Function definitions
+ */
+
+/*!
+ * csi ENC callback function.
+ *
+ * @param irq       int irq line
+ * @param dev_id    void * device id
+ *
+ * @return status   IRQ_HANDLED for handled
+ */
+static irqreturn_t csi_enc_callback(int irq, void *dev_id)
+{
+       cam_data *cam = (cam_data *) dev_id;
+
+       if (cam->enc_callback == NULL)
+               return IRQ_HANDLED;
+
+       cam->enc_callback(irq, dev_id);
+       return IRQ_HANDLED;
+}
+
+/*!
+ * CSI ENC enable channel setup function
+ *
+ * @param cam       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int csi_enc_setup(cam_data *cam)
+{
+       ipu_channel_params_t params;
+       u32 pixel_fmt;
+       int err = 0, sensor_protocol = 0;
+       dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
+       ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       CAMERA_TRACE("In csi_enc_setup\n");
+       if (!cam) {
+               printk(KERN_ERR "cam private is NULL\n");
+               return -ENXIO;
+       }
+
+       memset(&params, 0, sizeof(ipu_channel_params_t));
+       params.csi_mem.csi = cam->csi;
+
+       sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
+       switch (sensor_protocol) {
+       case IPU_CSI_CLK_MODE_GATED_CLK:
+       case IPU_CSI_CLK_MODE_NONGATED_CLK:
+       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
+       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
+       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
+               params.csi_mem.interlaced = false;
+               break;
+       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
+       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
+       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
+               params.csi_mem.interlaced = true;
+               break;
+       default:
+               printk(KERN_ERR "sensor protocol unsupported\n");
+               return -EINVAL;
+       }
+
+       if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
+               pixel_fmt = IPU_PIX_FMT_YUV420P;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420)
+               pixel_fmt = IPU_PIX_FMT_YVU420P;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
+               pixel_fmt = IPU_PIX_FMT_YUV422P;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
+               pixel_fmt = IPU_PIX_FMT_UYVY;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+               pixel_fmt = IPU_PIX_FMT_YUYV;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
+               pixel_fmt = IPU_PIX_FMT_NV12;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
+               pixel_fmt = IPU_PIX_FMT_BGR24;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
+               pixel_fmt = IPU_PIX_FMT_RGB24;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
+               pixel_fmt = IPU_PIX_FMT_RGB565;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
+               pixel_fmt = IPU_PIX_FMT_BGR32;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
+               pixel_fmt = IPU_PIX_FMT_RGB32;
+       else {
+               printk(KERN_ERR "format not supported\n");
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id) {
+                               params.csi_mem.mipi_en = true;
+                               params.csi_mem.mipi_vc =
+                               mipi_csi2_get_virtual_channel(mipi_csi2_info);
+                               params.csi_mem.mipi_id =
+                               mipi_csi2_get_datatype(mipi_csi2_info);
+
+                               mipi_csi2_pixelclk_enable(mipi_csi2_info);
+                       } else {
+                               params.csi_mem.mipi_en = false;
+                               params.csi_mem.mipi_vc = 0;
+                               params.csi_mem.mipi_id = 0;
+                       }
+               } else {
+                       params.csi_mem.mipi_en = false;
+                       params.csi_mem.mipi_vc = 0;
+                       params.csi_mem.mipi_id = 0;
+               }
+       }
+#endif
+
+       err = ipu_init_channel(cam->ipu, chan, &params);
+       if (err != 0) {
+               printk(KERN_ERR "ipu_init_channel %d\n", err);
+               return err;
+       }
+
+       err = ipu_init_channel_buffer(cam->ipu,
+                                     chan,
+                                     IPU_OUTPUT_BUFFER,
+                                     pixel_fmt, cam->v2f.fmt.pix.width,
+                                     cam->v2f.fmt.pix.height,
+                                     cam->v2f.fmt.pix.bytesperline,
+                                     IPU_ROTATE_NONE,
+                                     dummy, dummy, 0,
+                                     cam->offset.u_offset,
+                                     cam->offset.v_offset);
+       if (err != 0) {
+               printk(KERN_ERR "CSI_MEM output buffer\n");
+               return err;
+       }
+       err = ipu_enable_channel(cam->ipu, chan);
+       if (err < 0) {
+               printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
+               return err;
+       }
+
+       return err;
+}
+
+/*!
+ * function to update physical buffer address for encorder IDMA channel
+ *
+ * @param *private    pointer to the cam_data structure
+ * @param eba         physical buffer address for encorder IDMA channel
+ *
+ * @return  status
+ */
+static int csi_enc_eba_update(void *private, dma_addr_t eba)
+{
+       int err = 0;
+       cam_data *cam = (cam_data *) private;
+       struct ipu_soc *ipu = cam->ipu;
+       int *buffer_num = &cam->ping_pong_csi;
+       ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+
+       pr_debug("eba %x\n", eba);
+       err = ipu_update_channel_buffer(ipu, chan, IPU_OUTPUT_BUFFER,
+                                       *buffer_num, eba);
+       if (err != 0) {
+               ipu_clear_buffer_ready(ipu, chan, IPU_OUTPUT_BUFFER,
+                                      *buffer_num);
+
+               err = ipu_update_channel_buffer(ipu, chan,
+                               IPU_OUTPUT_BUFFER, *buffer_num, eba);
+               if (err != 0) {
+                       pr_err("ERROR: v4l2 capture: fail to update "
+                              "buf%d\n", *buffer_num);
+                       return err;
+               }
+       }
+
+       ipu_select_buffer(ipu, chan, IPU_OUTPUT_BUFFER, *buffer_num);
+
+       *buffer_num = (*buffer_num == 0) ? 1 : 0;
+
+       return 0;
+}
+
+/*!
+ * Enable encoder task
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int csi_enc_enabling_tasks(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+       uint32_t irq = (cam->csi == 0) ?
+               IPU_IRQ_CSI0_OUT_EOF : IPU_IRQ_CSI1_OUT_EOF;
+
+       CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");
+
+       cam->dummy_frame.vaddress = dma_alloc_coherent(0,
+                              PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+                              &cam->dummy_frame.paddress,
+                              GFP_DMA | GFP_KERNEL);
+       if (cam->dummy_frame.vaddress == 0) {
+               pr_err("ERROR: v4l2 capture: Allocate dummy frame "
+                      "failed.\n");
+               return -ENOBUFS;
+       }
+       cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE;
+       cam->dummy_frame.buffer.length =
+           PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+       cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
+
+       ipu_clear_irq(cam->ipu, irq);
+       err = ipu_request_irq(
+               cam->ipu, irq, csi_enc_callback, 0, "Mxc Camera", cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error registering rot irq\n");
+               return err;
+       }
+
+       err = csi_enc_setup(cam);
+       if (err != 0) {
+               printk(KERN_ERR "csi_enc_setup %d\n", err);
+               return err;
+       }
+
+       return err;
+}
+
+/*!
+ * Disable encoder task
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  int
+ */
+static int csi_enc_disabling_tasks(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+       ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       err = ipu_disable_channel(cam->ipu, chan, true);
+
+       ipu_uninit_channel(cam->ipu, chan);
+
+       if (cam->dummy_frame.vaddress != 0) {
+               dma_free_coherent(0, cam->dummy_frame.buffer.length,
+                                 cam->dummy_frame.vaddress,
+                                 cam->dummy_frame.paddress);
+               cam->dummy_frame.vaddress = 0;
+       }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id)
+                               mipi_csi2_pixelclk_disable(mipi_csi2_info);
+               }
+       }
+#endif
+
+       return err;
+}
+
+/*!
+ * Enable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int csi_enc_enable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int csi_enc_disable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       uint32_t irq = (cam->csi == 0) ?
+               IPU_IRQ_CSI0_OUT_EOF : IPU_IRQ_CSI1_OUT_EOF;
+
+       /* free csi eof irq firstly.
+        * when disable csi, wait for idmac eof.
+        * it requests eof irq again */
+       ipu_free_irq(cam->ipu, irq, cam);
+
+       return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select CSI ENC as the working path
+ *
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  int
+ */
+int csi_enc_select(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+
+       if (cam) {
+               cam->enc_update_eba = csi_enc_eba_update;
+               cam->enc_enable = csi_enc_enabling_tasks;
+               cam->enc_disable = csi_enc_disabling_tasks;
+               cam->enc_enable_csi = csi_enc_enable_csi;
+               cam->enc_disable_csi = csi_enc_disable_csi;
+       } else {
+               err = -EIO;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL(csi_enc_select);
+
+/*!
+ * function to de-select CSI ENC as the working path
+ *
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  int
+ */
+int csi_enc_deselect(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+
+       if (cam) {
+               cam->enc_update_eba = NULL;
+               cam->enc_enable = NULL;
+               cam->enc_disable = NULL;
+               cam->enc_enable_csi = NULL;
+               cam->enc_disable_csi = NULL;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL(csi_enc_deselect);
+
+/*!
+ * Init the Encorder channels
+ *
+ * @return  Error code indicating success or failure
+ */
+__init int csi_enc_init(void)
+{
+       return 0;
+}
+
+/*!
+ * Deinit the Encorder channels
+ *
+ */
+void __exit csi_enc_exit(void)
+{
+}
+
+module_init(csi_enc_init);
+module_exit(csi_enc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("CSI ENC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c b/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c
new file mode 100644 (file)
index 0000000..4d6b136
--- /dev/null
@@ -0,0 +1,638 @@
+/*
+ * Copyright 2004-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
+ */
+
+/*!
+ * @file ipu_foreground_sdc.c
+ *
+ * @brief IPU Use case for PRP-VF
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/console.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/mipi_csi2.h>
+
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+#ifdef CAMERA_DBG
+       #define CAMERA_TRACE(x) (printk)x
+#else
+       #define CAMERA_TRACE(x)
+#endif
+
+static int csi_buffer_num, buffer_num;
+static u32 csi_mem_bufsize;
+static struct ipu_soc *disp_ipu;
+static struct fb_info *fbi;
+static struct fb_var_screeninfo fbvar;
+static u32 vf_out_format;
+static void csi_buf_work_func(struct work_struct *work)
+{
+       int err = 0;
+       cam_data *cam =
+               container_of(work, struct _cam_data, csi_work_struct);
+
+       struct ipu_task task;
+       memset(&task, 0, sizeof(task));
+
+       if (csi_buffer_num)
+               task.input.paddr = cam->vf_bufs[0];
+       else
+               task.input.paddr = cam->vf_bufs[1];
+       task.input.width = cam->crop_current.width;
+       task.input.height = cam->crop_current.height;
+       task.input.format = IPU_PIX_FMT_NV12;
+
+       if (buffer_num == 0)
+               task.output.paddr = fbi->fix.smem_start +
+                               (fbi->fix.line_length * fbvar.yres);
+       else
+               task.output.paddr = fbi->fix.smem_start;
+       task.output.width = cam->win.w.width;
+       task.output.height = cam->win.w.height;
+       task.output.format = vf_out_format;
+       task.output.rotate = cam->rotation;
+again:
+       err = ipu_check_task(&task);
+       if (err != IPU_CHECK_OK) {
+               if (err > IPU_CHECK_ERR_MIN) {
+                       if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) {
+                               task.input.crop.w -= 8;
+                               goto again;
+                       }
+                       if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) {
+                               task.input.crop.h -= 8;
+                               goto again;
+                       }
+                       if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) {
+                                       task.output.width -= 8;
+                                       task.output.crop.w = task.output.width;
+                               goto again;
+                       }
+                       if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) {
+                                       task.output.height -= 8;
+                                       task.output.crop.h = task.output.height;
+                               goto again;
+                       }
+                       printk(KERN_ERR "check ipu taks fail\n");
+                       return;
+               }
+               printk(KERN_ERR "check ipu taks fail\n");
+               return;
+       }
+       err = ipu_queue_task(&task);
+       if (err < 0)
+               printk(KERN_ERR "queue ipu task error\n");
+       ipu_select_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, buffer_num);
+       buffer_num = (buffer_num == 0) ? 1 : 0;
+}
+
+static void get_disp_ipu(cam_data *cam)
+{
+       if (cam->output > 2)
+               disp_ipu = ipu_get_soc(1); /* using DISP4 */
+       else
+               disp_ipu = ipu_get_soc(0);
+}
+
+/*!
+ * csi ENC callback function.
+ *
+ * @param irq       int irq line
+ * @param dev_id    void * device id
+ *
+ * @return status   IRQ_HANDLED for handled
+ */
+static irqreturn_t csi_enc_callback(int irq, void *dev_id)
+{
+       cam_data *cam = (cam_data *) dev_id;
+       ipu_channel_t chan = (irq == IPU_IRQ_CSI0_OUT_EOF) ?
+               CSI_MEM0 : CSI_MEM1;
+
+       ipu_select_buffer(cam->ipu, chan,
+                         IPU_OUTPUT_BUFFER, csi_buffer_num);
+
+       if ((cam->crop_current.width != cam->win.w.width) ||
+               (cam->crop_current.height != cam->win.w.height) ||
+               (vf_out_format != IPU_PIX_FMT_NV12) ||
+               (cam->rotation >= IPU_ROTATE_VERT_FLIP))
+               schedule_work(&cam->csi_work_struct);
+       csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0;
+       return IRQ_HANDLED;
+}
+
+static int csi_enc_setup(cam_data *cam)
+{
+       ipu_channel_params_t params;
+       int err = 0, sensor_protocol = 0;
+       ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       CAMERA_TRACE("In csi_enc_setup\n");
+       if (!cam) {
+               printk(KERN_ERR "cam private is NULL\n");
+               return -ENXIO;
+       }
+
+       memset(&params, 0, sizeof(ipu_channel_params_t));
+       params.csi_mem.csi = cam->csi;
+
+       sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
+       switch (sensor_protocol) {
+       case IPU_CSI_CLK_MODE_GATED_CLK:
+       case IPU_CSI_CLK_MODE_NONGATED_CLK:
+       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
+       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
+       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
+               params.csi_mem.interlaced = false;
+               break;
+       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
+       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
+       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
+               params.csi_mem.interlaced = true;
+               break;
+       default:
+               printk(KERN_ERR "sensor protocol unsupported\n");
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id) {
+                               params.csi_mem.mipi_en = true;
+                               params.csi_mem.mipi_vc =
+                               mipi_csi2_get_virtual_channel(mipi_csi2_info);
+                               params.csi_mem.mipi_id =
+                               mipi_csi2_get_datatype(mipi_csi2_info);
+
+                               mipi_csi2_pixelclk_enable(mipi_csi2_info);
+                       } else {
+                               params.csi_mem.mipi_en = false;
+                               params.csi_mem.mipi_vc = 0;
+                               params.csi_mem.mipi_id = 0;
+                       }
+               } else {
+                       params.csi_mem.mipi_en = false;
+                       params.csi_mem.mipi_vc = 0;
+                       params.csi_mem.mipi_id = 0;
+               }
+       }
+#endif
+
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0],
+                                 (dma_addr_t) cam->vf_bufs[0]);
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1],
+                                 (dma_addr_t) cam->vf_bufs[1]);
+       }
+       csi_mem_bufsize = cam->crop_current.width *
+                         cam->crop_current.height * 3/2;
+       cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize);
+       cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
+                                                          cam->vf_bufs_size[0],
+                                                          (dma_addr_t *) &
+                                                          cam->vf_bufs[0],
+                                                          GFP_DMA |
+                                                          GFP_KERNEL);
+       if (cam->vf_bufs_vaddr[0] == NULL) {
+               printk(KERN_ERR "Error to allocate vf buffer\n");
+               err = -ENOMEM;
+               goto out_2;
+       }
+       cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize);
+       cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
+                                                          cam->vf_bufs_size[1],
+                                                          (dma_addr_t *) &
+                                                          cam->vf_bufs[1],
+                                                          GFP_DMA |
+                                                          GFP_KERNEL);
+       if (cam->vf_bufs_vaddr[1] == NULL) {
+               printk(KERN_ERR "Error to allocate vf buffer\n");
+               err = -ENOMEM;
+               goto out_1;
+       }
+       pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
+
+       err = ipu_init_channel(cam->ipu, chan, &params);
+       if (err != 0) {
+               printk(KERN_ERR "ipu_init_channel %d\n", err);
+               goto out_1;
+       }
+
+       if ((cam->crop_current.width == cam->win.w.width) &&
+               (cam->crop_current.height == cam->win.w.height) &&
+               (vf_out_format == IPU_PIX_FMT_NV12) &&
+               (cam->rotation < IPU_ROTATE_VERT_FLIP)) {
+               err = ipu_init_channel_buffer(cam->ipu, chan,
+                               IPU_OUTPUT_BUFFER, IPU_PIX_FMT_NV12,
+                               cam->crop_current.width,
+                               cam->crop_current.height,
+                               cam->crop_current.width, IPU_ROTATE_NONE,
+                               fbi->fix.smem_start +
+                               (fbi->fix.line_length * fbvar.yres),
+                               fbi->fix.smem_start, 0,
+                               cam->offset.u_offset, cam->offset.u_offset);
+       } else {
+               err = ipu_init_channel_buffer(cam->ipu, chan,
+                               IPU_OUTPUT_BUFFER, IPU_PIX_FMT_NV12,
+                               cam->crop_current.width,
+                               cam->crop_current.height,
+                               cam->crop_current.width, IPU_ROTATE_NONE,
+                               cam->vf_bufs[0], cam->vf_bufs[1], 0,
+                               cam->offset.u_offset, cam->offset.u_offset);
+       }
+       if (err != 0) {
+               printk(KERN_ERR "CSI_MEM output buffer\n");
+               goto out_1;
+       }
+       err = ipu_enable_channel(cam->ipu, chan);
+       if (err < 0) {
+               printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
+               goto out_1;
+       }
+
+       csi_buffer_num = 0;
+
+       ipu_select_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER, 0);
+       ipu_select_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER, 1);
+       return err;
+out_1:
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0],
+                                 (dma_addr_t) cam->vf_bufs[0]);
+               cam->vf_bufs_vaddr[0] = NULL;
+               cam->vf_bufs[0] = 0;
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1],
+                                 (dma_addr_t) cam->vf_bufs[1]);
+               cam->vf_bufs_vaddr[1] = NULL;
+               cam->vf_bufs[1] = 0;
+       }
+out_2:
+       return err;
+}
+
+/*!
+ * Enable encoder task
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int csi_enc_enabling_tasks(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+       CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");
+
+       ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi);
+       err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi,
+                             csi_enc_callback, 0, "Mxc Camera", cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error registering CSI_OUT_EOF irq\n");
+               return err;
+       }
+
+       INIT_WORK(&cam->csi_work_struct, csi_buf_work_func);
+
+       err = csi_enc_setup(cam);
+       if (err != 0) {
+               printk(KERN_ERR "csi_enc_setup %d\n", err);
+               goto out1;
+       }
+
+       return err;
+out1:
+       ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);
+       return err;
+}
+
+/*
+ * Function definitions
+ */
+
+/*!
+ * foreground_start - start the vf task
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ */
+static int foreground_start(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0, i = 0, screen_size;
+       char *base;
+
+       if (!cam) {
+               printk(KERN_ERR "private is NULL\n");
+               return -EIO;
+       }
+
+       if (cam->overlay_active == true) {
+               pr_debug("already started.\n");
+               return 0;
+       }
+
+       get_disp_ipu(cam);
+
+       for (i = 0; i < num_registered_fb; i++) {
+               char *idstr = registered_fb[i]->fix.id;
+               if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+                   ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
+                       fbi = registered_fb[i];
+                       break;
+               }
+       }
+
+       if (fbi == NULL) {
+               printk(KERN_ERR "DISP FG fb not found\n");
+               return -EPERM;
+       }
+
+       fbvar = fbi->var;
+
+       /* Store the overlay frame buffer's original std */
+       cam->fb_origin_std = fbvar.nonstd;
+
+       if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
+               /* Use DP to do CSC so that we can get better performance */
+               vf_out_format = IPU_PIX_FMT_NV12;
+               fbvar.nonstd = vf_out_format;
+       } else {
+               vf_out_format = IPU_PIX_FMT_RGB565;
+               fbvar.nonstd = 0;
+       }
+
+       fbvar.bits_per_pixel = 16;
+       fbvar.xres = fbvar.xres_virtual = cam->win.w.width;
+       fbvar.yres = cam->win.w.height;
+       fbvar.yres_virtual = cam->win.w.height * 2;
+       fbvar.yoffset = 0;
+       fbvar.vmode &= ~FB_VMODE_YWRAP;
+       fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG;
+       fbvar.activate |= FB_ACTIVATE_FORCE;
+       fb_set_var(fbi, &fbvar);
+
+       ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left,
+                       cam->win.w.top);
+
+       /* Fill black color for framebuffer */
+       base = (char *) fbi->screen_base;
+       screen_size = fbi->var.xres * fbi->var.yres;
+       if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
+               memset(base, 0, screen_size);
+               base += screen_size;
+               for (i = 0; i < screen_size / 2; i++, base++)
+                       *base = 0x80;
+       } else {
+               for (i = 0; i < screen_size * 2; i++, base++)
+                       *base = 0x00;
+       }
+
+       console_lock();
+       fb_blank(fbi, FB_BLANK_UNBLANK);
+       console_unlock();
+
+       /* correct display ch buffer address */
+       ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+                               0, fbi->fix.smem_start +
+                               (fbi->fix.line_length * fbvar.yres));
+       ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+                                       1, fbi->fix.smem_start);
+
+       err = csi_enc_enabling_tasks(cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error csi enc enable fail\n");
+               return err;
+       }
+
+       cam->overlay_active = true;
+       return err;
+
+}
+
+/*!
+ * foreground_stop - stop the vf task
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ */
+static int foreground_stop(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0, i = 0;
+       struct fb_info *fbi = NULL;
+       struct fb_var_screeninfo fbvar;
+       ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       if (cam->overlay_active == false)
+               return 0;
+
+       err = ipu_disable_channel(cam->ipu, chan, true);
+
+       ipu_uninit_channel(cam->ipu, chan);
+
+       csi_buffer_num = 0;
+       buffer_num = 0;
+
+       for (i = 0; i < num_registered_fb; i++) {
+               char *idstr = registered_fb[i]->fix.id;
+               if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+                   ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
+                       fbi = registered_fb[i];
+                       break;
+               }
+       }
+
+       if (fbi == NULL) {
+               printk(KERN_ERR "DISP FG fb not found\n");
+               return -EPERM;
+       }
+
+       console_lock();
+       fb_blank(fbi, FB_BLANK_POWERDOWN);
+       console_unlock();
+
+       /* Set the overlay frame buffer std to what it is used to be */
+       fbvar = fbi->var;
+       fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG;
+       fbvar.nonstd = cam->fb_origin_std;
+       fbvar.activate |= FB_ACTIVATE_FORCE;
+       fb_set_var(fbi, &fbvar);
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id)
+                               mipi_csi2_pixelclk_disable(mipi_csi2_info);
+               }
+       }
+#endif
+
+       flush_work(&cam->csi_work_struct);
+       cancel_work_sync(&cam->csi_work_struct);
+
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0],
+                                 (dma_addr_t) cam->vf_bufs[0]);
+               cam->vf_bufs_vaddr[0] = NULL;
+               cam->vf_bufs[0] = 0;
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1],
+                                 (dma_addr_t) cam->vf_bufs[1]);
+               cam->vf_bufs_vaddr[1] = NULL;
+               cam->vf_bufs[1] = 0;
+       }
+
+       cam->overlay_active = false;
+       return err;
+}
+
+/*!
+ * Enable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int foreground_enable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int foreground_disable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       /* free csi eof irq firstly.
+        * when disable csi, wait for idmac eof.
+        * it requests eof irq again */
+       ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);
+
+       return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select foreground as the working path
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ * @return  status
+ */
+int foreground_sdc_select(void *private)
+{
+       cam_data *cam;
+       int err = 0;
+       if (private) {
+               cam = (cam_data *) private;
+               cam->vf_start_sdc = foreground_start;
+               cam->vf_stop_sdc = foreground_stop;
+               cam->vf_enable_csi = foreground_enable_csi;
+               cam->vf_disable_csi = foreground_disable_csi;
+               cam->overlay_active = false;
+       } else
+               err = -EIO;
+
+       return err;
+}
+EXPORT_SYMBOL(foreground_sdc_select);
+
+/*!
+ * function to de-select foreground as the working path
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ * @return  int
+ */
+int foreground_sdc_deselect(void *private)
+{
+       cam_data *cam;
+
+       if (private) {
+               cam = (cam_data *) private;
+               cam->vf_start_sdc = NULL;
+               cam->vf_stop_sdc = NULL;
+               cam->vf_enable_csi = NULL;
+               cam->vf_disable_csi = NULL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(foreground_sdc_deselect);
+
+/*!
+ * Init viewfinder task.
+ *
+ * @return  Error code indicating success or failure
+ */
+__init int foreground_sdc_init(void)
+{
+       return 0;
+}
+
+/*!
+ * Deinit viewfinder task.
+ *
+ * @return  Error code indicating success or failure
+ */
+void __exit foreground_sdc_exit(void)
+{
+}
+
+module_init(foreground_sdc_init);
+module_exit(foreground_sdc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP VF SDC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_enc.c b/drivers/media/platform/mxc/capture/ipu_prp_enc.c
new file mode 100644 (file)
index 0000000..1e4420b
--- /dev/null
@@ -0,0 +1,597 @@
+/*
+ * Copyright 2004-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
+ */
+
+/*!
+ * @file ipu_prp_enc.c
+ *
+ * @brief IPU Use case for PRP-ENC
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/ipu.h>
+#include <linux/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+#ifdef CAMERA_DBG
+       #define CAMERA_TRACE(x) (printk)x
+#else
+       #define CAMERA_TRACE(x)
+#endif
+
+static ipu_rotate_mode_t grotation = IPU_ROTATE_NONE;
+
+/*
+ * Function definitions
+ */
+
+/*!
+ * IPU ENC callback function.
+ *
+ * @param irq       int irq line
+ * @param dev_id    void * device id
+ *
+ * @return status   IRQ_HANDLED for handled
+ */
+static irqreturn_t prp_enc_callback(int irq, void *dev_id)
+{
+       cam_data *cam = (cam_data *) dev_id;
+
+       if (cam->enc_callback == NULL)
+               return IRQ_HANDLED;
+
+       cam->enc_callback(irq, dev_id);
+
+       return IRQ_HANDLED;
+}
+
+/*!
+ * PrpENC enable channel setup function
+ *
+ * @param cam       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_enc_setup(cam_data *cam)
+{
+       ipu_channel_params_t enc;
+       int err = 0;
+       dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       CAMERA_TRACE("In prp_enc_setup\n");
+       if (!cam) {
+               printk(KERN_ERR "cam private is NULL\n");
+               return -ENXIO;
+       }
+       memset(&enc, 0, sizeof(ipu_channel_params_t));
+
+       ipu_csi_get_window_size(cam->ipu, &enc.csi_prp_enc_mem.in_width,
+                               &enc.csi_prp_enc_mem.in_height, cam->csi);
+
+       enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
+       enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width;
+       enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height;
+       enc.csi_prp_enc_mem.csi = cam->csi;
+       if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+               enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height;
+               enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width;
+       }
+
+       if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P;
+               pr_info("YUV420\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YVU420P;
+               pr_info("YVU420\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P;
+               pr_info("YUV422P\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV;
+               pr_info("YUYV\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY;
+               pr_info("UYVY\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12;
+               pr_info("NV12\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24;
+               pr_info("BGR24\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24;
+               pr_info("RGB24\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565;
+               pr_info("RGB565\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32;
+               pr_info("BGR32\n");
+       } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) {
+               enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32;
+               pr_info("RGB32\n");
+       } else {
+               printk(KERN_ERR "format not supported\n");
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id) {
+                               enc.csi_prp_enc_mem.mipi_en = true;
+                               enc.csi_prp_enc_mem.mipi_vc =
+                               mipi_csi2_get_virtual_channel(mipi_csi2_info);
+                               enc.csi_prp_enc_mem.mipi_id =
+                               mipi_csi2_get_datatype(mipi_csi2_info);
+
+                               mipi_csi2_pixelclk_enable(mipi_csi2_info);
+                       } else {
+                               enc.csi_prp_enc_mem.mipi_en = false;
+                               enc.csi_prp_enc_mem.mipi_vc = 0;
+                               enc.csi_prp_enc_mem.mipi_id = 0;
+                       }
+               } else {
+                       enc.csi_prp_enc_mem.mipi_en = false;
+                       enc.csi_prp_enc_mem.mipi_vc = 0;
+                       enc.csi_prp_enc_mem.mipi_id = 0;
+               }
+       }
+#endif
+
+       err = ipu_init_channel(cam->ipu, CSI_PRP_ENC_MEM, &enc);
+       if (err != 0) {
+               printk(KERN_ERR "ipu_init_channel %d\n", err);
+               return err;
+       }
+
+       grotation = cam->rotation;
+       if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+               if (cam->rot_enc_bufs_vaddr[0]) {
+                       dma_free_coherent(0, cam->rot_enc_buf_size[0],
+                                         cam->rot_enc_bufs_vaddr[0],
+                                         cam->rot_enc_bufs[0]);
+               }
+               if (cam->rot_enc_bufs_vaddr[1]) {
+                       dma_free_coherent(0, cam->rot_enc_buf_size[1],
+                                         cam->rot_enc_bufs_vaddr[1],
+                                         cam->rot_enc_bufs[1]);
+               }
+               cam->rot_enc_buf_size[0] =
+                   PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+               cam->rot_enc_bufs_vaddr[0] =
+                   (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0],
+                                              &cam->rot_enc_bufs[0],
+                                              GFP_DMA | GFP_KERNEL);
+               if (!cam->rot_enc_bufs_vaddr[0]) {
+                       printk(KERN_ERR "alloc enc_bufs0\n");
+                       return -ENOMEM;
+               }
+               cam->rot_enc_buf_size[1] =
+                   PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+               cam->rot_enc_bufs_vaddr[1] =
+                   (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1],
+                                              &cam->rot_enc_bufs[1],
+                                              GFP_DMA | GFP_KERNEL);
+               if (!cam->rot_enc_bufs_vaddr[1]) {
+                       dma_free_coherent(0, cam->rot_enc_buf_size[0],
+                                         cam->rot_enc_bufs_vaddr[0],
+                                         cam->rot_enc_bufs[0]);
+                       cam->rot_enc_bufs_vaddr[0] = NULL;
+                       cam->rot_enc_bufs[0] = 0;
+                       printk(KERN_ERR "alloc enc_bufs1\n");
+                       return -ENOMEM;
+               }
+
+               err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM,
+                                             IPU_OUTPUT_BUFFER,
+                                             enc.csi_prp_enc_mem.out_pixel_fmt,
+                                             enc.csi_prp_enc_mem.out_width,
+                                             enc.csi_prp_enc_mem.out_height,
+                                             enc.csi_prp_enc_mem.out_width,
+                                             IPU_ROTATE_NONE,
+                                             cam->rot_enc_bufs[0],
+                                             cam->rot_enc_bufs[1], 0, 0, 0);
+               if (err != 0) {
+                       printk(KERN_ERR "CSI_PRP_ENC_MEM err\n");
+                       return err;
+               }
+
+               err = ipu_init_channel(cam->ipu, MEM_ROT_ENC_MEM, NULL);
+               if (err != 0) {
+                       printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n");
+                       return err;
+               }
+
+               err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM,
+                                             IPU_INPUT_BUFFER,
+                                             enc.csi_prp_enc_mem.out_pixel_fmt,
+                                             enc.csi_prp_enc_mem.out_width,
+                                             enc.csi_prp_enc_mem.out_height,
+                                             enc.csi_prp_enc_mem.out_width,
+                                             cam->rotation,
+                                             cam->rot_enc_bufs[0],
+                                             cam->rot_enc_bufs[1], 0, 0, 0);
+               if (err != 0) {
+                       printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n");
+                       return err;
+               }
+
+               err =
+                   ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM,
+                                           IPU_OUTPUT_BUFFER,
+                                           enc.csi_prp_enc_mem.out_pixel_fmt,
+                                           enc.csi_prp_enc_mem.out_height,
+                                           enc.csi_prp_enc_mem.out_width,
+                                           cam->v2f.fmt.pix.bytesperline /
+                                           bytes_per_pixel(enc.csi_prp_enc_mem.
+                                                           out_pixel_fmt),
+                                           IPU_ROTATE_NONE,
+                                           dummy, dummy, 0,
+                                           cam->offset.u_offset,
+                                           cam->offset.v_offset);
+               if (err != 0) {
+                       printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n");
+                       return err;
+               }
+
+               err = ipu_link_channels(cam->ipu,
+                                       CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
+               if (err < 0) {
+                       printk(KERN_ERR
+                              "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n");
+                       return err;
+               }
+
+               err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM);
+               if (err < 0) {
+                       printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
+                       return err;
+               }
+               err = ipu_enable_channel(cam->ipu, MEM_ROT_ENC_MEM);
+               if (err < 0) {
+                       printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n");
+                       return err;
+               }
+
+               ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM,
+                                 IPU_OUTPUT_BUFFER, 0);
+               ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM,
+                                 IPU_OUTPUT_BUFFER, 1);
+       } else {
+               err =
+                   ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM,
+                                           IPU_OUTPUT_BUFFER,
+                                           enc.csi_prp_enc_mem.out_pixel_fmt,
+                                           enc.csi_prp_enc_mem.out_width,
+                                           enc.csi_prp_enc_mem.out_height,
+                                           cam->v2f.fmt.pix.bytesperline /
+                                           bytes_per_pixel(enc.csi_prp_enc_mem.
+                                                           out_pixel_fmt),
+                                           cam->rotation,
+                                           dummy, dummy, 0,
+                                           cam->offset.u_offset,
+                                           cam->offset.v_offset);
+               if (err != 0) {
+                       printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n");
+                       return err;
+               }
+               err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM);
+               if (err < 0) {
+                       printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
+                       return err;
+               }
+       }
+
+       return err;
+}
+
+/*!
+ * function to update physical buffer address for encorder IDMA channel
+ *
+ * @param private     pointer to cam_data structure
+ * @param eba         physical buffer address for encorder IDMA channel
+ *
+ * @return  status
+ */
+static int prp_enc_eba_update(void *private, dma_addr_t eba)
+{
+       int err = 0;
+       cam_data *cam = (cam_data *) private;
+       struct ipu_soc *ipu = cam->ipu;
+       int *buffer_num = &cam->ping_pong_csi;
+
+       pr_debug("eba %x\n", eba);
+       if (grotation >= IPU_ROTATE_90_RIGHT) {
+               err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM,
+                                               IPU_OUTPUT_BUFFER, *buffer_num,
+                                               eba);
+       } else {
+               err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM,
+                                               IPU_OUTPUT_BUFFER, *buffer_num,
+                                               eba);
+       }
+       if (err != 0) {
+               if (grotation >= IPU_ROTATE_90_RIGHT) {
+                       ipu_clear_buffer_ready(ipu, MEM_ROT_ENC_MEM,
+                                              IPU_OUTPUT_BUFFER,
+                                              *buffer_num);
+                       err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM,
+                                                       IPU_OUTPUT_BUFFER,
+                                                       *buffer_num,
+                                                       eba);
+               } else {
+                       ipu_clear_buffer_ready(ipu, CSI_PRP_ENC_MEM,
+                                              IPU_OUTPUT_BUFFER,
+                                              *buffer_num);
+                       err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM,
+                                                       IPU_OUTPUT_BUFFER,
+                                                       *buffer_num,
+                                                       eba);
+               }
+
+               if (err != 0) {
+                       pr_err("ERROR: v4l2 capture: fail to update "
+                              "buf%d\n", *buffer_num);
+                       return err;
+               }
+       }
+
+       if (grotation >= IPU_ROTATE_90_RIGHT) {
+               ipu_select_buffer(ipu, MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER,
+                                 *buffer_num);
+       } else {
+               ipu_select_buffer(ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER,
+                                 *buffer_num);
+       }
+
+       *buffer_num = (*buffer_num == 0) ? 1 : 0;
+       return 0;
+}
+
+/*!
+ * Enable encoder task
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_enc_enabling_tasks(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+       CAMERA_TRACE("IPU:In prp_enc_enabling_tasks\n");
+
+       cam->dummy_frame.vaddress = dma_alloc_coherent(0,
+                              PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+                              &cam->dummy_frame.paddress,
+                              GFP_DMA | GFP_KERNEL);
+       if (cam->dummy_frame.vaddress == 0) {
+               pr_err("ERROR: v4l2 capture: Allocate dummy frame "
+                      "failed.\n");
+               return -ENOBUFS;
+       }
+       cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE;
+       cam->dummy_frame.buffer.length =
+           PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+       cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
+
+       if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+               err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF,
+                                     prp_enc_callback, 0, "Mxc Camera", cam);
+       } else {
+               err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF,
+                                     prp_enc_callback, 0, "Mxc Camera", cam);
+       }
+       if (err != 0) {
+               printk(KERN_ERR "Error registering rot irq\n");
+               return err;
+       }
+
+       err = prp_enc_setup(cam);
+       if (err != 0) {
+               printk(KERN_ERR "prp_enc_setup %d\n", err);
+               return err;
+       }
+
+       return err;
+}
+
+/*!
+ * Disable encoder task
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  int
+ */
+static int prp_enc_disabling_tasks(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+               ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF, cam);
+               ipu_unlink_channels(cam->ipu, CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
+       }
+
+       err = ipu_disable_channel(cam->ipu, CSI_PRP_ENC_MEM, true);
+       if (cam->rotation >= IPU_ROTATE_90_RIGHT)
+               err |= ipu_disable_channel(cam->ipu, MEM_ROT_ENC_MEM, true);
+
+       ipu_uninit_channel(cam->ipu, CSI_PRP_ENC_MEM);
+       if (cam->rotation >= IPU_ROTATE_90_RIGHT)
+               ipu_uninit_channel(cam->ipu, MEM_ROT_ENC_MEM);
+
+       if (cam->dummy_frame.vaddress != 0) {
+               dma_free_coherent(0, cam->dummy_frame.buffer.length,
+                                 cam->dummy_frame.vaddress,
+                                 cam->dummy_frame.paddress);
+               cam->dummy_frame.vaddress = 0;
+       }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id)
+                               mipi_csi2_pixelclk_disable(mipi_csi2_info);
+               }
+       }
+#endif
+
+       return err;
+}
+
+/*!
+ * Enable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_enc_enable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_enc_disable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       /* free csi eof irq firstly.
+        * when disable csi, wait for idmac eof.
+        * it requests eof irq again */
+       if (cam->rotation < IPU_ROTATE_90_RIGHT)
+               ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF, cam);
+
+       return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select PRP-ENC as the working path
+ *
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  int
+ */
+int prp_enc_select(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+
+       if (cam) {
+               cam->enc_update_eba = prp_enc_eba_update;
+               cam->enc_enable = prp_enc_enabling_tasks;
+               cam->enc_disable = prp_enc_disabling_tasks;
+               cam->enc_enable_csi = prp_enc_enable_csi;
+               cam->enc_disable_csi = prp_enc_disable_csi;
+       } else {
+               err = -EIO;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL(prp_enc_select);
+
+/*!
+ * function to de-select PRP-ENC as the working path
+ *
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  int
+ */
+int prp_enc_deselect(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+
+       if (cam) {
+               cam->enc_update_eba = NULL;
+               cam->enc_enable = NULL;
+               cam->enc_disable = NULL;
+               cam->enc_enable_csi = NULL;
+               cam->enc_disable_csi = NULL;
+               if (cam->rot_enc_bufs_vaddr[0]) {
+                       dma_free_coherent(0, cam->rot_enc_buf_size[0],
+                                         cam->rot_enc_bufs_vaddr[0],
+                                         cam->rot_enc_bufs[0]);
+                       cam->rot_enc_bufs_vaddr[0] = NULL;
+                       cam->rot_enc_bufs[0] = 0;
+               }
+               if (cam->rot_enc_bufs_vaddr[1]) {
+                       dma_free_coherent(0, cam->rot_enc_buf_size[1],
+                                         cam->rot_enc_bufs_vaddr[1],
+                                         cam->rot_enc_bufs[1]);
+                       cam->rot_enc_bufs_vaddr[1] = NULL;
+                       cam->rot_enc_bufs[1] = 0;
+               }
+       }
+
+       return err;
+}
+EXPORT_SYMBOL(prp_enc_deselect);
+
+/*!
+ * Init the Encorder channels
+ *
+ * @return  Error code indicating success or failure
+ */
+__init int prp_enc_init(void)
+{
+       return 0;
+}
+
+/*!
+ * Deinit the Encorder channels
+ *
+ */
+void __exit prp_enc_exit(void)
+{
+}
+
+module_init(prp_enc_init);
+module_exit(prp_enc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP ENC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_sw.h b/drivers/media/platform/mxc/capture/ipu_prp_sw.h
new file mode 100644 (file)
index 0000000..be02ab0
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2004-2014 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 ipu_prp_sw.h
+ *
+ * @brief This file contains the IPU PRP use case driver header.
+ *
+ * @ingroup IPU
+ */
+
+#ifndef _INCLUDE_IPU__PRP_SW_H_
+#define _INCLUDE_IPU__PRP_SW_H_
+
+int csi_enc_select(void *private);
+int csi_enc_deselect(void *private);
+int prp_enc_select(void *private);
+int prp_enc_deselect(void *private);
+#ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+int prp_vf_sdc_select(void *private);
+int prp_vf_sdc_deselect(void *private);
+int prp_vf_sdc_select_bg(void *private);
+int prp_vf_sdc_deselect_bg(void *private);
+#else
+int foreground_sdc_select(void *private);
+int foreground_sdc_deselect(void *private);
+int bg_overlay_sdc_select(void *private);
+int bg_overlay_sdc_deselect(void *private);
+#endif
+int prp_still_select(void *private);
+int prp_still_deselect(void *private);
+
+#endif
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c b/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c
new file mode 100644 (file)
index 0000000..b9610f1
--- /dev/null
@@ -0,0 +1,582 @@
+/*
+ * Copyright 2004-2014 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 ipu_prp_vf_sdc.c
+ *
+ * @brief IPU Use case for PRP-VF
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/console.h>
+#include <linux/ipu.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <mach/hardware.h>
+#include <mach/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+static int buffer_num;
+static struct ipu_soc *disp_ipu;
+
+static void get_disp_ipu(cam_data *cam)
+{
+       if (cam->output > 2)
+               disp_ipu = ipu_get_soc(1); /* using DISP4 */
+       else
+               disp_ipu = ipu_get_soc(0);
+}
+
+static irqreturn_t prpvf_rot_eof_callback(int irq, void *dev_id)
+{
+       cam_data *cam = dev_id;
+       pr_debug("buffer_num %d\n",  buffer_num);
+
+       if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+               ipu_select_buffer(disp_ipu, MEM_FG_SYNC,
+                                 IPU_INPUT_BUFFER, buffer_num);
+               buffer_num = (buffer_num == 0) ? 1 : 0;
+               ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                                 IPU_OUTPUT_BUFFER, buffer_num);
+       } else {
+               ipu_select_buffer(disp_ipu, MEM_FG_SYNC,
+                                 IPU_INPUT_BUFFER, buffer_num);
+               buffer_num = (buffer_num == 0) ? 1 : 0;
+               ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+                                 IPU_OUTPUT_BUFFER, buffer_num);
+       }
+       return IRQ_HANDLED;
+}
+/*
+ * Function definitions
+ */
+
+/*!
+ * prpvf_start - start the vf task
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ */
+static int prpvf_start(void *private)
+{
+       struct fb_var_screeninfo fbvar;
+       struct fb_info *fbi = NULL;
+       cam_data *cam = (cam_data *) private;
+       ipu_channel_params_t vf;
+       u32 vf_out_format = 0;
+       u32 size = 2, temp = 0;
+       int err = 0, i = 0;
+       short *tmp, color;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       if (!cam) {
+               printk(KERN_ERR "private is NULL\n");
+               return -EIO;
+       }
+
+       if (cam->overlay_active == true) {
+               pr_debug("already started.\n");
+               return 0;
+       }
+
+       get_disp_ipu(cam);
+
+       for (i = 0; i < num_registered_fb; i++) {
+               char *idstr = registered_fb[i]->fix.id;
+               if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+                   ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
+                       fbi = registered_fb[i];
+                       break;
+               }
+       }
+
+       if (fbi == NULL) {
+               printk(KERN_ERR "DISP FG fb not found\n");
+               return -EPERM;
+       }
+
+       fbvar = fbi->var;
+
+       /* Store the overlay frame buffer's original std */
+       cam->fb_origin_std = fbvar.nonstd;
+
+       if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
+               /* Use DP to do CSC so that we can get better performance */
+               vf_out_format = IPU_PIX_FMT_UYVY;
+               fbvar.nonstd = vf_out_format;
+               color = 0x80;
+       } else {
+               vf_out_format = IPU_PIX_FMT_RGB565;
+               fbvar.nonstd = 0;
+               color = 0x0;
+       }
+
+       fbvar.bits_per_pixel = 16;
+       fbvar.xres = fbvar.xres_virtual = cam->win.w.width;
+       fbvar.yres = cam->win.w.height;
+       fbvar.yres_virtual = cam->win.w.height * 2;
+       fbvar.yoffset = 0;
+       fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG;
+       fbvar.activate |= FB_ACTIVATE_FORCE;
+       fb_set_var(fbi, &fbvar);
+
+       ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left,
+                       cam->win.w.top);
+
+       /* Fill black color for framebuffer */
+       tmp = (short *) fbi->screen_base;
+       for (i = 0; i < (fbi->fix.line_length * fbi->var.yres)/2;
+                       i++, tmp++)
+               *tmp = color;
+
+       console_lock();
+       fb_blank(fbi, FB_BLANK_UNBLANK);
+       console_unlock();
+
+       /* correct display ch buffer address */
+       ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+                               0, fbi->fix.smem_start +
+                               (fbi->fix.line_length * fbvar.yres));
+       ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+                                       1, fbi->fix.smem_start);
+
+       memset(&vf, 0, sizeof(ipu_channel_params_t));
+       ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width,
+                               &vf.csi_prp_vf_mem.in_height, cam->csi);
+       vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
+       vf.csi_prp_vf_mem.out_width = cam->win.w.width;
+       vf.csi_prp_vf_mem.out_height = cam->win.w.height;
+       vf.csi_prp_vf_mem.csi = cam->csi;
+       if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
+               vf.csi_prp_vf_mem.out_width = cam->win.w.height;
+               vf.csi_prp_vf_mem.out_height = cam->win.w.width;
+       }
+       vf.csi_prp_vf_mem.out_pixel_fmt = vf_out_format;
+       size = cam->win.w.width * cam->win.w.height * size;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id) {
+                               vf.csi_prp_vf_mem.mipi_en = true;
+                               vf.csi_prp_vf_mem.mipi_vc =
+                               mipi_csi2_get_virtual_channel(mipi_csi2_info);
+                               vf.csi_prp_vf_mem.mipi_id =
+                               mipi_csi2_get_datatype(mipi_csi2_info);
+
+                               mipi_csi2_pixelclk_enable(mipi_csi2_info);
+                       } else {
+                               vf.csi_prp_vf_mem.mipi_en = false;
+                               vf.csi_prp_vf_mem.mipi_vc = 0;
+                               vf.csi_prp_vf_mem.mipi_id = 0;
+                       }
+               } else {
+                       vf.csi_prp_vf_mem.mipi_en = false;
+                       vf.csi_prp_vf_mem.mipi_vc = 0;
+                       vf.csi_prp_vf_mem.mipi_id = 0;
+               }
+       }
+#endif
+
+       err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf);
+       if (err != 0)
+               goto out_5;
+
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0],
+                                 (dma_addr_t) cam->vf_bufs[0]);
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1],
+                                 (dma_addr_t) cam->vf_bufs[1]);
+       }
+       cam->vf_bufs_size[0] = PAGE_ALIGN(size);
+       cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
+                                                          cam->vf_bufs_size[0],
+                                                          (dma_addr_t *) &
+                                                          cam->vf_bufs[0],
+                                                          GFP_DMA |
+                                                          GFP_KERNEL);
+       if (cam->vf_bufs_vaddr[0] == NULL) {
+               printk(KERN_ERR "Error to allocate vf buffer\n");
+               err = -ENOMEM;
+               goto out_4;
+       }
+       cam->vf_bufs_size[1] = PAGE_ALIGN(size);
+       cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
+                                                          cam->vf_bufs_size[1],
+                                                          (dma_addr_t *) &
+                                                          cam->vf_bufs[1],
+                                                          GFP_DMA |
+                                                          GFP_KERNEL);
+       if (cam->vf_bufs_vaddr[1] == NULL) {
+               printk(KERN_ERR "Error to allocate vf buffer\n");
+               err = -ENOMEM;
+               goto out_3;
+       }
+       pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
+
+       if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+               err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
+                                             IPU_OUTPUT_BUFFER,
+                                             vf_out_format,
+                                             vf.csi_prp_vf_mem.out_width,
+                                             vf.csi_prp_vf_mem.out_height,
+                                             vf.csi_prp_vf_mem.out_width,
+                                             IPU_ROTATE_NONE,
+                                             cam->vf_bufs[0], cam->vf_bufs[1],
+                                             0, 0, 0);
+               if (err != 0)
+                       goto out_3;
+
+               err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL);
+               if (err != 0) {
+                       printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n");
+                       goto out_3;
+               }
+
+               err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                                             IPU_INPUT_BUFFER,
+                                             vf_out_format,
+                                             vf.csi_prp_vf_mem.out_width,
+                                             vf.csi_prp_vf_mem.out_height,
+                                             vf.csi_prp_vf_mem.out_width,
+                                             cam->vf_rotation,
+                                             cam->vf_bufs[0],
+                                             cam->vf_bufs[1],
+                                             0, 0, 0);
+               if (err != 0) {
+                       printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n");
+                       goto out_2;
+               }
+
+               if (cam->vf_rotation < IPU_ROTATE_90_RIGHT) {
+                       temp = vf.csi_prp_vf_mem.out_width;
+                       vf.csi_prp_vf_mem.out_width =
+                                               vf.csi_prp_vf_mem.out_height;
+                       vf.csi_prp_vf_mem.out_height = temp;
+               }
+
+               err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                                             IPU_OUTPUT_BUFFER,
+                                             vf_out_format,
+                                             vf.csi_prp_vf_mem.out_height,
+                                             vf.csi_prp_vf_mem.out_width,
+                                             vf.csi_prp_vf_mem.out_height,
+                                             IPU_ROTATE_NONE,
+                                             fbi->fix.smem_start +
+                                             (fbi->fix.line_length *
+                                              fbi->var.yres),
+                                             fbi->fix.smem_start, 0, 0, 0);
+
+               if (err != 0) {
+                       printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
+                       goto out_2;
+               }
+
+               ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF);
+               err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF,
+                                     prpvf_rot_eof_callback,
+                             0, "Mxc Camera", cam);
+               if (err < 0) {
+                       printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_ROT_OUT_EOF\n");
+                       goto out_2;
+               }
+
+               err = ipu_link_channels(cam->ipu,
+                                       CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
+               if (err < 0) {
+                       printk(KERN_ERR
+                              "Error link CSI_PRP_VF_MEM-MEM_ROT_VF_MEM\n");
+                       goto out_1;
+               }
+
+               ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
+               ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM);
+
+               ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+                                 IPU_OUTPUT_BUFFER, 0);
+               ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+                                 IPU_OUTPUT_BUFFER, 1);
+               ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                                 IPU_OUTPUT_BUFFER, 0);
+       } else {
+               err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
+                                             IPU_OUTPUT_BUFFER,
+                                             vf_out_format, cam->win.w.width,
+                                             cam->win.w.height,
+                                             cam->win.w.width,
+                                             cam->vf_rotation,
+                                             fbi->fix.smem_start +
+                                             (fbi->fix.line_length *
+                                              fbi->var.yres),
+                                             fbi->fix.smem_start, 0, 0, 0);
+               if (err != 0) {
+                       printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
+                       goto out_4;
+               }
+               ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF);
+               err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF,
+                                     prpvf_rot_eof_callback,
+                             0, "Mxc Camera", cam);
+               if (err < 0) {
+                       printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_OUT_EOF\n");
+                       goto out_4;
+               }
+
+               ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
+
+               ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+                                 IPU_OUTPUT_BUFFER, 0);
+       }
+
+       cam->overlay_active = true;
+       return err;
+
+out_1:
+       ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL);
+out_2:
+       if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP)
+               ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
+out_3:
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0],
+                                 (dma_addr_t) cam->vf_bufs[0]);
+               cam->vf_bufs_vaddr[0] = NULL;
+               cam->vf_bufs[0] = 0;
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1],
+                                 (dma_addr_t) cam->vf_bufs[1]);
+               cam->vf_bufs_vaddr[1] = NULL;
+               cam->vf_bufs[1] = 0;
+       }
+out_4:
+       ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
+out_5:
+       return err;
+}
+
+/*!
+ * prpvf_stop - stop the vf task
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ */
+static int prpvf_stop(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0, i = 0;
+       struct fb_info *fbi = NULL;
+       struct fb_var_screeninfo fbvar;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       if (cam->overlay_active == false)
+               return 0;
+
+       for (i = 0; i < num_registered_fb; i++) {
+               char *idstr = registered_fb[i]->fix.id;
+               if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+                   ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
+                       fbi = registered_fb[i];
+                       break;
+               }
+       }
+
+       if (fbi == NULL) {
+               printk(KERN_ERR "DISP FG fb not found\n");
+               return -EPERM;
+       }
+
+       if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+               ipu_unlink_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
+               ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, cam);
+       }
+       buffer_num = 0;
+
+       ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true);
+
+       if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+               ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true);
+               ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
+       }
+       ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
+
+       console_lock();
+       fb_blank(fbi, FB_BLANK_POWERDOWN);
+       console_unlock();
+
+       /* Set the overlay frame buffer std to what it is used to be */
+       fbvar = fbi->var;
+       fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG;
+       fbvar.nonstd = cam->fb_origin_std;
+       fbvar.activate |= FB_ACTIVATE_FORCE;
+       fb_set_var(fbi, &fbvar);
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id)
+                               mipi_csi2_pixelclk_disable(mipi_csi2_info);
+               }
+       }
+#endif
+
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0],
+                                 (dma_addr_t) cam->vf_bufs[0]);
+               cam->vf_bufs_vaddr[0] = NULL;
+               cam->vf_bufs[0] = 0;
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1],
+                                 (dma_addr_t) cam->vf_bufs[1]);
+               cam->vf_bufs_vaddr[1] = NULL;
+               cam->vf_bufs[1] = 0;
+       }
+
+       cam->overlay_active = false;
+       return err;
+}
+
+/*!
+ * Enable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_vf_enable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_vf_disable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       /* free csi eof irq firstly.
+        * when disable csi, wait for idmac eof.
+        * it requests eof irq again */
+       if (cam->vf_rotation < IPU_ROTATE_VERT_FLIP)
+               ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
+
+       return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select PRP-VF as the working path
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ * @return  status
+ */
+int prp_vf_sdc_select(void *private)
+{
+       cam_data *cam;
+       int err = 0;
+       if (private) {
+               cam = (cam_data *) private;
+               cam->vf_start_sdc = prpvf_start;
+               cam->vf_stop_sdc = prpvf_stop;
+               cam->vf_enable_csi = prp_vf_enable_csi;
+               cam->vf_disable_csi = prp_vf_disable_csi;
+               cam->overlay_active = false;
+       } else
+               err = -EIO;
+
+       return err;
+}
+EXPORT_SYMBOL(prp_vf_sdc_select);
+
+/*!
+ * function to de-select PRP-VF as the working path
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ * @return  int
+ */
+int prp_vf_sdc_deselect(void *private)
+{
+       cam_data *cam;
+
+       if (private) {
+               cam = (cam_data *) private;
+               cam->vf_start_sdc = NULL;
+               cam->vf_stop_sdc = NULL;
+               cam->vf_enable_csi = NULL;
+               cam->vf_disable_csi = NULL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(prp_vf_sdc_deselect);
+
+/*!
+ * Init viewfinder task.
+ *
+ * @return  Error code indicating success or failure
+ */
+__init int prp_vf_sdc_init(void)
+{
+       return 0;
+}
+
+/*!
+ * Deinit viewfinder task.
+ *
+ * @return  Error code indicating success or failure
+ */
+void __exit prp_vf_sdc_exit(void)
+{
+}
+
+module_init(prp_vf_sdc_init);
+module_exit(prp_vf_sdc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP VF SDC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c b/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c
new file mode 100644 (file)
index 0000000..a24d82d
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * Copyright 2004-2014 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 ipu_prp_vf_sdc_bg.c
+ *
+ * @brief IPU Use case for PRP-VF back-ground
+ *
+ * @ingroup IPU
+ */
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/ipu.h>
+#include <linux/module.h>
+#include <mach/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+static int buffer_num;
+static int buffer_ready;
+static struct ipu_soc *disp_ipu;
+
+static void get_disp_ipu(cam_data *cam)
+{
+       if (cam->output > 2)
+               disp_ipu = ipu_get_soc(1); /* using DISP4 */
+       else
+               disp_ipu = ipu_get_soc(0);
+}
+
+/*
+ * Function definitions
+ */
+
+/*!
+ * SDC V-Sync callback function.
+ *
+ * @param irq       int irq line
+ * @param dev_id    void * device id
+ *
+ * @return status   IRQ_HANDLED for handled
+ */
+static irqreturn_t prpvf_sdc_vsync_callback(int irq, void *dev_id)
+{
+       cam_data *cam = dev_id;
+       if (buffer_ready > 0) {
+               ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                                 IPU_OUTPUT_BUFFER, 0);
+               buffer_ready--;
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*!
+ * VF EOF callback function.
+ *
+ * @param irq       int irq line
+ * @param dev_id    void * device id
+ *
+ * @return status   IRQ_HANDLED for handled
+ */
+static irqreturn_t prpvf_vf_eof_callback(int irq, void *dev_id)
+{
+       cam_data *cam = dev_id;
+       pr_debug("buffer_ready %d buffer_num %d\n", buffer_ready, buffer_num);
+
+       ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                         IPU_INPUT_BUFFER, buffer_num);
+       buffer_num = (buffer_num == 0) ? 1 : 0;
+       ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+                         IPU_OUTPUT_BUFFER, buffer_num);
+       buffer_ready++;
+       return IRQ_HANDLED;
+}
+
+/*!
+ * prpvf_start - start the vf task
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ */
+static int prpvf_start(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       ipu_channel_params_t vf;
+       u32 format;
+       u32 offset;
+       u32 bpp, size = 3;
+       int err = 0;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       if (!cam) {
+               printk(KERN_ERR "private is NULL\n");
+               return -EIO;
+       }
+
+       if (cam->overlay_active == true) {
+               pr_debug("already start.\n");
+               return 0;
+       }
+
+       get_disp_ipu(cam);
+
+       format = cam->v4l2_fb.fmt.pixelformat;
+       if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) {
+               bpp = 3, size = 3;
+               pr_info("BGR24\n");
+       } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) {
+               bpp = 2, size = 2;
+               pr_info("RGB565\n");
+       } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) {
+               bpp = 4, size = 4;
+               pr_info("BGR32\n");
+       } else {
+               printk(KERN_ERR
+                      "unsupported fix format from the framebuffer.\n");
+               return -EINVAL;
+       }
+
+       offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top +
+           size * cam->win.w.left;
+
+       if (cam->v4l2_fb.base == 0)
+               printk(KERN_ERR "invalid frame buffer address.\n");
+       else
+               offset += (u32) cam->v4l2_fb.base;
+
+       memset(&vf, 0, sizeof(ipu_channel_params_t));
+       ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width,
+                               &vf.csi_prp_vf_mem.in_height, cam->csi);
+       vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
+       vf.csi_prp_vf_mem.out_width = cam->win.w.width;
+       vf.csi_prp_vf_mem.out_height = cam->win.w.height;
+       vf.csi_prp_vf_mem.csi = cam->csi;
+       if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
+               vf.csi_prp_vf_mem.out_width = cam->win.w.height;
+               vf.csi_prp_vf_mem.out_height = cam->win.w.width;
+       }
+       vf.csi_prp_vf_mem.out_pixel_fmt = format;
+       size = cam->win.w.width * cam->win.w.height * size;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id) {
+                               vf.csi_prp_vf_mem.mipi_en = true;
+                               vf.csi_prp_vf_mem.mipi_vc =
+                               mipi_csi2_get_virtual_channel(mipi_csi2_info);
+                               vf.csi_prp_vf_mem.mipi_id =
+                               mipi_csi2_get_datatype(mipi_csi2_info);
+
+                               mipi_csi2_pixelclk_enable(mipi_csi2_info);
+                       } else {
+                               vf.csi_prp_vf_mem.mipi_en = false;
+                               vf.csi_prp_vf_mem.mipi_vc = 0;
+                               vf.csi_prp_vf_mem.mipi_id = 0;
+                       }
+               } else {
+                       vf.csi_prp_vf_mem.mipi_en = false;
+                       vf.csi_prp_vf_mem.mipi_vc = 0;
+                       vf.csi_prp_vf_mem.mipi_id = 0;
+               }
+       }
+#endif
+
+       err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf);
+       if (err != 0)
+               goto out_4;
+
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
+       }
+       cam->vf_bufs_size[0] = PAGE_ALIGN(size);
+       cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
+                                                          cam->vf_bufs_size[0],
+                                                          &cam->vf_bufs[0],
+                                                          GFP_DMA |
+                                                          GFP_KERNEL);
+       if (cam->vf_bufs_vaddr[0] == NULL) {
+               printk(KERN_ERR "Error to allocate vf buffer\n");
+               err = -ENOMEM;
+               goto out_3;
+       }
+       cam->vf_bufs_size[1] = PAGE_ALIGN(size);
+       cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
+                                                          cam->vf_bufs_size[1],
+                                                          &cam->vf_bufs[1],
+                                                          GFP_DMA |
+                                                          GFP_KERNEL);
+       if (cam->vf_bufs_vaddr[1] == NULL) {
+               printk(KERN_ERR "Error to allocate vf buffer\n");
+               err = -ENOMEM;
+               goto out_3;
+       }
+
+       err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
+                                     IPU_OUTPUT_BUFFER,
+                                     format, vf.csi_prp_vf_mem.out_width,
+                                     vf.csi_prp_vf_mem.out_height,
+                                     vf.csi_prp_vf_mem.out_width,
+                                     IPU_ROTATE_NONE,
+                                     cam->vf_bufs[0],
+                                     cam->vf_bufs[1],
+                                     0, 0, 0);
+       if (err != 0) {
+               printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
+               goto out_3;
+       }
+       err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL);
+       if (err != 0) {
+               printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n");
+               goto out_3;
+       }
+
+       err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                                     IPU_INPUT_BUFFER,
+                                     format, vf.csi_prp_vf_mem.out_width,
+                                     vf.csi_prp_vf_mem.out_height,
+                                     vf.csi_prp_vf_mem.out_width,
+                                     cam->vf_rotation,
+                                     cam->vf_bufs[0],
+                                     cam->vf_bufs[1],
+                                     0, 0, 0);
+       if (err != 0) {
+               printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n");
+               goto out_2;
+       }
+
+       if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
+               err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                                             IPU_OUTPUT_BUFFER,
+                                             format,
+                                             vf.csi_prp_vf_mem.out_height,
+                                             vf.csi_prp_vf_mem.out_width,
+                                             cam->overlay_fb->var.xres * bpp,
+                                             IPU_ROTATE_NONE,
+                                             offset, 0, 0, 0, 0);
+
+               if (err != 0) {
+                       printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
+                       goto out_2;
+               }
+       } else {
+               err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+                                             IPU_OUTPUT_BUFFER,
+                                             format,
+                                             vf.csi_prp_vf_mem.out_width,
+                                             vf.csi_prp_vf_mem.out_height,
+                                             cam->overlay_fb->var.xres * bpp,
+                                             IPU_ROTATE_NONE,
+                                             offset, 0, 0, 0, 0);
+               if (err != 0) {
+                       printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
+                       goto out_2;
+               }
+       }
+
+       ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF);
+       err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF,
+                             prpvf_vf_eof_callback,
+                             0, "Mxc Camera", cam);
+       if (err != 0) {
+               printk(KERN_ERR
+                      "Error registering IPU_IRQ_PRP_VF_OUT_EOF irq.\n");
+               goto out_2;
+       }
+
+       ipu_clear_irq(disp_ipu, IPU_IRQ_BG_SF_END);
+       err = ipu_request_irq(disp_ipu, IPU_IRQ_BG_SF_END,
+                             prpvf_sdc_vsync_callback,
+                             0, "Mxc Camera", cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error registering IPU_IRQ_BG_SF_END irq.\n");
+               goto out_1;
+       }
+
+       ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
+       ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM);
+
+       buffer_num = 0;
+       buffer_ready = 0;
+       ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 0);
+
+       cam->overlay_active = true;
+       return err;
+
+out_1:
+       ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL);
+out_2:
+       ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
+out_3:
+       ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
+out_4:
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
+               cam->vf_bufs_vaddr[0] = NULL;
+               cam->vf_bufs[0] = 0;
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
+               cam->vf_bufs_vaddr[1] = NULL;
+               cam->vf_bufs[1] = 0;
+       }
+       if (cam->rot_vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->rot_vf_buf_size[0],
+                                 cam->rot_vf_bufs_vaddr[0],
+                                 cam->rot_vf_bufs[0]);
+               cam->rot_vf_bufs_vaddr[0] = NULL;
+               cam->rot_vf_bufs[0] = 0;
+       }
+       if (cam->rot_vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->rot_vf_buf_size[1],
+                                 cam->rot_vf_bufs_vaddr[1],
+                                 cam->rot_vf_bufs[1]);
+               cam->rot_vf_bufs_vaddr[1] = NULL;
+               cam->rot_vf_bufs[1] = 0;
+       }
+       return err;
+}
+
+/*!
+ * prpvf_stop - stop the vf task
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ */
+static int prpvf_stop(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+#ifdef CONFIG_MXC_MIPI_CSI2
+       void *mipi_csi2_info;
+       int ipu_id;
+       int csi_id;
+#endif
+
+       if (cam->overlay_active == false)
+               return 0;
+
+       ipu_free_irq(disp_ipu, IPU_IRQ_BG_SF_END, cam);
+
+       ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true);
+       ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true);
+       ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
+       ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       if (mipi_csi2_info) {
+               if (mipi_csi2_get_status(mipi_csi2_info)) {
+                       ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+                       csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+                       if (cam->ipu == ipu_get_soc(ipu_id)
+                               && cam->csi == csi_id)
+                               mipi_csi2_pixelclk_disable(mipi_csi2_info);
+               }
+       }
+#endif
+
+       if (cam->vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->vf_bufs_size[0],
+                                 cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
+               cam->vf_bufs_vaddr[0] = NULL;
+               cam->vf_bufs[0] = 0;
+       }
+       if (cam->vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->vf_bufs_size[1],
+                                 cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
+               cam->vf_bufs_vaddr[1] = NULL;
+               cam->vf_bufs[1] = 0;
+       }
+       if (cam->rot_vf_bufs_vaddr[0]) {
+               dma_free_coherent(0, cam->rot_vf_buf_size[0],
+                                 cam->rot_vf_bufs_vaddr[0],
+                                 cam->rot_vf_bufs[0]);
+               cam->rot_vf_bufs_vaddr[0] = NULL;
+               cam->rot_vf_bufs[0] = 0;
+       }
+       if (cam->rot_vf_bufs_vaddr[1]) {
+               dma_free_coherent(0, cam->rot_vf_buf_size[1],
+                                 cam->rot_vf_bufs_vaddr[1],
+                                 cam->rot_vf_bufs[1]);
+               cam->rot_vf_bufs_vaddr[1] = NULL;
+               cam->rot_vf_bufs[1] = 0;
+       }
+
+       buffer_num = 0;
+       buffer_ready = 0;
+       cam->overlay_active = false;
+       return 0;
+}
+
+/*!
+ * Enable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_vf_enable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_vf_disable_csi(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       /* free csi eof irq firstly.
+        * when disable csi, wait for idmac eof.
+        * it requests eof irq again */
+       ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
+
+       return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select PRP-VF as the working path
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ * @return  status
+ */
+int prp_vf_sdc_select_bg(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       if (cam) {
+               cam->vf_start_sdc = prpvf_start;
+               cam->vf_stop_sdc = prpvf_stop;
+               cam->vf_enable_csi = prp_vf_enable_csi;
+               cam->vf_disable_csi = prp_vf_disable_csi;
+               cam->overlay_active = false;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(prp_vf_sdc_select_bg);
+
+/*!
+ * function to de-select PRP-VF as the working path
+ *
+ * @param private    cam_data * mxc v4l2 main structure
+ *
+ * @return  status
+ */
+int prp_vf_sdc_deselect_bg(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       if (cam) {
+               cam->vf_start_sdc = NULL;
+               cam->vf_stop_sdc = NULL;
+               cam->vf_enable_csi = NULL;
+               cam->vf_disable_csi = NULL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(prp_vf_sdc_deselect_bg);
+
+/*!
+ * Init viewfinder task.
+ *
+ * @return  Error code indicating success or failure
+ */
+__init int prp_vf_sdc_init_bg(void)
+{
+       return 0;
+}
+
+/*!
+ * Deinit viewfinder task.
+ *
+ * @return  Error code indicating success or failure
+ */
+void __exit prp_vf_sdc_exit_bg(void)
+{
+}
+
+module_init(prp_vf_sdc_init_bg);
+module_exit(prp_vf_sdc_exit_bg);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_still.c b/drivers/media/platform/mxc/capture/ipu_still.c
new file mode 100644 (file)
index 0000000..b18c3cf
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2004-2014 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 ipu_still.c
+ *
+ * @brief IPU Use case for still image capture
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/module.h>
+#include <linux/semaphore.h>
+#include <linux/sched.h>
+#include <linux/ipu.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+static int callback_eof_flag;
+#ifndef CONFIG_MXC_IPU_V1
+static int buffer_num;
+#endif
+
+#ifdef CONFIG_MXC_IPU_V1
+static int callback_flag;
+/*
+ * Function definitions
+ */
+/*!
+ * CSI EOF callback function.
+ *
+ * @param irq       int irq line
+ * @param dev_id    void * device id
+ *
+ * @return status   IRQ_HANDLED for handled
+ */
+static irqreturn_t prp_csi_eof_callback(int irq, void *dev_id)
+{
+       cam_data *cam = devid;
+       ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
+                         callback_flag%2 ? 1 : 0);
+       if (callback_flag == 0)
+               ipu_enable_channel(cam->ipu, CSI_MEM);
+
+       callback_flag++;
+       return IRQ_HANDLED;
+}
+#endif
+
+/*!
+ * CSI callback function.
+ *
+ * @param irq       int irq line
+ * @param dev_id    void * device id
+ *
+ * @return status   IRQ_HANDLED for handled
+ */
+static irqreturn_t prp_still_callback(int irq, void *dev_id)
+{
+       cam_data *cam = (cam_data *) dev_id;
+
+       callback_eof_flag++;
+       if (callback_eof_flag < 5) {
+#ifndef CONFIG_MXC_IPU_V1
+               buffer_num = (buffer_num == 0) ? 1 : 0;
+               ipu_select_buffer(cam->ipu, CSI_MEM,
+                                 IPU_OUTPUT_BUFFER, buffer_num);
+#endif
+       } else {
+               cam->still_counter++;
+               wake_up_interruptible(&cam->still_queue);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*!
+ * start csi->mem task
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_still_start(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       u32 pixel_fmt;
+       int err;
+       ipu_channel_params_t params;
+
+       if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
+               pixel_fmt = IPU_PIX_FMT_YUV420P;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
+               pixel_fmt = IPU_PIX_FMT_NV12;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
+               pixel_fmt = IPU_PIX_FMT_YUV422P;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
+               pixel_fmt = IPU_PIX_FMT_UYVY;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+               pixel_fmt = IPU_PIX_FMT_YUYV;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
+               pixel_fmt = IPU_PIX_FMT_BGR24;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
+               pixel_fmt = IPU_PIX_FMT_RGB24;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
+               pixel_fmt = IPU_PIX_FMT_RGB565;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
+               pixel_fmt = IPU_PIX_FMT_BGR32;
+       else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
+               pixel_fmt = IPU_PIX_FMT_RGB32;
+       else {
+               printk(KERN_ERR "format not supported\n");
+               return -EINVAL;
+       }
+
+       memset(&params, 0, sizeof(params));
+       err = ipu_init_channel(cam->ipu, CSI_MEM, &params);
+       if (err != 0)
+               return err;
+
+       err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
+                                     pixel_fmt, cam->v2f.fmt.pix.width,
+                                     cam->v2f.fmt.pix.height,
+                                     cam->v2f.fmt.pix.width, IPU_ROTATE_NONE,
+                                     cam->still_buf[0], cam->still_buf[1], 0,
+                                     0, 0);
+       if (err != 0)
+               return err;
+
+#ifdef CONFIG_MXC_IPU_V1
+       ipu_clear_irq(IPU_IRQ_SENSOR_OUT_EOF);
+       err = ipu_request_irq(IPU_IRQ_SENSOR_OUT_EOF, prp_still_callback,
+                             0, "Mxc Camera", cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error registering irq.\n");
+               return err;
+       }
+       callback_flag = 0;
+       callback_eof_flag = 0;
+       ipu_clear_irq(IPU_IRQ_SENSOR_EOF);
+       err = ipu_request_irq(IPU_IRQ_SENSOR_EOF, prp_csi_eof_callback,
+                             0, "Mxc Camera", cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error IPU_IRQ_SENSOR_EOF\n");
+               return err;
+       }
+#else
+       callback_eof_flag = 0;
+       buffer_num = 0;
+
+       ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);
+       err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,
+                             prp_still_callback,
+                             0, "Mxc Camera", cam);
+       if (err != 0) {
+               printk(KERN_ERR "Error registering irq.\n");
+               return err;
+       }
+
+       ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0);
+       ipu_enable_channel(cam->ipu, CSI_MEM);
+       ipu_enable_csi(cam->ipu, cam->csi);
+#endif
+
+       return err;
+}
+
+/*!
+ * stop csi->mem encoder task
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+static int prp_still_stop(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+
+#ifdef CONFIG_MXC_IPU_V1
+       ipu_free_irq(IPU_IRQ_SENSOR_EOF, NULL);
+       ipu_free_irq(IPU_IRQ_SENSOR_OUT_EOF, cam);
+#else
+       ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
+#endif
+
+       ipu_disable_csi(cam->ipu, cam->csi);
+       ipu_disable_channel(cam->ipu, CSI_MEM, true);
+       ipu_uninit_channel(cam->ipu, CSI_MEM);
+
+       return err;
+}
+
+/*!
+ * function to select CSI_MEM as the working path
+ *
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+int prp_still_select(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+
+       if (cam) {
+               cam->csi_start = prp_still_start;
+               cam->csi_stop = prp_still_stop;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(prp_still_select);
+
+/*!
+ * function to de-select CSI_MEM as the working path
+ *
+ * @param private       struct cam_data * mxc capture instance
+ *
+ * @return  status
+ */
+int prp_still_deselect(void *private)
+{
+       cam_data *cam = (cam_data *) private;
+       int err = 0;
+
+       err = prp_still_stop(cam);
+
+       if (cam) {
+               cam->csi_start = NULL;
+               cam->csi_stop = NULL;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL(prp_still_deselect);
+
+/*!
+ * Init the Encorder channels
+ *
+ * @return  Error code indicating success or failure
+ */
+__init int prp_still_init(void)
+{
+       return 0;
+}
+
+/*!
+ * Deinit the Encorder channels
+ *
+ */
+void __exit prp_still_exit(void)
+{
+}
+
+module_init(prp_still_init);
+module_exit(prp_still_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP STILL IMAGE Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
new file mode 100644 (file)
index 0000000..37f9dff
--- /dev/null
@@ -0,0 +1,3138 @@
+/*
+ * Copyright 2004-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
+ */
+
+/*!
+ * @file drivers/media/video/mxc/capture/mxc_v4l2_capture.c
+ *
+ * @brief Mxc Video For Linux 2 driver
+ *
+ * @ingroup MXC_V4L2_CAPTURE
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/mxcfb.h>
+#include <linux/of_device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include "v4l2-int-device.h"
+#include <linux/fsl_devices.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+#define init_MUTEX(sem)         sema_init(sem, 1)
+
+static struct platform_device_id imx_v4l2_devtype[] = {
+       {
+               .name = "v4l2-capture-imx5",
+               .driver_data = IMX5_V4L2,
+       }, {
+               .name = "v4l2-capture-imx6",
+               .driver_data = IMX6_V4L2,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, imx_v4l2_devtype);
+
+static const struct of_device_id mxc_v4l2_dt_ids[] = {
+       {
+               .compatible = "fsl,imx6q-v4l2-capture",
+               .data = &imx_v4l2_devtype[IMX6_V4L2],
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, mxc_v4l2_dt_ids);
+
+static int video_nr = -1;
+
+/*! This data is used for the output to the display. */
+#define MXC_V4L2_CAPTURE_NUM_OUTPUTS   6
+#define MXC_V4L2_CAPTURE_NUM_INPUTS    2
+static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = {
+       {
+        .index = 0,
+        .name = "DISP3 BG",
+        .type = V4L2_OUTPUT_TYPE_ANALOG,
+        .audioset = 0,
+        .modulator = 0,
+        .std = V4L2_STD_UNKNOWN,
+        },
+       {
+        .index = 1,
+        .name = "DISP3 BG - DI1",
+        .type = V4L2_OUTPUT_TYPE_ANALOG,
+        .audioset = 0,
+        .modulator = 0,
+        .std = V4L2_STD_UNKNOWN,
+        },
+       {
+        .index = 2,
+        .name = "DISP3 FG",
+        .type = V4L2_OUTPUT_TYPE_ANALOG,
+        .audioset = 0,
+        .modulator = 0,
+        .std = V4L2_STD_UNKNOWN,
+        },
+       {
+        .index = 3,
+        .name = "DISP4 BG",
+        .type = V4L2_OUTPUT_TYPE_ANALOG,
+        .audioset = 0,
+        .modulator = 0,
+        .std = V4L2_STD_UNKNOWN,
+        },
+       {
+        .index = 4,
+        .name = "DISP4 BG - DI1",
+        .type = V4L2_OUTPUT_TYPE_ANALOG,
+        .audioset = 0,
+        .modulator = 0,
+        .std = V4L2_STD_UNKNOWN,
+        },
+       {
+        .index = 5,
+        .name = "DISP4 FG",
+        .type = V4L2_OUTPUT_TYPE_ANALOG,
+        .audioset = 0,
+        .modulator = 0,
+        .std = V4L2_STD_UNKNOWN,
+        },
+};
+
+static struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = {
+       {
+        .index = 0,
+        .name = "CSI IC MEM",
+        .type = V4L2_INPUT_TYPE_CAMERA,
+        .audioset = 0,
+        .tuner = 0,
+        .std = V4L2_STD_UNKNOWN,
+        .status = 0,
+        },
+       {
+        .index = 1,
+        .name = "CSI MEM",
+        .type = V4L2_INPUT_TYPE_CAMERA,
+        .audioset = 0,
+        .tuner = 0,
+        .std = V4L2_STD_UNKNOWN,
+        .status = V4L2_IN_ST_NO_POWER,
+        },
+};
+
+/*! List of TV input video formats supported. The video formats is corresponding
+ * to the v4l2_id in video_fmt_t.
+ * Currently, only PAL and NTSC is supported. Needs to be expanded in the
+ * future.
+ */
+typedef enum {
+       TV_NTSC = 0,            /*!< Locked on (M) NTSC video signal. */
+       TV_PAL,                 /*!< (B, G, H, I, N)PAL video signal. */
+       TV_NOT_LOCKED,          /*!< Not locked on a signal. */
+} video_fmt_idx;
+
+/*! Number of video standards supported (including 'not locked' signal). */
+#define TV_STD_MAX             (TV_NOT_LOCKED + 1)
+
+/*! Video format structure. */
+typedef struct {
+       int v4l2_id;            /*!< 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 active_top;         /*!< Active top. */
+       u16 active_left;        /*!< Active left. */
+} video_fmt_t;
+
+/*!
+ * Description of video formats supported.
+ *
+ *  PAL: raw=720x625, active=720x576.
+ *  NTSC: raw=720x525, active=720x480.
+ */
+static video_fmt_t video_fmts[] = {
+       {                       /*! NTSC */
+        .v4l2_id = V4L2_STD_NTSC,
+        .name = "NTSC",
+        .raw_width = 720,              /* SENS_FRM_WIDTH */
+        .raw_height = 525,             /* SENS_FRM_HEIGHT */
+        .active_width = 720,           /* ACT_FRM_WIDTH */
+        .active_height = 480,          /* ACT_FRM_HEIGHT */
+        .active_top = 13,
+        .active_left = 0,
+        },
+       {                       /*! (B, G, H, I, N) PAL */
+        .v4l2_id = V4L2_STD_PAL,
+        .name = "PAL",
+        .raw_width = 720,
+        .raw_height = 625,
+        .active_width = 720,
+        .active_height = 576,
+        .active_top = 0,
+        .active_left = 0,
+        },
+       {                       /*! Unlocked standard */
+        .v4l2_id = V4L2_STD_ALL,
+        .name = "Autodetect",
+        .raw_width = 720,
+        .raw_height = 625,
+        .active_width = 720,
+        .active_height = 576,
+        .active_top = 0,
+        .active_left = 0,
+        },
+};
+
+/*!* Standard index of TV. */
+static video_fmt_idx video_index = TV_NOT_LOCKED;
+
+static int mxc_v4l2_master_attach(struct v4l2_int_device *slave);
+static void mxc_v4l2_master_detach(struct v4l2_int_device *slave);
+static int start_preview(cam_data *cam);
+static int stop_preview(cam_data *cam);
+
+/*! Information about this driver. */
+static struct v4l2_int_master mxc_v4l2_master = {
+       .attach = mxc_v4l2_master_attach,
+       .detach = mxc_v4l2_master_detach,
+};
+
+/***************************************************************************
+ * Functions for handling Frame buffers.
+ **************************************************************************/
+
+/*!
+ * Free frame buffers
+ *
+ * @param cam      Structure cam_data *
+ *
+ * @return status  0 success.
+ */
+static int mxc_free_frame_buf(cam_data *cam)
+{
+       int i;
+
+       pr_debug("MVC: In mxc_free_frame_buf\n");
+
+       for (i = 0; i < FRAME_NUM; i++) {
+               if (cam->frame[i].vaddress != 0) {
+                       dma_free_coherent(0, cam->frame[i].buffer.length,
+                                         cam->frame[i].vaddress,
+                                         cam->frame[i].paddress);
+                       cam->frame[i].vaddress = 0;
+               }
+       }
+
+       return 0;
+}
+
+/*!
+ * Allocate frame buffers
+ *
+ * @param cam      Structure cam_data*
+ * @param count    int number of buffer need to allocated
+ *
+ * @return status  -0 Successfully allocated a buffer, -ENOBUFS        failed.
+ */
+static int mxc_allocate_frame_buf(cam_data *cam, int count)
+{
+       int i;
+
+       pr_debug("In MVC:mxc_allocate_frame_buf - size=%d\n",
+               cam->v2f.fmt.pix.sizeimage);
+
+       for (i = 0; i < count; i++) {
+               cam->frame[i].vaddress =
+                   dma_alloc_coherent(0,
+                                      PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+                                      &cam->frame[i].paddress,
+                                      GFP_DMA | GFP_KERNEL);
+               if (cam->frame[i].vaddress == 0) {
+                       pr_err("ERROR: v4l2 capture: "
+                               "mxc_allocate_frame_buf failed.\n");
+                       mxc_free_frame_buf(cam);
+                       return -ENOBUFS;
+               }
+               cam->frame[i].buffer.index = i;
+               cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
+               cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               cam->frame[i].buffer.length =
+                   PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+               cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP;
+               cam->frame[i].buffer.m.offset = cam->frame[i].paddress;
+               cam->frame[i].index = i;
+       }
+
+       return 0;
+}
+
+/*!
+ * Free frame buffers status
+ *
+ * @param cam    Structure cam_data *
+ *
+ * @return none
+ */
+static void mxc_free_frames(cam_data *cam)
+{
+       int i;
+
+       pr_debug("In MVC:mxc_free_frames\n");
+
+       for (i = 0; i < FRAME_NUM; i++)
+               cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
+
+       cam->enc_counter = 0;
+       INIT_LIST_HEAD(&cam->ready_q);
+       INIT_LIST_HEAD(&cam->working_q);
+       INIT_LIST_HEAD(&cam->done_q);
+}
+
+/*!
+ * Return the buffer status
+ *
+ * @param cam     Structure cam_data *
+ * @param buf     Structure v4l2_buffer *
+ *
+ * @return status  0 success, EINVAL failed.
+ */
+static int mxc_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf)
+{
+       pr_debug("In MVC:mxc_v4l2_buffer_status\n");
+
+       if (buf->index < 0 || buf->index >= FRAME_NUM) {
+               pr_err("ERROR: v4l2 capture: mxc_v4l2_buffer_status buffers "
+                      "not allocated\n");
+               return -EINVAL;
+       }
+
+       memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf));
+       return 0;
+}
+
+static int mxc_v4l2_release_bufs(cam_data *cam)
+{
+       pr_debug("In MVC:mxc_v4l2_release_bufs\n");
+       return 0;
+}
+
+static int mxc_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf)
+{
+       pr_debug("In MVC:mxc_v4l2_prepare_bufs\n");
+
+       if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length <
+                       PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage)) {
+               pr_err("ERROR: v4l2 capture: mxc_v4l2_prepare_bufs buffers "
+                       "not allocated,index=%d, length=%d\n", buf->index,
+                       buf->length);
+               return -EINVAL;
+       }
+
+       cam->frame[buf->index].buffer.index = buf->index;
+       cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED;
+       cam->frame[buf->index].buffer.length = buf->length;
+       cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress
+               = buf->m.offset;
+       cam->frame[buf->index].buffer.type = buf->type;
+       cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR;
+       cam->frame[buf->index].index = buf->index;
+
+       return 0;
+}
+
+/***************************************************************************
+ * Functions for handling the video stream.
+ **************************************************************************/
+
+/*!
+ * Indicates whether the palette is supported.
+ *
+ * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32
+ *
+ * @return 0 if failed
+ */
+static inline int valid_mode(u32 palette)
+{
+       return ((palette == V4L2_PIX_FMT_RGB565) ||
+               (palette == V4L2_PIX_FMT_BGR24) ||
+               (palette == V4L2_PIX_FMT_RGB24) ||
+               (palette == V4L2_PIX_FMT_BGR32) ||
+               (palette == V4L2_PIX_FMT_RGB32) ||
+               (palette == V4L2_PIX_FMT_YUV422P) ||
+               (palette == V4L2_PIX_FMT_UYVY) ||
+               (palette == V4L2_PIX_FMT_YUYV) ||
+               (palette == V4L2_PIX_FMT_YUV420) ||
+               (palette == V4L2_PIX_FMT_YVU420) ||
+               (palette == V4L2_PIX_FMT_NV12));
+}
+
+/*!
+ * Start the encoder job
+ *
+ * @param cam      structure cam_data *
+ *
+ * @return status  0 Success
+ */
+static int mxc_streamon(cam_data *cam)
+{
+       struct mxc_v4l_frame *frame;
+       unsigned long lock_flags;
+       int err = 0;
+
+       pr_debug("In MVC:mxc_streamon\n");
+
+       if (NULL == cam) {
+               pr_err("ERROR! cam parameter is NULL\n");
+               return -1;
+       }
+
+       if (cam->capture_on) {
+               pr_err("ERROR: v4l2 capture: Capture stream has been turned "
+                      " on\n");
+               return -1;
+       }
+
+       if (list_empty(&cam->ready_q)) {
+               pr_err("ERROR: v4l2 capture: mxc_streamon buffer has not been "
+                       "queued yet\n");
+               return -EINVAL;
+       }
+       if (cam->enc_update_eba &&
+               cam->ready_q.prev == cam->ready_q.next) {
+               pr_err("ERROR: v4l2 capture: mxc_streamon buffer need "
+                      "ping pong at least two buffers\n");
+               return -EINVAL;
+       }
+
+       cam->capture_pid = current->pid;
+
+       if (cam->overlay_on == true)
+               stop_preview(cam);
+
+       if (cam->enc_enable) {
+               err = cam->enc_enable(cam);
+               if (err != 0)
+                       return err;
+       }
+
+       spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
+       cam->ping_pong_csi = 0;
+       cam->local_buf_num = 0;
+       if (cam->enc_update_eba) {
+               frame =
+                   list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
+               list_del(cam->ready_q.next);
+               list_add_tail(&frame->queue, &cam->working_q);
+               frame->ipu_buf_num = cam->ping_pong_csi;
+               err = cam->enc_update_eba(cam, frame->buffer.m.offset);
+
+               frame =
+                   list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
+               list_del(cam->ready_q.next);
+               list_add_tail(&frame->queue, &cam->working_q);
+               frame->ipu_buf_num = cam->ping_pong_csi;
+               err |= cam->enc_update_eba(cam, frame->buffer.m.offset);
+               spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
+       } else {
+               spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
+               return -EINVAL;
+       }
+
+       if (cam->overlay_on == true)
+               start_preview(cam);
+
+       if (cam->enc_enable_csi) {
+               err = cam->enc_enable_csi(cam);
+               if (err != 0)
+                       return err;
+       }
+
+       cam->capture_on = true;
+
+       return err;
+}
+
+/*!
+ * Shut down the encoder job
+ *
+ * @param cam      structure cam_data *
+ *
+ * @return status  0 Success
+ */
+static int mxc_streamoff(cam_data *cam)
+{
+       int err = 0;
+
+       pr_debug("In MVC:mxc_streamoff\n");
+
+       if (cam->capture_on == false)
+               return 0;
+
+       /* For both CSI--MEM and CSI--IC--MEM
+        * 1. wait for idmac eof
+        * 2. disable csi first
+        * 3. disable idmac
+        * 4. disable smfc (CSI--MEM channel)
+        */
+       if (mxc_capture_inputs[cam->current_input].name != NULL) {
+               if (cam->enc_disable_csi) {
+                       err = cam->enc_disable_csi(cam);
+                       if (err != 0)
+                               return err;
+               }
+               if (cam->enc_disable) {
+                       err = cam->enc_disable(cam);
+                       if (err != 0)
+                               return err;
+               }
+       }
+
+       mxc_free_frames(cam);
+       mxc_capture_inputs[cam->current_input].status |= V4L2_IN_ST_NO_POWER;
+       cam->capture_on = false;
+       return err;
+}
+
+/*!
+ * Valid and adjust the overlay window size, position
+ *
+ * @param cam      structure cam_data *
+ * @param win      struct v4l2_window  *
+ *
+ * @return 0
+ */
+static int verify_preview(cam_data *cam, struct v4l2_window *win)
+{
+       int i = 0, width_bound = 0, height_bound = 0;
+       int *width, *height;
+       unsigned int ipu_ch = CHAN_NONE;
+       struct fb_info *bg_fbi = NULL, *fbi = NULL;
+       bool foregound_fb = false;
+       mm_segment_t old_fs;
+
+       pr_debug("In MVC: verify_preview\n");
+
+       do {
+               fbi = (struct fb_info *)registered_fb[i];
+               if (fbi == NULL) {
+                       pr_err("ERROR: verify_preview frame buffer NULL.\n");
+                       return -1;
+               }
+
+               /* Which DI supports 2 layers? */
+               if (((strncmp(fbi->fix.id, "DISP3 BG", 8) == 0) &&
+                                       (cam->output < 3)) ||
+                   ((strncmp(fbi->fix.id, "DISP4 BG", 8) == 0) &&
+                                       (cam->output >= 3))) {
+                       if (fbi->fbops->fb_ioctl) {
+                               old_fs = get_fs();
+                               set_fs(KERNEL_DS);
+                               fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN,
+                                               (unsigned long)&ipu_ch);
+                               set_fs(old_fs);
+                       }
+                       if (ipu_ch == MEM_BG_SYNC) {
+                               bg_fbi = fbi;
+                               pr_debug("Found background frame buffer.\n");
+                       }
+               }
+
+               /* Found the frame buffer to preview on. */
+               if (strcmp(fbi->fix.id,
+                           mxc_capture_outputs[cam->output].name) == 0) {
+                       if (((strcmp(fbi->fix.id, "DISP3 FG") == 0) &&
+                                               (cam->output < 3)) ||
+                           ((strcmp(fbi->fix.id, "DISP4 FG") == 0) &&
+                                               (cam->output >= 3)))
+                               foregound_fb = true;
+
+                       cam->overlay_fb = fbi;
+                       break;
+               }
+       } while (++i < FB_MAX);
+
+       if (foregound_fb) {
+               width_bound = bg_fbi->var.xres;
+               height_bound = bg_fbi->var.yres;
+
+               if (win->w.width + win->w.left > bg_fbi->var.xres ||
+                   win->w.height + win->w.top > bg_fbi->var.yres) {
+                       pr_err("ERROR: FG window position exceeds.\n");
+                       return -1;
+               }
+       } else {
+               /* 4 bytes alignment for BG */
+               width_bound = cam->overlay_fb->var.xres;
+               height_bound = cam->overlay_fb->var.yres;
+
+               if (cam->overlay_fb->var.bits_per_pixel == 24)
+                       win->w.left -= win->w.left % 4;
+               else if (cam->overlay_fb->var.bits_per_pixel == 16)
+                       win->w.left -= win->w.left % 2;
+
+               if (win->w.width + win->w.left > cam->overlay_fb->var.xres)
+                       win->w.width = cam->overlay_fb->var.xres - win->w.left;
+               if (win->w.height + win->w.top > cam->overlay_fb->var.yres)
+                       win->w.height = cam->overlay_fb->var.yres - win->w.top;
+       }
+
+       /* stride line limitation */
+       win->w.height -= win->w.height % 8;
+       win->w.width -= win->w.width % 8;
+
+       if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+               height = &win->w.width;
+               width = &win->w.height;
+       } else {
+               width = &win->w.width;
+               height = &win->w.height;
+       }
+
+       if (*width == 0 || *height == 0) {
+               pr_err("ERROR: v4l2 capture: width or height"
+                       " too small.\n");
+               return -EINVAL;
+       }
+
+       if ((cam->crop_bounds.width / *width > 8) ||
+           ((cam->crop_bounds.width / *width == 8) &&
+            (cam->crop_bounds.width % *width))) {
+               *width = cam->crop_bounds.width / 8;
+               if (*width % 8)
+                       *width += 8 - *width % 8;
+               if (*width + win->w.left > width_bound) {
+                       pr_err("ERROR: v4l2 capture: width exceeds "
+                               "resize limit.\n");
+                       return -1;
+               }
+               pr_err("ERROR: v4l2 capture: width exceeds limit. "
+                       "Resize to %d.\n",
+                       *width);
+       }
+
+       if ((cam->crop_bounds.height / *height > 8) ||
+           ((cam->crop_bounds.height / *height == 8) &&
+            (cam->crop_bounds.height % *height))) {
+               *height = cam->crop_bounds.height / 8;
+               if (*height % 8)
+                       *height += 8 - *height % 8;
+               if (*height + win->w.top > height_bound) {
+                       pr_err("ERROR: v4l2 capture: height exceeds "
+                               "resize limit.\n");
+                       return -1;
+               }
+               pr_err("ERROR: v4l2 capture: height exceeds limit "
+                       "resize to %d.\n",
+                       *height);
+       }
+
+       return 0;
+}
+
+/*!
+ * start the viewfinder job
+ *
+ * @param cam      structure cam_data *
+ *
+ * @return status  0 Success
+ */
+static int start_preview(cam_data *cam)
+{
+       int err = 0;
+
+       pr_debug("MVC: start_preview\n");
+
+       if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY)
+       #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+               err = prp_vf_sdc_select(cam);
+       #else
+               err = foreground_sdc_select(cam);
+       #endif
+       else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY)
+       #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+               err = prp_vf_sdc_select_bg(cam);
+       #else
+               err = bg_overlay_sdc_select(cam);
+       #endif
+       if (err != 0)
+               return err;
+
+       if (cam->vf_start_sdc) {
+               err = cam->vf_start_sdc(cam);
+               if (err != 0)
+                       return err;
+       }
+
+       if (cam->vf_enable_csi)
+               err = cam->vf_enable_csi(cam);
+
+       pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+                __func__,
+                cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+       pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+                __func__,
+                cam->crop_bounds.width, cam->crop_bounds.height);
+       pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+                __func__,
+                cam->crop_defrect.width, cam->crop_defrect.height);
+       pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+                __func__,
+                cam->crop_current.width, cam->crop_current.height);
+
+       return err;
+}
+
+/*!
+ * shut down the viewfinder job
+ *
+ * @param cam      structure cam_data *
+ *
+ * @return status  0 Success
+ */
+static int stop_preview(cam_data *cam)
+{
+       int err = 0;
+
+       if (cam->vf_disable_csi) {
+               err = cam->vf_disable_csi(cam);
+               if (err != 0)
+                       return err;
+       }
+
+       if (cam->vf_stop_sdc) {
+               err = cam->vf_stop_sdc(cam);
+               if (err != 0)
+                       return err;
+       }
+
+       if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY)
+       #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+               err = prp_vf_sdc_deselect(cam);
+       #else
+               err = foreground_sdc_deselect(cam);
+       #endif
+       else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY)
+       #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+               err = prp_vf_sdc_deselect_bg(cam);
+       #else
+               err = bg_overlay_sdc_deselect(cam);
+       #endif
+
+       return err;
+}
+
+/***************************************************************************
+ * VIDIOC Functions.
+ **************************************************************************/
+
+/*!
+ * V4L2 - mxc_v4l2_g_fmt function
+ *
+ * @param cam         structure cam_data *
+ *
+ * @param f           structure v4l2_format *
+ *
+ * @return  status    0 success, EINVAL failed
+ */
+static int mxc_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f)
+{
+       int retval = 0;
+
+       pr_debug("In MVC: mxc_v4l2_g_fmt type=%d\n", f->type);
+
+       switch (f->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               pr_debug("   type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+               f->fmt.pix = cam->v2f.fmt.pix;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               pr_debug("   type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
+               f->fmt.win = cam->win;
+               break;
+       default:
+               pr_debug("   type is invalid\n");
+               retval = -EINVAL;
+       }
+
+       pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+                __func__,
+                cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+       pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+                __func__,
+                cam->crop_bounds.width, cam->crop_bounds.height);
+       pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+                __func__,
+                cam->crop_defrect.width, cam->crop_defrect.height);
+       pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+                __func__,
+                cam->crop_current.width, cam->crop_current.height);
+
+       return retval;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_s_fmt function
+ *
+ * @param cam         structure cam_data *
+ *
+ * @param f           structure v4l2_format *
+ *
+ * @return  status    0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
+{
+       int retval = 0;
+       int size = 0;
+       int bytesperline = 0;
+       int *width, *height;
+
+       pr_debug("In MVC: mxc_v4l2_s_fmt\n");
+
+       switch (f->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               pr_debug("   type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+               if (!valid_mode(f->fmt.pix.pixelformat)) {
+                       pr_err("ERROR: v4l2 capture: mxc_v4l2_s_fmt: format "
+                              "not supported\n");
+                       return -EINVAL;
+               }
+
+               /*
+                * Force the capture window resolution to be crop bounds
+                * for CSI MEM input mode.
+                */
+               if (strcmp(mxc_capture_inputs[cam->current_input].name,
+                          "CSI MEM") == 0) {
+                       f->fmt.pix.width = cam->crop_current.width;
+                       f->fmt.pix.height = cam->crop_current.height;
+               }
+
+               if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+                       height = &f->fmt.pix.width;
+                       width = &f->fmt.pix.height;
+               } else {
+                       width = &f->fmt.pix.width;
+                       height = &f->fmt.pix.height;
+               }
+
+               /* stride line limitation */
+               *width -= *width % 8;
+               *height -= *height % 8;
+
+               if (*width == 0 || *height == 0) {
+                       pr_err("ERROR: v4l2 capture: width or height"
+                               " too small.\n");
+                       return -EINVAL;
+               }
+
+               if ((cam->crop_current.width / *width > 8) ||
+                   ((cam->crop_current.width / *width == 8) &&
+                    (cam->crop_current.width % *width))) {
+                       *width = cam->crop_current.width / 8;
+                       if (*width % 8)
+                               *width += 8 - *width % 8;
+                       pr_err("ERROR: v4l2 capture: width exceeds limit "
+                               "resize to %d.\n",
+                              *width);
+               }
+
+               if ((cam->crop_current.height / *height > 8) ||
+                   ((cam->crop_current.height / *height == 8) &&
+                    (cam->crop_current.height % *height))) {
+                       *height = cam->crop_current.height / 8;
+                       if (*height % 8)
+                               *height += 8 - *height % 8;
+                       pr_err("ERROR: v4l2 capture: height exceeds limit "
+                              "resize to %d.\n",
+                              *height);
+               }
+
+               switch (f->fmt.pix.pixelformat) {
+               case V4L2_PIX_FMT_RGB565:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 2;
+                       bytesperline = f->fmt.pix.width * 2;
+                       break;
+               case V4L2_PIX_FMT_BGR24:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 3;
+                       bytesperline = f->fmt.pix.width * 3;
+                       break;
+               case V4L2_PIX_FMT_RGB24:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 3;
+                       bytesperline = f->fmt.pix.width * 3;
+                       break;
+               case V4L2_PIX_FMT_BGR32:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 4;
+                       bytesperline = f->fmt.pix.width * 4;
+                       break;
+               case V4L2_PIX_FMT_RGB32:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 4;
+                       bytesperline = f->fmt.pix.width * 4;
+                       break;
+               case V4L2_PIX_FMT_YUV422P:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 2;
+                       bytesperline = f->fmt.pix.width;
+                       break;
+               case V4L2_PIX_FMT_UYVY:
+               case V4L2_PIX_FMT_YUYV:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 2;
+                       bytesperline = f->fmt.pix.width * 2;
+                       break;
+               case V4L2_PIX_FMT_YUV420:
+               case V4L2_PIX_FMT_YVU420:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
+                       bytesperline = f->fmt.pix.width;
+                       break;
+               case V4L2_PIX_FMT_NV12:
+                       size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
+                       bytesperline = f->fmt.pix.width;
+                       break;
+               default:
+                       break;
+               }
+
+               if (f->fmt.pix.bytesperline < bytesperline)
+                       f->fmt.pix.bytesperline = bytesperline;
+               else
+                       bytesperline = f->fmt.pix.bytesperline;
+
+               if (f->fmt.pix.sizeimage < size)
+                       f->fmt.pix.sizeimage = size;
+               else
+                       size = f->fmt.pix.sizeimage;
+
+               cam->v2f.fmt.pix = f->fmt.pix;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               pr_debug("   type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
+               retval = verify_preview(cam, &f->fmt.win);
+               cam->win = f->fmt.win;
+               break;
+       default:
+               retval = -EINVAL;
+       }
+
+       pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+                __func__,
+                cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+       pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+                __func__,
+                cam->crop_bounds.width, cam->crop_bounds.height);
+       pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+                __func__,
+                cam->crop_defrect.width, cam->crop_defrect.height);
+       pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+                __func__,
+                cam->crop_current.width, cam->crop_current.height);
+
+       return retval;
+}
+
+/*!
+ * get control param
+ *
+ * @param cam         structure cam_data *
+ *
+ * @param c           structure v4l2_control *
+ *
+ * @return  status    0 success, EINVAL failed
+ */
+static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
+{
+       int status = 0;
+
+       pr_debug("In MVC:mxc_v4l2_g_ctrl\n");
+
+       /* probably don't need to store the values that can be retrieved,
+        * locally, but they are for now. */
+       switch (c->id) {
+       case V4L2_CID_HFLIP:
+               /* This is handled in the ipu. */
+               if (cam->rotation == IPU_ROTATE_HORIZ_FLIP)
+                       c->value = 1;
+               break;
+       case V4L2_CID_VFLIP:
+               /* This is handled in the ipu. */
+               if (cam->rotation == IPU_ROTATE_VERT_FLIP)
+                       c->value = 1;
+               break;
+       case V4L2_CID_MXC_ROT:
+               /* This is handled in the ipu. */
+               c->value = cam->rotation;
+               break;
+       case V4L2_CID_BRIGHTNESS:
+               if (cam->sensor) {
+                       c->value = cam->bright;
+                       status = vidioc_int_g_ctrl(cam->sensor, c);
+                       cam->bright = c->value;
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       status = -ENODEV;
+               }
+               break;
+       case V4L2_CID_HUE:
+               if (cam->sensor) {
+                       c->value = cam->hue;
+                       status = vidioc_int_g_ctrl(cam->sensor, c);
+                       cam->hue = c->value;
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       status = -ENODEV;
+               }
+               break;
+       case V4L2_CID_CONTRAST:
+               if (cam->sensor) {
+                       c->value = cam->contrast;
+                       status = vidioc_int_g_ctrl(cam->sensor, c);
+                       cam->contrast = c->value;
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       status = -ENODEV;
+               }
+               break;
+       case V4L2_CID_SATURATION:
+               if (cam->sensor) {
+                       c->value = cam->saturation;
+                       status = vidioc_int_g_ctrl(cam->sensor, c);
+                       cam->saturation = c->value;
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       status = -ENODEV;
+               }
+               break;
+       case V4L2_CID_RED_BALANCE:
+               if (cam->sensor) {
+                       c->value = cam->red;
+                       status = vidioc_int_g_ctrl(cam->sensor, c);
+                       cam->red = c->value;
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       status = -ENODEV;
+               }
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               if (cam->sensor) {
+                       c->value = cam->blue;
+                       status = vidioc_int_g_ctrl(cam->sensor, c);
+                       cam->blue = c->value;
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       status = -ENODEV;
+               }
+               break;
+       case V4L2_CID_BLACK_LEVEL:
+               if (cam->sensor) {
+                       c->value = cam->ae_mode;
+                       status = vidioc_int_g_ctrl(cam->sensor, c);
+                       cam->ae_mode = c->value;
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       status = -ENODEV;
+               }
+               break;
+       default:
+               pr_err("ERROR: v4l2 capture: unsupported ioctrl!\n");
+       }
+
+       return status;
+}
+
+/*!
+ * V4L2 - set_control function
+ *          V4L2_CID_PRIVATE_BASE is the extention for IPU preprocessing.
+ *          0 for normal operation
+ *          1 for vertical flip
+ *          2 for horizontal flip
+ *          3 for horizontal and vertical flip
+ *          4 for 90 degree rotation
+ * @param cam         structure cam_data *
+ *
+ * @param c           structure v4l2_control *
+ *
+ * @return  status    0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
+{
+       int i, ret = 0;
+       int tmp_rotation = IPU_ROTATE_NONE;
+       struct sensor_data *sensor_data;
+
+       pr_debug("In MVC:mxc_v4l2_s_ctrl\n");
+
+       switch (c->id) {
+       case V4L2_CID_HFLIP:
+               /* This is done by the IPU */
+               if (c->value == 1) {
+                       if ((cam->rotation != IPU_ROTATE_VERT_FLIP) &&
+                           (cam->rotation != IPU_ROTATE_180))
+                               cam->rotation = IPU_ROTATE_HORIZ_FLIP;
+                       else
+                               cam->rotation = IPU_ROTATE_180;
+               } else {
+                       if (cam->rotation == IPU_ROTATE_HORIZ_FLIP)
+                               cam->rotation = IPU_ROTATE_NONE;
+                       if (cam->rotation == IPU_ROTATE_180)
+                               cam->rotation = IPU_ROTATE_VERT_FLIP;
+               }
+               break;
+       case V4L2_CID_VFLIP:
+               /* This is done by the IPU */
+               if (c->value == 1) {
+                       if ((cam->rotation != IPU_ROTATE_HORIZ_FLIP) &&
+                           (cam->rotation != IPU_ROTATE_180))
+                               cam->rotation = IPU_ROTATE_VERT_FLIP;
+                       else
+                               cam->rotation = IPU_ROTATE_180;
+               } else {
+                       if (cam->rotation == IPU_ROTATE_VERT_FLIP)
+                               cam->rotation = IPU_ROTATE_NONE;
+                       if (cam->rotation == IPU_ROTATE_180)
+                               cam->rotation = IPU_ROTATE_HORIZ_FLIP;
+               }
+               break;
+       case V4L2_CID_MXC_ROT:
+       case V4L2_CID_MXC_VF_ROT:
+               /* This is done by the IPU */
+               switch (c->value) {
+               case V4L2_MXC_ROTATE_NONE:
+                       tmp_rotation = IPU_ROTATE_NONE;
+                       break;
+               case V4L2_MXC_ROTATE_VERT_FLIP:
+                       tmp_rotation = IPU_ROTATE_VERT_FLIP;
+                       break;
+               case V4L2_MXC_ROTATE_HORIZ_FLIP:
+                       tmp_rotation = IPU_ROTATE_HORIZ_FLIP;
+                       break;
+               case V4L2_MXC_ROTATE_180:
+                       tmp_rotation = IPU_ROTATE_180;
+                       break;
+               case V4L2_MXC_ROTATE_90_RIGHT:
+                       tmp_rotation = IPU_ROTATE_90_RIGHT;
+                       break;
+               case V4L2_MXC_ROTATE_90_RIGHT_VFLIP:
+                       tmp_rotation = IPU_ROTATE_90_RIGHT_VFLIP;
+                       break;
+               case V4L2_MXC_ROTATE_90_RIGHT_HFLIP:
+                       tmp_rotation = IPU_ROTATE_90_RIGHT_HFLIP;
+                       break;
+               case V4L2_MXC_ROTATE_90_LEFT:
+                       tmp_rotation = IPU_ROTATE_90_LEFT;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+               if (c->id == V4L2_CID_MXC_VF_ROT)
+                       cam->vf_rotation = tmp_rotation;
+               else
+                       cam->rotation = tmp_rotation;
+               #else
+                       cam->rotation = tmp_rotation;
+               #endif
+
+               break;
+       case V4L2_CID_HUE:
+               if (cam->sensor) {
+                       cam->hue = c->value;
+                       ret = vidioc_int_s_ctrl(cam->sensor, c);
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       ret = -ENODEV;
+               }
+               break;
+       case V4L2_CID_CONTRAST:
+               if (cam->sensor) {
+                       cam->contrast = c->value;
+                       ret = vidioc_int_s_ctrl(cam->sensor, c);
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       ret = -ENODEV;
+               }
+               break;
+       case V4L2_CID_BRIGHTNESS:
+               if (cam->sensor) {
+                       cam->bright = c->value;
+                       ret = vidioc_int_s_ctrl(cam->sensor, c);
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       ret = -ENODEV;
+               }
+               break;
+       case V4L2_CID_SATURATION:
+               if (cam->sensor) {
+                       cam->saturation = c->value;
+                       ret = vidioc_int_s_ctrl(cam->sensor, c);
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       ret = -ENODEV;
+               }
+               break;
+       case V4L2_CID_RED_BALANCE:
+               if (cam->sensor) {
+                       cam->red = c->value;
+                       ret = vidioc_int_s_ctrl(cam->sensor, c);
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       ret = -ENODEV;
+               }
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               if (cam->sensor) {
+                       cam->blue = c->value;
+                       ret = vidioc_int_s_ctrl(cam->sensor, c);
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       ret = -ENODEV;
+               }
+               break;
+       case V4L2_CID_EXPOSURE:
+               if (cam->sensor) {
+                       cam->ae_mode = c->value;
+                       ret = vidioc_int_s_ctrl(cam->sensor, c);
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       ret = -ENODEV;
+               }
+               break;
+       case V4L2_CID_MXC_FLASH:
+#ifdef CONFIG_MXC_IPU_V1
+               ipu_csi_flash_strobe(true);
+#endif
+               break;
+       case V4L2_CID_MXC_SWITCH_CAM:
+               if (cam->sensor == cam->all_sensors[c->value])
+                       break;
+
+               /* power down other cameraes before enable new one */
+               for (i = 0; i < cam->sensor_index; i++) {
+                       if (i != c->value) {
+                               vidioc_int_dev_exit(cam->all_sensors[i]);
+                               vidioc_int_s_power(cam->all_sensors[i], 0);
+                               if (cam->mclk_on[cam->mclk_source]) {
+                                       ipu_csi_enable_mclk_if(cam->ipu,
+                                                       CSI_MCLK_I2C,
+                                                       cam->mclk_source,
+                                                       false, false);
+                                       cam->mclk_on[cam->mclk_source] =
+                                                               false;
+                               }
+                       }
+               }
+               sensor_data = cam->all_sensors[c->value]->priv;
+               if (sensor_data->io_init)
+                       sensor_data->io_init();
+               cam->sensor = cam->all_sensors[c->value];
+               cam->mclk_source = sensor_data->mclk_source;
+               ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
+                                      cam->mclk_source, true, true);
+               cam->mclk_on[cam->mclk_source] = true;
+               vidioc_int_s_power(cam->sensor, 1);
+               vidioc_int_dev_init(cam->sensor);
+               break;
+       default:
+               pr_debug("   default case\n");
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_s_param function
+ * Allows setting of capturemode and frame rate.
+ *
+ * @param cam         structure cam_data *
+ * @param parm        structure v4l2_streamparm *
+ *
+ * @return  status    0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
+{
+       struct v4l2_ifparm ifparm;
+       struct v4l2_format cam_fmt;
+       struct v4l2_streamparm currentparm;
+       ipu_csi_signal_cfg_t csi_param;
+       u32 current_fps, parm_fps;
+       int err = 0;
+
+       pr_debug("In mxc_v4l2_s_param\n");
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               pr_err(KERN_ERR "mxc_v4l2_s_param invalid type\n");
+               return -EINVAL;
+       }
+
+       /* Stop the viewfinder */
+       if (cam->overlay_on == true)
+               stop_preview(cam);
+
+       currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       /* First check that this device can support the changes requested. */
+       err = vidioc_int_g_parm(cam->sensor, &currentparm);
+       if (err) {
+               pr_err("%s: vidioc_int_g_parm returned an error %d\n",
+                       __func__, err);
+               goto exit;
+       }
+
+       current_fps = currentparm.parm.capture.timeperframe.denominator
+                       / currentparm.parm.capture.timeperframe.numerator;
+       parm_fps = parm->parm.capture.timeperframe.denominator
+                       / parm->parm.capture.timeperframe.numerator;
+
+       pr_debug("   Current capabilities are %x\n",
+                       currentparm.parm.capture.capability);
+       pr_debug("   Current capturemode is %d  change to %d\n",
+                       currentparm.parm.capture.capturemode,
+                       parm->parm.capture.capturemode);
+       pr_debug("   Current framerate is %d  change to %d\n",
+                       current_fps, parm_fps);
+
+       /* This will change any camera settings needed. */
+       err = vidioc_int_s_parm(cam->sensor, parm);
+       if (err) {
+               pr_err("%s: vidioc_int_s_parm returned an error %d\n",
+                       __func__, err);
+               goto exit;
+       }
+
+       /* If resolution changed, need to re-program the CSI */
+       /* Get new values. */
+       vidioc_int_g_ifparm(cam->sensor, &ifparm);
+
+       csi_param.data_width = 0;
+       csi_param.clk_mode = 0;
+       csi_param.ext_vsync = 0;
+       csi_param.Vsync_pol = 0;
+       csi_param.Hsync_pol = 0;
+       csi_param.pixclk_pol = 0;
+       csi_param.data_pol = 0;
+       csi_param.sens_clksrc = 0;
+       csi_param.pack_tight = 0;
+       csi_param.force_eof = 0;
+       csi_param.data_en_pol = 0;
+       csi_param.data_fmt = 0;
+       csi_param.csi = cam->csi;
+       csi_param.mclk = 0;
+
+       pr_debug("   clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr);
+       if (ifparm.u.bt656.clock_curr == 0)
+               csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
+       else
+               csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
+
+       csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
+
+       if (ifparm.u.bt656.mode == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT) {
+               csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
+       } else if (ifparm.u.bt656.mode
+                               == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT) {
+               csi_param.data_width = IPU_CSI_DATA_WIDTH_10;
+       } else {
+               csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
+       }
+
+       csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv;
+       csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv;
+       csi_param.ext_vsync = ifparm.u.bt656.bt_sync_correct;
+
+       /* if the capturemode changed, the size bounds will have changed. */
+       cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
+       pr_debug("   g_fmt_cap returns widthxheight of input as %d x %d\n",
+                       cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
+
+       csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
+
+       cam->crop_bounds.top = cam->crop_bounds.left = 0;
+       cam->crop_bounds.width = cam_fmt.fmt.pix.width;
+       cam->crop_bounds.height = cam_fmt.fmt.pix.height;
+
+       /*
+        * Set the default current cropped resolution to be the same with
+        * the cropping boundary(except for tvin module).
+        */
+       if (cam->device_type != 1) {
+               cam->crop_current.width = cam->crop_bounds.width;
+               cam->crop_current.height = cam->crop_bounds.height;
+       }
+
+       /* This essentially loses the data at the left and bottom of the image
+        * giving a digital zoom image, if crop_current is less than the full
+        * size of the image. */
+       ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
+                               cam->crop_current.height, cam->csi);
+       ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
+                              cam->crop_current.top,
+                              cam->csi);
+       ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width,
+                              cam->crop_bounds.height,
+                              cam_fmt.fmt.pix.pixelformat, csi_param);
+
+
+exit:
+       if (cam->overlay_on == true)
+               start_preview(cam);
+
+       return err;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_s_std function
+ *
+ * Sets the TV standard to be used.
+ *
+ * @param cam        structure cam_data *
+ * @param parm       structure v4l2_streamparm *
+ *
+ * @return  status    0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_std(cam_data *cam, v4l2_std_id e)
+{
+       pr_debug("In mxc_v4l2_s_std %Lx\n", e);
+
+       if (e == V4L2_STD_PAL) {
+               pr_debug("   Setting standard to PAL %Lx\n", V4L2_STD_PAL);
+               cam->standard.id = V4L2_STD_PAL;
+               video_index = TV_PAL;
+       } else if (e == V4L2_STD_NTSC) {
+               pr_debug("   Setting standard to NTSC %Lx\n",
+                               V4L2_STD_NTSC);
+               /* Get rid of the white dot line in NTSC signal input */
+               cam->standard.id = V4L2_STD_NTSC;
+               video_index = TV_NTSC;
+       } else {
+               cam->standard.id = V4L2_STD_ALL;
+               video_index = TV_NOT_LOCKED;
+               pr_err("ERROR: unrecognized std! %Lx (PAL=%Lx, NTSC=%Lx\n",
+                       e, V4L2_STD_PAL, V4L2_STD_NTSC);
+       }
+
+       cam->standard.index = video_index;
+       strcpy(cam->standard.name, video_fmts[video_index].name);
+       cam->crop_bounds.width = video_fmts[video_index].raw_width;
+       cam->crop_bounds.height = video_fmts[video_index].raw_height;
+       cam->crop_current.width = video_fmts[video_index].active_width;
+       cam->crop_current.height = video_fmts[video_index].active_height;
+       cam->crop_current.top = video_fmts[video_index].active_top;
+       cam->crop_current.left = video_fmts[video_index].active_left;
+
+       return 0;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_g_std function
+ *
+ * Gets the TV standard from the TV input device.
+ *
+ * @param cam        structure cam_data *
+ *
+ * @param e          structure v4l2_streamparm *
+ *
+ * @return  status    0 success, EINVAL failed
+ */
+static int mxc_v4l2_g_std(cam_data *cam, v4l2_std_id *e)
+{
+       struct v4l2_format tv_fmt;
+
+       pr_debug("In mxc_v4l2_g_std\n");
+
+       if (cam->device_type == 1) {
+               /* Use this function to get what the TV-In device detects the
+                * format to be. pixelformat is used to return the std value
+                * since the interface has no vidioc_g_std.*/
+               tv_fmt.type = V4L2_BUF_TYPE_PRIVATE;
+               vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt);
+
+               /* If the TV-in automatically detects the standard, then if it
+                * changes, the settings need to change. */
+               if (cam->standard_autodetect) {
+                       if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) {
+                               pr_debug("MVC: mxc_v4l2_g_std: "
+                                       "Changing standard\n");
+                               mxc_v4l2_s_std(cam, tv_fmt.fmt.pix.pixelformat);
+                       }
+               }
+
+               *e = tv_fmt.fmt.pix.pixelformat;
+       }
+
+       return 0;
+}
+
+/*!
+ * Dequeue one V4L capture buffer
+ *
+ * @param cam         structure cam_data *
+ * @param buf         structure v4l2_buffer *
+ *
+ * @return  status    0 success, EINVAL invalid frame number,
+ *                    ETIME timeout, ERESTARTSYS interrupted by user
+ */
+static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
+{
+       int retval = 0;
+       struct mxc_v4l_frame *frame;
+       unsigned long lock_flags;
+
+       pr_debug("In MVC:mxc_v4l_dqueue\n");
+
+       if (!wait_event_interruptible_timeout(cam->enc_queue,
+                                             cam->enc_counter != 0,
+                                             10 * HZ)) {
+               pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout "
+                       "enc_counter %x\n",
+                      cam->enc_counter);
+               return -ETIME;
+       } else if (signal_pending(current)) {
+               pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() "
+                       "interrupt received\n");
+               return -ERESTARTSYS;
+       }
+
+       if (down_interruptible(&cam->busy_lock))
+               return -EBUSY;
+
+       spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags);
+       cam->enc_counter--;
+
+       frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue);
+       list_del(cam->done_q.next);
+       if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) {
+               frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE;
+       } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
+               pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
+                       "Buffer not filled.\n");
+               frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
+               retval = -EINVAL;
+       } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) {
+               pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
+                       "Buffer not queued.\n");
+               retval = -EINVAL;
+       }
+
+       cam->frame[frame->index].buffer.field = cam->device_type ?
+                               V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
+
+       buf->bytesused = cam->v2f.fmt.pix.sizeimage;
+       buf->index = frame->index;
+       buf->flags = frame->buffer.flags;
+       buf->m = cam->frame[frame->index].buffer.m;
+       buf->timestamp = cam->frame[frame->index].buffer.timestamp;
+       buf->field = cam->frame[frame->index].buffer.field;
+       spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags);
+
+       up(&cam->busy_lock);
+       return retval;
+}
+
+/*!
+ * V4L interface - open function
+ *
+ * @param file         structure file *
+ *
+ * @return  status    0 success, ENODEV invalid device instance,
+ *                    ENODEV timeout, ERESTARTSYS interrupted by user
+ */
+static int mxc_v4l_open(struct file *file)
+{
+       struct v4l2_ifparm ifparm;
+       struct v4l2_format cam_fmt;
+       ipu_csi_signal_cfg_t csi_param;
+       struct video_device *dev = video_devdata(file);
+       cam_data *cam = video_get_drvdata(dev);
+       int err = 0;
+       struct sensor_data *sensor;
+
+       pr_debug("\nIn MVC: mxc_v4l_open\n");
+       pr_debug("   device name is %s\n", dev->name);
+
+       if (!cam) {
+               pr_err("ERROR: v4l2 capture: Internal error, "
+                       "cam_data not found!\n");
+               return -EBADF;
+       }
+
+       if (cam->sensor == NULL ||
+           cam->sensor->type != v4l2_int_type_slave) {
+               pr_err("ERROR: v4l2 capture: slave not found!\n");
+               return -EAGAIN;
+       }
+
+       sensor = cam->sensor->priv;
+       if (!sensor) {
+               pr_err("%s: Internal error, sensor_data is not found!\n",
+                      __func__);
+               return -EBADF;
+       }
+
+       down(&cam->busy_lock);
+       err = 0;
+       if (signal_pending(current))
+               goto oops;
+
+       if (cam->open_count++ == 0) {
+               wait_event_interruptible(cam->power_queue,
+                                        cam->low_power == false);
+
+               if (strcmp(mxc_capture_inputs[cam->current_input].name,
+                          "CSI MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
+                       err = csi_enc_select(cam);
+#endif
+               } else if (strcmp(mxc_capture_inputs[cam->current_input].name,
+                                 "CSI IC MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
+                       err = prp_enc_select(cam);
+#endif
+               }
+
+               cam->enc_counter = 0;
+               INIT_LIST_HEAD(&cam->ready_q);
+               INIT_LIST_HEAD(&cam->working_q);
+               INIT_LIST_HEAD(&cam->done_q);
+
+               vidioc_int_g_ifparm(cam->sensor, &ifparm);
+
+               csi_param.sens_clksrc = 0;
+
+               csi_param.clk_mode = 0;
+               csi_param.data_pol = 0;
+               csi_param.ext_vsync = 0;
+
+               csi_param.pack_tight = 0;
+               csi_param.force_eof = 0;
+               csi_param.data_en_pol = 0;
+
+               csi_param.mclk = ifparm.u.bt656.clock_curr;
+
+               csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
+
+               if (ifparm.u.bt656.mode
+                               == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT)
+                       csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
+               else if (ifparm.u.bt656.mode
+                               == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT)
+                       csi_param.data_width = IPU_CSI_DATA_WIDTH_10;
+               else
+                       csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
+
+
+               csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv;
+               csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv;
+
+               csi_param.csi = cam->csi;
+
+               cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
+
+               /* Reset the sizes.  Needed to prevent carryover of last
+                * operation.*/
+               cam->crop_bounds.top = cam->crop_bounds.left = 0;
+               cam->crop_bounds.width = cam_fmt.fmt.pix.width;
+               cam->crop_bounds.height = cam_fmt.fmt.pix.height;
+
+               /* This also is the max crop size for this device. */
+               cam->crop_defrect.top = cam->crop_defrect.left = 0;
+               cam->crop_defrect.width = cam_fmt.fmt.pix.width;
+               cam->crop_defrect.height = cam_fmt.fmt.pix.height;
+
+               /* At this point, this is also the current image size. */
+               cam->crop_current.top = cam->crop_current.left = 0;
+               cam->crop_current.width = cam_fmt.fmt.pix.width;
+               cam->crop_current.height = cam_fmt.fmt.pix.height;
+
+               pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+                       __func__,
+                       cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+               pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+                       __func__,
+                       cam->crop_bounds.width, cam->crop_bounds.height);
+               pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+                       __func__,
+                       cam->crop_defrect.width, cam->crop_defrect.height);
+               pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+                       __func__,
+                       cam->crop_current.width, cam->crop_current.height);
+
+               csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
+               pr_debug("On Open: Input to ipu size is %d x %d\n",
+                               cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
+               ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
+                                       cam->crop_current.height,
+                                       cam->csi);
+               ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
+                                       cam->crop_current.top,
+                                       cam->csi);
+               ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width,
+                                       cam->crop_bounds.height,
+                                       cam_fmt.fmt.pix.pixelformat,
+                                       csi_param);
+               clk_prepare_enable(sensor->sensor_clk);
+               vidioc_int_s_power(cam->sensor, 1);
+               vidioc_int_init(cam->sensor);
+               vidioc_int_dev_init(cam->sensor);
+       }
+
+       file->private_data = dev;
+
+oops:
+       up(&cam->busy_lock);
+       return err;
+}
+
+/*!
+ * V4L interface - close function
+ *
+ * @param file     struct file *
+ *
+ * @return         0 success
+ */
+static int mxc_v4l_close(struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       int err = 0;
+       cam_data *cam = video_get_drvdata(dev);
+       struct sensor_data *sensor;
+       pr_debug("In MVC:mxc_v4l_close\n");
+
+       if (!cam) {
+               pr_err("ERROR: v4l2 capture: Internal error, "
+                       "cam_data not found!\n");
+               return -EBADF;
+       }
+
+       if (!cam->sensor) {
+               pr_err("%s: Internal error, camera is not found!\n",
+                      __func__);
+               return -EBADF;
+       }
+
+       sensor = cam->sensor->priv;
+       if (!sensor) {
+               pr_err("%s: Internal error, sensor_data is not found!\n",
+                      __func__);
+               return -EBADF;
+       }
+
+       down(&cam->busy_lock);
+
+       /* for the case somebody hit the ctrl C */
+       if (cam->overlay_pid == current->pid && cam->overlay_on) {
+               err = stop_preview(cam);
+               cam->overlay_on = false;
+       }
+       if (cam->capture_pid == current->pid) {
+               err |= mxc_streamoff(cam);
+               wake_up_interruptible(&cam->enc_queue);
+       }
+
+       if (--cam->open_count == 0) {
+               vidioc_int_s_power(cam->sensor, 0);
+               clk_disable_unprepare(sensor->sensor_clk);
+               wait_event_interruptible(cam->power_queue,
+                                        cam->low_power == false);
+               pr_debug("mxc_v4l_close: release resource\n");
+
+               if (strcmp(mxc_capture_inputs[cam->current_input].name,
+                          "CSI MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
+                       err |= csi_enc_deselect(cam);
+#endif
+               } else if (strcmp(mxc_capture_inputs[cam->current_input].name,
+                                 "CSI IC MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
+                       err |= prp_enc_deselect(cam);
+#endif
+               }
+
+               mxc_free_frame_buf(cam);
+               file->private_data = NULL;
+
+               /* capture off */
+               wake_up_interruptible(&cam->enc_queue);
+               mxc_free_frames(cam);
+               cam->enc_counter++;
+       }
+
+       up(&cam->busy_lock);
+
+       return err;
+}
+
+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC) || \
+    defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) || \
+    defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
+/*
+ * V4L interface - read function
+ *
+ * @param file       struct file *
+ * @param read buf   char *
+ * @param count      size_t
+ * @param ppos       structure loff_t *
+ *
+ * @return           bytes read
+ */
+static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
+                           loff_t *ppos)
+{
+       int err = 0;
+       u8 *v_address[2];
+       struct video_device *dev = video_devdata(file);
+       cam_data *cam = video_get_drvdata(dev);
+
+       if (down_interruptible(&cam->busy_lock))
+               return -EINTR;
+
+       /* Stop the viewfinder */
+       if (cam->overlay_on == true)
+               stop_preview(cam);
+
+       v_address[0] = dma_alloc_coherent(0,
+                                      PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+                                      &cam->still_buf[0],
+                                      GFP_DMA | GFP_KERNEL);
+
+       v_address[1] = dma_alloc_coherent(0,
+                                      PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+                                      &cam->still_buf[1],
+                                      GFP_DMA | GFP_KERNEL);
+
+       if (!v_address[0] || !v_address[1]) {
+               err = -ENOBUFS;
+               goto exit0;
+       }
+
+       err = prp_still_select(cam);
+       if (err != 0) {
+               err = -EIO;
+               goto exit0;
+       }
+
+       cam->still_counter = 0;
+       err = cam->csi_start(cam);
+       if (err != 0) {
+               err = -EIO;
+               goto exit1;
+       }
+
+       if (!wait_event_interruptible_timeout(cam->still_queue,
+                                             cam->still_counter != 0,
+                                             10 * HZ)) {
+               pr_err("ERROR: v4l2 capture: mxc_v4l_read timeout counter %x\n",
+                      cam->still_counter);
+               err = -ETIME;
+               goto exit1;
+       }
+       err = copy_to_user(buf, v_address[1], cam->v2f.fmt.pix.sizeimage);
+
+exit1:
+       prp_still_deselect(cam);
+
+exit0:
+       if (v_address[0] != 0)
+               dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[0],
+                                 cam->still_buf[0]);
+       if (v_address[1] != 0)
+               dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[1],
+                                 cam->still_buf[1]);
+
+       cam->still_buf[0] = cam->still_buf[1] = 0;
+
+       if (cam->overlay_on == true)
+               start_preview(cam);
+
+       up(&cam->busy_lock);
+       if (err < 0)
+               return err;
+
+       return cam->v2f.fmt.pix.sizeimage - err;
+}
+#endif
+
+/*!
+ * V4L interface - ioctl function
+ *
+ * @param file       struct file*
+ *
+ * @param ioctlnr    unsigned int
+ *
+ * @param arg        void*
+ *
+ * @return           0 success, ENODEV for invalid device instance,
+ *                   -1 for other errors.
+ */
+static long mxc_v4l_do_ioctl(struct file *file,
+                           unsigned int ioctlnr, void *arg)
+{
+       struct video_device *dev = video_devdata(file);
+       cam_data *cam = video_get_drvdata(dev);
+       int retval = 0;
+       unsigned long lock_flags;
+
+       pr_debug("In MVC: mxc_v4l_do_ioctl %x\n", ioctlnr);
+       wait_event_interruptible(cam->power_queue, cam->low_power == false);
+       /* make this _really_ smp-safe */
+       if (ioctlnr != VIDIOC_DQBUF)
+               if (down_interruptible(&cam->busy_lock))
+                       return -EBUSY;
+
+       switch (ioctlnr) {
+       /*!
+        * V4l2 VIDIOC_QUERYCAP ioctl
+        */
+       case VIDIOC_QUERYCAP: {
+               struct v4l2_capability *cap = arg;
+               pr_debug("   case VIDIOC_QUERYCAP\n");
+               strcpy(cap->driver, "mxc_v4l2");
+               cap->version = KERNEL_VERSION(0, 1, 11);
+               cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+                                   V4L2_CAP_VIDEO_OVERLAY |
+                                   V4L2_CAP_STREAMING |
+                                   V4L2_CAP_READWRITE;
+               cap->card[0] = '\0';
+               cap->bus_info[0] = '\0';
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_G_FMT ioctl
+        */
+       case VIDIOC_G_FMT: {
+               struct v4l2_format *gf = arg;
+               pr_debug("   case VIDIOC_G_FMT\n");
+               retval = mxc_v4l2_g_fmt(cam, gf);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_S_DEST_CROP ioctl
+        */
+       case VIDIOC_S_DEST_CROP: {
+               struct v4l2_mxc_dest_crop  *of = arg;
+               pr_debug("   case VIDIOC_S_DEST_CROP\n");
+               cam->offset.u_offset = of->offset.u_offset;
+               cam->offset.v_offset = of->offset.v_offset;
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_S_FMT ioctl
+        */
+       case VIDIOC_S_FMT: {
+               struct v4l2_format *sf = arg;
+               pr_debug("   case VIDIOC_S_FMT\n");
+               retval = mxc_v4l2_s_fmt(cam, sf);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_REQBUFS ioctl
+        */
+       case VIDIOC_REQBUFS: {
+               struct v4l2_requestbuffers *req = arg;
+               pr_debug("   case VIDIOC_REQBUFS\n");
+
+               if (req->count > FRAME_NUM) {
+                       pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
+                              "not enough buffers\n");
+                       req->count = FRAME_NUM;
+               }
+
+               if ((req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+                       pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
+                              "wrong buffer type\n");
+                       retval = -EINVAL;
+                       break;
+               }
+
+               mxc_streamoff(cam);
+               if (req->memory & V4L2_MEMORY_MMAP) {
+                       mxc_free_frame_buf(cam);
+                       retval = mxc_allocate_frame_buf(cam, req->count);
+               }
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_QUERYBUF ioctl
+        */
+       case VIDIOC_QUERYBUF: {
+               struct v4l2_buffer *buf = arg;
+               int index = buf->index;
+               pr_debug("   case VIDIOC_QUERYBUF\n");
+
+               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                       pr_err("ERROR: v4l2 capture: "
+                              "VIDIOC_QUERYBUFS: "
+                              "wrong buffer type\n");
+                       retval = -EINVAL;
+                       break;
+               }
+
+               if (buf->memory & V4L2_MEMORY_MMAP) {
+                       memset(buf, 0, sizeof(buf));
+                       buf->index = index;
+               }
+
+               down(&cam->param_lock);
+               if (buf->memory & V4L2_MEMORY_USERPTR) {
+                       mxc_v4l2_release_bufs(cam);
+                       retval = mxc_v4l2_prepare_bufs(cam, buf);
+               }
+
+               if (buf->memory & V4L2_MEMORY_MMAP)
+                       retval = mxc_v4l2_buffer_status(cam, buf);
+               up(&cam->param_lock);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_QBUF ioctl
+        */
+       case VIDIOC_QBUF: {
+               struct v4l2_buffer *buf = arg;
+               int index = buf->index;
+               pr_debug("   case VIDIOC_QBUF\n");
+
+               spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
+               if ((cam->frame[index].buffer.flags & 0x7) ==
+                   V4L2_BUF_FLAG_MAPPED) {
+                       cam->frame[index].buffer.flags |=
+                           V4L2_BUF_FLAG_QUEUED;
+                       list_add_tail(&cam->frame[index].queue,
+                                     &cam->ready_q);
+               } else if (cam->frame[index].buffer.
+                          flags & V4L2_BUF_FLAG_QUEUED) {
+                       pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
+                              "buffer already queued\n");
+                       retval = -EINVAL;
+               } else if (cam->frame[index].buffer.
+                          flags & V4L2_BUF_FLAG_DONE) {
+                       pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
+                              "overwrite done buffer.\n");
+                       cam->frame[index].buffer.flags &=
+                           ~V4L2_BUF_FLAG_DONE;
+                       cam->frame[index].buffer.flags |=
+                           V4L2_BUF_FLAG_QUEUED;
+                       retval = -EINVAL;
+               }
+
+               buf->flags = cam->frame[index].buffer.flags;
+               spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_DQBUF ioctl
+        */
+       case VIDIOC_DQBUF: {
+               struct v4l2_buffer *buf = arg;
+               pr_debug("   case VIDIOC_DQBUF\n");
+
+               if ((cam->enc_counter == 0) &&
+                       (file->f_flags & O_NONBLOCK)) {
+                       retval = -EAGAIN;
+                       break;
+               }
+
+               retval = mxc_v4l_dqueue(cam, buf);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_STREAMON ioctl
+        */
+       case VIDIOC_STREAMON: {
+               pr_debug("   case VIDIOC_STREAMON\n");
+               retval = mxc_streamon(cam);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_STREAMOFF ioctl
+        */
+       case VIDIOC_STREAMOFF: {
+               pr_debug("   case VIDIOC_STREAMOFF\n");
+               retval = mxc_streamoff(cam);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_G_CTRL ioctl
+        */
+       case VIDIOC_G_CTRL: {
+               pr_debug("   case VIDIOC_G_CTRL\n");
+               retval = mxc_v4l2_g_ctrl(cam, arg);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_S_CTRL ioctl
+        */
+       case VIDIOC_S_CTRL: {
+               pr_debug("   case VIDIOC_S_CTRL\n");
+               retval = mxc_v4l2_s_ctrl(cam, arg);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_CROPCAP ioctl
+        */
+       case VIDIOC_CROPCAP: {
+               struct v4l2_cropcap *cap = arg;
+               pr_debug("   case VIDIOC_CROPCAP\n");
+               if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+                   cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+                       retval = -EINVAL;
+                       break;
+               }
+               cap->bounds = cam->crop_bounds;
+               cap->defrect = cam->crop_defrect;
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_G_CROP ioctl
+        */
+       case VIDIOC_G_CROP: {
+               struct v4l2_crop *crop = arg;
+               pr_debug("   case VIDIOC_G_CROP\n");
+
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+                   crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+                       retval = -EINVAL;
+                       break;
+               }
+               crop->c = cam->crop_current;
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_S_CROP ioctl
+        */
+       case VIDIOC_S_CROP: {
+               struct v4l2_crop *crop = arg;
+               struct v4l2_rect *b = &cam->crop_bounds;
+               pr_debug("   case VIDIOC_S_CROP\n");
+
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+                   crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+                       retval = -EINVAL;
+                       break;
+               }
+
+               crop->c.top = (crop->c.top < b->top) ? b->top
+                             : crop->c.top;
+               if (crop->c.top > b->top + b->height)
+                       crop->c.top = b->top + b->height - 1;
+               if (crop->c.height > b->top + b->height - crop->c.top)
+                       crop->c.height =
+                               b->top + b->height - crop->c.top;
+
+               crop->c.left = (crop->c.left < b->left) ? b->left
+                   : crop->c.left;
+               if (crop->c.left > b->left + b->width)
+                       crop->c.left = b->left + b->width - 1;
+               if (crop->c.width > b->left - crop->c.left + b->width)
+                       crop->c.width =
+                               b->left - crop->c.left + b->width;
+
+               crop->c.width -= crop->c.width % 8;
+               crop->c.left -= crop->c.left % 4;
+               cam->crop_current = crop->c;
+
+               pr_debug("   Cropping Input to ipu size %d x %d\n",
+                               cam->crop_current.width,
+                               cam->crop_current.height);
+               ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
+                                       cam->crop_current.height,
+                                       cam->csi);
+               ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
+                                      cam->crop_current.top,
+                                      cam->csi);
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_OVERLAY ioctl
+        */
+       case VIDIOC_OVERLAY: {
+               int *on = arg;
+               pr_debug("   VIDIOC_OVERLAY on=%d\n", *on);
+               if (*on) {
+                       cam->overlay_on = true;
+                       cam->overlay_pid = current->pid;
+                       retval = start_preview(cam);
+               }
+               if (!*on) {
+                       retval = stop_preview(cam);
+                       cam->overlay_on = false;
+               }
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_G_FBUF ioctl
+        */
+       case VIDIOC_G_FBUF: {
+               struct v4l2_framebuffer *fb = arg;
+               pr_debug("   case VIDIOC_G_FBUF\n");
+               *fb = cam->v4l2_fb;
+               fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
+               break;
+       }
+
+       /*!
+        * V4l2 VIDIOC_S_FBUF ioctl
+        */
+       case VIDIOC_S_FBUF: {
+               struct v4l2_framebuffer *fb = arg;
+               pr_debug("   case VIDIOC_S_FBUF\n");
+               cam->v4l2_fb = *fb;
+               break;
+       }
+
+       case VIDIOC_G_PARM: {
+               struct v4l2_streamparm *parm = arg;
+               pr_debug("   case VIDIOC_G_PARM\n");
+               if (cam->sensor)
+                       retval = vidioc_int_g_parm(cam->sensor, parm);
+               else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       retval = -ENODEV;
+               }
+               break;
+       }
+
+       case VIDIOC_S_PARM:  {
+               struct v4l2_streamparm *parm = arg;
+               pr_debug("   case VIDIOC_S_PARM\n");
+               if (cam->sensor)
+                       retval = mxc_v4l2_s_param(cam, parm);
+               else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       retval = -ENODEV;
+               }
+               break;
+       }
+
+       /* linux v4l2 bug, kernel c0485619 user c0405619 */
+       case VIDIOC_ENUMSTD: {
+               struct v4l2_standard *e = arg;
+               pr_debug("   case VIDIOC_ENUMSTD\n");
+               *e = cam->standard;
+               break;
+       }
+
+       case VIDIOC_G_STD: {
+               v4l2_std_id *e = arg;
+               pr_debug("   case VIDIOC_G_STD\n");
+               if (cam->sensor)
+                       retval = mxc_v4l2_g_std(cam, e);
+               else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       retval = -ENODEV;
+               }
+               break;
+       }
+
+       case VIDIOC_S_STD: {
+               v4l2_std_id *e = arg;
+               pr_debug("   case VIDIOC_S_STD\n");
+               retval = mxc_v4l2_s_std(cam, *e);
+
+               break;
+       }
+
+       case VIDIOC_ENUMOUTPUT: {
+               struct v4l2_output *output = arg;
+               pr_debug("   case VIDIOC_ENUMOUTPUT\n");
+               if (output->index >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) {
+                       retval = -EINVAL;
+                       break;
+               }
+               *output = mxc_capture_outputs[output->index];
+
+               break;
+       }
+       case VIDIOC_G_OUTPUT: {
+               int *p_output_num = arg;
+               pr_debug("   case VIDIOC_G_OUTPUT\n");
+               *p_output_num = cam->output;
+               break;
+       }
+
+       case VIDIOC_S_OUTPUT: {
+               int *p_output_num = arg;
+               pr_debug("   case VIDIOC_S_OUTPUT\n");
+               if (*p_output_num >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) {
+                       retval = -EINVAL;
+                       break;
+               }
+               cam->output = *p_output_num;
+               break;
+       }
+
+       case VIDIOC_ENUMINPUT: {
+               struct v4l2_input *input = arg;
+               pr_debug("   case VIDIOC_ENUMINPUT\n");
+               if (input->index >= MXC_V4L2_CAPTURE_NUM_INPUTS) {
+                       retval = -EINVAL;
+                       break;
+               }
+               *input = mxc_capture_inputs[input->index];
+               break;
+       }
+
+       case VIDIOC_G_INPUT: {
+               int *index = arg;
+               pr_debug("   case VIDIOC_G_INPUT\n");
+               *index = cam->current_input;
+               break;
+       }
+
+       case VIDIOC_S_INPUT: {
+               int *index = arg;
+               pr_debug("   case VIDIOC_S_INPUT\n");
+               if (*index >= MXC_V4L2_CAPTURE_NUM_INPUTS) {
+                       retval = -EINVAL;
+                       break;
+               }
+
+               if (*index == cam->current_input)
+                       break;
+
+               if ((mxc_capture_inputs[cam->current_input].status &
+                   V4L2_IN_ST_NO_POWER) == 0) {
+                       retval = mxc_streamoff(cam);
+                       if (retval)
+                               break;
+                       mxc_capture_inputs[cam->current_input].status |=
+                                                       V4L2_IN_ST_NO_POWER;
+               }
+
+               if (strcmp(mxc_capture_inputs[*index].name, "CSI MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
+                       retval = csi_enc_select(cam);
+                       if (retval)
+                               break;
+#endif
+               } else if (strcmp(mxc_capture_inputs[*index].name,
+                                 "CSI IC MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
+                       retval = prp_enc_select(cam);
+                       if (retval)
+                               break;
+#endif
+               }
+
+               mxc_capture_inputs[*index].status &= ~V4L2_IN_ST_NO_POWER;
+               cam->current_input = *index;
+               break;
+       }
+       case VIDIOC_ENUM_FMT: {
+               struct v4l2_fmtdesc *f = arg;
+               if (cam->sensor)
+                       retval = vidioc_int_enum_fmt_cap(cam->sensor, f);
+               else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       retval = -ENODEV;
+               }
+               break;
+       }
+       case VIDIOC_ENUM_FRAMESIZES: {
+               struct v4l2_frmsizeenum *fsize = arg;
+               if (cam->sensor)
+                       retval = vidioc_int_enum_framesizes(cam->sensor, fsize);
+               else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       retval = -ENODEV;
+               }
+               break;
+       }
+       case VIDIOC_ENUM_FRAMEINTERVALS: {
+               struct v4l2_frmivalenum *fival = arg;
+               if (cam->sensor) {
+                       retval = vidioc_int_enum_frameintervals(cam->sensor,
+                                                               fival);
+               } else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       retval = -ENODEV;
+               }
+               break;
+       }
+       case VIDIOC_DBG_G_CHIP_IDENT: {
+               struct v4l2_dbg_chip_ident *p = arg;
+               p->ident = V4L2_IDENT_NONE;
+               p->revision = 0;
+               if (cam->sensor)
+                       retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p);
+               else {
+                       pr_err("ERROR: v4l2 capture: slave not found!\n");
+                       retval = -ENODEV;
+               }
+               break;
+       }
+       case VIDIOC_TRY_FMT:
+       case VIDIOC_QUERYCTRL:
+       case VIDIOC_G_TUNER:
+       case VIDIOC_S_TUNER:
+       case VIDIOC_G_FREQUENCY:
+       case VIDIOC_S_FREQUENCY:
+       default:
+               pr_debug("   case default or not supported\n");
+               retval = -EINVAL;
+               break;
+       }
+
+       if (ioctlnr != VIDIOC_DQBUF)
+               up(&cam->busy_lock);
+       return retval;
+}
+
+/*
+ * V4L interface - ioctl function
+ *
+ * @return  None
+ */
+static long mxc_v4l_ioctl(struct file *file, unsigned int cmd,
+                        unsigned long arg)
+{
+       pr_debug("In MVC:mxc_v4l_ioctl\n");
+       return video_usercopy(file, cmd, arg, mxc_v4l_do_ioctl);
+}
+
+/*!
+ * V4L interface - mmap function
+ *
+ * @param file        structure file *
+ *
+ * @param vma         structure vm_area_struct *
+ *
+ * @return status     0 Success, EINTR busy lock error, ENOBUFS remap_page error
+ */
+static int mxc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *dev = video_devdata(file);
+       unsigned long size;
+       int res = 0;
+       cam_data *cam = video_get_drvdata(dev);
+
+       pr_debug("In MVC:mxc_mmap\n");
+       pr_debug("   pgoff=0x%lx, start=0x%lx, end=0x%lx\n",
+                vma->vm_pgoff, vma->vm_start, vma->vm_end);
+
+       /* make this _really_ smp-safe */
+       if (down_interruptible(&cam->busy_lock))
+               return -EINTR;
+
+       size = vma->vm_end - vma->vm_start;
+       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+       if (remap_pfn_range(vma, vma->vm_start,
+                           vma->vm_pgoff, size, vma->vm_page_prot)) {
+               pr_err("ERROR: v4l2 capture: mxc_mmap: "
+                       "remap_pfn_range failed\n");
+               res = -ENOBUFS;
+               goto mxc_mmap_exit;
+       }
+
+       vma->vm_flags &= ~VM_IO;        /* using shared anonymous pages */
+
+mxc_mmap_exit:
+       up(&cam->busy_lock);
+       return res;
+}
+
+/*!
+ * V4L interface - poll function
+ *
+ * @param file       structure file *
+ *
+ * @param wait       structure poll_table_struct *
+ *
+ * @return  status   POLLIN | POLLRDNORM
+ */
+static unsigned int mxc_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct video_device *dev = video_devdata(file);
+       cam_data *cam = video_get_drvdata(dev);
+       wait_queue_head_t *queue = NULL;
+       int res = POLLIN | POLLRDNORM;
+
+       pr_debug("In MVC:mxc_poll\n");
+
+       if (down_interruptible(&cam->busy_lock))
+               return -EINTR;
+
+       queue = &cam->enc_queue;
+       poll_wait(file, queue, wait);
+
+       up(&cam->busy_lock);
+
+       return res;
+}
+
+/*!
+ * This structure defines the functions to be called in this driver.
+ */
+static struct v4l2_file_operations mxc_v4l_fops = {
+       .owner = THIS_MODULE,
+       .open = mxc_v4l_open,
+       .release = mxc_v4l_close,
+       .read = mxc_v4l_read,
+       .unlocked_ioctl = mxc_v4l_ioctl,
+       .mmap = mxc_mmap,
+       .poll = mxc_poll,
+};
+
+static struct video_device mxc_v4l_template = {
+       .name = "Mxc Camera",
+       .fops = &mxc_v4l_fops,
+       .release = video_device_release,
+};
+
+/*!
+ * This function can be used to release any platform data on closing.
+ */
+static void camera_platform_release(struct device *device)
+{
+}
+
+/*!
+ * Camera V4l2 callback function.
+ *
+ * @param mask      u32
+ *
+ * @param dev       void device structure
+ *
+ * @return status
+ */
+static void camera_callback(u32 mask, void *dev)
+{
+       struct mxc_v4l_frame *done_frame;
+       struct mxc_v4l_frame *ready_frame;
+       struct timeval cur_time;
+
+       cam_data *cam = (cam_data *) dev;
+       if (cam == NULL)
+               return;
+
+       pr_debug("In MVC:camera_callback\n");
+
+       spin_lock(&cam->queue_int_lock);
+       spin_lock(&cam->dqueue_int_lock);
+       if (!list_empty(&cam->working_q)) {
+               do_gettimeofday(&cur_time);
+
+               done_frame = list_entry(cam->working_q.next,
+                                       struct mxc_v4l_frame,
+                                       queue);
+
+               if (done_frame->ipu_buf_num != cam->local_buf_num)
+                       goto next;
+
+               /*
+                * Set the current time to done frame buffer's
+                * timestamp. Users can use this information to judge
+                * the frame's usage.
+                */
+               done_frame->buffer.timestamp = cur_time;
+
+               if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
+                       done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE;
+                       done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
+
+                       /* Added to the done queue */
+                       list_del(cam->working_q.next);
+                       list_add_tail(&done_frame->queue, &cam->done_q);
+
+                       /* Wake up the queue */
+                       cam->enc_counter++;
+                       wake_up_interruptible(&cam->enc_queue);
+               } else
+                       pr_err("ERROR: v4l2 capture: camera_callback: "
+                               "buffer not queued\n");
+       }
+
+next:
+       if (!list_empty(&cam->ready_q)) {
+               ready_frame = list_entry(cam->ready_q.next,
+                                        struct mxc_v4l_frame,
+                                        queue);
+               if (cam->enc_update_eba)
+                       if (cam->enc_update_eba(
+                               cam,
+                               ready_frame->buffer.m.offset) == 0) {
+                               list_del(cam->ready_q.next);
+                               list_add_tail(&ready_frame->queue,
+                                             &cam->working_q);
+                               ready_frame->ipu_buf_num = cam->local_buf_num;
+                       }
+       } else {
+               if (cam->enc_update_eba)
+                       cam->enc_update_eba(
+                               cam, cam->dummy_frame.buffer.m.offset);
+       }
+
+       cam->local_buf_num = (cam->local_buf_num == 0) ? 1 : 0;
+       spin_unlock(&cam->dqueue_int_lock);
+       spin_unlock(&cam->queue_int_lock);
+
+       return;
+}
+
+/*!
+ * initialize cam_data structure
+ *
+ * @param cam      structure cam_data *
+ *
+ * @return status  0 Success
+ */
+static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(mxc_v4l2_dt_ids, &pdev->dev);
+       struct device_node *np = pdev->dev.of_node;
+       int ipu_id, csi_id, mclk_source;
+       int ret = 0;
+       struct v4l2_device *v4l2_dev;
+
+       pr_debug("In MVC: init_camera_struct\n");
+
+       ret = of_property_read_u32(np, "ipu_id", &ipu_id);
+       if (ret) {
+               dev_err(&pdev->dev, "ipu_id missing or invalid\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(np, "csi_id", &csi_id);
+       if (ret) {
+               dev_err(&pdev->dev, "csi_id missing or invalid\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(np, "mclk_source", &mclk_source);
+       if (ret) {
+               dev_err(&pdev->dev, "sensor mclk missing or invalid\n");
+               return ret;
+       }
+
+       /* Default everything to 0 */
+       memset(cam, 0, sizeof(cam_data));
+
+       /* get devtype to distinguish if the cpu is imx5 or imx6
+        * IMX5_V4L2 specify the cpu is imx5
+        * IMX6_V4L2 specify the cpu is imx6q or imx6sdl
+        */
+       if (of_id)
+               pdev->id_entry = of_id->data;
+       cam->devtype = pdev->id_entry->driver_data;
+
+       cam->ipu = ipu_get_soc(ipu_id);
+       if (cam->ipu == NULL) {
+               pr_err("ERROR: v4l2 capture: failed to get ipu\n");
+               return -EINVAL;
+       } else if (cam->ipu == ERR_PTR(-ENODEV)) {
+               pr_err("ERROR: v4l2 capture: get invalid ipu\n");
+               return -ENODEV;
+       }
+
+       init_MUTEX(&cam->param_lock);
+       init_MUTEX(&cam->busy_lock);
+
+       cam->video_dev = video_device_alloc();
+       if (cam->video_dev == NULL)
+               return -ENODEV;
+
+       *(cam->video_dev) = mxc_v4l_template;
+
+       video_set_drvdata(cam->video_dev, cam);
+       dev_set_drvdata(&pdev->dev, (void *)cam);
+       cam->video_dev->minor = -1;
+
+       v4l2_dev = kzalloc(sizeof(*v4l2_dev), GFP_KERNEL);
+       if (!v4l2_dev) {
+               dev_err(&pdev->dev, "failed to allocate v4l2_dev structure\n");
+               video_device_release(cam->video_dev);
+               return -ENOMEM;
+       }
+
+       if (v4l2_device_register(&pdev->dev, v4l2_dev) < 0) {
+               dev_err(&pdev->dev, "register v4l2 device failed\n");
+               video_device_release(cam->video_dev);
+               kfree(v4l2_dev);
+               return -ENODEV;
+       }
+       cam->video_dev->v4l2_dev = v4l2_dev;
+
+       init_waitqueue_head(&cam->enc_queue);
+       init_waitqueue_head(&cam->still_queue);
+
+       /* setup cropping */
+       cam->crop_bounds.left = 0;
+       cam->crop_bounds.width = 640;
+       cam->crop_bounds.top = 0;
+       cam->crop_bounds.height = 480;
+       cam->crop_current = cam->crop_defrect = cam->crop_bounds;
+       ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
+                               cam->crop_current.height, cam->csi);
+       ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
+                               cam->crop_current.top, cam->csi);
+       cam->streamparm.parm.capture.capturemode = 0;
+
+       cam->standard.index = 0;
+       cam->standard.id = V4L2_STD_UNKNOWN;
+       cam->standard.frameperiod.denominator = 30;
+       cam->standard.frameperiod.numerator = 1;
+       cam->standard.framelines = 480;
+       cam->standard_autodetect = true;
+       cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod;
+       cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+       cam->overlay_on = false;
+       cam->capture_on = false;
+       cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY;
+
+       cam->v2f.fmt.pix.sizeimage = 352 * 288 * 3 / 2;
+       cam->v2f.fmt.pix.bytesperline = 288 * 3 / 2;
+       cam->v2f.fmt.pix.width = 288;
+       cam->v2f.fmt.pix.height = 352;
+       cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
+       cam->win.w.width = 160;
+       cam->win.w.height = 160;
+       cam->win.w.left = 0;
+       cam->win.w.top = 0;
+
+       cam->ipu_id = ipu_id;
+       cam->csi = csi_id;
+       cam->mclk_source = mclk_source;
+       cam->mclk_on[cam->mclk_source] = false;
+
+       cam->enc_callback = camera_callback;
+       init_waitqueue_head(&cam->power_queue);
+       spin_lock_init(&cam->queue_int_lock);
+       spin_lock_init(&cam->dqueue_int_lock);
+
+       cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL);
+       cam->self->module = THIS_MODULE;
+       sprintf(cam->self->name, "mxc_v4l2_cap%d", cam->csi);
+       cam->self->type = v4l2_int_type_master;
+       cam->self->u.master = &mxc_v4l2_master;
+
+       return 0;
+}
+
+static ssize_t show_streaming(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct video_device *video_dev = container_of(dev,
+                                               struct video_device, dev);
+       cam_data *cam = video_get_drvdata(video_dev);
+
+       if (cam->capture_on)
+               return sprintf(buf, "stream on\n");
+       else
+               return sprintf(buf, "stream off\n");
+}
+static DEVICE_ATTR(fsl_v4l2_capture_property, S_IRUGO, show_streaming, NULL);
+
+static ssize_t show_overlay(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct video_device *video_dev = container_of(dev,
+                                               struct video_device, dev);
+       cam_data *cam = video_get_drvdata(video_dev);
+
+       if (cam->overlay_on)
+               return sprintf(buf, "overlay on\n");
+       else
+               return sprintf(buf, "overlay off\n");
+}
+static DEVICE_ATTR(fsl_v4l2_overlay_property, S_IRUGO, show_overlay, NULL);
+
+static ssize_t show_csi(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct video_device *video_dev = container_of(dev,
+                                               struct video_device, dev);
+       cam_data *cam = video_get_drvdata(video_dev);
+
+       return sprintf(buf, "ipu%d_csi%d\n", cam->ipu_id, cam->csi);
+}
+static DEVICE_ATTR(fsl_csi_property, S_IRUGO, show_csi, NULL);
+
+/*!
+ * This function is called to probe the devices if registered.
+ *
+ * @param   pdev  the device structure used to give information on which device
+ *                to probe
+ *
+ * @return  The function returns 0 on success and -1 on failure.
+ */
+static int mxc_v4l2_probe(struct platform_device *pdev)
+{
+       /* Create cam and initialize it. */
+       cam_data *cam = kmalloc(sizeof(cam_data), GFP_KERNEL);
+       if (cam == NULL) {
+               pr_err("ERROR: v4l2 capture: failed to register camera\n");
+               return -1;
+       }
+
+       init_camera_struct(cam, pdev);
+       pdev->dev.release = camera_platform_release;
+
+       /* Set up the v4l2 device and register it*/
+       cam->self->priv = cam;
+       v4l2_int_device_register(cam->self);
+
+       /* register v4l video device */
+       if (video_register_device(cam->video_dev, VFL_TYPE_GRABBER, video_nr)
+               < 0) {
+               kfree(cam);
+               cam = NULL;
+               pr_err("ERROR: v4l2 capture: video_register_device failed\n");
+               return -1;
+       }
+       pr_debug("   Video device registered: %s #%d\n",
+                cam->video_dev->name, cam->video_dev->minor);
+
+       if (device_create_file(&cam->video_dev->dev,
+                       &dev_attr_fsl_v4l2_capture_property))
+               dev_err(&pdev->dev, "Error on creating sysfs file"
+                       " for capture\n");
+
+       if (device_create_file(&cam->video_dev->dev,
+                       &dev_attr_fsl_v4l2_overlay_property))
+               dev_err(&pdev->dev, "Error on creating sysfs file"
+                       " for overlay\n");
+
+       if (device_create_file(&cam->video_dev->dev,
+                       &dev_attr_fsl_csi_property))
+               dev_err(&pdev->dev, "Error on creating sysfs file"
+                       " for csi number\n");
+
+       return 0;
+}
+
+/*!
+ * This function is called to remove the devices when device unregistered.
+ *
+ * @param   pdev  the device structure used to give information on which device
+ *                to remove
+ *
+ * @return  The function returns 0 on success and -1 on failure.
+ */
+static int mxc_v4l2_remove(struct platform_device *pdev)
+{
+       cam_data *cam = (cam_data *)platform_get_drvdata(pdev);
+       if (cam->open_count) {
+               pr_err("ERROR: v4l2 capture:camera open "
+                       "-- setting ops to NULL\n");
+               return -EBUSY;
+       } else {
+               struct v4l2_device *v4l2_dev = cam->video_dev->v4l2_dev;
+               device_remove_file(&cam->video_dev->dev,
+                       &dev_attr_fsl_v4l2_capture_property);
+               device_remove_file(&cam->video_dev->dev,
+                       &dev_attr_fsl_v4l2_overlay_property);
+               device_remove_file(&cam->video_dev->dev,
+                       &dev_attr_fsl_csi_property);
+
+               pr_info("V4L2 freeing image input device\n");
+               v4l2_int_device_unregister(cam->self);
+               video_unregister_device(cam->video_dev);
+
+               mxc_free_frame_buf(cam);
+               kfree(cam);
+
+               v4l2_device_unregister(v4l2_dev);
+               kfree(v4l2_dev);
+       }
+
+       pr_info("V4L2 unregistering video\n");
+       return 0;
+}
+
+/*!
+ * This function is called to put the sensor in a low power state.
+ * Refer to the document driver-model/driver.txt in the kernel source tree
+ * for more information.
+ *
+ * @param   pdev  the device structure used to give information on which I2C
+ *                to suspend
+ * @param   state the power state the device is entering
+ *
+ * @return  The function returns 0 on success and -1 on failure.
+ */
+static int mxc_v4l2_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       cam_data *cam = platform_get_drvdata(pdev);
+
+       pr_debug("In MVC:mxc_v4l2_suspend\n");
+
+       if (cam == NULL)
+               return -1;
+
+       down(&cam->busy_lock);
+
+       cam->low_power = true;
+
+       if (cam->overlay_on == true)
+               stop_preview(cam);
+       if ((cam->capture_on == true) && cam->enc_disable)
+               cam->enc_disable(cam);
+
+       if (cam->sensor && cam->open_count) {
+               if (cam->mclk_on[cam->mclk_source]) {
+                       ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
+                                              cam->mclk_source,
+                                              false, false);
+                       cam->mclk_on[cam->mclk_source] = false;
+               }
+               vidioc_int_s_power(cam->sensor, 0);
+       }
+
+       up(&cam->busy_lock);
+
+       return 0;
+}
+
+/*!
+ * This function is called to bring the sensor back from a low power state.
+ * Refer to the document driver-model/driver.txt in the kernel source tree
+ * for more information.
+ *
+ * @param   pdev   the device structure
+ *
+ * @return  The function returns 0 on success and -1 on failure
+ */
+static int mxc_v4l2_resume(struct platform_device *pdev)
+{
+       cam_data *cam = platform_get_drvdata(pdev);
+
+       pr_debug("In MVC:mxc_v4l2_resume\n");
+
+       if (cam == NULL)
+               return -1;
+
+       down(&cam->busy_lock);
+
+       cam->low_power = false;
+       wake_up_interruptible(&cam->power_queue);
+
+       if (cam->sensor && cam->open_count) {
+               vidioc_int_s_power(cam->sensor, 1);
+
+               if (!cam->mclk_on[cam->mclk_source]) {
+                       ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
+                                              cam->mclk_source,
+                                              true, true);
+                       cam->mclk_on[cam->mclk_source] = true;
+               }
+       }
+
+       if (cam->overlay_on == true)
+               start_preview(cam);
+       if (cam->capture_on == true)
+               mxc_streamon(cam);
+
+       up(&cam->busy_lock);
+
+       return 0;
+}
+
+/*!
+ * This structure contains pointers to the power management callback functions.
+ */
+static struct platform_driver mxc_v4l2_driver = {
+       .driver = {
+                  .name = "mxc_v4l2_capture",
+                  .owner = THIS_MODULE,
+                  .of_match_table = mxc_v4l2_dt_ids,
+                  },
+       .id_table = imx_v4l2_devtype,
+       .probe = mxc_v4l2_probe,
+       .remove = mxc_v4l2_remove,
+       .suspend = mxc_v4l2_suspend,
+       .resume = mxc_v4l2_resume,
+       .shutdown = NULL,
+};
+
+/*!
+ * Initializes the camera driver.
+ */
+static int mxc_v4l2_master_attach(struct v4l2_int_device *slave)
+{
+       cam_data *cam = slave->u.slave->master->priv;
+       struct v4l2_format cam_fmt;
+       int i;
+       struct sensor_data *sdata = slave->priv;
+
+       pr_debug("In MVC: mxc_v4l2_master_attach\n");
+       pr_debug("   slave.name = %s\n", slave->name);
+       pr_debug("   master.name = %s\n", slave->u.slave->master->name);
+
+       if (slave == NULL) {
+               pr_err("ERROR: v4l2 capture: slave parameter not valid.\n");
+               return -1;
+       }
+
+       if (sdata->csi != cam->csi) {
+               pr_debug("%s: csi doesn't match\n", __func__);
+               return -1;
+       }
+
+       cam->sensor = slave;
+
+       if (cam->sensor_index < MXC_SENSOR_NUM) {
+               cam->all_sensors[cam->sensor_index] = slave;
+               cam->sensor_index++;
+       } else {
+               pr_err("ERROR: v4l2 capture: slave number exceeds "
+                      "the maximum.\n");
+               return -1;
+       }
+
+       for (i = 0; i < cam->sensor_index; i++) {
+               vidioc_int_dev_exit(cam->all_sensors[i]);
+               vidioc_int_s_power(cam->all_sensors[i], 0);
+       }
+
+       cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
+
+       /* Used to detect TV in (type 1) vs. camera (type 0)*/
+       cam->device_type = cam_fmt.fmt.pix.priv;
+
+       /* Set the input size to the ipu for this device */
+       cam->crop_bounds.top = cam->crop_bounds.left = 0;
+       cam->crop_bounds.width = cam_fmt.fmt.pix.width;
+       cam->crop_bounds.height = cam_fmt.fmt.pix.height;
+
+       /* This also is the max crop size for this device. */
+       cam->crop_defrect.top = cam->crop_defrect.left = 0;
+       cam->crop_defrect.width = cam_fmt.fmt.pix.width;
+       cam->crop_defrect.height = cam_fmt.fmt.pix.height;
+
+       /* At this point, this is also the current image size. */
+       cam->crop_current.top = cam->crop_current.left = 0;
+       cam->crop_current.width = cam_fmt.fmt.pix.width;
+       cam->crop_current.height = cam_fmt.fmt.pix.height;
+
+       pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+                __func__,
+                cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+       pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+                __func__,
+                cam->crop_bounds.width, cam->crop_bounds.height);
+       pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+                __func__,
+                cam->crop_defrect.width, cam->crop_defrect.height);
+       pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+                __func__,
+                cam->crop_current.width, cam->crop_current.height);
+
+       return 0;
+}
+
+/*!
+ * Disconnects the camera driver.
+ */
+static void mxc_v4l2_master_detach(struct v4l2_int_device *slave)
+{
+       unsigned int i;
+       cam_data *cam = slave->u.slave->master->priv;
+
+       pr_debug("In MVC:mxc_v4l2_master_detach\n");
+
+       if (cam->sensor_index > 1) {
+               for (i = 0; i < cam->sensor_index; i++) {
+                       if (cam->all_sensors[i] != slave)
+                               continue;
+                       /* Move all the sensors behind this
+                        * sensor one step forward
+                        */
+                       for (; i <= MXC_SENSOR_NUM - 2; i++)
+                               cam->all_sensors[i] = cam->all_sensors[i+1];
+                       break;
+               }
+               /* Point current sensor to the last one */
+               cam->sensor = cam->all_sensors[cam->sensor_index - 2];
+       } else
+               cam->sensor = NULL;
+
+       cam->sensor_index--;
+       vidioc_int_dev_exit(slave);
+}
+
+/*!
+ * Entry point for the V4L2
+ *
+ * @return  Error code indicating success or failure
+ */
+static __init int camera_init(void)
+{
+       u8 err = 0;
+
+       pr_debug("In MVC:camera_init\n");
+
+       /* Register the device driver structure. */
+       err = platform_driver_register(&mxc_v4l2_driver);
+       if (err != 0) {
+               pr_err("ERROR: v4l2 capture:camera_init: "
+                       "platform_driver_register failed.\n");
+               return err;
+       }
+
+       return err;
+}
+
+/*!
+ * Exit and cleanup for the V4L2
+ */
+static void __exit camera_exit(void)
+{
+       pr_debug("In MVC: camera_exit\n");
+
+       platform_driver_unregister(&mxc_v4l2_driver);
+}
+
+module_init(camera_init);
+module_exit(camera_exit);
+
+module_param(video_nr, int, 0444);
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("V4L2 capture driver for Mxc based cameras");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("video");
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
new file mode 100644 (file)
index 0000000..f671775
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2004-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
+ */
+
+/*!
+ * @defgroup MXC_V4L2_CAPTURE MXC V4L2 Video Capture Driver
+ */
+/*!
+ * @file mxc_v4l2_capture.h
+ *
+ * @brief mxc V4L2 capture device API  Header file
+ *
+ * It include all the defines for frame operations, also three structure defines
+ * use case ops structure, common v4l2 driver structure and frame structure.
+ *
+ * @ingroup MXC_V4L2_CAPTURE
+ */
+#ifndef __MXC_V4L2_CAPTURE_H__
+#define __MXC_V4L2_CAPTURE_H__
+
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/mxc_v4l2.h>
+#include <linux/completion.h>
+#include <linux/dmaengine.h>
+#include <linux/pxp_dma.h>
+#include <linux/ipu-v3.h>
+#include <linux/platform_data/dma-imx.h>
+
+#include <media/v4l2-dev.h>
+#include "v4l2-int-device.h"
+
+
+#define FRAME_NUM 10
+#define MXC_SENSOR_NUM 2
+
+enum imx_v4l2_devtype {
+       IMX5_V4L2,
+       IMX6_V4L2,
+};
+
+/*!
+ * v4l2 frame structure.
+ */
+struct mxc_v4l_frame {
+       u32 paddress;
+       void *vaddress;
+       int count;
+       int width;
+       int height;
+
+       struct v4l2_buffer buffer;
+       struct list_head queue;
+       int index;
+       union {
+               int ipu_buf_num;
+               int csi_buf_num;
+       };
+};
+
+/* Only for old version.  Will go away soon. */
+typedef struct {
+       u8 clk_mode;
+       u8 ext_vsync;
+       u8 Vsync_pol;
+       u8 Hsync_pol;
+       u8 pixclk_pol;
+       u8 data_pol;
+       u8 data_width;
+       u8 pack_tight;
+       u8 force_eof;
+       u8 data_en_pol;
+       u16 width;
+       u16 height;
+       u32 pixel_fmt;
+       u32 mclk;
+       u16 active_width;
+       u16 active_height;
+} sensor_interface;
+
+/* Sensor control function */
+/* Only for old version.  Will go away soon. */
+struct camera_sensor {
+       void (*set_color) (int bright, int saturation, int red, int green,
+                          int blue);
+       void (*get_color) (int *bright, int *saturation, int *red, int *green,
+                          int *blue);
+       void (*set_ae_mode) (int ae_mode);
+       void (*get_ae_mode) (int *ae_mode);
+       sensor_interface *(*config) (int *frame_rate, int high_quality);
+       sensor_interface *(*reset) (void);
+       void (*get_std) (v4l2_std_id *std);
+       void (*set_std) (v4l2_std_id std);
+       unsigned int csi;
+};
+
+/*!
+ * common v4l2 driver structure.
+ */
+typedef struct _cam_data {
+       struct video_device *video_dev;
+       int device_type;
+
+       /* semaphore guard against SMP multithreading */
+       struct semaphore busy_lock;
+
+       int open_count;
+
+       /* params lock for this camera */
+       struct semaphore param_lock;
+
+       /* Encoder */
+       struct list_head ready_q;
+       struct list_head done_q;
+       struct list_head working_q;
+       int ping_pong_csi;
+       spinlock_t queue_int_lock;
+       spinlock_t dqueue_int_lock;
+       struct mxc_v4l_frame frame[FRAME_NUM];
+       struct mxc_v4l_frame dummy_frame;
+       wait_queue_head_t enc_queue;
+       int enc_counter;
+       dma_addr_t rot_enc_bufs[2];
+       void *rot_enc_bufs_vaddr[2];
+       int rot_enc_buf_size[2];
+       enum v4l2_buf_type type;
+
+       /* still image capture */
+       wait_queue_head_t still_queue;
+       int still_counter;
+       dma_addr_t still_buf[2];
+       void *still_buf_vaddr;
+
+       /* overlay */
+       struct v4l2_window win;
+       struct v4l2_framebuffer v4l2_fb;
+       dma_addr_t vf_bufs[2];
+       void *vf_bufs_vaddr[2];
+       int vf_bufs_size[2];
+       dma_addr_t rot_vf_bufs[2];
+       void *rot_vf_bufs_vaddr[2];
+       int rot_vf_buf_size[2];
+       bool overlay_active;
+       int output;
+       struct fb_info *overlay_fb;
+       int fb_origin_std;
+       struct work_struct csi_work_struct;
+
+       /* v4l2 format */
+       struct v4l2_format v2f;
+       struct v4l2_format input_fmt;   /* camera in */
+       bool bswapenable;
+       int rotation;   /* for IPUv1 and IPUv3, this means encoder rotation */
+       int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */
+       struct v4l2_mxc_offset offset;
+
+       /* V4l2 control bit */
+       int bright;
+       int hue;
+       int contrast;
+       int saturation;
+       int red;
+       int green;
+       int blue;
+       int ae_mode;
+
+       /* standard */
+       struct v4l2_streamparm streamparm;
+       struct v4l2_standard standard;
+       bool standard_autodetect;
+
+       /* crop */
+       struct v4l2_rect crop_bounds;
+       struct v4l2_rect crop_defrect;
+       struct v4l2_rect crop_current;
+
+       int (*enc_update_eba) (void *private, dma_addr_t eba);
+       int (*enc_enable) (void *private);
+       int (*enc_disable) (void *private);
+       int (*enc_enable_csi) (void *private);
+       int (*enc_disable_csi) (void *private);
+       void (*enc_callback) (u32 mask, void *dev);
+       int (*vf_start_adc) (void *private);
+       int (*vf_stop_adc) (void *private);
+       int (*vf_start_sdc) (void *private);
+       int (*vf_stop_sdc) (void *private);
+       int (*vf_enable_csi) (void *private);
+       int (*vf_disable_csi) (void *private);
+       int (*csi_start) (void *private);
+       int (*csi_stop) (void *private);
+
+       /* misc status flag */
+       bool overlay_on;
+       bool capture_on;
+       int overlay_pid;
+       int capture_pid;
+       bool low_power;
+       wait_queue_head_t power_queue;
+       unsigned int ipu_id;
+       unsigned int csi;
+       u8 mclk_source;
+       bool mclk_on[2];        /* two mclk sources at most now */
+       int current_input;
+
+       int local_buf_num;
+
+       /* camera sensor interface */
+       struct camera_sensor *cam_sensor;       /* old version */
+       struct v4l2_int_device *all_sensors[MXC_SENSOR_NUM];
+       struct v4l2_int_device *sensor;
+       struct v4l2_int_device *self;
+       int sensor_index;
+       void *ipu;
+       void *csi_soc;
+       enum imx_v4l2_devtype devtype;
+
+       /* v4l2 buf elements related to PxP DMA */
+       struct completion pxp_tx_cmpl;
+       struct pxp_channel *pxp_chan;
+       struct pxp_config_data pxp_conf;
+       struct dma_async_tx_descriptor *txd;
+       dma_cookie_t cookie;
+       struct scatterlist sg[2];
+} cam_data;
+
+struct sensor_data {
+       const struct ov5642_platform_data *platform_data;
+       struct v4l2_int_device *v4l2_int_device;
+       struct i2c_client *i2c_client;
+       struct v4l2_pix_format pix;
+       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);
+};
+
+void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi);
+#endif                         /* __MXC_V4L2_CAPTURE_H__ */
diff --git a/drivers/media/platform/mxc/capture/ov5640.c b/drivers/media/platform/mxc/capture/ov5640.c
new file mode 100644 (file)
index 0000000..ec8b809
--- /dev/null
@@ -0,0 +1,1950 @@
+/*
+ * 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 <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.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 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;
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct sensor_data 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[] = {
+       {"ov564x", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+       .driver = {
+                 .owner = THIS_MODULE,
+                 .name  = "ov564x",
+                 },
+       .probe  = ov5640_probe,
+       .remove = ov5640_remove,
+       .id_table = ov5640_id,
+};
+
+static inline void ov5640_power_down(int enable)
+{
+       gpio_set_value(pwn_gpio, enable);
+
+       msleep(2);
+}
+
+static inline void ov5640_reset(void)
+{
+       /* camera reset */
+       gpio_set_value(rst_gpio, 1);
+
+       /* camera power down */
+       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) {
+                       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;
+}
+
+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;
+}
+
+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+       if (s == NULL) {
+               pr_err("   ERROR!! no slave device set!\n");
+               return -1;
+       }
+
+       memset(p, 0, sizeof(*p));
+       p->u.bt656.clock_curr = ov5640_data.mclk;
+       pr_debug("   clock_curr=mclk=%d\n", ov5640_data.mclk);
+       p->if_type = V4L2_IF_TYPE_BT656;
+       p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+       p->u.bt656.clock_min = OV5640_XCLK_MIN;
+       p->u.bt656.clock_max = OV5640_XCLK_MAX;
+       p->u.bt656.bt_sync_correct = 1;  /* Indicate external vsync */
+
+       return 0;
+}
+
+/*!
+ * ioctl_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 ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+       struct sensor_data *sensor = s->priv;
+
+       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 (analog_regulator)
+                       if (regulator_enable(analog_regulator) != 0)
+                               return -EIO;
+               /* Make sure power on */
+               ov5640_power_down(0);
+       } 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);
+
+               ov5640_power_down(1);
+}
+
+       sensor->on = on;
+
+       return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+       struct sensor_data *sensor = s->priv;
+       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;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 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 ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+       struct sensor_data *sensor = s->priv;
+       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+       u32 tgt_fps;    /* target frames per secound */
+       enum ov5640_frame_rate frame_rate;
+       int ret = 0;
+
+       /* Make sure power on */
+       ov5640_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 = 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;
+               }
+
+               ret = ov5640_change_mode(frame_rate,
+                               a->parm.capture.capturemode);
+               if (ret < 0)
+                       return ret;
+
+               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;
+       }
+
+       return ret;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+       struct sensor_data *sensor = s->priv;
+
+       f->fmt.pix = sensor->pix;
+
+       return 0;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array.  Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+       int ret = 0;
+
+       switch (vc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               vc->value = ov5640_data.brightness;
+               break;
+       case V4L2_CID_HUE:
+               vc->value = ov5640_data.hue;
+               break;
+       case V4L2_CID_CONTRAST:
+               vc->value = ov5640_data.contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               vc->value = ov5640_data.saturation;
+               break;
+       case V4L2_CID_RED_BALANCE:
+               vc->value = ov5640_data.red;
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               vc->value = ov5640_data.blue;
+               break;
+       case V4L2_CID_EXPOSURE:
+               vc->value = ov5640_data.ae_mode;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array).  Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+       int retval = 0;
+
+       pr_debug("In ov5640:ioctl_s_ctrl %d\n",
+                vc->id);
+
+       switch (vc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               break;
+       case V4L2_CID_CONTRAST:
+               break;
+       case V4L2_CID_SATURATION:
+               break;
+       case V4L2_CID_HUE:
+               break;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               break;
+       case V4L2_CID_RED_BALANCE:
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               break;
+       case V4L2_CID_GAMMA:
+               break;
+       case V4L2_CID_EXPOSURE:
+               break;
+       case V4L2_CID_AUTOGAIN:
+               break;
+       case V4L2_CID_GAIN:
+               break;
+       case V4L2_CID_HFLIP:
+               break;
+       case V4L2_CID_VFLIP:
+               break;
+       default:
+               retval = -EPERM;
+               break;
+       }
+
+       return retval;
+}
+
+/*!
+ * ioctl_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 ioctl_enum_framesizes(struct v4l2_int_device *s,
+                                struct v4l2_frmsizeenum *fsize)
+{
+       if (fsize->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       fsize->pixel_format = ov5640_data.pix.pixelformat;
+       fsize->discrete.width =
+                       max(ov5640_mode_info_data[0][fsize->index].width,
+                           ov5640_mode_info_data[1][fsize->index].width);
+       fsize->discrete.height =
+                       max(ov5640_mode_info_data[0][fsize->index].height,
+                           ov5640_mode_info_data[1][fsize->index].height);
+       return 0;
+}
+
+/*!
+ * ioctl_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 ioctl_enum_frameintervals(struct v4l2_int_device *s,
+                                        struct v4l2_frmivalenum *fival)
+{
+       int i, j, count;
+
+       if (fival->index < 0 || fival->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       if (fival->width == 0 || fival->height == 0 ||
+           fival->pixel_format == 0) {
+               pr_warning("Please assign pixelformat, width and height.\n");
+               return -EINVAL;
+       }
+
+       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       fival->discrete.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 (fival->pixel_format == ov5640_data.pix.pixelformat
+                        && fival->width == ov5640_mode_info_data[i][j].width
+                        && fival->height == ov5640_mode_info_data[i][j].height
+                        && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
+                               count++;
+                       }
+                       if (fival->index == (count - 1)) {
+                               fival->discrete.denominator =
+                                               ov5640_framerates[i];
+                               return 0;
+                       }
+               }
+       }
+
+       return -EINVAL;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ *                     VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+       ((struct v4l2_dbg_chip_ident *)id)->match.type =
+                                       V4L2_CHIP_MATCH_I2C_DRIVER;
+       strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5640_camera");
+
+       return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+
+       return 0;
+}
+
+/*!
+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
+ * @s: pointer to standard V4L2 device structure
+ * @fmt: pointer to standard V4L2 fmt description structure
+ *
+ * Return 0.
+ */
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+                             struct v4l2_fmtdesc *fmt)
+{
+       if (fmt->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       fmt->pixelformat = ov5640_data.pix.pixelformat;
+
+       return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+       struct sensor_data *sensor = s->priv;
+       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);
+       clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk);
+
+       /* Default camera frame rate is set in probe */
+       tgt_fps = sensor->streamcap.timeperframe.denominator /
+                 sensor->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;
+}
+
+/*!
+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Delinitialise the device when slave detaches to the master.
+ */
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+       return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module and links them to the
+ * enumeration.
+ */
+static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = {
+       { vidioc_int_dev_init_num,
+         (v4l2_int_ioctl_func *)ioctl_dev_init },
+       { vidioc_int_dev_exit_num,
+         ioctl_dev_exit},
+       { vidioc_int_s_power_num,
+         (v4l2_int_ioctl_func *)ioctl_s_power },
+       { vidioc_int_g_ifparm_num,
+         (v4l2_int_ioctl_func *)ioctl_g_ifparm },
+       { vidioc_int_init_num,
+         (v4l2_int_ioctl_func *)ioctl_init },
+       { vidioc_int_enum_fmt_cap_num,
+         (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
+       { vidioc_int_g_fmt_cap_num,
+         (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
+       { vidioc_int_g_parm_num,
+         (v4l2_int_ioctl_func *)ioctl_g_parm },
+       { vidioc_int_s_parm_num,
+         (v4l2_int_ioctl_func *)ioctl_s_parm },
+       { vidioc_int_g_ctrl_num,
+         (v4l2_int_ioctl_func *)ioctl_g_ctrl },
+       { vidioc_int_s_ctrl_num,
+         (v4l2_int_ioctl_func *)ioctl_s_ctrl },
+       { vidioc_int_enum_framesizes_num,
+         (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
+       { vidioc_int_enum_frameintervals_num,
+         (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
+       { vidioc_int_g_chip_ident_num,
+         (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
+};
+
+static struct v4l2_int_slave ov5640_slave = {
+       .ioctls = ov5640_ioctl_desc,
+       .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc),
+};
+
+static struct v4l2_int_device ov5640_int_device = {
+       .module = THIS_MODULE,
+       .name = "ov564x",
+       .type = v4l2_int_type_slave,
+       .u = {
+               .slave = &ov5640_slave,
+       },
+};
+
+/*!
+ * 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;
+       }
+
+       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;
+       }
+
+       ov5640_power_down(1);
+
+       clk_disable_unprepare(ov5640_data.sensor_clk);
+
+       ov5640_int_device.priv = &ov5640_data;
+       retval = v4l2_int_device_register(&ov5640_int_device);
+
+       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)
+{
+       v4l2_int_device_unregister(&ov5640_int_device);
+
+       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/ov5640_mipi.c b/drivers/media/platform/mxc/capture/ov5640_mipi.c
new file mode 100644 (file)
index 0000000..ec813a6
--- /dev/null
@@ -0,0 +1,2142 @@
+/*
+ * Copyright (C) 2011-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/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/fsl_devices.h>
+#include <linux/mipi_csi2.h>
+#include <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.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,
+       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,
+};
+
+/* 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;
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct sensor_data 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, 0x3f, 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, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
+};
+
+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
+
+       {0x3035, 0x14, 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}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
+       {0x3035, 0x22, 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, 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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
+
+       {0x3035, 0x14, 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}, {0x3503, 0x00, 0, 0},
+       {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+       {0x380b, 0x00, 0, 0}, {0x3035, 0x12, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
+       {0x3035, 0x22, 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, 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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3808, 0x04, 0, 0},
+       {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
+       {0x3035, 0x14, 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, 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}, {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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
+       {0x3035, 0x22, 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, 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}, {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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
+       {0x3035, 0x14, 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, 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}, {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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
+       {0x3035, 0x22, 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, 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}, {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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
+       {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},
+};
+
+static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
+       {0x3035, 0x22, 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},
+};
+
+static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
+       {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, 0x02, 0, 0},
+       {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x38, 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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
+       {0x3035, 0x22, 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, 0x02, 0, 0},
+       {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x38, 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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 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_15fps_720P_1280_720[] = {
+       {0x3035, 0x41, 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},
+};
+
+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_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, 0x21, 0, 0},
+       {0x3036, 0x54, 0, 1}, {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[] = {
+       {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},
+       {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, SUBSAMPLING, 640,  480,
+               ov5640_setting_15fps_VGA_640_480,
+               ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
+               {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320,  240,
+               ov5640_setting_15fps_QVGA_320_240,
+               ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
+               {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
+               ov5640_setting_15fps_NTSC_720_480,
+               ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
+               {ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
+               ov5640_setting_15fps_PAL_720_576,
+               ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
+               {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
+               ov5640_setting_15fps_720P_1280_720,
+               ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
+               {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
+               ov5640_setting_15fps_1080P_1920_1080,
+               ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
+               {ov5640_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
+               ov5640_setting_15fps_QSXGA_2592_1944,
+               ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
+               {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
+               ov5640_setting_15fps_QCIF_176_144,
+               ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
+               {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768,
+               ov5640_setting_15fps_XGA_1024_768,
+               ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
+       },
+       {
+               {ov5640_mode_VGA_640_480, SUBSAMPLING, 640,  480,
+               ov5640_setting_30fps_VGA_640_480,
+               ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
+               {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320,  240,
+               ov5640_setting_30fps_QVGA_320_240,
+               ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
+               {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
+               ov5640_setting_30fps_NTSC_720_480,
+               ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
+               {ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
+               ov5640_setting_30fps_PAL_720_576,
+               ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
+               {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},
+               {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
+               ov5640_setting_30fps_QCIF_176_144,
+               ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
+               {ov5640_mode_XGA_1024_768, SUBSAMPLING, 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 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[] = {
+       {"ov564x_mipi", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+       .driver = {
+                 .owner = THIS_MODULE,
+                 .name  = "ov564x_mipi",
+                 },
+       .probe  = ov5640_probe,
+       .remove = ov5640_remove,
+       .id_table = ov5640_id,
+};
+
+static void ov5640_standby(s32 enable)
+{
+       if (enable)
+               gpio_set_value(pwn_gpio, 1);
+       else
+               gpio_set_value(pwn_gpio, 0);
+
+       msleep(2);
+}
+
+static void ov5640_reset(void)
+{
+       /* 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_power_on(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);
+}
+
+
+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);
+
+       OV5640_stream_on();
+
+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_stream_on();
+
+       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;
+       void *mipi_csi2_info;
+       u32 mipi_reg, 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;
+       }
+
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       /* initial mipi dphy */
+       if (!mipi_csi2_info) {
+               printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
+                      __func__, __FILE__);
+               return -1;
+       }
+
+       if (!mipi_csi2_get_status(mipi_csi2_info))
+               mipi_csi2_enable(mipi_csi2_info);
+
+       if (!mipi_csi2_get_status(mipi_csi2_info)) {
+               pr_err("Can not enable mipi csi2 driver!\n");
+               return -1;
+       }
+
+       mipi_csi2_set_lanes(mipi_csi2_info);
+
+       /*Only reset MIPI CSI2 HW at sensor initialize*/
+       if (mode == ov5640_mode_INIT)
+               mipi_csi2_reset(mipi_csi2_info);
+
+       if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_UYVY)
+               mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_YUV422);
+       else if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_RGB565)
+               mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_RGB565);
+       else
+               pr_err("currently this sensor format can not be supported!\n");
+
+       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 if (frame_rate == ov5640_15_fps) {
+               /* dump the first nine frames: 1/15*9 */
+               msec_wait4stable = 600;
+       } else if (frame_rate == ov5640_30_fps) {
+               /* dump the first nine frames: 1/30*9 */
+               msec_wait4stable = 300;
+       }
+       msleep(msec_wait4stable);
+
+       if (mipi_csi2_info) {
+               unsigned int i;
+
+               i = 0;
+
+               /* wait for mipi sensor ready */
+               mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
+               while ((mipi_reg == 0x200) && (i < 10)) {
+                       mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
+                       i++;
+                       msleep(10);
+               }
+
+               if (i >= 10) {
+                       pr_err("mipi csi2 can not receive sensor clk!\n");
+                       return -1;
+               }
+
+               i = 0;
+
+               /* wait for mipi stable */
+               mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
+               while ((mipi_reg != 0x0) && (i < 10)) {
+                       mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
+                       i++;
+                       msleep(10);
+               }
+
+               if (i >= 10) {
+                       pr_err("mipi csi2 can not reveive data correctly!\n");
+                       return -1;
+               }
+       }
+err:
+       return retval;
+}
+
+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+       if (s == NULL) {
+               pr_err("   ERROR!! no slave device set!\n");
+               return -1;
+       }
+
+       memset(p, 0, sizeof(*p));
+       p->u.bt656.clock_curr = ov5640_data.mclk;
+       pr_debug("   clock_curr=mclk=%d\n", ov5640_data.mclk);
+       p->if_type = V4L2_IF_TYPE_BT656;
+       p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+       p->u.bt656.clock_min = OV5640_XCLK_MIN;
+       p->u.bt656.clock_max = OV5640_XCLK_MAX;
+       p->u.bt656.bt_sync_correct = 1;  /* Indicate external vsync */
+
+       return 0;
+}
+
+/*!
+ * ioctl_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 ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+       struct sensor_data *sensor = s->priv;
+
+       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;
+               /* Make sure power on */
+               ov5640_standby(0);
+       } 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);
+
+               ov5640_standby(1);
+       }
+
+       sensor->on = on;
+
+       return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+       struct sensor_data *sensor = s->priv;
+       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;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 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 ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+       struct sensor_data *sensor = s->priv;
+       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;
+
+       /* Make sure power on */
+       ov5640_standby(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;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+       struct sensor_data *sensor = s->priv;
+
+       f->fmt.pix = sensor->pix;
+
+       return 0;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array.  Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+       int ret = 0;
+
+       switch (vc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               vc->value = ov5640_data.brightness;
+               break;
+       case V4L2_CID_HUE:
+               vc->value = ov5640_data.hue;
+               break;
+       case V4L2_CID_CONTRAST:
+               vc->value = ov5640_data.contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               vc->value = ov5640_data.saturation;
+               break;
+       case V4L2_CID_RED_BALANCE:
+               vc->value = ov5640_data.red;
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               vc->value = ov5640_data.blue;
+               break;
+       case V4L2_CID_EXPOSURE:
+               vc->value = ov5640_data.ae_mode;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array).  Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+       int retval = 0;
+
+       pr_debug("In ov5640:ioctl_s_ctrl %d\n",
+                vc->id);
+
+       switch (vc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               break;
+       case V4L2_CID_CONTRAST:
+               break;
+       case V4L2_CID_SATURATION:
+               break;
+       case V4L2_CID_HUE:
+               break;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               break;
+       case V4L2_CID_RED_BALANCE:
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               break;
+       case V4L2_CID_GAMMA:
+               break;
+       case V4L2_CID_EXPOSURE:
+               break;
+       case V4L2_CID_AUTOGAIN:
+               break;
+       case V4L2_CID_GAIN:
+               break;
+       case V4L2_CID_HFLIP:
+               break;
+       case V4L2_CID_VFLIP:
+               break;
+       default:
+               retval = -EPERM;
+               break;
+       }
+
+       return retval;
+}
+
+/*!
+ * ioctl_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 ioctl_enum_framesizes(struct v4l2_int_device *s,
+                                struct v4l2_frmsizeenum *fsize)
+{
+       if (fsize->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       fsize->pixel_format = ov5640_data.pix.pixelformat;
+       fsize->discrete.width =
+                       max(ov5640_mode_info_data[0][fsize->index].width,
+                           ov5640_mode_info_data[1][fsize->index].width);
+       fsize->discrete.height =
+                       max(ov5640_mode_info_data[0][fsize->index].height,
+                           ov5640_mode_info_data[1][fsize->index].height);
+       return 0;
+}
+
+/*!
+ * ioctl_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 ioctl_enum_frameintervals(struct v4l2_int_device *s,
+                                        struct v4l2_frmivalenum *fival)
+{
+       int i, j, count = 0;
+
+       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       fival->discrete.numerator = 1;
+
+       for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++)
+               for (j = 0; j < (ov5640_mode_MAX + 1); j++)
+                       if (fival->pixel_format == ov5640_data.pix.pixelformat
+                        && fival->width == ov5640_mode_info_data[i][j].width
+                        && fival->height == ov5640_mode_info_data[i][j].height
+                        && ov5640_mode_info_data[i][j].init_data_ptr != NULL
+                        && fival->index == count++) {
+                               fival->discrete.denominator =
+                                               ov5640_framerates[i];
+                               return 0;
+                       }
+
+       return -EINVAL;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ *                     VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+       ((struct v4l2_dbg_chip_ident *)id)->match.type =
+                                       V4L2_CHIP_MATCH_I2C_DRIVER;
+       strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
+               "ov5640_mipi_camera");
+
+       return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+
+       return 0;
+}
+
+/*!
+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
+ * @s: pointer to standard V4L2 device structure
+ * @fmt: pointer to standard V4L2 fmt description structure
+ *
+ * Return 0.
+ */
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+                             struct v4l2_fmtdesc *fmt)
+{
+       if (fmt->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+       fmt->pixelformat = ov5640_data.pix.pixelformat;
+
+       return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+       struct sensor_data *sensor = s->priv;
+       u32 tgt_xclk;   /* target xclk */
+       u32 tgt_fps;    /* target frames per secound */
+       int ret;
+       enum ov5640_frame_rate frame_rate;
+       void *mipi_csi2_info;
+
+       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 = sensor->streamcap.timeperframe.denominator /
+                 sensor->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. */
+
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       /* enable mipi csi2 */
+       if (mipi_csi2_info)
+               mipi_csi2_enable(mipi_csi2_info);
+       else {
+               printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
+                      __func__, __FILE__);
+               return -EPERM;
+       }
+
+       ret = ov5640_init_mode(frame_rate, ov5640_mode_INIT, ov5640_mode_INIT);
+
+       return ret;
+}
+
+/*!
+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Delinitialise the device when slave detaches to the master.
+ */
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+       void *mipi_csi2_info;
+
+       mipi_csi2_info = mipi_csi2_get_info();
+
+       /* disable mipi csi2 */
+       if (mipi_csi2_info)
+               if (mipi_csi2_get_status(mipi_csi2_info))
+                       mipi_csi2_disable(mipi_csi2_info);
+
+       return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module and links them to the
+ * enumeration.
+ */
+static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = {
+       {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *) ioctl_dev_init},
+       {vidioc_int_dev_exit_num, ioctl_dev_exit},
+       {vidioc_int_s_power_num, (v4l2_int_ioctl_func *) ioctl_s_power},
+       {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *) ioctl_g_ifparm},
+/*     {vidioc_int_g_needs_reset_num,
+                               (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */
+/*     {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */
+       {vidioc_int_init_num, (v4l2_int_ioctl_func *) ioctl_init},
+       {vidioc_int_enum_fmt_cap_num,
+                               (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap},
+/*     {vidioc_int_try_fmt_cap_num,
+                               (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */
+       {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap},
+/*     {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, */
+       {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm},
+       {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm},
+/*     {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *)ioctl_queryctrl}, */
+       {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl},
+       {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl},
+       {vidioc_int_enum_framesizes_num,
+                               (v4l2_int_ioctl_func *) ioctl_enum_framesizes},
+       {vidioc_int_enum_frameintervals_num,
+                       (v4l2_int_ioctl_func *) ioctl_enum_frameintervals},
+       {vidioc_int_g_chip_ident_num,
+                               (v4l2_int_ioctl_func *) ioctl_g_chip_ident},
+};
+
+static struct v4l2_int_slave ov5640_slave = {
+       .ioctls = ov5640_ioctl_desc,
+       .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc),
+};
+
+static struct v4l2_int_device ov5640_int_device = {
+       .module = THIS_MODULE,
+       .name = "ov564x",
+       .type = v4l2_int_type_slave,
+       .u = {
+               .slave = &ov5640_slave,
+       },
+};
+
+/*!
+ * 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 device *dev = &client->dev;
+       int retval;
+       u8 chip_id_high, chip_id_low;
+
+       /* 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");
+               return -EINVAL;
+       }
+       retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "ov5640_mipi_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_warn(dev, "no sensor reset pin available");
+               return -EINVAL;
+       }
+       retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "ov5640_mipi_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)) {
+               /* 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_UYVY;
+       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_power_on(dev);
+
+       ov5640_reset();
+
+       ov5640_standby(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;
+       }
+
+       ov5640_standby(1);
+
+       ov5640_int_device.priv = &ov5640_data;
+       retval = v4l2_int_device_register(&ov5640_int_device);
+
+       clk_disable_unprepare(ov5640_data.sensor_clk);
+
+       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)
+{
+       v4l2_int_device_unregister(&ov5640_int_device);
+
+       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;
+}
+
+/*!
+ * ov5640 init function
+ * Called by insmod ov5640_camera.ko.
+ *
+ * @return  Error code indicating success or failure
+ */
+static __init int ov5640_init(void)
+{
+       u8 err;
+
+       err = i2c_add_driver(&ov5640_i2c_driver);
+       if (err != 0)
+               pr_err("%s:driver registration failed, error=%d\n",
+                       __func__, err);
+
+       return err;
+}
+
+/*!
+ * OV5640 cleanup function
+ * Called on rmmod ov5640_camera.ko
+ *
+ * @return  Error code indicating success or failure
+ */
+static void __exit ov5640_clean(void)
+{
+       i2c_del_driver(&ov5640_i2c_driver);
+}
+
+module_init(ov5640_init);
+module_exit(ov5640_clean);
+
+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/ov5642.c b/drivers/media/platform/mxc/capture/ov5642.c
new file mode 100644 (file)
index 0000000..be61222
--- /dev/null
@@ -0,0 +1,4252 @@
+/*
+ * Copyright (C) 2012-2014 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/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/fsl_devices.h>
+#include <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.h"
+
+#define OV5642_VOLTAGE_ANALOG               2800000
+#define OV5642_VOLTAGE_DIGITAL_CORE         1500000
+#define OV5642_VOLTAGE_DIGITAL_IO           1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5642_XCLK_MIN 6000000
+#define OV5642_XCLK_MAX 24000000
+
+#define OV5642_CHIP_ID_HIGH_BYTE       0x300A
+#define OV5642_CHIP_ID_LOW_BYTE                0x300B
+
+enum ov5642_mode {
+       ov5642_mode_MIN = 0,
+       ov5642_mode_VGA_640_480 = 0,
+       ov5642_mode_QVGA_320_240 = 1,
+       ov5642_mode_NTSC_720_480 = 2,
+       ov5642_mode_PAL_720_576 = 3,
+       ov5642_mode_720P_1280_720 = 4,
+       ov5642_mode_1080P_1920_1080 = 5,
+       ov5642_mode_QSXGA_2592_1944 = 6,
+       ov5642_mode_QCIF_176_144 = 7,
+       ov5642_mode_XGA_1024_768 = 8,
+       ov5642_mode_MAX = 8
+};
+
+enum ov5642_frame_rate {
+       ov5642_15_fps,
+       ov5642_30_fps
+};
+
+static int ov5642_framerates[] = {
+       [ov5642_15_fps] = 15,
+       [ov5642_30_fps] = 30,
+};
+
+struct reg_value {
+       u16 u16RegAddr;
+       u8 u8Val;
+       u8 u8Mask;
+       u32 u32Delay_ms;
+};
+
+struct ov5642_mode_info {
+       enum ov5642_mode mode;
+       u32 width;
+       u32 height;
+       struct reg_value *init_data_ptr;
+       u32 init_data_size;
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct sensor_data ov5642_data;
+static int pwn_gpio, rst_gpio;
+
+static struct reg_value ov5642_rot_none_VGA[] = {
+       {0x3818, 0xc1, 0x00, 0x00}, {0x3621, 0x87, 0x00, 0x00},
+};
+
+static struct reg_value ov5642_rot_vert_flip_VGA[] = {
+       {0x3818, 0x20, 0xbf, 0x00}, {0x3621, 0x20, 0xff, 0x00},
+};
+
+static struct reg_value ov5642_rot_horiz_flip_VGA[] = {
+       {0x3818, 0x81, 0x00, 0x01}, {0x3621, 0xa7, 0x00, 0x00},
+};
+
+static struct reg_value ov5642_rot_180_VGA[] = {
+       {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00},
+};
+
+
+static struct reg_value ov5642_rot_none_FULL[] = {
+       {0x3818, 0xc0, 0x00, 0x00}, {0x3621, 0x09, 0x00, 0x00},
+};
+
+static struct reg_value ov5642_rot_vert_flip_FULL[] = {
+       {0x3818, 0x20, 0xbf, 0x01}, {0x3621, 0x20, 0xff, 0x00},
+};
+
+static struct reg_value ov5642_rot_horiz_flip_FULL[] = {
+       {0x3818, 0x80, 0x00, 0x01}, {0x3621, 0x29, 0x00, 0x00},
+};
+
+static struct reg_value ov5642_rot_180_FULL[] = {
+       {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00},
+};
+
+
+static struct reg_value ov5642_initial_setting[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+       {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c00, 0x04, 0, 0}, {0x3c01, 0x80, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0},
+       {0x5182, 0x00, 0, 0}, {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0},
+       {0x5001, 0xff, 0, 0}, {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0},
+       {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0},
+       {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0},
+       {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+       {0x380b, 0xe0, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0},
+       {0x501f, 0x00, 0, 0}, {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0},
+       {0x350b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0},
+       {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+       {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0},
+       {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+       {0x3801, 0x80, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0},
+       {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+       {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+       {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+       {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+       {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+       {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+       {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+       {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+       {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+       {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+       {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+       {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+       {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+       {0x3a1f, 0x10, 0, 0}, {0x3030, 0x0b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 300},
+};
+
+static struct reg_value ov5642_setting_15fps_QCIF_176_144[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+       {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+       {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+       {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+       {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+       {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+       {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+       {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+       {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+       {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+       {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+       {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+       {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+       {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+       {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+       {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+       {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+       {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+       {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+       {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+       {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+       {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+       {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+       {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+       {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+       {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+       {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+       {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+       {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+       {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+       {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+       {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+       {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+       {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+       {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+       {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+       {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+       {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+       {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+       {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+       {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+       {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+       {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+       {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+       {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+       {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+       {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+       {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+       {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+       {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+       {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+       {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+       {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+       {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+       {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+       {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+       {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+       {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+       {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+       {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+       {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+       {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+       {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+       {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+       {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+       {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+       {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+       {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+       {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+       {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+       {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+       {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+       {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+       {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+       {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+       {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+       {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+       {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+       {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+       {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+       {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+       {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+       {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+       {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+       {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+       {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+       {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+       {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+       {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+       {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+       {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+       {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+       {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+       {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+       {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+       {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+       {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+       {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+       {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+       {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+       {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+       {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+       {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+       {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+       {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+       {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+       {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+       {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+       {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+       {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+       {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+       {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+       {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+       {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+       {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+       {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+       {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+       {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+       {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+       {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+       {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+       {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+       {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+       {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+       {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+       {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+       {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+       {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+       {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+       {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
+       {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_QCIF_176_144[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+       {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x10, 0, 0},
+       {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+       {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+       {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+       {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+       {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+       {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+       {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+       {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+       {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+       {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+       {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+       {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+       {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+       {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+       {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+       {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+       {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+       {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+       {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+       {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+       {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+       {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+       {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+       {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+       {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+       {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+       {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+       {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+       {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+       {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+       {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+       {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+       {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+       {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+       {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+       {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+       {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+       {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+       {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+       {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+       {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+       {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+       {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+       {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+       {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+       {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+       {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+       {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+       {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+       {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+       {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+       {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+       {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+       {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+       {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+       {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+       {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+       {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+       {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+       {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+       {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+       {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+       {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+       {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+       {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+       {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+       {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+       {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+       {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+       {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+       {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+       {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+       {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+       {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+       {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+       {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+       {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+       {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+       {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+       {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+       {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+       {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+       {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+       {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+       {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+       {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+       {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+       {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+       {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+       {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+       {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+       {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+       {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+       {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+       {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+       {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+       {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+       {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+       {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+       {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+       {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+       {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+       {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+       {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+       {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+       {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+       {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+       {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+       {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+       {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+       {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+       {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+       {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+       {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+       {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+       {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+       {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+       {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+       {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+       {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+       {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+       {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+       {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+       {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+       {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+       {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+       {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+       {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
+       {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_QSXGA_2592_1944[] = {
+       {0x3503, 0x07, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0},
+       {0x3002, 0x00, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
+       {0x3005, 0xff, 0, 0}, {0x3006, 0xff, 0, 0}, {0x3007, 0x3f, 0, 0},
+       {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3818, 0xc0, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+       {0x3602, 0xe4, 0, 0}, {0x3612, 0xac, 0, 0}, {0x3613, 0x44, 0, 0},
+       {0x3622, 0x60, 0, 0}, {0x3623, 0x22, 0, 0}, {0x3604, 0x48, 0, 0},
+       {0x3705, 0xda, 0, 0}, {0x370a, 0x80, 0, 0}, {0x3801, 0x95, 0, 0},
+       {0x3803, 0x0e, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x20, 0, 0},
+       {0x3806, 0x07, 0, 0}, {0x3807, 0x98, 0, 0}, {0x3808, 0x0a, 0, 0},
+       {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
+       {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
+       {0x380f, 0xd0, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3815, 0x44, 0, 0},
+       {0x3824, 0x11, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
+       {0x3a00, 0x78, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
+       {0x5682, 0x0a, 0, 0}, {0x5683, 0x20, 0, 0}, {0x5686, 0x07, 0, 0},
+       {0x5687, 0x98, 0, 0}, {0x5001, 0xff, 0, 0}, {0x589b, 0x00, 0, 0},
+       {0x589a, 0xc0, 0, 0}, {0x4407, 0x04, 0, 0}, {0x3008, 0x02, 0, 0},
+       {0x460b, 0x37, 0, 0}, {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0},
+       {0x4713, 0x03, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x3815, 0x01, 0, 0},
+       {0x501f, 0x00, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0},
+       {0x5002, 0xe0, 0, 0}, {0x530a, 0x01, 0, 0}, {0x530d, 0x10, 0, 0},
+       {0x530c, 0x04, 0, 0}, {0x5312, 0x20, 0, 0}, {0x5282, 0x01, 0, 0},
+       {0x3010, 0x10, 0, 0}, {0x3012, 0x00, 0, 0},
+};
+
+
+static struct reg_value ov5642_setting_VGA_2_QVGA[] = {
+       {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
+       {0x380b, 0xf0, 0, 0}, {0x3815, 0x04, 0, 0},
+};
+
+static struct reg_value ov5642_setting_QSXGA_2_VGA[] = {
+       {0x3503, 0x00, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0},
+       {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
+       {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x3818, 0xc1, 0, 0}, {0x3621, 0x87, 0, 0},
+       {0x350c, 0x03, 0, 0}, {0x350d, 0xe8, 0, 0}, {0x3602, 0xfc, 0, 0},
+       {0x3612, 0xff, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3622, 0x60, 0, 0},
+       {0x3623, 0x01, 0, 0}, {0x3604, 0x48, 0, 0}, {0x3705, 0xdb, 0, 0},
+       {0x370a, 0x81, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0},
+       {0x3807, 0xc0, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
+       {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x0c, 0, 0},
+       {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+       {0x3810, 0x40, 0, 0}, {0x3815, 0x04, 0, 0}, {0x3824, 0x11, 0, 0},
+       {0x3825, 0xb4, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x5682, 0x05, 0, 0},
+       {0x5683, 0x00, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0},
+       {0x5001, 0xff, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x4407, 0x0c, 0, 0}, {0x3008, 0x02, 0, 0}, {0x460b, 0x37, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4713, 0x02, 0, 0},
+       {0x471c, 0xd0, 0, 0}, {0x3815, 0x04, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x3002, 0x5c, 0, 0}, {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0},
+       {0x530a, 0x01, 0, 0}, {0x530d, 0x0c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x5312, 0x40, 0, 0}, {0x5282, 0x00, 0, 0},
+       {0x3012, 0x02, 0, 0}, {0x3010, 0x00, 0, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_VGA_640_480[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+       {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+       {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+       {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+       {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+       {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+       {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+       {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+       {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+       {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+       {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+       {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+       {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+       {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+       {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+       {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+       {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+       {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+       {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+       {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+       {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_VGA_640_480[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+       {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+       {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+       {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+       {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0},
+       {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+       {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+       {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+       {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+       {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+       {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+       {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+       {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+       {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+       {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+       {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+       {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+       {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+       {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+       {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+       {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+
+static struct reg_value ov5642_setting_30fps_XGA_1024_768[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+       {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+       {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+       {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+       {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+       {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+       {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+       {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+       {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+       {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+       {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+       {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+       {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+       {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+       {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+       {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+       {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+       {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+       {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+       {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+       {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+       {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_XGA_1024_768[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+       {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+       {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+       {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+       {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0},
+       {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+       {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+       {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+       {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+       {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+       {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+       {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+       {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+       {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+       {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+       {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+       {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+       {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+       {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+       {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+       {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+       {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_QVGA_320_240[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+       {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+       {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+       {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+       {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+       {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+       {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+       {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+       {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+       {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+       {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+       {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+       {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+       {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+       {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+       {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+       {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+       {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+       {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+       {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+       {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3808, 0x01, 0, 0},
+       {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_NTSC_720_480[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+       {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+       {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+       {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+       {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+       {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+       {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+       {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+       {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0},
+       {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+       {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+       {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+       {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+       {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+       {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+       {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+       {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+       {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+       {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+       {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+       {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x302c, 0x60, 0x60, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_PAL_720_576[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+       {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+       {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+       {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+       {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xd8, 0, 0},
+       {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+       {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+       {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+       {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+       {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0},
+       {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x5682, 0x04, 0, 0},
+       {0x5683, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0},
+       {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+       {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+       {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+       {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+       {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+       {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+       {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+       {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+       {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+       {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+       {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+       {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+       {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+       {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x302c, 0x60, 0x60, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_720P_1280_720[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
+       {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
+       {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
+       {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
+       {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
+       {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
+       {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
+       {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
+       {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
+       {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
+       {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
+       {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
+       {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
+       {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
+       {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
+       {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
+       {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
+       {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
+       {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
+       {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
+       {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
+       {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
+       {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0},
+       {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0},
+       {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0},
+       {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0},
+       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+       {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0},
+       {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0},
+       {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0},
+       {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0},
+       {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0},
+       {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0},
+       {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0},
+       {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0},
+       {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0},
+       {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0},
+       {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0},
+       {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, {0x3010, 0x30, 0, 0},
+       {0x3a08, 0x06, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x05, 0, 0},
+       {0x3a0b, 0x50, 0, 0}, {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x07, 0, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_720P_1280_720[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
+       {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
+       {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
+       {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
+       {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
+       {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
+       {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
+       {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
+       {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
+       {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
+       {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
+       {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
+       {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
+       {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
+       {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
+       {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
+       {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
+       {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
+       {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
+       {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
+       {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
+       {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
+       {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0},
+       {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0},
+       {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0},
+       {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0},
+       {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+       {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0},
+       {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0},
+       {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0},
+       {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0},
+       {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0},
+       {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0},
+       {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0},
+       {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0},
+       {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0},
+       {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0},
+       {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0},
+       {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0},
+       {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_1080P_1920_1080[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
+       {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
+       {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
+       {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
+       {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
+       {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
+       {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
+       {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
+       {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
+       {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
+       {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
+       {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
+       {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
+       {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
+       {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
+       {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
+       {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
+       {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
+       {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
+       {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
+       {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+       {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
+       {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
+       {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+       {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+       {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+       {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
+       {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
+       {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
+       {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
+       {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+       {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+       {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+       {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+       {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+       {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+       {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+       {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+       {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+       {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+       {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+       {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+       {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+       {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+       {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+       {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+       {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+       {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+       {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+       {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+       {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+       {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+       {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+       {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+       {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+       {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+       {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+       {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+       {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+       {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+       {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+       {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+       {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+       {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+       {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+       {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+       {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+       {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+       {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+       {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+       {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+       {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0},
+       {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+       {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+       {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+       {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+       {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+       {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+       {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+       {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+       {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+       {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+       {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+       {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+       {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+       {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+       {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+       {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+       {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+       {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+       {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+       {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+       {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+       {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+       {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+       {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+       {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+       {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+       {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+       {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+       {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+       {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+       {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+       {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+       {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+       {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+       {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+       {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+       {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+       {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+       {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+       {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+       {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+       {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+       {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+       {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+       {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+       {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+       {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+       {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+       {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+       {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+       {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+       {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+       {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+       {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+       {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+       {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+       {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+       {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+       {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+       {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+       {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+       {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+       {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x07, 0, 0},
+       {0x350c, 0x04, 0, 0}, {0x350d, 0x58, 0, 0}, {0x3801, 0x8a, 0, 0},
+       {0x3803, 0x0a, 0, 0}, {0x3804, 0x07, 0, 0}, {0x3805, 0x80, 0, 0},
+       {0x3806, 0x04, 0, 0}, {0x3807, 0x39, 0, 0}, {0x3808, 0x07, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
+       {0x380c, 0x09, 0, 0}, {0x380d, 0xd6, 0, 0}, {0x380e, 0x04, 0, 0},
+       {0x380f, 0x58, 0, 0}, {0x381c, 0x11, 0, 0}, {0x381d, 0xba, 0, 0},
+       {0x381e, 0x04, 0, 0}, {0x381f, 0x48, 0, 0}, {0x3820, 0x04, 0, 0},
+       {0x3821, 0x18, 0, 0}, {0x3a08, 0x14, 0, 0}, {0x3a09, 0xe0, 0, 0},
+       {0x3a0a, 0x11, 0, 0}, {0x3a0b, 0x60, 0, 0}, {0x3a0d, 0x04, 0, 0},
+       {0x3a0e, 0x03, 0, 0}, {0x5682, 0x07, 0, 0}, {0x5683, 0x60, 0, 0},
+       {0x5686, 0x04, 0, 0}, {0x5687, 0x1c, 0, 0}, {0x5001, 0x7f, 0, 0},
+       {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, {0x460c, 0x20, 0, 0},
+       {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x471d, 0x05, 0, 0},
+       {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, {0x501f, 0x00, 0, 0},
+       {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0},
+       {0x5002, 0xe0, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_QVGA_320_240[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+       {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+       {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+       {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+       {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+       {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+       {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+       {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+       {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+       {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+       {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+       {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+       {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+       {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+       {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+       {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+       {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+       {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+       {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+       {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+       {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+       {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+       {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+       {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+       {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+       {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+       {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+       {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+       {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+       {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+       {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+       {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+       {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+       {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+       {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+       {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+       {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+       {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+       {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+       {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+       {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+       {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+       {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+       {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+       {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+       {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+       {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+       {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+       {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+       {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+       {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+       {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+       {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+       {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+       {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+       {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+       {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+       {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+       {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+       {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+       {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+       {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+       {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+       {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+       {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+       {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+       {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+       {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+       {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+       {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+       {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+       {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+       {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+       {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+       {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+       {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+       {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+       {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+       {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+       {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+       {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+       {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+       {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+       {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+       {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+       {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+       {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+       {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+       {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+       {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+       {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+       {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+       {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+       {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+       {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+       {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+       {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+       {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+       {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+       {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+       {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+       {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+       {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+       {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+       {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+       {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+       {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+       {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+       {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+       {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+       {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+       {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+       {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+       {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+       {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+       {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+       {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+       {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+       {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+       {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+       {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+       {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+       {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+       {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+       {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+       {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+       {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+       {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+       {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+       {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
+       {0x380b, 0xf0, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_NTSC_720_480[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+       {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+       {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+       {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+       {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+       {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+       {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+       {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+       {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+       {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+       {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+       {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+       {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+       {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+       {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+       {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+       {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+       {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+       {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+       {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+       {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+       {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+       {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+       {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+       {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+       {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+       {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+       {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+       {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+       {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+       {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+       {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+       {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+       {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+       {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+       {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+       {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+       {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+       {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+       {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+       {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+       {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+       {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+       {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+       {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+       {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+       {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+       {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+       {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+       {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+       {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+       {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+       {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+       {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+       {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+       {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+       {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+       {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+       {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+       {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+       {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+       {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+       {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+       {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+       {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+       {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+       {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+       {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+       {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+       {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+       {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+       {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+       {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+       {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+       {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+       {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+       {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+       {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+       {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+       {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+       {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+       {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+       {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+       {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+       {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+       {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+       {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+       {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+       {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+       {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+       {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+       {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+       {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+       {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+       {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+       {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+       {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+       {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+       {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+       {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+       {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+       {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+       {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+       {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+       {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+       {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+       {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+       {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+       {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+       {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+       {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+       {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+       {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+       {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+       {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+       {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+       {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+       {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+       {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+       {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+       {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+       {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+       {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+       {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+       {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+       {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+       {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+       {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+       {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+       {0x3824, 0x11, 0, 0}, {0x3825, 0xb4, 0, 0}, {0x3826, 0x00, 0, 0},
+       {0x3827, 0x3d, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0xd0, 0, 0}, {0x380A, 0x01, 0, 0}, {0x380B, 0xe0, 0, 0},
+       {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0},
+       {0x3807, 0x55, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0x55, 0, 0},
+       {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_PAL_720_576[] = {
+       {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+       {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+       {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+       {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+       {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+       {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+       {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+       {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+       {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+       {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+       {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+       {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+       {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+       {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+       {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+       {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+       {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+       {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+       {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+       {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+       {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+       {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+       {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+       {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+       {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+       {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+       {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+       {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+       {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+       {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+       {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+       {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+       {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+       {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+       {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+       {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+       {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+       {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+       {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+       {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+       {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+       {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+       {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+       {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+       {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+       {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+       {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+       {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+       {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+       {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+       {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+       {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+       {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+       {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+       {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+       {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+       {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+       {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+       {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+       {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+       {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+       {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+       {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+       {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+       {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+       {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+       {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+       {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+       {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+       {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+       {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+       {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+       {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+       {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+       {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+       {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+       {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+       {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+       {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+       {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+       {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+       {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+       {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+       {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+       {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+       {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+       {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+       {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+       {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+       {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+       {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+       {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+       {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+       {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+       {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+       {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+       {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+       {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+       {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+       {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+       {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+       {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+       {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+       {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+       {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+       {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+       {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+       {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+       {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+       {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+       {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+       {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+       {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+       {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+       {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+       {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+       {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+       {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+       {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+       {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+       {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+       {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+       {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+       {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+       {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+       {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+       {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+       {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+       {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+       {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+       {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+       {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+       {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+       {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+       {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+       {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+       {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+       {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+       {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+       {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+       {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+       {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+       {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+       {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+       {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+       {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+       {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+       {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+       {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+       {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+       {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+       {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+       {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+       {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+       {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+       {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+       {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+       {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+       {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+       {0x3824, 0x11, 0, 0}, {0x3825, 0xdc, 0, 0}, {0x3826, 0x00, 0, 0},
+       {0x3827, 0x08, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0},
+       {0x3809, 0xd0, 0, 0}, {0x380A, 0x02, 0, 0}, {0x380B, 0x40, 0, 0},
+       {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0},
+       {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xc0, 0, 0},
+       {0x5682, 0x04, 0, 0}, {0x5683, 0xb0, 0, 0},
+};
+
+static struct ov5642_mode_info ov5642_mode_info_data[2][ov5642_mode_MAX + 1] = {
+       {
+               {ov5642_mode_VGA_640_480,    640,  480,
+               ov5642_setting_15fps_VGA_640_480,
+               ARRAY_SIZE(ov5642_setting_15fps_VGA_640_480)},
+               {ov5642_mode_QVGA_320_240,   320,  240,
+               ov5642_setting_15fps_QVGA_320_240,
+               ARRAY_SIZE(ov5642_setting_15fps_QVGA_320_240)},
+               {ov5642_mode_NTSC_720_480,   720,  480,
+               ov5642_setting_15fps_NTSC_720_480,
+               ARRAY_SIZE(ov5642_setting_15fps_NTSC_720_480)},
+               {ov5642_mode_PAL_720_576,   720,  576,
+               ov5642_setting_15fps_PAL_720_576,
+               ARRAY_SIZE(ov5642_setting_15fps_PAL_720_576)},
+               {ov5642_mode_720P_1280_720,  1280, 720,
+               ov5642_setting_15fps_720P_1280_720,
+               ARRAY_SIZE(ov5642_setting_15fps_720P_1280_720)},
+               {ov5642_mode_1080P_1920_1080, 1920, 1080,
+               ov5642_setting_15fps_1080P_1920_1080,
+               ARRAY_SIZE(ov5642_setting_15fps_1080P_1920_1080)},
+               {ov5642_mode_QSXGA_2592_1944, 2592, 1944,
+               ov5642_setting_15fps_QSXGA_2592_1944,
+               ARRAY_SIZE(ov5642_setting_15fps_QSXGA_2592_1944)},
+               {ov5642_mode_QCIF_176_144, 176, 144,
+               ov5642_setting_15fps_QCIF_176_144,
+               ARRAY_SIZE(ov5642_setting_15fps_QCIF_176_144)},
+               {ov5642_mode_XGA_1024_768, 1024, 768,
+               ov5642_setting_15fps_XGA_1024_768,
+               ARRAY_SIZE(ov5642_setting_15fps_XGA_1024_768)},
+       },
+       {
+               {ov5642_mode_VGA_640_480,    640,  480,
+               ov5642_setting_30fps_VGA_640_480,
+               ARRAY_SIZE(ov5642_setting_30fps_VGA_640_480)},
+               {ov5642_mode_QVGA_320_240,   320,  240,
+               ov5642_setting_30fps_QVGA_320_240,
+               ARRAY_SIZE(ov5642_setting_30fps_QVGA_320_240)},
+               {ov5642_mode_NTSC_720_480,   720, 480,
+               ov5642_setting_30fps_NTSC_720_480,
+               ARRAY_SIZE(ov5642_setting_30fps_NTSC_720_480)},
+               {ov5642_mode_PAL_720_576,    720, 576,
+               ov5642_setting_30fps_PAL_720_576,
+               ARRAY_SIZE(ov5642_setting_30fps_PAL_720_576)},
+               {ov5642_mode_720P_1280_720,  1280, 720,
+               ov5642_setting_30fps_720P_1280_720,
+               ARRAY_SIZE(ov5642_setting_30fps_720P_1280_720)},
+               {ov5642_mode_1080P_1920_1080, 0, 0, NULL, 0},
+               {ov5642_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
+               {ov5642_mode_QCIF_176_144, 176, 144,
+               ov5642_setting_30fps_QCIF_176_144,
+               ARRAY_SIZE(ov5642_setting_30fps_QCIF_176_144)},
+               {ov5642_mode_XGA_1024_768, 1024, 768,
+               ov5642_setting_30fps_XGA_1024_768,
+               ARRAY_SIZE(ov5642_setting_30fps_XGA_1024_768)},
+       },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+static struct regulator *gpo_regulator;
+
+static int ov5642_probe(struct i2c_client *adapter,
+                               const struct i2c_device_id *device_id);
+static int ov5642_remove(struct i2c_client *client);
+
+static s32 ov5642_read_reg(u16 reg, u8 *val);
+static s32 ov5642_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5642_id[] = {
+       {"ov5642", 0},
+       {"ov564x", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5642_id);
+
+static struct i2c_driver ov5642_i2c_driver = {
+       .driver = {
+                 .owner = THIS_MODULE,
+                 .name  = "ov5642",
+                 },
+       .probe  = ov5642_probe,
+       .remove = ov5642_remove,
+       .id_table = ov5642_id,
+};
+
+static void ov5642_standby(s32 enable)
+{
+       if (enable)
+               gpio_set_value(pwn_gpio, 1);
+       else
+               gpio_set_value(pwn_gpio, 0);
+
+       msleep(2);
+}
+
+static void ov5642_reset(void)
+{
+       /* camera reset */
+       gpio_set_value(rst_gpio, 1);
+
+       /* camera power down */
+       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 ov5642_power_on(struct device *dev)
+{
+       int ret = 0;
+
+       io_regulator = devm_regulator_get(dev, "DOVDD");
+       if (!IS_ERR(io_regulator)) {
+               regulator_set_voltage(io_regulator,
+                                     OV5642_VOLTAGE_DIGITAL_IO,
+                                     OV5642_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,
+                                     OV5642_VOLTAGE_DIGITAL_CORE,
+                                     OV5642_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,
+                                     OV5642_VOLTAGE_ANALOG,
+                                     OV5642_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 ov5642_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(ov5642_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 ov5642_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(ov5642_data.i2c_client, au8RegBuf, 2)) {
+               pr_err("%s:write reg error:reg=%x\n",
+                               __func__, reg);
+               return -1;
+       }
+
+       if (1 != i2c_master_recv(ov5642_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 ov5642_set_rot_mode(struct reg_value *rot_mode)
+{
+       s32 i = 0;
+       s32 iModeSettingArySize = 2;
+       register u32 Delay_ms = 0;
+       register u16 RegAddr = 0;
+       register u8 Mask = 0;
+       register u8 Val = 0;
+       u8 RegVal = 0;
+       int retval = 0;
+       for (i = 0; i < iModeSettingArySize; ++i, ++rot_mode) {
+               Delay_ms = rot_mode->u32Delay_ms;
+               RegAddr = rot_mode->u16RegAddr;
+               Val = rot_mode->u8Val;
+               Mask = rot_mode->u8Mask;
+
+               if (Mask) {
+                       retval = ov5642_read_reg(RegAddr, &RegVal);
+                       if (retval < 0) {
+                               pr_err("%s, read reg 0x%x failed\n",
+                                               __func__, RegAddr);
+                               goto err;
+                       }
+
+                       Val |= RegVal;
+                       Val &= Mask;
+               }
+
+               retval = ov5642_write_reg(RegAddr, Val);
+               if (retval < 0) {
+                       pr_err("%s, write reg 0x%x failed\n",
+                                       __func__, RegAddr);
+                       goto err;
+               }
+
+               if (Delay_ms)
+                       mdelay(Delay_ms);
+       }
+err:
+       return retval;
+}
+static int ov5642_init_mode(enum ov5642_frame_rate frame_rate,
+               enum ov5642_mode mode);
+static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate,
+               enum ov5642_mode mode);
+static int ov5642_change_mode(enum ov5642_frame_rate new_frame_rate,
+               enum ov5642_frame_rate old_frame_rate,
+               enum ov5642_mode new_mode,
+               enum ov5642_mode orig_mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 i = 0;
+       s32 iModeSettingArySize = 0;
+       register u32 Delay_ms = 0;
+       register u16 RegAddr = 0;
+       register u8 Mask = 0;
+       register u8 Val = 0;
+       u8 RegVal = 0;
+       int retval = 0;
+
+       if (new_mode > ov5642_mode_MAX || new_mode < ov5642_mode_MIN) {
+               pr_err("Wrong ov5642 mode detected!\n");
+               return -1;
+       }
+
+       if ((new_frame_rate == old_frame_rate) &&
+           (new_mode == ov5642_mode_VGA_640_480) &&
+               (orig_mode == ov5642_mode_QSXGA_2592_1944)) {
+               pModeSetting = ov5642_setting_QSXGA_2_VGA;
+               iModeSettingArySize = ARRAY_SIZE(ov5642_setting_QSXGA_2_VGA);
+               ov5642_data.pix.width = 640;
+               ov5642_data.pix.height = 480;
+       } else if ((new_frame_rate == old_frame_rate) &&
+           (new_mode == ov5642_mode_QVGA_320_240) &&
+               (orig_mode == ov5642_mode_VGA_640_480)) {
+               pModeSetting = ov5642_setting_VGA_2_QVGA;
+               iModeSettingArySize = ARRAY_SIZE(ov5642_setting_VGA_2_QVGA);
+               ov5642_data.pix.width = 320;
+               ov5642_data.pix.height = 240;
+       } else {
+               retval = ov5642_write_snapshot_para(new_frame_rate, new_mode);
+               goto err;
+       }
+
+       if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 ||
+                       pModeSetting == NULL || iModeSettingArySize == 0)
+               return -EINVAL;
+
+       for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
+               Delay_ms = pModeSetting->u32Delay_ms;
+               RegAddr = pModeSetting->u16RegAddr;
+               Val = pModeSetting->u8Val;
+               Mask = pModeSetting->u8Mask;
+
+               if (Mask) {
+                       retval = ov5642_read_reg(RegAddr, &RegVal);
+                       if (retval < 0) {
+                               pr_err("read reg error addr=0x%x", RegAddr);
+                               goto err;
+                       }
+
+                       RegVal &= ~(u8)Mask;
+                       Val &= Mask;
+                       Val |= RegVal;
+               }
+
+               retval = ov5642_write_reg(RegAddr, Val);
+               if (retval < 0) {
+                       pr_err("write reg error addr=0x%x", RegAddr);
+                       goto err;
+               }
+
+               if (Delay_ms)
+                       msleep(Delay_ms);
+       }
+err:
+       return retval;
+}
+static int ov5642_init_mode(enum ov5642_frame_rate frame_rate,
+                           enum ov5642_mode mode)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 i = 0;
+       s32 iModeSettingArySize = 0;
+       register u32 Delay_ms = 0;
+       register u16 RegAddr = 0;
+       register u8 Mask = 0;
+       register u8 Val = 0;
+       u8 RegVal = 0;
+       int retval = 0;
+
+       if (mode > ov5642_mode_MAX || mode < ov5642_mode_MIN) {
+               pr_err("Wrong ov5642 mode detected!\n");
+               return -1;
+       }
+
+       pModeSetting = ov5642_mode_info_data[frame_rate][mode].init_data_ptr;
+       iModeSettingArySize =
+               ov5642_mode_info_data[frame_rate][mode].init_data_size;
+
+       ov5642_data.pix.width = ov5642_mode_info_data[frame_rate][mode].width;
+       ov5642_data.pix.height = ov5642_mode_info_data[frame_rate][mode].height;
+
+       if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 ||
+           pModeSetting == NULL || iModeSettingArySize == 0)
+               return -EINVAL;
+
+       for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
+               Delay_ms = pModeSetting->u32Delay_ms;
+               RegAddr = pModeSetting->u16RegAddr;
+               Val = pModeSetting->u8Val;
+               Mask = pModeSetting->u8Mask;
+
+               if (Mask) {
+                       retval = ov5642_read_reg(RegAddr, &RegVal);
+                       if (retval < 0) {
+                               pr_err("read reg error addr=0x%x", RegAddr);
+                               goto err;
+                       }
+
+                       RegVal &= ~(u8)Mask;
+                       Val &= Mask;
+                       Val |= RegVal;
+               }
+
+               retval = ov5642_write_reg(RegAddr, Val);
+               if (retval < 0) {
+                       pr_err("write reg error addr=0x%x", RegAddr);
+                       goto err;
+               }
+
+               if (Delay_ms)
+                       msleep(Delay_ms);
+       }
+err:
+       return retval;
+}
+
+static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate,
+       enum ov5642_mode mode)
+{
+       int ret = 0;
+       bool m_60Hz = false;
+       u16 cap_frame_rate = 50;
+       u16 g_prev_frame_rate = 225;
+
+       u8 ev_low, ev_mid, ev_high;
+       u8 ret_l, ret_m, ret_h, gain, lines_10ms;
+       u16 ulcap_ev, icap_gain, prev_maxlines;
+       u32 ulcap_ev_gain, cap_maxlines, g_prev_ev;
+
+       ov5642_write_reg(0x3503, 0x07);
+
+       ret_h = ret_m = ret_l = 0;
+       g_prev_ev = 0;
+       ov5642_read_reg(0x3500, &ret_h);
+       ov5642_read_reg(0x3501, &ret_m);
+       ov5642_read_reg(0x3502, &ret_l);
+       g_prev_ev = (ret_h << 12) + (ret_m << 4) + (ret_l >> 4);
+
+       ret_h = ret_m = ret_l = 0;
+       prev_maxlines = 0;
+       ov5642_read_reg(0x380e, &ret_h);
+       ov5642_read_reg(0x380f, &ret_l);
+       prev_maxlines = (ret_h << 8) + ret_l;
+       /*Read back AGC Gain for preview*/
+       gain = 0;
+       ov5642_read_reg(0x350b, &gain);
+
+       ret = ov5642_init_mode(frame_rate, mode);
+       if (ret < 0)
+               return ret;
+
+       ret_h = ret_m = ret_l = 0;
+       ov5642_read_reg(0x380e, &ret_h);
+       ov5642_read_reg(0x380f, &ret_l);
+       cap_maxlines = (ret_h << 8) + ret_l;
+       if (m_60Hz == true)
+               lines_10ms = cap_frame_rate * cap_maxlines/12000;
+       else
+               lines_10ms = cap_frame_rate * cap_maxlines/10000;
+
+       if (prev_maxlines == 0)
+               prev_maxlines = 1;
+
+       ulcap_ev = (g_prev_ev*(cap_frame_rate)*(cap_maxlines))/
+               (((prev_maxlines)*(g_prev_frame_rate)));
+       icap_gain = (gain & 0x0f) + 16;
+       if (gain & 0x10)
+               icap_gain = icap_gain << 1;
+
+       if (gain & 0x20)
+               icap_gain = icap_gain << 1;
+
+       if (gain & 0x40)
+               icap_gain = icap_gain << 1;
+
+       if (gain & 0x80)
+               icap_gain = icap_gain << 1;
+
+       ulcap_ev_gain = 2 * ulcap_ev * icap_gain;
+
+       if (ulcap_ev_gain < cap_maxlines*16) {
+               ulcap_ev = ulcap_ev_gain/16;
+               if (ulcap_ev > lines_10ms) {
+                       ulcap_ev /= lines_10ms;
+                       ulcap_ev *= lines_10ms;
+               }
+       } else
+               ulcap_ev = cap_maxlines;
+
+       if (ulcap_ev == 0)
+               ulcap_ev = 1;
+
+       icap_gain = (ulcap_ev_gain*2/ulcap_ev + 1)/2;
+       ev_low = ((unsigned char)ulcap_ev)<<4;
+       ev_mid = (unsigned char)(ulcap_ev >> 4) & 0xff;
+       ev_high = (unsigned char)(ulcap_ev >> 12);
+
+       gain = 0;
+       if (icap_gain > 31) {
+               gain |= 0x10;
+               icap_gain = icap_gain >> 1;
+       }
+       if (icap_gain > 31) {
+               gain |= 0x20;
+               icap_gain = icap_gain >> 1;
+       }
+       if (icap_gain > 31) {
+               gain |= 0x40;
+               icap_gain = icap_gain >> 1;
+       }
+       if (icap_gain > 31) {
+               gain |= 0x80;
+               icap_gain = icap_gain >> 1;
+       }
+       if (icap_gain > 16)
+               gain |= ((icap_gain - 16) & 0x0f);
+
+       if (gain == 0x10)
+               gain = 0x11;
+
+       ov5642_write_reg(0x350b, gain);
+       ov5642_write_reg(0x3502, ev_low);
+       ov5642_write_reg(0x3501, ev_mid);
+       ov5642_write_reg(0x3500, ev_high);
+       msleep(500);
+
+       return ret ;
+}
+
+
+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+       if (s == NULL) {
+               pr_err("   ERROR!! no slave device set!\n");
+               return -1;
+       }
+
+       memset(p, 0, sizeof(*p));
+       p->u.bt656.clock_curr = ov5642_data.mclk;
+       pr_debug("   clock_curr=mclk=%d\n", ov5642_data.mclk);
+       p->if_type = V4L2_IF_TYPE_BT656;
+       p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+       p->u.bt656.clock_min = OV5642_XCLK_MIN;
+       p->u.bt656.clock_max = OV5642_XCLK_MAX;
+       p->u.bt656.bt_sync_correct = 1;  /* Indicate external vsync */
+
+       return 0;
+}
+
+/*!
+ * ioctl_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 ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+       struct sensor_data *sensor = s->priv;
+
+       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;
+               /* Make sure power on */
+               ov5642_standby(0);
+       } 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);
+
+               ov5642_standby(1);
+       }
+
+       sensor->on = on;
+
+       return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+       struct sensor_data *sensor = s->priv;
+       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;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 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 ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+       struct sensor_data *sensor = s->priv;
+       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+       u32 tgt_fps, old_fps;   /* target frames per secound */
+       enum ov5642_frame_rate new_frame_rate, old_frame_rate;
+       int ret = 0;
+
+       /* Make sure power on */
+       ov5642_standby(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)
+                       new_frame_rate = ov5642_15_fps;
+               else if (tgt_fps == 30)
+                       new_frame_rate = ov5642_30_fps;
+               else {
+                       pr_err(" The camera frame rate is not supported!\n");
+                       return -EINVAL;
+               }
+
+               if (sensor->streamcap.timeperframe.numerator != 0)
+                       old_fps = sensor->streamcap.timeperframe.denominator /
+                               sensor->streamcap.timeperframe.numerator;
+               else
+                       old_fps = 30;
+
+               if (old_fps == 15)
+                       old_frame_rate = ov5642_15_fps;
+               else if (old_fps == 30)
+                       old_frame_rate = ov5642_30_fps;
+               else {
+                       pr_warning(" No valid frame rate set!\n");
+                       old_frame_rate = ov5642_30_fps;
+               }
+
+               ret = ov5642_change_mode(new_frame_rate, old_frame_rate,
+                               a->parm.capture.capturemode,
+                               sensor->streamcap.capturemode);
+               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;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+       struct sensor_data *sensor = s->priv;
+
+       f->fmt.pix = sensor->pix;
+
+       return 0;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array.  Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+       int ret = 0;
+
+       switch (vc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               vc->value = ov5642_data.brightness;
+               break;
+       case V4L2_CID_HUE:
+               vc->value = ov5642_data.hue;
+               break;
+       case V4L2_CID_CONTRAST:
+               vc->value = ov5642_data.contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               vc->value = ov5642_data.saturation;
+               break;
+       case V4L2_CID_RED_BALANCE:
+               vc->value = ov5642_data.red;
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               vc->value = ov5642_data.blue;
+               break;
+       case V4L2_CID_EXPOSURE:
+               vc->value = ov5642_data.ae_mode;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array).  Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+       int retval = 0;
+       struct sensor_data *sensor = s->priv;
+       __u32 captureMode = sensor->streamcap.capturemode;
+       struct reg_value *rot_mode = NULL;
+
+       pr_debug("In ov5642:ioctl_s_ctrl %d\n",
+                vc->id);
+
+       switch (vc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               break;
+       case V4L2_CID_CONTRAST:
+               break;
+       case V4L2_CID_SATURATION:
+               break;
+       case V4L2_CID_HUE:
+               break;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               break;
+       case V4L2_CID_RED_BALANCE:
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               break;
+       case V4L2_CID_GAMMA:
+               break;
+       case V4L2_CID_EXPOSURE:
+               break;
+       case V4L2_CID_AUTOGAIN:
+               break;
+       case V4L2_CID_GAIN:
+               break;
+       case V4L2_CID_HFLIP:
+               break;
+       case V4L2_CID_VFLIP:
+               break;
+       case V4L2_CID_MXC_ROT:
+       case V4L2_CID_MXC_VF_ROT:
+               switch (vc->value) {
+               case V4L2_MXC_ROTATE_NONE:
+                       if (captureMode == ov5642_mode_QSXGA_2592_1944)
+                               rot_mode = ov5642_rot_none_FULL;
+                       else
+                               rot_mode = ov5642_rot_none_VGA;
+
+                       if (ov5642_set_rot_mode(rot_mode))
+                               retval = -EPERM;
+                       break;
+               case V4L2_MXC_ROTATE_VERT_FLIP:
+                       if (captureMode == ov5642_mode_QSXGA_2592_1944)
+                               rot_mode = ov5642_rot_vert_flip_FULL;
+                       else
+                               rot_mode = ov5642_rot_vert_flip_VGA ;
+
+                       if (ov5642_set_rot_mode(rot_mode))
+                               retval = -EPERM;
+                       break;
+               case V4L2_MXC_ROTATE_HORIZ_FLIP:
+                       if (captureMode == ov5642_mode_QSXGA_2592_1944)
+                               rot_mode = ov5642_rot_horiz_flip_FULL;
+                       else
+                               rot_mode = ov5642_rot_horiz_flip_VGA;
+
+                       if (ov5642_set_rot_mode(rot_mode))
+                               retval = -EPERM;
+                       break;
+               case V4L2_MXC_ROTATE_180:
+                       if (captureMode == ov5642_mode_QSXGA_2592_1944)
+                               rot_mode = ov5642_rot_180_FULL;
+                       else
+                               rot_mode = ov5642_rot_180_VGA;
+
+                       if (ov5642_set_rot_mode(rot_mode))
+                               retval = -EPERM;
+                       break;
+               default:
+                       retval = -EPERM;
+                       break;
+               }
+               break;
+       default:
+               retval = -EPERM;
+               break;
+       }
+
+       return retval;
+}
+
+/*!
+ * ioctl_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 ioctl_enum_framesizes(struct v4l2_int_device *s,
+                                struct v4l2_frmsizeenum *fsize)
+{
+       if (fsize->index > ov5642_mode_MAX)
+               return -EINVAL;
+
+       fsize->pixel_format = ov5642_data.pix.pixelformat;
+       fsize->discrete.width =
+                       max(ov5642_mode_info_data[0][fsize->index].width,
+                           ov5642_mode_info_data[1][fsize->index].width);
+       fsize->discrete.height =
+                       max(ov5642_mode_info_data[0][fsize->index].height,
+                           ov5642_mode_info_data[1][fsize->index].height);
+       return 0;
+}
+
+/*!
+ * ioctl_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 ioctl_enum_frameintervals(struct v4l2_int_device *s,
+                                        struct v4l2_frmivalenum *fival)
+{
+       int i, j, count;
+
+       if (fival->index < 0 || fival->index > ov5642_mode_MAX)
+               return -EINVAL;
+
+       if (fival->pixel_format == 0 || fival->width == 0 ||
+                       fival->height == 0) {
+               pr_warning("Please assign pixelformat, width and height.\n");
+               return -EINVAL;
+       }
+
+       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       fival->discrete.numerator = 1;
+
+       count = 0;
+       for (i = 0; i < ARRAY_SIZE(ov5642_mode_info_data); i++) {
+               for (j = 0; j < (ov5642_mode_MAX + 1); j++) {
+                       if (fival->pixel_format == ov5642_data.pix.pixelformat
+                        && fival->width == ov5642_mode_info_data[i][j].width
+                        && fival->height == ov5642_mode_info_data[i][j].height
+                        && ov5642_mode_info_data[i][j].init_data_ptr != NULL) {
+                               count++;
+                       }
+                       if (fival->index == (count - 1)) {
+                               fival->discrete.denominator =
+                                               ov5642_framerates[i];
+                               return 0;
+                       }
+               }
+       }
+
+       return -EINVAL;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ *                     VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+       ((struct v4l2_dbg_chip_ident *)id)->match.type =
+                                       V4L2_CHIP_MATCH_I2C_DRIVER;
+       strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5642_camera");
+
+       return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+
+       return 0;
+}
+
+/*!
+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
+ * @s: pointer to standard V4L2 device structure
+ * @fmt: pointer to standard V4L2 fmt description structure
+ *
+ * Return 0.
+ */
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+                             struct v4l2_fmtdesc *fmt)
+{
+       if (fmt->index > 0)     /* only 1 pixelformat support so far */
+               return -EINVAL;
+
+       fmt->pixelformat = ov5642_data.pix.pixelformat;
+
+       return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+       struct reg_value *pModeSetting = NULL;
+       s32 i = 0;
+       s32 iModeSettingArySize = 0;
+       register u32 Delay_ms = 0;
+       register u16 RegAddr = 0;
+       register u8 Mask = 0;
+       register u8 Val = 0;
+       u8 RegVal = 0;
+       int retval = 0;
+
+       struct sensor_data *sensor = s->priv;
+       u32 tgt_xclk;   /* target xclk */
+       u32 tgt_fps;    /* target frames per secound */
+       enum ov5642_frame_rate frame_rate;
+
+       ov5642_data.on = true;
+
+       /* mclk */
+       tgt_xclk = ov5642_data.mclk;
+       tgt_xclk = min(tgt_xclk, (u32)OV5642_XCLK_MAX);
+       tgt_xclk = max(tgt_xclk, (u32)OV5642_XCLK_MIN);
+       ov5642_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 = sensor->streamcap.timeperframe.denominator /
+                 sensor->streamcap.timeperframe.numerator;
+
+       if (tgt_fps == 15)
+               frame_rate = ov5642_15_fps;
+       else if (tgt_fps == 30)
+               frame_rate = ov5642_30_fps;
+       else
+               return -EINVAL; /* Only support 15fps or 30fps now. */
+
+       pModeSetting = ov5642_initial_setting;
+       iModeSettingArySize = ARRAY_SIZE(ov5642_initial_setting);
+
+       for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
+               Delay_ms = pModeSetting->u32Delay_ms;
+               RegAddr = pModeSetting->u16RegAddr;
+               Val = pModeSetting->u8Val;
+               Mask = pModeSetting->u8Mask;
+               if (Mask) {
+                       retval = ov5642_read_reg(RegAddr, &RegVal);
+                       if (retval < 0)
+                               goto err;
+
+                       RegVal &= ~(u8)Mask;
+                       Val &= Mask;
+                       Val |= RegVal;
+               }
+
+               retval = ov5642_write_reg(RegAddr, Val);
+               if (retval < 0)
+                       goto err;
+
+               if (Delay_ms)
+                       msleep(Delay_ms);
+       }
+err:
+       return retval;
+}
+
+/*!
+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Delinitialise the device when slave detaches to the master.
+ */
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+       return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module and links them to the
+ * enumeration.
+ */
+static struct v4l2_int_ioctl_desc ov5642_ioctl_desc[] = {
+       { vidioc_int_dev_init_num,
+         (v4l2_int_ioctl_func *)ioctl_dev_init },
+       { vidioc_int_dev_exit_num, ioctl_dev_exit},
+       { vidioc_int_s_power_num,
+         (v4l2_int_ioctl_func *)ioctl_s_power },
+       { vidioc_int_g_ifparm_num,
+         (v4l2_int_ioctl_func *)ioctl_g_ifparm },
+/*     { vidioc_int_g_needs_reset_num,
+         (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, */
+/*     { vidioc_int_reset_num,
+         (v4l2_int_ioctl_func *)ioctl_reset }, */
+       { vidioc_int_init_num,
+         (v4l2_int_ioctl_func *)ioctl_init },
+       { vidioc_int_enum_fmt_cap_num,
+         (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
+/*     { vidioc_int_try_fmt_cap_num,
+         (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, */
+       { vidioc_int_g_fmt_cap_num,
+         (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
+/*     { vidioc_int_s_fmt_cap_num,
+         (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, */
+       { vidioc_int_g_parm_num,
+         (v4l2_int_ioctl_func *)ioctl_g_parm },
+       { vidioc_int_s_parm_num,
+         (v4l2_int_ioctl_func *)ioctl_s_parm },
+/*     { vidioc_int_queryctrl_num,
+         (v4l2_int_ioctl_func *)ioctl_queryctrl }, */
+       { vidioc_int_g_ctrl_num,
+         (v4l2_int_ioctl_func *)ioctl_g_ctrl },
+       { vidioc_int_s_ctrl_num,
+         (v4l2_int_ioctl_func *)ioctl_s_ctrl },
+       { vidioc_int_enum_framesizes_num,
+         (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
+       { vidioc_int_enum_frameintervals_num,
+         (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
+       { vidioc_int_g_chip_ident_num,
+         (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
+};
+
+static struct v4l2_int_slave ov5642_slave = {
+       .ioctls = ov5642_ioctl_desc,
+       .num_ioctls = ARRAY_SIZE(ov5642_ioctl_desc),
+};
+
+static struct v4l2_int_device ov5642_int_device = {
+       .module = THIS_MODULE,
+       .name = "ov5642",
+       .type = v4l2_int_type_slave,
+       .u = {
+               .slave = &ov5642_slave,
+       },
+};
+
+/*!
+ * ov5642 I2C probe function
+ *
+ * @param adapter            struct i2c_adapter *
+ * @return  Error code indicating success or failure
+ */
+static int ov5642_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;
+
+       /* ov5642 pinctrl */
+       pinctrl = devm_pinctrl_get_select_default(dev);
+       if (IS_ERR(pinctrl)) {
+               dev_err(dev, "ov5642 setup pinctrl failed!");
+               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_warn(dev, "no sensor pwdn pin available");
+               return -EINVAL;
+       }
+       retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "ov5642_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_warn(dev, "no sensor reset pin available");
+               return -EINVAL;
+       }
+       retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "ov5642_reset");
+       if (retval < 0)
+               return retval;
+
+       /* Set initial values for the sensor struct. */
+       memset(&ov5642_data, 0, sizeof(ov5642_data));
+       ov5642_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+       if (IS_ERR(ov5642_data.sensor_clk)) {
+               /* assuming clock enabled by default */
+               ov5642_data.sensor_clk = NULL;
+               dev_err(dev, "clock-frequency missing or invalid\n");
+               return PTR_ERR(ov5642_data.sensor_clk);
+       }
+
+       retval = of_property_read_u32(dev->of_node, "mclk",
+                                       (u32 *) &(ov5642_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 *) &(ov5642_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",
+                                       &(ov5642_data.csi));
+       if (retval) {
+               dev_err(dev, "csi_id missing or invalid\n");
+               return retval;
+       }
+
+       clk_prepare_enable(ov5642_data.sensor_clk);
+
+       ov5642_data.io_init = ov5642_reset;
+       ov5642_data.i2c_client = client;
+       ov5642_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+       ov5642_data.pix.width = 640;
+       ov5642_data.pix.height = 480;
+       ov5642_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+                                          V4L2_CAP_TIMEPERFRAME;
+       ov5642_data.streamcap.capturemode = 0;
+       ov5642_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+       ov5642_data.streamcap.timeperframe.numerator = 1;
+
+       ov5642_power_on(&client->dev);
+
+       ov5642_reset();
+
+       ov5642_standby(0);
+
+       retval = ov5642_read_reg(OV5642_CHIP_ID_HIGH_BYTE, &chip_id_high);
+       if (retval < 0 || chip_id_high != 0x56) {
+               pr_warning("camera ov5642 is not found\n");
+               clk_disable_unprepare(ov5642_data.sensor_clk);
+               return -ENODEV;
+       }
+       retval = ov5642_read_reg(OV5642_CHIP_ID_LOW_BYTE, &chip_id_low);
+       if (retval < 0 || chip_id_low != 0x42) {
+               pr_warning("camera ov5642 is not found\n");
+               clk_disable_unprepare(ov5642_data.sensor_clk);
+               return -ENODEV;
+       }
+
+       ov5642_standby(1);
+
+       ov5642_int_device.priv = &ov5642_data;
+       retval = v4l2_int_device_register(&ov5642_int_device);
+
+       clk_disable_unprepare(ov5642_data.sensor_clk);
+
+       pr_info("camera ov5642 is found\n");
+       return retval;
+}
+
+/*!
+ * ov5642 I2C detach function
+ *
+ * @param client            struct i2c_client *
+ * @return  Error code indicating success or failure
+ */
+static int ov5642_remove(struct i2c_client *client)
+{
+       v4l2_int_device_unregister(&ov5642_int_device);
+
+       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;
+}
+
+/*!
+ * ov5642 init function
+ * Called by insmod ov5642_camera.ko.
+ *
+ * @return  Error code indicating success or failure
+ */
+static __init int ov5642_init(void)
+{
+       u8 err;
+
+       err = i2c_add_driver(&ov5642_i2c_driver);
+       if (err != 0)
+               pr_err("%s:driver registration failed, error=%d\n",
+                       __func__, err);
+
+       return err;
+}
+
+/*!
+ * OV5642 cleanup function
+ * Called on rmmod ov5642_camera.ko
+ *
+ * @return  Error code indicating success or failure
+ */
+static void __exit ov5642_clean(void)
+{
+       i2c_del_driver(&ov5642_i2c_driver);
+}
+
+module_init(ov5642_init);
+module_exit(ov5642_clean);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5642 Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/capture/v4l2-int-device.c b/drivers/media/platform/mxc/capture/v4l2-int-device.c
new file mode 100644 (file)
index 0000000..e49da15
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * drivers/media/video/v4l2-int-device.c
+ *
+ * V4L2 internal ioctl interface.
+ *
+ * Copyright 2005-2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/sort.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+#include "v4l2-int-device.h"
+
+static DEFINE_MUTEX(mutex);
+static LIST_HEAD(int_list);
+
+void v4l2_int_device_try_attach_all(void)
+{
+       struct v4l2_int_device *m, *s;
+
+       list_for_each_entry(m, &int_list, head) {
+               if (m->type != v4l2_int_type_master)
+                       continue;
+
+               list_for_each_entry(s, &int_list, head) {
+                       if (s->type != v4l2_int_type_slave)
+                               continue;
+
+                       /* Slave is connected? */
+                       if (s->u.slave->master)
+                               continue;
+
+                       /* Slave wants to attach to master? */
+                       if (s->u.slave->attach_to[0] != 0
+                           && strncmp(m->name, s->u.slave->attach_to,
+                                      V4L2NAMESIZE))
+                               continue;
+
+                       if (!try_module_get(m->module))
+                               continue;
+
+                       s->u.slave->master = m;
+                       if (m->u.master->attach(s)) {
+                               s->u.slave->master = NULL;
+                               module_put(m->module);
+                               continue;
+                       }
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(v4l2_int_device_try_attach_all);
+
+static int ioctl_sort_cmp(const void *a, const void *b)
+{
+       const struct v4l2_int_ioctl_desc *d1 = a, *d2 = b;
+
+       if (d1->num > d2->num)
+               return 1;
+
+       if (d1->num < d2->num)
+               return -1;
+
+       return 0;
+}
+
+int v4l2_int_device_register(struct v4l2_int_device *d)
+{
+       if (d->type == v4l2_int_type_slave)
+               sort(d->u.slave->ioctls, d->u.slave->num_ioctls,
+                    sizeof(struct v4l2_int_ioctl_desc),
+                    &ioctl_sort_cmp, NULL);
+       mutex_lock(&mutex);
+       list_add(&d->head, &int_list);
+       v4l2_int_device_try_attach_all();
+       mutex_unlock(&mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_int_device_register);
+
+void v4l2_int_device_unregister(struct v4l2_int_device *d)
+{
+       mutex_lock(&mutex);
+       list_del(&d->head);
+       if (d->type == v4l2_int_type_slave
+           && d->u.slave->master != NULL) {
+               d->u.slave->master->u.master->detach(d);
+               module_put(d->u.slave->master->module);
+               d->u.slave->master = NULL;
+       }
+       mutex_unlock(&mutex);
+}
+EXPORT_SYMBOL_GPL(v4l2_int_device_unregister);
+
+/* Adapted from search_extable in extable.c. */
+static v4l2_int_ioctl_func *find_ioctl(struct v4l2_int_slave *slave, int cmd,
+                                      v4l2_int_ioctl_func *no_such_ioctl)
+{
+       const struct v4l2_int_ioctl_desc *first = slave->ioctls;
+       const struct v4l2_int_ioctl_desc *last =
+               first + slave->num_ioctls - 1;
+
+       while (first <= last) {
+               const struct v4l2_int_ioctl_desc *mid;
+
+               mid = (last - first) / 2 + first;
+
+               if (mid->num < cmd)
+                       first = mid + 1;
+               else if (mid->num > cmd)
+                       last = mid - 1;
+               else
+                       return mid->func;
+       }
+
+       return no_such_ioctl;
+}
+
+static int no_such_ioctl_0(struct v4l2_int_device *d)
+{
+       return -ENOIOCTLCMD;
+}
+
+int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd)
+{
+       return ((v4l2_int_ioctl_func_0 *)
+               find_ioctl(d->u.slave, cmd,
+                          (v4l2_int_ioctl_func *)no_such_ioctl_0))(d);
+}
+EXPORT_SYMBOL_GPL(v4l2_int_ioctl_0);
+
+static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg)
+{
+       return -ENOIOCTLCMD;
+}
+
+int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg)
+{
+       return ((v4l2_int_ioctl_func_1 *)
+               find_ioctl(d->u.slave, cmd,
+                          (v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg);
+}
+EXPORT_SYMBOL_GPL(v4l2_int_ioctl_1);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/v4l2-int-device.h b/drivers/media/platform/mxc/capture/v4l2-int-device.h
new file mode 100644 (file)
index 0000000..810d87f
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * include/media/v4l2-int-device.h
+ *
+ * V4L2 internal ioctl interface.
+ *
+ * Copyright 2005-2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef V4L2_INT_DEVICE_H
+#define V4L2_INT_DEVICE_H
+
+#include <media/v4l2-common.h>
+
+#define V4L2NAMESIZE 32
+
+/*
+ *
+ * The internal V4L2 device interface core.
+ *
+ */
+
+enum v4l2_int_type {
+       v4l2_int_type_master = 1,
+       v4l2_int_type_slave
+};
+
+struct module;
+
+struct v4l2_int_device;
+
+struct v4l2_int_master {
+       int (*attach)(struct v4l2_int_device *slave);
+       void (*detach)(struct v4l2_int_device *slave);
+};
+
+typedef int (v4l2_int_ioctl_func)(struct v4l2_int_device *);
+typedef int (v4l2_int_ioctl_func_0)(struct v4l2_int_device *);
+typedef int (v4l2_int_ioctl_func_1)(struct v4l2_int_device *, void *);
+
+struct v4l2_int_ioctl_desc {
+       int num;
+       v4l2_int_ioctl_func *func;
+};
+
+struct v4l2_int_slave {
+       /* Don't touch master. */
+       struct v4l2_int_device *master;
+
+       char attach_to[V4L2NAMESIZE];
+
+       int num_ioctls;
+       struct v4l2_int_ioctl_desc *ioctls;
+};
+
+struct v4l2_int_device {
+       /* Don't touch head. */
+       struct list_head head;
+
+       struct module *module;
+
+       char name[V4L2NAMESIZE];
+
+       enum v4l2_int_type type;
+       union {
+               struct v4l2_int_master *master;
+               struct v4l2_int_slave *slave;
+       } u;
+
+       void *priv;
+};
+
+void v4l2_int_device_try_attach_all(void);
+
+int v4l2_int_device_register(struct v4l2_int_device *d);
+void v4l2_int_device_unregister(struct v4l2_int_device *d);
+
+int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd);
+int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg);
+
+/*
+ *
+ * Types and definitions for IOCTL commands.
+ *
+ */
+
+enum v4l2_power {
+       V4L2_POWER_OFF = 0,
+       V4L2_POWER_ON,
+       V4L2_POWER_STANDBY,
+};
+
+/* Slave interface type. */
+enum v4l2_if_type {
+       /*
+        * Parallel 8-, 10- or 12-bit interface, used by for example
+        * on certain image sensors.
+        */
+       V4L2_IF_TYPE_BT656,
+};
+
+enum v4l2_if_type_bt656_mode {
+       /*
+        * Modes without Bt synchronisation codes. Separate
+        * synchronisation signal lines are used.
+        */
+       V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT,
+       V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT,
+       V4L2_IF_TYPE_BT656_MODE_NOBT_12BIT,
+       /*
+        * Use Bt synchronisation codes. The vertical and horizontal
+        * synchronisation is done based on synchronisation codes.
+        */
+       V4L2_IF_TYPE_BT656_MODE_BT_8BIT,
+       V4L2_IF_TYPE_BT656_MODE_BT_10BIT,
+};
+
+struct v4l2_if_type_bt656 {
+       /*
+        * 0: Frame begins when vsync is high.
+        * 1: Frame begins when vsync changes from low to high.
+        */
+       unsigned frame_start_on_rising_vs:1;
+       /* Use Bt synchronisation codes for sync correction. */
+       unsigned bt_sync_correct:1;
+       /* Swap every two adjacent image data elements. */
+       unsigned swap:1;
+       /* Inverted latch clock polarity from slave. */
+       unsigned latch_clk_inv:1;
+       /* Hs polarity. 0 is active high, 1 active low. */
+       unsigned nobt_hs_inv:1;
+       /* Vs polarity. 0 is active high, 1 active low. */
+       unsigned nobt_vs_inv:1;
+       enum v4l2_if_type_bt656_mode mode;
+       /* Minimum accepted bus clock for slave (in Hz). */
+       u32 clock_min;
+       /* Maximum accepted bus clock for slave. */
+       u32 clock_max;
+       /*
+        * Current wish of the slave. May only change in response to
+        * ioctls that affect image capture.
+        */
+       u32 clock_curr;
+};
+
+struct v4l2_ifparm {
+       enum v4l2_if_type if_type;
+       union {
+               struct v4l2_if_type_bt656 bt656;
+       } u;
+};
+
+/* IOCTL command numbers. */
+enum v4l2_int_ioctl_num {
+       /*
+        *
+        * "Proper" V4L ioctls, as in struct video_device.
+        *
+        */
+       vidioc_int_enum_fmt_cap_num = 1,
+       vidioc_int_g_fmt_cap_num,
+       vidioc_int_s_fmt_cap_num,
+       vidioc_int_try_fmt_cap_num,
+       vidioc_int_queryctrl_num,
+       vidioc_int_g_ctrl_num,
+       vidioc_int_s_ctrl_num,
+       vidioc_int_cropcap_num,
+       vidioc_int_g_crop_num,
+       vidioc_int_s_crop_num,
+       vidioc_int_g_parm_num,
+       vidioc_int_s_parm_num,
+       vidioc_int_querystd_num,
+       vidioc_int_s_std_num,
+       vidioc_int_s_video_routing_num,
+
+       /*
+        *
+        * Strictly internal ioctls.
+        *
+        */
+       /* Initialise the device when slave attaches to the master. */
+       vidioc_int_dev_init_num = 1000,
+       /* Delinitialise the device at slave detach. */
+       vidioc_int_dev_exit_num,
+       /* Set device power state. */
+       vidioc_int_s_power_num,
+       /*
+       * Get slave private data, e.g. platform-specific slave
+       * configuration used by the master.
+       */
+       vidioc_int_g_priv_num,
+       /* Get slave interface parameters. */
+       vidioc_int_g_ifparm_num,
+       /* Does the slave need to be reset after VIDIOC_DQBUF? */
+       vidioc_int_g_needs_reset_num,
+       vidioc_int_enum_framesizes_num,
+       vidioc_int_enum_frameintervals_num,
+
+       /*
+        *
+        * VIDIOC_INT_* ioctls.
+        *
+        */
+       /* VIDIOC_INT_RESET */
+       vidioc_int_reset_num,
+       /* VIDIOC_INT_INIT */
+       vidioc_int_init_num,
+       /* VIDIOC_DBG_G_CHIP_IDENT */
+       vidioc_int_g_chip_ident_num,
+
+       /*
+        *
+        * Start of private ioctls.
+        *
+        */
+       vidioc_int_priv_start_num = 2000,
+};
+
+/*
+ *
+ * IOCTL wrapper functions for better type checking.
+ *
+ */
+
+#define V4L2_INT_WRAPPER_0(name)                                       \
+       static inline int vidioc_int_##name(struct v4l2_int_device *d)  \
+       {                                                               \
+               return v4l2_int_ioctl_0(d, vidioc_int_##name##_num);    \
+       }                                                               \
+                                                                       \
+       static inline struct v4l2_int_ioctl_desc                        \
+       vidioc_int_##name##_cb(int (*func)                              \
+                              (struct v4l2_int_device *))              \
+       {                                                               \
+               struct v4l2_int_ioctl_desc desc;                        \
+                                                                       \
+               desc.num = vidioc_int_##name##_num;                     \
+               desc.func = (v4l2_int_ioctl_func *)func;                \
+                                                                       \
+               return desc;                                            \
+       }
+
+#define V4L2_INT_WRAPPER_1(name, arg_type, asterisk)                   \
+       static inline int vidioc_int_##name(struct v4l2_int_device *d,  \
+                                           arg_type asterisk arg)      \
+       {                                                               \
+               return v4l2_int_ioctl_1(d, vidioc_int_##name##_num,     \
+                                       (void *)(unsigned long)arg);    \
+       }                                                               \
+                                                                       \
+       static inline struct v4l2_int_ioctl_desc                        \
+       vidioc_int_##name##_cb(int (*func)                              \
+                              (struct v4l2_int_device *,               \
+                               arg_type asterisk))                     \
+       {                                                               \
+               struct v4l2_int_ioctl_desc desc;                        \
+                                                                       \
+               desc.num = vidioc_int_##name##_num;                     \
+               desc.func = (v4l2_int_ioctl_func *)func;                \
+                                                                       \
+               return desc;                                            \
+       }
+
+V4L2_INT_WRAPPER_1(enum_fmt_cap, struct v4l2_fmtdesc, *);
+V4L2_INT_WRAPPER_1(g_fmt_cap, struct v4l2_format, *);
+V4L2_INT_WRAPPER_1(s_fmt_cap, struct v4l2_format, *);
+V4L2_INT_WRAPPER_1(try_fmt_cap, struct v4l2_format, *);
+V4L2_INT_WRAPPER_1(queryctrl, struct v4l2_queryctrl, *);
+V4L2_INT_WRAPPER_1(g_ctrl, struct v4l2_control, *);
+V4L2_INT_WRAPPER_1(s_ctrl, struct v4l2_control, *);
+V4L2_INT_WRAPPER_1(cropcap, struct v4l2_cropcap, *);
+V4L2_INT_WRAPPER_1(g_crop, struct v4l2_crop, *);
+V4L2_INT_WRAPPER_1(s_crop, struct v4l2_crop, *);
+V4L2_INT_WRAPPER_1(g_parm, struct v4l2_streamparm, *);
+V4L2_INT_WRAPPER_1(s_parm, struct v4l2_streamparm, *);
+V4L2_INT_WRAPPER_1(querystd, v4l2_std_id, *);
+V4L2_INT_WRAPPER_1(s_std, v4l2_std_id, *);
+V4L2_INT_WRAPPER_1(s_video_routing, struct v4l2_routing, *);
+
+V4L2_INT_WRAPPER_0(dev_init);
+V4L2_INT_WRAPPER_0(dev_exit);
+V4L2_INT_WRAPPER_1(s_power, enum v4l2_power, /*dummy arg*/);
+V4L2_INT_WRAPPER_1(g_priv, void, *);
+V4L2_INT_WRAPPER_1(g_ifparm, struct v4l2_ifparm, *);
+V4L2_INT_WRAPPER_1(g_needs_reset, void, *);
+V4L2_INT_WRAPPER_1(enum_framesizes, struct v4l2_frmsizeenum, *);
+V4L2_INT_WRAPPER_1(enum_frameintervals, struct v4l2_frmivalenum, *);
+
+V4L2_INT_WRAPPER_0(reset);
+V4L2_INT_WRAPPER_0(init);
+V4L2_INT_WRAPPER_1(g_chip_ident, int, *);
+
+#endif
diff --git a/drivers/media/platform/mxc/subdev/Kconfig b/drivers/media/platform/mxc/subdev/Kconfig
new file mode 100644 (file)
index 0000000..b8e0ebb
--- /dev/null
@@ -0,0 +1,38 @@
+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
new file mode 100644 (file)
index 0000000..25b0d64
--- /dev/null
@@ -0,0 +1,14 @@
+#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
new file mode 100644 (file)
index 0000000..f45aa44
--- /dev/null
@@ -0,0 +1,1961 @@
+/*
+ * Copyright (C) 2014-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
+ */
+
+/*!
+ * @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_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;
+       struct mx6s_csi_mux csi_mux;
+};
+
+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_32bit_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_set_16bit_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 * 2) << 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_set_8bit_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);
+}
+
+/*
+ *  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 mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct mx6s_buffer *buf = container_of(vb, 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;
+
+       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:
+               csi_set_32bit_imagpara(csi_dev, pix->width, pix->height);
+               break;
+       case V4L2_PIX_FMT_UYVY:
+               csi_set_16bit_imagpara(csi_dev, pix->width, pix->height);
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               csi_set_16bit_imagpara(csi_dev, pix->width, pix->height);
+               break;
+       case V4L2_PIX_FMT_SBGGR8:
+               csi_set_8bit_imagpara(csi_dev, pix->width, pix->height);
+               break;
+       default:
+               pr_debug("   case not supported\n");
+               return -EINVAL;
+       }
+
+       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;
+       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;
+       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.state == VB2_BUF_STATE_ACTIVE)
+                       vb2_buffer_done(&buf->vb, 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.state == VB2_BUF_STATE_ACTIVE)
+                       vb2_buffer_done(&buf->vb, 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;
+               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;
+       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 cr1, 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 (status & BIT_HRESP_ERR_INT) {
+               /* 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);
+
+               pr_warning("Hresponse error is detected.\n");
+       }
+
+       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;
+       }
+
+       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;
+       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);
+
+       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 struct of_device_id mx6s_csi_dt_ids[] = {
+       { .compatible = "fsl,imx6s-csi", },
+       { /* 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
new file mode 100644 (file)
index 0000000..db09ba0
--- /dev/null
@@ -0,0 +1,1242 @@
+/*
+ * Freescale i.MX7 SoC series MIPI-CSI V3.3 receiver driver
+ *
+ * Copyright (C) 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
+ */
+/*
+ * 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
+ * @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 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);
+
+       ret = regulator_enable(state->mipi_phy_regulator);
+       if (ret) {
+               dev_err(state->dev, "failed to set mipi regulator.\n");
+               return ret;
+       }
+       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 settle)
+{
+       u32 val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL);
+
+       val = (val & ~MIPI_CSIS_DPHYCTRL_HSS_MASK) | (settle << 24);
+       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);
+
+       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);
+               state->flags |= ST_STREAMING;
+       } else {
+               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);
+       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, wclk: %d, freq: %u\n",
+                state->num_lanes, state->hs_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
new file mode 100644 (file)
index 0000000..00690d6
--- /dev/null
@@ -0,0 +1,822 @@
+/*
+ * 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_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,
+       .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
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/subdev/ov5640.c b/drivers/media/platform/mxc/subdev/ov5640.c
new file mode 100644 (file)
index 0000000..1e33d02
--- /dev/null
@@ -0,0 +1,1898 @@
+/*
+ * 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_frmsizeenum *fsize)
+                              struct v4l2_subdev_pad_config *cfg,
+                              struct v4l2_subdev_frame_size_enum *fse)
+{
+       if (fse->index > ov5640_mode_MAX)
+               return -EINVAL;
+
+//     fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+       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_frmivalenum *fival)
+               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
new file mode 100644 (file)
index 0000000..ca3bc52
--- /dev/null
@@ -0,0 +1,1949 @@
+/*
+ * 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 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,
+       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, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
+};
+
+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
+
+       {0x3035, 0x14, 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}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
+       {0x3035, 0x22, 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, 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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
+
+       {0x3035, 0x14, 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}, {0x3503, 0x00, 0, 0},
+       {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+       {0x380b, 0x00, 0, 0}, {0x3035, 0x12, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
+       {0x3035, 0x22, 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, 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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3808, 0x04, 0, 0},
+       {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
+       {0x3035, 0x14, 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, 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}, {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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
+       {0x3035, 0x22, 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, 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}, {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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
+       {0x3035, 0x14, 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, 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}, {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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
+       {0x3035, 0x22, 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, 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}, {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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
+       {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},
+};
+
+static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
+       {0x3035, 0x22, 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},
+};
+
+static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
+       {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, 0x02, 0, 0},
+       {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x38, 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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
+       {0x3035, 0x22, 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, 0x02, 0, 0},
+       {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+       {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+       {0x3811, 0x38, 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}, {0x4713, 0x03, 0, 0},
+       {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+       {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 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_15fps_720P_1280_720[] = {
+       {0x3035, 0x41, 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},
+};
+
+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_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, 0x21, 0, 0},
+       {0x3036, 0x54, 0, 1}, {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[] = {
+       {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},
+       {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, SUBSAMPLING, 640,  480,
+               ov5640_setting_15fps_VGA_640_480,
+               ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
+               {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320,  240,
+               ov5640_setting_15fps_QVGA_320_240,
+               ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
+               {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
+               ov5640_setting_15fps_NTSC_720_480,
+               ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
+               {ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
+               ov5640_setting_15fps_PAL_720_576,
+               ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
+               {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
+               ov5640_setting_15fps_720P_1280_720,
+               ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
+               {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
+               ov5640_setting_15fps_1080P_1920_1080,
+               ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
+               {ov5640_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
+               ov5640_setting_15fps_QSXGA_2592_1944,
+               ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
+               {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
+               ov5640_setting_15fps_QCIF_176_144,
+               ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
+               {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768,
+               ov5640_setting_15fps_XGA_1024_768,
+               ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
+       },
+       {
+               {ov5640_mode_VGA_640_480, SUBSAMPLING, 640,  480,
+               ov5640_setting_30fps_VGA_640_480,
+               ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
+               {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320,  240,
+               ov5640_setting_30fps_QVGA_320_240,
+               ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
+               {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
+               ov5640_setting_30fps_NTSC_720_480,
+               ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
+               {ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
+               ov5640_setting_30fps_PAL_720_576,
+               ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
+               {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},
+               {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
+               ov5640_setting_30fps_QCIF_176_144,
+               ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
+               {ov5640_mode_XGA_1024_768, SUBSAMPLING, 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 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)
+{
+       /* 19x19 pwdn pin invert by mipi daughter card */
+       if (!enable)
+               gpio_set_value(pwn_gpio, 1);
+       else
+               gpio_set_value(pwn_gpio, 0);
+
+       msleep(2);
+}
+
+static void ov5640_reset(void)
+{
+       /* 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);
+}
+
+
+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);
+
+       OV5640_stream_on();
+
+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_stream_on();
+
+       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 if (frame_rate == ov5640_15_fps) {
+               /* dump the first nine frames: 1/15*9 */
+               msec_wait4stable = 600;
+       } else if (frame_rate == ov5640_30_fps) {
+               /* dump the first nine frames: 1/30*9 */
+               msec_wait4stable = 300;
+       }
+       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 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_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");
+               return -EINVAL;
+       }
+       retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "ov5640_mipi_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_warn(dev, "no sensor reset pin available");
+               return -EINVAL;
+       }
+       retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+                                       "ov5640_mipi_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)) {
+               /* 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);
+
+       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
new file mode 100644 (file)
index 0000000..453478f
--- /dev/null
@@ -0,0 +1,1701 @@
+/*
+ * 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}, {0x0103, 0x01, 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}, {0x0103, 0x01, 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);
+}
+
+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_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);
+
+       ov5647_stream_on();
+
+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_stream_on();
+
+       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) {
+               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 struct v4l2_subdev_video_ops ov5647_subdev_video_ops = {
+       .g_parm = ov5647_g_parm,
+       .s_parm = ov5647_s_parm,
+};
+
+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);
+
+       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");
index 4d4c137..3dfa29b 100644 (file)
@@ -15,6 +15,7 @@ source "drivers/mxc/mlb/Kconfig"
 source "drivers/mxc/ipu3/Kconfig"
 source "drivers/mxc/gpu-viv/Kconfig"
 source "drivers/mxc/sim/Kconfig"
+source "drivers/mxc/mipi/Kconfig"
 source "drivers/mxc/vpu/Kconfig"
 source "drivers/mxc/hdmi-cec/Kconfig"
 
index e2ae1a0..8374cfa 100644 (file)
@@ -4,3 +4,4 @@ obj-$(CONFIG_MXC_VPU) += vpu/
 obj-$(CONFIG_MXC_IPU_V3) += ipu3/
 obj-$(CONFIG_MXC_HDMI_CEC) += hdmi-cec/
 obj-$(CONFIG_MXC_GPU_VIV) += gpu-viv/
+obj-$(CONFIG_MXC_MIPI_CSI2) += mipi/
diff --git a/drivers/mxc/mipi/Kconfig b/drivers/mxc/mipi/Kconfig
new file mode 100644 (file)
index 0000000..a6a3c33
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# MIPI configuration
+#
+
+menu "MXC MIPI Support"
+
+config MXC_MIPI_CSI2
+       tristate "MIPI CSI2 support"
+       depends on SOC_IMX6Q
+       default n
+       ---help---
+       Say Y to get the MIPI CSI2 support.
+
+endmenu
diff --git a/drivers/mxc/mipi/Makefile b/drivers/mxc/mipi/Makefile
new file mode 100644 (file)
index 0000000..98cda77
--- /dev/null
@@ -0,0 +1,4 @@
+#
+# Makefile for the mipi interface driver
+#
+obj-$(CONFIG_MXC_MIPI_CSI2) += mxc_mipi_csi2.o
diff --git a/drivers/mxc/mipi/mxc_mipi_csi2.c b/drivers/mxc/mipi/mxc_mipi_csi2.c
new file mode 100644 (file)
index 0000000..df45c36
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2011-2014 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/module.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/fsl_devices.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include <linux/mipi_csi2.h>
+
+#include "mxc_mipi_csi2.h"
+
+static struct mipi_csi2_info *gmipi_csi2;
+
+void _mipi_csi2_lock(struct mipi_csi2_info *info)
+{
+       if (!in_irq() && !in_softirq())
+               mutex_lock(&info->mutex_lock);
+}
+
+void _mipi_csi2_unlock(struct mipi_csi2_info *info)
+{
+       if (!in_irq() && !in_softirq())
+               mutex_unlock(&info->mutex_lock);
+}
+
+static inline void mipi_csi2_write(struct mipi_csi2_info *info,
+               unsigned value, unsigned offset)
+{
+       writel(value, info->mipi_csi2_base + offset);
+}
+
+static inline unsigned int mipi_csi2_read(struct mipi_csi2_info *info,
+               unsigned offset)
+{
+       return readl(info->mipi_csi2_base + offset);
+}
+
+/*!
+ * This function is called to enable the mipi csi2 interface.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns setted value
+ */
+bool mipi_csi2_enable(struct mipi_csi2_info *info)
+{
+       bool status;
+
+       _mipi_csi2_lock(info);
+
+       if (!info->mipi_en) {
+               info->mipi_en = true;
+               clk_prepare_enable(info->cfg_clk);
+               clk_prepare_enable(info->dphy_clk);
+       } else
+               mipi_dbg("mipi csi2 already enabled!\n");
+
+       status = info->mipi_en;
+
+       _mipi_csi2_unlock(info);
+
+       return status;
+}
+EXPORT_SYMBOL(mipi_csi2_enable);
+
+/*!
+ * This function is called to disable the mipi csi2 interface.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns setted value
+ */
+bool mipi_csi2_disable(struct mipi_csi2_info *info)
+{
+       bool status;
+
+       _mipi_csi2_lock(info);
+
+       if (info->mipi_en) {
+               info->mipi_en = false;
+               clk_disable_unprepare(info->dphy_clk);
+               clk_disable_unprepare(info->cfg_clk);
+       } else
+               mipi_dbg("mipi csi2 already disabled!\n");
+
+       status = info->mipi_en;
+
+       _mipi_csi2_unlock(info);
+
+       return status;
+}
+EXPORT_SYMBOL(mipi_csi2_disable);
+
+/*!
+ * This function is called to get mipi csi2 disable/enable status.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns mipi csi2 status
+ */
+bool mipi_csi2_get_status(struct mipi_csi2_info *info)
+{
+       bool status;
+
+       _mipi_csi2_lock(info);
+       status = info->mipi_en;
+       _mipi_csi2_unlock(info);
+
+       return status;
+}
+EXPORT_SYMBOL(mipi_csi2_get_status);
+
+/*!
+ * This function is called to set mipi lanes.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns setted value
+ */
+unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info)
+{
+       unsigned int lanes;
+
+       _mipi_csi2_lock(info);
+       mipi_csi2_write(info, info->lanes - 1, MIPI_CSI2_N_LANES);
+       lanes = mipi_csi2_read(info, MIPI_CSI2_N_LANES);
+       _mipi_csi2_unlock(info);
+
+       return lanes;
+}
+EXPORT_SYMBOL(mipi_csi2_set_lanes);
+
+/*!
+ * This function is called to set mipi data type.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns setted value
+ */
+unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info,
+                                       unsigned int datatype)
+{
+       unsigned int dtype;
+
+       _mipi_csi2_lock(info);
+       info->datatype = datatype;
+       dtype = info->datatype;
+       _mipi_csi2_unlock(info);
+
+       return dtype;
+}
+EXPORT_SYMBOL(mipi_csi2_set_datatype);
+
+/*!
+ * This function is called to get mipi data type.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns mipi data type
+ */
+unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info)
+{
+       unsigned int dtype;
+
+       _mipi_csi2_lock(info);
+       dtype = info->datatype;
+       _mipi_csi2_unlock(info);
+
+       return dtype;
+}
+EXPORT_SYMBOL(mipi_csi2_get_datatype);
+
+/*!
+ * This function is called to get mipi csi2 dphy status.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns dphy status
+ */
+unsigned int mipi_csi2_dphy_status(struct mipi_csi2_info *info)
+{
+       unsigned int status;
+
+       _mipi_csi2_lock(info);
+       status = mipi_csi2_read(info, MIPI_CSI2_PHY_STATE);
+       _mipi_csi2_unlock(info);
+
+       return status;
+}
+EXPORT_SYMBOL(mipi_csi2_dphy_status);
+
+/*!
+ * This function is called to get mipi csi2 error1 status.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns error1 value
+ */
+unsigned int mipi_csi2_get_error1(struct mipi_csi2_info *info)
+{
+       unsigned int err1;
+
+       _mipi_csi2_lock(info);
+       err1 = mipi_csi2_read(info, MIPI_CSI2_ERR1);
+       _mipi_csi2_unlock(info);
+
+       return err1;
+}
+EXPORT_SYMBOL(mipi_csi2_get_error1);
+
+/*!
+ * This function is called to get mipi csi2 error1 status.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns error1 value
+ */
+unsigned int mipi_csi2_get_error2(struct mipi_csi2_info *info)
+{
+       unsigned int err2;
+
+       _mipi_csi2_lock(info);
+       err2 = mipi_csi2_read(info, MIPI_CSI2_ERR2);
+       _mipi_csi2_unlock(info);
+
+       return err2;
+}
+EXPORT_SYMBOL(mipi_csi2_get_error2);
+
+/*!
+ * This function is called to enable mipi to ipu pixel clock.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns 0 on success or negative error code on fail
+ */
+int mipi_csi2_pixelclk_enable(struct mipi_csi2_info *info)
+{
+       return clk_prepare_enable(info->pixel_clk);
+}
+EXPORT_SYMBOL(mipi_csi2_pixelclk_enable);
+
+/*!
+ * This function is called to disable mipi to ipu pixel clock.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns 0 on success or negative error code on fail
+ */
+void mipi_csi2_pixelclk_disable(struct mipi_csi2_info *info)
+{
+       clk_disable_unprepare(info->pixel_clk);
+}
+EXPORT_SYMBOL(mipi_csi2_pixelclk_disable);
+
+/*!
+ * This function is called to power on mipi csi2.
+ *
+ * @param      info            mipi csi2 hander
+ * @return      Returns 0 on success or negative error code on fail
+ */
+int mipi_csi2_reset(struct mipi_csi2_info *info)
+{
+       _mipi_csi2_lock(info);
+
+       mipi_csi2_write(info, 0x0, MIPI_CSI2_PHY_SHUTDOWNZ);
+       mipi_csi2_write(info, 0x0, MIPI_CSI2_DPHY_RSTZ);
+       mipi_csi2_write(info, 0x0, MIPI_CSI2_CSI2_RESETN);
+
+       mipi_csi2_write(info, 0x00000001, MIPI_CSI2_PHY_TST_CTRL0);
+       mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL1);
+       mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
+       mipi_csi2_write(info, 0x00000002, MIPI_CSI2_PHY_TST_CTRL0);
+       mipi_csi2_write(info, 0x00010044, MIPI_CSI2_PHY_TST_CTRL1);
+       mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
+       mipi_csi2_write(info, 0x00000014, MIPI_CSI2_PHY_TST_CTRL1);
+       mipi_csi2_write(info, 0x00000002, MIPI_CSI2_PHY_TST_CTRL0);
+       mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
+
+       mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_PHY_SHUTDOWNZ);
+       mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_DPHY_RSTZ);
+       mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_CSI2_RESETN);
+
+       _mipi_csi2_unlock(info);
+
+       return 0;
+}
+EXPORT_SYMBOL(mipi_csi2_reset);
+
+/*!
+ * This function is called to get mipi csi2 info.
+ *
+ * @return      Returns mipi csi2 info struct pointor
+ */
+struct mipi_csi2_info *mipi_csi2_get_info(void)
+{
+       return gmipi_csi2;
+}
+EXPORT_SYMBOL(mipi_csi2_get_info);
+
+/*!
+ * This function is called to get mipi csi2 bind ipu num.
+ *
+ * @return      Returns mipi csi2 bind ipu num
+ */
+int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info)
+{
+       int ipu_id;
+
+       _mipi_csi2_lock(info);
+       ipu_id = info->ipu_id;
+       _mipi_csi2_unlock(info);
+
+       return ipu_id;
+}
+EXPORT_SYMBOL(mipi_csi2_get_bind_ipu);
+
+/*!
+ * This function is called to get mipi csi2 bind csi num.
+ *
+ * @return      Returns mipi csi2 bind csi num
+ */
+unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info)
+{
+       unsigned int csi_id;
+
+       _mipi_csi2_lock(info);
+       csi_id = info->csi_id;
+       _mipi_csi2_unlock(info);
+
+       return csi_id;
+}
+EXPORT_SYMBOL(mipi_csi2_get_bind_csi);
+
+/*!
+ * This function is called to get mipi csi2 virtual channel.
+ *
+ * @return      Returns mipi csi2 virtual channel num
+ */
+unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info)
+{
+       unsigned int v_channel;
+
+       _mipi_csi2_lock(info);
+       v_channel = info->v_channel;
+       _mipi_csi2_unlock(info);
+
+       return v_channel;
+}
+EXPORT_SYMBOL(mipi_csi2_get_virtual_channel);
+
+/**
+ * This function is called by the driver framework to initialize the MIPI CSI2
+ * device.
+ *
+ * @param      pdev    The device structure for the MIPI CSI2 passed in by the
+ *                     driver framework.
+ *
+ * @return      Returns 0 on success or negative error code on error
+ */
+static int mipi_csi2_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *res;
+       u32 mipi_csi2_dphy_ver;
+       int ret;
+
+       gmipi_csi2 = kmalloc(sizeof(struct mipi_csi2_info), GFP_KERNEL);
+       if (!gmipi_csi2) {
+               ret = -ENOMEM;
+               goto alloc_failed;
+       }
+
+       ret = of_property_read_u32(np, "ipu_id", &(gmipi_csi2->ipu_id));
+       if (ret) {
+               dev_err(&pdev->dev, "ipu_id missing or invalid\n");
+               goto err;
+       }
+
+       ret = of_property_read_u32(np, "csi_id", &(gmipi_csi2->csi_id));
+       if (ret) {
+               dev_err(&pdev->dev, "csi_id missing or invalid\n");
+               goto err;
+       }
+
+       ret = of_property_read_u32(np, "v_channel", &(gmipi_csi2->v_channel));
+       if (ret) {
+               dev_err(&pdev->dev, "v_channel missing or invalid\n");
+               goto err;
+       }
+
+       ret = of_property_read_u32(np, "lanes", &(gmipi_csi2->lanes));
+       if (ret) {
+               dev_err(&pdev->dev, "lanes missing or invalid\n");
+               goto err;
+       }
+
+       if ((gmipi_csi2->ipu_id < 0) || (gmipi_csi2->ipu_id > 1) ||
+               (gmipi_csi2->csi_id > 1) || (gmipi_csi2->v_channel > 3) ||
+               (gmipi_csi2->lanes > 4)) {
+               dev_err(&pdev->dev, "invalid param for mipi csi2!\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* initialize mutex */
+       mutex_init(&gmipi_csi2->mutex_lock);
+
+       /* get mipi csi2 informaiton */
+       gmipi_csi2->pdev = pdev;
+       gmipi_csi2->mipi_en = false;
+
+       gmipi_csi2->cfg_clk = devm_clk_get(dev, "cfg_clk");
+       if (IS_ERR(gmipi_csi2->cfg_clk)) {
+               dev_err(&pdev->dev, "failed to get cfg_clk\n");
+               ret = PTR_ERR(gmipi_csi2->cfg_clk);
+               goto err;
+       }
+
+       /* get mipi dphy clk */
+       gmipi_csi2->dphy_clk = devm_clk_get(dev, "dphy_clk");
+       if (IS_ERR(gmipi_csi2->dphy_clk)) {
+               dev_err(&pdev->dev, "failed to get dphy pll_ref_clk\n");
+               ret = PTR_ERR(gmipi_csi2->dphy_clk);
+               goto err;
+       }
+
+       /* get mipi to ipu pixel clk */
+       gmipi_csi2->pixel_clk = devm_clk_get(dev, "pixel_clk");
+       if (IS_ERR(gmipi_csi2->pixel_clk)) {
+               dev_err(&pdev->dev, "failed to get mipi pixel clk\n");
+               ret = PTR_ERR(gmipi_csi2->pixel_clk);
+               goto err;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               goto err;
+       }
+
+       /* mipi register mapping */
+       gmipi_csi2->mipi_csi2_base = ioremap(res->start, PAGE_SIZE);
+       if (!gmipi_csi2->mipi_csi2_base) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       /* mipi dphy clk enable for register access */
+       clk_prepare_enable(gmipi_csi2->dphy_clk);
+       /* get mipi csi2 dphy version */
+       mipi_csi2_dphy_ver = mipi_csi2_read(gmipi_csi2, MIPI_CSI2_VERSION);
+
+       clk_disable_unprepare(gmipi_csi2->dphy_clk);
+
+       platform_set_drvdata(pdev, gmipi_csi2);
+
+       dev_info(&pdev->dev, "i.MX MIPI CSI2 driver probed\n");
+       dev_info(&pdev->dev, "i.MX MIPI CSI2 dphy version is 0x%x\n",
+                                               mipi_csi2_dphy_ver);
+
+       return 0;
+
+err:
+       kfree(gmipi_csi2);
+alloc_failed:
+       dev_err(&pdev->dev, "i.MX MIPI CSI2 driver probed -  error\n");
+       return ret;
+}
+
+static int mipi_csi2_remove(struct platform_device *pdev)
+{
+       /* unmapping mipi register */
+       iounmap(gmipi_csi2->mipi_csi2_base);
+
+       kfree(gmipi_csi2);
+
+       dev_set_drvdata(&pdev->dev, NULL);
+
+       return 0;
+}
+
+static const struct of_device_id imx_mipi_csi2_dt_ids[] = {
+       { .compatible = "fsl,imx6q-mipi-csi2", },
+       { /* sentinel */ }
+};
+
+static struct platform_driver mipi_csi2_driver = {
+       .driver = {
+                  .name = "mxc_mipi_csi2",
+                  .of_match_table = imx_mipi_csi2_dt_ids,
+       },
+       .probe = mipi_csi2_probe,
+       .remove = mipi_csi2_remove,
+};
+
+static int __init mipi_csi2_init(void)
+{
+       int err;
+
+       err = platform_driver_register(&mipi_csi2_driver);
+       if (err) {
+               pr_err("mipi_csi2_driver register failed\n");
+               return -ENODEV;
+       }
+
+       pr_info("MIPI CSI2 driver module loaded\n");
+
+       return 0;
+}
+
+static void __exit mipi_csi2_cleanup(void)
+{
+       platform_driver_unregister(&mipi_csi2_driver);
+}
+
+subsys_initcall(mipi_csi2_init);
+module_exit(mipi_csi2_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX MIPI CSI2 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mxc/mipi/mxc_mipi_csi2.h b/drivers/mxc/mipi/mxc_mipi_csi2.h
new file mode 100644 (file)
index 0000000..291d7e8
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+#ifndef __MXC_MIPI_CSI2_H__
+#define __MXC_MIPI_CSI2_H__
+
+#ifdef DEBUG
+#define mipi_dbg(fmt, ...)     \
+       printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define mipi_dbg(fmt, ...)
+#endif
+
+/* driver private data */
+struct mipi_csi2_info {
+       bool            mipi_en;
+       int             ipu_id;
+       unsigned int    csi_id;
+       unsigned int    v_channel;
+       unsigned int    lanes;
+       unsigned int    datatype;
+       struct clk      *cfg_clk;
+       struct clk      *dphy_clk;
+       struct clk      *pixel_clk;
+       void __iomem    *mipi_csi2_base;
+       struct platform_device  *pdev;
+
+       struct mutex mutex_lock;
+};
+
+#endif
diff --git a/include/linux/mipi_csi2.h b/include/linux/mipi_csi2.h
new file mode 100644 (file)
index 0000000..7dc76fd
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011-2013 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.
+ */
+
+#ifndef __INCLUDE_MIPI_CSI2_H
+#define __INCLUDE_MIPI_CSI2_H
+
+/* MIPI CSI2 registers */
+#define MIPI_CSI2_REG(offset)          (offset)
+
+#define        MIPI_CSI2_VERSION               MIPI_CSI2_REG(0x000)
+#define        MIPI_CSI2_N_LANES               MIPI_CSI2_REG(0x004)
+#define        MIPI_CSI2_PHY_SHUTDOWNZ         MIPI_CSI2_REG(0x008)
+#define        MIPI_CSI2_DPHY_RSTZ             MIPI_CSI2_REG(0x00c)
+#define        MIPI_CSI2_CSI2_RESETN           MIPI_CSI2_REG(0x010)
+#define        MIPI_CSI2_PHY_STATE             MIPI_CSI2_REG(0x014)
+#define        MIPI_CSI2_DATA_IDS_1            MIPI_CSI2_REG(0x018)
+#define        MIPI_CSI2_DATA_IDS_2            MIPI_CSI2_REG(0x01c)
+#define        MIPI_CSI2_ERR1                  MIPI_CSI2_REG(0x020)
+#define        MIPI_CSI2_ERR2                  MIPI_CSI2_REG(0x024)
+#define        MIPI_CSI2_MASK1                 MIPI_CSI2_REG(0x028)
+#define        MIPI_CSI2_MASK2                 MIPI_CSI2_REG(0x02c)
+#define        MIPI_CSI2_PHY_TST_CTRL0         MIPI_CSI2_REG(0x030)
+#define        MIPI_CSI2_PHY_TST_CTRL1         MIPI_CSI2_REG(0x034)
+#define        MIPI_CSI2_SFT_RESET             MIPI_CSI2_REG(0xf00)
+
+/* mipi data type */
+#define MIPI_DT_YUV420         0x18 /* YYY.../UYVY.... */
+#define MIPI_DT_YUV420_LEGACY  0x1a /* UYY.../VYY...   */
+#define MIPI_DT_YUV422         0x1e /* UYVY...         */
+#define MIPI_DT_RGB444         0x20
+#define MIPI_DT_RGB555         0x21
+#define MIPI_DT_RGB565         0x22
+#define MIPI_DT_RGB666         0x23
+#define MIPI_DT_RGB888         0x24
+#define MIPI_DT_RAW6           0x28
+#define MIPI_DT_RAW7           0x29
+#define MIPI_DT_RAW8           0x2a
+#define MIPI_DT_RAW10          0x2b
+#define MIPI_DT_RAW12          0x2c
+#define MIPI_DT_RAW14          0x2d
+
+
+struct mipi_csi2_info;
+/* mipi csi2 API */
+struct mipi_csi2_info *mipi_csi2_get_info(void);
+
+bool mipi_csi2_enable(struct mipi_csi2_info *info);
+
+bool mipi_csi2_disable(struct mipi_csi2_info *info);
+
+bool mipi_csi2_get_status(struct mipi_csi2_info *info);
+
+int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info,
+                                       unsigned int datatype);
+
+unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_dphy_status(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_get_error1(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_get_error2(struct mipi_csi2_info *info);
+
+int mipi_csi2_pixelclk_enable(struct mipi_csi2_info *info);
+
+void mipi_csi2_pixelclk_disable(struct mipi_csi2_info *info);
+
+int mipi_csi2_reset(struct mipi_csi2_info *info);
+
+#endif
index 5049eee..f261b92 100644 (file)
@@ -53,6 +53,11 @@ struct v4l2_mxc_offset {
        uint32_t v_offset;
 };
 
+struct v4l2_mxc_dest_crop {
+       __u32                   type;   /* enum v4l2_buf_type */
+       struct v4l2_mxc_offset   offset;
+};
+
 /*
  * Private IOCTLs
  *
@@ -63,5 +68,6 @@ struct v4l2_mxc_offset {
        _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct v4l2_crop)
 #define VIDIOC_G_INPUT_CROP \
        _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct v4l2_crop)
-
+#define VIDIOC_S_DEST_CROP \
+       _IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct v4l2_mxc_dest_crop)
 #endif