]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
drivers: media: i2c: IMX185 sensor
authoresenc <esenc@nvidia.com>
Mon, 22 Feb 2016 02:32:12 +0000 (10:32 +0800)
committermobile promotions <svcmobile_promotions@nvidia.com>
Thu, 17 Mar 2016 07:22:25 +0000 (00:22 -0700)
Bug 200160365
Bug 200168141

DEPENDS ON: <http://git-master/r/1019687>

Change-Id: Ia6906a83e07a4e437909b37cd824131240991dab
Signed-off-by: esenc <esenc@nvidia.com>
Signed-off-by: Rui Zhuo <rzhuo@nvidia.com>
Reviewed-on: http://git-master/r/1019677
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
drivers/media/i2c/Kconfig
drivers/media/i2c/Makefile
drivers/media/i2c/imx185.c [new file with mode: 0644]
drivers/media/i2c/imx185_mode_tbls.h [new file with mode: 0644]
include/media/imx185.h [new file with mode: 0644]

index b1a3599026c16f44d75fd33fe4fb203304fe91b2..91c727da710fdb442dd92760292118b36e9da4e1 100644 (file)
@@ -518,6 +518,16 @@ config VIDEO_IMX274
        To compile this driver as a module, choose M here: the module
        will be called imx274.
 
+config VIDEO_IMX185
+       tristate "IMX185 camera sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       ---help---
+       This is a Video4Linux2 sensor-level driver for the Sony
+       IMX185 camera sensor
+
+       To compile this driver as a module, choose M here: the module
+       will be called imx185.
+
 config VIDEO_VS6624
        tristate "ST VS6624 sensor support"
        depends on VIDEO_V4L2 && I2C
index 8e1deffa2060722b38c46277e6bb91c7445cadc6..f91dbf693c7349e8c81d20eccd8d464f5b5c51e8 100644 (file)
@@ -58,6 +58,7 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
 obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
 obj-$(CONFIG_VIDEO_IMX219) += imx219.o
 obj-$(CONFIG_VIDEO_IMX274) += imx274.o
+obj-$(CONFIG_VIDEO_IMX185) += imx185.o
 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 obj-$(CONFIG_VIDEO_OV23850) += ov23850.o
 obj-$(CONFIG_VIDEO_LC898212) += lc898212.o
