]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
drivers: soc_camera: add ov23850 OTP controls
authorDavid Wang <davidw@nvidia.com>
Thu, 17 Sep 2015 23:08:23 +0000 (16:08 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Tue, 10 Nov 2015 07:33:09 +0000 (23:33 -0800)
enabling ov23850 driver with OTP and fuse id controls.

bug 1651635.

Change-Id: I0e9b4a72135730a5a55e986d1f3a2e064f3cc834
Signed-off-by: David Wang <davidw@nvidia.com>
(cherry picked from commit 6d3d3aa222a273bec33d630b18e1e30efda16882)
Reviewed-on: http://git-master/r/825097
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
drivers/media/i2c/soc_camera/imx214_v4l2.c
drivers/media/i2c/soc_camera/ov23850_v4l2.c
drivers/media/platform/soc_camera/camera_common.c
include/media/camera_common.h
include/media/ov23850.h
include/media/tegra_v4l2_camera.h

index 71c56d9a3a4991a897b5cadff7bf3cf0bf0172b8..7d9764d5303def418aa47d5f4772e65ea05eca06 100644 (file)
@@ -628,6 +628,25 @@ fail:
        return err;
 }
 
+int imx214_to_gain(u32 rep, int shift)
+{
+       int gain;
+       int gain_int;
+       int gain_dec;
+       int min_int = (1 << shift);
+       int denom;
+
+       /* last 4 bit of rep is
+        * decimal representation of gain */
+       gain_int = (int)(rep >> shift);
+       gain_dec = (int)(rep & ~(0xffff << shift));
+
+       denom = gain_int * min_int + gain_dec;
+       gain = 512 - ((512 * min_int + (denom - 1)) / denom);
+
+       return gain;
+}
+
 static int imx214_set_gain(struct imx214 *priv, s32 val)
 {
        imx214_reg reg_list[2];
@@ -637,7 +656,7 @@ static int imx214_set_gain(struct imx214 *priv, s32 val)
        int i = 0;
 
        /* translate value */
-       gain = (u16)camera_common_to_gain(val, IMX214_GAIN_SHIFT);
+       gain = (u16)imx214_to_gain(val, IMX214_GAIN_SHIFT);
 
        dev_dbg(&priv->i2c_client->dev,
                 "%s: val: %d\n", __func__, gain);
index 6e76b0a6a32648001f8e599493732e91709bf87e..c70e5a234c2eb11b5ec220456181249291d53c70 100644 (file)
@@ -26,9 +26,8 @@
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 
-#include <mach/io_dpd.h>
-
 #include <media/v4l2-chip-ident.h>
+#include <media/tegra_v4l2_camera.h>
 #include <media/camera_common.h>
 #include <media/ov23850.h>
 
@@ -40,7 +39,7 @@
 #define OV23850_MIN_GAIN               (1 << OV23850_GAIN_SHIFT)
 #define OV23850_MAX_GAIN               (16 << OV23850_GAIN_SHIFT)
 #define OV23850_MIN_FRAME_LENGTH       (0x0)
-#define OV23850_MAX_FRAME_LENGTH       (0xffff)
+#define OV23850_MAX_FRAME_LENGTH       (0x7fff)
 #define OV23850_MIN_EXPOSURE_COARSE    (0x0001)
 #define OV23850_MAX_EXPOSURE_COARSE    \
        (OV23850_MAX_FRAME_LENGTH-OV23850_MAX_COARSE_DIFF)
 #define OV23850_DEFAULT_DATAFMT        V4L2_MBUS_FMT_SRGGB10_1X10
 #define OV23850_DEFAULT_CLK_FREQ       24000000
 
-static struct tegra_io_dpd csia_io = {
-       .name                   = "CSIA",
-       .io_dpd_reg_index       = 0,
-       .io_dpd_bit             = 0x0,
-};
-
-static struct tegra_io_dpd csib_io = {
-       .name                   = "CSIB",
-       .io_dpd_reg_index       = 0,
-       .io_dpd_bit             = 0x1,
-};
-
-static struct tegra_io_dpd csic_io = {
-       .name                   = "CSIC",
-       .io_dpd_reg_index       = 1,
-       .io_dpd_bit             = 0xa,
-};
-
-static struct tegra_io_dpd csid_io = {
-       .name                   = "CSID",
-       .io_dpd_reg_index       = 1,
-       .io_dpd_bit             = 0xb,
-};
-
-
 struct ov23850 {
        struct mutex                    ov23850_camera_lock;
        struct camera_common_power_rail power;
-       int                             num_ctrls;
+       int                             numctrls;
        struct v4l2_ctrl_handler        ctrl_handler;
 #if 0
        struct camera_common_eeprom_data eeprom[OV23850_EEPROM_NUM_BLOCKS];
@@ -93,8 +67,8 @@ struct ov23850 {
        struct i2c_client               *i2c_client;
        struct v4l2_subdev              *subdev;
 
-       s32 group_hold_prev;
-       bool group_hold_en;
+       s32                             group_hold_prev;
+       bool                            group_hold_en;
        struct regmap                   *regmap;
        struct camera_common_data       *s_data;
        struct camera_common_pdata      *pdata;
@@ -332,21 +306,10 @@ static int ov23850_power_on(struct camera_common_data *s_data)
        struct camera_common_power_rail *pw = &priv->power;
 
        dev_dbg(&priv->i2c_client->dev, "%s: power on\n", __func__);
-       if (priv->i2c_client->addr == 0x10) {
-                       /* disable CSIA/B IOs DPD mode to turn on camera A*/
-                       tegra_io_dpd_disable(&csia_io);
-                       tegra_io_dpd_disable(&csib_io);
-       } else if (priv->i2c_client->addr == 0x36) {
-                       /* disable CSIC/D IOs DPD mode to turn on camera B*/
-                       tegra_io_dpd_disable(&csic_io);
-                       tegra_io_dpd_disable(&csid_io);
-       }
 
        if (priv->pdata->power_on) {
                err = priv->pdata->power_on(pw);
                if (err) {
-                       tegra_io_dpd_enable(&csia_io);
-                       tegra_io_dpd_enable(&csib_io);
                        pr_err("%s failed.\n", __func__);
                } else {
                        pw->state = SWITCH_ON;
@@ -399,14 +362,6 @@ ov23850_dvdd_fail:
        regulator_disable(pw->avdd);
 
 ov23850_avdd_fail:
-       if (priv->i2c_client->addr == 0x10) {
-                       tegra_io_dpd_enable(&csia_io);
-                       tegra_io_dpd_enable(&csib_io);
-       } else if (priv->i2c_client->addr == 0x36) {
-                       tegra_io_dpd_enable(&csic_io);
-                       tegra_io_dpd_enable(&csid_io);
-       }
-
        pr_err("%s failed.\n", __func__);
        return -ENODEV;
 }
@@ -446,18 +401,6 @@ static int ov23850_power_off(struct camera_common_data *s_data)
                regulator_disable(pw->avdd);
 
 power_off_done:
-       if (priv->i2c_client->addr == 0x10) {
-                       /* put CSIA/B IOs into DPD mode
-                        * to save additional power*/
-                       tegra_io_dpd_enable(&csia_io);
-                       tegra_io_dpd_enable(&csib_io);
-       } else if (priv->i2c_client->addr == 0x36) {
-                       /* put CSIC/D IOs into DPD mode
-                        * to save additional power*/
-                       tegra_io_dpd_enable(&csic_io);
-                       tegra_io_dpd_enable(&csid_io);
-       }
-
        pw->state = SWITCH_OFF;
        return 0;
 }
@@ -664,6 +607,7 @@ static int ov23850_set_gain(struct ov23850 *priv, s32 val)
                 "%s: val: %d\n", __func__, gain);
 
        ov23850_get_gain_reg(reg_list, gain);
+       ov23850_get_gain_short_reg(reg_list_short, gain);
        ov23850_set_group_hold(priv);
 
        /* writing long gain */
@@ -761,7 +705,7 @@ static int ov23850_set_coarse_time_short(struct ov23850 *priv, s32 val)
        /* check hdr enable ctrl */
        hdr_control.id = V4L2_CID_HDR_EN;
 
-       err = v4l2_g_ctrl(&priv->ctrl_handler, &hdr_control);
+       err = camera_common_g_ctrl(priv->s_data, &hdr_control);
        if (err < 0) {
                dev_err(&priv->i2c_client->dev,
                        "could not find device ctrl.\n");
@@ -890,40 +834,95 @@ static int ov23850_write_eeprom(struct ov23850 *priv,
        }
        return 0;
 }
+#endif
 
-static int ov23850_read_otp_page(struct ov23850 *priv,
-                               u8 *buf, int page, u16 addr, int size)
+static int ov23850_read_otp_manual(struct ov23850 *priv,
+                               u8 *buf, u16 addr_start, u16 addr_end)
 {
        u8 status;
+       int i;
        int err;
+       int size = addr_end - addr_start + 1;
+       u8 isp;
+       u16 addr_start_capped = addr_start;
 
-       err = ov23850_write_reg(priv->s_data, OV23850_OTP_PAGE_NUM_ADDR, page);
+       if (addr_start > 0x6A00)
+               addr_start_capped = 0x69FF;
+
+       usleep_range(10000, 11000);
+       err = ov23850_write_table(priv, mode_table[OV23850_MODE_START_STREAM]);
        if (err)
                return err;
-       err = ov23850_write_reg(priv->s_data, OV23850_OTP_CTRL_ADDR, 0x01);
+
+       err = ov23850_read_reg(priv->s_data, OV23850_OTP_ISP_CTRL_ADDR, &isp);
        if (err)
                return err;
-       err = ov23850_read_reg(priv->s_data, OV23850_OTP_STATUS_ADDR, &status);
+       err = ov23850_write_reg(priv->s_data, OV23850_OTP_ISP_CTRL_ADDR,
+                               isp & 0xfe);
        if (err)
                return err;
-       if (status == OV23850_OTP_STATUS_IN_PROGRESS) {
-               dev_err(&priv->i2c_client->dev,
-                       "another OTP read in progress\n");
+
+       err = ov23850_write_reg(priv->s_data, OV23850_OTP_MODE_CTRL_ADDR, 0x40);
+       if (err)
                return err;
-       }
 
-       err = regmap_bulk_read(priv->regmap, addr, buf, size);
+
+       err = ov23850_write_reg(priv->s_data, OV23850_OTP_START_REG_ADDR_MSB,
+                               (addr_start_capped >> 8) & 0xff);
+       if (err)
+               return err;
+       err = ov23850_write_reg(priv->s_data, OV23850_OTP_START_REG_ADDR_LSB,
+                               addr_start_capped & 0xff);
        if (err)
                return err;
 
-       err = ov23850_read_reg(priv->s_data, OV23850_OTP_STATUS_ADDR, &status);
+       err = ov23850_write_reg(priv->s_data, OV23850_OTP_END_REG_ADDR_MSB,
+                               (addr_end >> 8) & 0xff);
+       if (err)
+               return err;
+       err = ov23850_write_reg(priv->s_data, OV23850_OTP_END_REG_ADDR_LSB,
+                               addr_end & 0xff);
        if (err)
                return err;
-       if (status == OV23850_OTP_STATUS_READ_FAIL) {
-               dev_err(&priv->i2c_client->dev, "fuse id read error\n");
+
+       err = ov23850_write_reg(priv->s_data, OV23850_OTP_LOAD_CTRL_ADDR, 0x01);
+       if (err)
                return err;
+
+       usleep_range(10000, 11000);
+       for (i = 0; i < size; i++) {
+               err = ov23850_read_reg(priv->s_data, addr_start + i, &buf[i]);
+               if (err)
+                       return err;
+
+               err = ov23850_read_reg(priv->s_data,
+                                      OV23850_OTP_LOAD_CTRL_ADDR, &status);
+               if (err)
+                       return err;
+
+               if (status & OV23850_OTP_RD_BUSY_MASK) {
+                       dev_err(&priv->i2c_client->dev,
+                               "another OTP read in progress\n");
+                       return err;
+               } else if (status & OV23850_OTP_BIST_ERROR_MASK) {
+                       dev_err(&priv->i2c_client->dev, "fuse id read error\n");
+                       return err;
+               }
        }
 
+       err = ov23850_write_table(priv,
+                       mode_table[OV23850_MODE_STOP_STREAM]);
+       if (err)
+               return err;
+
+       err = ov23850_read_reg(priv->s_data, OV23850_OTP_ISP_CTRL_ADDR, &isp);
+       if (err)
+               return err;
+       err = ov23850_write_reg(priv->s_data, OV23850_OTP_ISP_CTRL_ADDR,
+                               isp | 0x01);
+       if (err)
+               return err;
+
        return 0;
 }
 
@@ -938,13 +937,10 @@ static int ov23850_otp_setup(struct ov23850 *priv)
        if (err)
                return -ENODEV;
 
-       for (i = 0; i < OV23850_OTP_NUM_PAGES; i++) {
-               ov23850_read_otp_page(priv,
-                                  &otp_buf[i * OV23850_OTP_PAGE_SIZE],
-                                  i,
-                                  OV23850_OTP_PAGE_START_ADDR,
-                                  OV23850_OTP_PAGE_SIZE);
-       }
+       ov23850_read_otp_manual(priv,
+                               otp_buf,
+                               OV23850_OTP_START_ADDR,
+                               OV23850_OTP_END_ADDR);
 
        ctrl = v4l2_ctrl_find(&priv->ctrl_handler, V4L2_CID_OTP_DATA);
        if (!ctrl) {
@@ -976,11 +972,10 @@ static int ov23850_fuse_id_setup(struct ov23850 *priv)
        if (err)
                return -ENODEV;
 
-       ov23850_read_otp_page(priv,
-                          &fuse_id[0],
-                          OV23850_FUSE_ID_OTP_PAGE,
-                          OV23850_FUSE_ID_OTP_ROW_ADDR,
-                          OV23850_FUSE_ID_SIZE);
+       ov23850_read_otp_manual(priv,
+                               fuse_id,
+                               OV23850_FUSE_ID_OTP_START_ADDR,
+                               OV23850_FUSE_ID_OTP_END_ADDR);
 
        ctrl = v4l2_ctrl_find(&priv->ctrl_handler, V4L2_CID_FUSE_ID);
        if (!ctrl) {
@@ -1000,7 +995,6 @@ static int ov23850_fuse_id_setup(struct ov23850 *priv)
 
        return 0;
 }
-#endif
 
 static int ov23850_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
@@ -1080,16 +1074,16 @@ static int ov23850_ctrls_init(struct ov23850 *priv)
 {
        struct i2c_client *client = priv->i2c_client;
        struct v4l2_ctrl *ctrl;
-       int num_ctrls;
+       int numctrls;
        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);
+       numctrls = ARRAY_SIZE(ctrl_config_list);
+       v4l2_ctrl_handler_init(&priv->ctrl_handler, numctrls);
 
-       for (i = 0; i < num_ctrls; i++) {
+       for (i = 0; i < numctrls; i++) {
                ctrl = v4l2_ctrl_new_custom(&priv->ctrl_handler,
                        &ctrl_config_list[i], NULL);
                if (ctrl == NULL) {
@@ -1106,7 +1100,7 @@ static int ov23850_ctrls_init(struct ov23850 *priv)
                priv->ctrls[i] = ctrl;
        }
 
-       priv->num_ctrls = num_ctrls;
+       priv->numctrls = numctrls;
        priv->subdev->ctrl_handler = &priv->ctrl_handler;
        if (priv->ctrl_handler.error) {
                dev_err(&client->dev, "Error %d adding controls\n",
@@ -1122,7 +1116,6 @@ static int ov23850_ctrls_init(struct ov23850 *priv)
                goto error;
        }
 
-#if 0
        err = ov23850_otp_setup(priv);
        if (err) {
                dev_err(&client->dev,
@@ -1136,7 +1129,6 @@ static int ov23850_ctrls_init(struct ov23850 *priv)
                        "Error %d reading fuse id data\n", err);
                goto error;
        }
-#endif
 
        return 0;
 
@@ -1222,8 +1214,10 @@ static int ov23850_probe(struct i2c_client *client,
 {
        struct camera_common_data *common_data;
        struct ov23850 *priv;
-       int err;
+       struct soc_camera_subdev_desc *ssdd;
+       struct tegra_camera_platform_data *ov23850_camera_data;
        char node_name[10];
+       int err;
 
        pr_info("[OV23850]: probing v4l2 sensor at addr 0x%0x.\n",
                client->addr);
@@ -1242,16 +1236,39 @@ static int ov23850_probe(struct i2c_client *client,
                return -ENODEV;
        }
 
-       if (client->addr == 0x10)
-               sprintf(node_name, "%s", "ov23850_a");
-       else if (client->addr == 0x36)
-               sprintf(node_name, "%s", "ov23850_c");
-       else {
-               dev_err(&client->dev, "unsupported i2c addr %u\n",
-                       client->addr);
+       ssdd = soc_camera_i2c_to_desc(client);
+       ov23850_camera_data = (struct tegra_camera_platform_data *)
+                            ssdd->drv_priv;
+       if (!ov23850_camera_data) {
+               dev_err(&client->dev, "unable to find iclink module name\n");
                return -EFAULT;
        }
 
+       switch (ov23850_camera_data->port) {
+       case TEGRA_CAMERA_PORT_CSI_A:
+       case TEGRA_CAMERA_PORT_CSI_B:
+         sprintf(node_name, "%s", "ov23850_a");
+               common_data->csi_io[0] = true;
+               common_data->csi_io[1] = true;
+               break;
+       case TEGRA_CAMERA_PORT_CSI_C:
+       case TEGRA_CAMERA_PORT_CSI_D:
+         sprintf(node_name, "%s", "ov23850_c");
+               common_data->csi_io[2] = true;
+               common_data->csi_io[3] = true;
+               break;
+       case TEGRA_CAMERA_PORT_CSI_E:
+       case TEGRA_CAMERA_PORT_CSI_F:
+         sprintf(node_name, "%s", "ov23850_e");
+               common_data->csi_io[4] = true;
+               common_data->csi_io[5] = true;
+               break;
+       default:
+         dev_err(&client->dev, "unsupported device port\n");
+         return -EFAULT;
+       }
+
+       dev_dbg(&client->dev, "%s: dt node name %s\n", __func__, node_name);
        client->dev.of_node = of_find_node_by_name(NULL, node_name);
 
        if (client->dev.of_node) {
@@ -1274,7 +1291,9 @@ static int ov23850_probe(struct i2c_client *client,
        common_data->colorfmt           = camera_common_find_datafmt(
                                          OV23850_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(ov23850_frmfmt);
        common_data->def_mode           = OV23850_DEFAULT_MODE;
        common_data->def_width          = OV23850_DEFAULT_WIDTH;
@@ -1350,3 +1369,4 @@ module_i2c_driver(ov23850_i2c_driver);
 MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV23850");
 MODULE_AUTHOR("David Wang <davidw@nvidia.com>");
 MODULE_LICENSE("GPL v2");
+
index 9a4470e2731aec7c472fe14c5fd6651efd74ee25..e10abfa6e5760b0b0e7efcb919f3a216823861d1 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <media/camera_common.h>
+#include <mach/io_dpd.h>
 
 #define has_s_op(master, op) \
        (master->ops && master->ops->op)
@@ -32,23 +33,55 @@ static const struct camera_common_colorfmt camera_common_color_fmts[] = {
        {V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_COLORSPACE_SRGB},
 };
 
-int camera_common_to_gain(u32 rep, int shift)
-{
-       int gain;
-       int gain_int;
-       int gain_dec;
-       int min_int = (1 << shift);
-       int denom;
+static struct tegra_io_dpd camera_common_csi_io[] = {
+       {
+               .name                   = "CSIA",
+               .io_dpd_reg_index       = 0,
+               .io_dpd_bit             = 0x0,
+       },
+       {
+               .name                   = "CSIB",
+               .io_dpd_reg_index       = 0,
+               .io_dpd_bit             = 0x1,
+       },
+       {
+               .name                   = "CSIC",
+               .io_dpd_reg_index       = 1,
+               .io_dpd_bit             = 0xa,
+       },
+       {
+               .name                   = "CSID",
+               .io_dpd_reg_index       = 1,
+               .io_dpd_bit             = 0xb,
+       },
+       {
+               .name                   = "CSIE",
+               .io_dpd_reg_index       = 1,
+               .io_dpd_bit             = 0xc,
+       },
+       {
+               .name                   = "CSIF",
+               .io_dpd_reg_index       = 1,
+               .io_dpd_bit             = 0xd,
+       },
+};
 
-       /* last 4 bit of rep is
-        * decimal representation of gain */
-       gain_int = (int)(rep >> shift);
-       gain_dec = (int)(rep & ~(0xffff << shift));
+int camera_common_g_ctrl(struct camera_common_data *s_data,
+                        struct v4l2_control *control)
+{
+       int i;
 
-       denom = gain_int * min_int + gain_dec;
-       gain = 512 - ((512 * min_int + (denom - 1)) / denom);
+       for (i = 0; i < s_data->numctrls; i++) {
+               if (s_data->ctrls[i]->id == control->id) {
+                       control->value = s_data->ctrls[i]->val;
+                       dev_dbg(&s_data->i2c_client->dev,
+                                "%s: found control %s\n", __func__,
+                                s_data->ctrls[i]->name);
+                       return 0;
+               }
+       }
 
-       return gain;
+       return -EFAULT;
 }
 
 int camera_common_regulator_get(struct i2c_client *client,
@@ -227,7 +260,7 @@ int camera_common_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
        int err;
        int i;
 
-       dev_dbg(&client->dev, "%s: szie %i x %i\n", __func__,
+       dev_dbg(&client->dev, "%s: size %i x %i\n", __func__,
                 mf->width, mf->height);
 
        /* check hdr enable ctrl */
@@ -328,6 +361,13 @@ int camera_common_g_chip_ident(struct v4l2_subdev *sd,
 static void camera_common_mclk_disable(struct camera_common_data *s_data)
 {
        struct camera_common_power_rail *pw = s_data->power;
+
+       if (!pw) {
+               dev_err(&s_data->i2c_client->dev, "%s: no device power rail\n",
+                       __func__);
+               return;
+       }
+
        dev_dbg(&s_data->i2c_client->dev, "%s: disable MCLK\n", __func__);
        clk_disable_unprepare(pw->mclk);
 }
@@ -338,6 +378,12 @@ static int camera_common_mclk_enable(struct camera_common_data *s_data)
        struct camera_common_power_rail *pw = s_data->power;
        unsigned long mclk_init_rate = s_data->def_clk_freq;
 
+       if (!pw) {
+               dev_err(&s_data->i2c_client->dev, "%s: no device power rail\n",
+                       __func__);
+               return -EFAULT;
+       }
+
        dev_dbg(&s_data->i2c_client->dev, "%s: enable MCLK with %lu Hz\n",
                __func__, mclk_init_rate);
 
@@ -347,6 +393,28 @@ static int camera_common_mclk_enable(struct camera_common_data *s_data)
        return err;
 }
 
+static void camera_common_dpd_disable(struct camera_common_data *s_data)
+{
+       int i;
+
+       /* disable CSI IOs DPD mode to turn on camera */
+       for (i = 0; i < ARRAY_SIZE(s_data->csi_io); i++) {
+               if (s_data->csi_io[i])
+                       tegra_io_dpd_disable(&camera_common_csi_io[i]);
+       }
+}
+
+static void camera_common_dpd_enable(struct camera_common_data *s_data)
+{
+       int i;
+
+       /* disable CSI IOs DPD mode to turn on camera */
+       for (i = 0; i < ARRAY_SIZE(s_data->csi_io); i++) {
+               if (s_data->csi_io[i])
+                       tegra_io_dpd_enable(&camera_common_csi_io[i]);
+       }
+}
+
 int camera_common_s_power(struct v4l2_subdev *sd, int on)
 {
        int err;
@@ -355,13 +423,17 @@ int camera_common_s_power(struct v4l2_subdev *sd, int on)
 
        if (on) {
                err = camera_common_mclk_enable(s_data);
+               camera_common_dpd_disable(s_data);
                if (!err)
                        err = call_s_op(s_data, power_on);
-               if (err)
+               if (err) {
+                       camera_common_dpd_enable(s_data);
                        camera_common_mclk_disable(s_data);
+               }
                return err;
        } else if (!on) {
                call_s_op(s_data, power_off);
+               camera_common_dpd_enable(s_data);
                camera_common_mclk_disable(s_data);
                return 0;
        } else
@@ -378,3 +450,4 @@ int camera_common_g_mbus_config(struct v4l2_subdev *sd,
 
        return 0;
 }
+
index 4fce587a69ff3369aa671728ed8ac045dcc88bb3..5c7db60fb26c8072d072e08bb54bc0bf73965ca0 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/kernel.h>
 #include <linux/debugfs.h>
 
+#include <media/tegra_v4l2_camera.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-ctrls.h>
@@ -154,9 +155,12 @@ struct camera_common_data {
        struct camera_common_power_rail         *power;
 
        struct v4l2_subdev                      subdev;
+       struct v4l2_ctrl                        **ctrls;
 
        void    *priv;
        int     ident;
+       int     numctrls;
+       bool    csi_io[TEGRA_CAMERA_NUM_CSI_PORT];
        int     mode;
        int     numfmts;
        int     def_mode, def_width, def_height;
@@ -176,7 +180,9 @@ static inline struct camera_common_data *to_camera_common_data(
                            struct camera_common_data, subdev);
 }
 
-int camera_common_to_gain(u32 rep, int shift);
+int camera_common_g_ctrl(struct camera_common_data *s_data,
+                        struct v4l2_control *control);
+
 int camera_common_regulator_get(struct i2c_client *client,
                       struct regulator **vreg, const char *vreg_name);
 
index 6e9a73e8b9f4128ab2b66cb2a211da8d0bf80ac6..4a8feaa468817c50af0e423e8835b5c9fe3a92a1 100644 (file)
 #define OV23850_EEPROM_NUM_BLOCKS \
         (OV23850_EEPROM_SIZE / OV23850_EEPROM_BLOCK_SIZE)
 
-#define OV23850_OTP_CTRL_ADDR          0x0
-#define OV23850_OTP_STATUS_ADDR                0x0
-#define OV23850_OTP_PAGE_NUM_ADDR      0x0
-#define OV23850_OTP_PAGE_START_ADDR    0x0
-#define OV23850_OTP_PAGE_END_ADDR      0x0
-#define OV23850_OTP_NUM_PAGES          (16)
-#define OV23850_OTP_PAGE_SIZE \
-        (OV23850_OTP_PAGE_END_ADDR - OV23850_OTP_PAGE_START_ADDR + 1)
+#define OV23850_OTP_ISP_CTRL_ADDR              0x5000
+#define OV23850_OTP_LOAD_CTRL_ADDR             0x3D81
+#define OV23850_OTP_MODE_CTRL_ADDR             0x3D84
+#define OV23850_OTP_POWER_UP_ADDR              0x3D85
+#define OV23850_OTP_START_REG_ADDR_MSB         0x3D88
+#define OV23850_OTP_START_REG_ADDR_LSB         0x3D89
+#define OV23850_OTP_END_REG_ADDR_MSB           0x3D8A
+#define OV23850_OTP_END_REG_ADDR_LSB           0x3D8B
+#define OV23850_OTP_START_ADDR 0x6000
+#define OV23850_OTP_END_ADDR   0x601F
 #define OV23850_OTP_SIZE \
-        (OV23850_OTP_PAGE_SIZE * OV23850_OTP_NUM_PAGES)
+        (OV23850_OTP_END_ADDR - OV23850_OTP_START_ADDR + 1)
+
 #define OV23850_OTP_STR_SIZE (OV23850_OTP_SIZE * 2)
-#define OV23850_OTP_STATUS_IN_PROGRESS         0
-#define OV23850_OTP_STATUS_READ_COMPLETE       1
-#define OV23850_OTP_STATUS_READ_FAIL           5
+#define OV23850_OTP_RD_BUSY_MASK               0x80
+#define OV23850_OTP_BIST_ERROR_MASK    0x10
+#define OV23850_OTP_BIST_DONE_MASK             0x08
 
-#define OV23850_FUSE_ID_OTP_ROW_ADDR   0x0
-#define OV23850_FUSE_ID_OTP_PAGE       19 /*0x13*/
-#define OV23850_FUSE_ID_SIZE           11
+#define OV23850_FUSE_ID_OTP_START_ADDR 0x6000
+#define OV23850_FUSE_ID_OTP_END_ADDR   0x600F
+#define OV23850_FUSE_ID_SIZE \
+        (OV23850_FUSE_ID_OTP_END_ADDR - OV23850_FUSE_ID_OTP_START_ADDR + 1)
 #define OV23850_FUSE_ID_STR_SIZE       (OV23850_FUSE_ID_SIZE * 2)
 
 #define OV23850_FRAME_LENGTH_ADDR_MSB          0x380E
index f4e50df0169855a6c09b720877e7b0b889d153f8..531452ee446d942f027ebd7517877c9fba95390d 100644 (file)
@@ -30,6 +30,8 @@ enum tegra_camera_port {
        TEGRA_CAMERA_PORT_VIP,
 };
 
+#define TEGRA_CAMERA_NUM_CSI_PORT      6
+
 struct tegra_camera_platform_data {
        int                     (*enable_camera)(struct platform_device *pdev);
        void                    (*disable_camera)(struct platform_device *pdev);