Merge branch dev_17 into rel17

This change adds the camera supoorted changes to bring AOHDR feature in
to rel-17.

Change-Id: I39929e0644ce0d3e63c8a6960e2a8c3ebd3596ee
Signed-off-by: sivasubramaniam venkataraman <svenkatarama@nvidia.com>
diff --git a/arch/arm/configs/tegra11_android_defconfig b/arch/arm/configs/tegra11_android_defconfig
index d1a2b505..7857717 100644
--- a/arch/arm/configs/tegra11_android_defconfig
+++ b/arch/arm/configs/tegra11_android_defconfig
@@ -367,12 +367,15 @@
 CONFIG_TEGRA_NVAVP_AUDIO=y
 CONFIG_VIDEO_OV5640=y
 CONFIG_VIDEO_IMX091=y
+CONFIG_VIDEO_IMX135=y
 CONFIG_VIDEO_IMX132=y
 CONFIG_VIDEO_OV9772=y
 CONFIG_TORCH_SSL3250A=y
 CONFIG_MAX77665_FLASH=y
 CONFIG_TORCH_AS364X=y
 CONFIG_VIDEO_AD5816=y
+CONFIG_VIDEO_AR0833=y
+CONFIG_VIDEO_DW9718=y
 # CONFIG_RADIO_ADAPTERS is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
diff --git a/drivers/media/video/tegra/Kconfig b/drivers/media/video/tegra/Kconfig
index ff576d6..6c88a06 100644
--- a/drivers/media/video/tegra/Kconfig
+++ b/drivers/media/video/tegra/Kconfig
@@ -68,6 +68,13 @@
           This is a driver for the IMX091 camera sensor
           for use with the tegra isp.
 
+config VIDEO_IMX135
+        tristate "IMX135 camera sensor support"
+        depends on I2C && ARCH_TEGRA
+        ---help---
+          This is a driver for the IMX135 camera sensor
+          for use with the tegra isp.
+
 config VIDEO_IMX132
         tristate "IMX132 camera sensor support"
         depends on I2C && ARCH_TEGRA
@@ -154,3 +161,17 @@
         ---help---
           This is a driver for the AD5816 focuser
           for use with the tegra isp.
+
+config VIDEO_AR0833
+        tristate "AR0833 camera sensor support"
+        depends on I2C && ARCH_TEGRA
+        ---help---
+          This is a driver for the AR0833 camera sensor
+          for use with the tegra isp.
+
+config VIDEO_DW9718
+        tristate "DW9718 focuser support"
+        depends on I2C && ARCH_TEGRA
+        ---help---
+          This is a driver for the DW9718 focuser
+          for use with the tegra isp.
diff --git a/drivers/media/video/tegra/Makefile b/drivers/media/video/tegra/Makefile
index 7ce7bb0..b76e27b 100644
--- a/drivers/media/video/tegra/Makefile
+++ b/drivers/media/video/tegra/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_TEGRA_NVAVP)	+= nvavp/
 obj-$(CONFIG_TEGRA_DTV)		+= tegra_dtv.o
 obj-$(CONFIG_VIDEO_AR0832)	+= ar0832_main.o
+obj-$(CONFIG_VIDEO_AR0833)	+= ar0833.o
 obj-$(CONFIG_VIDEO_OV5650)	+= ov5650.o
 obj-$(CONFIG_VIDEO_OV5640)	+= ov5640.o
 obj-$(CONFIG_VIDEO_OV14810)	+= ov14810.o
@@ -21,9 +22,11 @@
 obj-$(CONFIG_MAX77665_FLASH)	+= max77665-flash.o
 obj-$(CONFIG_TORCH_AS364X)	+= as364x.o
 obj-$(CONFIG_VIDEO_SH532U)	+= sh532u.o
+obj-$(CONFIG_VIDEO_DW9718)	+= dw9718.o
 obj-$(CONFIG_VIDEO_AD5820)	+= ad5820.o
 obj-$(CONFIG_VIDEO_AD5816)	+= ad5816.o
 obj-$(CONFIG_VIDEO_IMX091)	+= imx091.o