diff --git a/drivers/media/i2c/imx185.c b/drivers/media/i2c/imx185.c
new file mode 100644 (file)
index 0000000..042da89
--- /dev/null
@@ -0,0 +1,1142 @@
+/*
+ * imx185.c - imx185 sensor driver
+ *
+ * Copyright (c) 2016, 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/slab.h>
+#include <linux/uaccess.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include <linux/seq_file.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+
+#include <media/camera_common.h>
+#include <media/imx185.h>
+#include "imx185_mode_tbls.h"
+
+
+#define TESTING_10BIT  1
+
+#ifdef TESTING_10BIT
+#define IMX185_DEFAULT_MODE    IMX185_MODE_1920X1080_CROP_10BIT
+#define IMX185_DEFAULT_DATAFMT V4L2_MBUS_FMT_SRGGB10_1X10
+#else
+#define IMX185_DEFAULT_MODE    IMX185_MODE_1920X1080_CROP
+#define IMX185_DEFAULT_DATAFMT V4L2_MBUS_FMT_SRGGB12_1X12
+#endif
+
+#define IMX185_MAX_COARSE_DIFF 2
+#define IMX185_MAX_COARSE_DIFF_HDR 5
+#define IMX185_GAIN_SHIFT              0
+#define IMX185_MIN_GAIN                (1)
+#define IMX185_MAX_GAIN                (255)
+#define IMX185_MIN_FRAME_LENGTH        (1125)
+#define IMX185_MAX_FRAME_LENGTH        (0xFFFF)
+#define IMX185_MIN_EXPOSURE_COARSE     (0x0001)
+#define IMX185_MAX_EXPOSURE_COARSE     \
+       (IMX185_MAX_FRAME_LENGTH-IMX185_MAX_COARSE_DIFF)
+
+#define IMX185_MIN_FRAME_LENGTH_1080P_HDR      (1125)
+#define IMX185_MIN_EXPOSURE_COARSE_1080P_HDR_SHS1      (5)
+#define IMX185_MAX_EXPOSURE_COARSE_1080P_HDR_SHS1      (70)
+#define IMX185_MIN_EXPOSURE_COARSE_1080P_HDR_SHS2      (80)
+#define IMX185_MAX_EXPOSURE_COARSE_1080P_HDR_SHS2      (1120)
+
+
+#define IMX185_DEFAULT_WIDTH   1920
+#define IMX185_DEFAULT_HEIGHT  1080
+#define IMX185_DEFAULT_GAIN            IMX185_MIN_GAIN
+#define IMX185_DEFAULT_FRAME_LENGTH    (1125)
+#define IMX185_DEFAULT_EXPOSURE_COARSE \
+       (IMX185_DEFAULT_FRAME_LENGTH-IMX185_MAX_COARSE_DIFF)
+#define IMX185_DEFAULT_EXPOSURE_COARSE_SHORT_HDR       \
+       (IMX185_MAX_EXPOSURE_COARSE_1080P_HDR_SHS1- \
+       IMX185_MAX_COARSE_DIFF_HDR)
+
+
+#define IMX185_DEFAULT_CLK_FREQ        37125000
+
+
+struct imx185 {
+       struct camera_common_power_rail power;
+       int                             num_ctrls;
+       struct v4l2_ctrl_handler        ctrl_handler;
+       struct i2c_client               *i2c_client;
+       struct v4l2_subdev              *subdev;
+       struct media_pad                pad;
+
+       s32 group_hold_prev;
+       bool group_hold_en;
+       u32     frame_length;
+
+       u32 i2c_channel;
+       struct i2c_client *pca954x_i2c_client;
+       struct i2c_adapter *pca954x_adap;
+       struct i2c_board_info pca954x_brd;
+       struct regmap *pca954x_regmap;
+
+       struct regmap                   *regmap;
+       struct camera_common_data       *s_data;
+       struct camera_common_pdata      *pdata;
+       struct v4l2_ctrl                *ctrls[];
+};
+
+static const struct regmap_config sensor_regmap_config = {
+       .reg_bits = 16,
+       .val_bits = 8,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static int imx185_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
+static int imx185_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops imx185_ctrl_ops = {
+       .g_volatile_ctrl = imx185_g_volatile_ctrl,
+       .s_ctrl = imx185_s_ctrl,
+};
+
+static struct v4l2_ctrl_config ctrl_config_list[] = {
+/* Do not change the name field for the controls! */
+       {
+               .ops = &imx185_ctrl_ops,
+               .id = V4L2_CID_GAIN,
+               .name = "Gain",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .flags = V4L2_CTRL_FLAG_SLIDER,
+               .min = IMX185_MIN_GAIN,
+               .max = IMX185_MAX_GAIN,
+               .def = IMX185_DEFAULT_GAIN,
+               .step = 1,
+       },
+       {
+               .ops = &imx185_ctrl_ops,
+               .id = V4L2_CID_FRAME_LENGTH,
+               .name = "Frame Length",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .flags = V4L2_CTRL_FLAG_SLIDER,
+               .min = IMX185_MIN_FRAME_LENGTH,
+               .max = IMX185_MAX_FRAME_LENGTH,
+               .def = IMX185_DEFAULT_FRAME_LENGTH,
+               .step = 1,
+       },
+       {
+               .ops = &imx185_ctrl_ops,
+               .id = V4L2_CID_COARSE_TIME,
+               .name = "Coarse Time",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .flags = V4L2_CTRL_FLAG_SLIDER,
+               .min = IMX185_MIN_EXPOSURE_COARSE,
+               .max = IMX185_MAX_EXPOSURE_COARSE,
+               .def = IMX185_DEFAULT_EXPOSURE_COARSE,
+               .step = 1,
+       },
+       {
+               .ops = &imx185_ctrl_ops,
+               .id = V4L2_CID_COARSE_TIME_SHORT,
+               .name = "Coarse Time Short",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .flags = V4L2_CTRL_FLAG_SLIDER,
+               .min = IMX185_MIN_EXPOSURE_COARSE_1080P_HDR_SHS1,
+               .max = IMX185_MAX_EXPOSURE_COARSE_1080P_HDR_SHS1,
+               .def = IMX185_DEFAULT_EXPOSURE_COARSE_SHORT_HDR,
+               .step = 1,
+       },
+       {
+               .ops = &imx185_ctrl_ops,
+               .id = V4L2_CID_GROUP_HOLD,
+               .name = "Group Hold",
+               .type = V4L2_CTRL_TYPE_INTEGER_MENU,
+               .min = 0,
+               .max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
+               .menu_skip_mask = 0,
+               .def = 0,
+               .qmenu_int = switch_ctrl_qmenu,
+       },
+       {
+               .ops = &imx185_ctrl_ops,
+               .id = V4L2_CID_HDR_EN,
+               .name = "HDR enable",
+               .type = V4L2_CTRL_TYPE_INTEGER_MENU,
+               .min = 0,
+               .max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
+               .menu_skip_mask = 0,
+               .def = 0,
+               .qmenu_int = switch_ctrl_qmenu,
+       },
+       {
+               .ops = &imx185_ctrl_ops,
+               .id = V4L2_CID_FUSE_ID,
+               .name = "Fuse ID",
+               .type = V4L2_CTRL_TYPE_STRING,
+               .flags = V4L2_CTRL_FLAG_READ_ONLY,
+               .min = 0,
+               .max = IMX185_FUSE_ID_STR_SIZE,
+               .step = 2,
+       },
+};
+
+static inline void imx185_get_frame_length_regs(imx185_reg *regs,
+                               u16 frame_length)
+{
+       regs->addr = IMX185_FRAME_LENGTH_ADDR_MID;
+       regs->val = (frame_length >> 8) & 0xff;
+
+       (regs + 1)->addr = IMX185_FRAME_LENGTH_ADDR_LSB;
+       (regs + 1)->val = (frame_length) & 0xff;
+}
+
+static inline void imx185_get_coarse_time_regs_shs1(imx185_reg *regs,
+                               u16 coarse_time)
+{
+       regs->addr = IMX185_COARSE_TIME_SHS1_ADDR_MID;
+       regs->val = (coarse_time >> 8) & 0xff;
+
+       (regs + 1)->addr = IMX185_COARSE_TIME_SHS1_ADDR_LSB;
+       (regs + 1)->val = (coarse_time) & 0xff;
+}
+
+static inline void imx185_get_coarse_time_regs_shs2(imx185_reg *regs,
+                               u16 coarse_time)
+{
+       regs->addr = IMX185_COARSE_TIME_SHS2_ADDR_MID;
+       regs->val = (coarse_time >> 8) & 0xff;
+
+       (regs + 1)->addr = IMX185_COARSE_TIME_SHS2_ADDR_LSB;
+       (regs + 1)->val = (coarse_time) & 0xff;
+}
+
+static inline void imx185_get_gain_reg(imx185_reg *regs,
+                               u8 gain)
+{
+       regs->addr = IMX185_GAIN_ADDR;
+       regs->val = (gain) & 0xff;
+}
+
+static int test_mode;
+module_param(test_mode, int, 0644);
+
+static inline int imx185_read_reg(struct camera_common_data *s_data,
+                               u16 addr, u8 *val)
+{
+       struct imx185 *priv = (struct imx185 *)s_data->priv;
+       return regmap_read(priv->regmap, addr, (unsigned int *) val);
+}
+
+static int imx185_write_reg(struct camera_common_data *s_data,
+                               u16 addr, u8 val)
+{
+       int err;
+       struct imx185 *priv = (struct imx185 *)s_data->priv;
+
+       err = regmap_write(priv->regmap, addr, val);
+       if (err)
+               pr_err("%s:i2c write failed, 0x%x = %x\n",
+                       __func__, addr, val);
+
+       return err;
+}
+
+
+
+static int imx185_write_table(struct imx185 *priv,
+                               const imx185_reg table[])
+{
+       return regmap_util_write_table_8(priv->regmap,
+                                        table,
+                                        NULL, 0,
+                                        IMX185_TABLE_WAIT_MS,
+                                        IMX185_TABLE_END);
+}
+
+static int pca954x_device_release(struct imx185 *priv)
+{
+       if (priv->pca954x_i2c_client != NULL) {
+               i2c_unregister_device(priv->pca954x_i2c_client);
+               priv->pca954x_i2c_client = NULL;
+       }
+       return 0;
+}
+
+static int pca954x_device_init(struct imx185 *priv)
+{
+       int err;
+       char *dev_name = "pca954x";
+
+       static  struct regmap_config pca954x_regmap_config = {
+               .reg_bits = 8,
+               .val_bits = 8,
+               .cache_type = REGCACHE_RBTREE,
+       };
+
+       priv->pca954x_adap = i2c_get_adapter(
+                       priv->i2c_client->adapter->nr);
+       memset(&priv->pca954x_brd, 0, sizeof(priv->pca954x_brd));
+       strncpy(priv->pca954x_brd.type, dev_name,
+                       sizeof(priv->pca954x_brd.type));
+
+       priv->pca954x_brd.addr = IMX185_PCA954X_I2C_ADDR;
+       priv->pca954x_i2c_client = i2c_new_device(
+                       priv->pca954x_adap, &priv->pca954x_brd);
+
+       priv->pca954x_regmap = devm_regmap_init_i2c(
+               priv->pca954x_i2c_client, &pca954x_regmap_config);
+       if (IS_ERR(priv->pca954x_regmap)) {
+               err = PTR_ERR(priv->pca954x_regmap);
+               pca954x_device_release(priv);
+               return err;
+       }
+       return 0;
+}
+
+static int pca954x_write_reg(struct camera_common_data *s_data,
+                               u8 addr, u8 val)
+{
+       int err;
+       struct imx185 *priv = (struct imx185 *)s_data->priv;
+
+       err = regmap_write(priv->pca954x_regmap, addr, val);
+       if (err)
+               pr_err("%s:i2c write failed, 0x%x = %x\n",
+                       __func__, addr, val);
+
+       return err;
+}
+
+static int imx185_power_on(struct camera_common_data *s_data)
+{
+       int err = 0;
+       struct imx185 *priv = (struct imx185 *)s_data->priv;
+       struct camera_common_power_rail *pw = &priv->power;
+
+       dev_dbg(&priv->i2c_client->dev, "%s: power on\n", __func__);
+       if (priv->pdata && priv->pdata->power_on) {
+               err = priv->pdata->power_on(pw);
+               if (err) {
+                       pr_err("%s failed.\n", __func__);
+                       return err;
+               }
+       }
+
+       /*exit reset mode: XCLR */
+       if (pw->reset_gpio) {
+               gpio_set_value(pw->reset_gpio, 0);
+               usleep_range(30, 50);
+               gpio_set_value(pw->reset_gpio, 1);
+               usleep_range(30, 50);
+       }
+
+       pw->state = SWITCH_ON;
+       return 0;
+
+}
+
+static int imx185_power_off(struct camera_common_data *s_data)
+{
+       int err = 0;
+       struct imx185 *priv = (struct imx185 *)s_data->priv;
+       struct camera_common_power_rail *pw = &priv->power;
+
+       dev_dbg(&priv->i2c_client->dev, "%s: power off\n", __func__);
+       if (priv->pdata && priv->pdata->power_off) {
+               err = priv->pdata->power_off(pw);
+               if (err) {
+                       pr_err("%s failed.\n", __func__);
+                       return err;
+               }
+       }
+       /* enter reset mode: XCLR */
+       usleep_range(1, 2);
+       if (pw->reset_gpio)
+               gpio_set_value(pw->reset_gpio, 0);
+
+       pw->state = SWITCH_OFF;
+
+       return 0;
+}
+
+static int imx185_power_put(struct imx185 *priv)
+{
+       struct camera_common_power_rail *pw = &priv->power;
+       if (unlikely(!pw))
+               return -EFAULT;
+       return 0;
+}
+
+static int imx185_power_get(struct imx185 *priv)
+{
+       struct camera_common_power_rail *pw = &priv->power;
+       struct camera_common_pdata *pdata = priv->pdata;
+       const char *mclk_name;
+       const char *parentclk_name;
+       struct clk *parent;
+       int err = 0;
+
+       mclk_name = priv->pdata->mclk_name ?
+                               priv->pdata->mclk_name : "cam_mclk1";
+       pw->mclk = devm_clk_get(&priv->i2c_client->dev, mclk_name);
+       if (IS_ERR(pw->mclk)) {
+               dev_err(&priv->i2c_client->dev,
+                       "unable to get clock %s\n", mclk_name);
+               return PTR_ERR(pw->mclk);
+       }
+
+       parentclk_name = priv->pdata->parentclk_name;
+       if (parentclk_name) {
+               parent = devm_clk_get(&priv->i2c_client->dev, parentclk_name);
+               if (IS_ERR(parent)) {
+                       dev_err(&priv->i2c_client->dev,
+                               "unable to get parent clcok %s",
+                               parentclk_name);
+               } else
+                       clk_set_parent(pw->mclk, parent);
+       }
+
+       if (pdata->regulators.iovdd != NULL)
+               camera_common_regulator_get(priv->i2c_client,
+                               &pw->iovdd, pdata->regulators.iovdd);
+       if (!err)
+               pw->reset_gpio = pdata->reset_gpio;
+
+       pw->state = SWITCH_OFF;
+       return err;
+}
+
+static int imx185_set_gain(struct imx185 *priv, s32 val);
+static int imx185_set_frame_length(struct imx185 *priv, s32 val);
+static int imx185_set_coarse_time(struct imx185 *priv, s32 val);
+static int imx185_set_coarse_time_shs1(struct imx185 *priv, s32 val);
+static int imx185_set_coarse_time_hdr_shs2(struct imx185 *priv, s32 val);
+
+static int imx185_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct camera_common_data *s_data = to_camera_common_data(client);
+       struct imx185 *priv = (struct imx185 *)s_data->priv;
+       struct v4l2_control control;
+       int err;
+
+       dev_dbg(&client->dev, "%s++ enable %d\n", __func__, enable);
+
+       err =  imx185_write_table(priv, mode_table[IMX185_MODE_STOP_STREAM]);
+       if (err)
+               goto exit;
+       if (!enable)
+               return err;
+
+       err = imx185_write_table(priv, mode_table[s_data->mode]);
+       if (err)
+               goto exit;
+       /* write list of override regs for the asking frame length, */
+       /* coarse integration time, and gain. Failures to write
+        * overrides are non-fatal */
+       control.id = V4L2_CID_GAIN;
+       err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
+       err |= imx185_set_gain(priv, control.value);
+       if (err)
+               dev_dbg(&client->dev, "%s: warning gain override failed\n",
+                       __func__);
+
+       control.id = V4L2_CID_FRAME_LENGTH;
+       err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
+       err |= imx185_set_frame_length(priv, control.value);
+       if (err)
+               dev_dbg(&client->dev,
+                       "%s: warning frame length override failed\n", __func__);
+
+       control.id = V4L2_CID_COARSE_TIME;
+       err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
+       err |= imx185_set_coarse_time(priv, control.value);
+       if (err)
+               dev_dbg(&client->dev,
+                       "%s: warning coarse time override failed\n", __func__);
+
+       control.id = V4L2_CID_COARSE_TIME_SHORT;
+       err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
+       err |= imx185_set_coarse_time_shs1(priv, control.value);
+       if (err)
+               dev_dbg(&client->dev,
+                       "%s: warning coarse time short override failed\n",
+                       __func__);
+       if (test_mode)
+               err = imx185_write_table(priv,
+                       mode_table[IMX185_MODE_TEST_PATTERN]);
+
+       err = imx185_write_table(priv, mode_table[IMX185_MODE_START_STREAM]);
+       if (err)
+               goto exit;
+
+       return 0;
+exit:
+       dev_dbg(&client->dev, "%s: error setting stream\n", __func__);
+       return err;
+}
+
+static struct v4l2_subdev_video_ops imx185_subdev_video_ops = {
+       .s_stream       = imx185_s_stream,
+       .s_mbus_fmt     = camera_common_s_fmt,
+       .g_mbus_fmt     = camera_common_g_fmt,
+       .try_mbus_fmt   = camera_common_try_fmt,
+       .enum_mbus_fmt  = camera_common_enum_fmt,
+       .g_mbus_config  = camera_common_g_mbus_config,
+};
+
+static struct v4l2_subdev_core_ops imx185_subdev_core_ops = {
+       .s_power        = camera_common_s_power,
+};
+
+static struct v4l2_subdev_ops imx185_subdev_ops = {
+       .core   = &imx185_subdev_core_ops,
+       .video  = &imx185_subdev_video_ops,
+};
+
+static struct of_device_id imx185_of_match[] = {
+       { .compatible = "nvidia,imx185", },
+       { },
+};
+
+static struct camera_common_sensor_ops imx185_common_ops = {
+       .power_on = imx185_power_on,
+       .power_off = imx185_power_off,
+       .write_reg = imx185_write_reg,
+       .read_reg = imx185_read_reg,
+};
+
+static int imx185_set_group_hold(struct imx185 *priv, s32 val)
+{
+       int err;
+       int gh_en = switch_ctrl_qmenu[val];
+
+       priv->group_hold_prev = val;
+       if (gh_en == SWITCH_ON) {
+
+               err = imx185_write_reg(priv->s_data,
+                                      IMX185_GROUP_HOLD_ADDR, 0x1);
+               if (err)
+                       goto fail;
+       } else if (gh_en == SWITCH_OFF) {
+               err = imx185_write_reg(priv->s_data,
+                                      IMX185_GROUP_HOLD_ADDR, 0x0);
+               if (err)
+                       goto fail;
+       }
+       return 0;
+fail:
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: Group hold control error\n", __func__);
+       return err;
+}
+
+static int imx185_calculate_gain(u32 rep, int shift)
+{
+       u8 gain;
+       int i;
+
+       if (rep < IMX185_MIN_GAIN || rep > IMX185_MAX_GAIN) {
+               pr_err("%s: %d is not a valid gain\n", __func__, rep);
+               return -ENODEV;
+       }
+
+       if (rep == (imx185_gain_lookup_table[rep-1].gain_x))
+               gain = imx185_gain_lookup_table[rep-1].reg_val;
+       else
+               pr_err("%s: invalid gain set, rep=%d\n", __func__, rep);
+
+       return gain;
+}
+
+static int imx185_set_gain(struct imx185 *priv, s32 val)
+{
+       imx185_reg reg_list[1];
+       int err;
+       u8 gain;
+
+       /* translate value */
+       gain = (u8)imx185_calculate_gain(val, IMX185_GAIN_SHIFT);
+
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: val: %d gain: %d\n", __func__, val, gain);
+
+       imx185_get_gain_reg(reg_list, gain);
+
+       err = imx185_write_table(priv, reg_list);
+       if (err)
+               goto fail;
+
+       return 0;
+
+fail:
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: GAIN control error\n", __func__);
+       return err;
+}
+
+static int imx185_set_frame_length(struct imx185 *priv, s32 val)
+{
+       imx185_reg reg_list[2];
+       int err;
+       u16 frame_length;
+
+       frame_length = val;
+
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: val: %d\n", __func__, frame_length);
+
+       priv->frame_length = frame_length;
+       imx185_get_frame_length_regs(reg_list, frame_length);
+       err = imx185_write_table(priv, reg_list);
+       if (err)
+               goto fail;
+
+       return 0;
+
+fail:
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: FRAME_LENGTH control error\n", __func__);
+       return err;
+}
+
+static int imx185_set_coarse_time(struct imx185 *priv, s32 val)
+{
+       int err;
+       struct v4l2_control control;
+       int hdr_en;
+
+       /* check hdr enable ctrl */
+       control.id = V4L2_CID_HDR_EN;
+       err = camera_common_g_ctrl(priv->s_data, &control);
+       if (err < 0) {
+               dev_err(&priv->i2c_client->dev,
+                       "could not find device ctrl.\n");
+               return err;
+       }
+
+       hdr_en = switch_ctrl_qmenu[control.value];
+       if (hdr_en == SWITCH_OFF) {
+               /*no WDR, update SHS1 as ET*/
+               err = imx185_set_coarse_time_shs1(priv, val);
+               if (err)
+                       dev_dbg(&priv->i2c_client->dev,
+                       "%s: error coarse time SHS1 override\n", __func__);
+       } else if (hdr_en == SWITCH_ON) {
+               /*WDR, update SHS2 as long ET*/
+               err = imx185_set_coarse_time_hdr_shs2(priv, val);
+               if (err)
+                       dev_dbg(&priv->i2c_client->dev,
+                       "%s: error coarse time SHS2 override\n", __func__);
+       }
+       return err;
+fail:
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: COARSE_TIME_SHORT control error\n", __func__);
+       return err;
+}
+
+static int imx185_set_coarse_time_shs1(struct imx185 *priv, s32 val)
+{
+       imx185_reg reg_list[2];
+       int err;
+       u16 coarse_shs1;
+       struct v4l2_control control;
+       int hdr_en;
+
+       coarse_shs1 = val;
+
+       if (priv->frame_length == 0)
+               priv->frame_length = IMX185_MIN_FRAME_LENGTH;
+
+       /* check hdr enable ctrl */
+       control.id = V4L2_CID_HDR_EN;
+       err = camera_common_g_ctrl(priv->s_data, &control);
+       if (err < 0) {
+               dev_err(&priv->i2c_client->dev,
+                       "could not find device ctrl.\n");
+               return err;
+       }
+
+       hdr_en = switch_ctrl_qmenu[control.value];
+       if (hdr_en == SWITCH_ON) {
+               if (coarse_shs1 < IMX185_MIN_EXPOSURE_COARSE_1080P_HDR_SHS1)
+                       coarse_shs1 = IMX185_MIN_EXPOSURE_COARSE_1080P_HDR_SHS1;
+
+               if (coarse_shs1 > IMX185_MAX_EXPOSURE_COARSE_1080P_HDR_SHS1)
+                       coarse_shs1 = IMX185_MAX_EXPOSURE_COARSE_1080P_HDR_SHS1;
+
+               priv->frame_length = IMX185_MIN_FRAME_LENGTH;
+       }
+
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: val: %d,  shs1=%d, frame_length: %d\n", __func__,
+                coarse_shs1,
+                priv->frame_length - coarse_shs1 - 1,
+                priv->frame_length);
+
+       imx185_get_coarse_time_regs_shs1(reg_list,
+                       priv->frame_length - coarse_shs1 - 1);
+
+       err = imx185_write_table(priv, reg_list);
+       if (err)
+               goto fail;
+
+       return 0;
+
+fail:
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: COARSE_TIME control error\n", __func__);
+       return err;
+}
+
+static int imx185_set_coarse_time_hdr_shs2(struct imx185 *priv, s32 val)
+{
+       imx185_reg reg_list[2];
+       int err;
+       u16 coarse_shs2;
+
+       coarse_shs2 = val;
+       if (coarse_shs2 < IMX185_MIN_EXPOSURE_COARSE_1080P_HDR_SHS2)
+               coarse_shs2 = IMX185_MIN_EXPOSURE_COARSE_1080P_HDR_SHS2;
+
+       if (coarse_shs2 > IMX185_MAX_EXPOSURE_COARSE_1080P_HDR_SHS2)
+               coarse_shs2 = IMX185_MAX_EXPOSURE_COARSE_1080P_HDR_SHS2;
+
+       priv->frame_length = IMX185_MIN_FRAME_LENGTH;
+
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: val: %d,  shs2=%d, frame_length: %d\n", __func__,
+                coarse_shs2,
+                priv->frame_length - coarse_shs2 - 1,
+                priv->frame_length);
+
+
+       imx185_get_coarse_time_regs_shs2(reg_list,
+                       priv->frame_length - coarse_shs2 - 1);
+
+       err = imx185_write_table(priv, reg_list);
+       if (err)
+               goto fail;
+
+       return 0;
+
+fail:
+       dev_dbg(&priv->i2c_client->dev,
+                "%s: COARSE_TIME_SHORT control error\n", __func__);
+       return err;
+}
+
+static int imx185_fuse_id_setup(struct imx185 *priv)
+{
+       int err;
+       int i;
+       struct i2c_client *client = v4l2_get_subdevdata(priv->subdev);
+       struct camera_common_data *s_data = to_camera_common_data(client);
+       struct camera_common_power_rail *pw = &priv->power;
+
+       struct v4l2_ctrl *ctrl;
+       u8 fuse_id[IMX185_FUSE_ID_SIZE];
+       u8 bak = 0;
+
+       err = camera_common_s_power(priv->subdev, true);
+       if (err)
+               return -ENODEV;
+       if (pw->iovdd) {
+               err = pca954x_device_init(priv);
+               if (err)
+                       dev_err(&client->dev,
+                               "Fail to allocate pca954x regmap: %d\n", err);
+               err = regulator_enable(pw->iovdd);
+               if (!err) {
+                       usleep_range(500, 510);
+                       pca954x_write_reg(priv->s_data, IMX185_PCA954X_I2C_ADDR,
+                               priv->i2c_channel);
+                       usleep_range(500, 510);
+               } else {
+                       pr_err("%s: iovdd regulator_enable faill\n", __func__);
+               }
+       }
+
+       for (i = 0; i < IMX185_FUSE_ID_SIZE; i++) {
+               err |= imx185_read_reg(s_data,
+                       IMX185_FUSE_ID_ADDR + i, (unsigned int *) &bak);
+               if (!err)
+                       fuse_id[i] = bak;
+               else
+                       pr_err("%s: can not read fuse id\n", __func__);
+       }
+
+       ctrl = v4l2_ctrl_find(&priv->ctrl_handler, V4L2_CID_FUSE_ID);
+       if (!ctrl) {
+               dev_err(&priv->i2c_client->dev,
+                       "could not find device ctrl.\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < IMX185_FUSE_ID_SIZE; i++)
+               sprintf(&ctrl->string[i*2], "%02x",
+                       fuse_id[i]);
+       ctrl->cur.string = ctrl->string;
+       pr_info("%s,  fuse id: %s\n", __func__, ctrl->cur.string);
+
+       err = camera_common_s_power(priv->subdev, false);
+       if (err)
+               return -ENODEV;
+
+       return 0;
+}
+
+static int imx185_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct imx185 *priv =
+               container_of(ctrl->handler, struct imx185, ctrl_handler);
+       int err = 0;
+
+       if (priv->power.state == SWITCH_OFF)
+               return 0;
+
+       switch (ctrl->id) {
+
+       default:
+                       pr_err("%s: unknown ctrl id.\n", __func__);
+                       return -EINVAL;
+       }
+
+       return err;
+}
+
+static int imx185_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct imx185 *priv =
+               container_of(ctrl->handler, struct imx185, ctrl_handler);
+       int err = 0;
+
+       if (priv->power.state == SWITCH_OFF)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               err = imx185_set_gain(priv, ctrl->val);
+               break;
+       case V4L2_CID_FRAME_LENGTH:
+               err = imx185_set_frame_length(priv, ctrl->val);
+               break;
+       case V4L2_CID_COARSE_TIME:
+               err = imx185_set_coarse_time(priv, ctrl->val);
+               break;
+       case V4L2_CID_COARSE_TIME_SHORT:
+               err = imx185_set_coarse_time_shs1(priv, ctrl->val);
+               break;
+       case V4L2_CID_GROUP_HOLD:
+               err = imx185_set_group_hold(priv, ctrl->val);
+               break;
+       case V4L2_CID_HDR_EN:
+
+               break;
+       default:
+               pr_err("%s: unknown ctrl id.\n", __func__);
+               return -EINVAL;
+       }
+
+       return err;
+}
+
+static int imx185_ctrls_init(struct imx185 *priv)
+{
+       struct i2c_client *client = priv->i2c_client;
+       struct v4l2_ctrl *ctrl;
+       int num_ctrls;
+       int err;
+       int i;
+
+       dev_dbg(&client->dev, "%s++\n", __func__);
+
+       num_ctrls = ARRAY_SIZE(ctrl_config_list);
+       v4l2_ctrl_handler_init(&priv->ctrl_handler, num_ctrls);
+
+       for (i = 0; i < num_ctrls; i++) {
+               ctrl = v4l2_ctrl_new_custom(&priv->ctrl_handler,
+                       &ctrl_config_list[i], NULL);
+               if (ctrl == NULL) {
+                       dev_err(&client->dev, "Failed to init %s ctrl\n",
+                               ctrl_config_list[i].name);
+                       continue;
+               }
+
+               if (ctrl_config_list[i].type == V4L2_CTRL_TYPE_STRING &&
+                       ctrl_config_list[i].flags & V4L2_CTRL_FLAG_READ_ONLY) {
+                       ctrl->string = devm_kzalloc(&client->dev,
+                               ctrl_config_list[i].max + 1, GFP_KERNEL);
+                       if (!ctrl->string) {
+                               dev_err(&client->dev,
+                                       "Failed to allocate otp data\n");
+                               return -ENOMEM;
+                       }
+               }
+               priv->ctrls[i] = ctrl;
+       }
+
+       priv->num_ctrls = num_ctrls;
+       priv->subdev->ctrl_handler = &priv->ctrl_handler;
+       if (priv->ctrl_handler.error) {
+               dev_err(&client->dev, "Error %d adding controls\n",
+                       priv->ctrl_handler.error);
+               err = priv->ctrl_handler.error;
+               goto error;
+       }
+
+       err = v4l2_ctrl_handler_setup(&priv->ctrl_handler);
+       if (err) {
+               dev_err(&client->dev,
+                       "Error %d setting default controls\n", err);
+               goto error;
+       }
+
+       err = imx185_fuse_id_setup(priv);
+       if (err) {
+               dev_err(&client->dev,
+                       "Error %d reading fuse id data\n", err);
+               goto error;
+       }
+
+       return 0;
+
+error:
+       v4l2_ctrl_handler_free(&priv->ctrl_handler);
+       return err;
+}
+
+MODULE_DEVICE_TABLE(of, imx185_of_match);
+
+static struct camera_common_pdata *imx185_parse_dt(struct imx185 *priv,
+                               struct i2c_client *client)
+{
+       struct device_node *np = client->dev.of_node;
+       struct camera_common_pdata *board_priv_pdata;
+       const struct of_device_id *match;
+       int sts;
+
+       if (!np)
+               return NULL;
+
+       match = of_match_device(imx185_of_match, &client->dev);
+       if (!match) {
+               dev_err(&client->dev, "Failed to find matching dt id\n");
+               return NULL;
+       }
+
+       board_priv_pdata = devm_kzalloc(&client->dev,
+                          sizeof(*board_priv_pdata), GFP_KERNEL);
+       if (!board_priv_pdata) {
+               dev_err(&client->dev, "Failed to allocate pdata\n");
+               return NULL;
+       }
+
+       sts = camera_common_parse_clocks(client, board_priv_pdata);
+       if (sts)
+               dev_err(&client->dev, "Failed to find clocks\n");
+
+       sts = of_property_read_string(np, "mclk",
+                                     &board_priv_pdata->mclk_name);
+       if (sts)
+               dev_err(&client->dev, "mclk not in DT\n");
+
+       board_priv_pdata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+       if (sts) {
+               dev_err(&client->dev, "reset-gpios not found %d\n", sts);
+               board_priv_pdata->reset_gpio = 0;
+       }
+
+       sts = of_property_read_string(np, "iovdd-reg",
+                       &board_priv_pdata->regulators.iovdd);
+       if (sts) {
+               board_priv_pdata->regulators.iovdd = NULL;
+               dev_err(&client->dev, "iovdd-reg not found %d\n", sts);
+       }
+
+       sts = of_property_read_u32(np, "i2c-channel", &priv->i2c_channel);
+       if (sts) {
+               board_priv_pdata->regulators.iovdd = NULL;
+               dev_err(&client->dev, "i2c-channel not found %d\n", sts);
+       }
+
+       return board_priv_pdata;
+}
+
+static int imx185_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       dev_dbg(&client->dev, "%s:\n", __func__);
+
+       return 0;
+}
+
+static const struct v4l2_subdev_internal_ops imx185_subdev_internal_ops = {
+       .open = imx185_open,
+};
+
+static const struct media_entity_operations imx185_media_ops = {
+       .link_validate = v4l2_subdev_link_validate,
+};
+
+static int imx185_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct camera_common_data *common_data;
+       struct imx185 *priv;
+       char dt_name[16];
+       char debugfs_name[10];
+       int err;
+
+       pr_info("[IMX185]: probing v4l2 sensor at addr 0x%0x.\n", client->addr);
+
+       if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
+               return -EINVAL;
+
+       common_data = devm_kzalloc(&client->dev,
+                           sizeof(struct camera_common_data), GFP_KERNEL);
+       if (!common_data) {
+               dev_err(&client->dev, "unable to allocate memory!\n");
+               return -ENOMEM;
+       }
+
+       priv = devm_kzalloc(&client->dev,
+                           sizeof(struct imx185) + sizeof(struct v4l2_ctrl *) *
+                           ARRAY_SIZE(ctrl_config_list),
+                           GFP_KERNEL);
+       if (!priv) {
+               dev_err(&client->dev, "unable to allocate memory!\n");
+               return -ENOMEM;
+       }
+
+       priv->regmap = devm_regmap_init_i2c(client, &sensor_regmap_config);
+       if (IS_ERR(priv->regmap)) {
+               dev_err(&client->dev,
+                       "regmap init failed: %ld\n", PTR_ERR(priv->regmap));
+               return -ENODEV;
+       }
+
+       if (client->dev.of_node)
+               priv->pdata = imx185_parse_dt(priv, client);
+       if (!priv->pdata) {
+               dev_err(&client->dev, "unable to get platform data\n");
+               return -EFAULT;
+       }
+
+       common_data->ops = &imx185_common_ops;
+       common_data->ctrl_handler = &priv->ctrl_handler;
+       common_data->i2c_client = client;
+       common_data->frmfmt = &imx185_frmfmt[0];
+       common_data->colorfmt = camera_common_find_datafmt(
+                                         IMX185_DEFAULT_DATAFMT);
+       common_data->power = &priv->power;
+       common_data->ctrls = priv->ctrls;
+       common_data->priv = (void *)priv;
+       common_data->numctrls = ARRAY_SIZE(ctrl_config_list);
+       common_data->numfmts = ARRAY_SIZE(imx185_frmfmt);
+       common_data->def_mode = IMX185_DEFAULT_MODE;
+       common_data->def_width = IMX185_DEFAULT_WIDTH;
+       common_data->def_height = IMX185_DEFAULT_HEIGHT;
+       common_data->def_clk_freq = IMX185_DEFAULT_CLK_FREQ;
+
+       priv->i2c_client = client;
+       priv->s_data = common_data;
+       priv->subdev = &common_data->subdev;
+       priv->subdev->dev = &client->dev;
+
+       err = imx185_power_get(priv);
+       if (err)
+               return err;
+
+       err = camera_common_parse_ports(client, common_data);
+       if (err) {
+               dev_err(&client->dev, "Failed to find port info\n");
+               return err;
+       }
+       sprintf(debugfs_name, "imx185_%c", common_data->csi_port + 'a');
+       dev_dbg(&client->dev, "%s: name %s\n", __func__, debugfs_name);
+
+       camera_common_create_debugfs(common_data, debugfs_name);
+
+       v4l2_i2c_subdev_init(priv->subdev, client, &imx185_subdev_ops);
+
+       err = imx185_ctrls_init(priv);
+       if (err)
+               return err;
+
+       priv->subdev->internal_ops = &imx185_subdev_internal_ops;
+       priv->subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+                    V4L2_SUBDEV_FL_HAS_EVENTS;
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       priv->pad.flags = MEDIA_PAD_FL_SOURCE;
+       priv->subdev->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+       priv->subdev->entity.ops = &imx185_media_ops;
+       err = media_entity_init(&priv->subdev->entity, 1, &priv->pad, 0);
+       if (err < 0) {
+               dev_err(&client->dev, "unable to init media entity\n");
+               return err;
+       }
+#endif
+
+       err = v4l2_async_register_subdev(priv->subdev);
+       if (err)
+               return err;
+
+       dev_info(&client->dev, "Detected IMX185 sensor\n");
+
+       return 0;
+}
+
+static int
+imx185_remove(struct i2c_client *client)
+{
+       struct camera_common_data *s_data = to_camera_common_data(client);
+       struct imx185 *priv = (struct imx185 *)s_data->priv;
+
+       v4l2_async_unregister_subdev(priv->subdev);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       media_entity_cleanup(&priv->subdev->entity);
+#endif
+
+       v4l2_ctrl_handler_free(&priv->ctrl_handler);
+       imx185_power_put(priv);
+       camera_common_remove_debugfs(s_data);
+
+       return 0;
+}
+
+static const struct i2c_device_id imx185_id[] = {
+       { "imx185", 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, imx185_id);
+
+static struct i2c_driver imx185_i2c_driver = {
+       .driver = {
+               .name = "imx185",
+               .owner = THIS_MODULE,
+       },
+       .probe = imx185_probe,
+       .remove = imx185_remove,
+       .id_table = imx185_id,
+};
+
+module_i2c_driver(imx185_i2c_driver);
+
+MODULE_DESCRIPTION("Media Controller driver for Sony IMX185");
+MODULE_AUTHOR("NVIDIA Corporation");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/imx185_mode_tbls.h b/drivers/media/i2c/imx185_mode_tbls.h
new file mode 100644 (file)
index 0000000..4bad373
--- /dev/null
@@ -0,0 +1,1489 @@
+/*
+ * imx185_mode_tbls.h - imx185 sensor mode tables
+ *
+ * Copyright (c) 2016, 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 __IMX185_I2C_TABLES__
+#define __IMX185_I2C_TABLES__
+
+#include <media/camera_common.h>
+#include <linux/miscdevice.h>
+
+#define IMX185_TABLE_WAIT_MS   0
+#define IMX185_TABLE_END       1
+#define IMX185_MAX_RETRIES     3
+#define IMX185_WAIT_MS_STOP    1
+#define IMX185_WAIT_MS_START   30
+#define IMX185_WAIT_MS_STREAM  210
+#define IMX185_GAIN_TABLE_SIZE 255
+
+/*
+#define INIT_ET_INSETTING 1
+*/
+
+#define imx185_reg struct reg_8
+
+struct  gain_lookup_table {
+       u8 gain_x;
+       u8 reg_val;
+};
+
+static const struct gain_lookup_table
+       imx185_gain_lookup_table[IMX185_GAIN_TABLE_SIZE] = {
+       /*(20.0f*log10((x))*160.0f /48.0f)) */
+       {0x01, 0x00},
+       {0x02, 0x14},
+       {0x03, 0x1F},
+       {0x04, 0x28},
+       {0x05, 0x2E},
+       {0x06, 0x33},
+       {0x07, 0x38},
+       {0x08, 0x3C},
+       {0x09, 0x3F},
+       {0x0A, 0x42},
+       {0x0B, 0x45},
+       {0x0C, 0x47},
+       {0x0D, 0x4A},
+       {0x0E, 0x4C},
+       {0x0F, 0x4E},
+       {0x10, 0x50},
+       {0x11, 0x52},
+       {0x12, 0x53},
+       {0x13, 0x55},
+       {0x14, 0x56},
+       {0x15, 0x58},
+       {0x16, 0x59},
+       {0x17, 0x5A},
+       {0x18, 0x5C},
+       {0x19, 0x5D},
+       {0x1A, 0x5E},
+       {0x1B, 0x5F},
+       {0x1C, 0x60},
+       {0x1D, 0x61},
+       {0x1E, 0x62},
+       {0x1F, 0x63},
+       {0x20, 0x64},
+       {0x21, 0x65},
+       {0x22, 0x66},
+       {0x23, 0x66},
+       {0x24, 0x67},
+       {0x25, 0x68},
+       {0x26, 0x69},
+       {0x27, 0x6A},
+       {0x28, 0x6A},
+       {0x29, 0x6B},
+       {0x2A, 0x6C},
+       {0x2B, 0x6C},
+       {0x2C, 0x6D},
+       {0x2D, 0x6E},
+       {0x2E, 0x6E},
+       {0x2F, 0x6F},
+       {0x30, 0x70},
+       {0x31, 0x70},
+       {0x32, 0x71},
+       {0x33, 0x71},
+       {0x34, 0x72},
+       {0x35, 0x72},
+       {0x36, 0x73},
+       {0x37, 0x74},
+       {0x38, 0x74},
+       {0x39, 0x75},
+       {0x3A, 0x75},
+       {0x3B, 0x76},
+       {0x3C, 0x76},
+       {0x3D, 0x77},
+       {0x3E, 0x77},
+       {0x3F, 0x77},
+       {0x40, 0x78},
+       {0x41, 0x78},
+       {0x42, 0x79},
+       {0x43, 0x79},
+       {0x44, 0x7A},
+       {0x45, 0x7A},
+       {0x46, 0x7B},
+       {0x47, 0x7B},
+       {0x48, 0x7B},
+       {0x49, 0x7C},
+       {0x4A, 0x7C},
+       {0x4B, 0x7D},
+       {0x4C, 0x7D},
+       {0x4D, 0x7D},
+       {0x4E, 0x7E},
+       {0x4F, 0x7E},
+       {0x50, 0x7E},
+       {0x51, 0x7F},
+       {0x52, 0x7F},
+       {0x53, 0x7F},
+       {0x54, 0x80},
+       {0x55, 0x80},
+       {0x56, 0x80},
+       {0x57, 0x81},
+       {0x58, 0x81},
+       {0x59, 0x81},
+       {0x5A, 0x82},
+       {0x5B, 0x82},
+       {0x5C, 0x82},
+       {0x5D, 0x83},
+       {0x5E, 0x83},
+       {0x5F, 0x83},
+       {0x60, 0x84},
+       {0x61, 0x84},
+       {0x62, 0x84},
+       {0x63, 0x85},
+       {0x64, 0x85},
+       {0x65, 0x85},
+       {0x66, 0x85},
+       {0x67, 0x86},
+       {0x68, 0x86},
+       {0x69, 0x86},
+       {0x6A, 0x87},
+       {0x6B, 0x87},
+       {0x6C, 0x87},
+       {0x6D, 0x87},
+       {0x6E, 0x88},
+       {0x6F, 0x88},
+       {0x70, 0x88},
+       {0x71, 0x88},
+       {0x72, 0x89},
+       {0x73, 0x89},
+       {0x74, 0x89},
+       {0x75, 0x89},
+       {0x76, 0x8A},
+       {0x77, 0x8A},
+       {0x78, 0x8A},
+       {0x79, 0x8A},
+       {0x7A, 0x8B},
+       {0x7B, 0x8B},
+       {0x7C, 0x8B},
+       {0x7D, 0x8B},
+       {0x7E, 0x8C},
+       {0x7F, 0x8C},
+       {0x80, 0x8C},
+       {0x81, 0x8C},
+       {0x82, 0x8C},
+       {0x83, 0x8D},
+       {0x84, 0x8D},
+       {0x85, 0x8D},
+       {0x86, 0x8D},
+       {0x87, 0x8E},
+       {0x88, 0x8E},
+       {0x89, 0x8E},
+       {0x8A, 0x8E},
+       {0x8B, 0x8E},
+       {0x8C, 0x8F},
+       {0x8D, 0x8F},
+       {0x8E, 0x8F},
+       {0x8F, 0x8F},
+       {0x90, 0x8F},
+       {0x91, 0x90},
+       {0x92, 0x90},
+       {0x93, 0x90},
+       {0x94, 0x90},
+       {0x95, 0x90},
+       {0x96, 0x91},
+       {0x97, 0x91},
+       {0x98, 0x91},
+       {0x99, 0x91},
+       {0x9A, 0x91},
+       {0x9B, 0x92},
+       {0x9C, 0x92},
+       {0x9D, 0x92},
+       {0x9E, 0x92},
+       {0x9F, 0x92},
+       {0xA0, 0x92},
+       {0xA1, 0x93},
+       {0xA2, 0x93},
+       {0xA3, 0x93},
+       {0xA4, 0x93},
+       {0xA5, 0x93},
+       {0xA6, 0x94},
+       {0xA7, 0x94},
+       {0xA8, 0x94},
+       {0xA9, 0x94},
+       {0xAA, 0x94},
+       {0xAB, 0x94},
+       {0xAC, 0x95},
+       {0xAD, 0x95},
+       {0xAE, 0x95},
+       {0xAF, 0x95},
+       {0xB0, 0x95},
+       {0xB1, 0x95},
+       {0xB2, 0x96},
+       {0xB3, 0x96},
+       {0xB4, 0x96},
+       {0xB5, 0x96},
+       {0xB6, 0x96},
+       {0xB7, 0x96},
+       {0xB8, 0x96},
+       {0xB9, 0x97},
+       {0xBA, 0x97},
+       {0xBB, 0x97},
+       {0xBC, 0x97},
+       {0xBD, 0x97},
+       {0xBE, 0x97},
+       {0xBF, 0x98},
+       {0xC0, 0x98},
+       {0xC1, 0x98},
+       {0xC2, 0x98},
+       {0xC3, 0x98},
+       {0xC4, 0x98},
+       {0xC5, 0x98},
+       {0xC6, 0x99},
+       {0xC7, 0x99},
+       {0xC8, 0x99},
+       {0xC9, 0x99},
+       {0xCA, 0x99},
+       {0xCB, 0x99},
+       {0xCC, 0x99},
+       {0xCD, 0x9A},
+       {0xCE, 0x9A},
+       {0xCF, 0x9A},
+       {0xD0, 0x9A},
+       {0xD1, 0x9A},
+       {0xD2, 0x9A},
+       {0xD3, 0x9A},
+       {0xD4, 0x9B},
+       {0xD5, 0x9B},
+       {0xD6, 0x9B},
+       {0xD7, 0x9B},
+       {0xD8, 0x9B},
+       {0xD9, 0x9B},
+       {0xDA, 0x9B},
+       {0xDB, 0x9C},
+       {0xDC, 0x9C},
+       {0xDD, 0x9C},
+       {0xDE, 0x9C},
+       {0xDF, 0x9C},
+       {0xE0, 0x9C},
+       {0xE1, 0x9C},
+       {0xE2, 0x9C},
+       {0xE3, 0x9D},
+       {0xE4, 0x9D},
+       {0xE5, 0x9D},
+       {0xE6, 0x9D},
+       {0xE7, 0x9D},
+       {0xE8, 0x9D},
+       {0xE9, 0x9D},
+       {0xEA, 0x9D},
+       {0xEB, 0x9E},
+       {0xEC, 0x9E},
+       {0xED, 0x9E},
+       {0xEE, 0x9E},
+       {0xEF, 0x9E},
+       {0xF0, 0x9E},
+       {0xF1, 0x9E},
+       {0xF2, 0x9E},
+       {0xF3, 0x9F},
+       {0xF4, 0x9F},
+       {0xF5, 0x9F},
+       {0xF6, 0x9F},
+       {0xF7, 0x9F},
+       {0xF8, 0x9F},
+       {0xF9, 0x9F},
+       {0xFA, 0x9F},
+       {0xFB, 0x9F},
+       {0xFC, 0xA0},
+       {0xFD, 0xA0},
+       {0xFE, 0xA0},
+       {0xFF, 0xA0}
+};
+
+static imx185_reg imx185_start[] = {
+       {0x3000, 0x00 },
+       {IMX185_TABLE_WAIT_MS, IMX185_WAIT_MS_START},
+       {0x3002, 0x00},
+       {0x3049, 0x0a},
+       {IMX185_TABLE_WAIT_MS, IMX185_WAIT_MS_STREAM},
+       { IMX185_TABLE_END, 0x00 }
+};
+
+static imx185_reg imx185_stop[] = {
+       {0x3000, 0x01 },
+       {IMX185_TABLE_WAIT_MS, IMX185_WAIT_MS_STOP},
+       {IMX185_TABLE_END, 0x00 }
+};
+
+static imx185_reg tp_colorbars[] = {
+       {0x300A, 0x00},/*BLC for PG*/
+       {0x300E, 0x00},
+       {0x3089, 0x00},
+       {0x308C, 0x13},
+       /*
+       * bit 0: PG mode enable
+       * bit 1: Back Ground Transient:
+       * bit [4-7]: PG mode setting, Set at 0h to Fh, suggest 1 or 5
+       * raw12 max output FFEh
+       */
+       {IMX185_TABLE_WAIT_MS, IMX185_WAIT_MS_STOP},
+       {IMX185_TABLE_END, 0x00}
+};
+
+
+/* IMX185_I2C_MIPI_HD1080p_RAW12_60fps.txt
+       output: 2200x1125
+       total pixels: 1952x1115
+       recording pixels: 1920x1080
+       data rate: 445.5Mhz
+       pixel rate: 148.5Mhz
+       mclk_khz = "37125";
+       num_lanes = "4";
+       fps: 60fps
+*/
+static imx185_reg imx185_1952x1115[] = {
+       {0x3002, 0x01},
+       {0x3005, 0x01},
+       {0x3006, 0x00},
+       {0x3007, 0x10},
+       {0x3009, 0x01},
+       {0x300a, 0xf0},
+       {0x300f, 0x01},
+       {0x3018, 0x65},
+       {0x3019, 0x04},
+       {0x301b, 0x4c},
+       {0x301c, 0x04},
+       {0x301d, 0x08},
+       {0x301e, 0x02},
+       {0x3044, 0xe1},
+       {0x3048, 0x33},
+
+       {0x305C, 0x20},
+       {0x305D, 0x00},
+       {0x305E, 0x18},
+       {0x305F, 0x00},
+       {0x3063, 0x74},
+
+       {0x3084, 0x0f},
+       {0x3086, 0x10},
+       {0x30A1, 0x44},
+       {0x30cf, 0xe1},
+       {0x30d0, 0x29},
+       {0x30d2, 0x9b},
+       {0x30d3, 0x01},
+
+       {0x311d, 0x0a},
+       {0x3123, 0x0f},
+       {0x3126, 0xdf},
+       {0x3147, 0x87},
+       {0x31e0, 0x01},
+       {0x31e1, 0x9e},
+       {0x31e2, 0x01},
+       {0x31e5, 0x05},
+       {0x31e6, 0x05},
+       {0x31e7, 0x3a},
+       {0x31e8, 0x3a},
+
+       {0x3203, 0xc8},
+       {0x3207, 0x54},
+       {0x3213, 0x16},
+       {0x3215, 0xf6},
+       {0x321a, 0x14},
+       {0x321b, 0x51},
+       {0x3229, 0xe7},
+       {0x322a, 0xf0},
+       {0x322b, 0x10},
+       {0x3231, 0xe7},
+       {0x3232, 0xf0},
+       {0x3233, 0x10},
+       {0x323c, 0xe8},
+       {0x323d, 0x70},
+       {0x3243, 0x08},
+       {0x3244, 0xe1},
+       {0x3245, 0x10},
+       {0x3247, 0xe7},
+       {0x3248, 0x60},
+       {0x3249, 0x1e},
+       {0x324b, 0x00},
+       {0x324c, 0x41},
+       {0x3250, 0x30},
+       {0x3251, 0x0a},
+       {0x3252, 0xff},
+       {0x3253, 0xff},
+       {0x3254, 0xff},
+       {0x3255, 0x02},
+       {0x3257, 0xf0},
+       {0x325a, 0xa6},
+       {0x325d, 0x14},
+       {0x325e, 0x51},
+       {0x3260, 0x00},
+       {0x3261, 0x61},
+       {0x3266, 0x30},
+       {0x3267, 0x05},
+       {0x3275, 0xe7},
+       {0x3281, 0xea},
+       {0x3282, 0x70},
+       {0x3285, 0xff},
+       {0x328a, 0xf0},
+       {0x328d, 0xb6},
+       {0x328e, 0x40},
+       {0x3290, 0x42},
+       {0x3291, 0x51},
+       {0x3292, 0x1e},
+       {0x3294, 0xc4},
+       {0x3295, 0x20},
+       {0x3297, 0x50},
+       {0x3298, 0x31},
+       {0x3299, 0x1f},
+       {0x329b, 0xc0},
+       {0x329c, 0x60},
+       {0x329e, 0x4c},
+       {0x329f, 0x71},
+       {0x32a0, 0x1f},
+       {0x32a2, 0xb6},
+       {0x32a3, 0xc0},
+       {0x32a4, 0x0b},
+       {0x32a9, 0x24},
+       {0x32aa, 0x41},
+       {0x32b0, 0x25},
+       {0x32b1, 0x51},
+       {0x32b7, 0x1c},
+       {0x32b8, 0xc1},
+       {0x32b9, 0x12},
+       {0x32be, 0x1d},
+       {0x32bf, 0xd1},
+       {0x32c0, 0x12},
+       {0x32c2, 0xa8},
+       {0x32c3, 0xc0},
+       {0x32c4, 0x0a},
+       {0x32c5, 0x1e},
+       {0x32c6, 0x21},
+       {0x32c9, 0xb0},
+       {0x32ca, 0x40},
+       {0x32cc, 0x26},
+       {0x32cd, 0xa1},
+       {0x32d0, 0xb6},
+       {0x32d1, 0xc0},
+       {0x32d2, 0x0b},
+       {0x32d4, 0xe2},
+       {0x32d5, 0x40},
+       {0x32d8, 0x4e},
+       {0x32d9, 0xa1},
+       {0x32ec, 0xf0},
+
+       {0x3303, 0x00},
+       {0x3305, 0x03},
+       {0x3314, 0x08},
+       {0x3315, 0x01},
+       {0x3316, 0x04},
+       {0x3317, 0x04},
+       {0x3318, 0x49},
+       {0x3319, 0x04},
+       {0x332c, 0x40},
+       {0x332d, 0x20},
+       {0x332e, 0x03},
+       {0x333e, 0x0c},
+       {0x333f, 0x0c},
+       {0x3340, 0x03},
+       {0x3341, 0x20},
+       {0x3342, 0x25},
+       {0x3343, 0x68},
+       {0x3344, 0x20},
+       {0x3345, 0x40},
+       {0x3346, 0x28},
+       {0x3347, 0x20},
+       {0x3348, 0x18},
+       {0x3349, 0x78},
+       {0x334a, 0x28},
+       {0x334e, 0xb4},
+       {0x334f, 0x01},
+#ifdef INIT_ET_INSETTING
+       {0x3020, 0xe1},
+       {0x3021, 0x04},
+#endif
+       {IMX185_TABLE_END, 0x00}
+};
+
+/*
+       output: 2200x1125
+       total pixels: 1952x1115
+       recording pixels: 1920x1080
+       data rate: 222.25Mhz
+       pixel rate: 74.25Mhz
+       mclk_khz = "37125";
+       num_lanes = "4";
+       fps: 30fps
+*/
+static imx185_reg imx185_1952x1115_hdr[] = {
+       {0x3002, 0x01},
+       {0x3005, 0x01},
+       {0x3006, 0x00},
+       {0x3007, 0x10},
+       {0x3009, 0x02},
+       {0x300a, 0xf0},
+
+       {0x300c, 0x02},
+       {0x300f, 0x01},
+       {0x3010, 0x38},
+       {0x3011, 0x00},
+       {0x3012, 0x0f},
+       {0x3013, 0x00},
+
+       {0x3018, 0x65},
+       {0x3019, 0x04},
+       {0x301b, 0x98},
+       {0x301c, 0x08},
+       {0x301d, 0x08},
+       {0x301e, 0x02},
+       {0x3044, 0xe1},
+       {0x3048, 0x33},
+#ifdef INIT_ET_INSETTING
+       {0x3020, 0x70},
+       {0x3021, 0x00},
+       {0x3023, 0x20},
+       {0x3024, 0x11},
+#endif
+       {0x3056, 0xc9},
+       {0x3057, 0x64},
+
+       {0x305C, 0x20},
+       {0x305D, 0x00},
+       {0x305E, 0x18},
+       {0x305F, 0x00},
+       {0x3063, 0x74},
+
+       {0x3065, 0x00},
+
+       {0x3084, 0x0f},
+       {0x3086, 0x10},
+       {0x30cf, 0xe1},
+       {0x30d0, 0x29},
+       {0x30d2, 0x9b},
+       {0x30d3, 0x01},
+
+       {0x311d, 0x0a},
+       {0x3123, 0x0f},
+       {0x3126, 0xdf},
+       {0x3147, 0x87},
+       {0x31e0, 0x01},
+       {0x31e1, 0x9e},
+       {0x31e2, 0x01},
+       {0x31e5, 0x05},
+       {0x31e6, 0x05},
+       {0x31e7, 0x3a},
+       {0x31e8, 0x3a},
+
+       {0x3203, 0xc8},
+       {0x3207, 0x54},
+       {0x3213, 0x16},
+       {0x3215, 0xf6},
+       {0x321a, 0x14},
+       {0x321b, 0x51},
+       {0x3229, 0xe7},
+       {0x322a, 0xf0},
+       {0x322b, 0x10},
+       {0x3231, 0xe7},
+       {0x3232, 0xf0},
+       {0x3233, 0x10},
+       {0x323c, 0xe8},
+       {0x323d, 0x70},
+       {0x3243, 0x08},
+       {0x3244, 0xe1},
+       {0x3245, 0x10},
+       {0x3247, 0xe7},
+       {0x3248, 0x60},
+       {0x3249, 0x1e},
+       {0x324b, 0x00},
+       {0x324c, 0x41},
+       {0x3250, 0x30},
+       {0x3251, 0x0a},
+       {0x3252, 0xff},
+       {0x3253, 0xff},
+       {0x3254, 0xff},
+       {0x3255, 0x02},
+       {0x3257, 0xf0},
+       {0x325a, 0xa6},
+       {0x325d, 0x14},
+       {0x325e, 0x51},
+       {0x3260, 0x00},
+       {0x3261, 0x61},
+       {0x3266, 0x30},
+       {0x3267, 0x05},
+       {0x3275, 0xe7},
+       {0x3281, 0xea},
+       {0x3282, 0x70},
+       {0x3285, 0xff},
+       {0x328a, 0xf0},
+       {0x328d, 0xb6},
+       {0x328e, 0x40},
+       {0x3290, 0x42},
+       {0x3291, 0x51},
+       {0x3292, 0x1e},
+       {0x3294, 0xc4},
+       {0x3295, 0x20},
+       {0x3297, 0x50},
+       {0x3298, 0x31},
+       {0x3299, 0x1f},
+       {0x329b, 0xc0},
+       {0x329c, 0x60},
+       {0x329e, 0x4c},
+       {0x329f, 0x71},
+       {0x32a0, 0x1f},
+       {0x32a2, 0xb6},
+       {0x32a3, 0xc0},
+       {0x32a4, 0x0b},
+       {0x32a9, 0x24},
+       {0x32aa, 0x41},
+       {0x32b0, 0x25},
+       {0x32b1, 0x51},
+       {0x32b7, 0x1c},
+       {0x32b8, 0xc1},
+       {0x32b9, 0x12},
+       {0x32be, 0x1d},
+       {0x32bf, 0xd1},
+       {0x32c0, 0x12},
+       {0x32c2, 0xa8},
+       {0x32c3, 0xc0},
+       {0x32c4, 0x0a},
+       {0x32c5, 0x1e},
+       {0x32c6, 0x21},
+       {0x32c9, 0xb0},
+       {0x32ca, 0x40},
+       {0x32cc, 0x26},
+       {0x32cd, 0xa1},
+       {0x32d0, 0xb6},
+       {0x32d1, 0xc0},
+       {0x32d2, 0x0b},
+       {0x32d4, 0xe2},
+       {0x32d5, 0x40},
+       {0x32d8, 0x4e},
+       {0x32d9, 0xa1},
+       {0x32ec, 0xf0},
+
+       {0x3303, 0x10},
+       {0x3305, 0x03},
+       {0x3314, 0x08},
+       {0x3315, 0x01},
+       {0x3316, 0x04},
+       {0x3317, 0x04},
+       {0x3318, 0x49},
+       {0x3319, 0x04},
+       {0x332c, 0x30},
+       {0x332d, 0x20},
+       {0x332e, 0x03},
+       {0x333e, 0x0c},
+       {0x333f, 0x0c},
+       {0x3340, 0x03},
+
+       {0x3341, 0x20},
+       {0x3342, 0x25},
+       {0x3343, 0x58},
+       {0x3344, 0x10},
+       {0x3345, 0x30},
+       {0x3346, 0x18},
+       {0x3347, 0x10},
+       {0x3348, 0x10},
+       {0x3349, 0x48},
+       {0x334a, 0x28},
+       {0x334e, 0xb4},
+       {0x334f, 0x01},
+
+#ifdef INIT_ET_INSETTING
+/*
+ * *min  ET: (05H-80H)
+ * *           SHS1=1125-1-05=1119(0x45F)
+ * *           SHS2=1125-1-80=1044(0x414)
+ * *max ET: (70H--1120H)
+ * *           SHS1=1125-1-70=1054(0x41E)
+ * *           SHS2=1125-1-1120=1044(0x04)
+ * *mid  ET: (45H--720H)
+ * *           SHS1=1125-1-45=1079(0x437)
+ * *           SHS2=1125-1-80=404(0x194)
+ * */
+       {0x3020, 0x05},/*SHS1 short LSB*/
+       {0x3021, 0x00},
+       {0x3022, 0x00},
+       {0x3023, 0x50},/*SHS2 long LSB*/
+       {0x3024, 0x00},
+       {0x3025, 0x00},
+#endif
+       {0x300C, 0x02},
+       {0x300F, 0x05},
+       {0x3010, 0x38},
+       {0x3012, 0x0F},
+       {0x3084, 0x0F},
+       {0x3065, 0x00},
+       {IMX185_TABLE_END, 0x00}
+};
+
+static  imx185_reg imx185_1920x1080_crop[] = {
+       {0x3002, 0x01},
+       {0x3005, 0x01},
+       {0x3006, 0x00},
+       {0x3007, 0x50},
+       {0x3009, 0x01},
+       {0x300a, 0xf0},
+       {0x300f, 0x01},
+       {0x3018, 0x65},
+       {0x3019, 0x04},
+       {0x301b, 0x4c},
+       {0x301c, 0x04},
+       {0x301d, 0x08},
+       {0x301e, 0x02},
+
+       {0x3036, 0x06},
+       {0x3038, 0x08},
+       {0x3039, 0x00},
+       {0x303a, 0x40},
+       {0x303b, 0x04},
+       {0x303c, 0x0c},
+       {0x303d, 0x00},
+       {0x303e, 0x7c},
+       {0x303f, 0x07},
+
+       {0x3044, 0xe1},
+       {0x3048, 0x33},
+
+       {0x305C, 0x20},
+       {0x305D, 0x00},
+       {0x305E, 0x18},
+       {0x305F, 0x00},
+       {0x3063, 0x74},
+
+       {0x3084, 0x0f},
+       {0x3086, 0x10},
+       {0x30A1, 0x44},
+       {0x30cf, 0xe1},
+       {0x30d0, 0x29},
+       {0x30d2, 0x9b},
+       {0x30d3, 0x01},
+
+       {0x311d, 0x0a},
+       {0x3123, 0x0f},
+       {0x3126, 0xdf},
+       {0x3147, 0x87},
+       {0x31e0, 0x01},
+       {0x31e1, 0x9e},
+       {0x31e2, 0x01},
+       {0x31e5, 0x05},
+       {0x31e6, 0x05},
+       {0x31e7, 0x3a},
+       {0x31e8, 0x3a},
+
+       {0x3203, 0xc8},
+       {0x3207, 0x54},
+       {0x3213, 0x16},
+       {0x3215, 0xf6},
+       {0x321a, 0x14},
+       {0x321b, 0x51},
+       {0x3229, 0xe7},
+       {0x322a, 0xf0},
+       {0x322b, 0x10},
+       {0x3231, 0xe7},
+       {0x3232, 0xf0},
+       {0x3233, 0x10},
+       {0x323c, 0xe8},
+       {0x323d, 0x70},
+       {0x3243, 0x08},
+       {0x3244, 0xe1},
+       {0x3245, 0x10},
+       {0x3247, 0xe7},
+       {0x3248, 0x60},
+       {0x3249, 0x1e},
+       {0x324b, 0x00},
+       {0x324c, 0x41},
+       {0x3250, 0x30},
+       {0x3251, 0x0a},
+       {0x3252, 0xff},
+       {0x3253, 0xff},
+       {0x3254, 0xff},
+       {0x3255, 0x02},
+       {0x3257, 0xf0},
+       {0x325a, 0xa6},
+       {0x325d, 0x14},
+       {0x325e, 0x51},
+       {0x3260, 0x00},
+       {0x3261, 0x61},
+       {0x3266, 0x30},
+       {0x3267, 0x05},
+       {0x3275, 0xe7},
+       {0x3281, 0xea},
+       {0x3282, 0x70},
+       {0x3285, 0xff},
+       {0x328a, 0xf0},
+       {0x328d, 0xb6},
+       {0x328e, 0x40},
+       {0x3290, 0x42},
+       {0x3291, 0x51},
+       {0x3292, 0x1e},
+       {0x3294, 0xc4},
+       {0x3295, 0x20},
+       {0x3297, 0x50},
+       {0x3298, 0x31},
+       {0x3299, 0x1f},
+       {0x329b, 0xc0},
+       {0x329c, 0x60},
+       {0x329e, 0x4c},
+       {0x329f, 0x71},
+       {0x32a0, 0x1f},
+       {0x32a2, 0xb6},
+       {0x32a3, 0xc0},
+       {0x32a4, 0x0b},
+       {0x32a9, 0x24},
+       {0x32aa, 0x41},
+       {0x32b0, 0x25},
+       {0x32b1, 0x51},
+       {0x32b7, 0x1c},
+       {0x32b8, 0xc1},
+       {0x32b9, 0x12},
+       {0x32be, 0x1d},
+       {0x32bf, 0xd1},
+       {0x32c0, 0x12},
+       {0x32c2, 0xa8},
+       {0x32c3, 0xc0},
+       {0x32c4, 0x0a},
+       {0x32c5, 0x1e},
+       {0x32c6, 0x21},
+       {0x32c9, 0xb0},
+       {0x32ca, 0x40},
+       {0x32cc, 0x26},
+       {0x32cd, 0xa1},
+       {0x32d0, 0xb6},
+       {0x32d1, 0xc0},
+       {0x32d2, 0x0b},
+       {0x32d4, 0xe2},
+       {0x32d5, 0x40},
+       {0x32d8, 0x4e},
+       {0x32d9, 0xa1},
+       {0x32ec, 0xf0},
+
+       {0x3303, 0x00},
+       {0x3305, 0x03},
+       {0x3314, 0x04},
+       {0x3315, 0x01},
+       {0x3316, 0x04},
+       {0x3317, 0x04},
+       {0x3318, 0x38},
+       {0x3319, 0x04},
+       {0x332c, 0x40},
+       {0x332d, 0x20},
+       {0x332e, 0x03},
+       {0x333e, 0x0c},
+       {0x333f, 0x0c},
+       {0x3340, 0x03},
+       {0x3341, 0x20},
+       {0x3342, 0x25},
+       {0x3343, 0x68},
+       {0x3344, 0x20},
+       {0x3345, 0x40},
+       {0x3346, 0x28},
+       {0x3347, 0x20},
+       {0x3348, 0x18},
+       {0x3349, 0x78},
+       {0x334a, 0x28},
+       {0x334e, 0xb4},
+       {0x334f, 0x01},
+#ifdef INIT_ET_INSETTING
+       {0x3020, 0xe1},
+       {0x3021, 0x04},
+#endif
+       {IMX185_TABLE_END, 0x00}
+};
+
+static imx185_reg imx185_1920x1080_hdr_crop[] = {
+       {0x3002, 0x01},
+       {0x3005, 0x01},
+       {0x3006, 0x00},
+       {0x3007, 0x50},
+       {0x3009, 0x02},
+       {0x300a, 0xf0},
+
+       {0x300c, 0x02},
+       {0x300f, 0x01},
+       {0x3010, 0x38},
+       {0x3011, 0x00},
+       {0x3012, 0x0f},
+       {0x3013, 0x00},
+
+       {0x3018, 0x65},
+       {0x3019, 0x04},
+       {0x301b, 0x98},
+       {0x301c, 0x08},
+       {0x301d, 0x08},
+       {0x301e, 0x02},
+
+       {0x3036, 0x06},
+       {0x3038, 0x08},
+       {0x3039, 0x00},
+       {0x303a, 0x40},
+       {0x303b, 0x04},
+       {0x303c, 0x0c},
+       {0x303d, 0x00},
+       {0x303e, 0x7c},
+       {0x303f, 0x07},
+
+       {0x3044, 0xe1},
+       {0x3048, 0x33},
+#ifdef INIT_ET_INSETTING
+       {0x3020, 0x70},
+       {0x3021, 0x00},
+       {0x3023, 0x20},
+       {0x3024, 0x11},
+#endif
+       {0x3056, 0xc9},
+       {0x3057, 0x64},
+
+       {0x305C, 0x20},
+       {0x305D, 0x00},
+       {0x305E, 0x18},
+       {0x305F, 0x00},
+       {0x3063, 0x74},
+
+       {0x3065, 0x00},
+
+       {0x3084, 0x0f},
+       {0x3086, 0x10},
+       {0x30cf, 0xe1},
+       {0x30d0, 0x29},
+       {0x30d2, 0x9b},
+       {0x30d3, 0x01},
+
+       {0x311d, 0x0a},
+       {0x3123, 0x0f},
+       {0x3126, 0xdf},
+       {0x3147, 0x87},
+       {0x31e0, 0x01},
+       {0x31e1, 0x9e},
+       {0x31e2, 0x01},
+       {0x31e5, 0x05},
+       {0x31e6, 0x05},
+       {0x31e7, 0x3a},
+       {0x31e8, 0x3a},
+
+       {0x3203, 0xc8},
+       {0x3207, 0x54},
+       {0x3213, 0x16},
+       {0x3215, 0xf6},
+       {0x321a, 0x14},
+       {0x321b, 0x51},
+       {0x3229, 0xe7},
+       {0x322a, 0xf0},
+       {0x322b, 0x10},
+       {0x3231, 0xe7},
+       {0x3232, 0xf0},
+       {0x3233, 0x10},
+       {0x323c, 0xe8},
+       {0x323d, 0x70},
+       {0x3243, 0x08},
+       {0x3244, 0xe1},
+       {0x3245, 0x10},
+       {0x3247, 0xe7},
+       {0x3248, 0x60},
+       {0x3249, 0x1e},
+       {0x324b, 0x00},
+       {0x324c, 0x41},
+       {0x3250, 0x30},
+       {0x3251, 0x0a},
+       {0x3252, 0xff},
+       {0x3253, 0xff},
+       {0x3254, 0xff},
+       {0x3255, 0x02},
+       {0x3257, 0xf0},
+       {0x325a, 0xa6},
+       {0x325d, 0x14},
+       {0x325e, 0x51},
+       {0x3260, 0x00},
+       {0x3261, 0x61},
+       {0x3266, 0x30},
+       {0x3267, 0x05},
+       {0x3275, 0xe7},
+       {0x3281, 0xea},
+       {0x3282, 0x70},
+       {0x3285, 0xff},
+       {0x328a, 0xf0},
+       {0x328d, 0xb6},
+       {0x328e, 0x40},
+       {0x3290, 0x42},
+       {0x3291, 0x51},
+       {0x3292, 0x1e},
+       {0x3294, 0xc4},
+       {0x3295, 0x20},
+       {0x3297, 0x50},
+       {0x3298, 0x31},
+       {0x3299, 0x1f},
+       {0x329b, 0xc0},
+       {0x329c, 0x60},
+       {0x329e, 0x4c},
+       {0x329f, 0x71},
+       {0x32a0, 0x1f},
+       {0x32a2, 0xb6},
+       {0x32a3, 0xc0},
+       {0x32a4, 0x0b},
+       {0x32a9, 0x24},
+       {0x32aa, 0x41},
+       {0x32b0, 0x25},
+       {0x32b1, 0x51},
+       {0x32b7, 0x1c},
+       {0x32b8, 0xc1},
+       {0x32b9, 0x12},
+       {0x32be, 0x1d},
+       {0x32bf, 0xd1},
+       {0x32c0, 0x12},
+       {0x32c2, 0xa8},
+       {0x32c3, 0xc0},
+       {0x32c4, 0x0a},
+       {0x32c5, 0x1e},
+       {0x32c6, 0x21},
+       {0x32c9, 0xb0},
+       {0x32ca, 0x40},
+       {0x32cc, 0x26},
+       {0x32cd, 0xa1},
+       {0x32d0, 0xb6},
+       {0x32d1, 0xc0},
+       {0x32d2, 0x0b},
+       {0x32d4, 0xe2},
+       {0x32d5, 0x40},
+       {0x32d8, 0x4e},
+       {0x32d9, 0xa1},
+       {0x32ec, 0xf0},
+
+       {0x3303, 0x10},
+       {0x3305, 0x03},
+       {0x3314, 0x04},
+       {0x3315, 0x01},
+       {0x3316, 0x04},
+       {0x3317, 0x04},
+       {0x3318, 0x38},
+       {0x3319, 0x04},
+       {0x332c, 0x30},
+       {0x332d, 0x20},
+       {0x332e, 0x03},
+       {0x333e, 0x0c},
+       {0x333f, 0x0c},
+       {0x3340, 0x03},
+
+       {0x3341, 0x20},
+       {0x3342, 0x25},
+       {0x3343, 0x58},
+       {0x3344, 0x10},
+       {0x3345, 0x30},
+       {0x3346, 0x18},
+       {0x3347, 0x10},
+       {0x3348, 0x10},
+       {0x3349, 0x48},
+       {0x334a, 0x28},
+       {0x334e, 0xb4},
+       {0x334f, 0x01},
+
+#ifdef INIT_ET_INSETTING
+       {0x3020, 0x05},/*SHS1 short LSB*/
+       {0x3021, 0x00},
+       {0x3022, 0x00},
+       {0x3023, 0x50},/*SHS2 long LSB*/
+       {0x3024, 0x00},
+       {0x3025, 0x00},
+#endif
+       {0x300C, 0x02},
+       {0x300F, 0x05},
+       {0x3010, 0x38},
+       {0x3012, 0x0F},
+       {0x3084, 0x0F},
+       {0x3065, 0x00},
+       {IMX185_TABLE_END, 0x00}
+};
+
+static imx185_reg imx185_1920x1080_crop_10bit[] = {
+/*10bit 60fps*/
+
+       {0x3002, 0x01},
+       {0x3005, 0x00},/*10BIT*/
+       {0x3006, 0x00},
+       {0x3007, 0x50},
+       {0x3009, 0x01},
+       {0x300a, 0x3c},/*10BIT*/
+       {0x300f, 0x01},
+       {0x3018, 0x65},
+       {0x3019, 0x04},
+       {0x301b, 0x4c},
+       {0x301c, 0x04},
+       {0x301d, 0x08},
+       {0x301e, 0x02},
+
+       {0x3036, 0x06},
+       {0x3038, 0x08},
+       {0x3039, 0x00},
+       {0x303a, 0x40},
+       {0x303b, 0x04},
+       {0x303c, 0x0c},
+       {0x303d, 0x00},
+       {0x303e, 0x7c},
+       {0x303f, 0x07},
+
+       {0x3044, 0xe1},
+       {0x3048, 0x33},
+
+       {0x305C, 0x20},
+       {0x305D, 0x00},
+       {0x305E, 0x18},
+       {0x305F, 0x00},
+       {0x3063, 0x74},
+
+       {0x3084, 0x0f},
+       {0x3086, 0x10},
+       {0x30A1, 0x44},
+       {0x30cf, 0xe1},
+       {0x30d0, 0x29},
+       {0x30d2, 0x9b},
+       {0x30d3, 0x01},
+
+       {0x311d, 0x0a},
+       {0x3123, 0x0f},
+       {0x3126, 0xdf},
+       {0x3147, 0x87},
+       {0x31e0, 0x01},
+       {0x31e1, 0x9e},
+       {0x31e2, 0x01},
+       {0x31e5, 0x05},
+       {0x31e6, 0x05},
+       {0x31e7, 0x3a},
+       {0x31e8, 0x3a},
+
+       {0x3203, 0xc8},
+       {0x3207, 0x54},
+       {0x3213, 0x16},
+       {0x3215, 0xf6},
+       {0x321a, 0x14},
+       {0x321b, 0x51},
+       {0x3229, 0xe7},
+       {0x322a, 0xf0},
+       {0x322b, 0x10},
+       {0x3231, 0xe7},
+       {0x3232, 0xf0},
+       {0x3233, 0x10},
+       {0x323c, 0xe8},
+       {0x323d, 0x70},
+       {0x3243, 0x08},
+       {0x3244, 0xe1},
+       {0x3245, 0x10},
+       {0x3247, 0xe7},
+       {0x3248, 0x60},
+       {0x3249, 0x1e},
+       {0x324b, 0x00},
+       {0x324c, 0x41},
+       {0x3250, 0x30},
+       {0x3251, 0x0a},
+       {0x3252, 0xff},
+       {0x3253, 0xff},
+       {0x3254, 0xff},
+       {0x3255, 0x02},
+       {0x3257, 0xf0},
+       {0x325a, 0xa6},
+       {0x325d, 0x14},
+       {0x325e, 0x51},
+       {0x3260, 0x00},
+       {0x3261, 0x61},
+       {0x3266, 0x30},
+       {0x3267, 0x05},
+       {0x3275, 0xe7},
+       {0x3281, 0xea},
+       {0x3282, 0x70},
+       {0x3285, 0xff},
+       {0x328a, 0xf0},
+       {0x328d, 0xb6},
+       {0x328e, 0x40},
+       {0x3290, 0x42},
+       {0x3291, 0x51},
+       {0x3292, 0x1e},
+       {0x3294, 0xc4},
+       {0x3295, 0x20},
+       {0x3297, 0x50},
+       {0x3298, 0x31},
+       {0x3299, 0x1f},
+       {0x329b, 0xc0},
+       {0x329c, 0x60},
+       {0x329e, 0x4c},
+       {0x329f, 0x71},
+       {0x32a0, 0x1f},
+       {0x32a2, 0xb6},
+       {0x32a3, 0xc0},
+       {0x32a4, 0x0b},
+       {0x32a9, 0x24},
+       {0x32aa, 0x41},
+       {0x32b0, 0x25},
+       {0x32b1, 0x51},
+       {0x32b7, 0x1c},
+       {0x32b8, 0xc1},
+       {0x32b9, 0x12},
+       {0x32be, 0x1d},
+       {0x32bf, 0xd1},
+       {0x32c0, 0x12},
+       {0x32c2, 0xa8},
+       {0x32c3, 0xc0},
+       {0x32c4, 0x0a},
+       {0x32c5, 0x1e},
+       {0x32c6, 0x21},
+       {0x32c9, 0xb0},
+       {0x32ca, 0x40},
+       {0x32cc, 0x26},
+       {0x32cd, 0xa1},
+       {0x32d0, 0xb6},
+       {0x32d1, 0xc0},
+       {0x32d2, 0x0b},
+       {0x32d4, 0xe2},
+       {0x32d5, 0x40},
+       {0x32d8, 0x4e},
+       {0x32d9, 0xa1},
+       {0x32ec, 0xf0},
+
+       {0x3303, 0x00},
+       {0x3305, 0x03},
+       {0x3314, 0x04},
+       {0x3315, 0x01},
+       {0x3316, 0x04},
+       {0x3317, 0x04},
+       {0x3318, 0x38},
+       {0x3319, 0x04},
+       {0x332c, 0x40},
+       {0x332d, 0x20},
+       {0x332e, 0x03},
+       {0x333e, 0x0a},/*10BIT*/
+       {0x333f, 0x0a},/*10BIT*/
+       {0x3340, 0x03},
+       {0x3341, 0x20},
+       {0x3342, 0x25},
+       {0x3343, 0x68},
+       {0x3344, 0x20},
+       {0x3345, 0x40},
+       {0x3346, 0x28},
+       {0x3347, 0x20},
+       {0x3348, 0x18},
+       {0x3349, 0x78},
+       {0x334a, 0x28},
+       {0x334e, 0xb4},
+       {0x334f, 0x01},
+#ifdef INIT_ET_INSETTING
+       {0x3020, 0xe1},
+       {0x3021, 0x04},
+#endif
+       {IMX185_TABLE_END, 0x00}
+};
+
+static imx185_reg imx185_1920x1080_crop_10bit_30fps[] = {
+/*30fps 10bit*/
+       {0x3002, 0x01},
+       {0x3005, 0x00},
+       {0x3006, 0x00},
+       {0x3007, 0x50},
+       {0x3009, 0x02},
+       {0x300a, 0x3c},
+       {0x300f, 0x01},
+       {0x3018, 0x65},
+       {0x3019, 0x04},
+       {0x301b, 0x98},
+       {0x301c, 0x08},
+       {0x301d, 0x08},
+       {0x301e, 0x02},
+
+       {0x3036, 0x06},
+       {0x3038, 0x08},
+       {0x3039, 0x00},
+       {0x303a, 0x40},
+       {0x303b, 0x04},
+       {0x303c, 0x0c},
+       {0x303d, 0x00},
+       {0x303e, 0x7c},
+       {0x303f, 0x07},
+
+       {0x3044, 0xe1},
+       {0x3048, 0x33},
+
+       {0x305C, 0x20},
+       {0x305D, 0x00},
+       {0x305E, 0x18},
+       {0x305F, 0x00},
+       {0x3063, 0x74},
+
+       {0x3084, 0x0f},
+       {0x3086, 0x10},
+       {0x30cf, 0xe1},
+       {0x30d0, 0x29},
+       {0x30d2, 0x9b},
+       {0x30d3, 0x01},
+
+       {0x311d, 0x0a},
+       {0x3123, 0x0f},
+       {0x3126, 0xdf},
+       {0x3147, 0x87},
+       {0x31e0, 0x01},
+       {0x31e1, 0x9e},
+       {0x31e2, 0x01},
+       {0x31e5, 0x05},
+       {0x31e6, 0x05},
+       {0x31e7, 0x3a},
+       {0x31e8, 0x3a},
+
+       {0x3203, 0xc8},
+       {0x3207, 0x54},
+       {0x3213, 0x16},
+       {0x3215, 0xf6},
+       {0x321a, 0x14},
+       {0x321b, 0x51},
+       {0x3229, 0xe7},
+       {0x322a, 0xf0},
+       {0x322b, 0x10},
+       {0x3231, 0xe7},
+       {0x3232, 0xf0},
+       {0x3233, 0x10},
+       {0x323c, 0xe8},
+       {0x323d, 0x70},
+       {0x3243, 0x08},
+       {0x3244, 0xe1},
+       {0x3245, 0x10},
+       {0x3247, 0xe7},
+       {0x3248, 0x60},
+       {0x3249, 0x1e},
+       {0x324b, 0x00},
+       {0x324c, 0x41},
+       {0x3250, 0x30},
+       {0x3251, 0x0a},
+       {0x3252, 0xff},
+       {0x3253, 0xff},
+       {0x3254, 0xff},
+       {0x3255, 0x02},
+       {0x3257, 0xf0},
+       {0x325a, 0xa6},
+       {0x325d, 0x14},
+       {0x325e, 0x51},
+       {0x3260, 0x00},
+       {0x3261, 0x61},
+       {0x3266, 0x30},
+       {0x3267, 0x05},
+       {0x3275, 0xe7},
+       {0x3281, 0xea},
+       {0x3282, 0x70},
+       {0x3285, 0xff},
+       {0x328a, 0xf0},
+       {0x328d, 0xb6},
+       {0x328e, 0x40},
+       {0x3290, 0x42},
+       {0x3291, 0x51},
+       {0x3292, 0x1e},
+       {0x3294, 0xc4},
+       {0x3295, 0x20},
+       {0x3297, 0x50},
+       {0x3298, 0x31},
+       {0x3299, 0x1f},
+       {0x329b, 0xc0},
+       {0x329c, 0x60},
+       {0x329e, 0x4c},
+       {0x329f, 0x71},
+       {0x32a0, 0x1f},
+       {0x32a2, 0xb6},
+       {0x32a3, 0xc0},
+       {0x32a4, 0x0b},
+       {0x32a9, 0x24},
+       {0x32aa, 0x41},
+       {0x32b0, 0x25},
+       {0x32b1, 0x51},
+       {0x32b7, 0x1c},
+       {0x32b8, 0xc1},
+       {0x32b9, 0x12},
+       {0x32be, 0x1d},
+       {0x32bf, 0xd1},
+       {0x32c0, 0x12},
+       {0x32c2, 0xa8},
+       {0x32c3, 0xc0},
+       {0x32c4, 0x0a},
+       {0x32c5, 0x1e},
+       {0x32c6, 0x21},
+       {0x32c9, 0xb0},
+       {0x32ca, 0x40},
+       {0x32cc, 0x26},
+       {0x32cd, 0xa1},
+       {0x32d0, 0xb6},
+       {0x32d1, 0xc0},
+       {0x32d2, 0x0b},
+       {0x32d4, 0xe2},
+       {0x32d5, 0x40},
+       {0x32d8, 0x4e},
+       {0x32d9, 0xa1},
+       {0x32ec, 0xf0},
+
+       {0x3303, 0x10},
+       {0x3305, 0x03},
+       {0x3314, 0x04},
+       {0x3315, 0x01},
+       {0x3316, 0x04},
+       {0x3317, 0x04},
+       {0x3318, 0x38},
+       {0x3319, 0x04},
+       {0x332c, 0x30},
+       {0x332d, 0x20},
+       {0x332e, 0x03},
+       {0x333e, 0x0a},
+       {0x333f, 0x0a},
+       {0x3340, 0x03},
+
+       {0x3341, 0x20},
+       {0x3342, 0x25},
+       {0x3343, 0x58},
+       {0x3344, 0x10},
+       {0x3345, 0x30},
+       {0x3346, 0x18},
+       {0x3347, 0x10},
+       {0x3348, 0x10},
+       {0x3349, 0x48},
+       {0x334a, 0x28},
+       {0x334e, 0xb4},
+       {0x334f, 0x01},
+#ifdef INIT_ET_INSETTING
+       {0x3020, 0xe1},
+       {0x3021, 0x04},
+#endif
+       {IMX185_TABLE_END, 0x00}
+};
+
+
+enum {
+       IMX185_MODE_1952X1115_60FPS,
+       IMX185_MODE_1952X1115_HDR_30FPS,
+       IMX185_MODE_1920X1080_CROP,
+       IMX185_MODE_1920X1080_HDR_CROP,
+       IMX185_MODE_1920X1080_CROP_10BIT,
+       IMX185_MODE_TEST_1080P_10BIT_30FPS,
+       IMX185_MODE_START_STREAM,
+       IMX185_MODE_STOP_STREAM,
+       IMX185_MODE_TEST_PATTERN
+};
+
+static imx185_reg *mode_table[] = {
+       [IMX185_MODE_1952X1115_60FPS] = imx185_1952x1115,
+       [IMX185_MODE_1952X1115_HDR_30FPS] = imx185_1952x1115_hdr,
+
+       [IMX185_MODE_1920X1080_CROP] = imx185_1920x1080_crop,
+       [IMX185_MODE_1920X1080_HDR_CROP] = imx185_1920x1080_hdr_crop,
+       [IMX185_MODE_1920X1080_CROP_10BIT] = imx185_1920x1080_crop_10bit,
+       [IMX185_MODE_TEST_1080P_10BIT_30FPS] =
+               imx185_1920x1080_crop_10bit_30fps,
+
+       [IMX185_MODE_START_STREAM] = imx185_start,
+       [IMX185_MODE_STOP_STREAM] = imx185_stop,
+       [IMX185_MODE_TEST_PATTERN] = tp_colorbars,
+};
+
+static const struct camera_common_frmfmt imx185_frmfmt[] = {
+#if 0
+       /*1080p-HD mode*/
+       {{1952, 1115}, 0, IMX185_MODE_1952X1115_60FPS},
+       {{1952, 1115}, 1, IMX185_MODE_1952X1115_HDR_30FPS},
+
+       /*cropping mode*/
+       {{1920, 1080}, 0, IMX185_MODE_1920X1080_CROP},
+       {{1920, 1080}, 1, IMX185_MODE_1920X1080_HDR_CROP},
+       {{1920, 1080}, 0, IMX185_MODE_1920X1080_CROP_10BIT},
+       {{1920, 1080}, 0, IMX185_MODE_TEST_1080P_10BIT_30FPS},
+#endif
+       {{1920, 1080}, 0, IMX185_MODE_1920X1080_CROP_10BIT},
+
+};
+#endif /* __IMX185_I2C_TABLES__ */
diff --git a/include/media/imx185.h b/include/media/imx185.h
new file mode 100644 (file)
index 0000000..ffd0b73
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2016, 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 __IMX185_H__
+#define __IMX185_H__
+
+#include <linux/ioctl.h>
+#include <media/nvc.h>
+#include <media/nvc_image.h>
+
+#define IMX185_EEPROM_STR_SIZE 80
+#define IMX185_OTP_STR_SIZE    60
+#define IMX185_FUSE_ID_ADDR    0x3382
+#define IMX185_FUSE_ID_SIZE    6
+#define IMX185_FUSE_ID_STR_SIZE        (IMX185_FUSE_ID_SIZE * 2)
+
+#define IMX185_FRAME_LENGTH_ADDR_MSB   0x301A
+#define IMX185_FRAME_LENGTH_ADDR_MID   0x3019
+#define IMX185_FRAME_LENGTH_ADDR_LSB   0x3018
+#define IMX185_COARSE_TIME_SHS1_ADDR_MSB       0x3022
+#define IMX185_COARSE_TIME_SHS1_ADDR_MID       0x3021
+#define IMX185_COARSE_TIME_SHS1_ADDR_LSB       0x3020
+#define IMX185_COARSE_TIME_SHS2_ADDR_MSB       0x3025
+#define IMX185_COARSE_TIME_SHS2_ADDR_MID       0x3024
+#define IMX185_COARSE_TIME_SHS2_ADDR_LSB       0x3023
+#define IMX185_GAIN_ADDR       0x3014
+#define IMX185_GROUP_HOLD_ADDR 0x3001
+
+#define IMX185_PCA954X_I2C_ADDR (0x70)
+
+struct imx185_mode {
+       __u32 xres;
+       __u32 yres;
+       __u32 frame_length;
+       __u32 coarse_time;
+       __u32 coarse_time_short;
+       __u16 gain;
+       __u8 hdr_en;
+};
+
+struct imx185_hdr {
+       __u32 coarse_time_long;
+       __u32 coarse_time_short;
+};
+
+struct imx185_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 imx185_sensordata {
+       __u32 fuse_id_size;
+       __u8  fuse_id[IMX185_FUSE_ID_SIZE];
+};
+
+#ifdef __KERNEL__
+struct imx185_power_rail {
+       struct regulator *dvdd;
+       struct regulator *avdd;
+       struct regulator *iovdd;
+       struct regulator *ext_reg1;
+       struct regulator *ext_reg2;
+       struct clk *mclk;
+       unsigned int pwdn_gpio;
+       unsigned int cam1_gpio;
+       unsigned int reset_gpio;
+       unsigned int af_gpio;
+};
+
+struct imx185_platform_data {
+       const char *mclk_name; /* NULL for default default_mclk */
+       unsigned int cam1_gpio;
+       unsigned int reset_gpio;
+       unsigned int af_gpio;
+       bool ext_reg;
+       int (*power_on)(struct imx185_power_rail *pw);
+       int (*power_off)(struct imx185_power_rail *pw);
+};
+#endif /* __KERNEL__ */
+#endif  /* __IMX185_H__ */