media: tegra: add ov5693 with ad5823 focuser
Lihui Cui [Fri, 18 Jan 2013 01:12:53 +0000 (10:12 +0900)]
bug 1218661

Change-Id: Id6c8d697c8a9fa8f0d4414802ad866783c00d695
Signed-off-by: Lihui Cui <lcui@nvidia.com>
Reviewed-on: http://git-master/r/192227
GVS: Gerrit_Virtual_Submit
Reviewed-by: Dan Willemsen <dwillemsen@nvidia.com>

drivers/media/video/tegra/Kconfig
drivers/media/video/tegra/Makefile
drivers/media/video/tegra/ad5823.c [new file with mode: 0644]
drivers/media/video/tegra/ov5693.c [new file with mode: 0644]
include/media/ad5823.h [new file with mode: 0644]
include/media/ov5693.h [new file with mode: 0644]

index 8d59c89..cdf2b9c 100644 (file)
@@ -81,6 +81,13 @@ config VIDEO_OV9772
           This is a driver for the OV9772 camera sensor
           for use with the tegra isp.
 
+config VIDEO_OV5693
+        tristate "OV5693 camera sensor support"
+        depends on I2C && ARCH_TEGRA
+        ---help---
+          This is a driver for the OV5693 camera sensor
+          for use with the tegra isp.
+
 config TORCH_SSL3250A
         tristate "SSL3250A flash/torch support"
         depends on I2C && ARCH_TEGRA
@@ -120,6 +127,13 @@ config VIDEO_AD5820
           This is a driver for the AD5820 focuser
           for use with the tegra isp.
 
+config VIDEO_AD5823
+        tristate "AD5823 focuser support"
+        depends on I2C && ARCH_TEGRA
+        ---help---
+          This is a driver for the AD5823 focuser
+          for use with the tegra isp.
+
 config VIDEO_AD5816
         tristate "AD5816 focuser support"
         depends on I2C && ARCH_TEGRA
index d643b3a..f117fa2 100644 (file)
@@ -25,3 +25,5 @@ obj-$(CONFIG_VIDEO_AD5820)    += ad5820.o
 obj-$(CONFIG_VIDEO_AD5816)     += ad5816.o
 obj-$(CONFIG_VIDEO_IMX091)     += imx091.o
 obj-$(CONFIG_VIDEO_IMX132)     += imx132.o
