media: video: tegra: add ar0833 HDR sensor
Frank Chen [Thu, 27 Dec 2012 23:28:27 +0000 (15:28 -0800)]
Add driver support for ar0833 HDR sensor

Bug 1250073

Change-Id: I47033e64955153dbfa510a7470e9999ba26d4208
Signed-off-by: Frank Chen <frankc@nvidia.com>
Signed-off-by: David Schalig <dschalig@nvidia.com>
Reviewed-on: http://git-master/r/206769
(cherry picked from commit 3b926a89b0db6fcf74c99f878d5913d84738d250)
Reviewed-on: http://git-master/r/227906
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

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

index 0f9d733..460f362 100644 (file)
@@ -169,3 +169,10 @@ config VIDEO_DW9718
         ---help---
           This is a driver for the DW9718 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.
index ffd8c03..f867c25 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_TEGRA_MEDIASERVER) += mediaserver/
 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
diff --git a/drivers/media/video/tegra/ar0833.c b/drivers/media/video/tegra/ar0833.c
new file mode 100644 (file)
index 0000000..0d1e771
--- /dev/null
@@ -0,0 +1,1202 @@
+/*
+ * 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"
+
+static struct ar0833_reg set_param_grphold_tbl[] = {
+       /* Enable Group Hold */
+       {0x0104 | AR0833_TABLE_8BIT, 0x0001},
+       /* place holders */
+       {AR0833_TABLE_NOP, 0x0000},
+       {AR0833_TABLE_NOP, 0x0000},
+       /* Release Group Hold */
+       {0x0104 | AR0833_TABLE_8BIT, 0x0000},
+       {AR0833_TABLE_END, 0x0000},
+};
+
+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_frame_length_regs(struct ar0833_reg *regs,
+                                               u32 frame_length)
+{
+       regs->addr = 0x0340;
+       regs->val = frame_length & 0xFFFF;
+}
+
+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_frame_length(struct ar0833_info *info, u32 frame_length)
+{
+       int ret;
+
+       dev_dbg(&info->i2c_client->dev, "%s 0x%x\n", __func__, frame_length);
+       set_param_grphold_tbl[1].addr = 0x0340;
+       set_param_grphold_tbl[1].val = (u16)frame_length;
+       ret = ar0833_write_table(info, set_param_grphold_tbl, NULL, 0);
+       set_param_grphold_tbl[1].addr = AR0833_TABLE_NOP;
+
+       return ret;
+}
+
+static int ar0833_set_coarse_time(struct ar0833_info *info, u32 coarse_time)
+{
+       int ret;
+
+       dev_dbg(&info->i2c_client->dev, "%s 0x%x\n", __func__, coarse_time);
+       set_param_grphold_tbl[1].addr = 0x0202;
+       set_param_grphold_tbl[1].val = (u16)coarse_time;
+       ret = ar0833_write_table(info, set_param_grphold_tbl, NULL, 0);
+       set_param_grphold_tbl[1].addr = AR0833_TABLE_NOP;
+
+       return ret;
+}
+
+static int ar0833_set_hdr_coarse_time(
+       struct ar0833_info *info, struct ar0833_hdr *values)
+{
+       int ret;
+
+       dev_dbg(&info->i2c_client->dev, "%s 0x%04x 0x%04x\n",
+               __func__, values->coarse_time_long, values->coarse_time_short);
+       set_param_grphold_tbl[1].addr = 0x0202;
+       set_param_grphold_tbl[1].val = values->coarse_time_long;
+       set_param_grphold_tbl[2].addr = 0x3088;
+       set_param_grphold_tbl[2].val = values->coarse_time_short;
+       ret = ar0833_write_table(info, set_param_grphold_tbl, NULL, 0);
+       set_param_grphold_tbl[1].addr = AR0833_TABLE_NOP;
+       set_param_grphold_tbl[2].addr = AR0833_TABLE_NOP;
+
+       return ret;
+}
+
+static int ar0833_set_gain(struct ar0833_info *info, u16 gain)
+{
+       int ret;
+
+       dev_dbg(&info->i2c_client->dev, "%s 0x%04x\n", __func__, gain);
+       set_param_grphold_tbl[1].addr = 0x305e;
+       set_param_grphold_tbl[1].val = gain;
+       ret = ar0833_write_table(info, set_param_grphold_tbl, NULL, 0);
+       set_param_grphold_tbl[1].addr = AR0833_TABLE_NOP;
+
+       return ret;
+}
+
+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_frame_length_regs(reg_list, mode->frame_length);
+       ar0833_get_coarse_time_regs(reg_list + 1, mode->coarse_time);
+       ar0833_get_gain_reg(reg_list + 2, mode->gain);
+       if (mode->hdr_en == 1)  /* if HDR is enabled */
+               ar0833_get_coarse_time_short_regs(
+                       reg_list + 3, mode->coarse_time_short);
+
+       err = ar0833_write_table(
+               info, sensor_mode->mode_tbl, reg_list, mode->hdr_en ? 4 : 3);
+       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);
+               err = ar0833_set_frame_length(info, (u32)arg);
+               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);
+               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);
+               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);
+               break;
+       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 (file)
index 0000000..33bc7aa
--- /dev/null
@@ -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, 100},
+       /* 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=100
+ * 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, 100},
+       {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, 100},
+       /*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=100
+ * 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, 100},
+       {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=100
+ * 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, 100},
+       /*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=100
+ * 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, 100},
+       {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=100
+ * 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, 100},
+       {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/include/media/ar0833.h b/include/media/ar0833.h
new file mode 100644 (file)
index 0000000..12f66e0
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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)
+
+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_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__ */