+obj-$(CONFIG_VIDEO_IMX135)	+= imx135.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/ar0833.c b/drivers/media/video/tegra/ar0833.c
new file mode 100644
index 0000000..701468f
--- /dev/null
+++ b/drivers/media/video/tegra/ar0833.c
@@ -0,0 +1,1266 @@
+/*
+ * ar0833.c - ar0833 sensor driver
+ *
+ * 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/kernel.h>
+#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/gpio.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/atomic.h>
+#include <linux/regulator/consumer.h>
+#include <linux/export.h>
+#include <linux/module.h>
+
+#include <media/ar0833.h>
+
+#define SIZEOF_I2C_TRANSBUF 128
+
+struct ar0833_reg {
+	u16 addr;
+	u16 val;
+};
+
+struct ar0833_reg_blob {
+	u16 addr;
+	u16 size;
+	u8 *data;
+};
+
+struct ar0833_info {
+	struct miscdevice		miscdev_info;
+	struct ar0833_power_rail	power;
+	struct ar0833_sensordata	sensor_data;
+	struct i2c_client		*i2c_client;
+	struct ar0833_platform_data	*pdata;
+	atomic_t			in_use;
+	const struct ar0833_reg		*mode;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry			*debugfs_root;
+	u32				debug_i2c_offset;
+	int				enableDCBLC;
+#endif
+	u8				i2c_trans_buf[SIZEOF_I2C_TRANSBUF];
+};
+
+#define AR0833_TABLE_WAIT_MS	0xC000
+#define AR0833_TABLE_NOP	0xC001
+#define AR0833_TABLE_CALL	0xC002
+#define AR0833_TABLE_BLOB	0xC003
+#define AR0833_TABLE_END	0xC004
+#define AR0833_TABLE_8BIT	0x8000
+
+#include "ar0833_mode_tbls.c"
+
+struct ar0833_mode_desc {
+	u16			xres;
+	u16			yres;
+	u8			hdr_en;
+	const struct ar0833_reg *mode_tbl;
+	struct ar0833_modeinfo	mode_info;
+};
+
+static struct ar0833_mode_desc mode_table[] = {
+	{
+		.xres = 3264,
+		.yres = 2448,
+		.hdr_en = 0,
+		.mode_tbl = mode_3264x2448_30fps,
+	},
+	{
+		.xres = 3264,
+		.yres = 2448,
+		.hdr_en = 1,
+		.mode_tbl = mode_3264x2448_HDR_30fps,
+	},
+	{
+		.xres = 1920,
+		.yres = 1080,
+		.hdr_en = 0,
+		.mode_tbl = mode_1920x1080_30fps,
+	},
+	{
+		.xres = 1920,
+		.yres = 1080,
+		.hdr_en = 1,
+		.mode_tbl = mode_1920x1080_HDR_30fps,
+	},
+	{
+		.xres = 3264,
+		.yres = 1836,
+		.hdr_en = 0,
+		.mode_tbl = mode_3264x1836_30fps,
+	},
+	{
+		.xres = 3264,
+		.yres = 1836,
+		.hdr_en = 1,
+		.mode_tbl = mode_3264x1836_HDR_30fps,
+	},
+	{ },
+};
+
+static long ar0833_ioctl(struct file *file,
+			unsigned int cmd, unsigned long arg);
+
+static inline void ar0833_msleep(u32 t)
+{
+	usleep_range(t*1000, t*1000 + 500);
+}
+
+static inline void ar0833_get_coarse_time_regs(struct ar0833_reg *regs,
+						u32 coarse_time)
+{
+	regs->addr = 0x0202;
+	regs->val = coarse_time & 0xFFFF;
+}
+
+static inline void ar0833_get_coarse_time_short_regs(struct ar0833_reg *regs,
+						u32 coarse_time)
+{
+	regs->addr = 0x3088;
+	regs->val = coarse_time & 0xFFFF;
+}
+
+static inline void ar0833_get_gain_reg(struct ar0833_reg *regs, u16 gain)
+{
+	regs->addr = 0x305E;
+	regs->val = gain & 0xFFFF;
+}
+
+static int ar0833_read_reg(struct i2c_client *client, u16 addr, u8 *val)
+{
+	int err;
+	struct i2c_msg msg[2];
+	unsigned char data[3];
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 2;
+	msg[0].buf = data;
+
+	/* high byte goes out first */
+	data[0] = (u8) (addr >> 8);
+	data[1] = (u8) (addr & 0xff);
+
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = 1;
+	msg[1].buf = data + 2;
+
+	err = i2c_transfer(client->adapter, msg, 2);
+
+	if (err != 2)
+		return -EINVAL;
+
+	*val = data[2];
+
+	return 0;
+}
+
+static int ar0833_write_bulk_reg(struct i2c_client *client, u8 *data, int len)
+{
+	int err;
+	struct i2c_msg msg;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = len;
+	msg.buf = data;
+
+	dev_dbg(&client->dev,
+		"%s {0x%04x,", __func__, (int)data[0] << 8 | data[1]);
+	for (err = 2; err < len; err++)
+		dev_dbg(&client->dev, " 0x%02x", data[err]);
+	dev_dbg(&client->dev, "},\n");
+
+	err = i2c_transfer(client->adapter, &msg, 1);
+	if (err == 1)
+		return 0;
+
+	dev_err(&client->dev, "ar0833: i2c bulk transfer failed at %x\n",
+		(int)data[0] << 8 | data[1]);
+
+	return err;
+}
+
+static int ar0833_write_reg8(struct i2c_client *client, u16 addr, u8 val)
+{
+	unsigned char data[3];
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	data[0] = (u8) (addr >> 8);
+	data[1] = (u8) (addr & 0xff);
+	data[2] = (u8) (val & 0xff);
+
+	dev_dbg(&client->dev, "0x%x = 0x%x\n", addr, val);
+	return ar0833_write_bulk_reg(client, data, sizeof(data));
+}
+
+static int ar0833_write_reg16(struct i2c_client *client, u16 addr, u16 val)
+{
+	unsigned char data[4];
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	data[0] = (u8) (addr >> 8);
+	data[1] = (u8) (addr & 0xff);
+	data[2] = (u8) (val >> 8);
+	data[3] = (u8) (val & 0xff);
+
+	dev_dbg(&client->dev, "0x%x = 0x%x\n", addr, val);
+	return ar0833_write_bulk_reg(client, data, sizeof(data));
+}
+
+/* flush and reset buffer */
+static int ar0833_flash_buffer(struct ar0833_info *info, int *len)
+{
+	int err;
+
+	if (!(*len))
+		return 0;
+
+	err = ar0833_write_bulk_reg(info->i2c_client,
+				info->i2c_trans_buf, *len);
+
+	*len = 0;
+	return err;
+}
+
+static int ar0833_write_blob(
+	struct ar0833_info *info, struct ar0833_reg_blob *pblob)
+{
+	u8 *pdata = pblob->data;
+	u16 addr = pblob->addr;
+	u16 size = pblob->size;
+	int err = 0;
+	u16 blk;
+
+	dev_dbg(&info->i2c_client->dev, "ar0833_write_blob ++\n");
+	while (size) {
+		blk = size > sizeof(info->i2c_trans_buf) - 2 ?
+			sizeof(info->i2c_trans_buf) - 2 : size;
+		info->i2c_trans_buf[0] = addr >> 8;
+		info->i2c_trans_buf[1] = (u8)addr;
+		memcpy(info->i2c_trans_buf + 2, pdata, blk);
+		err = ar0833_write_bulk_reg(info->i2c_client,
+			info->i2c_trans_buf, blk + 2);
+		if (err)
+			break;
+
+		size -= blk;
+		pdata += blk;
+		addr += blk;
+	}
+	dev_dbg(&info->i2c_client->dev, "ar0833_write_blob -- %d\n", err);
+	return err;
+}
+
+static int ar0833_write_table(
+	struct ar0833_info *info,
+	const struct ar0833_reg table[],
+	const struct ar0833_reg override_list[],
+	int num_override_regs)
+{
+	int err = 0;
+	const struct ar0833_reg *next, *n_next;
+	u8 *b_ptr = info->i2c_trans_buf;
+	unsigned int buf_filled = 0;
+	int i;
+	u16 val;
+
+	dev_dbg(&info->i2c_client->dev, "%s ++\n", __func__);
+	for (next = table; !err; next++) {
+		switch (next->addr) {
+		case AR0833_TABLE_END:
+			dev_dbg(&info->i2c_client->dev, "ar0833_table_end\n");
+			err = ar0833_flash_buffer(info, &buf_filled);
+			return err;
+		case AR0833_TABLE_NOP:
+			continue;
+		case AR0833_TABLE_WAIT_MS:
+			dev_dbg(&info->i2c_client->dev,
+				"ar0833_wait_ms %d\n", next->val);
+			err = ar0833_flash_buffer(info, &buf_filled);
+			if (err < 0)
+				return err;
+			ar0833_msleep(next->val);
+			continue;
+		case AR0833_TABLE_CALL:
+			err = ar0833_flash_buffer(info, &buf_filled);
+			if (next->val >= NUM_OF_SUBTBLS) {
+				dev_err(&info->i2c_client->dev,
+					"%s: invalid tbl index %d\n",
+					__func__, next->val);
+				return -EFAULT;
+			}
+			if (err < 0)
+				return err;
+
+			err = ar0833_write_table(
+				info, sub_tbls[next->val], NULL, 0);
+			if (err < 0)
+				return err;
+			continue;
+		case AR0833_TABLE_BLOB:
+			err = ar0833_flash_buffer(info, &buf_filled);
+			if (next->val >= NUM_OF_SUBTBLS) {
+				dev_err(&info->i2c_client->dev,
+					"%s: invalid tbl index %d\n",
+					__func__, next->val);
+				return -EFAULT;
+			}
+			if (err < 0)
+				return err;
+
+			err = ar0833_write_blob(info, sub_tbls[next->val]);
+			if (err < 0)
+				return err;
+			continue;
+		}
+
+		val = next->val;
+		/* When an override list is passed in, replace the reg */
+		/* value to write if the reg is in the list	*/
+		if (override_list)
+			for (i = 0; i < num_override_regs; i++)
+				if (next->addr == override_list[i].addr) {
+					val = override_list[i].val;
+					break;
+				}
+
+		if (!buf_filled) {
+			b_ptr = info->i2c_trans_buf;
+			*b_ptr++ = (next->addr & ~AR0833_TABLE_8BIT) >> 8;
+			*b_ptr++ = next->addr & 0xff;
+			buf_filled = 2;
+		}
+		if (!(next->addr & AR0833_TABLE_8BIT)) {
+			*b_ptr++ = (u8)(val >> 8);
+			buf_filled++;
+		}
+		*b_ptr++ = (u8)val;
+		buf_filled++;
+
+		n_next = next + 1;
+		if (buf_filled < (sizeof(info->i2c_trans_buf) & 0xFFFE) &&
+			n_next->addr == next->addr + 2)
+			continue;
+		err = ar0833_flash_buffer(info, &buf_filled);
+		if (err < 0)
+			return err;
+	}
+	dev_dbg(&info->i2c_client->dev, "%s --\n", __func__);
+	return 0;
+}
+
+static int ar0833_set_coarse_time(struct ar0833_info *info, u32 coarse_time,
+					bool group_hold)
+{
+	int ret;
+	struct ar0833_reg reg_list;
+
+	ar0833_get_coarse_time_regs(&reg_list, coarse_time);
+
+	if (group_hold) {
+		ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x1);
+		if (ret)
+			return ret;
+	}
+
+	ret = ar0833_write_reg16(info->i2c_client, reg_list.addr,
+		reg_list.val);
+	if (ret)
+		return ret;
+
+	if (group_hold) {
+		ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x0);
+		if (ret)
+			return ret;
+	}
+	return ret;
+}
+
+static int ar0833_set_hdr_coarse_time(struct ar0833_info *info,
+				 struct ar0833_hdr *values,
+				 bool group_hold)
+{
+	int ret;
+	struct ar0833_reg reg_list;
+	struct ar0833_reg reg_list_short;
+
+	ar0833_get_coarse_time_regs(&reg_list, values->coarse_time_long);
+	ar0833_get_coarse_time_short_regs(&reg_list_short,
+					values->coarse_time_short);
+
+	if (group_hold) {
+		ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x1);
+		if (ret)
+			return ret;
+	}
+
+	ret = ar0833_write_reg16(info->i2c_client, reg_list.addr,
+		reg_list.val);
+	if (ret)
+		return ret;
+
+	ret = ar0833_write_reg16(info->i2c_client, reg_list_short.addr,
+		reg_list_short.val);
+	if (ret)
+		return ret;
+
+	if (group_hold) {
+		ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x0);
+		if (ret)
+			return ret;
+	}
+	return ret;
+}
+
+static int ar0833_set_gain(struct ar0833_info *info, u16 gain,
+				bool group_hold)
+{
+	int ret;
+	struct ar0833_reg reg_list;
+
+	ar0833_get_gain_reg(&reg_list, gain);
+
+	if (group_hold) {
+		ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x1);
+		if (ret)
+			return ret;
+	}
+
+	ret = ar0833_write_reg16(info->i2c_client, reg_list.addr,
+		reg_list.val);
+	if (ret)
+		return ret;
+
+	if (group_hold) {
+		ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x0);
+		if (ret)
+			return ret;
+	}
+	return ret;
+}
+
+static int
+ar0833_set_group_hold(struct ar0833_info *info, struct ar0833_ae *ae)
+{
+	int ret;
+	int count = 0;
+	bool groupHoldEnabled = false;
+	struct ar0833_hdr values;
+
+	values.coarse_time_long = ae->coarse_time;
+	values.coarse_time_short = ae->coarse_time_short;
+
+	if (ae->gain_enable)
+		count++;
+	if (ae->coarse_time_enable)
+		count++;
+	if (count >= 1)
+		groupHoldEnabled = true;
+
+	if (groupHoldEnabled) {
+		ret = ar0833_write_reg16(info->i2c_client, 0x104, 0x1);
+		if (ret)
+			return ret;
+	}
+
+	if (ae->gain_enable)
+		ar0833_set_gain(info, ae->gain, false);
+	if (ae->coarse_time_enable)
+		ar0833_set_hdr_coarse_time(info, &values, false);
+
+	if (groupHoldEnabled) {
+		ret = ar0833_write_reg16(info->i2c_client, 0x104, 0x0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int ar0833_get_status(struct ar0833_info *info, u8 *status)
+{
+	int err;
+
+	err = ar0833_read_reg(info->i2c_client, 0x380e, status);
+	return err;
+}
+
+static int ar0833_open(struct inode *inode, struct file *file)
+{
+	struct miscdevice	*miscdev = file->private_data;
+	struct ar0833_info	*info;
+
+	info = container_of(miscdev, struct ar0833_info, miscdev_info);
+	/* check if the device is in use */
+	if (atomic_xchg(&info->in_use, 1)) {
+		dev_info(&info->i2c_client->dev, "%s:BUSY!\n", __func__);
+		return -EBUSY;
+	}
+
+	file->private_data = info;
+
+	if (info->pdata && info->pdata->power_on)
+		info->pdata->power_on(&info->power);
+	else {
+		dev_err(&info->i2c_client->dev,
+			"%s:no valid power_on function.\n", __func__);
+		return -EEXIST;
+	}
+	return 0;
+}
+
+int ar0833_release(struct inode *inode, struct file *file)
+{
+	struct ar0833_info *info = file->private_data;
+
+	if (info->pdata && info->pdata->power_off)
+		info->pdata->power_off(&info->power);
+	file->private_data = NULL;
+
+	/* warn if device is already released */
+	WARN_ON(!atomic_xchg(&info->in_use, 0));
+	return 0;
+}
+
+static int ar0833_regulator_get(struct ar0833_info *info,
+	struct regulator **vreg, char vreg_name[])
+{
+	struct regulator *reg = NULL;
+	int err = 0;
+
+	reg = regulator_get(&info->i2c_client->dev, vreg_name);
+	if (unlikely(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;
+	return err;
+}
+
+static int ar0833_power_get(struct ar0833_info *info)
+{
+	struct ar0833_power_rail *pw = &info->power;
+
+	ar0833_regulator_get(info, &pw->avdd, "vana"); /* ananlog 2.7v */
+	ar0833_regulator_get(info, &pw->dvdd, "vdig"); /* digital 1.2v */
+	ar0833_regulator_get(info, &pw->iovdd, "vif"); /* interface 1.8v */
+
+	return 0;
+}
+
+static const struct file_operations ar0833_fileops = {
+	.owner = THIS_MODULE,
+	.open = ar0833_open,
+	.unlocked_ioctl = ar0833_ioctl,
+	.release = ar0833_release,
+};
+
+static struct miscdevice ar0833_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "ar0833",
+	.fops = &ar0833_fileops,
+};
+
+#ifdef CONFIG_DEBUG_FS
+int control_DC_BLC(struct ar0833_info *info)
+{
+	u8 reg0x3d0a;
+	u8 reg0x3d0b;
+	u8 reg0x4006;
+
+	if (info->enableDCBLC) {
+		ar0833_write_reg8(info->i2c_client, 0x3d84, 0xdf);
+		ar0833_write_reg8(info->i2c_client, 0x3d81, 0x01);
+		ar0833_msleep(10);
+
+		ar0833_read_reg(info->i2c_client, 0x3d0a, &reg0x3d0a);
+		ar0833_read_reg(info->i2c_client, 0x3d0b, &reg0x3d0b);
+		ar0833_write_reg8(info->i2c_client, 0x3d81, 0x00);
+
+		if ((reg0x3d0b > 0x10 && reg0x3d0b < 0x20))
+			reg0x4006 = reg0x3d0b;
+		else if ((reg0x3d0a > 0x10) && (reg0x3d0a < 0x20))
+			reg0x4006 = reg0x3d0a;
+		else
+			reg0x4006 = 0x20;
+
+		ar0833_write_reg8(info->i2c_client, 0x4006, reg0x4006);
+		dev_info(&info->i2c_client->dev,
+				"ar0833: %s: wrote the DC BLC commands\n",
+				__func__);
+	} else {
+		dev_info(&info->i2c_client->dev,
+				"ar0833: %s: DID NOT do the DC BLC commands\n",
+				__func__);
+	}
+
+	return 0;
+}
+
+static int ar0833_stats_show(struct seq_file *s, void *data)
+{
+	static struct ar0833_info *info;
+
+	seq_printf(s, "%-20s : %-20s\n", "Name", "ar0833-debugfs-testing");
+	seq_printf(s, "%-20s : 0x%X\n", "Current i2c-offset Addr",
+			info->debug_i2c_offset);
+	seq_printf(s, "%-20s : 0x%X\n", "DC BLC Enabled",
+			info->debug_i2c_offset);
+	return 0;
+}
+
+static int ar0833_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ar0833_stats_show, inode->i_private);
+}
+
+static const struct file_operations ar0833_stats_fops = {
+	.open       = ar0833_stats_open,
+	.read       = seq_read,
+	.llseek     = seq_lseek,
+	.release    = single_release,
+};
+
+static int debug_i2c_offset_w(void *data, u64 val)
+{
+	struct ar0833_info *info = (struct ar0833_info *)(data);
+	dev_info(&info->i2c_client->dev,
+			"ar0833:%s setting i2c offset to 0x%X\n",
+			__func__, (u32)val);
+	info->debug_i2c_offset = (u32)val;
+	dev_info(&info->i2c_client->dev,
+			"ar0833:%s new i2c offset is 0x%X\n", __func__,
+			info->debug_i2c_offset);
+	return 0;
+}
+
+static int debug_i2c_offset_r(void *data, u64 *val)
+{
+	struct ar0833_info *info = (struct ar0833_info *)(data);
+	*val = (u64)info->debug_i2c_offset;
+	dev_info(&info->i2c_client->dev,
+			"ar0833:%s reading i2c offset is 0x%X\n", __func__,
+			info->debug_i2c_offset);
+	return 0;
+}
+
+static int debug_i2c_read(void *data, u64 *val)
+{
+	struct ar0833_info *info = (struct ar0833_info *)(data);
+	u8 temp1 = 0;
+	u8 temp2 = 0;
+	dev_info(&info->i2c_client->dev,
+			"ar0833:%s reading offset 0x%X\n", __func__,
+			info->debug_i2c_offset);
+	if (ar0833_read_reg(info->i2c_client,
+				info->debug_i2c_offset, &temp1)
+		|| ar0833_read_reg(info->i2c_client,
+			info->debug_i2c_offset+1, &temp2)) {
+		dev_err(&info->i2c_client->dev,
+				"ar0833:%s failed\n", __func__);
+		return -EIO;
+	}
+	dev_info(&info->i2c_client->dev,
+			"ar0833:%s read value is 0x%X\n", __func__,
+			temp1<<8 | temp2);
+	*val = (u64)(temp1<<8 | temp2);
+	return 0;
+}
+
+static int debug_i2c_write(void *data, u64 val)
+{
+	struct ar0833_info *info = (struct ar0833_info *)(data);
+	dev_info(&info->i2c_client->dev,
+			"ar0833:%s writing 0x%X to offset 0x%X\n", __func__,
+			(u16)val, info->debug_i2c_offset);
+	if (ar0833_write_reg16(info->i2c_client,
+				info->debug_i2c_offset, (u16)val)) {
+		dev_err(&info->i2c_client->dev, "ar0833:%s failed\n", __func__);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int debug_dcblc_r(void *data, u64 *val)
+{
+	struct ar0833_info *info = (struct ar0833_info *)(data);
+	*val = (u64)info->enableDCBLC;
+	dev_info(&info->i2c_client->dev,
+			"ar0833:%s read DC BLC [%d]\n", __func__,
+			info->enableDCBLC);
+
+	return 0;
+}
+
+static int debug_dcblc_w(void *data, u64 val)
+{
+	struct ar0833_info *info = (struct ar0833_info *)(data);
+	if (val != 0) {
+		info->enableDCBLC = 1;
+		dev_info(&info->i2c_client->dev,
+				"ar0833:%s enabled DC BLC\n", __func__);
+	} else {
+		info->enableDCBLC = 0;
+		dev_info(&info->i2c_client->dev,
+				"ar0833:%s disabled DC BLC\n", __func__);
+	}
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_dcblc_fops, debug_dcblc_r,
+		debug_dcblc_w, "0x%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(i2c_offset_fops, debug_i2c_offset_r,
+		debug_i2c_offset_w, "0x%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(i2c_read_fops, debug_i2c_read,
+		/*debug_i2c_dummy_w*/ NULL, "0x%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(i2c_write_fops, /*debug_i2c_dummy_r*/NULL,
+		debug_i2c_write, "0x%llx\n");
+
+static int ar0833_debug_init(struct ar0833_info *info)
+{
+	dev_dbg(&info->i2c_client->dev, "%s", __func__);
+
+	info->debugfs_root = debugfs_create_dir(ar0833_device.name, NULL);
+
+	if (!info->debugfs_root)
+		goto err_out;
+
+	if (!debugfs_create_file("stats", S_IRUGO,
+			info->debugfs_root, info, &ar0833_stats_fops))
+		goto err_out;
+
+	if (!debugfs_create_file("i2c_offset", S_IRUGO | S_IWUSR,
+			info->debugfs_root, info, &i2c_offset_fops))
+		goto err_out;
+
+	if (!debugfs_create_file("i2c_read", S_IRUGO,
+			info->debugfs_root, info, &i2c_read_fops))
+		goto err_out;
+
+	if (!debugfs_create_file("i2c_write", S_IWUSR,
+			info->debugfs_root, info, &i2c_write_fops))
+		goto err_out;
+
+	if (!debugfs_create_file("DCBLC", S_IRUGO | S_IWUSR,
+			info->debugfs_root, info, &debug_dcblc_fops))
+		goto err_out;
+
+	return 0;
+
+err_out:
+	dev_err(&info->i2c_client->dev, "ERROR:%s failed", __func__);
+	if (info->debugfs_root)
+		debugfs_remove_recursive(info->debugfs_root);
+	return -ENOMEM;
+}
+#endif
+
+static struct ar0833_modeinfo def_modeinfo = {
+	.xres = 3264,
+	.yres = 2448,
+	.hdr = 0,
+	.lanes = 4,
+	.line_len = 0x0f68,
+	.frame_len = 0x0a01,
+	.coarse_time = 2400,
+	.coarse_time_2nd = 300,
+	.xstart = 8,
+	.xend = 0x0cc7,
+	.ystart = 8,
+	.yend = 0x0997,
+	.xsize = 0x0cc0,
+	.ysize = 0x0990,
+	.gain = 0x1000,
+	.x_flip = 1,
+	.y_flip = 0,
+	.x_bin = 1,
+	.y_bin = 1,
+	.vt_pix_clk_div = 5,
+	.vt_sys_clk_div = 1,
+	.pre_pll_clk_div = 2,
+	.pll_multi = 0x40,
+	.op_pix_clk_div = 0x0a,
+	.op_sys_clk_div = 1,
+};
+
+static struct ar0833_mode_desc *ar0833_get_mode(
+	struct ar0833_info *info, struct ar0833_mode *mode)
+{
+	struct ar0833_mode_desc *mt = mode_table;
+
+	while (mt->xres) {
+		if ((mt->xres == mode->xres) &&
+			(mt->yres == mode->yres) &&
+			(mt->hdr_en == mode->hdr_en))
+				break;
+		mt++;
+	}
+
+	if (!mt->xres)
+		mt = NULL;
+	return mt;
+}
+
+static int ar0833_mode_info_init(struct ar0833_info *info)
+{
+	struct ar0833_mode_desc *md = mode_table;
+	const struct ar0833_reg *mt;
+	struct ar0833_modeinfo *mi;
+
+	dev_dbg(&info->i2c_client->dev, "%s", __func__);
+	while (md->xres) {
+		mi = &md->mode_info;
+		mt = md->mode_tbl;
+		memcpy(mi, &def_modeinfo, sizeof(*mi));
+		dev_dbg(&info->i2c_client->dev, "mode %d x %d %s",
+			md->xres, md->yres, md->hdr_en ? "HDR" : "REG");
+		mi->xres = md->xres;
+		mi->yres = md->yres;
+		mi->hdr = md->hdr_en;
+		while (mt->addr != AR0833_TABLE_END) {
+			switch (mt->addr) {
+			case 0x0300:
+				mi->vt_pix_clk_div = mt->val;
+				break;
+			case 0x0302:
+				mi->vt_sys_clk_div = mt->val;
+				break;
+			case 0x0304:
+				mi->pre_pll_clk_div = mt->val;
+				break;
+			case 0x0306:
+				mi->pll_multi = mt->val;
+				break;
+			case 0x0308:
+				mi->op_pix_clk_div = mt->val;
+				break;
+			case 0x030a:
+				mi->op_sys_clk_div = mt->val;
+				break;
+			case 0x0202:
+				mi->coarse_time = mt->val;
+				break;
+			case 0x3088:
+				mi->coarse_time_2nd = mt->val;
+				break;
+			case 0x0340:
+				mi->frame_len = mt->val;
+				break;
+			case 0x0342:
+				mi->line_len = mt->val;
+				break;
+			case 0x0344:
+				mi->xstart = mt->val;
+				break;
+			case 0x0346:
+				mi->ystart = mt->val;
+				break;
+			case 0x0348:
+				mi->xend = mt->val;
+				break;
+			case 0x034a:
+				mi->yend = mt->val;
+				break;
+			case 0x034c:
+				mi->xsize = mt->val;
+				break;
+			case 0x034e:
+				mi->ysize = mt->val;
+				break;
+			case 0x305e:
+				mi->gain = mt->val;
+				break;
+			case 0x31ae:
+				mi->lanes = mt->val & 0x7;
+				break;
+			case 0x3040:
+				if (mt->val & 0x8000)
+					mi->y_flip = 1;
+				if (mt->val & 0x4000)
+					mi->x_flip = 1;
+				switch (mt->val & 0x1c0) {
+				case 1:
+					mi->x_bin = 1;
+					break;
+				case 3:
+					mi->x_bin = 2;
+					break;
+				case 7:
+					mi->x_bin = 4;
+					break;
+				default:
+					dev_warn(&info->i2c_client->dev,
+						"%s :Unrecognized x_odd_inc"
+						"setting in mode %d x %d %s,"
+						" 0x3040 = 0x%x\n",
+						__func__, md->xres, md->yres,
+						md->hdr_en ? "HDR" : "REG",
+						mt->val);
+					break;
+				}
+
+				switch (mt->val & 0x3f) {
+				case 1:
+					mi->y_bin = 1;
+					break;
+				case 3:
+					mi->y_bin = 2;
+					break;
+				case 7:
+					mi->y_bin = 4;
+					break;
+				case 15:
+					mi->y_bin = 8;
+					break;
+				case 31:
+					mi->y_bin = 16;
+					break;
+				case 63:
+					mi->y_bin = 32;
+					break;
+				default:
+					dev_warn(&info->i2c_client->dev,
+						"%s :Unrecognized y_odd_inc"
+						"setting in mode %d x %d %s,"
+						" 0x3040 = 0x%x\n",
+						__func__, md->xres, md->yres,
+						md->hdr_en ? "HDR" : "REG",
+						mt->val);
+					break;
+				}
+				break;
+			};
+			mt++;
+		};
+		md++;
+	}
+	return 0;
+}
+
+static struct ar0833_modeinfo *ar0833_get_mode_info(
+	struct ar0833_info *info, struct ar0833_modeinfo *mi)
+{
+	struct ar0833_mode mode;
+	struct ar0833_mode_desc *mode_desc;
+
+	mode.xres = mi->xres;
+	mode.yres = mi->yres;
+	mode.hdr_en = mi->hdr;
+	mode_desc = ar0833_get_mode(info, &mode);
+	if (mode_desc == NULL) {
+		dev_err(&info->i2c_client->dev,
+			"%s: invalid params to get mode info %d %d %d\n",
+			__func__, mi->xres, mi->yres, mi->hdr);
+		return NULL;
+	}
+
+	return &mode_desc->mode_info;
+}
+
+static int ar0833_set_mode(struct ar0833_info *info, struct ar0833_mode *mode)
+{
+	struct ar0833_mode_desc *sensor_mode;
+	struct ar0833_reg reg_list[4];
+	int err;
+
+	dev_info(&info->i2c_client->dev,
+		"%s: xres %u yres %u hdr %d\n",
+		__func__, mode->xres, mode->yres, mode->hdr_en);
+	dev_info(&info->i2c_client->dev,
+		"framelength %u coarsetime %u gain %x\n",
+		mode->frame_length, mode->coarse_time, mode->gain);
+
+	sensor_mode = ar0833_get_mode(info, mode);
+	if (sensor_mode == NULL) {
+		dev_err(&info->i2c_client->dev,
+				"%s: invalid params supplied to set mode %d %d %d\n",
+				__func__, mode->xres, mode->yres, mode->hdr_en);
+		return -EINVAL;
+	}
+
+	if (mode->hdr_en == 1)  /* if HDR is enabled */
+		dev_info(&info->i2c_client->dev, "ar0833 HDR enabled\n");
+	else
+		dev_info(&info->i2c_client->dev, "ar0833 HDR disabled\n");
+
+	memset(reg_list, 0, sizeof(reg_list));
+	/* get a list of override regs for the asking frame length, */
+	/* coarse integration time, and gain.	*/
+	ar0833_get_coarse_time_regs(reg_list, mode->coarse_time);
+	ar0833_get_gain_reg(reg_list + 1, mode->gain);
+	if (mode->hdr_en == 1)  /* if HDR is enabled */
+		ar0833_get_coarse_time_short_regs(
+			reg_list + 2, mode->coarse_time_short);
+
+	err = ar0833_write_table(
+		info, sensor_mode->mode_tbl, reg_list, mode->hdr_en ? 3 : 2);
+	if (err)
+		return err;
+
+	info->mode = sensor_mode->mode_tbl;
+
+#ifdef CONFIG_DEBUG_FS
+	control_DC_BLC(info);
+#endif
+
+	return 0;
+}
+
+static long ar0833_ioctl(struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	int err = 0;
+	struct ar0833_info *info = file->private_data;
+
+	switch (cmd) {
+	case AR0833_IOCTL_SET_MODE:
+	{
+		struct ar0833_mode mode;
+
+		dev_dbg(&info->i2c_client->dev, "AR0833_IOCTL_SET_MODE\n");
+		if (copy_from_user(&mode, (const void __user *)arg,
+			sizeof(struct ar0833_mode))) {
+			err = -EFAULT;
+			break;
+		}
+		err = ar0833_set_mode(info, &mode);
+		break;
+	}
+	case AR0833_IOCTL_SET_FRAME_LENGTH:
+		dev_dbg(&info->i2c_client->dev,
+			"AR0833_IOCTL_SET_FRAME_LENGTH %x\n", (u32)arg);
+		/* obsolete. we should not update frame length,
+		   it is done by sensor automatically */
+		break;
+	case AR0833_IOCTL_SET_COARSE_TIME:
+		dev_dbg(&info->i2c_client->dev,
+			"AR0833_IOCTL_SET_COARSE_TIME %x\n", (u32)arg);
+		err = ar0833_set_coarse_time(info, (u32)arg, true);
+		break;
+	case AR0833_IOCTL_SET_HDR_COARSE_TIME:
+	{
+		struct ar0833_hdr values;
+
+		dev_dbg(&info->i2c_client->dev,
+			"AR0833_IOCTL_SET_HDR_COARSE_TIME\n");
+		if (copy_from_user(&values,
+					 (const void __user *)arg,
+					 sizeof(struct ar0833_hdr))) {
+			err = -EFAULT;
+			break;
+		}
+		err = ar0833_set_hdr_coarse_time(info, &values, true);
+		break;
+	}
+	case AR0833_IOCTL_SET_GAIN:
+		dev_dbg(&info->i2c_client->dev,
+			"AR0833_IOCTL_SET_GAIN %x\n", (u32)arg);
+		err = ar0833_set_gain(info, (u16)arg, true);
+		break;
+	case AR0833_IOCTL_SET_GROUP_HOLD:
+	{
+		struct ar0833_ae ae;
+		if (copy_from_user(&ae, (const void __user *)arg,
+				sizeof(struct ar0833_ae))) {
+			dev_err(&info->i2c_client->dev,
+				"%s:fail group hold\n", __func__);
+			return -EFAULT;
+		}
+		return ar0833_set_group_hold(info, &ae);
+	}
+	case AR0833_IOCTL_GET_STATUS:
+	{
+		u8 status;
+
+		dev_dbg(&info->i2c_client->dev, "AR0833_IOCTL_GET_STATUS\n");
+		err = ar0833_get_status(info, &status);
+		if (err)
+			break;
+		if (copy_to_user((void __user *)arg, &status, 2)) {
+			err = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AR0833_IOCTL_GET_MODE:
+	{
+		struct ar0833_modeinfo mode_info, *mi;
+
+		dev_dbg(&info->i2c_client->dev, "AR0833_IOCTL_GET_MODE\n");
+		if (copy_from_user(&mode_info,
+					 (const void __user *)arg,
+					 sizeof(struct ar0833_mode))) {
+			err = -EFAULT;
+			break;
+		}
+		mi = ar0833_get_mode_info(info, &mode_info);
+		if (mi == NULL)
+			err = -EFAULT;
+		else {
+			if (copy_to_user((void __user *)arg, mi, sizeof(*mi))) {
+				err = -EFAULT;
+				break;
+			}
+			dev_dbg(&info->i2c_client->dev, "mode %d x %d %s:\n",
+				mi->xres, mi->yres, mi->hdr ? "HDR" : "REG");
+			dev_dbg(&info->i2c_client->dev,
+				"line_len = %d\n", mi->line_len);
+			dev_dbg(&info->i2c_client->dev,
+				"frame_len = %d\n", mi->frame_len);
+			dev_dbg(&info->i2c_client->dev,
+				"xsize = %d\n", mi->xsize);
+			dev_dbg(&info->i2c_client->dev,
+				"ysize = %d\n", mi->ysize);
+			dev_dbg(&info->i2c_client->dev,
+				"vt_pix_clk_div = %d\n", mi->vt_pix_clk_div);
+			dev_dbg(&info->i2c_client->dev,
+				"vt_sys_clk_div = %d\n", mi->vt_sys_clk_div);
+			dev_dbg(&info->i2c_client->dev,
+				"pre_pll_clk_div = %d\n", mi->pre_pll_clk_div);
+			dev_dbg(&info->i2c_client->dev,
+				"pll_multi = %d\n", mi->pll_multi);
+			dev_dbg(&info->i2c_client->dev,
+				"op_pix_clk_div = %d\n", mi->op_pix_clk_div);
+			dev_dbg(&info->i2c_client->dev,
+				"op_sys_clk_div = %d\n", mi->op_sys_clk_div);
+		}
+		break;
+	}
+	default:
+		dev_dbg(&info->i2c_client->dev, "INVALID IOCTL\n");
+		err = -EINVAL;
+	}
+
+	if (err)
+		dev_dbg(&info->i2c_client->dev,
+			"%s - %x: ERR = %d\n", __func__, cmd, err);
+	return err;
+}
+
+static int ar0833_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int err;
+	struct ar0833_info *info;
+	dev_info(&client->dev, "ar0833: probing sensor.\n");
+
+	info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		dev_err(&client->dev, "%s: kzalloc error\n", __func__);
+		return -ENOMEM;
+	}
+
+	info->pdata = client->dev.platform_data;
+	info->i2c_client = client;
+	atomic_set(&info->in_use, 0);
+	info->mode = NULL;
+
+	i2c_set_clientdata(client, info);
+
+	ar0833_power_get(info);
+	ar0833_mode_info_init(info);
+
+	memcpy(&info->miscdev_info,
+		&ar0833_device,
+		sizeof(struct miscdevice));
+
+	err = misc_register(&info->miscdev_info);
+	if (err) {
+		dev_err(&info->i2c_client->dev,
+				"ar0833: Unable to register misc device!\n");
+		kfree(info);
+		return err;
+	}
+#ifdef CONFIG_DEBUG_FS
+	ar0833_debug_init(info);
+	info->enableDCBLC = 0;
+#endif
+
+	return 0;
+}
+
+static int ar0833_remove(struct i2c_client *client)
+{
+	struct ar0833_info *info;
+	info = i2c_get_clientdata(client);
+	misc_deregister(&info->miscdev_info);
+	kfree(info);
+
+#ifdef CONFIG_DEBUG_FS
+	if (info->debugfs_root)
+		debugfs_remove_recursive(info->debugfs_root);
+#endif
+
+	return 0;
+}
+
+static const struct i2c_device_id ar0833_id[] = {
+	{ "ar0833", 0 },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(i2c, ar0833_id);
+
+static struct i2c_driver ar0833_i2c_driver = {
+	.driver = {
+		.name = "ar0833",
+		.owner = THIS_MODULE,
+	},
+	.probe = ar0833_probe,
+	.remove = ar0833_remove,
+	.id_table = ar0833_id,
+};
+
+static int __init ar0833_init(void)
+{
+	pr_info("ar0833 sensor driver loading\n");
+	return i2c_add_driver(&ar0833_i2c_driver);
+}
+
+static void __exit ar0833_exit(void)
+{
+	i2c_del_driver(&ar0833_i2c_driver);
+}
+
+module_init(ar0833_init);
+module_exit(ar0833_exit);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/tegra/ar0833_mode_tbls.c b/drivers/media/video/tegra/ar0833_mode_tbls.c
new file mode 100644
index 0000000..39a3db3
--- /dev/null
+++ b/drivers/media/video/tegra/ar0833_mode_tbls.c
@@ -0,0 +1,565 @@
+/*
+ * ar0833_mode_tbls.c - ar0833 sensor mode table
+ *
+ * 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/>.
+ */
+
+static struct ar0833_reg Reset_tbl[] = {
+	{0x301A, 0x0019},
+	{AR0833_TABLE_WAIT_MS, 1},
+	/* Disable Streaming */
+	{0x301A, 0x0218},
+	{AR0833_TABLE_END, 0x0000},
+};
+
+/*All image captures should be taken with these settings */
+static struct ar0833_reg Default_3P_tbl[] = {
+	{0x3042, 0x0000},
+	{0x30C0, 0x1810},
+	{0x30C8, 0x0018},
+	{0x30D2, 0x0000},
+	{0x30D4, 0xD030},
+	{0x30D6, 0x2200},
+	{0x30DA, 0x0080},
+	{0x30DC, 0x0080},
+	{0x30EE, 0x0340},
+	{0x316A, 0x8800},
+	{0x316C, 0x8200},
+	{0x3172, 0x0286},
+	{0x3174, 0x8000},
+	{0x317C, 0xE103},
+	{0x3180, 0xF0FF},
+	{0x31E0, 0x0741},
+	{0x3ECC, 0x0056},
+	{0x3ED0, 0xA8AA},
+	{0x3ED2, 0xAAA8},
+	{0x3ED4, 0x8ACC},
+	{0x3ED8, 0x7288},
+	{0x3EDA, 0x77CA},
+	{0x3EDE, 0x6664},
+	{0x3EE0, 0x26D5},
+	{0x3EE4, 0x1548},
+	{0x3EE6, 0xB10C},
+	{0x3EE8, 0x6E79},
+	{0x3EFE, 0x77CC},
+	{0x31E6, 0x0000},
+	{0x3F00, 0x0028},
+	{0x3F02, 0x0140},
+	{0x3F04, 0x0002},
+	{0x3F06, 0x0004},
+	{0x3F08, 0x0008},
+	{0x3F0A, 0x0B09},
+	{0x3F0C, 0x0302},
+	{0x3F10, 0x0505},
+	{0x3F12, 0x0303},
+	{0x3F14, 0x0101},
+	{0x3F16, 0x2020},
+	{0x3F18, 0x0404},
+	{0x3F1A, 0x7070},
+	{0x3F1C, 0x003A},
+	{0x3F1E, 0x003C},
+	{0x3F2C, 0x2210},
+	{0x3F40, 0x2020},
+	{0x3F42, 0x0808},
+	{0x3F44, 0x0101},
+	{AR0833_TABLE_END, 0x0000},
+};
+
+u8 Sequencer_Adjustment_v7p2_data[] = {
+	0x04, 0x70, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0x40, 0x14,
+	0x0E, 0x23, 0x82, 0x41, 0x5C, 0x54, 0x6E, 0x42, 0x00, 0xC0, 0x5D,
+	0x80, 0x5A, 0x80, 0x57, 0x84, 0x64, 0x80, 0x55, 0x86, 0x64, 0x80,
+	0x65, 0x88, 0x65, 0x84, 0x58, 0x80, 0x00, 0xC0, 0x80, 0x30, 0x0C,
+	0x84, 0x42, 0x82, 0x10, 0x30, 0xA6, 0x5B, 0x80, 0x63, 0x8B, 0x30,
+	0x0C, 0xA5, 0x59, 0x84, 0x6C, 0x80, 0x6D, 0x81, 0x5F, 0x60, 0x61,
+	0x10, 0x30, 0x88, 0x66, 0x83, 0x6E, 0x80, 0x64, 0x87, 0x64, 0x30,
+	0x50, 0xDA, 0x6A, 0x83, 0x6B, 0xA6, 0x30, 0x94, 0x67, 0x84, 0x65,
+	0x82, 0x4D, 0x83, 0x65, 0x30, 0x50, 0xA6, 0x58, 0x43, 0x06, 0x00,
+	0x8D, 0x45, 0xA0, 0x45, 0x6A, 0x83, 0x6B, 0x06, 0x00, 0x81, 0x43,
+	0x9C, 0x58, 0x84, 0x30, 0x90, 0x67, 0x64, 0x88, 0x64, 0x80, 0x65,
+	0x88, 0x65, 0x82, 0x10, 0xC0, 0xEB, 0x10, 0xC0, 0x66, 0x85, 0x64,
+	0x81, 0x17, 0x00, 0x80, 0x20, 0x0D, 0x80, 0x18, 0x0C, 0x80, 0x64,
+	0x30, 0x60, 0x41, 0x82, 0x42, 0xB2, 0x42, 0x80, 0x40, 0x81, 0x40,
+	0x80, 0x41, 0x80, 0x42, 0x80, 0x43, 0x83, 0x06, 0xC0, 0x88, 0x44,
+	0x87, 0x6A, 0x83, 0x6B, 0x92, 0x44, 0x88, 0x06, 0xC8, 0x81, 0x41,
+	0x85, 0x30, 0xA4, 0x67, 0x85, 0x65, 0x87, 0x65, 0x30, 0x60, 0x8D,
+	0x42, 0x82, 0x40, 0x82, 0x40, 0x80, 0x41, 0x80, 0x42, 0x80, 0x43,
+	0x83, 0x06, 0xC0, 0x88, 0x44, 0x9C, 0x44, 0x88, 0x06, 0xC8, 0x85,
+	0x41, 0x6A, 0x83, 0x6B, 0xA0, 0x42, 0x82, 0x40, 0x6C, 0x3A, 0xA8,
+	0x80, 0x28, 0x30, 0x70, 0x6F, 0x40, 0x14, 0x0E, 0x23, 0xC2, 0x41,
+	0x82, 0x42, 0x00, 0xC0, 0x5D, 0x80, 0x5A, 0x80, 0x57, 0x84, 0x64,
+	0x80, 0x55, 0x86, 0x64, 0x80, 0x65, 0x88, 0x65, 0x82, 0x54, 0x80,
+	0x58, 0x80, 0x00, 0xC0, 0x86, 0x42, 0x82, 0x10, 0x30, 0x9C, 0x5C,
+	0x80, 0x6E, 0x86, 0x5B, 0x80, 0x63, 0x9E, 0x59, 0x8C, 0x5E, 0x8A,
+	0x6C, 0x80, 0x6D, 0x81, 0x5F, 0x60, 0x61, 0x88, 0x10, 0x30, 0x66,
+	0x83, 0x6E, 0x80, 0x64, 0x87, 0x64, 0x30, 0x50, 0xD3, 0x6A, 0x6B,
+	0xAD, 0x30, 0x94, 0x67, 0x84, 0x65, 0x82, 0x4D, 0x83, 0x65, 0x30,
+	0x50, 0xA7, 0x43, 0x06, 0x00, 0x8D, 0x45, 0x9A, 0x6A, 0x6B, 0x45,
+	0x85, 0x06, 0x00, 0x81, 0x43, 0x8A, 0x6F, 0x96, 0x30, 0x90, 0x67,
+	0x64, 0x88, 0x64, 0x80, 0x65, 0x82, 0x10, 0xC0, 0x84, 0x65, 0xEF,
+	0x10, 0xC0, 0x66, 0x85, 0x64, 0x81, 0x17, 0x00, 0x80, 0x20, 0x0D,
+	0x80, 0x18, 0x0C, 0x80, 0x64, 0x30, 0x60, 0x41, 0x82, 0x42, 0xB2,
+	0x42, 0x80, 0x40, 0x82, 0x40, 0x4C, 0x45, 0x92, 0x6A, 0x6B, 0x9B,
+	0x45, 0x81, 0x4C, 0x40, 0x8C, 0x30, 0xA4, 0x67, 0x85, 0x65, 0x87,
+	0x65, 0x30, 0x60, 0xD3, 0x6A, 0x6B, 0xAC, 0x6C, 0x32, 0xA8, 0x80,
+	0x28, 0x30, 0x70, 0x00, 0x80, 0x40, 0x4C, 0xBD, 0x00, 0x0E, 0xBE,
+	0x44, 0x88, 0x44, 0xBC, 0x78, 0x09, 0x00, 0x89, 0x04, 0x80, 0x80,
+	0x02, 0x40, 0x86, 0x09, 0x00, 0x8E, 0x09, 0x00, 0x80, 0x02, 0x40,
+	0x80, 0x04, 0x80, 0x88, 0x7D, 0x9E, 0x86, 0x09, 0x00, 0x87, 0x7A,
+	0x00, 0x0E, 0xC3, 0x79, 0x4C, 0x40, 0xBF, 0x70, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+u8 Sequencer_iHDR_v12p12_data[] = {
+	0x04, 0x87, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0x40, 0x14,
+	0x0E, 0x23, 0x82, 0x41, 0x5C, 0x54, 0x6E, 0x42, 0x00, 0xC0, 0x5D,
+	0x80, 0x5A, 0x80, 0x57, 0x84, 0x64, 0x80, 0x55, 0x84, 0x00, 0xC4,
+	0x10, 0x30, 0x64, 0x80, 0x65, 0x88, 0x65, 0x88, 0x30, 0x0C, 0xB0,
+	0x5B, 0x80, 0x63, 0x8B, 0x30, 0x0C, 0xA2, 0x58, 0x87, 0x6C, 0x80,
+	0x6D, 0x81, 0x5F, 0x60, 0x61, 0xA3, 0x59, 0x8C, 0x10, 0x30, 0x88,
+	0x66, 0x83, 0x6E, 0x80, 0x64, 0x87, 0x64, 0x30, 0x50, 0xDA, 0x6A,
+	0x83, 0x6B, 0xA6, 0x30, 0x94, 0x67, 0x84, 0x65, 0x82, 0x4D, 0x83,
+	0x65, 0x30, 0x50, 0xA6, 0x58, 0x43, 0x06, 0x00, 0x8D, 0x45, 0xA0,
+	0x45, 0x6A, 0x83, 0x6B, 0x06, 0x00, 0x81, 0x43, 0x9C, 0x58, 0x84,
+	0x30, 0x90, 0x67, 0x64, 0x88, 0x64, 0x80, 0x65, 0x88, 0x65, 0x82,
+	0x10, 0xC0, 0xC3, 0x10, 0xC0, 0x66, 0x85, 0x64, 0x81, 0x17, 0x00,
+	0x80, 0x20, 0x0D, 0x80, 0x18, 0x0C, 0x80, 0x64, 0x30, 0x60, 0x41,
+	0x82, 0x42, 0xB2, 0x42, 0x80, 0x40, 0x81, 0x40, 0x80, 0x41, 0x80,
+	0x42, 0x80, 0x43, 0x83, 0x06, 0xC0, 0x88, 0x44, 0x87, 0x6A, 0x83,
+	0x6B, 0x92, 0x44, 0x88, 0x06, 0xC8, 0x81, 0x41, 0x85, 0x30, 0xA4,
+	0x67, 0x85, 0x65, 0x87, 0x65, 0x30, 0x60, 0x8D, 0x42, 0x82, 0x40,
+	0x82, 0x40, 0x80, 0x41, 0x80, 0x42, 0x80, 0x43, 0x83, 0x06, 0xC0,
+	0x88, 0x44, 0x9C, 0x44, 0x88, 0x06, 0xC8, 0x85, 0x41, 0x6A, 0x83,
+	0x6B, 0xA0, 0x42, 0x82, 0x40, 0x6C, 0x3A, 0xA8, 0x80, 0x28, 0x30,
+	0x40, 0x80, 0x41, 0x80, 0x42, 0x80, 0x43, 0x88, 0x06, 0xC0, 0x83,
+	0x44, 0xA0, 0x44, 0x88, 0x06, 0xC8, 0x81, 0x41, 0xA6, 0x42, 0x82,
+	0x40, 0x82, 0x40, 0x80, 0x41, 0x80, 0x42, 0x80, 0x43, 0x83, 0x06,
+	0xC0, 0x88, 0x44, 0xA0, 0x44, 0x88, 0x06, 0xC8, 0x81, 0x41, 0xA6,
+	0x42, 0x82, 0x40, 0x80, 0x70, 0x00, 0x6F, 0x40, 0x14, 0x0E, 0x23,
+	0xC2, 0x41, 0x82, 0x42, 0x00, 0xC0, 0x5D, 0x80, 0x5A, 0x80, 0x57,
+	0x84, 0x64, 0x80, 0x55, 0x86, 0x64, 0x80, 0x65, 0x88, 0x65, 0x82,
+	0x54, 0x80, 0x58, 0x80, 0x00, 0xC0, 0x86, 0x42, 0x82, 0x10, 0x30,
+	0x9C, 0x5C, 0x80, 0x6E, 0x86, 0x5B, 0x80, 0x63, 0x9E, 0x59, 0x8C,
+	0x5E, 0x8A, 0x6C, 0x80, 0x6D, 0x81, 0x5F, 0x60, 0x61, 0x10, 0x30,
+	0x88, 0x66, 0x83, 0x6E, 0x80, 0x64, 0x87, 0x64, 0x30, 0x50, 0xD3,
+	0x6A, 0x6B, 0xAD, 0x30, 0x94, 0x67, 0x84, 0x65, 0x82, 0x4D, 0x83,
+	0x65, 0x30, 0x50, 0xA7, 0x43, 0x06, 0x00, 0x8D, 0x45, 0x9A, 0x6A,
+	0x6B, 0x45, 0x85, 0x06, 0x00, 0x81, 0x43, 0x8A, 0x6F, 0x96, 0x30,
+	0x90, 0x67, 0x64, 0x88, 0x64, 0x80, 0x65, 0x82, 0x10, 0xC0, 0x84,
+	0x65, 0xEF, 0x10, 0xC0, 0x66, 0x85, 0x64, 0x81, 0x17, 0x00, 0x80,
+	0x20, 0x0D, 0x80, 0x18, 0x0C, 0x80, 0x64, 0x30, 0x60, 0x41, 0x82,
+	0x42, 0xB2, 0x42, 0x80, 0x40, 0x82, 0x40, 0x4C, 0x45, 0x92, 0x6A,
+	0x6B, 0x9B, 0x45, 0x81, 0x4C, 0x40, 0x8C, 0x30, 0xA4, 0x67, 0x85,
+	0x65, 0x87, 0x65, 0x30, 0x60, 0xD3, 0x6A, 0x6B, 0xAC, 0x6C, 0x32,
+	0xA8, 0x80, 0x28, 0x30, 0x70, 0x00, 0x80, 0x40, 0x4C, 0xBD, 0x00,
+	0x0E, 0xBE, 0x44, 0x88, 0x44, 0xBC, 0x78, 0x00, 0x00,
+};
+
+static struct ar0833_reg_blob Sequencer_iHDR_v12p12 = {
+	.addr = 0x3D00,
+	.size = sizeof(Sequencer_iHDR_v12p12_data),
+	.data = Sequencer_iHDR_v12p12_data,
+};
+
+static struct ar0833_reg_blob Sequencer_Adjustment_v7p2 = {
+	.addr = 0x3D00,
+	.size = sizeof(Sequencer_Adjustment_v7p2_data),
+	.data = Sequencer_Adjustment_v7p2_data,
+};
+
+u8 Sequencer_iHDR_v7p2_data[] = {
+	0x04, 0x88, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0x40, 0x14,
+	0x0E, 0x23, 0x82, 0x41, 0x5C, 0x54, 0x6E, 0x42, 0x00, 0xC0, 0x5D,
+	0x80, 0x5A, 0x80, 0x57, 0x84, 0x64, 0x80, 0x55, 0x86, 0x64, 0x80,
+	0x65, 0x88, 0x65, 0x84, 0x58, 0x80, 0x00, 0xC0, 0x80, 0x30, 0x0C,
+	0x84, 0x42, 0x82, 0x10, 0x30, 0xA6, 0x5B, 0x80, 0x63, 0x8B, 0x30,
+	0x0C, 0xA5, 0x59, 0x84, 0x6C, 0x80, 0x6D, 0x81, 0x5F, 0x60, 0x61,
+	0x10, 0x30, 0x88, 0x66, 0x83, 0x6E, 0x80, 0x64, 0x87, 0x64, 0x30,
+	0x50, 0xDA, 0x6A, 0x83, 0x6B, 0xA6, 0x30, 0x94, 0x67, 0x84, 0x65,
+	0x82, 0x4D, 0x83, 0x65, 0x30, 0x50, 0xA6, 0x58, 0x43, 0x06, 0x00,
+	0x8D, 0x45, 0xA0, 0x45, 0x6A, 0x83, 0x6B, 0x06, 0x00, 0x81, 0x43,
+	0x9C, 0x58, 0x84, 0x30, 0x90, 0x67, 0x64, 0x88, 0x64, 0x80, 0x65,
+	0x88, 0x65, 0x82, 0x10, 0xC0, 0xEB, 0x10, 0xC0, 0x66, 0x85, 0x64,
+	0x81, 0x17, 0x00, 0x80, 0x20, 0x0D, 0x80, 0x18, 0x0C, 0x80, 0x64,
+	0x30, 0x60, 0x41, 0x82, 0x42, 0xB2, 0x42, 0x80, 0x40, 0x81, 0x40,
+	0x80, 0x41, 0x80, 0x42, 0x80, 0x43, 0x83, 0x06, 0xC0, 0x88, 0x44,
+	0x87, 0x6A, 0x83, 0x6B, 0x92, 0x44, 0x88, 0x06, 0xC8, 0x81, 0x41,
+	0x85, 0x30, 0xA4, 0x67, 0x85, 0x65, 0x87, 0x65, 0x30, 0x60, 0x8D,
+	0x42, 0x82, 0x40, 0x82, 0x40, 0x80, 0x41, 0x80, 0x42, 0x80, 0x43,
+	0x83, 0x06, 0xC0, 0x88, 0x44, 0x9C, 0x44, 0x88, 0x06, 0xC8, 0x85,
+	0x41, 0x6A, 0x83, 0x6B, 0xA0, 0x42, 0x82, 0x40, 0x6C, 0x3A, 0xA8,
+	0x80, 0x28, 0x30, 0x40, 0x80, 0x41, 0x80, 0x42, 0x80, 0x43, 0x88,
+	0x06, 0xC0, 0x83, 0x44, 0xA0, 0x44, 0x88, 0x06, 0xC8, 0x81, 0x41,
+	0xA6, 0x42, 0x82, 0x40, 0x82, 0x40, 0x80, 0x41, 0x80, 0x42, 0x80,
+	0x43, 0x83, 0x06, 0xC0, 0x88, 0x44, 0xA0, 0x44, 0x88, 0x06, 0xC8,
+	0x81, 0x41, 0xA6, 0x42, 0x82, 0x40, 0x80, 0x70, 0x6F, 0x40, 0x14,
+	0x0E, 0x23, 0xC2, 0x41, 0x82, 0x42, 0x00, 0xC0, 0x5D, 0x80, 0x5A,
+	0x80, 0x57, 0x84, 0x64, 0x80, 0x55, 0x86, 0x64, 0x80, 0x65, 0x88,
+	0x65, 0x82, 0x54, 0x80, 0x58, 0x80, 0x00, 0xC0, 0x86, 0x42, 0x82,
+	0x10, 0x30, 0x9C, 0x5C, 0x80, 0x6E, 0x86, 0x5B, 0x80, 0x63, 0x9E,
+	0x59, 0x8C, 0x5E, 0x8A, 0x6C, 0x80, 0x6D, 0x81, 0x5F, 0x60, 0x61,
+	0x10, 0x30, 0x88, 0x66, 0x83, 0x6E, 0x80, 0x64, 0x87, 0x64, 0x30,
+	0x50, 0xD3, 0x6A, 0x6B, 0xAD, 0x30, 0x94, 0x67, 0x84, 0x65, 0x82,
+	0x4D, 0x83, 0x65, 0x30, 0x50, 0xA7, 0x43, 0x06, 0x00, 0x8D, 0x45,
+	0x9A, 0x6A, 0x6B, 0x45, 0x85, 0x06, 0x00, 0x81, 0x43, 0x8A, 0x6F,
+	0x96, 0x30, 0x90, 0x67, 0x64, 0x88, 0x64, 0x80, 0x65, 0x82, 0x10,
+	0xC0, 0x84, 0x65, 0xEF, 0x10, 0xC0, 0x66, 0x85, 0x64, 0x81, 0x17,
+	0x00, 0x80, 0x20, 0x0D, 0x80, 0x18, 0x0C, 0x80, 0x64, 0x30, 0x60,
+	0x41, 0x82, 0x42, 0xB2, 0x42, 0x80, 0x40, 0x82, 0x40, 0x4C, 0x45,
+	0x92, 0x6A, 0x6B, 0x9B, 0x45, 0x81, 0x4C, 0x40, 0x8C, 0x30, 0xA4,
+	0x67, 0x85, 0x65, 0x87, 0x65, 0x30, 0x60, 0xD3, 0x6A, 0x6B, 0xAC,
+	0x6C, 0x32, 0xA8, 0x80, 0x28, 0x30, 0x70, 0x00, 0x80, 0x40, 0x4C,
+	0xBD, 0x00, 0x0E, 0xBE, 0x44, 0x88, 0x44, 0xBC, 0x78,
+};
+
+static struct ar0833_reg_blob Sequencer_iHDR_v7p2 = {
+	.addr = 0x3D00,
+	.size = sizeof(Sequencer_iHDR_v7p2_data),
+	.data = Sequencer_iHDR_v7p2_data,
+};
+
+static struct ar0833_reg MipiTimings[] = {
+	{0x31B0, 0x0060},
+	{0x31B2, 0x0042},
+	{0x31B4, 0x4C36},
+	{0x31B6, 0x5218},
+	{0x31B8, 0x404A},
+	{0x31BA, 0x028A},
+	{0x31BC, 0x0008},
+	{AR0833_TABLE_WAIT_MS, 1},
+	{AR0833_TABLE_END, 0x0000},
+};
+
+enum {
+	AR0833_TBL_RESET,
+	AR0833_TBL_DEF3P,
+	AR0833_TBL_SEQ_ADJ_V7P2,
+	AR0833_TBL_SEQ_HDR_V12P12,
+	AR0833_TBL_SEQ_HDR_V7P2,
+	AR0833_TBL_MIPITM,
+	NUM_OF_SUBTBLS,
+};
+
+static void *sub_tbls[] = {
+	[AR0833_TBL_RESET] = Reset_tbl,
+	[AR0833_TBL_DEF3P] = Default_3P_tbl,
+	[AR0833_TBL_SEQ_ADJ_V7P2] = &Sequencer_Adjustment_v7p2,
+	[AR0833_TBL_SEQ_HDR_V12P12] = &Sequencer_iHDR_v12p12,
+	[AR0833_TBL_SEQ_HDR_V7P2] = &Sequencer_iHDR_v7p2,
+	[AR0833_TBL_MIPITM] = MipiTimings,
+};
+
+/*
+ * Initialize
+ * XMCLK=24000000
+ * PAUSE=1
+ * STATE= Master Clock, 292800000
+ * REG=0x301A, 0x0218, Disable Streaming
+ * LOAD=Default_3P
+ * LOAD=Sequencer_Adjustment_v7p2
+ */
+static struct ar0833_reg mode_3264x2448_30fps[] = {
+	{AR0833_TABLE_CALL, AR0833_TBL_RESET},
+	{AR0833_TABLE_CALL, AR0833_TBL_DEF3P},
+	{AR0833_TABLE_WAIT_MS, 1},
+	{AR0833_TABLE_BLOB, AR0833_TBL_SEQ_ADJ_V7P2},
+
+	/* PLL Configuration */
+	{0x0300, 0x0005},	/*VT_PIX_CLK_DIV=5 */
+	{0x0302, 0x0001},	/*VT_SYS_CLK_DIV=1 */
+	{0x0304, 0x0004},	/*PRE_PLL_CLK_DIV=4 Note: 24MHz/4=6MHz */
+	/*PLL_MULTIPLIER=122 Note: Running at 732MHz */
+	{0x0306, 0x007A},
+	{0x0308, 0x000A},	/*OP_PIX_CLK_DIV=10 */
+	{0x030A, 0x0001},	/*OP_SYS_CLK_DIV=1 */
+	{0x3064, 0x7800},
+	{AR0833_TABLE_WAIT_MS, 1},
+
+	/* LOAD=MIPI Timings */
+	{AR0833_TABLE_CALL, AR0833_TBL_MIPITM},
+
+	/* Frame Timing */
+	{0x0340, 0x0A10},	/*FRAME_LENGTH_LINES */
+	{0x0342, 0x0ECC},	/*LINE_LENGTH_PCK */
+	{0x0344, 0x0008},	/*X_ADDR_START 8 */
+	{0x0346, 0x0008},	/*Y_ADDR_START 8 */
+	{0x0348, 0x0CC7},	/*X_ADDR_END 3271 */
+	{0x034A, 0x0997},	/*Y_ADDR_END 2455 */
+	{0x034C, 0x0CC0},	/*X_OUTPUT_SIZE 3264 */
+	{0x034E, 0x0990},	/*Y_OUTPUT_SIZE 2448 */
+	{0x3040, 0x4041},	/*X_ODD_INC & Y_ODD_INC */
+	{0x0202, 0x0A01},	/*COARSE_INTEGRATION_TIME */
+	{0x305E, 0x1000},   /* gain */
+	/*Scaling Enabling: 0= disable, 1= x-dir, 2= xy-dir */
+	{0x0400, 0x0000},
+	{0x0402, 0x0000},	/*Co-Site Scaling */
+	{0x0404, 0x0010},	/*Scale_M = 16 */
+	{0x0408, 0x1010},
+	{0x040A, 0x0210},
+	{0x306E, 0x9080},	/*Data Path Select */
+	{0x301A, 0x001C},	/* Enable Streaming */
+	{AR0833_TABLE_END, 0x0000},
+};
+
+static struct ar0833_reg mode_3264x2448_HDR_30fps[] = {
+	{AR0833_TABLE_CALL, AR0833_TBL_RESET},
+	{AR0833_TABLE_CALL, AR0833_TBL_DEF3P},
+
+	{0x0300, 0x0004},   /* VT_PIX_CLK_DIV = 4 */
+	{0x0304, 0x0004},
+	{0x0306, 0x007A},
+
+	/* LOAD=MIPI Timings */
+	{AR0833_TABLE_CALL, AR0833_TBL_MIPITM},
+
+	{0x0340,   2579},   /* FLL = 2579 */
+	{0x0342,   4832},   /* LLPCK = 4832 */
+	{0x0344, 0x0008},	/*X_ADDR_START */
+	{0x0346, 0x0008},	/*Y_ADDR_START */
+	{0x0348, 0x0CC7},	/*X_ADDR_END */
+	{0x034A, 0x0997},	/*Y_ADDR_END */
+	{0x034C, 0x0CC0},	/*X_OUTPUT_SIZE */
+	{0x034E, 0x0990},	/*Y_OUTPUT_SIZE */
+	{0x0202,   2400},   /* T1 Coarse Integration */
+	{0x3088,    300},   /* T2 Coarse Integration */
+	{0x305E, 0x1000},   /* gain */
+	{0x3040, 0x4041},	/*Default read mode */
+
+	/* Disable Streaming */
+	{0x301A, 0x0218},
+	{AR0833_TABLE_WAIT_MS, 1},
+	/*LOAD=Sequencer_iHDR_v7p2 */
+	{AR0833_TABLE_BLOB, AR0833_TBL_SEQ_HDR_V12P12},
+	/* Enable iHDR readout */
+	{0x303E, 0x0001},
+	/* Other Settings
+		BLC Options need to be set to not use auto calib in iHDR */
+	{0x30C0, 0x2001},
+	{0x30C8, 0x2020},
+	/*Disable Defect Correction, check for 1DDC? -> REG= 0x31E0, 0x01F1 */
+	{0x31E0, 0x0000},
+
+	/* No3 iHDR*/
+	{0x316C, 0x8200},
+	{0x3EFE, 0x2222},
+	{0x3EE6, 0xB10C},
+	{0x3ED8, 0x7288},
+
+	{0x301A, 0x001C},   /* Enable Streaming */
+	{AR0833_TABLE_END, 0x0000},
+};
+
+/*
+ * Initialize
+ * XMCLK=24000000
+ * PAUSE=1
+ * STATE= Master Clock, 292800000
+ * REG=0x301A, 0x0218, Disable Streaming
+ * LOAD=Default_3P
+ * LOAD=Sequencer_Adjustment_v7p2
+ */
+static struct ar0833_reg mode_1920x1080_HDR_30fps[] = {
+	{AR0833_TABLE_CALL, AR0833_TBL_RESET},
+	{AR0833_TABLE_CALL, AR0833_TBL_DEF3P},
+
+	{0x0304, 0x0004},
+	{0x0306, 0x007A},
+
+	/* LOAD=MIPI Timings */
+	{AR0833_TABLE_CALL, AR0833_TBL_MIPITM},
+
+	{0x0340,   1990},	/* FLL = 2579 */
+	{0x0342,   4832},	/* LLPCK = 4832v */
+	{0x0344, 0x02A0},	/*X_ADDR_START 672 */
+	{0x0346, 0x0130},	/*Y_ADDR_START 304 */
+	{0x0348, 0x0A1F},	/*X_ADDR_END 2591 */
+	{0x034A, 0x0567},	/*Y_ADDR_END 1751 */
+	{0x034C, 0x0780},	/*X_OUTPUT_SIZE 1920 */
+	{0x034E, 0x0438},	/*Y_OUTPUT_SIZE 1080 */
+	{0x3040, 0x4041},	/*X_ODD_INC and Y_ODD_INC */
+	{0x0202,   1952},	/* T1 Coarse Integration */
+	{0x3088,    244},	/* T2 Coarse Integration */
+	{0x305E, 0x1000},   /* gain */
+
+	/* Disable Streaming */
+	{0x301A, 0x0218},
+	{AR0833_TABLE_WAIT_MS, 1},
+	{AR0833_TABLE_BLOB, AR0833_TBL_SEQ_HDR_V7P2},
+
+	{0x303E, 0x0001},	/* Enable iHDR readout */
+	/* Other Settings
+	   BLC Options need to be set to not use auto calib in iHDR */
+	{0x30C0, 0x2001},
+	{0x30C8, 0x2020},
+	/*Disable Defect Correction, check for 1DDC? -> REG= 0x31E0, 0x01F1 */
+	{0x31E0, 0x0000},
+	/*BITFIELD=0x301A,0x0004,0  Disable Streaming */
+	{0x316C, 0x8200},	/* auto switch Txlo at 2x */
+	{0x3EFE, 0xC1C1},	/* Txlo Level: Txlo1=-12,Txlo0=+1 */
+	{0x3EE6, 0xB10D},	/* Txlo polarity: Txlo1-,Txlo0+ */
+	{0x3ED8, 0x7288},	/* Txlo booster setting */
+	{0x301A, 0x001C},	/* Enable Streaming */
+	{AR0833_TABLE_END, 0x0000},
+};
+
+/*
+ * Initialize
+ * XMCLK=24000000
+ * PAUSE=1
+ * STATE= Master Clock, 292800000
+ * REG=0x301A, 0x0218, Disable Streaming
+ * LOAD=Default_3P
+ * LOAD=Sequencer_Adjustment_v7p2
+ */
+static struct ar0833_reg mode_3264x1836_HDR_30fps[] = {
+	{AR0833_TABLE_CALL, AR0833_TBL_RESET},
+	{AR0833_TABLE_CALL, AR0833_TBL_DEF3P},
+
+	{0x0300, 0x0005},   /* VT_PIX_CLK_DIV = 5 */
+	{0x0304, 0x0004},
+	{0x0306, 0x007A},
+
+	/* LOAD=MIPI Timings */
+	{AR0833_TABLE_CALL, AR0833_TBL_MIPITM},
+
+	{0x0340,   1990},	/* FLL = 2579 */
+	{0x0342,   4832},	/* LLPCK = 4832 */
+	{0x0344, 0x0008},	/*X_ADDR_START */
+	{0x0346, 0x0130},	/*Y_ADDR_START */
+	{0x0348, 0x0CC7},	/*X_ADDR_END */
+	{0x034A, 0x085B},	/*Y_ADDR_END */
+	{0x034C, 0x0CC0},	/*X_OUTPUT_SIZE */
+	{0x034E, 0x072C},	/*Y_OUTPUT_SIZE */
+	{0x3040, 0x4041},	/*Default read mode */
+	{0x0202,   1952},	/* T1 Coarse Integration */
+	{0x3088,    244},	/* T2 Coarse Integration */
+	{0x305E, 0x1000},   /* gain */
+
+	/* Disable Streaming */
+	{0x301A, 0x0218},
+	{AR0833_TABLE_WAIT_MS, 1},
+	/*LOAD=Sequencer_iHDR_v7p2 */
+	{AR0833_TABLE_BLOB, AR0833_TBL_SEQ_HDR_V7P2},
+	/* Enable iHDR readout */
+	{0x303E, 0x0001},
+	/* Other Settings
+	   BLC Options need to be set to not use auto calib in iHDR */
+	{0x30C0, 0x2001},
+	{0x30C8, 0x2020},
+	/*Disable Defect Correction, check for 1DDC? -> REG= 0x31E0, 0x01F1 */
+	{0x31E0, 0x0000},
+	{0x301A, 0x001C},	/* Enable Streaming */
+	{AR0833_TABLE_END, 0x0000},
+};
+
+/*
+ * Initialize
+ * XMCLK=24000000
+ * PAUSE=1
+ * STATE= Master Clock, 292800000
+ * REG=0x301A, 0x0218, Disable Streaming
+ * LOAD=Default_3P
+ * LOAD=Sequencer_Adjustment_v7p2
+ */
+static struct ar0833_reg mode_1920x1080_30fps[] = {
+	{AR0833_TABLE_CALL, AR0833_TBL_RESET},
+	{AR0833_TABLE_CALL, AR0833_TBL_DEF3P},
+	{AR0833_TABLE_WAIT_MS, 1},
+	{AR0833_TABLE_BLOB, AR0833_TBL_SEQ_ADJ_V7P2},
+
+	/*PLL Configuration */
+	{0x0300, 0x0005},	/*VT_PIX_CLK_DIV=5 */
+	{0x0302, 0x0001},	/*VT_SYS_CLK_DIV=1 */
+	{0x0304, 0x0004},	/*PRE_PLL_CLK_DIV=4 Note: 24MHz/4=6MHz */
+	{0x0306, 0x007A},	/*PLL_MULTIPLIER=122 Note: Running at 732MHz */
+	{0x0308, 0x000A},	/*OP_PIX_CLK_DIV=10 */
+	{0x030A, 0x0001},	/*OP_SYS_CLK_DIV=1 */
+	{0x3064, 0x7800},
+	{AR0833_TABLE_WAIT_MS, 1},
+
+	/*LOAD=MIPI Timings */
+	{AR0833_TABLE_CALL, AR0833_TBL_MIPITM},
+
+	{0x0340, 0x079D},	/*FRAME_LENGTH_LINES */
+	{0x0342, 0x139E},	/*LINE_LENGTH_PCK */
+	{0x0344, 0x0008},	/*X_ADDR_START */
+	{0x0346, 0x0130},	/*Y_ADDR_START */
+	{0x0348, 0x0CC7},	/*X_ADDR_END */
+	{0x034A, 0x085B},	/*Y_ADDR_END */
+	{0x034C, 0x0780},	/*X_OUTPUT_SIZE */
+	{0x034E, 0x0438},	/*Y_OUTPUT_SIZE */
+	{0x3040, 0x4041},	/*X_ODD_INC & Y_ODD_INC */
+	{0x0202, 0x0700},	/*COARSE_INTEGRATION_TIME */
+	{0x305E, 0x1000},   /* gain */
+	/*Scaling Enabling: 0= disable, 1= x-dir, 2= xy-dir */
+	{0x0400, 0x0002},
+	{0x0402, 0x0000},	/*Co-Site Scaling */
+	{0x0404, 0x001A},	/*Scale_M = 16 */
+	{0x0408, 0x0B0C},
+	{0x040A, 0x018C},
+	{0x306E, 0x9090},	/*Data Path Select */
+	{0x301A, 0x001C},	/* Enable Streaming */
+	{AR0833_TABLE_END, 0x0000},
+};
+
+/*
+ * Initialize
+ * XMCLK=24000000
+ * PAUSE=1
+ * STATE= Master Clock, 292800000
+ * REG=0x301A, 0x0218, Disable Streaming
+ * LOAD=Default_3P
+ * LOAD=Sequencer_Adjustment_v7p2
+ */
+static struct ar0833_reg mode_3264x1836_30fps[] = {
+	{AR0833_TABLE_CALL, AR0833_TBL_RESET},
+	{AR0833_TABLE_CALL, AR0833_TBL_DEF3P},
+	{AR0833_TABLE_WAIT_MS, 1},
+	{AR0833_TABLE_BLOB, AR0833_TBL_SEQ_ADJ_V7P2},
+
+	/*PLL Configuration */
+	{0x0300, 0x0005},	/*VT_PIX_CLK_DIV=5 */
+	{0x0302, 0x0001},	/*VT_SYS_CLK_DIV=1 */
+	{0x0304, 0x0004},	/*PRE_PLL_CLK_DIV=4 Note: 24MHz/4=6MHz */
+	{0x0306, 0x007A},	/*PLL_MULTIPLIER=122 Note: Running at 732MHz */
+	{0x0308, 0x000A},	/*OP_PIX_CLK_DIV=10 */
+	{0x030A, 0x0001},	/*OP_SYS_CLK_DIV=1 */
+	{0x3064, 0x7800},
+	{AR0833_TABLE_WAIT_MS, 1},
+
+	{AR0833_TABLE_CALL, AR0833_TBL_MIPITM},
+
+	/*Frame Timing */
+	{0x0340, 0x079D},	/*FRAME_LENGTH_LINES */
+	{0x0342, 0x139E},	/*LINE_LENGTH_PCK */
+	{0x0344, 0x0008},	/*X_ADDR_START */
+	{0x0346, 0x0130},	/*Y_ADDR_START */
+	{0x0348, 0x0CC7},	/*X_ADDR_END */
+	{0x034A, 0x085B},	/*Y_ADDR_END */
+	{0x034C, 0x0CC0},	/*X_OUTPUT_SIZE */
+	{0x034E, 0x072C},	/*Y_OUTPUT_SIZE */
+	{0x3040, 0x4041},	/*X_ODD_INC & Y_ODD_INC */
+	{0x0202, 0x0700},	/*COARSE_INTEGRATION_TIME */
+	{0x305E, 0x1000},   /* gain */
+	/*Scaling Enabling: 0= disable, 1= x-dir, 2= xy-dir */
+	{0x0400, 0x0000},
+	{0x0402, 0x0000},	/*Co-Site Scaling */
+	{0x0404, 0x0010},	/*Scale_M = 16 */
+	{0x0408, 0x1010},
+	{0x040A, 0x0210},
+	{0x306E, 0x9080},	/*Data Path Select */
+	{0x301A, 0x001C},	/* Enable Streaming */
+	{AR0833_TABLE_END, 0x0000},
+};
diff --git a/drivers/media/video/tegra/dw9718.c b/drivers/media/video/tegra/dw9718.c
new file mode 100644
index 0000000..c2044ae
--- /dev/null
+++ b/drivers/media/video/tegra/dw9718.c
@@ -0,0 +1,1077 @@
+/*
+ * dw9718.c - dw9718 focuser driver
+ *
+ * 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/>.
+ */
+/* Implementation
+ * --------------
+ * The board level details about the device need to be provided in the board
+ * file with the <device>_platform_data structure.
+ * Standard among NVC kernel drivers in this structure is:
+ * .cfg = Use the NVC_CFG_ defines that are in nvc.h.
+ *  Descriptions of the configuration options are with the defines.
+ *      This value is typically 0.
+ * .num = The number of the instance of the device.  This should start at 1 and
+ *      and increment for each device on the board.  This number will be
+ *      appended to the MISC driver name, Example: /dev/focuser.1
+ *      If not used or 0, then nothing is appended to the name.
+ * .sync = If there is a need to synchronize two devices, then this value is
+ *       the number of the device instance (.num above) this device is to
+ *       sync to.  For example:
+ *       Device 1 platform entries =
+ *       .num = 1,
+ *       .sync = 2,
+ *       Device 2 platfrom entries =
+ *       .num = 2,
+ *       .sync = 1,
+ *       The above example sync's device 1 and 2.
+ *       To disable sync, set .sync = 0.  Note that the .num = 0 device is not
+ *       allowed to be synced to.
+ *       This is typically used for stereo applications.
+ * .dev_name = The MISC driver name the device registers as.  If not used,
+ *       then the part number of the device is used for the driver name.
+ *       If using the NVC user driver then use the name found in this
+ *       driver under _default_pdata.
+ * .gpio_count = The ARRAY_SIZE of the nvc_gpio_pdata table.
+ * .gpio = A pointer to the nvc_gpio_pdata structure's platform GPIO data.
+ *       The GPIO mechanism works by cross referencing the .gpio_type key
+ *       among the nvc_gpio_pdata GPIO data and the driver's nvc_gpio_init
+ *       GPIO data to build a GPIO table the driver can use.  The GPIO's
+ *       defined in the device header file's _gpio_type enum are the
+ *       gpio_type keys for the nvc_gpio_pdata and nvc_gpio_init structures.
+ *       These need to be present in the board file's nvc_gpio_pdata
+ *       structure for the GPIO's that are used.
+ *       The driver's GPIO logic uses assert/deassert throughout until the
+ *       low level _gpio_wr/rd calls where the .assert_high is used to
+ *       convert the value to the correct signal level.
+ *       See the GPIO notes in nvc.h for additional information.
+ *
+ * The following is specific to NVC kernel focus drivers:
+ * .nvc = Pointer to the nvc_focus_nvc structure.  This structure needs to
+ *      be defined and populated if overriding the driver defaults.
+ * .cap = Pointer to the nvc_focus_cap structure.  This structure needs to
+ *      be defined and populated if overriding the driver defaults.
+ *
+ * The following is specific to this NVC kernel focus driver:
+ * .info = Pointer to the dw9718_pdata_info structure.  This structure does
+ *       not need to be defined and populated unless overriding ROM data.
+ *
+ * Power Requirements:
+ * The device's header file defines the voltage regulators needed with the
+ * enumeration <device>_vreg.  The order these are enumerated is the order
+ * the regulators will be enabled when powering on the device.  When the
+ * device is powered off the regulators are disabled in descending order.
+ * The <device>_vregs table in this driver uses the nvc_regulator_init
+ * structure to define the regulator ID strings that go with the regulators
+ * defined with <device>_vreg.  These regulator ID strings (or supply names)
+ * will be used in the regulator_get function in the _vreg_init function.
+ * The board power file and <device>_vregs regulator ID strings must match.
+ */
+
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <media/dw9718.h>
+
+#define ENABLE_DEBUGFS_INTERFACE
+
+#define dw9718_ID			0x04
+#define dw9718_FOCAL_LENGTH_FLOAT	(4.570f)
+#define dw9718_FNUMBER_FLOAT		(2.8f)
+#define dw9718_FOCAL_LENGTH		(0x40923D71) /* 4.570f */
+#define dw9718_FNUMBER			(0x40333333) /* 2.8f */
+#define dw9718_SLEW_RATE		0x0060
+#define dw9718_ACTUATOR_RANGE		1023
+#define dw9718_SETTLETIME		30
+#define dw9718_FOCUS_MACRO		620
+#define dw9718_FOCUS_INFINITY		70
+#define dw9718_POS_LOW_DEFAULT		0
+#define dw9718_POS_HIGH_DEFAULT		1023
+#define dw9718_POS_CLAMP		0x03ff
+/* Need to decide exact value of VCM_THRESHOLD and its use */
+/* define dw9718_VCM_THRESHOLD	20 */
+
+struct dw9718_info {
+	atomic_t in_use;
+	struct i2c_client *i2c_client;
+	struct dw9718_platform_data *pdata;
+	struct miscdevice miscdev;
+	struct list_head list;
+	int pwr_dev;
+	struct dw9718_power_rail power;
+	int status;
+	u32 cur_pos;
+	u8 s_mode;
+	bool reset_flag;
+	struct dw9718_info *s_info;
+	struct nvc_focus_nvc nvc;
+	struct nvc_focus_cap cap;
+	struct nv_focuser_config nv_config;
+};
+
+/**
+ * The following are default values
+ */
+static struct nvc_focus_cap dw9718_default_cap = {
+	.version = NVC_FOCUS_CAP_VER2,
+	.slew_rate = dw9718_SLEW_RATE,
+	.actuator_range = dw9718_ACTUATOR_RANGE,
+	.settle_time = dw9718_SETTLETIME,
+	.focus_macro = dw9718_FOCUS_MACRO,
+	.focus_infinity = dw9718_FOCUS_INFINITY,
+	.focus_hyper = dw9718_FOCUS_INFINITY,
+};
+
+static struct nvc_focus_nvc dw9718_default_nvc = {
+	.focal_length = dw9718_FOCAL_LENGTH,
+	.fnumber = dw9718_FNUMBER,
+	.max_aperature = dw9718_FNUMBER,
+};
+
+static struct dw9718_platform_data dw9718_default_pdata = {
+	.cfg = 0,
+	.num = 0,
+	.sync = 0,
+	.dev_name = "focuser",
+};
+static LIST_HEAD(dw9718_info_list);
+static DEFINE_SPINLOCK(dw9718_spinlock);
+
+static int dw9718_i2c_wr8(struct dw9718_info *info, u8 reg, u8 val)
+{
+	struct i2c_msg msg;
+	u8 buf[2];
+	buf[0] = reg;
+	buf[1] = val;
+	msg.addr = info->i2c_client->addr;
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = &buf[0];
+	if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
+		return -EIO;
+	return 0;
+}
+
+static int dw9718_i2c_wr16(struct dw9718_info *info, u8 reg, u16 val)
+{
+	struct i2c_msg msg;
+	u8 buf[3];
+	buf[0] = reg;
+	buf[1] = (u8)(val >> 8);
+	buf[2] = (u8)(val & 0xff);
+	msg.addr = info->i2c_client->addr;
+	msg.flags = 0;
+	msg.len = 3;
+	msg.buf = &buf[0];
+	if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
+		return -EIO;
+	return 0;
+}
+
+/**
+ * Below are device specific functions.
+ */
+static int dw9718_position_wr(struct dw9718_info *info, s32 position)
+{
+	int err;
+
+	dev_dbg(&info->i2c_client->dev, "%s %d\n", __func__, position);
+	position &= dw9718_POS_CLAMP;
+	err = dw9718_i2c_wr16(info, DW9718_VCM_CODE_MSB, position);
+	if (!err)
+		info->cur_pos = position;
+	else
+		dev_err(&info->i2c_client->dev, "%s: ERROR set position %d",
+			__func__, position);
+	return err;
+}
+
+int dw9718_set_arc_mode(struct dw9718_info *info)
+{
+	int err;
+	u32 sr = info->nv_config.slew_rate;
+
+	dev_dbg(&info->i2c_client->dev, "%s %x\n", __func__, sr);
+	/* set ARC enable */
+	err = dw9718_i2c_wr8(info, DW9718_CONTROL, (sr >> 16) & 0xFF);
+	if (err) {
+		dev_err(&info->i2c_client->dev,
+		"%s: CONTROL reg write failed\n", __func__);
+		goto set_arc_mode_done;
+	}
+	usleep_range(80, 100);
+
+	/* set the ARC RES2 */
+	err = dw9718_i2c_wr8(info, DW9718_SWITCH_MODE, (sr >> 8) & 0xFF);
+	if (err) {
+		dev_err(&info->i2c_client->dev,
+		"%s: MODE write failed\n", __func__);
+		goto set_arc_mode_done;
+	}
+
+	err = dw9718_i2c_wr8(info, DW9718_SACT, sr & 0XFF);
+	if (err) {
+		dev_err(&info->i2c_client->dev,
+		"%s: RES write failed\n", __func__);
+		goto set_arc_mode_done;
+	}
+
+	err = dw9718_position_wr(info, 0);
+
+set_arc_mode_done:
+	return err;
+}
+
+static int dw9718_pm_wr(struct dw9718_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:
+		if (info->pdata && info->pdata->power_off)
+			info->pdata->power_off(&info->power);
+		break;
+	case NVC_PWR_STDBY_OFF:
+	case NVC_PWR_STDBY:
+		if (info->pdata && info->pdata->power_off)
+			info->pdata->power_off(&info->power);
+		break;
+	case NVC_PWR_COMM:
+	case NVC_PWR_ON:
+		if (info->pdata && info->pdata->power_on)
+			info->pdata->power_on(&info->power);
+		dw9718_set_arc_mode(info);
+		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);
+
+	return err;
+}
+
+static int dw9718_power_put(struct dw9718_power_rail *pw)
+{
+	if (unlikely(!pw))
+		return -EFAULT;
+
+	if (likely(pw->vdd))
+		regulator_put(pw->vdd);
+
+	if (likely(pw->vdd_i2c))
+		regulator_put(pw->vdd_i2c);
+
+	pw->vdd = NULL;
+	pw->vdd_i2c = NULL;
+
+	return 0;
+}
+
+static int dw9718_regulator_get(struct dw9718_info *info,
+	struct regulator **vreg, char vreg_name[])
+{
+	struct regulator *reg = NULL;
+	int err = 0;
+
+	reg = regulator_get(&info->i2c_client->dev, vreg_name);
+	if (unlikely(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;
+	return err;
+}
+
+static int dw9718_power_get(struct dw9718_info *info)
+{
+	struct dw9718_power_rail *pw = &info->power;
+
+	dw9718_regulator_get(info, &pw->vdd, "vdd");
+	dw9718_regulator_get(info, &pw->vdd_i2c, "vdd_i2c");
+
+	return 0;
+}
+
+static int dw9718_pm_dev_wr(struct dw9718_info *info, int pwr)
+{
+	if (pwr < info->pwr_dev)
+		pwr = info->pwr_dev;
+	return dw9718_pm_wr(info, pwr);
+}
+
+static void dw9718_pm_exit(struct dw9718_info *info)
+{
+	dw9718_pm_wr(info, NVC_PWR_OFF_FORCE);
+	dw9718_power_put(&info->power);
+}
+
+static int dw9718_reset(struct dw9718_info *info, u32 level)
+{
+	int err = 0;
+
+	if (level == NVC_RESET_SOFT) {
+		err = dw9718_i2c_wr8(info, DW9718_POWER_DN, 0x01);
+		usleep_range(200, 220);
+		err |= dw9718_i2c_wr8(info, DW9718_POWER_DN, 0x00);
+		usleep_range(100, 120);
+	} else
+		err = dw9718_pm_wr(info, NVC_PWR_OFF_FORCE);
+
+	return err;
+}
+
+static void dw9718_get_focuser_capabilities(struct dw9718_info *info)
+{
+	memset(&info->nv_config, 0, sizeof(info->nv_config));
+
+	dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+	info->nv_config.focal_length = info->nvc.focal_length;
+	info->nv_config.fnumber = info->nvc.fnumber;
+	info->nv_config.max_aperture = info->nvc.fnumber;
+	info->nv_config.range_ends_reversed = 0;
+
+	info->nv_config.pos_working_low = info->cap.focus_infinity;
+	info->nv_config.pos_working_high = info->cap.focus_macro;
+	info->nv_config.pos_actual_low = dw9718_POS_LOW_DEFAULT;
+	info->nv_config.pos_actual_high = dw9718_POS_HIGH_DEFAULT;
+
+	info->nv_config.slew_rate = info->cap.slew_rate;
+	info->nv_config.circle_of_confusion = -1;
+	info->nv_config.num_focuser_sets = 1;
+	info->nv_config.focuser_set[0].macro = info->cap.focus_macro;
+	info->nv_config.focuser_set[0].hyper = info->cap.focus_hyper;
+	info->nv_config.focuser_set[0].inf = info->cap.focus_infinity;
+	info->nv_config.focuser_set[0].settle_time = info->cap.settle_time;
+}
+
+static int dw9718_set_focuser_capabilities(struct dw9718_info *info,
+					struct nvc_param *params)
+{
+	dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+	if (copy_from_user(&info->nv_config,
+		(const void __user *)params->p_value,
+		sizeof(struct nv_focuser_config))) {
+			dev_err(&info->i2c_client->dev,
+			"%s Error: copy_from_user bytes %d\n",
+			__func__, sizeof(struct nv_focuser_config));
+			return -EFAULT;
+	}
+
+	/* set pre-set value, as currently ODM sets incorrect value */
+	info->cap.settle_time = dw9718_SETTLETIME;
+
+	dev_dbg(&info->i2c_client->dev,
+		"%s: copy_from_user bytes %d info->cap.settle_time %d\n",
+		__func__, sizeof(struct nv_focuser_config),
+		info->cap.settle_time);
+
+	return 0;
+}
+
+static int dw9718_param_rd(struct dw9718_info *info, unsigned long arg)
+{
+	struct nvc_param params;
+	const void *data_ptr = NULL;
+	u32 data_size = 0;
+
+	dev_dbg(&info->i2c_client->dev, "%s %lx\n", __func__, arg);
+	if (copy_from_user(&params,
+		(const void __user *)arg,
+		sizeof(struct nvc_param))) {
+		dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
+			__func__, __LINE__);
+		return -EFAULT;
+	}
+	if (info->s_mode == NVC_SYNC_SLAVE)
+		info = info->s_info;
+	switch (params.param) {
+	case NVC_PARAM_LOCUS:
+		data_ptr = &info->cur_pos;
+		data_size = sizeof(info->cur_pos);
+		dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n",
+			__func__, info->cur_pos);
+		break;
+	case NVC_PARAM_FOCAL_LEN:
+		info->nvc.focal_length = dw9718_FOCAL_LENGTH;
+		data_ptr = &info->nvc.focal_length;
+		data_size = sizeof(info->nvc.focal_length);
+		break;
+	case NVC_PARAM_MAX_APERTURE:
+		data_ptr = &info->nvc.max_aperature;
+		data_size = sizeof(info->nvc.max_aperature);
+		dev_dbg(&info->i2c_client->dev, "%s MAX_APERTURE: %x\n",
+				__func__, info->nvc.max_aperature);
+		break;
+	case NVC_PARAM_FNUMBER:
+		data_ptr = &info->nvc.fnumber;
+		data_size = sizeof(info->nvc.fnumber);
+		dev_dbg(&info->i2c_client->dev, "%s FNUMBER: %u\n",
+				__func__, info->nvc.fnumber);
+		break;
+	case NVC_PARAM_CAPS:
+		/* send back just what's requested or our max size */
+		dw9718_get_focuser_capabilities(info);
+		data_ptr = &info->nv_config;
+		data_size = sizeof(info->nv_config);
+		dev_err(&info->i2c_client->dev, "%s CAPS\n", __func__);
+		break;
+	case NVC_PARAM_STS:
+		data_ptr = &info->status;
+		data_size = sizeof(info->status);
+		dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+		break;
+	case NVC_PARAM_STEREO:
+		data_ptr = &info->s_mode;
+		data_size = sizeof(info->s_mode);
+		dev_err(&info->i2c_client->dev, "%s STEREO: %d\n", __func__,
+			info->s_mode);
+		break;
+	default:
+		dev_err(&info->i2c_client->dev,
+			"%s unsupported parameter: %d\n",
+			__func__, params.param);
+		return -EINVAL;
+	}
+	if (params.sizeofvalue < data_size) {
+		dev_err(&info->i2c_client->dev,
+			"%s data size mismatch %d != %d Param: %d\n",
+			__func__, params.sizeofvalue, data_size, params.param);
+		return -EINVAL;
+	}
+	if (copy_to_user((void __user *)params.p_value, data_ptr, data_size)) {
+		dev_err(&info->i2c_client->dev, "%s copy_to_user err line %d\n",
+			__func__, __LINE__);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static int dw9718_param_wr_s(struct dw9718_info *info,
+		struct nvc_param *params, s32 s32val)
+{
+	int err = 0;
+
+	switch (params->param) {
+	case NVC_PARAM_LOCUS:
+		dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n",
+			__func__, s32val);
+		err = dw9718_position_wr(info, s32val);
+		break;
+	case NVC_PARAM_RESET:
+		err = dw9718_reset(info, s32val);
+		dev_dbg(&info->i2c_client->dev, "%s RESET\n", __func__);
+		break;
+	case NVC_PARAM_SELF_TEST:
+		dev_dbg(&info->i2c_client->dev, "%s SELF_TEST\n", __func__);
+		break;
+	default:
+		dev_dbg(&info->i2c_client->dev,
+			"%s unsupported parameter: %d\n",
+			__func__, params->param);
+		err = -EINVAL;
+		break;
+	}
+
+	if (err)
+		dev_err(&info->i2c_client->dev, "ERROR! %d\n", err);
+	return err;
+}
+
+static int dw9718_param_wr(struct dw9718_info *info, unsigned long arg)
+{
+	struct nvc_param params;
+	u8 u8val;
+	s32 s32val;
+	int err = 0;
+	if (copy_from_user(&params, (const void __user *)arg,
+		sizeof(struct nvc_param))) {
+		dev_err(&info->i2c_client->dev,
+			"%s copy_from_user err line %d\n",
+			__func__, __LINE__);
+		return -EFAULT;
+	}
+	if (copy_from_user(&s32val,
+		(const void __user *)params.p_value, sizeof(s32val))) {
+		dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
+			__func__, __LINE__);
+		return -EFAULT;
+	}
+	u8val = (u8)s32val;
+	/* parameters independent of sync mode */
+	switch (params.param) {
+	case NVC_PARAM_STEREO:
+		dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
+			__func__, u8val);
+		if (u8val == info->s_mode)
+			return 0;
+		switch (u8val) {
+		case NVC_SYNC_OFF:
+			info->s_mode = u8val;
+			break;
+		case NVC_SYNC_MASTER:
+			info->s_mode = u8val;
+			break;
+		case NVC_SYNC_SLAVE:
+			if (info->s_info != NULL) {
+				/* default slave lens position */
+				err = dw9718_position_wr(info->s_info,
+					info->s_info->cap.focus_infinity);
+				if (!err) {
+					info->s_mode = u8val;
+					info->s_info->s_mode = u8val;
+				} else {
+					if (info->s_mode != NVC_SYNC_STEREO)
+						dw9718_pm_wr(info->s_info,
+						NVC_PWR_OFF);
+						err = -EIO;
+				}
+			} else {
+				err = -EINVAL;
+			}
+			break;
+		case NVC_SYNC_STEREO:
+			if (info->s_info != NULL) {
+				/* sync power */
+				info->s_info->pwr_dev = info->pwr_dev;
+				/* move slave lens to master position */
+				err = dw9718_position_wr(info->s_info,
+					(s32)info->cur_pos);
+				if (!err) {
+					info->s_mode = u8val;
+					info->s_info->s_mode = u8val;
+				} else {
+					if (info->s_mode != NVC_SYNC_SLAVE)
+						dw9718_pm_wr(info->s_info,
+							NVC_PWR_OFF);
+					err = -EIO;
+				}
+			} else {
+				err = -EINVAL;
+			}
+			break;
+		default:
+			err = -EINVAL;
+		}
+		if (info->pdata->cfg & NVC_CFG_NOERR)
+			return 0;
+		return err;
+
+	case NVC_PARAM_CAPS:
+		if (dw9718_set_focuser_capabilities(info, &params)) {
+			dev_err(&info->i2c_client->dev,
+				"%s: Error: copy_from_user bytes %d\n",
+				__func__, params.sizeofvalue);
+			return -EFAULT;
+		}
+		return 0;
+
+	default:
+		/* parameters dependent on sync mode */
+		switch (info->s_mode) {
+		case NVC_SYNC_OFF:
+		case NVC_SYNC_MASTER:
+			return dw9718_param_wr_s(info, &params, s32val);
+		case NVC_SYNC_SLAVE:
+			return dw9718_param_wr_s(info->s_info, &params, s32val);
+		case NVC_SYNC_STEREO:
+			err = dw9718_param_wr_s(info, &params, s32val);
+			if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
+				err |= dw9718_param_wr_s(info->s_info,
+						&params, s32val);
+			return err;
+		default:
+			dev_err(&info->i2c_client->dev, "%s %d internal err\n",
+					__func__, __LINE__);
+			return -EINVAL;
+		}
+	}
+}
+
+static long dw9718_ioctl(struct file *file,
+					unsigned int cmd,
+					unsigned long arg)
+{
+	struct dw9718_info *info = file->private_data;
+	int pwr;
+	int err = 0;
+	switch (cmd) {
+	case NVC_IOCTL_PARAM_WR:
+		dw9718_pm_dev_wr(info, NVC_PWR_ON);
+		err = dw9718_param_wr(info, arg);
+		dw9718_pm_dev_wr(info, NVC_PWR_OFF);
+		return err;
+	case NVC_IOCTL_PARAM_RD:
+		dw9718_pm_dev_wr(info, NVC_PWR_ON);
+		err = dw9718_param_rd(info, arg);
+		dw9718_pm_dev_wr(info, NVC_PWR_OFF);
+		return err;
+	case NVC_IOCTL_PWR_WR:
+		/* This is a Guaranteed Level of Service (GLOS) call */
+		pwr = (int)arg * 2;
+		dev_dbg(&info->i2c_client->dev, "%s PWR_WR: %d\n",
+				__func__, pwr);
+		err = dw9718_pm_dev_wr(info, pwr);
+		return err;
+	case NVC_IOCTL_PWR_RD:
+		if (info->s_mode == NVC_SYNC_SLAVE)
+			pwr = info->s_info->pwr_dev;
+		else
+			pwr = info->pwr_dev;
+		dev_dbg(&info->i2c_client->dev, "%s PWR_RD: %d\n",
+				__func__, pwr);
+		if (copy_to_user((void __user *)arg,
+			(const void *)&pwr, sizeof(pwr))) {
+			dev_err(&info->i2c_client->dev,
+				"%s copy_to_user err line %d\n",
+				__func__, __LINE__);
+			return -EFAULT;
+		}
+		return 0;
+	default:
+		dev_dbg(&info->i2c_client->dev, "%s unsupported ioctl: %x\n",
+			__func__, cmd);
+	}
+	return -EINVAL;
+}
+
+
+static void dw9718_sdata_init(struct dw9718_info *info)
+{
+	/* set defaults */
+	memcpy(&info->nvc, &dw9718_default_nvc, sizeof(info->nvc));
+	memcpy(&info->cap, &dw9718_default_cap, sizeof(info->cap));
+
+	/* set overrides if any */
+	if (info->pdata->nvc) {
+		if (info->pdata->nvc->fnumber)
+			info->nvc.fnumber = info->pdata->nvc->fnumber;
+		if (info->pdata->nvc->focal_length)
+			info->nvc.focal_length = info->pdata->nvc->focal_length;
+		if (info->pdata->nvc->max_aperature)
+			info->nvc.max_aperature =
+				info->pdata->nvc->max_aperature;
+	}
+
+	if (info->pdata->cap) {
+		if (info->pdata->cap->actuator_range)
+			info->cap.actuator_range =
+				info->pdata->cap->actuator_range;
+		if (info->pdata->cap->settle_time)
+			info->cap.settle_time = info->pdata->cap->settle_time;
+		if (info->pdata->cap->slew_rate)
+			info->cap.slew_rate = info->pdata->cap->slew_rate;
+		if (info->pdata->cap->focus_macro)
+			info->cap.focus_macro = info->pdata->cap->focus_macro;
+		if (info->pdata->cap->focus_hyper)
+			info->cap.focus_hyper = info->pdata->cap->focus_hyper;
+		if (info->pdata->cap->focus_infinity)
+			info->cap.focus_infinity =
+				info->pdata->cap->focus_infinity;
+	}
+}
+
+static int dw9718_sync_en(unsigned num, unsigned sync)
+{
+	struct dw9718_info *master = NULL;
+	struct dw9718_info *slave = NULL;
+	struct dw9718_info *pos = NULL;
+	rcu_read_lock();
+	list_for_each_entry_rcu(pos, &dw9718_info_list, list) {
+		if (pos->pdata->num == num) {
+			master = pos;
+			break;
+		}
+	}
+	pos = NULL;
+	list_for_each_entry_rcu(pos, &dw9718_info_list, list) {
+		if (pos->pdata->num == sync) {
+			slave = pos;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	if (master != NULL)
+		master->s_info = NULL;
+	if (slave != NULL)
+		slave->s_info = NULL;
+	if (!sync)
+		return 0; /* no err if sync disabled */
+	if (num == sync)
+		return -EINVAL; /* err if sync instance is itself */
+	if ((master != NULL) && (slave != NULL)) {
+		master->s_info = slave;
+		slave->s_info = master;
+	}
+	return 0;
+}
+
+static int dw9718_sync_dis(struct dw9718_info *info)
+{
+	if (info->s_info != NULL) {
+		info->s_info->s_mode = 0;
+		info->s_info->s_info = NULL;
+		info->s_mode = 0;
+		info->s_info = NULL;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int dw9718_open(struct inode *inode, struct file *file)
+{
+	struct dw9718_info *info = NULL;
+	struct dw9718_info *pos = NULL;
+	int err;
+	rcu_read_lock();
+	list_for_each_entry_rcu(pos, &dw9718_info_list, list) {
+		if (pos->miscdev.minor == iminor(inode)) {
+			info = pos;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	if (!info)
+		return -ENODEV;
+	err = dw9718_sync_en(info->pdata->num, info->pdata->sync);
+	if (err == -EINVAL)
+		dev_err(&info->i2c_client->dev,
+			"%s err: invalid num (%u) and sync (%u) instance\n",
+			__func__, info->pdata->num, info->pdata->sync);
+	if (atomic_xchg(&info->in_use, 1))
+		return -EBUSY;
+	if (info->s_info != NULL) {
+		if (atomic_xchg(&info->s_info->in_use, 1))
+			return -EBUSY;
+	}
+	file->private_data = info;
+	dw9718_pm_dev_wr(info, NVC_PWR_ON);
+	dw9718_position_wr(info, info->cap.focus_infinity);
+	dw9718_pm_dev_wr(info, NVC_PWR_OFF);
+	dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+
+	return 0;
+}
+
+static int dw9718_release(struct inode *inode, struct file *file)
+{
+	struct dw9718_info *info = file->private_data;
+	dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+	dw9718_pm_wr(info, NVC_PWR_OFF);
+	file->private_data = NULL;
+	WARN_ON(!atomic_xchg(&info->in_use, 0));
+	if (info->s_info != NULL)
+		WARN_ON(!atomic_xchg(&info->s_info->in_use, 0));
+	dw9718_sync_dis(info);
+	return 0;
+}
+
+static const struct file_operations dw9718_fileops = {
+	.owner = THIS_MODULE,
+	.open = dw9718_open,
+	.unlocked_ioctl = dw9718_ioctl,
+	.release = dw9718_release,
+};
+
+static void dw9718_del(struct dw9718_info *info)
+{
+	dw9718_pm_exit(info);
+	if ((info->s_mode == NVC_SYNC_SLAVE) ||
+		(info->s_mode == NVC_SYNC_STEREO))
+		dw9718_pm_exit(info->s_info);
+
+	dw9718_sync_dis(info);
+	spin_lock(&dw9718_spinlock);
+	list_del_rcu(&info->list);
+	spin_unlock(&dw9718_spinlock);
+	synchronize_rcu();
+}
+
+static int dw9718_remove(struct i2c_client *client)
+{
+	struct dw9718_info *info = i2c_get_clientdata(client);
+	dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+	misc_deregister(&info->miscdev);
+	dw9718_del(info);
+	return 0;
+}
+
+static int nvc_debugfs_init(const char *dir_name,
+	struct dentry **d_entry, struct dentry **f_entry, void *info);
+
+static int dw9718_probe(
+		struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct dw9718_info *info;
+	char dname[16];
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+	pr_info("dw9718: probing focuser.\n");
+
+	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 = &dw9718_default_pdata;
+		dev_dbg(&client->dev, "%s No platform data.  Using defaults.\n",
+			__func__);
+	}
+
+	i2c_set_clientdata(client, info);
+	INIT_LIST_HEAD(&info->list);
+	spin_lock(&dw9718_spinlock);
+	list_add_rcu(&info->list, &dw9718_info_list);
+	spin_unlock(&dw9718_spinlock);
+	dw9718_power_get(info);
+	dw9718_sdata_init(info);
+
+	if (info->pdata->dev_name != 0)
+		strcpy(dname, info->pdata->dev_name);
+	else
+		strcpy(dname, "dw9718");
+
+	if (info->pdata->num)
+		snprintf(dname, sizeof(dname),
+			"%s.%u", dname, info->pdata->num);
+
+	info->miscdev.name = dname;
+	info->miscdev.fops = &dw9718_fileops;
+	info->miscdev.minor = MISC_DYNAMIC_MINOR;
+	if (misc_register(&info->miscdev)) {
+		dev_err(&client->dev, "%s unable to register misc device %s\n",
+			__func__, dname);
+		dw9718_del(info);
+		return -ENODEV;
+	}
+
+	nvc_debugfs_init(
+		info->miscdev.this_device->kobj.name, NULL, NULL, info);
+
+	return 0;
+}
+
+#ifdef ENABLE_DEBUGFS_INTERFACE
+static int nvc_status_show(struct seq_file *s, void *data)
+{
+	struct dw9718_info *k_info = s->private;
+	struct nv_focuser_config *pcfg = &k_info->nv_config;
+	struct nvc_focus_cap *pcap = &k_info->cap;
+
+	pr_info("%s\n", __func__);
+
+	seq_printf(s, "focuser status:\n"
+		"    Limit          = (%04d - %04d)\n"
+		"    Range          = (%04d - %04d)\n"
+		"    Current Pos    = %04d\n"
+		"    Settle time    = %04d\n"
+		"    Macro          = %04d\n"
+		"    Infinity       = %04d\n"
+		"    Hyper          = %04d\n"
+		"    SlewRate       = 0x%06x\n"
+		,
+		pcfg->pos_actual_low, pcfg->pos_actual_high,
+		pcfg->pos_working_low, pcfg->pos_working_high,
+		k_info->cur_pos,
+		pcap->settle_time,
+		pcap->focus_macro,
+		pcap->focus_infinity,
+		pcap->focus_hyper,
+		pcfg->slew_rate
+		);
+
+	return 0;
+}
+
+static ssize_t nvc_attr_set(struct file *s,
+	const char __user *user_buf, size_t count, loff_t *ppos)
+{
+	struct dw9718_info *k_info =
+		((struct seq_file *)s->private_data)->private;
+	struct nv_focuser_config *pcfg = &k_info->nv_config;
+	char buf[24];
+	int buf_size;
+	int err;
+	u32 val = 0;
+
+	pr_info("%s (%d)\n", __func__, count);
+
+	if (!user_buf || count <= 1)
+		return -EFAULT;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+
+	if (sscanf(buf + 1, "0x%x", &val) == 1)
+		goto set_attr;
+	if (sscanf(buf + 1, "0X%x", &val) == 1)
+		goto set_attr;
+	if (sscanf(buf + 1, "%d", &val) == 1)
+		goto set_attr;
+
+	pr_err("SYNTAX ERROR: %s\n", buf);
+	return -EFAULT;
+
+set_attr:
+	pr_info("new data = %x\n", val);
+	switch (buf[0]) {
+	case 'p':
+		pr_info("new pos = %d\n", val);
+		err = dw9718_position_wr(k_info, val);
+		if (err)
+			pr_err("ERROR set position %x\n", val);
+		break;
+	case 'h':
+		if (val <= pcfg->pos_working_low || val >= 1024) {
+			pr_info("new pos_high(%d) out of range\n",
+				val);
+			break;
+		}
+		pr_info("new pos_high = %d\n", val);
+		pcfg->pos_working_high = val;
+		break;
+	case 'l':
+		if (val >= pcfg->pos_working_high) {
+			pr_info("new pos_low(%d) out of range\n",
+				val);
+			break;
+		}
+		pr_info("new pos_low = %d\n", val);
+		pcfg->pos_working_low = val;
+		break;
+	case 'm':
+		pr_info("new vcm mode = %x\n", val);
+		pcfg->slew_rate = val;
+		dw9718_set_arc_mode(k_info);
+		break;
+	}
+
+	return count;
+}
+
+static int nvc_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, nvc_status_show, inode->i_private);
+}
+
+static const struct file_operations nvc_debugfs_fops = {
+	.open = nvc_debugfs_open,
+	.read = seq_read,
+	.write = nvc_attr_set,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int nvc_debugfs_init(const char *dir_name,
+	struct dentry **d_entry, struct dentry **f_entry, void *info)
+{
+	struct dentry *dp, *fp;
+
+	dp = debugfs_create_dir(dir_name, NULL);
+	if (dp == NULL) {
+		pr_info("%s: debugfs create dir failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	fp = debugfs_create_file("d", S_IRUGO|S_IWUSR,
+		dp, info, &nvc_debugfs_fops);
+	if (!fp) {
+		pr_info("%s: debugfs create file failed\n", __func__);
+		debugfs_remove_recursive(dp);
+		return -ENOMEM;
+	}
+
+	if (d_entry)
+		*d_entry = dp;
+	if (f_entry)
+		*f_entry = fp;
+	return 0;
+}
+#else
+static int nvc_debugfs_init(const char *dir_name,
+	struct dentry **d_entry, struct dentry **f_entry, void *info)
+{
+	return 0;
+}
+#endif
+
+
+static const struct i2c_device_id dw9718_id[] = {
+	{ "dw9718", 0 },
+	{ },
+};
+
+
+MODULE_DEVICE_TABLE(i2c, dw9718_id);
+
+static struct i2c_driver dw9718_i2c_driver = {
+	.driver = {
+		.name = "dw9718",
+		.owner = THIS_MODULE,
+	},
+	.id_table = dw9718_id,
+	.probe = dw9718_probe,
+	.remove = dw9718_remove,
+};
+
+static int __init dw9718_init(void)
+{
+	return i2c_add_driver(&dw9718_i2c_driver);
+}
+
+static void __exit dw9718_exit(void)
+{
+	i2c_del_driver(&dw9718_i2c_driver);
+}
+
+module_init(dw9718_init);
+module_exit(dw9718_exit);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/tegra/imx132.c b/drivers/media/video/tegra/imx132.c
index 22a1ab7..6e89577 100644
--- a/drivers/media/video/tegra/imx132.c
+++ b/drivers/media/video/tegra/imx132.c
@@ -1,15 +1,19 @@
 /*
  * imx132.c - imx132 sensor driver
  *
- * Copyright (c) 2012-2013, NVIDIA Corporation. All Rights Reserved.
- *
- * Contributors:
- *      Krupal Divvela <kdivvela@nvidia.com>
- *
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
+ * Copyright (c) 2012 - 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>
@@ -756,6 +760,7 @@
 
 static const struct i2c_device_id imx132_id[] = {
 	{ "imx132", 0 },
+	{ }
 };
 
 MODULE_DEVICE_TABLE(i2c, imx132_id);
diff --git a/drivers/media/video/tegra/imx135.c b/drivers/media/video/tegra/imx135.c
new file mode 100644
index 0000000..ca4d894
--- /dev/null
+++ b/drivers/media/video/tegra/imx135.c
@@ -0,0 +1,2417 @@
+/*
+ * imx135.c - imx135 sensor driver
+ *
+ * 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 <media/imx135.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+struct imx135_reg {
+	u16 addr;
+	u8 val;
+};
+
+struct imx135_info {
+	struct miscdevice		miscdev_info;
+	int				mode;
+	struct imx135_power_rail	power;
+	struct imx135_sensordata	sensor_data;
+	struct i2c_client		*i2c_client;
+	struct imx135_platform_data	*pdata;
+	struct mutex			imx135_camera_lock;
+	struct dentry			*debugdir;
+	atomic_t			in_use;
+};
+
+#define IMX135_TABLE_WAIT_MS 0
+#define IMX135_TABLE_END 1
+#define IMX135_MAX_RETRIES 3
+#define IMX135_WAIT_MS 3
+
+#define IMX135_4208x3120_HDR
+
+#ifdef IMX135_4208x3120_HDR
+/* HDR */
+static struct imx135_reg mode_4208x3120[] = {
+	/* software reset */
+	{0x0103, 0x01},
+	/* global settings */
+	{0x0101, 0x00},
+	{0x0105, 0x01},
+	{0x0110, 0x00},
+	{0x0220, 0x01},
+	{0x3302, 0x11},
+	{0x3833, 0x20},
+	{0x3873, 0x03},
+	{0x3893, 0x00},
+	{0x3906, 0x08},
+	{0x3907, 0x01},
+	{0x391B, 0x00},
+	{0x3C09, 0x01},
+	{0x600A, 0x00},
+	{0x3008, 0xB0},
+	{0x320A, 0x01},
+	{0x320D, 0x10},
+	{0x3216, 0x2E},
+	{0x322C, 0x02},
+	{0x3409, 0x0C},
+	{0x340C, 0x2D},
+	{0x3411, 0x39},
+	{0x3414, 0x1E},
+	{0x3427, 0x04},
+	{0x3480, 0x1E},
+	{0x3484, 0x1E},
+	{0x3488, 0x1E},
+	{0x348C, 0x1E},
+	{0x3490, 0x1E},
+	{0x3494, 0x1E},
+	{0x3511, 0x8F},
+	{0x364F, 0x2D},
+
+	/* Clock Setting */
+	{0x011E, 0x18},
+	{0x011F, 0x00},
+	{0x0301, 0x05},
+	{0x0303, 0x01},
+	{0x0305, 0x0C},
+	{0x0309, 0x05},
+	{0x030B, 0x01},
+	{0x030C, 0x01},
+	{0x030D, 0xC2},
+	{0x030E, 0x01},
+	{0x3A06, 0x11},
+
+	/* Mode Settings */
+	{0x0108, 0x03},
+	{0x0112, 0x0E},
+	{0x0113, 0x0A},
+	{0x0381, 0x01},
+	{0x0383, 0x01},
+	{0x0385, 0x01},
+	{0x0387, 0x01},
+	{0x0390, 0x00},
+	{0x0391, 0x11},
+	{0x0392, 0x00},
+	{0x0401, 0x00},
+	{0x0404, 0x00},
+	{0x0405, 0x10},
+	{0x4082, 0x01},
+	{0x4083, 0x01},
+	{0x7006, 0x04},
+
+	/* Optinal/Function settings */
+	{0x0700, 0x00},
+	{0x3A63, 0x00},
+	{0x4100, 0xF8},
+	{0x4203, 0xFF},
+	{0x4344, 0x00},
+	{0x441C, 0x01},
+
+	/* Size Setting */
+	{0x0340, 0x0C},
+	{0x0341, 0xD0},
+	{0x0342, 0x11},
+	{0x0343, 0xDC},
+	{0x0344, 0x00},
+	{0x0345, 0x00},
+	{0x0346, 0x00},
+	{0x0347, 0x00},
+	{0x0348, 0x10},
+	{0x0349, 0x6F},
+	{0x034A, 0x0C},
+	{0x034B, 0x2F},
+	{0x034C, 0x10},
+	{0x034D, 0x70},
+	{0x034E, 0x0C},
+	{0x034F, 0x30},
+	{0x0350, 0x00},
+	{0x0351, 0x00},
+	{0x0352, 0x00},
+	{0x0353, 0x00},
+	{0x0354, 0x10},
+	{0x0355, 0x70},
+	{0x0356, 0x0C},
+	{0x0357, 0x30},
+	{0x301D, 0x30},
+	{0x3310, 0x10},
+	{0x3311, 0x70},
+	{0x3312, 0x0C},
+	{0x3313, 0x30},
+	{0x331C, 0x01},
+	{0x331D, 0x68},
+	{0x4084, 0x00},
+	{0x4085, 0x00},
+	{0x4086, 0x00},
+	{0x4087, 0x00},
+	{0x4400, 0x00},
+
+	/* Global Timing Setting */
+	{0x0830, 0x87},
+	{0x0831, 0x3F},
+	{0x0832, 0x67},
+	{0x0833, 0x3F},
+	{0x0834, 0x3F},
+	{0x0835, 0x4F},
+	{0x0836, 0xDF},
+	{0x0837, 0x47},
+	{0x0839, 0x1F},
+	{0x083A, 0x17},
+	{0x083B, 0x02},
+
+	/* Integration Time Setting */
+	{0x0202, 0x0C},
+	{0x0203, 0xCC},
+
+	/* Gain Setting */
+	{0x0205, 0x00},
+	{0x020E, 0x01},
+	{0x020F, 0x00},
+	{0x0210, 0x01},
+	{0x0211, 0x00},
+	{0x0212, 0x01},
+	{0x0213, 0x00},
+	{0x0214, 0x01},
+	{0x0215, 0x00},
+
+	/* HDR Setting */
+	{0x0230, 0x00},
+	{0x0231, 0x00},
+	{0x0233, 0x00},
+	{0x0234, 0x00},
+	{0x0235, 0x40},
+	{0x0238, 0x01},
+	{0x0239, 0x04},
+	{0x023B, 0x00},
+	{0x023C, 0x01},
+	{0x33B0, 0x10},
+	{0x33B1, 0x70},
+	{0x33B3, 0x01},
+	{0x33B4, 0x01},
+	{0x3800, 0x00},
+
+	{0x3A43, 0x01},
+	/* stream on */
+	{0x0100, 0x01},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+#else
+/* standard */
+static struct imx135_reg mode_4208x3120[] = {
+	/* software reset */
+	{0x0103, 0x01},
+	/* global settings */
+	{0x0101, 0x00},
+	{0x0105, 0x01},
+	{0x0110, 0x00},
+	{0x0220, 0x01},
+	{0x3302, 0x11},
+	{0x3833, 0x20},
+	{0x3893, 0x00},
+	{0x3906, 0x08},
+	{0x3907, 0x01},
+	{0x391B, 0x01},
+	{0x3C09, 0x01},
+	{0x600A, 0x00},
+	{0x3008, 0xB0},
+	{0x320A, 0x01},
+	{0x320D, 0x10},
+	{0x3216, 0x2E},
+	{0x322C, 0x02},
+	{0x3409, 0x0C},
+	{0x340C, 0x2D},
+	{0x3411, 0x39},
+	{0x3414, 0x1E},
+	{0x3427, 0x04},
+	{0x3480, 0x1E},
+	{0x3484, 0x1E},
+	{0x3488, 0x1E},
+	{0x348C, 0x1E},
+	{0x3490, 0x1E},
+	{0x3494, 0x1E},
+	{0x3511, 0x8F},
+	{0x364F, 0x2D},
+
+	/* Clock Setting */
+	{0x011E, 0x18},
+	{0x011F, 0x00},
+	{0x0301, 0x05},
+	{0x0303, 0x01},
+	{0x0305, 0x0C},
+	{0x0309, 0x05},
+	{0x030B, 0x01},
+	{0x030C, 0x01},
+	{0x030D, 0xC2},
+	{0x030E, 0x01},
+	{0x3A06, 0x11},
+
+	/* Mode Settings */
+	{0x0108, 0x03},
+	{0x0112, 0x0A},
+	{0x0113, 0x0A},
+	{0x0381, 0x01},
+	{0x0383, 0x01},
+	{0x0385, 0x01},
+	{0x0387, 0x01},
+	{0x0390, 0x00},
+	{0x0391, 0x11},
+	{0x0392, 0x00},
+	{0x0401, 0x00},
+	{0x0404, 0x00},
+	{0x0405, 0x10},
+	{0x4082, 0x01},
+	{0x4083, 0x01},
+	{0x7006, 0x04},
+
+	/* Optinal/Function settings */
+	{0x0700, 0x00},
+	{0x3A63, 0x00},
+	{0x4100, 0xF8},
+	{0x4203, 0xFF},
+	{0x4344, 0x00},
+	{0x441C, 0x01},
+
+	/* Size Setting */
+	{0x0340, 0x0C},
+	{0x0341, 0xD0},
+	{0x0342, 0x11},
+	{0x0343, 0xDC},
+	{0x0344, 0x00},
+	{0x0345, 0x00},
+	{0x0346, 0x00},
+	{0x0347, 0x00},
+	{0x0348, 0x10},
+	{0x0349, 0x6F},
+	{0x034A, 0x0C},
+	{0x034B, 0x2F},
+	{0x034C, 0x10},
+	{0x034D, 0x70},
+	{0x034E, 0x0C},
+	{0x034F, 0x30},
+	{0x0350, 0x00},
+	{0x0351, 0x00},
+	{0x0352, 0x00},
+	{0x0353, 0x00},
+	{0x0354, 0x10},
+	{0x0355, 0x70},
+	{0x0356, 0x0C},
+	{0x0357, 0x30},
+	{0x301D, 0x30},
+	{0x3310, 0x10},
+	{0x3311, 0x70},
+	{0x3312, 0x0C},
+	{0x3313, 0x30},
+	{0x331C, 0x01},
+	{0x331D, 0x68},
+	{0x4084, 0x00},
+	{0x4085, 0x00},
+	{0x4086, 0x00},
+	{0x4087, 0x00},
+	{0x4400, 0x00},
+
+	/* Global Timing Setting */
+	{0x0830, 0x87},
+	{0x0831, 0x3F},
+	{0x0832, 0x67},
+	{0x0833, 0x3F},
+	{0x0834, 0x3F},
+	{0x0835, 0x4F},
+	{0x0836, 0xDF},
+	{0x0837, 0x47},
+	{0x0839, 0x1F},
+	{0x083A, 0x17},
+	{0x083B, 0x02},
+
+	/* Integration Time Setting */
+	{0x0202, 0x0C},
+	{0x0203, 0xCC},
+
+	/* Gain Setting */
+	{0x0205, 0x04},
+	{0x020E, 0x01},
+	{0x020F, 0x00},
+	{0x0210, 0x01},
+	{0x0211, 0x00},
+	{0x0212, 0x01},
+	{0x0213, 0x00},
+	{0x0214, 0x01},
+	{0x0215, 0x00},
+
+	/* HDR Setting */
+	{0x0230, 0x00},
+	{0x0231, 0x00},
+	{0x0233, 0x00},
+	{0x0234, 0x00},
+	{0x0235, 0x40},
+	{0x0238, 0x01},
+	{0x0239, 0x04},
+	{0x023B, 0x00},
+	{0x023C, 0x01},
+	{0x33B0, 0x04},
+	{0x33B1, 0x00},
+	{0x33B3, 0x00},
+	{0x33B4, 0x01},
+	{0x3800, 0x00},
+
+	{0x3A43, 0x01},
+	/* stream on */
+	{0x0100, 0x01},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+#endif
+
+static struct imx135_reg mode_1920x1080[] = {
+	/* software reset */
+	{0x0103, 0x01},
+	/* global settings */
+	{0x0101, 0x00},
+	{0x0105, 0x01},
+	{0x0110, 0x00},
+	{0x0220, 0x01},
+	{0x3302, 0x11},
+	{0x3833, 0x20},
+	{0x3893, 0x00},
+	{0x3906, 0x08},
+	{0x3907, 0x01},
+	{0x391B, 0x01},
+	{0x3C09, 0x01},
+	{0x600A, 0x00},
+	{0x3008, 0xB0},
+	{0x320A, 0x01},
+	{0x320D, 0x10},
+	{0x3216, 0x2E},
+	{0x322C, 0x02},
+	{0x3409, 0x0C},
+	{0x340C, 0x2D},
+	{0x3411, 0x39},
+	{0x3414, 0x1E},
+	{0x3427, 0x04},
+	{0x3480, 0x1E},
+	{0x3484, 0x1E},
+	{0x3488, 0x1E},
+	{0x348C, 0x1E},
+	{0x3490, 0x1E},
+	{0x3494, 0x1E},
+	{0x3511, 0x8F},
+	{0x364F, 0x2D},
+
+	/* Clock Setting */
+	{0x011E, 0x18},
+	{0x011F, 0x00},
+	{0x0301, 0x05},
+	{0x0303, 0x01},
+	{0x0305, 0x0C},
+	{0x0309, 0x05},
+	{0x030B, 0x02},
+	{0x030C, 0x01},
+	{0x030D, 0xC2},
+	{0x030E, 0x01},
+	{0x3A06, 0x12},
+
+	/* Mode Settings */
+	{0x0108, 0x03},
+	{0x0112, 0x0A},
+	{0x0113, 0x0A},
+	{0x0381, 0x01},
+	{0x0383, 0x01},
+	{0x0385, 0x01},
+	{0x0387, 0x01},
+	{0x0390, 0x01},
+	{0x0391, 0x22},
+	{0x0392, 0x00},
+	{0x0401, 0x02},
+	{0x0404, 0x00},
+	{0x0405, 0x11},
+	{0x4082, 0x00},
+	{0x4083, 0x00},
+	{0x7006, 0x04},
+
+	/* Optinal/Function settings */
+	{0x0700, 0x00},
+	{0x3A63, 0x00},
+	{0x4100, 0xF8},
+	{0x4203, 0xFF},
+	{0x4344, 0x00},
+	{0x441C, 0x01},
+
+	/* Size Setting */
+	{0x0340, 0x0A},
+	{0x0341, 0x40},
+	{0x0342, 0x11},
+	{0x0343, 0xDC},
+	{0x0344, 0x00},
+	{0x0345, 0x40},
+	{0x0346, 0x01},
+	{0x0347, 0x9C},
+	{0x0348, 0x10},
+	{0x0349, 0x2F},
+	{0x034A, 0x0A},
+	{0x034B, 0x93},
+	{0x034C, 0x07},
+	{0x034D, 0x80},
+	{0x034E, 0x04},
+	{0x034F, 0x38},
+	{0x0350, 0x00},
+	{0x0351, 0x00},
+	{0x0352, 0x00},
+	{0x0353, 0x00},
+	{0x0354, 0x07},
+	{0x0355, 0xF8},
+	{0x0356, 0x04},
+	{0x0357, 0x7C},
+	{0x301D, 0x30},
+	{0x3310, 0x07},
+	{0x3311, 0x80},
+	{0x3312, 0x04},
+	{0x3313, 0x38},
+	{0x331C, 0x00},
+	{0x331D, 0xD2},
+	{0x4084, 0x07},
+	{0x4085, 0x80},
+	{0x4086, 0x04},
+	{0x4087, 0x38},
+	{0x4400, 0x00},
+
+	/* Global Timing Setting */
+	{0x0830, 0x67},
+	{0x0831, 0x27},
+	{0x0832, 0x47},
+	{0x0833, 0x27},
+	{0x0834, 0x27},
+	{0x0835, 0x1F},
+	{0x0836, 0x87},
+	{0x0837, 0x2F},
+	{0x0839, 0x1F},
+	{0x083A, 0x17},
+	{0x083B, 0x02},
+
+	/* Integration Time Setting */
+	{0x0202, 0x0A},
+	{0x0203, 0x3C},
+
+	/* Gain Setting */
+	{0x0205, 0x00},
+	{0x020E, 0x01},
+	{0x020F, 0x00},
+	{0x0210, 0x01},
+	{0x0211, 0x00},
+	{0x0212, 0x01},
+	{0x0213, 0x00},
+	{0x0214, 0x01},
+	{0x0215, 0x00},
+
+	/* HDR Setting */
+	{0x0230, 0x00},
+	{0x0231, 0x00},
+	{0x0233, 0x00},
+	{0x0234, 0x00},
+	{0x0235, 0x40},
+	{0x0238, 0x01},
+	{0x0239, 0x04},
+	{0x023B, 0x00},
+	{0x023C, 0x01},
+	{0x33B0, 0x04},
+	{0x33B1, 0x00},
+	{0x33B3, 0x00},
+	{0x33B4, 0x01},
+	{0x3800, 0x00},
+
+	{0x3A43, 0x01},
+	/* stream on */
+	{0x0100, 0x01},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+
+#ifdef IMX135_1280x720_90_FPS
+/* 720p 90fps */
+static struct imx135_reg mode_1280x720[] = {
+	/* software reset */
+	{0x0103, 0x01},
+	/* global settings */
+	{0x0101, 0x00},
+	{0x0105, 0x01},
+	{0x0110, 0x00},
+	{0x0220, 0x01},
+	{0x3302, 0x11},
+	{0x3833, 0x20},
+	{0x3893, 0x00},
+	{0x3906, 0x08},
+	{0x3907, 0x01},
+	{0x391B, 0x01},
+	{0x3C09, 0x01},
+	{0x600A, 0x00},
+	{0x3008, 0xB0},
+	{0x320A, 0x01},
+	{0x320D, 0x10},
+	{0x3216, 0x2E},
+	{0x322C, 0x02},
+	{0x3409, 0x0C},
+	{0x340C, 0x2D},
+	{0x3411, 0x39},
+	{0x3414, 0x1E},
+	{0x3427, 0x04},
+	{0x3480, 0x1E},
+	{0x3484, 0x1E},
+	{0x3488, 0x1E},
+	{0x348C, 0x1E},
+	{0x3490, 0x1E},
+	{0x3494, 0x1E},
+	{0x3511, 0x8F},
+	{0x364F, 0x2D},
+
+	/* Clock Setting */
+	{0x011E, 0x18},
+	{0x011F, 0x00},
+	{0x0301, 0x05},
+	{0x0303, 0x01},
+	{0x0305, 0x0C},
+	{0x0309, 0x05},
+	{0x030B, 0x02},
+	{0x030C, 0x01},
+	{0x030D, 0xC2},
+	{0x030E, 0x01},
+	{0x3A06, 0x12},
+
+	/* Mode Settings */
+	{0x0108, 0x03},
+	{0x0112, 0x0A},
+	{0x0113, 0x0A},
+	{0x0381, 0x01},
+	{0x0383, 0x01},
+	{0x0385, 0x01},
+	{0x0387, 0x01},
+	{0x0390, 0x01},
+	{0x0391, 0x22},
+	{0x0392, 0x00},
+	{0x0401, 0x00},
+	{0x0404, 0x00},
+	{0x0405, 0x10},
+	{0x4082, 0x01},
+	{0x4083, 0x01},
+	{0x7006, 0x04},
+
+	/* Optinal/Function settings */
+	{0x0700, 0x00},
+	{0x3A63, 0x00},
+	{0x4100, 0xF8},
+	{0x4203, 0xFF},
+	{0x4344, 0x00},
+	{0x441C, 0x01},
+
+	/* Size Setting */
+	{0x0340, 0x03},
+	{0x0341, 0x6A},
+	{0x0342, 0x11},
+	{0x0343, 0xDC},
+	{0x0344, 0x03},
+	{0x0345, 0x38},
+	{0x0346, 0x03},
+	{0x0347, 0x48},
+	{0x0348, 0x0D},
+	{0x0349, 0x37},
+	{0x034A, 0x08},
+	{0x034B, 0xE7},
+	{0x034C, 0x05},
+	{0x034D, 0x00},
+	{0x034E, 0x02},
+	{0x034F, 0xD0},
+	{0x0350, 0x00},
+	{0x0351, 0x00},
+	{0x0352, 0x00},
+	{0x0353, 0x00},
+	{0x0354, 0x05},
+	{0x0355, 0x00},
+	{0x0356, 0x02},
+	{0x0357, 0xD0},
+	{0x301D, 0x30},
+	{0x3310, 0x05},
+	{0x3311, 0x00},
+	{0x3312, 0x02},
+	{0x3313, 0xD0},
+	{0x331C, 0x00},
+	{0x331D, 0x10},
+	{0x4084, 0x00},
+	{0x4085, 0x00},
+	{0x4086, 0x00},
+	{0x4087, 0x00},
+	{0x4400, 0x00},
+
+	/* Global Timing Setting */
+	{0x0830, 0x67},
+	{0x0831, 0x27},
+	{0x0832, 0x47},
+	{0x0833, 0x27},
+	{0x0834, 0x27},
+	{0x0835, 0x1F},
+	{0x0836, 0x87},
+	{0x0837, 0x2F},
+	{0x0839, 0x1F},
+	{0x083A, 0x17},
+	{0x083B, 0x02},
+
+	/* Integration Time Setting */
+	{0x0202, 0x03},
+	{0x0203, 0x66},
+
+	/* Gain Setting */
+	{0x0205, 0x00},
+	{0x020E, 0x01},
+	{0x020F, 0x00},
+	{0x0210, 0x01},
+	{0x0211, 0x00},
+	{0x0212, 0x01},
+	{0x0213, 0x00},
+	{0x0214, 0x01},
+	{0x0215, 0x00},
+
+	/* HDR Setting */
+	{0x0230, 0x00},
+	{0x0231, 0x00},
+	{0x0233, 0x00},
+	{0x0234, 0x00},
+	{0x0235, 0x40},
+	{0x0238, 0x01},
+	{0x0239, 0x04},
+	{0x023B, 0x00},
+	{0x023C, 0x01},
+	{0x33B0, 0x04},
+	{0x33B1, 0x00},
+	{0x33B3, 0x00},
+	{0x33B4, 0x01},
+	{0x3800, 0x00},
+
+	{0x3A43, 0x01},
+	/* stream on */
+	{0x0100, 0x01},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+#else
+/* 720p 30fps */
+static struct imx135_reg mode_1280x720[] = {
+	/* software reset */
+	{0x0103, 0x01},
+	/* global settings */
+	{0x0101, 0x00},
+	{0x0105, 0x01},
+	{0x0110, 0x00},
+	{0x0220, 0x01},
+	{0x3302, 0x11},
+	{0x3833, 0x20},
+	{0x3893, 0x00},
+	{0x3906, 0x08},
+	{0x3907, 0x01},
+	{0x391B, 0x01},
+	{0x3C09, 0x01},
+	{0x600A, 0x00},
+	{0x3008, 0xB0},
+	{0x320A, 0x01},
+	{0x320D, 0x10},
+	{0x3216, 0x2E},
+	{0x322C, 0x02},
+	{0x3409, 0x0C},
+	{0x340C, 0x2D},
+	{0x3411, 0x39},
+	{0x3414, 0x1E},
+	{0x3427, 0x04},
+	{0x3480, 0x1E},
+	{0x3484, 0x1E},
+	{0x3488, 0x1E},
+	{0x348C, 0x1E},
+	{0x3490, 0x1E},
+	{0x3494, 0x1E},
+	{0x3511, 0x8F},
+	{0x364F, 0x2D},
+
+	/* Clock Setting */
+	{0x011E, 0x18},
+	{0x011F, 0x00},
+	{0x0301, 0x05},
+	{0x0303, 0x01},
+	{0x0305, 0x0C},
+	{0x0309, 0x05},
+	{0x030B, 0x02},
+	{0x030C, 0x01},
+	{0x030D, 0xC2},
+	{0x030E, 0x01},
+	{0x3A06, 0x12},
+
+	/* Mode Settings */
+	{0x0108, 0x03},
+	{0x0112, 0x0A},
+	{0x0113, 0x0A},
+	{0x0381, 0x01},
+	{0x0383, 0x01},
+	{0x0385, 0x01},
+	{0x0387, 0x01},
+	{0x0390, 0x01},
+	{0x0391, 0x22},
+	{0x0392, 0x00},
+	{0x0401, 0x02},
+	{0x0404, 0x00},
+	{0x0405, 0x1A},
+	{0x4082, 0x00},
+	{0x4083, 0x00},
+	{0x7006, 0x04},
+
+	/* Optinal/Function settings */
+	{0x0700, 0x00},
+	{0x3A63, 0x00},
+	{0x4100, 0xF8},
+	{0x4203, 0xFF},
+	{0x4344, 0x00},
+	{0x441C, 0x01},
+
+	/* Size Setting */
+	{0x0340, 0x0A},
+	{0x0341, 0x40},
+	{0x0342, 0x11},
+	{0x0343, 0xDC},
+	{0x0344, 0x00},
+	{0x0345, 0x18},
+	{0x0346, 0x01},
+	{0x0347, 0x88},
+	{0x0348, 0x10},
+	{0x0349, 0x57},
+	{0x034A, 0x0A},
+	{0x034B, 0xAB},
+	{0x034C, 0x05},
+	{0x034D, 0x00},
+	{0x034E, 0x02},
+	{0x034F, 0xD0},
+	{0x0350, 0x00},
+	{0x0351, 0x00},
+	{0x0352, 0x00},
+	{0x0353, 0x00},
+	{0x0354, 0x08},
+	{0x0355, 0x20},
+	{0x0356, 0x04},
+	{0x0357, 0x92},
+	{0x301D, 0x30},
+	{0x3310, 0x05},
+	{0x3311, 0x00},
+	{0x3312, 0x02},
+	{0x3313, 0xD0},
+	{0x331C, 0x02},
+	{0x331D, 0x18},
+	{0x4084, 0x05},
+	{0x4085, 0x00},
+	{0x4086, 0x02},
+	{0x4087, 0xD0},
+	{0x4400, 0x00},
+
+	/* Global Timing Setting */
+	{0x0830, 0x67},
+	{0x0831, 0x27},
+	{0x0832, 0x47},
+	{0x0833, 0x27},
+	{0x0834, 0x27},
+	{0x0835, 0x1F},
+	{0x0836, 0x87},
+	{0x0837, 0x2F},
+	{0x0839, 0x1F},
+	{0x083A, 0x17},
+	{0x083B, 0x02},
+
+	/* Integration Time Setting */
+	{0x0202, 0x0A},
+	{0x0203, 0x3C},
+
+	/* Gain Setting */
+	{0x0205, 0x00},
+	{0x020E, 0x01},
+	{0x020F, 0x00},
+	{0x0210, 0x01},
+	{0x0211, 0x00},
+	{0x0212, 0x01},
+	{0x0213, 0x00},
+	{0x0214, 0x01},
+	{0x0215, 0x00},
+
+	/* HDR Setting */
+	{0x0230, 0x00},
+	{0x0231, 0x00},
+	{0x0233, 0x00},
+	{0x0234, 0x00},
+	{0x0235, 0x40},
+	{0x0238, 0x01},
+	{0x0239, 0x04},
+	{0x023B, 0x00},
+	{0x023C, 0x01},
+	{0x33B0, 0x04},
+	{0x33B1, 0x00},
+	{0x33B3, 0x00},
+	{0x33B4, 0x01},
+	{0x3800, 0x00},
+
+	{0x3A43, 0x01},
+	/* stream on */
+	{0x0100, 0x01},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+#endif
+
+static struct imx135_reg mode_2616x1472[] = {
+	/* software reset */
+	{0x0103, 0x01},
+	/* global settings */
+	{0x0101, 0x00},
+	{0x0105, 0x01},
+	{0x0110, 0x00},
+	{0x0220, 0x01},
+	{0x3302, 0x11},
+	{0x3833, 0x20},
+	{0x3873, 0x03},
+	{0x3893, 0x00},
+	{0x3906, 0x08},
+	{0x3907, 0x01},
+	{0x391B, 0x00},
+	{0x3C09, 0x01},
+	{0x600A, 0x00},
+	{0x3008, 0xB0},
+	{0x320A, 0x01},
+	{0x320D, 0x10},
+	{0x3216, 0x2E},
+	{0x322C, 0x02},
+	{0x3409, 0x0C},
+	{0x340C, 0x2D},
+	{0x3411, 0x39},
+	{0x3414, 0x1E},
+	{0x3427, 0x04},
+	{0x3480, 0x1E},
+	{0x3484, 0x1E},
+	{0x3488, 0x1E},
+	{0x348C, 0x1E},
+	{0x3490, 0x1E},
+	{0x3494, 0x1E},
+	{0x3511, 0x8F},
+	{0x364F, 0x2D},
+
+	/* Clock Setting */
+	{0x011E, 0x18},
+	{0x011F, 0x00},
+	{0x0301, 0x05},
+	{0x0303, 0x01},
+	{0x0305, 0x0C},
+	{0x0309, 0x05},
+	{0x030B, 0x01},
+	{0x030C, 0x01},
+	{0x030D, 0xC2},
+	{0x030E, 0x01},
+	{0x3A06, 0x11},
+
+	/* Mode Settings */
+	{0x0108, 0x03},
+	{0x0112, 0x0E},
+	{0x0113, 0x0A},
+	{0x0381, 0x01},
+	{0x0383, 0x01},
+	{0x0385, 0x01},
+	{0x0387, 0x01},
+	{0x0390, 0x00},
+	{0x0391, 0x11},
+	{0x0392, 0x00},
+	{0x0401, 0x00},
+	{0x0404, 0x00},
+	{0x0405, 0x10},
+	{0x4082, 0x01},
+	{0x4083, 0x01},
+	{0x7006, 0x04},
+
+	/* Optinal/Function settings */
+	{0x0700, 0x00},
+	{0x3A63, 0x00},
+	{0x4100, 0xF8},
+	{0x4203, 0xFF},
+	{0x4344, 0x00},
+	{0x441C, 0x01},
+
+	/* Size Setting */
+	{0x0340, 0x0A},
+	{0x0341, 0x40},
+	{0x0342, 0x11},
+	{0x0343, 0xDC},
+	{0x0344, 0x03},
+	{0x0345, 0x1C},
+	{0x0346, 0x03},
+	{0x0347, 0x38},
+	{0x0348, 0x0D},
+	{0x0349, 0x53},
+	{0x034A, 0x08},
+	{0x034B, 0xF7},
+	{0x034C, 0x0A},
+	{0x034D, 0x38},
+	{0x034E, 0x05},
+	{0x034F, 0xC0},
+	{0x0350, 0x00},
+	{0x0351, 0x00},
+	{0x0352, 0x00},
+	{0x0353, 0x00},
+	{0x0354, 0x0A},
+	{0x0355, 0x38},
+	{0x0356, 0x05},
+	{0x0357, 0xC0},
+	{0x301D, 0x30},
+	{0x3310, 0x0A},
+	{0x3311, 0x38},
+	{0x3312, 0x05},
+	{0x3313, 0xC0},
+	{0x331C, 0x08},
+	{0x331D, 0xD4},
+	{0x4084, 0x00},
+	{0x4085, 0x00},
+	{0x4086, 0x00},
+	{0x4087, 0x00},
+	{0x4400, 0x00},
+
+	/* Global Timing Setting */
+	{0x0830, 0x87},
+	{0x0831, 0x3F},
+	{0x0832, 0x67},
+	{0x0833, 0x3F},
+	{0x0834, 0x3F},
+	{0x0835, 0x4F},
+	{0x0836, 0xDF},
+	{0x0837, 0x47},
+	{0x0839, 0x1F},
+	{0x083A, 0x17},
+	{0x083B, 0x02},
+
+	/* Integration Time Setting */
+	{0x0202, 0x0A},
+	{0x0203, 0x3C},
+
+	/* Gain Setting */
+	{0x0205, 0x00},
+	{0x020E, 0x01},
+	{0x020F, 0x00},
+	{0x0210, 0x01},
+	{0x0211, 0x00},
+	{0x0212, 0x01},
+	{0x0213, 0x00},
+	{0x0214, 0x01},
+	{0x0215, 0x00},
+
+	/* HDR Setting */
+	{0x0230, 0x00},
+	{0x0231, 0x00},
+	{0x0233, 0x00},
+	{0x0234, 0x00},
+	{0x0235, 0x40},
+	{0x0238, 0x01},
+	{0x0239, 0x04},
+	{0x023B, 0x00},
+	{0x023C, 0x01},
+	{0x33B0, 0x0A},
+	{0x33B1, 0x38},
+	{0x33B3, 0x01},
+	{0x33B4, 0x01},
+	{0x3800, 0x00},
+
+	{0x3A43, 0x01},
+	/* stream on */
+	{0x0100, 0x01},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+
+static struct imx135_reg mode_3896x2192[] = {
+	/* software reset */
+	{0x0103, 0x01},
+	/* global settings */
+	{0x0101, 0x00},
+	{0x0105, 0x01},
+	{0x0110, 0x00},
+	{0x0220, 0x01},
+	{0x3302, 0x11},
+	{0x3833, 0x20},
+	{0x3873, 0x03},
+	{0x3893, 0x00},
+	{0x3906, 0x08},
+	{0x3907, 0x01},
+	{0x391B, 0x00},
+	{0x3C09, 0x01},
+	{0x600A, 0x00},
+	{0x3008, 0xB0},
+	{0x320A, 0x01},
+	{0x320D, 0x10},
+	{0x3216, 0x2E},
+	{0x322C, 0x02},
+	{0x3409, 0x0C},
+	{0x340C, 0x2D},
+	{0x3411, 0x39},
+	{0x3414, 0x1E},
+	{0x3427, 0x04},
+	{0x3480, 0x1E},
+	{0x3484, 0x1E},
+	{0x3488, 0x1E},
+	{0x348C, 0x1E},
+	{0x3490, 0x1E},
+	{0x3494, 0x1E},
+	{0x3511, 0x8F},
+	{0x364F, 0x2D},
+
+	/* Clock Setting */
+	{0x011E, 0x18},
+	{0x011F, 0x00},
+	{0x0301, 0x05},
+	{0x0303, 0x01},
+	{0x0305, 0x0C},
+	{0x0309, 0x05},
+	{0x030B, 0x01},
+	{0x030C, 0x01},
+	{0x030D, 0xC2},
+	{0x030E, 0x01},
+	{0x3A06, 0x11},
+
+	/* Mode Settings */
+	{0x0108, 0x03},
+	{0x0112, 0x0E},
+	{0x0113, 0x0A},
+	{0x0381, 0x01},
+	{0x0383, 0x01},
+	{0x0385, 0x01},
+	{0x0387, 0x01},
+	{0x0390, 0x00},
+	{0x0391, 0x11},
+	{0x0392, 0x00},
+	{0x0401, 0x00},
+	{0x0404, 0x00},
+	{0x0405, 0x10},
+	{0x4082, 0x01},
+	{0x4083, 0x01},
+	{0x7006, 0x04},
+
+	/* Optinal/Function settings */
+	{0x0700, 0x00},
+	{0x3A63, 0x00},
+	{0x4100, 0xF8},
+	{0x4203, 0xFF},
+	{0x4344, 0x00},
+	{0x441C, 0x01},
+
+	/* Size Setting */
+	{0x0340, 0x0A},
+	{0x0341, 0x40},
+	{0x0342, 0x11},
+	{0x0343, 0xDC},
+	{0x0344, 0x00},
+	{0x0345, 0x9C},
+	{0x0346, 0x01},
+	{0x0347, 0xD0},
+	{0x0348, 0x0F},
+	{0x0349, 0xD3},
+	{0x034A, 0x0A},
+	{0x034B, 0x5F},
+	{0x034C, 0x0F},
+	{0x034D, 0x38},
+	{0x034E, 0x08},
+	{0x034F, 0x90},
+	{0x0350, 0x00},
+	{0x0351, 0x00},
+	{0x0352, 0x00},
+	{0x0353, 0x00},
+	{0x0354, 0x0F},
+	{0x0355, 0x38},
+	{0x0356, 0x08},
+	{0x0357, 0x90},
+	{0x301D, 0x30},
+	{0x3310, 0x0F},
+	{0x3311, 0x38},
+	{0x3312, 0x08},
+	{0x3313, 0x90},
+	{0x331C, 0x0F},
+	{0x331D, 0x32},
+	{0x4084, 0x00},
+	{0x4085, 0x00},
+	{0x4086, 0x00},
+	{0x4087, 0x00},
+	{0x4400, 0x00},
+
+	/* Global Timing Setting */
+	{0x0830, 0x87},
+	{0x0831, 0x3F},
+	{0x0832, 0x67},
+	{0x0833, 0x3F},
+	{0x0834, 0x3F},
+	{0x0835, 0x4F},
+	{0x0836, 0xDF},
+	{0x0837, 0x47},
+	{0x0839, 0x1F},
+	{0x083A, 0x17},
+	{0x083B, 0x02},
+
+	/* Integration Time Setting */
+	{0x0202, 0x0A},
+	{0x0203, 0x3C},
+
+	/* Gain Setting */
+	{0x0205, 0x00},
+	{0x020E, 0x01},
+	{0x020F, 0x00},
+	{0x0210, 0x01},
+	{0x0211, 0x00},
+	{0x0212, 0x01},
+	{0x0213, 0x00},
+	{0x0214, 0x01},
+	{0x0215, 0x00},
+
+	/* HDR Setting */
+	{0x0230, 0x00},
+	{0x0231, 0x00},
+	{0x0233, 0x00},
+	{0x0234, 0x00},
+	{0x0235, 0x40},
+	{0x0238, 0x01},
+	{0x0239, 0x04},
+	{0x023B, 0x00},
+	{0x023C, 0x01},
+	{0x33B0, 0x0F},
+	{0x33B1, 0x38},
+	{0x33B3, 0x01},
+	{0x33B4, 0x01},
+	{0x3800, 0x00},
+
+	{0x3A43, 0x01},
+	/* stream on */
+	{0x0100, 0x01},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+
+static struct imx135_reg mode_quality_hdr[] = {
+	/* defect correction */
+	{0x380A, 0x00},
+	{0x380B, 0x00},
+	{0x4103, 0x00},
+	/* color artifact */
+	{0x4243, 0x9A},
+	{0x4330, 0x01},
+	{0x4331, 0x90},
+	{0x4332, 0x02},
+	{0x4333, 0x58},
+	{0x4334, 0x03},
+	{0x4335, 0x20},
+	{0x4336, 0x03},
+	{0x4337, 0x84},
+	{0x433C, 0x01},
+	{0x4340, 0x02},
+	{0x4341, 0x58},
+	{0x4342, 0x03},
+	{0x4343, 0x52},
+	/* moire reduction */
+	{0x4364, 0x0B},
+	{0x4368, 0x00},
+	{0x4369, 0x0F},
+	{0x436A, 0x03},
+	{0x436B, 0xA8},
+	{0x436C, 0x00},
+	{0x436D, 0x00},
+	{0x436E, 0x00},
+	{0x436F, 0x06},
+	/* CNR parameter */
+	{0x4281, 0x21},
+	{0x4282, 0x18},
+	{0x4283, 0x04},
+	{0x4284, 0x08},
+	{0x4287, 0x7F},
+	{0x4288, 0x08},
+	{0x428B, 0x7F},
+	{0x428C, 0x08},
+	{0x428F, 0x7F},
+	{0x4297, 0x00},
+	{0x4298, 0x7E},
+	{0x4299, 0x7E},
+	{0x429A, 0x7E},
+	{0x42A4, 0xFB},
+	{0x42A5, 0x7E},
+	{0x42A6, 0xDF},
+	{0x42A7, 0xB7},
+	{0x42AF, 0x03},
+
+	/* ARNR Parameter Settings */
+	{0x4207, 0x03},
+	{0x4216, 0x08},
+	{0x4217, 0x08},
+
+	/* DLC parameter */
+	{0x4218, 0x00},
+	{0x421B, 0x20},
+	{0x421F, 0x04},
+	{0x4222, 0x02},
+	{0x4223, 0x22},
+	{0x422E, 0x54},
+	{0x422F, 0xFB},
+	{0x4230, 0xFF},
+	{0x4231, 0xFE},
+	{0x4232, 0xFF},
+	{0x4235, 0x58},
+	{0x4236, 0xF7},
+	{0x4237, 0xFD},
+	{0x4239, 0x4E},
+	{0x423A, 0xFC},
+	{0x423B, 0xFD},
+
+	/* HDR Setting */
+	{0x4300, 0x00},
+	{0x4316, 0x12},
+	{0x4317, 0x22},
+	{0x4318, 0x00},
+	{0x4319, 0x00},
+	{0x431A, 0x00},
+	{0x4324, 0x03},
+	{0x4325, 0x20},
+	{0x4326, 0x03},
+	{0x4327, 0x84},
+	{0x4328, 0x03},
+	{0x4329, 0x20},
+	{0x432A, 0x03},
+	{0x432B, 0x20},
+	{0x432C, 0x01},
+	{0x432D, 0x01},
+	{0x4338, 0x02},
+	{0x4339, 0x00},
+	{0x433A, 0x00},
+	{0x433B, 0x02},
+	{0x435A, 0x03},
+	{0x435B, 0x84},
+	{0x435E, 0x01},
+	{0x435F, 0xFF},
+	{0x4360, 0x01},
+	{0x4361, 0xF4},
+	{0x4362, 0x03},
+	{0x4363, 0x84},
+	{0x437B, 0x01},
+	{0x4401, 0x3F},
+	{0x4402, 0xFF},
+	{0x4404, 0x13},
+	{0x4405, 0x26},
+	{0x4406, 0x07},
+	{0x4408, 0x20},
+	{0x4409, 0xE5},
+	{0x440A, 0xFB},
+	{0x440C, 0xF6},
+	{0x440D, 0xEA},
+	{0x440E, 0x20},
+	{0x4410, 0x00},
+	{0x4411, 0x00},
+	{0x4412, 0x3F},
+	{0x4413, 0xFF},
+	{0x4414, 0x1F},
+	{0x4415, 0xFF},
+	{0x4416, 0x20},
+	{0x4417, 0x00},
+	{0x4418, 0x1F},
+	{0x4419, 0xFF},
+	{0x441A, 0x20},
+	{0x441B, 0x00},
+	{0x441D, 0x40},
+	{0x441E, 0x1E},
+	{0x441F, 0x38},
+	{0x4420, 0x01},
+	{0x4444, 0x00},
+	{0x4445, 0x00},
+	{0x4446, 0x1D},
+	{0x4447, 0xF9},
+	{0x4452, 0x00},
+	{0x4453, 0xA0},
+	{0x4454, 0x08},
+	{0x4455, 0x00},
+	{0x4456, 0x0F},
+	{0x4457, 0xFF},
+	{0x4458, 0x18},
+	{0x4459, 0x18},
+	{0x445A, 0x3F},
+	{0x445B, 0x3A},
+	{0x445C, 0x00},
+	{0x445D, 0x28},
+	{0x445E, 0x01},
+	{0x445F, 0x90},
+	{0x4460, 0x00},
+	{0x4461, 0x60},
+	{0x4462, 0x00},
+	{0x4463, 0x00},
+	{0x4464, 0x00},
+	{0x4465, 0x00},
+	{0x446C, 0x01},
+	{0x446D, 0x00},
+	{0x446E, 0x00},
+
+	/* LSC setting */
+	{0x452A, 0x02},
+
+	/* White balance */
+	{0x0712, 0x01},
+	{0x0713, 0x00},
+	{0x0714, 0x01},
+	{0x0715, 0x00},
+	{0x0716, 0x01},
+	{0x0717, 0x00},
+	{0x0718, 0x01},
+	{0x0719, 0x00},
+
+	/* Shading */
+	{0x4500, 0x1F},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+
+static struct imx135_reg mode_quality[] = {
+	/* defect correction */
+	{0x380A, 0x00},
+	{0x380B, 0x00},
+	{0x4103, 0x00},
+	/* color artifact */
+	{0x4243, 0x9A},
+	{0x4330, 0x01},
+	{0x4331, 0x90},
+	{0x4332, 0x02},
+	{0x4333, 0x58},
+	{0x4334, 0x03},
+	{0x4335, 0x20},
+	{0x4336, 0x03},
+	{0x4337, 0x84},
+	{0x433C, 0x01},
+	{0x4340, 0x02},
+	{0x4341, 0x58},
+	{0x4342, 0x03},
+	{0x4343, 0x52},
+	/* moire reduction */
+	{0x4364, 0x0B},
+	{0x4368, 0x00},
+	{0x4369, 0x0F},
+	{0x436A, 0x03},
+	{0x436B, 0xA8},
+	{0x436C, 0x00},
+	{0x436D, 0x00},
+	{0x436E, 0x00},
+	{0x436F, 0x06},
+	/* CNR parameter */
+	{0x4281, 0x21},
+	{0x4282, 0x18},
+	{0x4283, 0x04},
+	{0x4284, 0x08},
+	{0x4287, 0x7F},
+	{0x4288, 0x08},
+	{0x428B, 0x7F},
+	{0x428C, 0x08},
+	{0x428F, 0x7F},
+	{0x4297, 0x00},
+	{0x4298, 0x7E},
+	{0x4299, 0x7E},
+	{0x429A, 0x7E},
+	{0x42A4, 0xFB},
+	{0x42A5, 0x7E},
+	{0x42A6, 0xDF},
+	{0x42A7, 0xB7},
+	{0x42AF, 0x03},
+
+	/* ARNR Parameter Settings */
+	{0x4207, 0x03},
+	{0x4216, 0x08},
+	{0x4217, 0x08},
+
+	/* DLC parameter */
+	{0x4218, 0x00},
+	{0x421B, 0x20},
+	{0x421F, 0x04},
+	{0x4222, 0x02},
+	{0x4223, 0x22},
+	{0x422E, 0x54},
+	{0x422F, 0xFB},
+	{0x4230, 0xFF},
+	{0x4231, 0xFE},
+	{0x4232, 0xFF},
+	{0x4235, 0x58},
+	{0x4236, 0xF7},
+	{0x4237, 0xFD},
+	{0x4239, 0x4E},
+	{0x423A, 0xFC},
+	{0x423B, 0xFD},
+
+	/* HDR Setting */
+	{0x4300, 0x00},
+	{0x4316, 0x12},
+	{0x4317, 0x22},
+	{0x4318, 0x00},
+	{0x4319, 0x00},
+	{0x431A, 0x00},
+	{0x4324, 0x03},
+	{0x4325, 0x20},
+	{0x4326, 0x03},
+	{0x4327, 0x84},
+	{0x4328, 0x03},
+	{0x4329, 0x20},
+	{0x432A, 0x03},
+	{0x432B, 0x20},
+	{0x432C, 0x01},
+	{0x432D, 0x01},
+	{0x4338, 0x02},
+	{0x4339, 0x00},
+	{0x433A, 0x00},
+	{0x433B, 0x02},
+	{0x435A, 0x03},
+	{0x435B, 0x84},
+	{0x435E, 0x01},
+	{0x435F, 0xFF},
+	{0x4360, 0x01},
+	{0x4361, 0xF4},
+	{0x4362, 0x03},
+	{0x4363, 0x84},
+	{0x437B, 0x01},
+	{0x4401, 0x3F},
+	{0x4402, 0xFF},
+	{0x4404, 0x13},
+	{0x4405, 0x26},
+	{0x4406, 0x07},
+	{0x4408, 0x20},
+	{0x4409, 0xE5},
+	{0x440A, 0xFB},
+	{0x440C, 0xF6},
+	{0x440D, 0xEA},
+	{0x440E, 0x20},
+	{0x4410, 0x00},
+	{0x4411, 0x00},
+	{0x4412, 0x3F},
+	{0x4413, 0xFF},
+	{0x4414, 0x1F},
+	{0x4415, 0xFF},
+	{0x4416, 0x20},
+	{0x4417, 0x00},
+	{0x4418, 0x1F},
+	{0x4419, 0xFF},
+	{0x441A, 0x20},
+	{0x441B, 0x00},
+	{0x441D, 0x40},
+	{0x441E, 0x1E},
+	{0x441F, 0x38},
+	{0x4420, 0x01},
+	{0x4444, 0x00},
+	{0x4445, 0x00},
+	{0x4446, 0x1D},
+	{0x4447, 0xF9},
+	{0x4452, 0x00},
+	{0x4453, 0xA0},
+	{0x4454, 0x08},
+	{0x4455, 0x00},
+	{0x4456, 0x0F},
+	{0x4457, 0xFF},
+	{0x4458, 0x18},
+	{0x4459, 0x18},
+	{0x445A, 0x3F},
+	{0x445B, 0x3A},
+	{0x445C, 0x00},
+	{0x445D, 0x28},
+	{0x445E, 0x01},
+	{0x445F, 0x90},
+	{0x4460, 0x00},
+	{0x4461, 0x60},
+	{0x4462, 0x00},
+	{0x4463, 0x00},
+	{0x4464, 0x00},
+	{0x4465, 0x00},
+	{0x446C, 0x01},
+	{0x446D, 0x00},
+	{0x446E, 0x00},
+
+	/* LSC setting */
+	{0x452A, 0x02},
+
+	/* White balance */
+	{0x0712, 0x01},
+	{0x0713, 0x00},
+	{0x0714, 0x01},
+	{0x0715, 0x00},
+	{0x0716, 0x01},
+	{0x0717, 0x00},
+	{0x0718, 0x01},
+	{0x0719, 0x00},
+
+	/* Shading */
+	{0x4500, 0x1F},
+
+	{IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+	{IMX135_TABLE_END, 0x00}
+};
+
+enum {
+	IMX135_MODE_4208X3120,
+	IMX135_MODE_1920X1080,
+	IMX135_MODE_1280X720,
+	IMX135_MODE_2616X1472,
+	IMX135_MODE_3896X2192,
+	IMX135_MODE_QUALITY_HDR,
+	IMX135_MODE_QUALITY,
+};
+
+static struct imx135_reg *mode_table[] = {
+	[IMX135_MODE_4208X3120] = mode_4208x3120,
+	[IMX135_MODE_1920X1080] = mode_1920x1080,
+	[IMX135_MODE_1280X720]  = mode_1280x720,
+	[IMX135_MODE_2616X1472]  = mode_2616x1472,
+	[IMX135_MODE_3896X2192]  = mode_3896x2192,
+	[IMX135_MODE_QUALITY_HDR]  = mode_quality_hdr,
+	[IMX135_MODE_QUALITY]  = mode_quality,
+};
+
+static inline void
+msleep_range(unsigned int delay_base)
+{
+	usleep_range(delay_base*1000, delay_base*1000+500);
+}
+
+static inline void
+imx135_get_frame_length_regs(struct imx135_reg *regs, u32 frame_length)
+{
+	regs->addr = 0x0340;
+	regs->val = (frame_length >> 8) & 0xff;
+	(regs + 1)->addr = 0x0341;
+	(regs + 1)->val = (frame_length) & 0xff;
+}
+
+static inline void
+imx135_get_coarse_time_regs(struct imx135_reg *regs, u32 coarse_time)
+{
+	regs->addr = 0x202;
+	regs->val = (coarse_time >> 8) & 0xff;
+	(regs + 1)->addr = 0x203;
+	(regs + 1)->val = (coarse_time) & 0xff;
+}
+
+static inline void
+imx135_get_coarse_time_short_regs(struct imx135_reg *regs, u32 coarse_time)
+{
+	regs->addr = 0x230;
+	regs->val = (coarse_time >> 8) & 0xff;
+	(regs + 1)->addr = 0x231;
+	(regs + 1)->val = (coarse_time) & 0xff;
+}
+
+static inline void
+imx135_get_gain_reg(struct imx135_reg *regs, u16 gain)
+{
+	regs->addr = 0x205;
+	regs->val = gain;
+}
+
+static inline void
+imx135_get_gain_short_reg(struct imx135_reg *regs, u16 gain)
+{
+	regs->addr = 0x233;
+	regs->val = gain;
+}
+
+static int
+imx135_read_reg(struct i2c_client *client, u16 addr, u8 *val)
+{
+	int err;
+	struct i2c_msg msg[2];
+	unsigned char data[3];
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 2;
+	msg[0].buf = data;
+
+	/* high byte goes out first */
+	data[0] = (u8) (addr >> 8);
+	data[1] = (u8) (addr & 0xff);
+
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = 1;
+	msg[1].buf = data + 2;
+
+	err = i2c_transfer(client->adapter, msg, 2);
+
+	if (err != 2)
+		return -EINVAL;
+
+	*val = data[2];
+	return 0;
+}
+
+static int
+imx135_write_reg(struct i2c_client *client, u16 addr, u8 val)
+{
+	int err;
+	struct i2c_msg msg;
+	unsigned char data[3];
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	data[0] = (u8) (addr >> 8);
+	data[1] = (u8) (addr & 0xff);
+	data[2] = (u8) (val & 0xff);
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = 3;
+	msg.buf = data;
+
+	err = i2c_transfer(client->adapter, &msg, 1);
+	if (err == 1)
+		return 0;
+
+	pr_err("%s:i2c write failed, %x = %x\n",
+			__func__, addr, val);
+
+	return err;
+}
+
+static int
+imx135_write_table(struct i2c_client *client,
+				 const struct imx135_reg table[],
+				 const struct imx135_reg override_list[],
+				 int num_override_regs)
+{
+	int err;
+	const struct imx135_reg *next;
+	int i;
+	u16 val;
+
+	for (next = table; next->addr != IMX135_TABLE_END; next++) {
+		if (next->addr == IMX135_TABLE_WAIT_MS) {
+			msleep_range(next->val);
+			continue;
+		}
+
+		val = next->val;
+
+		/* When an override list is passed in, replace the reg */
+		/* value to write if the reg is in the list            */
+		if (override_list) {
+			for (i = 0; i < num_override_regs; i++) {
+				if (next->addr == override_list[i].addr) {
+					val = override_list[i].val;
+					break;
+				}
+			}
+		}
+
+		err = imx135_write_reg(client, next->addr, val);
+		if (err) {
+			pr_err("%s:imx135_write_table:%d", __func__, err);
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int
+imx135_set_mode(struct imx135_info *info, struct imx135_mode *mode)
+{
+	int sensor_mode;
+	u8 quality_hdr;
+	int err;
+	struct imx135_reg reg_list[8];
+
+	pr_info("%s: xres %u yres %u framelength %u coarsetime %u gain %u, hdr %d\n",
+			 __func__, mode->xres, mode->yres, mode->frame_length,
+			 mode->coarse_time, mode->gain, mode->hdr_en);
+
+	if (mode->xres == 4208 && mode->yres == 3120) {
+		sensor_mode = IMX135_MODE_4208X3120;
+		quality_hdr = 1;
+	} else if (mode->xres == 1920 && mode->yres == 1080) {
+		sensor_mode = IMX135_MODE_1920X1080;
+		quality_hdr = 0;
+	} else if (mode->xres == 1280 && mode->yres == 720) {
+		sensor_mode = IMX135_MODE_1280X720;
+		quality_hdr = 0;
+	} else if (mode->xres == 2616 && mode->yres == 1472) {
+		sensor_mode = IMX135_MODE_2616X1472;
+		quality_hdr = 1;
+	} else if (mode->xres == 3896 && mode->yres == 2192) {
+		sensor_mode = IMX135_MODE_3896X2192;
+		quality_hdr = 1;
+	} else {
+		pr_err("%s: invalid resolution supplied to set mode %d %d\n",
+			 __func__, mode->xres, mode->yres);
+		return -EINVAL;
+	}
+
+	/* get a list of override regs for the asking frame length, */
+	/* coarse integration time, and gain.                       */
+	imx135_get_frame_length_regs(reg_list, mode->frame_length);
+	imx135_get_coarse_time_regs(reg_list + 2, mode->coarse_time);
+	imx135_get_gain_reg(reg_list + 4, mode->gain);
+	if (mode->hdr_en == 1)  /* if HDR is enabled */
+	{
+		imx135_get_gain_short_reg(reg_list + 5, mode->gain);
+		imx135_get_coarse_time_short_regs(
+			reg_list + 6, mode->coarse_time_short);
+	}
+
+	err = imx135_write_table(info->i2c_client,
+				mode_table[sensor_mode],
+				reg_list, mode->hdr_en ? 8 : 5);
+	if (err)
+		return err;
+	if (quality_hdr)
+		err = imx135_write_table(info->i2c_client,
+				mode_table[IMX135_MODE_QUALITY_HDR],
+				reg_list, 0);
+	else
+		err = imx135_write_table(info->i2c_client,
+				mode_table[IMX135_MODE_QUALITY],
+				reg_list, 0);
+	if (err)
+		return err;
+
+	info->mode = sensor_mode;
+	pr_info("[IMX135]: stream on.\n");
+	return 0;
+}
+
+static int
+imx135_get_status(struct imx135_info *info, u8 *dev_status)
+{
+	*dev_status = 0;
+	return 0;
+}
+
+static int
+imx135_set_frame_length(struct imx135_info *info, u32 frame_length,
+						 bool group_hold)
+{
+	struct imx135_reg reg_list[2];
+	int i = 0;
+	int ret;
+
+	imx135_get_frame_length_regs(reg_list, frame_length);
+
+	if (group_hold) {
+		ret = imx135_write_reg(info->i2c_client, 0x0104, 0x01);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < 2; i++) {
+		ret = imx135_write_reg(info->i2c_client, reg_list[i].addr,
+			 reg_list[i].val);
+		if (ret)
+			return ret;
+	}
+
+	if (group_hold) {
+		ret = imx135_write_reg(info->i2c_client, 0x0104, 0x0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int
+imx135_set_coarse_time(struct imx135_info *info, u32 coarse_time,
+						 bool group_hold)
+{
+	int ret;
+
+	struct imx135_reg reg_list[2];
+	int i = 0;
+
+	imx135_get_coarse_time_regs(reg_list, coarse_time);
+
+	if (group_hold) {
+		ret = imx135_write_reg(info->i2c_client, 0x104, 0x01);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < 2; i++) {
+		ret = imx135_write_reg(info->i2c_client, reg_list[i].addr,
+			 reg_list[i].val);
+		if (ret)
+			return ret;
+	}
+
+	if (group_hold) {
+		ret = imx135_write_reg(info->i2c_client, 0x104, 0x0);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static int
+imx135_set_gain(struct imx135_info *info, u16 gain, bool group_hold)
+{
+	int ret;
+	struct imx135_reg reg_list;
+
+	imx135_get_gain_reg(&reg_list, gain);
+
+	if (group_hold) {
+		ret = imx135_write_reg(info->i2c_client, 0x104, 0x1);
+		if (ret)
+			return ret;
+	}
+
+	ret = imx135_write_reg(info->i2c_client, reg_list.addr, reg_list.val);
+	/* writing second gain register for HDR */
+	ret = imx135_write_reg(info->i2c_client, 0x233, reg_list.val);
+	if (ret)
+		return ret;
+
+	if (group_hold) {
+		ret = imx135_write_reg(info->i2c_client, 0x104, 0x0);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static int
+imx135_set_hdr_coarse_time(struct imx135_info *info, struct imx135_hdr *values)
+{
+	struct imx135_reg reg_list[2];
+	struct imx135_reg reg_list_short[2];
+	int ret, i = 0;
+
+	/* get long and short coarse time registers */
+	imx135_get_coarse_time_regs(reg_list, values->coarse_time_long);
+	imx135_get_coarse_time_short_regs(reg_list_short,
+			values->coarse_time_short);
+	/* set to direct mode */
+	ret = imx135_write_reg(info->i2c_client, 0x238, 0x1);
+	if (ret)
+		return ret;
+	/* set group hold */
+	ret = imx135_write_reg(info->i2c_client, 0x104, 0x1);
+	if (ret)
+		return ret;
+	/* writing long exposure */
+	for (i = 0; i < 2; i++) {
+		ret = imx135_write_reg(info->i2c_client, reg_list[i].addr,
+			 reg_list[i].val);
+		if (ret)
+			return ret;
+	}
+	/* writing short exposure */
+	for (i = 0; i < 2; i++) {
+		ret = imx135_write_reg(info->i2c_client, reg_list_short[i].addr,
+			 reg_list_short[i].val);
+		if (ret)
+			return ret;
+	}
+	ret = imx135_write_reg(info->i2c_client, 0x104, 0x0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int
+imx135_set_group_hold(struct imx135_info *info, struct imx135_ae *ae)
+{
+	int ret;
+	int count = 0;
+	bool groupHoldEnabled = false;
+	struct imx135_hdr values;
+
+	values.coarse_time_long = ae->coarse_time;
+	values.coarse_time_short = ae->coarse_time_short;
+
+	if (ae->gain_enable)
+		count++;
+	if (ae->coarse_time_enable)
+		count++;
+	if (ae->frame_length_enable)
+		count++;
+	if (count >= 2)
+		groupHoldEnabled = true;
+
+	if (groupHoldEnabled) {
+		ret = imx135_write_reg(info->i2c_client, 0x104, 0x1);
+		if (ret)
+			return ret;
+	}
+
+	if (ae->gain_enable)
+		imx135_set_gain(info, ae->gain, false);
+	if (ae->coarse_time_enable)
+		imx135_set_hdr_coarse_time(info, &values);
+	if (ae->frame_length_enable)
+		imx135_set_frame_length(info, ae->frame_length, false);
+
+	if (groupHoldEnabled) {
+		ret = imx135_write_reg(info->i2c_client, 0x104, 0x0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int imx135_get_sensor_id(struct imx135_info *info)
+{
+	int ret = 0;
+	int i;
+	u8 bak = 0;
+
+	pr_info("%s\n", __func__);
+	if (info->sensor_data.fuse_id_size)
+		return 0;
+
+	/* Note 1: If the sensor does not have power at this point
+	Need to supply the power, e.g. by calling power on function */
+
+	ret |= imx135_write_reg(info->i2c_client, 0x3B02, 0x00);
+	ret |= imx135_write_reg(info->i2c_client, 0x3B00, 0x01);
+	for (i = 0; i < 9 ; i++) {
+		ret |= imx135_read_reg(info->i2c_client, 0x3B24 + i, &bak);
+		info->sensor_data.fuse_id[i] = bak;
+	}
+
+	if (!ret)
+		info->sensor_data.fuse_id_size = i;
+
+	/* Note 2: Need to clean up any action carried out in Note 1 */
+
+	return ret;
+}
+
+static long
+imx135_ioctl(struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	int err;
+	struct imx135_info *info = file->private_data;
+
+	switch (cmd) {
+	case IMX135_IOCTL_SET_MODE:
+	{
+		struct imx135_mode mode;
+		if (copy_from_user(&mode, (const void __user *)arg,
+			sizeof(struct imx135_mode))) {
+			pr_err("%s:Failed to get mode from user.\n", __func__);
+			return -EFAULT;
+		}
+		return imx135_set_mode(info, &mode);
+	}
+	case IMX135_IOCTL_SET_FRAME_LENGTH:
+		return imx135_set_frame_length(info, (u32)arg, true);
+	case IMX135_IOCTL_SET_COARSE_TIME:
+		return imx135_set_coarse_time(info, (u32)arg, true);
+	case IMX135_IOCTL_SET_GAIN:
+		return imx135_set_gain(info, (u16)arg, true);
+	case IMX135_IOCTL_GET_STATUS:
+	{
+		u8 status;
+
+		err = imx135_get_status(info, &status);
+		if (err)
+			return err;
+		if (copy_to_user((void __user *)arg, &status, 1)) {
+			pr_err("%s:Failed to copy status to user\n", __func__);
+			return -EFAULT;
+			}
+		return 0;
+	}
+	case IMX135_IOCTL_GET_SENSORDATA:
+	{
+		err = imx135_get_sensor_id(info);
+
+		if (err) {
+			pr_err("%s:Failed to get fuse id info.\n", __func__);
+			return err;
+		}
+		if (copy_to_user((void __user *)arg, &info->sensor_data,
+				sizeof(struct imx135_sensordata))) {
+			pr_info("%s:Failed to copy fuse id to user space\n",
+				__func__);
+			return -EFAULT;
+		}
+		return 0;
+	}
+	case IMX135_IOCTL_SET_GROUP_HOLD:
+	{
+	  struct imx135_ae ae;
+	  if (copy_from_user(&ae, (const void __user *)arg,
+			sizeof(struct imx135_ae))) {
+		pr_info("%s:fail group hold\n", __func__);
+		return -EFAULT;
+	  }
+	  return imx135_set_group_hold(info, &ae);
+	}
+	case IMX135_IOCTL_SET_HDR_COARSE_TIME:
+	{
+		struct imx135_hdr values;
+
+		dev_dbg(&info->i2c_client->dev,
+				"IMX135_IOCTL_SET_HDR_COARSE_TIME\n");
+		if (copy_from_user(&values,
+			(const void __user *)arg,
+			sizeof(struct imx135_hdr))) {
+				err = -EFAULT;
+				break;
+		}
+		err = imx135_set_hdr_coarse_time(info, &values);
+		break;
+	}
+	default:
+	  pr_err("%s:unknown cmd.\n", __func__);
+	  return -EINVAL;
+	}
+	return 0;
+}
+
+static int imx135_debugfs_show(struct seq_file *s, void *unused)
+{
+	struct imx135_info *dev = s->private;
+
+	dev_dbg(&dev->i2c_client->dev, "%s: ++\n", __func__);
+
+	mutex_lock(&dev->imx135_camera_lock);
+	mutex_unlock(&dev->imx135_camera_lock);
+
+	return 0;
+}
+
+static ssize_t imx135_debugfs_write(
+	struct file *file,
+	char const __user *buf,
+	size_t count,
+	loff_t *offset)
+{
+	struct imx135_info *dev =
+			((struct seq_file *)file->private_data)->private;
+	struct i2c_client *i2c_client = dev->i2c_client;
+	int ret = 0;
+	char buffer[24];
+	u32 address;
+	u32 data;
+	u8 readback;
+
+	dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
+
+	if (copy_from_user(&buffer, buf, sizeof(buffer)))
+		goto debugfs_write_fail;
+
+	if (sscanf(buf, "0x%x 0x%x", &address, &data) == 2)
+		goto set_attr;
+	if (sscanf(buf, "0X%x 0X%x", &address, &data) == 2)
+		goto set_attr;
+	if (sscanf(buf, "%d %d", &address, &data) == 2)
+		goto set_attr;
+
+	if (sscanf(buf, "0x%x 0x%x", &address, &data) == 1)
+		goto read;
+	if (sscanf(buf, "0X%x 0X%x", &address, &data) == 1)
+		goto read;
+	if (sscanf(buf, "%d %d", &address, &data) == 1)
+		goto read;
+
+	dev_err(&i2c_client->dev, "SYNTAX ERROR: %s\n", buf);
+	return -EFAULT;
+
+set_attr:
+	dev_info(&i2c_client->dev,
+			"new address = %x, data = %x\n", address, data);
+	ret |= imx135_write_reg(i2c_client, address, data);
+read:
+	ret |= imx135_read_reg(i2c_client, address, &readback);
+	dev_dbg(&i2c_client->dev,
+			"wrote to address 0x%x with value 0x%x\n",
+			address, readback);
+
+	if (ret)
+		goto debugfs_write_fail;
+
+	return count;
+
+debugfs_write_fail:
+	dev_err(&i2c_client->dev,
+			"%s: test pattern write failed\n", __func__);
+	return -EFAULT;
+}
+
+static int imx135_debugfs_open(struct inode *inode, struct file *file)
+{
+	struct imx135_info *dev = inode->i_private;
+	struct i2c_client *i2c_client = dev->i2c_client;
+
+	dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
+
+	return single_open(file, imx135_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations imx135_debugfs_fops = {
+	.open		= imx135_debugfs_open,
+	.read		= seq_read,
+	.write		= imx135_debugfs_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void imx135_remove_debugfs(struct imx135_info *dev)
+{
+	struct i2c_client *i2c_client = dev->i2c_client;
+
+	dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
+
+	if (dev->debugdir)
+		debugfs_remove_recursive(dev->debugdir);
+	dev->debugdir = NULL;
+}
+
+static void imx135_create_debugfs(struct imx135_info *dev)
+{
+	struct dentry *ret;
+	struct i2c_client *i2c_client = dev->i2c_client;
+
+	dev_dbg(&i2c_client->dev, "%s\n", __func__);
+
+	dev->debugdir =
+		debugfs_create_dir(dev->miscdev_info.this_device->kobj.name,
+							NULL);
+	if (!dev->debugdir)
+		goto remove_debugfs;
+
+	ret = debugfs_create_file("d",
+				S_IWUSR | S_IRUGO,
+				dev->debugdir, dev,
+				&imx135_debugfs_fops);
+	if (!ret)
+		goto remove_debugfs;
+
+	return;
+remove_debugfs:
+	dev_err(&i2c_client->dev, "couldn't create debugfs\n");
+	imx135_remove_debugfs(dev);
+}
+
+static int
+imx135_open(struct inode *inode, struct file *file)
+{
+	struct miscdevice	*miscdev = file->private_data;
+	struct imx135_info *info;
+
+	info = container_of(miscdev, struct imx135_info, miscdev_info);
+	/* check if the device is in use */
+	if (atomic_xchg(&info->in_use, 1)) {
+		pr_info("%s:BUSY!\n", __func__);
+		return -EBUSY;
+	}
+
+	file->private_data = info;
+
+	if (info->pdata && info->pdata->power_on)
+		info->pdata->power_on(&info->power);
+	else{
+		pr_err("%s:no valid power_on function.\n", __func__);
+		return -EEXIST;
+	}
+
+	return 0;
+}
+
+static int
+imx135_release(struct inode *inode, struct file *file)
+{
+	struct imx135_info *info = file->private_data;
+
+	if (info->pdata && info->pdata->power_off)
+		info->pdata->power_off(&info->power);
+	file->private_data = NULL;
+
+	/* warn if device is already released */
+	WARN_ON(!atomic_xchg(&info->in_use, 0));
+	return 0;
+}
+
+static int imx135_power_put(struct imx135_power_rail *pw)
+{
+	if (unlikely(!pw))
+		return -EFAULT;
+
+	if (likely(pw->avdd))
+		regulator_put(pw->avdd);
+
+	if (likely(pw->iovdd))
+		regulator_put(pw->iovdd);
+
+	if (likely(pw->dvdd))
+		regulator_put(pw->dvdd);
+
+	pw->avdd = NULL;
+	pw->iovdd = NULL;
+	pw->dvdd = NULL;
+
+	return 0;
+}
+
+static int imx135_regulator_get(struct imx135_info *info,
+	struct regulator **vreg, char vreg_name[])
+{
+	struct regulator *reg = NULL;
+	int err = 0;
+
+	reg = regulator_get(&info->i2c_client->dev, vreg_name);
+	if (unlikely(IS_ERR_OR_NULL(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;
+	return err;
+}
+
+static int imx135_power_get(struct imx135_info *info)
+{
+	struct imx135_power_rail *pw = &info->power;
+
+	imx135_regulator_get(info, &pw->avdd, "vana"); /* ananlog 2.7v */
+	imx135_regulator_get(info, &pw->dvdd, "vdig"); /* digital 1.2v */
+	imx135_regulator_get(info, &pw->iovdd, "vif"); /* interface 1.8v */
+
+	return 0;
+}
+
+static const struct file_operations imx135_fileops = {
+	.owner = THIS_MODULE,
+	.open = imx135_open,
+	.unlocked_ioctl = imx135_ioctl,
+	.release = imx135_release,
+};
+
+static struct miscdevice imx135_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "imx135",
+	.fops = &imx135_fileops,
+};
+
+
+static int
+imx135_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct imx135_info *info;
+	int err;
+
+	pr_info("[IMX135]: probing sensor.\n");
+
+	info = devm_kzalloc(&client->dev,
+			sizeof(struct imx135_info), GFP_KERNEL);
+	if (!info) {
+		pr_err("%s:Unable to allocate memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	info->pdata = client->dev.platform_data;
+	info->i2c_client = client;
+	atomic_set(&info->in_use, 0);
+	info->mode = -1;
+
+	imx135_power_get(info);
+
+	memcpy(&info->miscdev_info,
+		&imx135_device,
+		sizeof(struct miscdevice));
+
+	err = misc_register(&info->miscdev_info);
+	if (err) {
+		pr_err("%s:Unable to register misc device!\n", __func__);
+		goto imx135_probe_fail;
+	}
+
+	i2c_set_clientdata(client, info);
+	/* create debugfs interface */
+	imx135_create_debugfs(info);
+	return 0;
+
+imx135_probe_fail:
+	imx135_power_put(&info->power);
+
+	return err;
+}
+
+static int
+imx135_remove(struct i2c_client *client)
+{
+	struct imx135_info *info;
+	info = i2c_get_clientdata(client);
+	misc_deregister(&imx135_device);
+
+	imx135_power_put(&info->power);
+
+	imx135_remove_debugfs(info);
+	return 0;
+}
+
+static const struct i2c_device_id imx135_id[] = {
+	{ "imx135", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, imx135_id);
+
+static struct i2c_driver imx135_i2c_driver = {
+	.driver = {
+		.name = "imx135",
+		.owner = THIS_MODULE,
+	},
+	.probe = imx135_probe,
+	.remove = imx135_remove,
+	.id_table = imx135_id,
+};
+
+static int __init imx135_init(void)
+{
+	pr_info("[IMX135] sensor driver loading\n");
+	return i2c_add_driver(&imx135_i2c_driver);
+}
+
+static void __exit imx135_exit(void)
+{
+	i2c_del_driver(&imx135_i2c_driver);
+}
+
+module_init(imx135_init);
+module_exit(imx135_exit);
diff --git a/drivers/media/video/tegra/max77665-flash.c b/drivers/media/video/tegra/max77665-flash.c
index 15cf889..2feee30 100644
--- a/drivers/media/video/tegra/max77665-flash.c
+++ b/drivers/media/video/tegra/max77665-flash.c
@@ -1,7 +1,7 @@
 /*
  * MAX77665_F.c - MAX77665_F flash/torch kernel driver
  *
- * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012 - 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,
@@ -65,7 +65,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
-#include <linux/list.h>
 #include <linux/regulator/consumer.h>
 #include <linux/gpio.h>
 #include <linux/seq_file.h>
@@ -172,6 +171,8 @@
 #define MAX77665_F_MAX_FLASH_LEVEL	((1 << 6) + 1)
 #define MAX77665_F_MAX_TORCH_LEVEL	((1 << 4) + 1)
 
+#define MAX77665_F_LEVEL_OFF		0xFFFF
+
 #define MAX77665_F_MAX_FLASH_CURRENT(x)    \
 	DIV_ROUND_UP(((x) * MAX77665_F_MAX_FLASH_LEVEL), 1000)
 #define MAX77665_F_MAX_TORCH_CURRENT(x) \
@@ -180,6 +181,9 @@
 #define SUSTAINTIME_DEF			558
 #define DEFAULT_FLASH_TMR_DUR		((SUSTAINTIME_DEF * 10 - 1) / 625)
 
+#define MAX77665_F_FLASH_TIMER_NUM	16
+#define MAX77665_F_TORCH_TIMER_NUM	17
+
 /* minimium debounce time 600uS */
 #define RECHARGEFACTOR_DEF		600
 
@@ -187,11 +191,27 @@
 #define MAXFLASH_MODE_TORCH		1
 #define MAXFLASH_MODE_FLASH		2
 
-#define max77665_f_max_flash_cap_size	(sizeof(u32) \
-				+ (sizeof(struct nvc_torch_level_info) \
-				* (MAX77665_F_MAX_FLASH_LEVEL)))
-#define max77665_f_max_torch_cap_size	(sizeof(u32) \
-				+ (sizeof(s32) * (MAX77665_F_MAX_TORCH_LEVEL)))
+#define max77665_f_flash_cap_size \
+			(sizeof(struct nvc_torch_flash_capabilities_v1) \
+			+ sizeof(struct nvc_torch_lumi_level_v1) \
+			* MAX77665_F_MAX_FLASH_LEVEL)
+#define max77665_f_flash_timeout_size \
+			(sizeof(struct nvc_torch_timer_capabilities_v1) \
+			+ sizeof(struct nvc_torch_timeout_v1) \
+			* MAX77665_F_FLASH_TIMER_NUM)
+#define max77665_f_max_flash_cap_size (max77665_f_flash_cap_size * 2 \
+			+ max77665_f_flash_timeout_size * 2)
+
+#define max77665_f_torch_cap_size \
+			(sizeof(struct nvc_torch_torch_capabilities_v1) \
+			+ sizeof(struct nvc_torch_lumi_level_v1) \
+			* MAX77665_F_MAX_TORCH_LEVEL)
+#define max77665_f_torch_timeout_size \
+			(sizeof(struct nvc_torch_timer_capabilities_v1) \
+			+ sizeof(struct nvc_torch_timeout_v1) \
+			* MAX77665_F_TORCH_TIMER_NUM)
+#define max77665_f_max_torch_cap_size (max77665_f_torch_timeout_size * 2\
+			+ max77665_f_torch_timeout_size * 2)
 
 #define GET_CURRENT_BY_INDEX(c)	((c) * 125 / 8)		/* mul 15.625 mA */
 #define GET_INDEX_BY_CURRENT(c)	((c) * 8 / 125)		/* div by 15.625 mA */
@@ -230,13 +250,14 @@
 	struct device *dev;
 	struct miscdevice miscdev;
 	struct dentry *d_max77665_f;
-	struct list_head list;
-	struct max77665_f_info *s_info;
 	struct mutex mutex;
 	struct max77665_f_power_rail pwr_rail;
 	struct max77665_f_platform_data *pdata;
-	struct nvc_torch_flash_capabilities *flash_cap;
-	struct nvc_torch_torch_capabilities *torch_cap;
+	struct nvc_torch_capability_query query;
+	struct nvc_torch_flash_capabilities_v1 *flash_cap[2];
+	struct nvc_torch_timer_capabilities_v1 *flash_timeouts[2];
+	struct nvc_torch_torch_capabilities_v1 *torch_cap[2];
+	struct nvc_torch_timer_capabilities_v1 *torch_timeouts[2];
 	struct max77665_f_config config;
 	struct max77665_f_reg_cache regs;
 	struct max77665_f_state_regs states;
@@ -246,13 +267,10 @@
 	atomic_t in_use;
 	int flash_cap_size;
 	int torch_cap_size;
-	int pwr_api;
-	int pwr_dev;
-	int sustainTime;
+	int pwr_state;
 	u8 fled_settings;
 	u8 op_mode;
 	u8 power_is_on;
-	u8 s_mode;
 	u8 ftimer_mode;
 	u8 ttimer_mode;
 	u8 new_ftimer;
@@ -336,8 +354,15 @@
 	.pinstate	= {0x0000, 0x0000},
 };
 
-static LIST_HEAD(max77665_f_info_list);
-static DEFINE_SPINLOCK(max77665_f_spinlock);
+/* torch timer duration settings in uS */
+#define MAX77665_F_TORCH_TIMER_FOREVER	0xFFFFFFFF
+static u32 max77665_f_torch_timer[] = {
+	262000, 524000, 786000, 1048000,
+	1572000, 2096000, 2620000, 3144000,
+	4193000, 5242000, 6291000, 7340000,
+	9437000, 11534000, 13631000, 15728000,
+	MAX77665_F_TORCH_TIMER_FOREVER
+};
 
 static void max77665_f_throttle(unsigned int new_state, void *priv_data);
 
@@ -467,8 +492,10 @@
 		u8 mask, u8 curr1, u8 curr2)
 {
 	int err = 0;
-	u16 f_levels = info->flash_cap->numberoflevels - 2;
-	u16 t_levels = info->torch_cap->numberoflevels - 2;
+	u32 f_levels1 = info->flash_cap[0]->numberoflevels - 2;
+	u32 f_levels2 = info->flash_cap[1]->numberoflevels - 2;
+	u32 t_levels1 = info->torch_cap[0]->numberoflevels - 2;
+	u32 t_levels2 = info->torch_cap[1]->numberoflevels - 2;
 	u8 fled_en = 0;
 	u8 t_curr = 0;
 	u8 regs[6];
@@ -490,13 +517,13 @@
 
 	if (mask & 1) {
 		if (info->op_mode == MAXFLASH_MODE_FLASH) {
-			if (curr1 > f_levels)
-				curr1 = f_levels;
+			if (curr1 > f_levels1)
+				curr1 = f_levels1;
 			fled_en |= (info->fled_settings & LED1_FLASH_TRIG_MASK);
 			regs[0] = curr1;
 		} else {
-			if (curr1 > t_levels)
-				curr1 = t_levels;
+			if (curr1 > t_levels1)
+				curr1 = t_levels1;
 			fled_en |= (info->fled_settings & LED1_TORCH_TRIG_MASK);
 			t_curr = curr1;
 		}
@@ -504,13 +531,13 @@
 
 	if (mask & 2) {
 		if (info->op_mode == MAXFLASH_MODE_FLASH) {
-			if (curr2 > f_levels)
-				curr2 = f_levels;
+			if (curr2 > f_levels2)
+				curr2 = f_levels2;
 			fled_en |= (info->fled_settings & LED2_FLASH_TRIG_MASK);
 			regs[1] = curr2;
 		} else {
-			if (curr2 > t_levels)
-				curr2 = t_levels;
+			if (curr2 > t_levels2)
+				curr2 = t_levels2;
 			fled_en |= (info->fled_settings & LED2_TORCH_TRIG_MASK);
 			t_curr |= curr2 << 4;
 		}
@@ -778,10 +805,12 @@
 static int max77665_f_configure(struct max77665_f_info *info, bool update)
 {
 	struct max77665_f_config *pcfg = &info->config;
-	struct nvc_torch_flash_capabilities *pfcap = info->flash_cap;
-	struct nvc_torch_torch_capabilities *ptcap = info->torch_cap;
-	int val;
-	int i;
+	struct nvc_torch_capability_query *pqry = &info->query;
+	struct nvc_torch_flash_capabilities_v1	*pfcap = NULL;
+	struct nvc_torch_torch_capabilities_v1	*ptcap = NULL;
+	struct nvc_torch_timer_capabilities_v1	*ptmcap = NULL;
+	struct nvc_torch_lumi_level_v1		*plvls = NULL;
+	int val, i, j;
 
 	if (pcfg->max_peak_current_mA > max77665_f_caps.max_peak_curr_mA ||
 		!pcfg->max_peak_current_mA) {
@@ -792,9 +821,14 @@
 		pcfg->max_peak_current_mA = max77665_f_caps.max_peak_curr_mA;
 	}
 
+	/* number of leds enabled */
 	i = 1;
-	if ((info->config.led_mask & 3) == 3)
+	/* in synchronize mode, both leds are considered as 1 */
+	if (!pcfg->synchronized_led && (info->config.led_mask & 3) == 3)
 		i = 2;
+	pqry->flash_num = i;
+	pqry->torch_num = i;
+
 	val = pcfg->max_peak_current_mA * i;
 	if (val > max77665_f_caps.max_total_current_mA)
 		val = max77665_f_caps.max_total_current_mA;
@@ -814,37 +848,80 @@
 			max77665_f_caps.max_torch_curr_mA;
 	}
 
-	pfcap->levels[0].guidenum = 0;
-	pfcap->levels[0].sustaintime = 0xFFFFFFFF;
-	pfcap->levels[0].rechargefactor = 0;
-	val = max77665_f_caps.curr_step_uA;
-	for (i = 1; i < MAX77665_F_MAX_FLASH_LEVEL; i++) {
-		pfcap->levels[i].guidenum = val * i / 1000; /* mA */
-		if (pfcap->levels[i].guidenum >
-			pcfg->max_peak_current_mA) {
-			pfcap->levels[i].guidenum = 0;
-			break;
-		}
-		pfcap->levels[i].sustaintime = info->sustainTime;
-		pfcap->levels[i].rechargefactor = RECHARGEFACTOR_DEF;
-	}
-	info->flash_cap_size = (sizeof(u32) +
-			(sizeof(struct nvc_torch_level_info) * i));
-	pfcap->numberoflevels = i;
+	pqry->version = NVC_TORCH_CAPABILITY_VER_1;
+	pqry->led_attr = 0;
+	for (i = 0; i < pqry->flash_num; i++) {
+		pfcap = info->flash_cap[i];
+		pfcap->version = NVC_TORCH_CAPABILITY_VER_1;
+		pfcap->led_idx = i;
+		pfcap->attribute = 0;
+		pfcap->numberoflevels = pcfg->led_config[i].flash_levels + 1;
+		pfcap->granularity = pcfg->led_config[i].granularity;
+		pfcap->timeout_num = MAX77665_F_FLASH_TIMER_NUM;
+		ptmcap = info->flash_timeouts[i];
+		pfcap->timeout_off = (void *)ptmcap - (void *)pfcap;
+		pfcap->flash_torch_ratio =
+				pcfg->led_config[i].flash_torch_ratio;
+		dev_dbg(info->dev,
+			"%s flash#%d, attr: %x, levels: %d, g: %d, ratio: %d\n",
+			__func__, pfcap->led_idx, pfcap->attribute,
+			pfcap->numberoflevels, pfcap->granularity,
+			pfcap->flash_torch_ratio);
 
-	ptcap->guidenum[0] = 0;
-	for (i = 1; i < MAX77665_F_MAX_TORCH_LEVEL; i++) {
-		ptcap->guidenum[i] = pfcap->levels[i].guidenum;
-		if (ptcap->guidenum[i] > pcfg->max_torch_current_mA) {
-			ptcap->guidenum[i] = 0;
-			break;
+		plvls = pcfg->led_config[i].lumi_levels;
+		pfcap->levels[0].guidenum = MAX77665_F_LEVEL_OFF;
+		pfcap->levels[0].luminance = 0;
+		for (j = 1; j < pfcap->numberoflevels; j++) {
+			pfcap->levels[j].guidenum = plvls[j - 1].guidenum;
+			pfcap->levels[j].luminance = plvls[j - 1].luminance;
+			dev_dbg(info->dev, "%02d - %d\n",
+				pfcap->levels[j].guidenum,
+				pfcap->levels[j].luminance);
+		}
+
+		ptmcap->timeout_num = pfcap->timeout_num;
+		for (j = 0; j < ptmcap->timeout_num; j++) {
+			ptmcap->timeouts[j].timeout = 62500 * (j + 1);
+			dev_dbg(info->dev, "t: %02d - %d uS\n", j,
+				ptmcap->timeouts[j].timeout);
 		}
 	}
-	info->torch_cap_size = (sizeof(u32) + (sizeof(s32) * i));
-	ptcap->numberoflevels = i;
 
-	if (update && (info->pwr_dev == NVC_PWR_COMM ||
-			info->pwr_dev == NVC_PWR_ON))
+	for (i = 0; i < pqry->torch_num; i++) {
+		ptcap = info->torch_cap[i];
+		ptcap->version = NVC_TORCH_CAPABILITY_VER_1;
+		ptcap->led_idx = i;
+		ptcap->attribute = 0;
+		ptcap->numberoflevels = pcfg->led_config[i].flash_levels + 1;
+		ptcap->granularity = pcfg->led_config[i].granularity;
+		ptcap->timeout_num = MAX77665_F_TORCH_TIMER_NUM;
+		ptmcap = info->torch_timeouts[i];
+		ptcap->timeout_off = (void *)ptmcap - (void *)ptcap;
+		dev_dbg(info->dev, "torch#%d, attr: %x, levels: %d, g: %d\n",
+			ptcap->led_idx, ptcap->attribute,
+			ptcap->numberoflevels, ptcap->granularity);
+
+		plvls = pcfg->led_config[i].lumi_levels;
+		ptcap->levels[0].guidenum = MAX77665_F_LEVEL_OFF;
+		ptcap->levels[0].luminance = 0;
+		for (j = 1; j < ptcap->numberoflevels; j++) {
+			ptcap->levels[j].guidenum = plvls[j - 1].guidenum;
+			ptcap->levels[j].luminance = plvls[j - 1].luminance;
+			dev_dbg(info->dev, "%02d - %d\n",
+				ptcap->levels[j].guidenum,
+				ptcap->levels[j].luminance);
+		}
+
+		ptmcap->timeout_num = ptcap->timeout_num;
+		for (j = 0; j < ptmcap->timeout_num; j++) {
+			ptmcap->timeouts[j].timeout = max77665_f_torch_timer[j];
+			dev_dbg(info->dev, "t: %02d - %d uS\n", j,
+				ptmcap->timeouts[j].timeout);
+		}
+	}
+
+	if (update && (info->pwr_state == NVC_PWR_COMM ||
+			info->pwr_state == NVC_PWR_ON))
 		return max77665_f_update_settings(info);
 
 	return 0;
@@ -1018,25 +1095,25 @@
 	return err;
 }
 
-static int max77665_f_power(struct max77665_f_info *info, int pwr)
+static int max77665_f_power_set(struct max77665_f_info *info, int pwr)
 {
 	int err = 0;
 
-	if (pwr == info->pwr_dev)
+	if (pwr == info->pwr_state)
 		return 0;
 
 	switch (pwr) {
 	case NVC_PWR_OFF:
 		max77665_f_enter_offmode(info, true);
 		if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) ||
-			     (info->pdata->cfg & NVC_CFG_BOOT_INIT))
+			(info->pdata->cfg & NVC_CFG_BOOT_INIT))
 			pwr = NVC_PWR_STDBY;
 		else
 			err = max77665_f_power_off(info);
 		break;
 	case NVC_PWR_STDBY_OFF:
 		if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) ||
-			     (info->pdata->cfg & NVC_CFG_BOOT_INIT))
+			(info->pdata->cfg & NVC_CFG_BOOT_INIT))
 			pwr = NVC_PWR_STDBY;
 		else
 			err = max77665_f_power_on(info);
@@ -1060,54 +1137,28 @@
 		dev_err(info->dev, "%s error\n", __func__);
 		pwr = NVC_PWR_ERR;
 	}
-	info->pwr_dev = pwr;
+	info->pwr_state = pwr;
 	if (err > 0)
 		return 0;
 
 	return err;
 }
 
-static int max77665_f_power_sync(struct max77665_f_info *info, int pwr)
-{
-	int err1 = 0;
-	int err2 = 0;
-
-	if ((info->s_mode == NVC_SYNC_OFF) ||
-			(info->s_mode == NVC_SYNC_MASTER) ||
-			(info->s_mode == NVC_SYNC_STEREO))
-		err1 = max77665_f_power(info, pwr);
-	if ((info->s_mode == NVC_SYNC_SLAVE) ||
-			(info->s_mode == NVC_SYNC_STEREO))
-		err2 = max77665_f_power(info->s_info, pwr);
-	return err1 | err2;
-}
-
-static int max77665_f_power_user_set(struct max77665_f_info *info, int pwr)
+static inline int max77665_f_power_user_set(
+	struct max77665_f_info *info, int pwr)
 {
 	int err = 0;
 
 	if (!pwr || (pwr > NVC_PWR_ON))
 		return 0;
 
-	if (pwr > info->pwr_dev)
-		err = max77665_f_power_sync(info, pwr);
-	if (!err)
-		info->pwr_api = pwr;
-	else
-		info->pwr_api = NVC_PWR_ERR;
+	err = max77665_f_power_set(info, pwr);
 	if (info->pdata->cfg & NVC_CFG_NOERR)
 		return 0;
 
 	return err;
 }
 
-static int max77665_f_dev_power_set(struct max77665_f_info *info, int pwr)
-{
-	if (pwr < info->pwr_api)
-		pwr = info->pwr_api;
-	return max77665_f_power(info, pwr);
-}
-
 static int max77665_f_get_param(struct max77665_f_info *info, long arg)
 {
 	struct nvc_param params;
@@ -1116,43 +1167,70 @@
 	u32 data_size = 0;
 	u8 reg;
 
-	if (copy_from_user(&params,
-			(const void __user *)arg,
+	if (copy_from_user(&params, (const void __user *)arg,
 			sizeof(struct nvc_param))) {
 		dev_err(info->dev, "%s %d copy_from_user err\n",
 				__func__, __LINE__);
 		return -EINVAL;
 	}
 
-	if (info->s_mode == NVC_SYNC_SLAVE)
-		info = info->s_info;
 	switch (params.param) {
-	case NVC_PARAM_FLASH_CAPS:
-		dev_dbg(info->dev, "%s FLASH_CAPS\n", __func__);
-		data_ptr = info->flash_cap;
+	case NVC_PARAM_TORCH_QUERY:
+		dev_dbg(info->dev, "%s QUERY\n", __func__);
+		data_ptr = &info->query;
+		data_size = sizeof(info->query);
+		break;
+	case NVC_PARAM_FLASH_EXT_CAPS:
+		dev_dbg(info->dev, "%s EXT_FLASH_CAPS %d\n",
+			__func__, params.variant);
+		if (params.variant >= info->query.flash_num) {
+			dev_err(info->dev, "%s unsupported flash index.\n",
+				__func__);
+			return -EINVAL;
+		}
+		data_ptr = info->flash_cap[params.variant];
 		data_size = info->flash_cap_size;
 		break;
-
-	case NVC_PARAM_FLASH_LEVEL:
-		reg = info->regs.led1_curr;
-		data_ptr = &info->flash_cap->levels[reg].guidenum;
-		data_size = sizeof(info->flash_cap->levels[reg].guidenum);
-		dev_dbg(info->dev, "%s FLASH_LEVEL %d\n", __func__, reg);
-		break;
-
-	case NVC_PARAM_TORCH_CAPS:
-		dev_dbg(info->dev, "%s TORCH_CAPS\n", __func__);
-		data_ptr = info->torch_cap;
+	case NVC_PARAM_TORCH_EXT_CAPS:
+		dev_dbg(info->dev, "%s EXT_TORCH_CAPS %d\n",
+			__func__, params.variant);
+		if (params.variant >= info->query.torch_num) {
+			dev_err(info->dev, "%s unsupported torch index.\n",
+				__func__);
+			return -EINVAL;
+		}
+		data_ptr = info->torch_cap[params.variant];
 		data_size = info->torch_cap_size;
 		break;
-
+	case NVC_PARAM_FLASH_LEVEL:
+		if (params.variant >= info->query.flash_num) {
+			dev_err(info->dev,
+				"%s unsupported flash index.\n", __func__);
+			return -EINVAL;
+		}
+		if (params.variant > 0)
+			reg = info->regs.led2_curr;
+		else
+			reg = info->regs.led1_curr;
+		data_ptr = &reg;
+		data_size = sizeof(reg);
+		dev_dbg(info->dev, "%s FLASH_LEVEL %d\n", __func__, reg);
+		break;
 	case NVC_PARAM_TORCH_LEVEL:
-		reg = info->regs.led1_curr;
-		data_ptr = &info->torch_cap->guidenum[reg];
-		data_size = sizeof(info->torch_cap->guidenum[reg]);
+		reg = info->regs.led_tcurr;
+		if (params.variant >= info->query.torch_num) {
+			dev_err(info->dev, "%s unsupported torch index.\n",
+				__func__);
+			return -EINVAL;
+		}
+		if (params.variant > 0)
+			reg >>= 4;
+		else
+			reg &= 0x0F;
+		data_ptr = &reg;
+		data_size = sizeof(reg);
 		dev_dbg(info->dev, "%s TORCH_LEVEL %d\n", __func__, reg);
 		break;
-
 	case NVC_PARAM_FLASH_PIN_STATE:
 		pinstate = info->pdata->pinstate;
 		if (info->op_mode != MAXFLASH_MODE_FLASH)
@@ -1164,28 +1242,21 @@
 		data_ptr = &pinstate;
 		data_size = sizeof(pinstate);
 		break;
-
-	case NVC_PARAM_STEREO:
-		dev_dbg(info->dev, "%s STEREO: %d\n", __func__, info->s_mode);
-		data_ptr = &info->s_mode;
-		data_size = sizeof(info->s_mode);
-		break;
-
 	default:
 		dev_err(info->dev, "%s unsupported parameter: %d\n",
 				__func__, params.param);
 		return -EINVAL;
 	}
 
+	dev_dbg(info->dev, "%s data size user %d vs local %d\n",
+			__func__, params.sizeofvalue, data_size);
 	if (params.sizeofvalue < data_size) {
-		dev_err(info->dev, "%s data size mismatch %d != %d\n",
-				__func__, params.sizeofvalue, data_size);
+		dev_err(info->dev, "%s data size mismatch\n", __func__);
 		return -EINVAL;
 	}
 
 	if (copy_to_user((void __user *)params.p_value,
-			 data_ptr,
-			 data_size)) {
+			 data_ptr, data_size)) {
 		dev_err(info->dev, "%s copy_to_user err line %d\n",
 				__func__, __LINE__);
 		return -EFAULT;
@@ -1194,160 +1265,118 @@
 	return 0;
 }
 
-static int max77665_f_param_update(struct max77665_f_info *info,
+static int max77665_f_get_levels(struct max77665_f_info *info,
 			       struct nvc_param *params,
-			       u8 val)
+			       bool flash_mode,
+			       struct nvc_torch_set_level_v1 *plevels)
 {
-	int err;
+	struct nvc_torch_timer_capabilities_v1 *p_tm;
+	u8 op_mode;
 
-	switch (params->param) {
-	case NVC_PARAM_FLASH_LEVEL:
-		dev_dbg(info->dev, "%s FLASH_LEVEL: %d\n", __func__, val);
-		if (val) {
-			info->new_ftimer = DEFAULT_FLASH_TMR_DUR;
-			info->op_mode = MAXFLASH_MODE_FLASH;
-			val--;
-		} else
-			info->op_mode = MAXFLASH_MODE_NONE;
-
-		max77665_f_dev_power_set(info, NVC_PWR_ON);
-		err = max77665_f_set_leds(info,
-			info->config.led_mask, val, val);
-		/*turn pwr off if no flash && no pwr_api*/
-		if (info->op_mode == MAXFLASH_MODE_NONE)
-			max77665_f_dev_power_set(info, NVC_PWR_OFF);
-		return err;
-
-	case NVC_PARAM_TORCH_LEVEL:
-		dev_dbg(info->dev, "%s TORCH_LEVEL: %d\n", __func__, val);
-		if (val) {
-			info->op_mode = MAXFLASH_MODE_TORCH;
-			val--;
-		} else
-			info->op_mode = MAXFLASH_MODE_NONE;
-
-		max77665_f_dev_power_set(info, NVC_PWR_ON);
-		err = max77665_f_set_leds(info,
-			info->config.led_mask, val, val);
-		/*turn pwr off if no flash && no pwr_api*/
-		if (info->op_mode == MAXFLASH_MODE_NONE)
-			max77665_f_dev_power_set(info, NVC_PWR_OFF);
-		return err;
-
-	case NVC_PARAM_FLASH_PIN_STATE:
-		dev_dbg(info->dev, "%s FLASH_PIN_STATE: %d\n",
-				__func__, val);
-		return max77665_f_strobe(info, val);
-
-	default:
-		dev_err(info->dev, "%s unsupported parameter: %d\n",
-				__func__, params->param);
+	if (copy_from_user(plevels, (const void __user *)params->p_value,
+			   sizeof(*plevels))) {
+		dev_err(info->dev, "%s %d copy_from_user err\n",
+				__func__, __LINE__);
 		return -EINVAL;
 	}
+
+	if (flash_mode) {
+		dev_dbg(info->dev, "%s FLASH_LEVEL: %d %d %d\n",
+			__func__, plevels->ledmask,
+			plevels->levels[0], plevels->levels[1]);
+		p_tm = info->flash_timeouts[0];
+		op_mode = MAXFLASH_MODE_FLASH;
+	} else {
+		dev_dbg(info->dev, "%s TORCH_LEVEL: %d %d %d\n",
+			__func__, plevels->ledmask,
+			plevels->levels[0], plevels->levels[1]);
+		p_tm = info->torch_timeouts[0];
+		op_mode = MAXFLASH_MODE_TORCH;
+	}
+
+	if (plevels->timeout) {
+		u16 i;
+		for (i = 0; i < p_tm->timeout_num; i++) {
+			plevels->timeout = i;
+			if (plevels->timeout == p_tm->timeouts[i].timeout)
+				break;
+		}
+	} else
+		plevels->timeout = p_tm->timeout_num - 1;
+
+	if (plevels->levels[0] == MAX77665_F_LEVEL_OFF)
+		plevels->ledmask &= ~1;
+	if (plevels->levels[1] == MAX77665_F_LEVEL_OFF)
+		plevels->ledmask &= ~2;
+	plevels->ledmask &= info->config.led_mask;
+
+	if (!plevels->ledmask)
+		info->op_mode = MAXFLASH_MODE_NONE;
+	else {
+		info->op_mode = op_mode;
+		if (info->config.synchronized_led) {
+			plevels->ledmask = 3;
+			plevels->levels[1] = plevels->levels[0];
+		}
+	}
+
+	dev_dbg(info->dev, "Return: %d - %d %d %d\n", info->op_mode,
+		plevels->ledmask, plevels->levels[0], plevels->levels[1]);
+	return 0;
 }
 
 static int max77665_f_set_param(struct max77665_f_info *info, long arg)
 {
 	struct nvc_param params;
+	struct nvc_torch_set_level_v1 led_levels;
+	u8 curr1;
+	u8 curr2;
 	u8 val;
 	int err = 0;
 
-	if (copy_from_user(&params,
-				(const void __user *)arg,
-				sizeof(struct nvc_param))) {
+	if (copy_from_user(
+		&params, (const void __user *)arg, sizeof(struct nvc_param))) {
 		dev_err(info->dev, "%s %d copy_from_user err\n",
 				__func__, __LINE__);
 		return -EINVAL;
 	}
 
-	if (copy_from_user(&val, (const void __user *)params.p_value,
-			   sizeof(val))) {
-		dev_err(info->dev, "%s %d copy_from_user err\n",
-				__func__, __LINE__);
-		return -EINVAL;
-	}
-
-	/* parameters independent of sync mode */
 	switch (params.param) {
-	case NVC_PARAM_STEREO:
-		dev_dbg(info->dev, "%s STEREO: %d\n", __func__, (int)val);
-		if (val == info->s_mode)
-			return 0;
-
-		switch (val) {
-		case NVC_SYNC_OFF:
-			info->s_mode = val;
-			if (info->s_info != NULL) {
-				info->s_info->s_mode = val;
-				max77665_f_power(info->s_info, NVC_PWR_OFF);
-			}
-			break;
-
-		case NVC_SYNC_MASTER:
-			info->s_mode = val;
-			if (info->s_info != NULL)
-				info->s_info->s_mode = val;
-			break;
-
-		case NVC_SYNC_SLAVE:
-		case NVC_SYNC_STEREO:
-			if (info->s_info != NULL) {
-				/* sync power */
-				info->s_info->pwr_api = info->pwr_api;
-				err = max77665_f_power(info->s_info,
-						     info->pwr_dev);
-				if (!err) {
-					info->s_mode = val;
-					info->s_info->s_mode = val;
-				} else {
-					max77665_f_power(info->s_info,
-						       NVC_PWR_OFF);
-					err = -EIO;
-				}
-			} else {
-				err = -EINVAL;
-			}
-			break;
-
-		default:
-			err = -EINVAL;
-		}
-		if (info->pdata->cfg & NVC_CFG_NOERR)
-			return 0;
-
+	case NVC_PARAM_FLASH_LEVEL:
+		max77665_f_get_levels(info, &params, true, &led_levels);
+		info->new_ftimer = led_levels.timeout & 0X0F;
+		curr1 = led_levels.levels[0];
+		curr2 = led_levels.levels[1];
+		err = max77665_f_set_leds(info,
+			led_levels.ledmask, curr1, curr2);
 		return err;
-
-	default:
-	/* parameters dependent on sync mode */
-		switch (info->s_mode) {
-		case NVC_SYNC_OFF:
-		case NVC_SYNC_MASTER:
-			return max77665_f_param_update(info, &params, val);
-
-		case NVC_SYNC_SLAVE:
-			return max77665_f_param_update(info->s_info,
-						 &params,
-						 val);
-
-		case NVC_SYNC_STEREO:
-			err = max77665_f_param_update(info, &params, val);
-			if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
-				err |= max77665_f_param_update(info->s_info,
-							 &params,
-							 val);
-			return err;
-
-		default:
-			dev_err(info->dev, "%s %d internal err\n",
-					__func__, __LINE__);
+	case NVC_PARAM_TORCH_LEVEL:
+		max77665_f_get_levels(info, &params, false, &led_levels);
+		info->new_ftimer = led_levels.timeout & 0X0F;
+		curr1 = led_levels.levels[0];
+		curr2 = led_levels.levels[1];
+		err = max77665_f_set_leds(info,
+			led_levels.ledmask, curr1, curr2);
+		return err;
+	case NVC_PARAM_FLASH_PIN_STATE:
+		if (copy_from_user(&val, (const void __user *)params.p_value,
+			   sizeof(val))) {
+			dev_err(info->dev, "%s %d copy_from_user err\n",
+				__func__, __LINE__);
 			return -EINVAL;
 		}
+		dev_dbg(info->dev, "%s FLASH_PIN_STATE: %d\n",
+				__func__, val);
+		return max77665_f_strobe(info, val);
+	default:
+		dev_err(info->dev, "%s unsupported parameter: %d\n",
+				__func__, params.param);
+		return -EINVAL;
 	}
 }
 
-static long max77665_f_ioctl(struct file *file,
-			   unsigned int cmd,
-			   unsigned long arg)
+static long max77665_f_ioctl(
+	struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct max77665_f_info *info = file->private_data;
 	int pwr;
@@ -1355,31 +1384,24 @@
 	switch (cmd) {
 	case NVC_IOCTL_PARAM_WR:
 		return max77665_f_set_param(info, arg);
-
 	case NVC_IOCTL_PARAM_RD:
 		return max77665_f_get_param(info, arg);
-
 	case NVC_IOCTL_PWR_WR:
 		/* This is a Guaranteed Level of Service (GLOS) call */
 		pwr = (int)arg * 2;
 		dev_dbg(info->dev, "%s PWR_WR: %d\n", __func__, pwr);
 		return max77665_f_power_user_set(info, pwr);
-
 	case NVC_IOCTL_PWR_RD:
-		if (info->s_mode == NVC_SYNC_SLAVE)
-			pwr = info->s_info->pwr_api / 2;
-		else
-			pwr = info->pwr_api / 2;
+		pwr = info->pwr_state / 2;
 		dev_dbg(info->dev, "%s PWR_RD: %d\n", __func__, pwr);
-		if (copy_to_user((void __user *)arg, (const void *)&pwr,
-				 sizeof(pwr))) {
+		if (copy_to_user(
+			(void __user *)arg, (const void *)&pwr, sizeof(pwr))) {
 			dev_err(info->dev, "%s copy_to_user err line %d\n",
 					__func__, __LINE__);
 			return -EFAULT;
 		}
 
 		return 0;
-
 	default:
 		dev_err(info->dev, "%s unsupported ioctl: %x\n",
 				__func__, cmd);
@@ -1387,88 +1409,18 @@
 	}
 }
 
-static int max77665_f_sync_enable(int dev1, int dev2)
-{
-	struct max77665_f_info *sync1 = NULL;
-	struct max77665_f_info *sync2 = NULL;
-	struct max77665_f_info *pos = NULL;
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(pos, &max77665_f_info_list, list) {
-		if (pos->pdata->num == dev1) {
-			sync1 = pos;
-			break;
-		}
-	}
-	pos = NULL;
-	list_for_each_entry_rcu(pos, &max77665_f_info_list, list) {
-		if (pos->pdata->num == dev2) {
-			sync2 = pos;
-			break;
-		}
-	}
-	rcu_read_unlock();
-	if (sync1 != NULL)
-		sync1->s_info = NULL;
-	if (sync2 != NULL)
-		sync2->s_info = NULL;
-	if (!dev1 && !dev2)
-		return 0; /* no err if default instance 0's used */
-
-	if (dev1 == dev2)
-		return -EINVAL; /* err if sync instance is itself */
-
-	if ((sync1 != NULL) && (sync2 != NULL)) {
-		sync1->s_info = sync2;
-		sync2->s_info = sync1;
-	}
-
-	return 0;
-}
-
-static int max77665_f_sync_disable(struct max77665_f_info *info)
-{
-	if (info->s_info != NULL) {
-		info->s_info->s_mode = 0;
-		info->s_info->s_info = NULL;
-		info->s_mode = 0;
-		info->s_info = NULL;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
 static int max77665_f_open(struct inode *inode, struct file *file)
 {
-	struct max77665_f_info *info = NULL;
-	struct max77665_f_info *pos = NULL;
-	int err;
+	struct miscdevice	*miscdev = file->private_data;
+	struct max77665_f_info *info;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(pos, &max77665_f_info_list, list) {
-		if (pos->miscdev.minor == iminor(inode)) {
-			info = pos;
-			break;
-		}
-	}
-	rcu_read_unlock();
+	info = container_of(miscdev, struct max77665_f_info, miscdev);
 	if (!info)
 		return -ENODEV;
 
-	err = max77665_f_sync_enable(info->pdata->num, info->pdata->sync);
-	if (err == -EINVAL)
-		dev_err(info->dev,
-			 "%s err: invalid num (%u) and sync (%u) instance\n",
-			 __func__, info->pdata->num, info->pdata->sync);
 	if (atomic_xchg(&info->in_use, 1))
 		return -EBUSY;
 
-	if (info->s_info != NULL) {
-		if (atomic_xchg(&info->s_info->in_use, 1))
-			return -EBUSY;
-	}
-
 	file->private_data = info;
 	dev_dbg(info->dev, "%s\n", __func__);
 	return 0;
@@ -1479,12 +1431,9 @@
 	struct max77665_f_info *info = file->private_data;
 
 	dev_dbg(info->dev, "%s\n", __func__);
-	max77665_f_power_sync(info, NVC_PWR_OFF);
+	max77665_f_power_set(info, NVC_PWR_OFF);
 	file->private_data = NULL;
 	WARN_ON(!atomic_xchg(&info->in_use, 0));
-	if (info->s_info != NULL)
-		WARN_ON(!atomic_xchg(&info->s_info->in_use, 0));
-	max77665_f_sync_disable(info);
 	return 0;
 }
 
@@ -1546,13 +1495,8 @@
 
 static void max77665_f_del(struct max77665_f_info *info)
 {
-	max77665_f_power_sync(info, NVC_PWR_OFF);
+	max77665_f_power_set(info, NVC_PWR_OFF);
 	max77665_f_power_put(&info->pwr_rail);
-	max77665_f_sync_disable(info);
-	spin_lock(&max77665_f_spinlock);
-	list_del_rcu(&info->list);
-	spin_unlock(&max77665_f_spinlock);
-	synchronize_rcu();
 }
 
 static int max77665_f_remove(struct platform_device *pdev)
@@ -1570,6 +1514,38 @@
 
 static int max77665_f_debugfs_init(struct max77665_f_info *info);
 
+static void max77665_f_caps_layout(struct max77665_f_info *info)
+{
+#define MAX77665_FLASH_CAP_TIMEOUT_SIZE \
+	(max77665_f_flash_cap_size + max77665_f_flash_timeout_size)
+#define MAX77665_TORCH_CAP_TIMEOUT_SIZE \
+	(max77665_f_torch_cap_size + max77665_f_torch_timeout_size)
+	void *start_ptr = (void *)info + sizeof(*info);
+
+	info->flash_cap[0] = start_ptr;
+	info->flash_timeouts[0] = start_ptr + max77665_f_flash_cap_size;
+
+	start_ptr += MAX77665_FLASH_CAP_TIMEOUT_SIZE;
+	info->flash_cap[1] = start_ptr;
+	info->flash_timeouts[1] = start_ptr + max77665_f_flash_cap_size;
+
+	info->flash_cap_size = MAX77665_FLASH_CAP_TIMEOUT_SIZE;
+
+	start_ptr += MAX77665_FLASH_CAP_TIMEOUT_SIZE;
+	info->torch_cap[0] = start_ptr;
+	info->torch_timeouts[0] = start_ptr + max77665_f_torch_cap_size;
+
+	start_ptr += MAX77665_TORCH_CAP_TIMEOUT_SIZE;
+	info->torch_cap[1] = start_ptr;
+	info->torch_timeouts[1] = start_ptr + max77665_f_torch_cap_size;
+
+	info->torch_cap_size = MAX77665_TORCH_CAP_TIMEOUT_SIZE;
+	dev_dbg(info->dev, "%s: %d(%d + %d), %d(%d + %d)\n", __func__,
+		info->flash_cap_size, max77665_f_flash_cap_size,
+		max77665_f_flash_timeout_size, info->torch_cap_size,
+		max77665_f_torch_cap_size, max77665_f_torch_timeout_size);
+}
+
 static int max77665_f_probe(struct platform_device *pdev)
 {
 	struct max77665_f_info *info;
@@ -1603,10 +1579,7 @@
 	} else
 		dev_warn(&pdev->dev, "%s NO platform data\n", __func__);
 
-	info->flash_cap = (void *)info + sizeof(*info);
-	info->torch_cap = (void *)info->flash_cap +
-				max77665_f_max_flash_cap_size;
-	info->sustainTime = SUSTAINTIME_DEF;
+	max77665_f_caps_layout(info);
 
 	max77665_f_update_config(info);
 
@@ -1619,10 +1592,6 @@
 
 	dev_set_drvdata(info->dev, info);
 	mutex_init(&info->mutex);
-	INIT_LIST_HEAD(&info->list);
-	spin_lock(&max77665_f_spinlock);
-	list_add_rcu(&info->list, &max77665_f_info_list);
-	spin_unlock(&max77665_f_spinlock);
 
 	if (info->pdata->dev_name != NULL)
 		strcpy(dname, info->pdata->dev_name);
@@ -1664,7 +1633,7 @@
 		"    PinState Values  = 0x%04x\n"
 		"    Max_Peak_Current = %dmA\n"
 		,
-		info->pwr_dev,
+		info->pwr_state,
 		info->config.led_mask,
 		info->regs.led1_curr,
 		info->regs.led2_curr,
@@ -1732,9 +1701,9 @@
 		break;
 	case 'p':
 		if (val)
-			max77665_f_power(info, NVC_PWR_ON);
+			max77665_f_power_set(info, NVC_PWR_ON);
 		else
-			max77665_f_power(info, NVC_PWR_OFF);
+			max77665_f_power_set(info, NVC_PWR_OFF);
 		break;
 	case 'k':
 		if (val & 0xffff)
diff --git a/drivers/media/video/tegra/ov5693.c b/drivers/media/video/tegra/ov5693.c
index f63d5ef..8c8797f 100644
--- a/drivers/media/video/tegra/ov5693.c
+++ b/drivers/media/video/tegra/ov5693.c
@@ -110,8 +110,9 @@
 	.res_chg_wait_time	= OV5693_RES_CHG_WAIT_TIME_MS,
 };
 
-static const struct ov5693_reg ov5693_2592x1944_i2c[] = {
+static const struct ov5693_reg ov5693_2592x1944_hdr_i2c[] = {
 	{OV5693_TABLE_RESET, 0},/* Including sw reset */
+
 	{0x3001, 0x0a},
 	{0x3002, 0x80},
 	{0x3006, 0x00},
@@ -128,10 +129,6 @@
 	{0x3021, 0x00},
 	{0x3022, 0x01},
 	{0x3028, 0x44},
-	{0x3090, 0x02},
-	{0x3091, 0x0e},
-	{0x3092, 0x00},
-	{0x3093, 0x00},
 	{0x3098, 0x03},
 	{0x3099, 0x1e},
 	{0x309a, 0x02},
@@ -154,19 +151,19 @@
 	{0x3405, 0x00},
 	{0x3406, 0x01},
 	{0x3500, 0x00},
-	{0x3501, 0x7b},
-	{0x3502, 0x00},
+	{0x3501, 0x9a},
+	{0x3502, 0x80},
 	{0x3503, 0x07},
 	{0x3504, 0x00},
 	{0x3505, 0x00},
 	{0x3506, 0x00},
-	{0x3507, 0x02},
-	{0x3508, 0x00},
-	{0x3509, 0x08},
+	{0x3507, 0x01},
+	{0x3508, 0x80},
+	{0x3509, 0x10},
 	{0x350a, 0x00},
 	{0x350b, 0x40},
 	{0x3601, 0x0a},
-	{0x3602, 0x18},
+	{0x3602, 0x38},
 	{0x3612, 0x80},
 	{0x3620, 0x54},
 	{0x3621, 0xc7},
@@ -209,6 +206,7 @@
 	{0x371e, 0xa1},
 	{0x371f, 0x0c},
 	{0x3721, 0x00},
+	{0x3724, 0x10},
 	{0x3726, 0x00},
 	{0x372a, 0x01},
 	{0x3730, 0x10},
@@ -235,6 +233,7 @@
 	{0x3759, 0x0f},
 	{0x376b, 0x44},
 	{0x375c, 0x04},
+	{0x3774, 0x10},
 	{0x3776, 0x00},
 	{0x377f, 0x08},
 	{0x3780, 0x22},
@@ -271,10 +270,10 @@
 	{0x3809, 0x20},
 	{0x380a, 0x07},
 	{0x380b, 0x98},
-	{0x380c, 0x0a},
-	{0x380d, 0x80},
-	{0x380e, 0x07},
-	{0x380f, 0xc0},
+	{0x380c, 0x0e},
+	{0x380d, 0x40},
+	{0x380e, 0x09},
+	{0x380f, 0xb4},
 	{0x3810, 0x00},
 	{0x3811, 0x02},
 	{0x3812, 0x00},
@@ -282,15 +281,15 @@
 	{0x3814, 0x11},
 	{0x3815, 0x11},
 	{0x3820, 0x00},
-	{0x3821, 0x1e},
+	{0x3821, 0x9e},
 	{0x3823, 0x00},
 	{0x3824, 0x00},
 	{0x3825, 0x00},
 	{0x3826, 0x00},
 	{0x3827, 0x00},
 	{0x382a, 0x04},
-	{0x3a04, 0x06},
-	{0x3a05, 0x14},
+	{0x3a04, 0x09},
+	{0x3a05, 0xa9},
 	{0x3a06, 0x00},
 	{0x3a07, 0xfe},
 	{0x3b00, 0x00},
@@ -298,25 +297,6 @@
 	{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},
@@ -325,10 +305,13 @@
 	{0x4005, 0x18},
 	{0x4006, 0x20},
 	{0x4008, 0x24},
-	{0x4009, 0x10},
+	{0x4009, 0x40},
 	{0x400c, 0x00},
 	{0x400d, 0x00},
 	{0x4058, 0x00},
+	{0x404e, 0x37},
+	{0x404f, 0x8f},
+	{0x4058, 0x00},
 	{0x4101, 0xb2},
 	{0x4303, 0x00},
 	{0x4304, 0x08},
@@ -382,262 +365,9 @@
 	{OV5693_TABLE_END, 0x0000}
 };
 
-static const struct ov5693_reg ov5693_1296x972_i2c[] = {
+static const struct ov5693_reg ov5693_1296x972_hdr_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, 0x10},
-	{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, 0x00},
-	{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},
@@ -676,15 +406,15 @@
 	{0x3405, 0x00},
 	{0x3406, 0x01},
 	{0x3500, 0x00},
-	{0x3501, 0x7b},
+	{0x3501, 0x72},
 	{0x3502, 0x00},
 	{0x3503, 0x07},
 	{0x3504, 0x00},
 	{0x3505, 0x00},
 	{0x3506, 0x00},
-	{0x3507, 0x02},
-	{0x3508, 0x00},
-	{0x3509, 0x08},
+	{0x3507, 0x01},
+	{0x3508, 0x80},
+	{0x3509, 0x10},
 	{0x350a, 0x00},
 	{0x350b, 0x40},
 	{0x3601, 0x0a},
@@ -783,22 +513,22 @@
 	{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},
+	{0x3800, 0x02},
+	{0x3801, 0xa0},
+	{0x3802, 0x01},
+	{0x3803, 0xe8},
+	{0x3804, 0x07},
+	{0x3805, 0xb7},
+	{0x3806, 0x05},
+	{0x3807, 0xb9},
+	{0x3808, 0x05},
+	{0x3809, 0x10},
+	{0x380a, 0x03},
+	{0x380b, 0xcc},
+	{0x380c, 0x0b},
+	{0x380d, 0x40},
 	{0x380e, 0x07},
-	{0x380f, 0xc0},
+	{0x380f, 0x3a},
 	{0x3810, 0x00},
 	{0x3811, 0x02},
 	{0x3812, 0x00},
@@ -806,269 +536,15 @@
 	{0x3814, 0x11},
 	{0x3815, 0x11},
 	{0x3820, 0x00},
-	{0x3821, 0x1e},
+	{0x3821, 0x9e},
 	{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, 0x10},
-	{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},
+	{0x3a04, 0x09},
+	{0x3a05, 0xa9},
 	{0x3a06, 0x00},
 	{0x3a07, 0xfe},
 	{0x3b00, 0x00},
@@ -1140,22 +616,532 @@
 	{0x5e00, 0x00},
 	{0x5e10, 0x0c},
 	{0x0100, 0x01},
-	{0x350b, 0xF8},
+
+	{OV5693_TABLE_END, 0x0000}
+};
+
+static const struct ov5693_reg ov5693_1920x1080_hdr_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, 0x72},
+	{0x3502, 0x00},
+	{0x3503, 0x07},
+	{0x3504, 0x00},
+	{0x3505, 0x00},
+	{0x3506, 0x00},
+	{0x3507, 0x01},
+	{0x3508, 0x80},
+	{0x3509, 0x10},
+	{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, 0x01},
+	{0x3801, 0x70},
+	{0x3802, 0x01},
+	{0x3803, 0xbc},
+	{0x3804, 0x09},
+	{0x3805, 0x0f},
+	{0x3806, 0x05},
+	{0x3807, 0xff},
+	{0x3808, 0x07},
+	{0x3809, 0x80},
+	{0x380a, 0x04},
+	{0x380b, 0x38},
+	{0x380c, 0x0b},
+	{0x380d, 0x40},
+	{0x380e, 0x07},
+	{0x380f, 0x3a},
+	{0x3810, 0x00},
+	{0x3811, 0x02},
+	{0x3812, 0x00},
+	{0x3813, 0x02},
+	{0x3814, 0x11},
+	{0x3815, 0x11},
+	{0x3820, 0x00},
+	{0x3821, 0x9e},
+	{0x3823, 0x00},
+	{0x3824, 0x00},
+	{0x3825, 0x00},
+	{0x3826, 0x00},
+	{0x3827, 0x00},
+	{0x382a, 0x04},
+	{0x3a04, 0x09},
+	{0x3a05, 0xa9},
+	{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, 0x10},
+	{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_1280x720_hdr_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, 0x39},
+	{0x3502, 0x00},
+	{0x3503, 0x07},
+	{0x3504, 0x00},
+	{0x3505, 0x00},
+	{0x3506, 0x00},
+	{0x3507, 0x01},
+	{0x3508, 0x80},
+	{0x3509, 0x10},
+	{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, 0x02},
+	{0x3801, 0xa8},
+	{0x3802, 0x02},
+	{0x3803, 0x68},
+	{0x3804, 0x07},
+	{0x3805, 0xb7},
+	{0x3806, 0x05},
+	{0x3807, 0x3b},
+	{0x3808, 0x05},
+	{0x3809, 0x00},
+	{0x380a, 0x02},
+	{0x380b, 0xd0},
+	{0x380c, 0x0b},
+	{0x380d, 0x40},
+	{0x380e, 0x03},
+	{0x380f, 0x9e},
+	{0x3810, 0x00},
+	{0x3811, 0x02},
+	{0x3812, 0x00},
+	{0x3813, 0x02},
+	{0x3814, 0x11},
+	{0x3815, 0x11},
+	{0x3820, 0x00},
+	{0x3821, 0x9e},
+	{0x3823, 0x00},
+	{0x3824, 0x00},
+	{0x3825, 0x00},
+	{0x3826, 0x00},
+	{0x3827, 0x00},
+	{0x382a, 0x04},
+	{0x3a04, 0x09},
+	{0x3a05, 0xa9},
+	{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, 0x10},
+	{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, 0x00},
+	{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}
 };
 
 enum {
-	OV5693_MODE_2592x1944 = 0,
-	OV5693_MODE_1920x1080,
-	OV5693_MODE_1296x972,
-	OV5693_MODE_1280x720_120FPS,
+	OV5693_MODE_2592x1944_HDR = 0,
+	OV5693_MODE_1920x1080_HDR,
+	OV5693_MODE_1296x972_HDR,
+	OV5693_MODE_1280x720_HDR,
 };
 
 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,
+	[OV5693_MODE_2592x1944_HDR]	= ov5693_2592x1944_hdr_i2c,
+	[OV5693_MODE_1920x1080_HDR]		= ov5693_1920x1080_hdr_i2c,
+	[OV5693_MODE_1296x972_HDR]		= ov5693_1296x972_hdr_i2c,
+	[OV5693_MODE_1280x720_HDR] = ov5693_1280x720_hdr_i2c,
 };
 
 static int ov5693_i2c_rd8(struct ov5693_info *info, u16 reg, u8 *val)
@@ -1241,8 +1227,9 @@
 }
 
 static inline int ov5693_coarse_time_reg(struct ov5693_reg *regs,
-					u32 coarse_time)
+					u32 coarse_time, u32 coarse_time_short)
 {
+	int ret = 0;
 	regs->addr = 0x3500;
 	regs->val = (coarse_time >> 12) & 0xff;
 	(regs + 1)->addr = 0x3501;
@@ -1250,7 +1237,20 @@
 	(regs + 2)->addr = 0x3502;
 	(regs + 2)->val = (coarse_time & 0xf) << 4;
 
-	return 3;
+	ret += 3;
+
+	if (coarse_time_short != OV5693_INVALID_COARSE_TIME) {
+		regs->addr = 0x3506;
+		regs->val = (coarse_time_short >> 12) & 0xff;
+		(regs + 1)->addr = 0x3507;
+		(regs + 1)->val = (coarse_time_short >> 4) & 0xff;
+		(regs + 2)->addr = 0x3508;
+		(regs + 2)->val = (coarse_time_short & 0xf) << 4;
+
+		ret += 3;
+	}
+
+	return ret;
 }
 
 #define OV5693_ENTER_GROUP_HOLD(group_hold) \
@@ -1294,14 +1294,17 @@
 }
 
 static int ov5693_set_coarse_time(struct ov5693_info *info,
-				  u32 coarse_time, bool group_hold)
+				  u32 coarse_time, u32 coarse_time_short,
+				  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);
+	offset += ov5693_coarse_time_reg(reg_list + offset,
+						coarse_time,
+						coarse_time_short);
 	OV5693_LEAVE_GROUP_HOLD(group_hold);
 
 	reg_list[offset].addr = OV5693_TABLE_END;
@@ -1343,7 +1346,9 @@
 	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_coarse_time_reg(reg_list + offset,
+						mode->coarse_time,
+						mode->coarse_time_short);
 	offset += ov5693_gain_reg(reg_list + offset, mode->gain);
 	OV5693_LEAVE_GROUP_HOLD(group_hold);
 
@@ -1389,7 +1394,7 @@
 						  ae->frame_length);
 	if (ae->coarse_time_enable)
 		offset += ov5693_coarse_time_reg(reg_list + offset,
-						 ae->coarse_time);
+			ae->coarse_time, OV5693_INVALID_COARSE_TIME);
 	OV5693_LEAVE_GROUP_HOLD(group_hold);
 
 	reg_list[offset].addr = OV5693_TABLE_END;
@@ -1406,7 +1411,7 @@
 	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);
+			   info->gpio[type].gpio, val);
 		if (!info->gpio[type].active_high)
 			val = !val;
 		val &= 1;
@@ -1427,7 +1432,7 @@
 		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);
+			   info->gpio[type].gpio, val);
 	}
 	return err; /* return value written or error */
 }
@@ -1712,23 +1717,19 @@
 	}
 
 	if (mode->res_x == 2592 && mode->res_y == 1944)
-		mode_index = OV5693_MODE_2592x1944;
+		mode_index = OV5693_MODE_2592x1944_HDR;
 	else if (mode->res_x == 1296 && mode->res_y == 972)
-		mode_index = OV5693_MODE_1296x972;
+		mode_index = OV5693_MODE_1296x972_HDR;
 	else if (mode->res_x == 1920 && mode->res_y == 1080)
-		mode_index = OV5693_MODE_1920x1080;
+		mode_index = OV5693_MODE_1920x1080_HDR;
 	else if (mode->res_x == 1280 && mode->res_y == 720)
-		mode_index = OV5693_MODE_1280x720_120FPS;
+		mode_index = OV5693_MODE_1280x720_HDR;
 
 	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;
@@ -1801,7 +1802,19 @@
 		return ov5693_set_frame_length(info, (u32)arg, true);
 
 	case OV5693_IOCTL_SET_COARSE_TIME:
-		return ov5693_set_coarse_time(info, (u32)arg, true);
+		return ov5693_set_coarse_time(info, (u32)arg,
+					OV5693_INVALID_COARSE_TIME, true);
+
+	case OV5693_IOCTL_SET_HDR_COARSE_TIME:
+	{
+		struct ov5693_hdr *hdrcoarse = (struct ov5693_hdr *)arg;
+		int ret = ov5693_set_coarse_time(info,
+				hdrcoarse->coarse_time_long,
+				hdrcoarse->coarse_time_short,
+				false);
+		return ret;
+	}
+
 
 	case OV5693_IOCTL_SET_GAIN:
 		return ov5693_set_gain(info, (u32)arg, true);
diff --git a/include/media/ar0833.h b/include/media/ar0833.h
new file mode 100644
index 0000000..1e32c14
--- /dev/null
+++ b/include/media/ar0833.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 Motorola, Inc.
+ * Copyright (C) 2012-2013, NVIDIA Corporation. 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 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., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#ifndef __AR0833_H__
+#define __AR0833_H__
+
+#include <linux/ioctl.h>  /* For IOCTL macros */
+
+#define AR0833_IOCTL_SET_MODE		_IOW('o', 1, struct ar0833_mode)
+#define AR0833_IOCTL_SET_FRAME_LENGTH	_IOW('o', 2, __u32)
+#define AR0833_IOCTL_SET_COARSE_TIME	_IOW('o', 3, __u32)
+#define AR0833_IOCTL_SET_GAIN		_IOW('o', 4, __u16)
+#define AR0833_IOCTL_GET_STATUS		_IOR('o', 5, __u8)
+#define AR0833_IOCTL_GET_MODE		_IOR('o', 6, struct ar0833_modeinfo)
+#define AR0833_IOCTL_SET_HDR_COARSE_TIME	_IOW('o', 7, struct ar0833_hdr)
+#define AR0833_IOCTL_SET_GROUP_HOLD	_IOW('o', 8, struct ar0833_ae)
+
+struct ar0833_mode {
+	int xres;
+	int yres;
+	__u32 frame_length;
+	__u32 coarse_time;
+	__u32 coarse_time_short;
+	__u16 gain;
+	__u8 hdr_en;
+};
+
+struct ar0833_modeinfo {
+	int xres;
+	int yres;
+	__u8 hdr;
+	__u8 lanes;
+	__u16 line_len;
+	__u16 frame_len;
+	__u16 coarse_time;
+	__u16 coarse_time_2nd;
+	__u16 xstart;
+	__u16 xend;
+	__u16 ystart;
+	__u16 yend;
+	__u16 xsize;
+	__u16 ysize;
+	__u16 gain;
+	__u8 x_flip;
+	__u8 y_flip;
+	__u8 x_bin;
+	__u8 y_bin;
+	__u16 vt_pix_clk_div;
+	__u16 vt_sys_clk_div;
+	__u16 pre_pll_clk_div;
+	__u16 pll_multi;
+	__u16 op_pix_clk_div;
+	__u16 op_sys_clk_div;
+};
+
+struct ar0833_hdr {
+	__u32 coarse_time_long;
+	__u32 coarse_time_short;
+};
+
+struct ar0833_ae {
+	__u32 frame_length;
+	__u8  frame_length_enable;
+	__u32 coarse_time;
+	__u32 coarse_time_short;
+	__u8  coarse_time_enable;
+	__s32 gain;
+	__u8  gain_enable;
+};
+
+struct ar0833_sensordata {
+	__u32 fuse_id_size;
+	__u8  fuse_id[16];
+};
+
+#ifdef __KERNEL__
+struct ar0833_power_rail {
+	struct regulator *dvdd;
+	struct regulator *avdd;
+	struct regulator *iovdd;
+};
+
+struct ar0833_platform_data {
+	int (*power_on)(struct ar0833_power_rail *pw);
+	int (*power_off)(struct ar0833_power_rail *pw);
+};
+#endif /* __KERNEL__ */
+
+#endif  /* __AR0833_H__ */
diff --git a/include/media/dw9718.h b/include/media/dw9718.h
new file mode 100644
index 0000000..7c88a8e
--- /dev/null
+++ b/include/media/dw9718.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010-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 __DW9718_H__
+#define __DW9718_H__
+
+#include <media/nvc_focus.h>
+#include <media/nvc.h>
+
+struct dw9718_power_rail {
+	struct regulator *vdd;
+	struct regulator *vdd_i2c;
+};
+
+struct dw9718_platform_data {
+	int cfg;
+	int num;
+	int sync;
+	const char *dev_name;
+	struct nvc_focus_nvc (*nvc);
+	struct nvc_focus_cap (*cap);
+	int gpio_count;
+	struct nvc_gpio_pdata *gpio;
+	int (*power_on)(struct dw9718_power_rail *pw);
+	int (*power_off)(struct dw9718_power_rail *pw);
+};
+
+/* Register Definitions */
+#define DW9718_POWER_DN		0x00
+#define DW9718_CONTROL			0x01
+#define DW9718_VCM_CODE_MSB		0x02
+#define DW9718_VCM_CODE_LSB		0x03
+#define DW9718_SWITCH_MODE		0x04
+#define DW9718_SACT			0x05
+#define DW9718_STATUS			0x06
+
+#endif  /* __DW9718_H__ */
diff --git a/include/media/imx135.h b/include/media/imx135.h
new file mode 100644
index 0000000..d7d0196
--- /dev/null
+++ b/include/media/imx135.h
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2012-2013, NVIDIA Corporation.  All rights reserved.
+ *
+ * NVIDIA Corporation and its licensors retain all intellectual property
+ * and proprietary rights in and to this software and related documentation
+ * and any modifications thereto.  Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA Corporation is strictly prohibited.
+ */
+
+#ifndef __IMX135_H__
+#define __IMX135_H__
+
+#include <linux/ioctl.h>  /* For IOCTL macros */
+#include <media/nvc.h>
+#include <media/nvc_image.h>
+
+#define IMX135_IOCTL_SET_MODE		_IOW('o', 1, struct imx135_mode)
+#define IMX135_IOCTL_GET_STATUS		_IOR('o', 2, __u8)
+#define IMX135_IOCTL_SET_FRAME_LENGTH	_IOW('o', 3, __u32)
+#define IMX135_IOCTL_SET_COARSE_TIME	_IOW('o', 4, __u32)
+#define IMX135_IOCTL_SET_GAIN		_IOW('o', 5, __u16)
+#define IMX135_IOCTL_GET_SENSORDATA	_IOR('o', 6, struct imx135_sensordata)
+#define IMX135_IOCTL_SET_GROUP_HOLD	_IOW('o', 7, struct imx135_ae)
+#define IMX135_IOCTL_SET_HDR_COARSE_TIME	_IOW('o', 8, struct imx135_hdr)
+
+struct imx135_mode {
+	int xres;
+	int yres;
+	__u32 frame_length;
+	__u32 coarse_time;
+	__u32 coarse_time_short;
+	__u16 gain;
+	__u8 hdr_en;
+};
+
+struct imx135_hdr {
+	__u32 coarse_time_long;
+	__u32 coarse_time_short;
+};
+
+struct imx135_ae {
+	__u32 frame_length;
+	__u8  frame_length_enable;
+	__u32 coarse_time;
+	__u32 coarse_time_short;
+	__u8  coarse_time_enable;
+	__s32 gain;
+	__u8  gain_enable;
+};
+
+struct imx135_sensordata {
+	__u32 fuse_id_size;
+	__u8  fuse_id[16];
+};
+
+#ifdef __KERNEL__
+struct imx135_power_rail {
+	struct regulator *dvdd;
+	struct regulator *avdd;
+	struct regulator *iovdd;
+};
+
+struct imx135_platform_data {
+	int (*power_on)(struct imx135_power_rail *pw);
+	int (*power_off)(struct imx135_power_rail *pw);
+};
+#endif /* __KERNEL__ */
+
+#endif  /* __IMX135_H__ */
diff --git a/include/media/nvc.h b/include/media/nvc.h
index ec5d6ae..4158469 100644
--- a/include/media/nvc.h
+++ b/include/media/nvc.h
@@ -1,18 +1,16 @@
-/* Copyright (C) 2012 NVIDIA Corporation.
- *
- * 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.
- *
+/* Copyright (c) 2012 - 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __NVC_H__
@@ -27,6 +25,7 @@
 struct nvc_param {
 	int param;
 	__u32 sizeofvalue;
+	__u32 variant;
 	void *p_value;
 } __packed;
 
@@ -80,6 +79,9 @@
 	NVC_PARAM_DEV_ID,
 	NVC_PARAM_GROUP_HOLD,
 	NVC_PARAM_SET_SENSOR_FLASH_MODE,
+	NVC_PARAM_TORCH_QUERY,
+	NVC_PARAM_FLASH_EXT_CAPS,
+	NVC_PARAM_TORCH_EXT_CAPS,
 	NVC_PARAM_BEGIN_VENDOR_EXTENSIONS = 0x10000000,
 	NVC_PARAM_CALIBRATION_STATUS,
 	NVC_PARAM_TEST_PATTERN,
diff --git a/include/media/ov5693.h b/include/media/ov5693.h
index d81c36b..a093919 100644
--- a/include/media/ov5693.h
+++ b/include/media/ov5693.h
@@ -34,7 +34,9 @@
 #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)
+#define OV5693_IOCTL_SET_HDR_COARSE_TIME	_IOW('o', 13, struct ov5693_hdr)
 
+#define OV5693_INVALID_COARSE_TIME	-1
 
 struct ov5693_mode {
 	int res_x;
@@ -42,6 +44,7 @@
 	int fps;
 	__u32 frame_length;
 	__u32 coarse_time;
+	__u32 coarse_time_short;
 	__u16 gain;
 };
 
@@ -49,6 +52,7 @@
 	__u32 frame_length;
 	__u8  frame_length_enable;
 	__u32 coarse_time;
+	__u16 coarse_time_short;
 	__u8  coarse_time_enable;
 	__s32 gain;
 	__u8  gain_enable;
@@ -59,6 +63,12 @@
 	__u8  id[16];
 };
 
+struct ov5693_hdr {
+	__u32 coarse_time_long;
+	__u32 coarse_time_short;
+};
+
+
 /* See notes in the nvc.h file on the GPIO usage */
 enum ov5693_gpio_type {
 	OV5693_GPIO_TYPE_PWRDN = 0,