+obj-$(CONFIG_VIDEO_OV5693)     += ov5693.o
+obj-$(CONFIG_VIDEO_AD5823)     += ad5823.o
diff --git a/drivers/media/video/tegra/ad5823.c b/drivers/media/video/tegra/ad5823.c
new file mode 100644 (file)
index 0000000..5666a10
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <media/ad5823.h>
+
+#define POS_LOW                (32)
+#define POS_HIGH       (850)
+#define SETTLETIME_MS  (70)
+#define FOCAL_LENGTH   (4.507f)
+#define FNUMBER                (2.8f)
+
+#define AD5823_MAX_RETRIES (3)
+
+struct ad5823_info {
+       struct i2c_client *i2c_client;
+       struct regulator *regulator;
+       struct ad5823_config config;
+       struct ad5823_platform_data *pdata;
+       struct miscdevice miscdev;
+       struct regmap *regmap;
+};
+
+static int ad5823_set_position(struct ad5823_info *info, u32 position)
+{
+       int ret = 0;
+
+       if (position < info->config.pos_low ||
+               position > info->config.pos_high) {
+               dev_err(&info->i2c_client->dev,
+                       "%s: position(%d) out of bound([%d, %d])\n",
+                       __func__, position, info->config.pos_low,
+                       info->config.pos_high);
+               if (position < info->config.pos_low)
+                       position = info->config.pos_low;
+               else
+                       position = info->config.pos_high;
+       }
+
+       ret |= regmap_write(info->regmap, AD5823_MODE, 0);
+       ret |= regmap_write(info->regmap, AD5823_VCM_CODE_MSB,
+               ((position >> 8) & 0x3) | (1 << 2));
+       ret |= regmap_write(info->regmap, AD5823_VCM_CODE_LSB,
+               position & 0xFF);
+
+       return ret;
+}
+
+static long ad5823_ioctl(struct file *file,
+                       unsigned int cmd, unsigned long arg)
+{
+       struct ad5823_info *info = file->private_data;
+
+       switch (cmd) {
+       case AD5823_IOCTL_GET_CONFIG:
+       {
+               if (copy_to_user((void __user *) arg,
+                                &info->config,
+                                sizeof(info->config))) {
+                       dev_err(&info->i2c_client->dev, "%s: 0x%x\n",
+                               __func__, __LINE__);
+                       return -EFAULT;
+               }
+
+               break;
+       }
+       case AD5823_IOCTL_SET_POSITION:
+               return ad5823_set_position(info, (u32) arg);
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ad5823_open(struct inode *inode, struct file *file)
+{
+       int err = 0;
+       struct miscdevice *miscdev = file->private_data;
+       struct ad5823_info *info = dev_get_drvdata(miscdev->parent);
+
+       if (info->regulator)
+               err = regulator_enable(info->regulator);
+
+       if (info->pdata->power_on)
+               err = info->pdata->power_on(info->pdata);
+
+       file->private_data = info;
+       msleep(100);
+       return err;
+}
+
+int ad5823_release(struct inode *inode, struct file *file)
+{
+       struct ad5823_info *info = file->private_data;
+
+       if (info->regulator)
+               regulator_disable(info->regulator);
+       file->private_data = NULL;
+
+       if (info->pdata->power_off)
+               info->pdata->power_off(info->pdata);
+
+       return 0;
+}
+
+
+static const struct file_operations ad5823_fileops = {
+       .owner = THIS_MODULE,
+       .open = ad5823_open,
+       .unlocked_ioctl = ad5823_ioctl,
+       .release = ad5823_release,
+};
+
+static struct miscdevice ad5823_device = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "focuser",
+       .fops = &ad5823_fileops,
+};
+
+static int ad5823_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       int err;
+       struct ad5823_info *info;
+       static struct regmap_config ad5823_regmap_config = {
+               .reg_bits = 8,
+               .val_bits = 8,
+       };
+
+
+       dev_dbg(&client->dev, "ad5823: probing sensor.\n");
+
+       info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               dev_err(&client->dev, "ad5823: Unable to allocate memory!\n");
+               return -ENOMEM;
+       }
+
+       ad5823_device.parent = &client->dev;
+       err = misc_register(&ad5823_device);
+       if (err) {
+               dev_err(&client->dev, "ad5823: Unable to register misc device!\n");
+               goto ERROR_RET;
+       }
+
+       if (client->dev.platform_data) {
+               info->pdata = client->dev.platform_data;
+       } else {
+               info->pdata = NULL;
+               dev_err(&client->dev, "ad5823: Platform data missing.");
+               err = EINVAL;
+               goto ERROR_RET;
+       }
+
+       info->regulator = devm_regulator_get(&client->dev, "vdd");
+       if (IS_ERR_OR_NULL(info->regulator)) {
+               dev_err(&client->dev, "unable to get regulator %s\n",
+                       dev_name(&client->dev));
+               info->regulator = NULL;
+       } else {
+               regulator_enable(info->regulator);
+       }
+
+       info->regmap = devm_regmap_init_i2c(client, &ad5823_regmap_config);
+       if (IS_ERR(info->regmap)) {
+               err = PTR_ERR(info->regmap);
+               dev_err(&client->dev,
+                       "Failed to allocate register map: %d\n", err);
+               goto ERROR_RET;
+       }
+
+
+       info->i2c_client                = client;
+       info->config.settle_time        = SETTLETIME_MS;
+       info->config.focal_length       = FOCAL_LENGTH;
+       info->config.fnumber            = FNUMBER;
+       info->config.pos_low            = POS_LOW;
+       info->config.pos_high           = POS_HIGH;
+       info->miscdev                   = ad5823_device;
+
+       i2c_set_clientdata(client, info);
+
+       return 0;
+
+ERROR_RET:
+       if (info->regulator)
+               regulator_disable(info->regulator);
+
+       misc_deregister(&ad5823_device);
+       return err;
+}
+
+static int ad5823_remove(struct i2c_client *client)
+{
+       struct ad5823_info *info;
+       info = i2c_get_clientdata(client);
+       misc_deregister(&ad5823_device);
+       return 0;
+}
+
+static const struct i2c_device_id ad5823_id[] = {
+       { "ad5823", 0 },
+       { },
+};
+
+MODULE_DEVICE_TABLE(i2c, ad5823_id);
+
+static struct i2c_driver ad5823_i2c_driver = {
+       .driver = {
+               .name = "ad5823",
+               .owner = THIS_MODULE,
+       },
+       .probe = ad5823_probe,
+       .remove = ad5823_remove,
+       .id_table = ad5823_id,
+};
+
+module_i2c_driver(ad5823_i2c_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/tegra/ov5693.c b/drivers/media/video/tegra/ov5693.c
new file mode 100644 (file)
index 0000000..27e852b
--- /dev/null
@@ -0,0 +1,1989 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <media/ov5693.h>
+
+#define OV5693_ID                      0x5693
+#define OV5693_SENSOR_TYPE             NVC_IMAGER_TYPE_RAW
+#define OV5693_RES_CHG_WAIT_TIME_MS    100
+#define OV5693_SIZEOF_I2C_BUF          16
+#define OV5693_TABLE_WAIT_MS           0
+#define OV5693_TABLE_END               1
+#define OV5693_TABLE_RESET             2
+#define OV5693_TABLE_RESET_TIMEOUT     50
+#define OV5693_LENS_MAX_APERTURE       0       /* _INT2FLOAT_DIVISOR */
+#define OV5693_LENS_FNUMBER            0       /* _INT2FLOAT_DIVISOR */
+#define OV5693_LENS_FOCAL_LENGTH       6120    /* _INT2FLOAT_DIVISOR */
+#define OV5693_LENS_VIEW_ANGLE_H       60000   /* _INT2FLOAT_DIVISOR */
+#define OV5693_LENS_VIEW_ANGLE_V       60000   /* _INT2FLOAT_DIVISOR */
+
+static struct nvc_gpio_init ov5693_gpio[] = {
+       { OV5693_GPIO_TYPE_PWRDN, GPIOF_OUT_INIT_LOW, "pwrdn", false, true, },
+};
+
+struct ov5693_info {
+       atomic_t in_use;
+       struct i2c_client *i2c_client;
+       struct ov5693_platform_data *pdata;
+       struct miscdevice miscdev;
+       int pwr_api;
+       int pwr_dev;
+       struct nvc_gpio gpio[ARRAY_SIZE(ov5693_gpio)];
+       struct ov5693_power_rail regulators;
+       bool power_on;
+       u32 mode_index;
+       bool mode_valid;
+       bool mode_enable;
+       unsigned test_pattern;
+       struct nvc_imager_static_nvc sdata;
+       u8 bin_en;
+       struct ov5693_fuseid fuseid;
+       struct regmap *regmap;
+};
+
+struct ov5693_reg {
+       u16 addr;
+       u16 val;
+};
+
+struct ov5693_mode_data {
+       struct nvc_imager_mode sensor_mode;
+       struct nvc_imager_dynamic_nvc sensor_dnvc;
+       struct ov5693_reg *p_mode_i2c;
+};
+
+static struct ov5693_platform_data ov5693_dflt_pdata = {
+       .cfg            = 0,
+       .num            = 0,
+       .dev_name       = "camera",
+};
+
+/*
+ * NOTE: static vs dynamic
+ * If a member in the nvc_imager_static_nvc structure is not actually
+ * static data, then leave blank and add the parameter to the parameter
+ * read function that dynamically reads the data.  The NVC user driver
+ * will call the parameter read for the data if the member data is 0.
+ * If the dynamic data becomes static during probe (a one time read
+ * such as device ID) then add the dynamic read to the _sdata_init
+ * function.
+ */
+static struct nvc_imager_static_nvc ov5693_dflt_sdata = {
+       .api_version            = NVC_IMAGER_API_STATIC_VER,
+       .sensor_type            = OV5693_SENSOR_TYPE,
+       .bits_per_pixel         = 10,
+       .sensor_id              = OV5693_ID,
+       .sensor_id_minor        = 0,
+       .focal_len              = OV5693_LENS_FOCAL_LENGTH,
+       .max_aperture           = OV5693_LENS_MAX_APERTURE,
+       .fnumber                = OV5693_LENS_FNUMBER,
+       .view_angle_h           = OV5693_LENS_VIEW_ANGLE_H,
+       .view_angle_v           = OV5693_LENS_VIEW_ANGLE_V,
+       .res_chg_wait_time      = OV5693_RES_CHG_WAIT_TIME_MS,
+};
+
+static const struct ov5693_reg ov5693_2592x1944_i2c[] = {
+       {OV5693_TABLE_RESET, 0},/* Including sw reset */
+       {0x3001, 0x0a},
+       {0x3002, 0x80},
+       {0x3006, 0x00},
+       {0x3011, 0x21},
+       {0x3012, 0x09},
+       {0x3013, 0x10},
+       {0x3014, 0x00},
+       {0x3015, 0x08},
+       {0x3016, 0xf0},
+       {0x3017, 0xf0},
+       {0x3018, 0xf0},
+       {0x301b, 0xb4},
+       {0x301d, 0x02},
+       {0x3021, 0x00},
+       {0x3022, 0x01},
+       {0x3028, 0x44},
+       {0x3090, 0x02},
+       {0x3091, 0x0e},
+       {0x3092, 0x00},
+       {0x3093, 0x00},
+       {0x3098, 0x03},
+       {0x3099, 0x1e},
+       {0x309a, 0x02},
+       {0x309b, 0x01},
+       {0x309c, 0x00},
+       {0x30a0, 0xd2},
+       {0x30a2, 0x01},
+       {0x30b2, 0x00},
+       {0x30b3, 0x68},
+       {0x30b4, 0x03},
+       {0x30b5, 0x04},
+       {0x30b6, 0x01},
+       {0x3104, 0x21},
+       {0x3106, 0x00},
+       {0x3400, 0x04},
+       {0x3401, 0x00},
+       {0x3402, 0x04},
+       {0x3403, 0x00},
+       {0x3404, 0x04},
+       {0x3405, 0x00},
+       {0x3406, 0x01},
+       {0x3500, 0x00},
+       {0x3501, 0x7b},
+       {0x3502, 0x00},
+       {0x3503, 0x07},
+       {0x3504, 0x00},
+       {0x3505, 0x00},
+       {0x3506, 0x00},
+       {0x3507, 0x02},
+       {0x3508, 0x00},
+       {0x3509, 0x08},
+       {0x350a, 0x00},
+       {0x350b, 0x40},
+       {0x3601, 0x0a},
+       {0x3602, 0x18},
+       {0x3612, 0x80},
+       {0x3620, 0x54},
+       {0x3621, 0xc7},
+       {0x3622, 0x0f},
+       {0x3625, 0x10},
+       {0x3630, 0x55},
+       {0x3631, 0xf4},
+       {0x3632, 0x00},
+       {0x3633, 0x34},
+       {0x3634, 0x02},
+       {0x364d, 0x0d},
+       {0x364f, 0xdd},
+       {0x3660, 0x04},
+       {0x3662, 0x10},
+       {0x3663, 0xf1},
+       {0x3665, 0x00},
+       {0x3666, 0x20},
+       {0x3667, 0x00},
+       {0x366a, 0x80},
+       {0x3680, 0xe0},
+       {0x3681, 0x00},
+       {0x3700, 0x42},
+       {0x3701, 0x14},
+       {0x3702, 0xa0},
+       {0x3703, 0xd8},
+       {0x3704, 0x78},
+       {0x3705, 0x02},
+       {0x3708, 0xe2},
+       {0x3709, 0xc3},
+       {0x370a, 0x00},
+       {0x370b, 0x20},
+       {0x370c, 0x0c},
+       {0x370d, 0x11},
+       {0x370e, 0x00},
+       {0x370f, 0x40},
+       {0x3710, 0x00},
+       {0x371a, 0x1c},
+       {0x371b, 0x05},
+       {0x371c, 0x01},
+       {0x371e, 0xa1},
+       {0x371f, 0x0c},
+       {0x3721, 0x00},
+       {0x3726, 0x00},
+       {0x372a, 0x01},
+       {0x3730, 0x10},
+       {0x3738, 0x22},
+       {0x3739, 0xe5},
+       {0x373a, 0x50},
+       {0x373b, 0x02},
+       {0x373c, 0x41},
+       {0x373f, 0x02},
+       {0x3740, 0x42},
+       {0x3741, 0x02},
+       {0x3742, 0x18},
+       {0x3743, 0x01},
+       {0x3744, 0x02},
+       {0x3747, 0x10},
+       {0x374c, 0x04},
+       {0x3751, 0xf0},
+       {0x3752, 0x00},
+       {0x3753, 0x00},
+       {0x3754, 0xc0},
+       {0x3755, 0x00},
+       {0x3756, 0x1a},
+       {0x3758, 0x00},
+       {0x3759, 0x0f},
+       {0x376b, 0x44},
+       {0x375c, 0x04},
+       {0x3776, 0x00},
+       {0x377f, 0x08},
+       {0x3780, 0x22},
+       {0x3781, 0x0c},
+       {0x3784, 0x2c},
+       {0x3785, 0x1e},
+       {0x378f, 0xf5},
+       {0x3791, 0xb0},
+       {0x3795, 0x00},
+       {0x3796, 0x64},
+       {0x3797, 0x11},
+       {0x3798, 0x30},
+       {0x3799, 0x41},
+       {0x379a, 0x07},
+       {0x379b, 0xb0},
+       {0x379c, 0x0c},
+       {0x37c5, 0x00},
+       {0x37c6, 0x00},
+       {0x37c7, 0x00},
+       {0x37c9, 0x00},
+       {0x37ca, 0x00},
+       {0x37cb, 0x00},
+       {0x37de, 0x00},
+       {0x37df, 0x00},
+       {0x3800, 0x00},
+       {0x3801, 0x00},
+       {0x3802, 0x00},
+       {0x3803, 0x00},
+       {0x3804, 0x0a},
+       {0x3805, 0x3f},
+       {0x3806, 0x07},
+       {0x3807, 0xa3},
+       {0x3808, 0x0a},
+       {0x3809, 0x20},
+       {0x380a, 0x07},
+       {0x380b, 0x98},
+       {0x380c, 0x0a},
+       {0x380d, 0x80},
+       {0x380e, 0x07},
+       {0x380f, 0xc0},
+       {0x3810, 0x00},
+       {0x3811, 0x02},
+       {0x3812, 0x00},
+       {0x3813, 0x02},
+       {0x3814, 0x11},
+       {0x3815, 0x11},
+       {0x3820, 0x00},
+       {0x3821, 0x1e},
+       {0x3823, 0x00},
+       {0x3824, 0x00},
+       {0x3825, 0x00},
+       {0x3826, 0x00},
+       {0x3827, 0x00},
+       {0x382a, 0x04},
+       {0x3a04, 0x06},
+       {0x3a05, 0x14},
+       {0x3a06, 0x00},
+       {0x3a07, 0xfe},
+       {0x3b00, 0x00},
+       {0x3b02, 0x00},
+       {0x3b03, 0x00},
+       {0x3b04, 0x00},
+       {0x3b05, 0x00},
+       {0x3d00, 0x00},
+       {0x3d01, 0x00},
+       {0x3d02, 0x00},
+       {0x3d03, 0x00},
+       {0x3d04, 0x00},
+       {0x3d05, 0x00},
+       {0x3d06, 0x00},
+       {0x3d07, 0x00},
+       {0x3d08, 0x00},
+       {0x3d09, 0x00},
+       {0x3d0a, 0x00},
+       {0x3d0b, 0x00},
+       {0x3d0c, 0x00},
+       {0x3d0d, 0x00},
+       {0x3d0e, 0x00},
+       {0x3d0f, 0x00},
+       {0x3d80, 0x00},
+       {0x3d81, 0x00},
+       {0x3d84, 0x00},
+       {0x3e07, 0x20},
+       {0x4000, 0x08},
+       {0x4001, 0x04},
+       {0x4002, 0x45},
+       {0x4004, 0x08},
+       {0x4005, 0x18},
+       {0x4006, 0x20},
+       {0x4008, 0x24},
+       {0x4009, 0x10},
+       {0x400c, 0x00},
+       {0x400d, 0x00},
+       {0x4058, 0x00},
+       {0x4101, 0xb2},
+       {0x4303, 0x00},
+       {0x4304, 0x08},
+       {0x4307, 0x30},
+       {0x4311, 0x04},
+       {0x4315, 0x01},
+       {0x4511, 0x05},
+       {0x4512, 0x01},
+       {0x4806, 0x00},
+       {0x4816, 0x52},
+       {0x481f, 0x30},
+       {0x4826, 0x2c},
+       {0x4831, 0x64},
+       {0x4d00, 0x04},
+       {0x4d01, 0x71},
+       {0x4d02, 0xfd},
+       {0x4d03, 0xf5},
+       {0x4d04, 0x0c},
+       {0x4d05, 0xcc},
+       {0x4837, 0x09},
+       {0x5000, 0x06},
+       {0x5001, 0x01},
+       {0x5002, 0x00},
+       {0x5003, 0x20},
+       {0x5046, 0x0a},
+       {0x5013, 0x00},
+       {0x5046, 0x0a},
+       {0x5780, 0x1c},
+       {0x5786, 0x20},
+       {0x5787, 0x10},
+       {0x5788, 0x18},
+       {0x578a, 0x04},
+       {0x578b, 0x02},
+       {0x578c, 0x02},
+       {0x578e, 0x06},
+       {0x578f, 0x02},
+       {0x5790, 0x02},
+       {0x5791, 0xff},
+       {0x5842, 0x01},
+       {0x5843, 0x2b},
+       {0x5844, 0x01},
+       {0x5845, 0x92},
+       {0x5846, 0x01},
+       {0x5847, 0x8f},
+       {0x5848, 0x01},
+       {0x5849, 0x0c},
+       {0x5e00, 0x00},
+       {0x5e10, 0x0c},
+       {0x0100, 0x01},
+
+       {OV5693_TABLE_END, 0x0000}
+};
+
+static const struct ov5693_reg ov5693_1296x972_i2c[] = {
+       {OV5693_TABLE_RESET, 0},/* Including sw reset */
+       {0x0103, 0x01},
+       {0x3001, 0x0a},
+       {0x3002, 0x80},
+       {0x3006, 0x00},
+       {0x3011, 0x21},
+       {0x3012, 0x09},
+       {0x3013, 0x10},
+       {0x3014, 0x00},
+       {0x3015, 0x08},
+       {0x3016, 0xf0},
+       {0x3017, 0xf0},
+       {0x3018, 0xf0},
+       {0x301b, 0xb4},
+       {0x301d, 0x02},
+       {0x3021, 0x00},
+       {0x3022, 0x01},
+       {0x3028, 0x44},
+       {0x3098, 0x03},
+       {0x3099, 0x1e},
+       {0x309a, 0x02},
+       {0x309b, 0x01},
+       {0x309c, 0x00},
+       {0x30a0, 0xd2},
+       {0x30a2, 0x01},
+       {0x30b2, 0x00},
+       {0x30b3, 0x64},
+       {0x30b4, 0x03},
+       {0x30b5, 0x04},
+       {0x30b6, 0x01},
+       {0x3104, 0x21},
+       {0x3106, 0x00},
+       {0x3400, 0x04},
+       {0x3401, 0x00},
+       {0x3402, 0x04},
+       {0x3403, 0x00},
+       {0x3404, 0x04},
+       {0x3405, 0x00},
+       {0x3406, 0x01},
+       {0x3500, 0x00},
+       {0x3501, 0x7b},
+       {0x3502, 0x00},
+       {0x3503, 0x07},
+       {0x3504, 0x00},
+       {0x3505, 0x00},
+       {0x3506, 0x00},
+       {0x3507, 0x02},
+       {0x3508, 0x00},
+       {0x3509, 0x08},
+       {0x350a, 0x00},
+       {0x350b, 0x40},
+       {0x3601, 0x0a},
+       {0x3602, 0x38},
+       {0x3612, 0x80},
+       {0x3620, 0x54},
+       {0x3621, 0xc7},
+       {0x3622, 0x0f},
+       {0x3625, 0x10},
+       {0x3630, 0x55},
+       {0x3631, 0xf4},
+       {0x3632, 0x00},
+       {0x3633, 0x34},
+       {0x3634, 0x02},
+       {0x364d, 0x0d},
+       {0x364f, 0xdd},
+       {0x3660, 0x04},
+       {0x3662, 0x10},
+       {0x3663, 0xf1},
+       {0x3665, 0x00},
+       {0x3666, 0x20},
+       {0x3667, 0x00},
+       {0x366a, 0x80},
+       {0x3680, 0xe0},
+       {0x3681, 0x00},
+       {0x3700, 0x42},
+       {0x3701, 0x14},
+       {0x3702, 0xa0},
+       {0x3703, 0xd8},
+       {0x3704, 0x78},
+       {0x3705, 0x02},
+       {0x3708, 0xe6},
+       {0x3709, 0xc3},
+       {0x370a, 0x00},
+       {0x370b, 0x20},
+       {0x370c, 0x0c},
+       {0x370d, 0x11},
+       {0x370e, 0x00},
+       {0x370f, 0x40},
+       {0x3710, 0x00},
+       {0x371a, 0x1c},
+       {0x371b, 0x05},
+       {0x371c, 0x01},
+       {0x371e, 0xa1},
+       {0x371f, 0x0c},
+       {0x3721, 0x00},
+       {0x3724, 0x10},
+       {0x3726, 0x00},
+       {0x372a, 0x01},
+       {0x3730, 0x10},
+       {0x3738, 0x22},
+       {0x3739, 0xe5},
+       {0x373a, 0x50},
+       {0x373b, 0x02},
+       {0x373c, 0x41},
+       {0x373f, 0x02},
+       {0x3740, 0x42},
+       {0x3741, 0x02},
+       {0x3742, 0x18},
+       {0x3743, 0x01},
+       {0x3744, 0x02},
+       {0x3747, 0x10},
+       {0x374c, 0x04},
+       {0x3751, 0xf0},
+       {0x3752, 0x00},
+       {0x3753, 0x00},
+       {0x3754, 0xc0},
+       {0x3755, 0x00},
+       {0x3756, 0x1a},
+       {0x3758, 0x00},
+       {0x3759, 0x0f},
+       {0x376b, 0x44},
+       {0x375c, 0x04},
+       {0x3774, 0x10},
+       {0x3776, 0x00},
+       {0x377f, 0x08},
+       {0x3780, 0x22},
+       {0x3781, 0x0c},
+       {0x3784, 0x2c},
+       {0x3785, 0x1e},
+       {0x378f, 0xf5},
+       {0x3791, 0xb0},
+       {0x3795, 0x00},
+       {0x3796, 0x64},
+       {0x3797, 0x11},
+       {0x3798, 0x30},
+       {0x3799, 0x41},
+       {0x379a, 0x07},
+       {0x379b, 0xb0},
+       {0x379c, 0x0c},
+       {0x37c5, 0x00},
+       {0x37c6, 0x00},
+       {0x37c7, 0x00},
+       {0x37c9, 0x00},
+       {0x37ca, 0x00},
+       {0x37cb, 0x00},
+       {0x37de, 0x00},
+       {0x37df, 0x00},
+       {0x3800, 0x00},
+       {0x3801, 0x00},
+       {0x3802, 0x00},
+       {0x3803, 0x00},
+       {0x3804, 0x0a},
+       {0x3805, 0x3f},
+       {0x3806, 0x07},
+       {0x3807, 0xa3},
+       {0x3808, 0x05},
+       {0x3809, 0x10},
+       {0x380a, 0x03},
+       {0x380b, 0xcc},
+       {0x380c, 0x0a},
+       {0x380d, 0x80},
+       {0x380e, 0x07},
+       {0x380f, 0xc0},
+       {0x3810, 0x00},
+       {0x3811, 0x02},
+       {0x3812, 0x00},
+       {0x3813, 0x02},
+       {0x3814, 0x31},
+       {0x3815, 0x31},
+       {0x3820, 0x01},
+       {0x3821, 0x1f},
+       {0x3823, 0x00},
+       {0x3824, 0x00},
+       {0x3825, 0x00},
+       {0x3826, 0x00},
+       {0x3827, 0x00},
+       {0x382a, 0x04},
+       {0x3a04, 0x06},
+       {0x3a05, 0x14},
+       {0x3a06, 0x00},
+       {0x3a07, 0xfe},
+       {0x3b00, 0x00},
+       {0x3b02, 0x00},
+       {0x3b03, 0x00},
+       {0x3b04, 0x00},
+       {0x3b05, 0x00},
+       {0x3e07, 0x20},
+       {0x4000, 0x08},
+       {0x4001, 0x04},
+       {0x4002, 0x45},
+       {0x4004, 0x08},
+       {0x4005, 0x18},
+       {0x4006, 0x20},
+       {0x4008, 0x24},
+       {0x4009, 0x40},
+       {0x400c, 0x00},
+       {0x400d, 0x00},
+       {0x4058, 0x00},
+       {0x404e, 0x37},
+       {0x404f, 0x8f},
+       {0x4058, 0x00},
+       {0x4101, 0xb2},
+       {0x4303, 0x00},
+       {0x4304, 0x08},
+       {0x4307, 0x30},
+       {0x4311, 0x04},
+       {0x4315, 0x01},
+       {0x4511, 0x05},
+       {0x4512, 0x01},
+       {0x4806, 0x00},
+       {0x4816, 0x52},
+       {0x481f, 0x30},
+       {0x4826, 0x2c},
+       {0x4831, 0x64},
+       {0x4d00, 0x04},
+       {0x4d01, 0x71},
+       {0x4d02, 0xfd},
+       {0x4d03, 0xf5},
+       {0x4d04, 0x0c},
+       {0x4d05, 0xcc},
+       {0x4837, 0x0a},
+       {0x5000, 0x06},
+       {0x5001, 0x01},
+       {0x5002, 0x00},
+       {0x5003, 0x20},
+       {0x5046, 0x0a},
+       {0x5013, 0x00},
+       {0x5046, 0x0a},
+       {0x5780, 0x1c},
+       {0x5786, 0x20},
+       {0x5787, 0x10},
+       {0x5788, 0x18},
+       {0x578a, 0x04},
+       {0x578b, 0x02},
+       {0x578c, 0x02},
+       {0x578e, 0x06},
+       {0x578f, 0x02},
+       {0x5790, 0x02},
+       {0x5791, 0xff},
+       {0x5842, 0x01},
+       {0x5843, 0x2b},
+       {0x5844, 0x01},
+       {0x5845, 0x92},
+       {0x5846, 0x01},
+       {0x5847, 0x8f},
+       {0x5848, 0x01},
+       {0x5849, 0x0c},
+       {0x5e00, 0x00},
+       {0x5e10, 0x0c},
+       {0x0100, 0x01},
+       {OV5693_TABLE_END, 0x0000}
+};
+
+static const struct ov5693_reg ov5693_1920x1080_i2c[] = {
+       {OV5693_TABLE_RESET, 0x0},/*, 0xIncluding, 0xsw, 0xreset, 0x*/
+       {0x3001, 0x0a},
+       {0x3002, 0x80},
+       {0x3006, 0x00},
+       {0x3011, 0x21},
+       {0x3012, 0x09},
+       {0x3013, 0x10},
+       {0x3014, 0x00},
+       {0x3015, 0x08},
+       {0x3016, 0xf0},
+       {0x3017, 0xf0},
+       {0x3018, 0xf0},
+       {0x301b, 0xb4},
+       {0x301d, 0x02},
+       {0x3021, 0x00},
+       {0x3022, 0x01},
+       {0x3028, 0x44},
+       {0x3098, 0x03},
+       {0x3099, 0x1e},
+       {0x309a, 0x02},
+       {0x309b, 0x01},
+       {0x309c, 0x00},
+       {0x30a0, 0xd2},
+       {0x30a2, 0x01},
+       {0x30b2, 0x00},
+       {0x30b3, 0x64},
+       {0x30b4, 0x03},
+       {0x30b5, 0x04},
+       {0x30b6, 0x01},
+       {0x3104, 0x21},
+       {0x3106, 0x00},
+       {0x3400, 0x04},
+       {0x3401, 0x00},
+       {0x3402, 0x04},
+       {0x3403, 0x00},
+       {0x3404, 0x04},
+       {0x3405, 0x00},
+       {0x3406, 0x01},
+       {0x3500, 0x00},
+       {0x3501, 0x7b},
+       {0x3502, 0x00},
+       {0x3503, 0x07},
+       {0x3504, 0x00},
+       {0x3505, 0x00},
+       {0x3506, 0x00},
+       {0x3507, 0x02},
+       {0x3508, 0x00},
+       {0x3509, 0x08},
+       {0x350a, 0x00},
+       {0x350b, 0x40},
+       {0x3601, 0x0a},
+       {0x3602, 0x38},
+       {0x3612, 0x80},
+       {0x3620, 0x54},
+       {0x3621, 0xc7},
+       {0x3622, 0x0f},
+       {0x3625, 0x10},
+       {0x3630, 0x55},
+       {0x3631, 0xf4},
+       {0x3632, 0x00},
+       {0x3633, 0x34},
+       {0x3634, 0x02},
+       {0x364d, 0x0d},
+       {0x364f, 0xdd},
+       {0x3660, 0x04},
+       {0x3662, 0x10},
+       {0x3663, 0xf1},
+       {0x3665, 0x00},
+       {0x3666, 0x20},
+       {0x3667, 0x00},
+       {0x366a, 0x80},
+       {0x3680, 0xe0},
+       {0x3681, 0x00},
+       {0x3700, 0x42},
+       {0x3701, 0x14},
+       {0x3702, 0xa0},
+       {0x3703, 0xd8},
+       {0x3704, 0x78},
+       {0x3705, 0x02},
+       {0x3708, 0xe2},
+       {0x3709, 0xc3},
+       {0x370a, 0x00},
+       {0x370b, 0x20},
+       {0x370c, 0x0c},
+       {0x370d, 0x11},
+       {0x370e, 0x00},
+       {0x370f, 0x40},
+       {0x3710, 0x00},
+       {0x371a, 0x1c},
+       {0x371b, 0x05},
+       {0x371c, 0x01},
+       {0x371e, 0xa1},
+       {0x371f, 0x0c},
+       {0x3721, 0x00},
+       {0x3724, 0x10},
+       {0x3726, 0x00},
+       {0x372a, 0x01},
+       {0x3730, 0x10},
+       {0x3738, 0x22},
+       {0x3739, 0xe5},
+       {0x373a, 0x50},
+       {0x373b, 0x02},
+       {0x373c, 0x41},
+       {0x373f, 0x02},
+       {0x3740, 0x42},
+       {0x3741, 0x02},
+       {0x3742, 0x18},
+       {0x3743, 0x01},
+       {0x3744, 0x02},
+       {0x3747, 0x10},
+       {0x374c, 0x04},
+       {0x3751, 0xf0},
+       {0x3752, 0x00},
+       {0x3753, 0x00},
+       {0x3754, 0xc0},
+       {0x3755, 0x00},
+       {0x3756, 0x1a},
+       {0x3758, 0x00},
+       {0x3759, 0x0f},
+       {0x376b, 0x44},
+       {0x375c, 0x04},
+       {0x3774, 0x10},
+       {0x3776, 0x00},
+       {0x377f, 0x08},
+       {0x3780, 0x22},
+       {0x3781, 0x0c},
+       {0x3784, 0x2c},
+       {0x3785, 0x1e},
+       {0x378f, 0xf5},
+       {0x3791, 0xb0},
+       {0x3795, 0x00},
+       {0x3796, 0x64},
+       {0x3797, 0x11},
+       {0x3798, 0x30},
+       {0x3799, 0x41},
+       {0x379a, 0x07},
+       {0x379b, 0xb0},
+       {0x379c, 0x0c},
+       {0x37c5, 0x00},
+       {0x37c6, 0x00},
+       {0x37c7, 0x00},
+       {0x37c9, 0x00},
+       {0x37ca, 0x00},
+       {0x37cb, 0x00},
+       {0x37de, 0x00},
+       {0x37df, 0x00},
+       {0x3800, 0x00},
+       {0x3801, 0x00},
+       {0x3802, 0x00},
+       {0x3803, 0xf8},
+       {0x3804, 0x0a},
+       {0x3805, 0x3f},
+       {0x3806, 0x06},
+       {0x3807, 0xab},
+       {0x3808, 0x07},
+       {0x3809, 0x80},
+       {0x380a, 0x04},
+       {0x380b, 0x38},
+       {0x380c, 0x0a},
+       {0x380d, 0x80},
+       {0x380e, 0x07},
+       {0x380f, 0xc0},
+       {0x3810, 0x00},
+       {0x3811, 0x02},
+       {0x3812, 0x00},
+       {0x3813, 0x02},
+       {0x3814, 0x11},
+       {0x3815, 0x11},
+       {0x3820, 0x00},
+       {0x3821, 0x1e},
+       {0x3823, 0x00},
+       {0x3824, 0x00},
+       {0x3825, 0x00},
+       {0x3826, 0x00},
+       {0x3827, 0x00},
+       {0x382a, 0x04},
+       {0x3a04, 0x06},
+       {0x3a05, 0x14},
+       {0x3a06, 0x00},
+       {0x3a07, 0xfe},
+       {0x3b00, 0x00},
+       {0x3b02, 0x00},
+       {0x3b03, 0x00},
+       {0x3b04, 0x00},
+       {0x3b05, 0x00},
+       {0x3e07, 0x20},
+       {0x4000, 0x08},
+       {0x4001, 0x04},
+       {0x4002, 0x45},
+       {0x4004, 0x08},
+       {0x4005, 0x18},
+       {0x4006, 0x20},
+       {0x4008, 0x24},
+       {0x4009, 0x40},
+       {0x400c, 0x00},
+       {0x400d, 0x00},
+       {0x4058, 0x00},
+       {0x404e, 0x37},
+       {0x404f, 0x8f},
+       {0x4058, 0x00},
+       {0x4101, 0xb2},
+       {0x4303, 0x00},
+       {0x4304, 0x08},
+       {0x4307, 0x30},
+       {0x4311, 0x04},
+       {0x4315, 0x01},
+       {0x4511, 0x05},
+       {0x4512, 0x01},
+       {0x4806, 0x00},
+       {0x4816, 0x52},
+       {0x481f, 0x30},
+       {0x4826, 0x2c},
+       {0x4831, 0x64},
+       {0x4d00, 0x04},
+       {0x4d01, 0x71},
+       {0x4d02, 0xfd},
+       {0x4d03, 0xf5},
+       {0x4d04, 0x0c},
+       {0x4d05, 0xcc},
+       {0x4837, 0x0a},
+       {0x5000, 0x06},
+       {0x5001, 0x01},
+       {0x5002, 0x80},
+       {0x5003, 0x20},
+       {0x5046, 0x0a},
+       {0x5013, 0x00},
+       {0x5046, 0x0a},
+       {0x5780, 0x1c},
+       {0x5786, 0x20},
+       {0x5787, 0x10},
+       {0x5788, 0x18},
+       {0x578a, 0x04},
+       {0x578b, 0x02},
+       {0x578c, 0x02},
+       {0x578e, 0x06},
+       {0x578f, 0x02},
+       {0x5790, 0x02},
+       {0x5791, 0xff},
+       {0x5842, 0x01},
+       {0x5843, 0x2b},
+       {0x5844, 0x01},
+       {0x5845, 0x92},
+       {0x5846, 0x01},
+       {0x5847, 0x8f},
+       {0x5848, 0x01},
+       {0x5849, 0x0c},
+       {0x5e00, 0x00},
+       {0x5e10, 0x0c},
+       {0x0100, 0x01},
+       {OV5693_TABLE_END, 0x0000}
+};
+
+
+static const struct ov5693_reg ov5693_1280x720_120fps_i2c[] = {
+       {OV5693_TABLE_RESET, 0},/* Including sw reset */
+       {0x3001, 0x0a},
+       {0x3002, 0x80},
+       {0x3006, 0x00},
+       {0x3011, 0x21},
+       {0x3012, 0x09},
+       {0x3013, 0x10},
+       {0x3014, 0x00},
+       {0x3015, 0x08},
+       {0x3016, 0xf0},
+       {0x3017, 0xf0},
+       {0x3018, 0xf0},
+       {0x301b, 0xb4},
+       {0x301d, 0x02},
+       {0x3021, 0x00},
+       {0x3022, 0x01},
+       {0x3028, 0x44},
+       {0x3098, 0x03},
+       {0x3099, 0x1e},
+       {0x309a, 0x02},
+       {0x309b, 0x01},
+       {0x309c, 0x00},
+       {0x30a0, 0xd2},
+       {0x30a2, 0x01},
+       {0x30b2, 0x00},
+       {0x30b3, 0x64},
+       {0x30b4, 0x03},
+       {0x30b5, 0x04},
+       {0x30b6, 0x01},
+       {0x3104, 0x21},
+       {0x3106, 0x00},
+       {0x3400, 0x04},
+       {0x3401, 0x00},
+       {0x3402, 0x04},
+       {0x3403, 0x00},
+       {0x3404, 0x04},
+       {0x3405, 0x00},
+       {0x3406, 0x01},
+       {0x3500, 0x00},
+       {0x3501, 0x2e},
+       {0x3502, 0x80},
+       {0x3503, 0x07},
+       {0x3504, 0x00},
+       {0x3505, 0x00},
+       {0x3506, 0x00},
+       {0x3507, 0x02},
+       {0x3508, 0x00},
+       {0x3509, 0x08},
+       {0x350a, 0x00},
+       {0x350b, 0x40},
+       {0x3601, 0x0a},
+       {0x3602, 0x38},
+       {0x3612, 0x80},
+       {0x3620, 0x54},
+       {0x3621, 0xc7},
+       {0x3622, 0x0f},
+       {0x3625, 0x10},
+       {0x3630, 0x55},
+       {0x3631, 0xf4},
+       {0x3632, 0x00},
+       {0x3633, 0x34},
+       {0x3634, 0x02},
+       {0x364d, 0x0d},
+       {0x364f, 0xdd},
+       {0x3660, 0x04},
+       {0x3662, 0x10},
+       {0x3663, 0xf1},
+       {0x3665, 0x00},
+       {0x3666, 0x20},
+       {0x3667, 0x00},
+       {0x366a, 0x80},
+       {0x3680, 0xe0},
+       {0x3681, 0x00},
+       {0x3700, 0x42},
+       {0x3701, 0x14},
+       {0x3702, 0xa0},
+       {0x3703, 0xd8},
+       {0x3704, 0x78},
+       {0x3705, 0x02},
+       {0x3708, 0xe6},
+       {0x3709, 0xc7},
+       {0x370a, 0x00},
+       {0x370b, 0x20},
+       {0x370c, 0x0c},
+       {0x370d, 0x11},
+       {0x370e, 0x00},
+       {0x370f, 0x40},
+       {0x3710, 0x00},
+       {0x371a, 0x1c},
+       {0x371b, 0x05},
+       {0x371c, 0x01},
+       {0x371e, 0xa1},
+       {0x371f, 0x0c},
+       {0x3721, 0x00},
+       {0x3724, 0x10},
+       {0x3726, 0x00},
+       {0x372a, 0x01},
+       {0x3730, 0x10},
+       {0x3738, 0x22},
+       {0x3739, 0xe5},
+       {0x373a, 0x50},
+       {0x373b, 0x02},
+       {0x373c, 0x41},
+       {0x373f, 0x02},
+       {0x3740, 0x42},
+       {0x3741, 0x02},
+       {0x3742, 0x18},
+       {0x3743, 0x01},
+       {0x3744, 0x02},
+       {0x3747, 0x10},
+       {0x374c, 0x04},
+       {0x3751, 0xf0},
+       {0x3752, 0x00},
+       {0x3753, 0x00},
+       {0x3754, 0xc0},
+       {0x3755, 0x00},
+       {0x3756, 0x1a},
+       {0x3758, 0x00},
+       {0x3759, 0x0f},
+       {0x376b, 0x44},
+       {0x375c, 0x04},
+       {0x3774, 0x10},
+       {0x3776, 0x00},
+       {0x377f, 0x08},
+       {0x3780, 0x22},
+       {0x3781, 0x0c},
+       {0x3784, 0x2c},
+       {0x3785, 0x1e},
+       {0x378f, 0xf5},
+       {0x3791, 0xb0},
+       {0x3795, 0x00},
+       {0x3796, 0x64},
+       {0x3797, 0x11},
+       {0x3798, 0x30},
+       {0x3799, 0x41},
+       {0x379a, 0x07},
+       {0x379b, 0xb0},
+       {0x379c, 0x0c},
+       {0x37c5, 0x00},
+       {0x37c6, 0x00},
+       {0x37c7, 0x00},
+       {0x37c9, 0x00},
+       {0x37ca, 0x00},
+       {0x37cb, 0x00},
+       {0x37de, 0x00},
+       {0x37df, 0x00},
+       {0x3800, 0x00},
+       {0x3801, 0x00},
+       {0x3802, 0x00},
+       {0x3803, 0xf4},
+       {0x3804, 0x0a},
+       {0x3805, 0x3f},
+       {0x3806, 0x06},
+       {0x3807, 0xab},
+       {0x3808, 0x05},
+       {0x3809, 0x00},
+       {0x380a, 0x02},
+       {0x380b, 0xd0},
+       {0x380c, 0x06},
+       {0x380d, 0xd8},
+       {0x380e, 0x02},
+       {0x380f, 0xf8},
+       {0x3810, 0x00},
+       {0x3811, 0x02},
+       {0x3812, 0x00},
+       {0x3813, 0x02},
+       {0x3814, 0x31},
+       {0x3815, 0x31},
+       {0x3820, 0x04},
+       {0x3821, 0x1f},
+       {0x3823, 0x00},
+       {0x3824, 0x00},
+       {0x3825, 0x00},
+       {0x3826, 0x00},
+       {0x3827, 0x00},
+       {0x382a, 0x04},
+       {0x3a04, 0x06},
+       {0x3a05, 0x14},
+       {0x3a06, 0x00},
+       {0x3a07, 0xfe},
+       {0x3b00, 0x00},
+       {0x3b02, 0x00},
+       {0x3b03, 0x00},
+       {0x3b04, 0x00},
+       {0x3b05, 0x00},
+       {0x3e07, 0x20},
+       {0x4000, 0x08},
+       {0x4001, 0x04},
+       {0x4002, 0x45},
+       {0x4004, 0x08},
+       {0x4005, 0x18},
+       {0x4006, 0x20},
+       {0x4008, 0x24},
+       {0x4009, 0x40},
+       {0x400c, 0x00},
+       {0x400d, 0x00},
+       {0x4058, 0x00},
+       {0x404e, 0x37},
+       {0x404f, 0x8f},
+       {0x4058, 0x00},
+       {0x4101, 0xb2},
+       {0x4303, 0x00},
+       {0x4304, 0x08},
+       {0x4307, 0x30},
+       {0x4311, 0x04},
+       {0x4315, 0x01},
+       {0x4511, 0x05},
+       {0x4512, 0x01},
+       {0x4806, 0x00},
+       {0x4816, 0x52},
+       {0x481f, 0x30},
+       {0x4826, 0x2c},
+       {0x4831, 0x64},
+       {0x4d00, 0x04},
+       {0x4d01, 0x71},
+       {0x4d02, 0xfd},
+       {0x4d03, 0xf5},
+       {0x4d04, 0x0c},
+       {0x4d05, 0xcc},
+       {0x4837, 0x0a},
+       {0x5000, 0x06},
+       {0x5001, 0x01},
+       {0x5002, 0x00},
+       {0x5003, 0x20},
+       {0x5046, 0x0a},
+       {0x5013, 0x00},
+       {0x5046, 0x0a},
+       {0x5780, 0x1c},
+       {0x5786, 0x20},
+       {0x5787, 0x10},
+       {0x5788, 0x18},
+       {0x578a, 0x04},
+       {0x578b, 0x02},
+       {0x578c, 0x02},
+       {0x578e, 0x06},
+       {0x578f, 0x02},
+       {0x5790, 0x02},
+       {0x5791, 0xff},
+       {0x5842, 0x01},
+       {0x5843, 0x2b},
+       {0x5844, 0x01},
+       {0x5845, 0x92},
+       {0x5846, 0x01},
+       {0x5847, 0x8f},
+       {0x5848, 0x01},
+       {0x5849, 0x0c},
+       {0x5e00, 0x00},
+       {0x5e10, 0x0c},
+       {0x0100, 0x01},
+       {0x350b, 0xF8},
+       {OV5693_TABLE_END, 0x0000}
+};
+
+enum {
+       OV5693_MODE_2592x1944 = 0,
+       OV5693_MODE_1920x1080,
+       OV5693_MODE_1296x972,
+       OV5693_MODE_1280x720_120FPS,
+};
+
+static const struct ov5693_reg *mode_table[] = {
+       [OV5693_MODE_2592x1944]         = ov5693_2592x1944_i2c,
+       [OV5693_MODE_1920x1080]         = ov5693_1920x1080_i2c,
+       [OV5693_MODE_1296x972]          = ov5693_1296x972_i2c,
+       [OV5693_MODE_1280x720_120FPS]   = ov5693_1280x720_120fps_i2c,
+};
+
+static int ov5693_i2c_rd8(struct ov5693_info *info, u16 reg, u8 *val)
+{
+       unsigned int data;
+       int ret = regmap_read(info->regmap, reg, &data);
+       *val = data;
+
+       return ret;
+}
+
+static int ov5693_i2c_wr_table(struct ov5693_info *info,
+                               const struct ov5693_reg table[])
+{
+       int err;
+       int buf_count = 0;
+       const struct ov5693_reg *next, *n_next;
+       u16 i2c_reg = 0;
+       u8 i2c_buf[OV5693_SIZEOF_I2C_BUF];
+
+       u8 *b_ptr = i2c_buf;
+       u8 reset_status = 1;
+       u8 reset_tries_left = OV5693_TABLE_RESET_TIMEOUT;
+
+       for (next = table; next->addr != OV5693_TABLE_END; next++) {
+               if (next->addr == OV5693_TABLE_WAIT_MS) {
+                       msleep(next->val);
+                       continue;
+               } else if (next->addr == OV5693_TABLE_RESET) {
+                       err = regmap_write(info->regmap, 0x0103, 0x01);
+                       if (err)
+                               return err;
+                       while (reset_status) {
+                               usleep_range(200, 300);
+                               if (reset_tries_left < 1)
+                                       return -EIO;
+                               err = ov5693_i2c_rd8(info, 0x0103,
+                                                       &reset_status);
+                               if (err)
+                                       return err;
+                               reset_status &= 0x01;
+                               reset_tries_left -= 1;
+                       }
+                       continue;
+               }
+
+               if (buf_count == 0) {
+                       b_ptr = i2c_buf;
+                       i2c_reg = next->addr;
+               }
+
+               *b_ptr++ = next->val;
+               buf_count++;
+               n_next = next + 1;
+               if (n_next->addr == next->addr + 1 &&
+                       n_next->addr != OV5693_TABLE_WAIT_MS &&
+                       buf_count < OV5693_SIZEOF_I2C_BUF &&
+                       n_next->addr != OV5693_TABLE_RESET &&
+                       n_next->addr != OV5693_TABLE_END)
+                       continue;
+
+               err = regmap_bulk_write(info->regmap, i2c_reg,
+                                       i2c_buf, buf_count);
+               if (err)
+                       return err;
+
+               buf_count = 0;
+       }
+
+       return 0;
+}
+
+
+static inline int ov5693_frame_length_reg(struct ov5693_reg *regs,
+                                       u32 frame_length)
+{
+       regs->addr = 0x380E;
+       regs->val = (frame_length >> 8) & 0xff;
+       (regs + 1)->addr = 0x380F;
+       (regs + 1)->val = (frame_length) & 0xff;
+
+       return 2;
+}
+
+static inline int ov5693_coarse_time_reg(struct ov5693_reg *regs,
+                                       u32 coarse_time)
+{
+       regs->addr = 0x3500;
+       regs->val = (coarse_time >> 12) & 0xff;
+       (regs + 1)->addr = 0x3501;
+       (regs + 1)->val = (coarse_time >> 4) & 0xff;
+       (regs + 2)->addr = 0x3502;
+       (regs + 2)->val = (coarse_time & 0xf) << 4;
+
+       return 3;
+}
+
+#define OV5693_ENTER_GROUP_HOLD(group_hold) \
+       do {    \
+               if (group_hold) {   \
+                       reg_list[offset].addr = 0x3208; \
+                       reg_list[offset].val = 0x01;\
+                       offset++;  \
+               }   \
+       } while (0)
+
+#define OV5693_LEAVE_GROUP_HOLD(group_hold) \
+       do {    \
+               if (group_hold) {   \
+                       reg_list[offset].addr = 0x3208; \
+                       reg_list[offset].val = 0x11;\
+                       offset++;  \
+                       reg_list[offset].addr = 0x3208; \
+                       reg_list[offset].val = 0xe1;\
+                       offset++;  \
+               } \
+       } while (0)
+
+static int ov5693_set_frame_length(struct ov5693_info *info,
+                                  u32 frame_length, bool group_hold)
+{
+       struct ov5693_reg reg_list[9];
+       int err = 0;
+       int offset = 0;
+
+       OV5693_ENTER_GROUP_HOLD(group_hold);
+       offset += ov5693_frame_length_reg(reg_list + offset, frame_length);
+       OV5693_LEAVE_GROUP_HOLD(group_hold);
+
+       reg_list[offset].addr = OV5693_TABLE_END;
+       offset++;
+
+       err = ov5693_i2c_wr_table(info, reg_list);
+
+       return err;
+}
+
+static int ov5693_set_coarse_time(struct ov5693_info *info,
+                                 u32 coarse_time, bool group_hold)
+{
+       struct ov5693_reg reg_list[16];
+       int err = 0;
+       int offset = 0;
+
+       OV5693_ENTER_GROUP_HOLD(group_hold);
+       offset += ov5693_coarse_time_reg(reg_list + offset, coarse_time);
+       OV5693_LEAVE_GROUP_HOLD(group_hold);
+
+       reg_list[offset].addr = OV5693_TABLE_END;
+       offset++;
+
+       err = ov5693_i2c_wr_table(info, reg_list);
+
+       return err;
+}
+
+static inline int ov5693_gain_reg(struct ov5693_reg *regs, u32 gain)
+{
+       (regs)->addr = 0x350B;
+       (regs)->val = gain;
+
+       return 1;
+}
+
+static int ov5693_bin_wr(struct ov5693_info *info, u8 enable)
+{
+       int err = 0;
+
+       if (enable == info->bin_en)
+               return 0;
+
+       if (!err)
+               info->bin_en = enable;
+       dev_dbg(&info->i2c_client->dev, "%s bin_en=%x err=%d\n",
+               __func__, info->bin_en, err);
+       return err;
+}
+
+static int ov5693_exposure_wr(struct ov5693_info *info,
+                               struct ov5693_mode *mode)
+{
+       struct ov5693_reg reg_list[16];
+       int err = 0;
+       int offset = 0;
+       bool group_hold = true; /* To use GROUP_HOLD macros */
+
+       OV5693_ENTER_GROUP_HOLD(group_hold);
+       offset += ov5693_coarse_time_reg(reg_list + offset, mode->coarse_time);
+       offset += ov5693_gain_reg(reg_list + offset, mode->gain);
+       OV5693_LEAVE_GROUP_HOLD(group_hold);
+
+       reg_list[offset].addr = OV5693_TABLE_END;
+       err = ov5693_i2c_wr_table(info, reg_list);
+
+       return err;
+}
+
+
+static int ov5693_set_gain(struct ov5693_info *info, u32 gain, bool group_hold)
+{
+       struct ov5693_reg reg_list[9];
+       int err = 0;
+       int offset = 0;
+
+       OV5693_ENTER_GROUP_HOLD(group_hold);
+       offset += ov5693_gain_reg(reg_list + offset, gain);
+       OV5693_LEAVE_GROUP_HOLD(group_hold);
+
+       reg_list[offset].addr = OV5693_TABLE_END;
+       offset++;
+
+       err = ov5693_i2c_wr_table(info, reg_list);
+
+       return err;
+}
+
+static int ov5693_set_group_hold(struct ov5693_info *info,
+                               struct ov5693_ae *ae)
+{
+       int err = 0;
+       struct ov5693_reg reg_list[16];
+       int offset = 0;
+       bool group_hold = true; /* To use GROUP_HOLD macros */
+
+       OV5693_ENTER_GROUP_HOLD(group_hold);
+       if (ae->gain_enable)
+               offset += ov5693_gain_reg(reg_list + offset,
+                                         ae->gain);
+       if (ae->frame_length_enable)
+               offset += ov5693_frame_length_reg(reg_list + offset,
+                                                 ae->frame_length);
+       if (ae->coarse_time_enable)
+               offset += ov5693_coarse_time_reg(reg_list + offset,
+                                                ae->coarse_time);
+       OV5693_LEAVE_GROUP_HOLD(group_hold);
+
+       reg_list[offset].addr = OV5693_TABLE_END;
+       err |= ov5693_i2c_wr_table(info, reg_list);
+
+       return err;
+}
+
+static int ov5693_gpio_rd(struct ov5693_info *info,
+                       enum ov5693_gpio_type type)
+{
+       int val = -EINVAL;
+
+       if (info->gpio[type].gpio) {
+               val = gpio_get_value_cansleep(info->gpio[type].gpio);
+               dev_dbg(&info->i2c_client->dev, "%s %u %d\n", __func__,
+                      info->gpio[type].gpio, val);
+               if (!info->gpio[type].active_high)
+                       val = !val;
+               val &= 1;
+       }
+       return val; /* return read value or error */
+}
+
+static int ov5693_gpio_wr(struct ov5693_info *info,
+                       enum ov5693_gpio_type type,
+                       int val) /* val: 0=deassert, 1=assert */
+{
+       int err = -EINVAL;
+
+       if (info->gpio[type].gpio) {
+               if (!info->gpio[type].active_high)
+                       val = !val;
+               val &= 1;
+               err = val;
+               gpio_set_value_cansleep(info->gpio[type].gpio, val);
+               dev_dbg(&info->i2c_client->dev, "%s %u %d\n", __func__,
+                      info->gpio[type].gpio, val);
+       }
+       return err; /* return value written or error */
+}
+
+static void ov5693_gpio_pwrdn(struct ov5693_info *info, int val)
+{
+       int prev_val;
+
+       prev_val = ov5693_gpio_rd(info, OV5693_GPIO_TYPE_PWRDN);
+       if ((prev_val < 0) || (val == prev_val))
+               return;
+
+       ov5693_gpio_wr(info, OV5693_GPIO_TYPE_PWRDN, val);
+       if (!val && prev_val)
+               /* if transition from assert to deassert then delay for I2C */
+               msleep(50);
+}
+
+static void ov5693_gpio_exit(struct ov5693_info *info)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(ov5693_gpio); i++) {
+               if (info->gpio[i].gpio && info->gpio[i].own)
+                       gpio_free(info->gpio[i].gpio);
+       }
+}
+
+static void ov5693_gpio_init(struct ov5693_info *info)
+{
+       char label[32];
+       unsigned long flags;
+       unsigned type;
+       unsigned i;
+       unsigned j;
+       int err;
+
+       if (!info->pdata->gpio_count || !info->pdata->gpio)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(ov5693_gpio); i++) {
+               type = ov5693_gpio[i].gpio_type;
+               for (j = 0; j < info->pdata->gpio_count; j++) {
+                       if (type == info->pdata->gpio[j].gpio_type)
+                               break;
+               }
+               if (j == info->pdata->gpio_count)
+                       continue;
+
+               info->gpio[type].gpio = info->pdata->gpio[j].gpio;
+               if (ov5693_gpio[i].use_flags) {
+                       flags = ov5693_gpio[i].flags;
+                       info->gpio[type].active_high =
+                                               ov5693_gpio[i].active_high;
+               } else {
+                       info->gpio[type].active_high =
+                                       info->pdata->gpio[j].active_high;
+                       if (info->gpio[type].active_high)
+                               flags = GPIOF_OUT_INIT_LOW;
+                       else
+                               flags = GPIOF_OUT_INIT_HIGH;
+               }
+               if (!info->pdata->gpio[j].init_en)
+                       continue;
+
+               snprintf(label, sizeof(label), "ov5693_%u_%s",
+                        info->pdata->num, ov5693_gpio[i].label);
+               err = gpio_request_one(info->gpio[type].gpio, flags, label);
+               if (err) {
+                       dev_err(&info->i2c_client->dev,
+                               "%s ERR %s %u\n", __func__, label,
+                               info->gpio[type].gpio);
+               } else {
+                       info->gpio[type].own = true;
+                       dev_dbg(&info->i2c_client->dev,
+                               "%s %s %u\n", __func__, label,
+                               info->gpio[type].gpio);
+               }
+       }
+}
+
+static int ov5693_power_off(struct ov5693_info *info)
+{
+       struct ov5693_power_rail *pw = &info->regulators;
+       int err;
+
+       if (false == info->power_on)
+               return 0;
+
+       if (info->pdata && info->pdata->power_off) {
+               err = info->pdata->power_off(pw);
+               if (0 > err)
+                       return err;
+               info->power_on = false;
+               ov5693_gpio_pwrdn(info, 1);
+       } else {
+               dev_err(&info->i2c_client->dev,
+                       "%s ERR: has no power_off function\n", __func__);
+               err = -EINVAL;
+       }
+       return err;
+}
+
+static int ov5693_power_on(struct ov5693_info *info, bool standby)
+{
+       struct ov5693_power_rail *pw = &info->regulators;
+       int err;
+
+       if (true == info->power_on)
+               return 0;
+
+       if (info->pdata && info->pdata->power_on) {
+               err = info->pdata->power_on(pw);
+               if (0 > err)
+                       return err;
+               info->power_on = true;
+               ov5693_gpio_pwrdn(info, standby ? 1 : 0);
+               msleep(100);
+       } else {
+               dev_err(&info->i2c_client->dev,
+                       "%s ERR: has no power_on function\n", __func__);
+               err = -EINVAL;
+       }
+       return err;
+}
+
+static int ov5693_pm_wr(struct ov5693_info *info, int pwr)
+{
+       int err = 0;
+
+       if ((info->pdata->cfg & (NVC_CFG_OFF2STDBY | NVC_CFG_BOOT_INIT)) &&
+                       (pwr == NVC_PWR_OFF ||
+                        pwr == NVC_PWR_STDBY_OFF))
+               pwr = NVC_PWR_STDBY;
+       if (pwr == info->pwr_dev)
+               return 0;
+
+       switch (pwr) {
+       case NVC_PWR_OFF_FORCE:
+       case NVC_PWR_OFF:
+       case NVC_PWR_STDBY_OFF:
+               err = ov5693_power_off(info);
+               info->mode_valid = false;
+               info->bin_en = 0;
+               break;
+
+       case NVC_PWR_STDBY:
+               err = ov5693_power_on(info, true);
+               break;
+
+       case NVC_PWR_COMM:
+       case NVC_PWR_ON:
+               err = ov5693_power_on(info, false);
+               break;
+
+       default:
+               err = -EINVAL;
+               break;
+       }
+
+       if (err < 0) {
+               dev_err(&info->i2c_client->dev, "%s err %d\n", __func__, err);
+               pwr = NVC_PWR_ERR;
+       }
+       info->pwr_dev = pwr;
+       dev_dbg(&info->i2c_client->dev, "%s pwr_dev=%d\n",
+               __func__, info->pwr_dev);
+       if (err > 0)
+               return 0;
+
+       return err;
+}
+
+static int ov5693_pm_dev_wr(struct ov5693_info *info, int pwr)
+{
+       if (info->mode_enable)
+               pwr = NVC_PWR_ON;
+       if (pwr < info->pwr_api)
+               pwr = info->pwr_api;
+       return ov5693_pm_wr(info, pwr);
+}
+
+static void ov5693_pm_exit(struct ov5693_info *info)
+{
+       ov5693_pm_wr(info, NVC_PWR_OFF_FORCE);
+
+       ov5693_gpio_exit(info);
+}
+
+static void ov5693_regulator_get(struct ov5693_info *info,
+                                struct regulator **vreg,
+                                const char vreg_name[])
+{
+       struct regulator *reg = NULL;
+       int err = 0;
+
+       reg = devm_regulator_get(&info->i2c_client->dev, vreg_name);
+       if (IS_ERR(reg)) {
+               dev_err(&info->i2c_client->dev, "%s %s ERR: %d\n",
+                       __func__, vreg_name, (int)reg);
+               err = PTR_ERR(reg);
+               reg = NULL;
+       } else {
+               dev_dbg(&info->i2c_client->dev, "%s: %s\n",
+                       __func__, vreg_name);
+       }
+
+       *vreg = reg;
+}
+
+static void ov5693_pm_init(struct ov5693_info *info)
+{
+       struct ov5693_power_rail *pw = &info->regulators;
+
+       ov5693_gpio_init(info);
+
+       ov5693_regulator_get(info, &pw->dvdd, "dvdd");
+
+       ov5693_regulator_get(info, &pw->avdd, "avdd");
+
+       ov5693_regulator_get(info, &pw->dovdd, "dovdd");
+       info->power_on = false;
+}
+
+static int ov5693_mode_able(struct ov5693_info *info, bool mode_enable)
+{
+       u8 val;
+       int err;
+
+       if (mode_enable)
+               val = 0x01;
+       else
+               val = 0x00;
+       err = regmap_write(info->regmap, 0x0100, val);
+       if (!err) {
+               info->mode_enable = mode_enable;
+               dev_dbg(&info->i2c_client->dev, "%s streaming=%x\n",
+                       __func__, info->mode_enable);
+               if (!mode_enable)
+                       ov5693_pm_dev_wr(info, NVC_PWR_STDBY);
+       }
+       return err;
+}
+
+static int ov5693_mode_wr_full(struct ov5693_info *info, u32 mode_index)
+{
+       int err;
+
+       ov5693_pm_dev_wr(info, NVC_PWR_ON);
+       ov5693_bin_wr(info, 0);
+       err = ov5693_i2c_wr_table(info, mode_table[mode_index]);
+       if (!err) {
+               dev_dbg(&info->i2c_client->dev,
+                       "init done(mode=%d)!!!\n", mode_index);
+               info->mode_index = mode_index;
+               info->mode_valid = true;
+       } else {
+               dev_dbg(&info->i2c_client->dev,
+                       "init error(mode=%d)!!!\n", mode_index);
+               info->mode_valid = false;
+       }
+       return err;
+}
+
+
+static int ov5693_set_mode(struct ov5693_info *info,
+               struct ov5693_mode *mode)
+{
+       u32 mode_index = 0;
+       int err = 0;
+
+       if (!mode->res_x && !mode->res_y) {
+               if (mode->frame_length || mode->coarse_time || mode->gain) {
+                       /* write exposure only */
+                       err = ov5693_exposure_wr(info, mode);
+                       return err;
+               } else {
+                       /* turn off streaming */
+                       err = ov5693_mode_able(info, false);
+                       return err;
+               }
+       }
+
+       if (mode->res_x == 2592 && mode->res_y == 1944)
+               mode_index = OV5693_MODE_2592x1944;
+       else if (mode->res_x == 1296 && mode->res_y == 972)
+               mode_index = OV5693_MODE_1296x972;
+       else if (mode->res_x == 1920 && mode->res_y == 1080)
+               mode_index = OV5693_MODE_1920x1080;
+       else if (mode->res_x == 1280 && mode->res_y == 720)
+               mode_index = OV5693_MODE_1280x720_120FPS;
+
+       if (!info->mode_valid || (info->mode_index != mode_index))
+               err = ov5693_mode_wr_full(info, mode_index);
+       else
+               dev_dbg(&info->i2c_client->dev, "%s short mode\n", __func__);
+       dev_dbg(&info->i2c_client->dev, "%s: mode #: %d\n",
+               __func__, mode_index);
+       dev_dbg(&info->i2c_client->dev, "%s: AE: %d, %d, %d\n",
+               __func__, mode->frame_length,
+               mode->coarse_time, mode->gain);
+       err |= ov5693_exposure_wr(info, mode);
+       if (err < 0) {
+               info->mode_valid = false;
+               dev_err(&info->i2c_client->dev,
+                       "%s set_mode error\n", __func__);
+               goto ov5693_mode_wr_err;
+       }
+
+       return 0;
+
+ov5693_mode_wr_err:
+       if (!info->mode_enable)
+               ov5693_pm_dev_wr(info, NVC_PWR_OFF);
+       return err;
+}
+
+static int ov5693_get_fuse_id(struct ov5693_info *info)
+{
+       ov5693_i2c_rd8(info, 0x300A, &info->fuseid.id[0]);
+       ov5693_i2c_rd8(info, 0x300B, &info->fuseid.id[0]);
+       info->fuseid.size = 2;
+       dev_dbg(&info->i2c_client->dev, "ov5693 fuse_id: %x,%x\n",
+               info->fuseid.id[0], info->fuseid.id[1]);
+       return 0;
+}
+
+static long ov5693_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct ov5693_info *info = file->private_data;
+       int err;
+
+       switch (cmd) {
+       case OV5693_IOCTL_SET_MODE:
+       {
+               struct ov5693_mode mode;
+               if (copy_from_user(&mode,
+                       (const void __user *)arg,
+                       sizeof(struct ov5693_mode))) {
+                       dev_err(&info->i2c_client->dev,
+                               "%s:Failed to get mode from user.\n",
+                       __func__);
+                       return -EFAULT;
+               }
+               return ov5693_set_mode(info, &mode);
+       }
+       case OV5693_IOCTL_GET_STATUS: {
+               u8 status = 0;
+               if (copy_to_user((void __user *)arg, &status, sizeof(status))) {
+                       dev_err(&info->i2c_client->dev,
+                               "%s:Failed to copy status to user.\n",
+                       __func__);
+                       return -EFAULT;
+               }
+               return 0;
+               }
+
+       case OV5693_IOCTL_SET_GROUP_HOLD: {
+               struct ov5693_ae ae;
+               if (copy_from_user(&ae, (const void __user *)arg,
+                               sizeof(struct ov5693_ae))) {
+                       dev_dbg(&info->i2c_client->dev,
+                               "%s:fail group hold\n", __func__);
+                       return -EFAULT;
+               }
+
+               return ov5693_set_group_hold(info, &ae);
+               }
+
+       case OV5693_IOCTL_SET_FRAME_LENGTH:
+               return ov5693_set_frame_length(info, (u32)arg, true);
+
+       case OV5693_IOCTL_SET_COARSE_TIME:
+               return ov5693_set_coarse_time(info, (u32)arg, true);
+
+       case OV5693_IOCTL_SET_GAIN:
+               return ov5693_set_gain(info, (u32)arg, true);
+
+       case OV5693_IOCTL_GET_FUSEID:
+       {
+               err = ov5693_get_fuse_id(info);
+
+               if (err) {
+                       dev_err(&info->i2c_client->dev, "%s:Failed to get fuse id info.\n",
+                       __func__);
+                       return err;
+               }
+               if (copy_to_user((void __user *)arg,
+                               &info->fuseid,
+                               sizeof(struct ov5693_fuseid))) {
+                       dev_dbg(&info->i2c_client->dev, "%s:Fail copy fuse id to user space\n",
+                               __func__);
+                       return -EFAULT;
+               }
+               return 0;
+       }
+       default:
+               dev_err(&info->i2c_client->dev, "%s unsupported ioctl: %x\n",
+                       __func__, cmd);
+       }
+       return -EINVAL;
+}
+
+static void ov5693_sdata_init(struct ov5693_info *info)
+{
+       memcpy(&info->sdata, &ov5693_dflt_sdata, sizeof(info->sdata));
+       if (info->pdata->lens_focal_length)
+               info->sdata.focal_len = info->pdata->lens_focal_length;
+       if (info->pdata->lens_max_aperture)
+               info->sdata.max_aperture = info->pdata->lens_max_aperture;
+       if (info->pdata->lens_fnumber)
+               info->sdata.fnumber = info->pdata->lens_fnumber;
+       if (info->pdata->lens_view_angle_h)
+               info->sdata.view_angle_h = info->pdata->lens_view_angle_h;
+       if (info->pdata->lens_view_angle_v)
+               info->sdata.view_angle_v = info->pdata->lens_view_angle_v;
+}
+
+static int ov5693_open(struct inode *inode, struct file *file)
+{
+       int err;
+       struct miscdevice *miscdev = file->private_data;
+       struct ov5693_info *info = dev_get_drvdata(miscdev->parent);
+
+       if (atomic_xchg(&info->in_use, 1))
+               return -EBUSY;
+
+       file->private_data = info;
+       dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+
+       err = ov5693_power_on(info, false);
+       return err;
+}
+
+int ov5693_release(struct inode *inode, struct file *file)
+{
+       struct ov5693_info *info = file->private_data;
+
+       dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+       ov5693_pm_wr(info, NVC_PWR_OFF);
+       file->private_data = NULL;
+       WARN_ON(!atomic_xchg(&info->in_use, 0));
+       return 0;
+}
+
+static const struct file_operations ov5693_fileops = {
+       .owner = THIS_MODULE,
+       .open = ov5693_open,
+       .unlocked_ioctl = ov5693_ioctl,
+       .release = ov5693_release,
+};
+
+static void ov5693_del(struct ov5693_info *info)
+{
+       ov5693_pm_exit(info);
+       synchronize_rcu();
+}
+
+static int ov5693_remove(struct i2c_client *client)
+{
+       struct ov5693_info *info = i2c_get_clientdata(client);
+
+       dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+       misc_deregister(&info->miscdev);
+       ov5693_del(info);
+       return 0;
+}
+
+static int ov5693_probe(
+       struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       struct ov5693_info *info;
+       char dname[16];
+       unsigned long clock_probe_rate;
+       int err;
+       static struct regmap_config ad5823_regmap_config = {
+               .reg_bits = 16,
+               .val_bits = 8,
+       };
+
+
+       dev_dbg(&client->dev, "%s\n", __func__);
+       info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
+       if (info == NULL) {
+               dev_err(&client->dev, "%s: kzalloc error\n", __func__);
+               return -ENOMEM;
+       }
+
+       info->i2c_client = client;
+       if (client->dev.platform_data)
+               info->pdata = client->dev.platform_data;
+       else {
+               info->pdata = &ov5693_dflt_pdata;
+               dev_dbg(&client->dev,
+                       "%s No platform data. Using defaults.\n",
+                       __func__);
+       }
+
+       info->regmap = devm_regmap_init_i2c(client, &ad5823_regmap_config);
+       if (IS_ERR(info->regmap)) {
+               err = PTR_ERR(info->regmap);
+               dev_err(&client->dev,
+                       "Failed to allocate register map: %d\n", err);
+               return err;
+       }
+
+
+       i2c_set_clientdata(client, info);
+       ov5693_pm_init(info);
+       ov5693_sdata_init(info);
+       if (info->pdata->cfg & (NVC_CFG_NODEV | NVC_CFG_BOOT_INIT)) {
+               if (info->pdata->probe_clock) {
+                       clock_probe_rate = 6000;  /* initial_clcok*/
+                       clock_probe_rate *= 1000;
+                       info->pdata->probe_clock(clock_probe_rate);
+               }
+               ov5693_pm_dev_wr(info, NVC_PWR_COMM);
+               ov5693_pm_dev_wr(info, NVC_PWR_OFF);
+               if (info->pdata->probe_clock)
+                       info->pdata->probe_clock(0);
+       }
+       if (info->pdata->dev_name != NULL)
+               strcpy(dname, info->pdata->dev_name);
+       else
+               strcpy(dname, "ov5693");
+       if (info->pdata->num)
+               snprintf(dname, sizeof(dname), "%s.%u",
+                        dname, info->pdata->num);
+       info->miscdev.name = dname;
+       info->miscdev.fops = &ov5693_fileops;
+       info->miscdev.minor = MISC_DYNAMIC_MINOR;
+       info->miscdev.parent = &client->dev;
+       if (misc_register(&info->miscdev)) {
+               dev_err(&client->dev, "%s unable to register misc device %s\n",
+                       __func__, dname);
+               ov5693_del(info);
+               return -ENODEV;
+       }
+
+       dev_dbg(&client->dev, "ov5693 sensor driver loading done\n");
+       return 0;
+}
+
+static const struct i2c_device_id ov5693_id[] = {
+       { "ov5693", 0 },
+       { },
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5693_id);
+
+static struct i2c_driver ov5693_i2c_driver = {
+       .driver = {
+               .name = "ov5693",
+               .owner = THIS_MODULE,
+       },
+       .id_table = ov5693_id,
+       .probe = ov5693_probe,
+       .remove = ov5693_remove,
+};
+
+module_i2c_driver(ov5693_i2c_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/include/media/ad5823.h b/include/media/ad5823.h
new file mode 100644 (file)
index 0000000..bc5af4b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AD5823_H__
+#define __AD5823_H__
+
+#include <linux/ioctl.h>  /* For IOCTL macros */
+
+#define AD5823_IOCTL_GET_CONFIG   _IOR('o', 1, struct ad5823_config)
+#define AD5823_IOCTL_SET_POSITION _IOW('o', 2, u32)
+
+/* address */
+#define AD5823_RESET                (0x1)
+#define AD5823_MODE                 (0x2)
+#define AD5823_VCM_MOVE_TIME        (0x3)
+#define AD5823_VCM_CODE_MSB         (0x4)
+#define AD5823_VCM_CODE_LSB         (0x5)
+#define AD5823_VCM_THRESHOLD_MSB    (0x6)
+#define AD5823_VCM_THRESHOLD_LSB    (0x7)
+#define AD5823_RING_CTRL            (1 << 2)
+struct ad5823_config {
+       __u32 settle_time;
+       __u32 actuator_range;
+       __u32 pos_low;
+       __u32 pos_high;
+       float focal_length;
+       float fnumber;
+       float max_aperture;
+};
+
+struct ad5823_platform_data {
+       int gpio;
+       int (*power_on)(struct ad5823_platform_data *);
+       int (*power_off)(struct ad5823_platform_data *);
+};
+#endif  /* __AD5820_H__ */
+
diff --git a/include/media/ov5693.h b/include/media/ov5693.h
new file mode 100644 (file)
index 0000000..21e10e8
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OV5693_H__
+#define __OV5693_H__
+
+#include <media/nvc.h>
+#include <media/nvc_image.h>
+
+#define OV5693_IOCTL_SET_MODE               _IOW('o', 1, struct ov5693_mode)
+#define OV5693_IOCTL_SET_FRAME_LENGTH       _IOW('o', 2, __u32)
+#define OV5693_IOCTL_SET_COARSE_TIME        _IOW('o', 3, __u32)
+#define OV5693_IOCTL_SET_GAIN               _IOW('o', 4, __u16)
+#define OV5693_IOCTL_GET_STATUS             _IOR('o', 5, __u8)
+#define OV5693_IOCTL_SET_BINNING            _IOW('o', 6, __u8)
+#define OV5693_IOCTL_TEST_PATTERN           _IOW('o', 7, \
+                                                enum ov5693_test_pattern)
+#define OV5693_IOCTL_SET_GROUP_HOLD         _IOW('o', 8, struct ov5693_ae)
+/* IOCTL to set the operating mode of camera.
+ * This can be either stereo , leftOnly or rightOnly */
+#define OV5693_IOCTL_SET_CAMERA_MODE        _IOW('o', 10, __u32)
+#define OV5693_IOCTL_SYNC_SENSORS           _IOW('o', 11, __u32)
+#define OV5693_IOCTL_GET_FUSEID             _IOR('o', 12, struct ov5693_fuseid)
+
+
+struct ov5693_mode {
+       int res_x;
+       int res_y;
+       int fps;
+       __u32 frame_length;
+       __u32 coarse_time;
+       __u16 gain;
+};
+
+struct ov5693_ae {
+       __u32 frame_length;
+       __u8  frame_length_enable;
+       __u32 coarse_time;
+       __u8  coarse_time_enable;
+       __s32 gain;
+       __u8  gain_enable;
+};
+
+struct ov5693_fuseid {
+       __u32 size;
+       __u8  id[16];
+};
+
+/* See notes in the nvc.h file on the GPIO usage */
+enum ov5693_gpio_type {
+       OV5693_GPIO_TYPE_PWRDN = 0,
+};
+
+struct ov5693_power_rail {
+       struct regulator *dvdd;
+       struct regulator *avdd;
+       struct regulator *dovdd;
+};
+
+struct ov5693_platform_data {
+       unsigned cfg;
+       unsigned num;
+       const char *dev_name;
+       unsigned gpio_count; /* see nvc.h GPIO notes */
+       struct nvc_gpio_pdata *gpio; /* see nvc.h GPIO notes */
+       unsigned lens_focal_length; /* / _INT2FLOAT_DIVISOR */
+       unsigned lens_max_aperture; /* / _INT2FLOAT_DIVISOR */
+       unsigned lens_fnumber; /* / _INT2FLOAT_DIVISOR */
+       unsigned lens_view_angle_h; /* / _INT2FLOAT_DIVISOR */
+       unsigned lens_view_angle_v; /* / _INT2FLOAT_DIVISOR */
+       int (*probe_clock)(unsigned long);
+       int (*power_on)(struct ov5693_power_rail *);
+       int (*power_off)(struct ov5693_power_rail *);
+};
+
+#endif  /* __OV5693_H__ */