arm: tegra: enterprise: support stereo sensor
Jihoon Bang [Fri, 24 Jun 2011 17:12:47 +0000 (10:12 -0700)]
Add separate power sequence and ID to rear sensors.
It will allow them to operate independently.

Bug 844021

Original-Change-Id: Iaf3399ea4c70999d1c8ea432f2df10c078e86004
Reviewed-on: http://git-master/r/40386
Reviewed-by: Daniel Willemsen <dwillemsen@nvidia.com>
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
Tested-by: Jihoon Bang <jbang@nvidia.com>

Rebase-Id: R4bbc3008be78ea2fba63926fafedaea5b54cc4b3

arch/arm/mach-tegra/board-enterprise-power.c
arch/arm/mach-tegra/board-enterprise-sensors.c

index 436c1d7..244ad27 100644 (file)
@@ -279,18 +279,23 @@ static struct regulator_consumer_supply gpio_switch_sdmmc3_vdd_sel_supply[] = {
        REGULATOR_SUPPLY("vddio_sdmmc3_2v85_1v8", NULL),
        REGULATOR_SUPPLY("sdmmc3_compu_pu", NULL),
        REGULATOR_SUPPLY("vddio_sdmmc3", NULL),
+       REGULATOR_SUPPLY("vsys_3v7", NULL),
 };
 static int gpio_switch_sdmmc3_vdd_sel_voltages[] = {2850};
 
 /* LCD-D23 (GPIO M7) from T30*/
+/* 2-0036 is dev_name of ar0832 */
 static struct regulator_consumer_supply gpio_switch_cam_ldo_2v8_en_supply[] = {
-       REGULATOR_SUPPLY("vdd_2v8_cam", NULL),
+       REGULATOR_SUPPLY("vaa", "2-0036"),
+       REGULATOR_SUPPLY("vaa", "2-0032"),
 };
 static int gpio_switch_cam_ldo_2v8_en_voltages[] = {2800};
 
 /* LCD-D9 (GPIO F1) from T30*/
+/* 2-0036 is dev_name of ar0832 */
 static struct regulator_consumer_supply gpio_switch_cam_ldo_1v8_en_supply[] = {
-       REGULATOR_SUPPLY("vdd_1v8_cam", NULL),
+       REGULATOR_SUPPLY("vdd", "2-0036"),
+       REGULATOR_SUPPLY("vdd", "2-0032"),
 };
 static int gpio_switch_cam_ldo_1v8_en_voltages[] = {1800};
 
@@ -326,10 +331,10 @@ GREG_INIT(0, pmu_5v15_en,     NULL,      ENT_TPS80031_GPIO_REGEN1, false, 0, 0,
 GREG_INIT(1, pmu_3v3_en,      "vdd_5v15", ENT_TPS80031_GPIO_REGEN2, false, 0, 0, 0, 0);
 GREG_INIT(2, pmu_hdmi_5v0_en, "vdd_5v15", ENT_TPS80031_GPIO_SYSEN, false, 0, 0, 0, 0);
 
-GREG_INIT(3, vdd_fuse_en,    "avdd_usb_hdmi_3v3", TEGRA_GPIO_PM0, false, 0, 0, 0, 0);
+GREG_INIT(3, vdd_fuse_en, "avdd_usb_hdmi_3v3", TEGRA_GPIO_PM0, false, 0, 0, 0, 0);
 GREG_INIT(4, sdmmc3_vdd_sel, "vddio_sdmmc_2v85", TEGRA_GPIO_PM1, false, 0, 0, 0, 0);
-GREG_INIT(5, cam_ldo_2v8_en,    NULL, TEGRA_GPIO_PM7, false, 0, 0, 0, 0);
-GREG_INIT(6, cam_ldo_1v8_en,    NULL, TEGRA_GPIO_PF1, false, 0, 0, 0, 0);
+GREG_INIT(5, cam_ldo_2v8_en, NULL, TEGRA_GPIO_PM7, false, 0, 0, 0, 0);
+GREG_INIT(6, cam_ldo_1v8_en, NULL, TEGRA_GPIO_PF1, false, 0, 0, 0, 0);
 
 #define ADD_GPIO_REG(_name)    (&gpio_pdata_##_name)
 static struct gpio_switch_regulator_subdev_data *gswitch_subdevs[] = {
index 21f30ef..9365733 100644 (file)
@@ -52,15 +52,10 @@ static struct i2c_board_info enterprise_i2c4_nct1008_board_info[] = {
        }
 };
 
-static inline void enterprise_msleep(u32 t)
-{
-       /*
-       If timer value is between ( 10us - 20ms),
-       usleep_range() is recommended.
-       Please read Documentation/timers/timers-howto.txt.
-       */
-       usleep_range(t*1000, t*1000 + 500);
-}
+struct enterprise_power_rail {
+       struct regulator *cam_reg;
+       struct regulator *csi_reg;
+};
 
 static void enterprise_nct1008_init(void)
 {
@@ -119,6 +114,16 @@ static struct i2c_board_info __initdata mpu3050_i2c0_boardinfo[] = {
        },
 };
 
+static inline void enterprise_msleep(u32 t)
+{
+       /*
+       If timer value is between ( 10us - 20ms),
+       usleep_range() is recommended.
+       Please read Documentation/timers/timers-howto.txt.
+       */
+       usleep_range(t*1000, t*1000 + 500);
+}
+
 static void enterprise_mpuirq_init(void)
 {
        int ret = 0;
@@ -153,81 +158,139 @@ static void enterprise_isl_init(void)
                                ARRAY_SIZE(enterprise_i2c0_isl_board_info));
 }
 
-
-static struct regulator *cam_reg;
-static struct regulator *csi_reg;
-
-static int enterprise_ar0832_power_on(void)
+static int enterprise_ar0832_power_on(struct enterprise_power_rail *prail)
 {
        int ret = 0;
 
-       csi_reg = regulator_get(NULL, "avdd_dsi_csi");
-       if (IS_ERR_OR_NULL(csi_reg)) {
-               pr_err("%s: get csi pwr err\n", __func__);
-               return PTR_ERR(cam_reg);
-       }
+       pr_info("%s: ++\n", __func__);
 
-       ret = regulator_enable(csi_reg);
+       if (!prail->csi_reg) {
+               prail->csi_reg = regulator_get(NULL, "avdd_dsi_csi");
+               if (IS_ERR_OR_NULL(prail->csi_reg)) {
+                       pr_err("%s: failed to get csi pwr\n", __func__);
+                       return PTR_ERR(prail->csi_reg);
+               }
+       }
+       ret = regulator_enable(prail->csi_reg);
        if (ret) {
-               pr_err("%s: enable csi pwr err\n", __func__);
+               pr_err("%s: failed to enable csi pwr\n", __func__);
                goto fail_regulator_csi_reg;
        }
 
-       cam_reg = regulator_get(NULL, "vddio_cam");
-       if (IS_ERR_OR_NULL(cam_reg)) {
-               pr_err("%s: get cam pwr err\n", __func__);
-               return PTR_ERR(cam_reg);
+       if (!prail->cam_reg) {
+               prail->cam_reg = regulator_get(NULL, "vddio_cam");
+               if (IS_ERR_OR_NULL(prail->cam_reg)) {
+                       pr_err("%s: failed to get cam pwr\n", __func__);
+                       ret = PTR_ERR(prail->cam_reg);
+                       goto fail_regulator_csi_reg;
+               }
        }
-
-       ret = regulator_enable(cam_reg);
+       ret = regulator_enable(prail->cam_reg);
        if (ret) {
-               pr_err("%s: enable cam pwr err\n", __func__);
+               pr_err("%s: failed to enable cam pwr\n", __func__);
                goto fail_regulator_cam_reg;
        }
 
-       pr_info("%s: enable 1.8V...\n", __func__);
-       gpio_set_value(CAM_LDO_1V8_EN_L_GPIO, 1);
-       enterprise_msleep(20);
-       pr_info("%s: enable 2.8V...\n", __func__);
-       gpio_set_value(CAM_LDO_2V8_EN_L_GPIO, 1);
+       return 0;
+
+fail_regulator_cam_reg:
+       regulator_put(prail->cam_reg);
+       prail->cam_reg = NULL;
+fail_regulator_csi_reg:
+       regulator_put(prail->csi_reg);
+       prail->csi_reg = NULL;
+       return ret;
+}
+
+static struct enterprise_power_rail enterprise_ar0832_power_rail;
+
+static int enterprise_ar0832_ri_power_on(int is_stereo)
+{
+       int ret = 0;
+
+       pr_info("%s: ++\n", __func__);
+       ret = enterprise_ar0832_power_on(&enterprise_ar0832_power_rail);
 
-       gpio_set_value(CAM1_PWDN_GPIO, 1);
-       enterprise_msleep(5);
-       gpio_set_value(CAM1_RST_L_GPIO, 1);
+       /* Release Reset */
+       if (is_stereo) {
+               gpio_set_value(CAM1_RST_L_GPIO, 1);
+               gpio_set_value(CAM2_RST_L_GPIO, 1);
+       } else
+               gpio_set_value(CAM1_RST_L_GPIO, 1);
        /*
        It takes 2400 EXTCLK for ar0832 to be ready for I2c.
-       EXTCLK is 10 ~ 24MCK. 1 ms should be enough to cover
+       EXTCLK is 10 ~ 24MHz. 1 ms should be enough to cover
        at least 2400 EXTCLK within frequency range.
        */
        enterprise_msleep(1);
-       return 0;
 
-fail_regulator_cam_reg:
-       regulator_put(cam_reg);
-fail_regulator_csi_reg:
-       regulator_put(csi_reg);
+       return ret;
+}
+
+static int enterprise_ar0832_le_power_on(int is_stereo)
+{
+       int ret = 0;
+
+       pr_info("%s: ++\n", __func__);
+       ret = enterprise_ar0832_power_on(&enterprise_ar0832_power_rail);
+
+       /* Release Reset */
+       gpio_set_value(CAM2_RST_L_GPIO, 1);
+
+       /*
+       It takes 2400 EXTCLK for ar0832 to be ready for I2c.
+       EXTCLK is 10 ~ 24MHz. 1 ms should be enough to cover
+       at least 2400 EXTCLK within frequency range.
+       */
+       enterprise_msleep(1);
+
+       /* CSI B is shared between Front camera and Rear Left camera */
+       gpio_set_value(CAM_CSI_MUX_SEL_GPIO, 1);
 
        return ret;
 }
 
-static int enterprise_ar0832_power_off(void)
+static int enterprise_ar0832_power_off(struct enterprise_power_rail *prail)
 {
-       if (cam_reg) {
-               regulator_disable(cam_reg);
-               regulator_put(cam_reg);
-       }
-       if (csi_reg) {
-               regulator_disable(csi_reg);
-               regulator_put(csi_reg);
-       }
+       if (prail->cam_reg)
+               regulator_disable(prail->cam_reg);
 
-       gpio_set_value(CAM_LDO_2V8_EN_L_GPIO, 0);
-       mdelay(20);
-       gpio_set_value(CAM_LDO_1V8_EN_L_GPIO, 0);
+       if (prail->csi_reg)
+               regulator_disable(prail->csi_reg);
 
        return 0;
 }
 
+static int enterprise_ar0832_ri_power_off(int is_stereo)
+{
+       int ret;
+
+       pr_info("%s: ++\n", __func__);
+       ret = enterprise_ar0832_power_off(&enterprise_ar0832_power_rail);
+
+       /* Assert Reset */
+       if (is_stereo) {
+               gpio_set_value(CAM1_RST_L_GPIO, 0);
+               gpio_set_value(CAM2_RST_L_GPIO, 0);
+       } else
+               gpio_set_value(CAM1_RST_L_GPIO, 0);
+
+       return ret;
+}
+
+static int enterprise_ar0832_le_power_off(int is_stereo)
+{
+       int ret;
+
+       pr_info("%s: ++\n", __func__);
+       ret = enterprise_ar0832_power_off(&enterprise_ar0832_power_rail);
+
+       /* Assert Reset */
+       gpio_set_value(CAM2_RST_L_GPIO, 0);
+
+       return ret;
+}
+
 struct enterprise_cam_gpio {
        int gpio;
        const char *label;
@@ -237,37 +300,46 @@ struct enterprise_cam_gpio {
 #define TEGRA_CAMERA_GPIO(_gpio, _label, _value)       \
        {                                               \
                .gpio = _gpio,                          \
-               .label = _label,                                \
+               .label = _label,                        \
                .value = _value,                        \
        }
 
 static struct enterprise_cam_gpio enterprise_cam_gpio_data[] = {
-       [0] = TEGRA_CAMERA_GPIO(CAM_LDO_1V8_EN_L_GPIO, "cam_ldo_1v8", 0),
-       [1] = TEGRA_CAMERA_GPIO(CAM_LDO_2V8_EN_L_GPIO, "cam_ldo_2v8", 0),
-       [2] = TEGRA_CAMERA_GPIO(CAM_CSI_MUX_SEL_GPIO, "cam_csi_sel", 1),
-
-       [3] = TEGRA_CAMERA_GPIO(CAM1_RST_L_GPIO, "cam1_rst_lo", 0),
-       [4] = TEGRA_CAMERA_GPIO(CAM1_PWDN_GPIO, "cam1_pwdn", 1),
-
-       [5] = TEGRA_CAMERA_GPIO(CAM2_RST_L_GPIO, "cam2_rst_lo", 0),
-       [6] = TEGRA_CAMERA_GPIO(CAM2_PWDN_GPIO, "cam2_pwdn", 1),
+       [0] = TEGRA_CAMERA_GPIO(CAM_CSI_MUX_SEL_GPIO, "cam_csi_sel", 1),
+       [1] = TEGRA_CAMERA_GPIO(CAM1_RST_L_GPIO, "cam1_rst_lo", 0),
+       [2] = TEGRA_CAMERA_GPIO(CAM2_RST_L_GPIO, "cam2_rst_lo", 0),
+       [3] = TEGRA_CAMERA_GPIO(CAM3_RST_L_GPIO, "cam3_rst_lo", 0),
+       [4] = TEGRA_CAMERA_GPIO(CAM3_PWDN_GPIO, "cam3_pwdn", 1),
+};
 
-       [7] = TEGRA_CAMERA_GPIO(CAM3_RST_L_GPIO, "cam3_rst_lo", 0),
-       [8] = TEGRA_CAMERA_GPIO(CAM3_PWDN_GPIO, "cam3_pwdn", 1),
+struct ar0832_platform_data enterprise_ar0832_ri_data = {
+       .power_on = enterprise_ar0832_ri_power_on,
+       .power_off = enterprise_ar0832_ri_power_off,
+       .id = "right",
 };
 
-struct ar0832_platform_data enterprise_ar0832_data = {
-       .power_on = enterprise_ar0832_power_on,
-       .power_off = enterprise_ar0832_power_off,
+struct ar0832_platform_data enterprise_ar0832_le_data = {
+       .power_on = enterprise_ar0832_le_power_on,
+       .power_off = enterprise_ar0832_le_power_off,
+       .id = "left",
 };
 
+/*
+ * Since ar0832 driver should support multiple devices, slave
+ * address should be changed after it is open. Default slave
+ * address of ar0832 is 0x36. It will be changed to alternate
+ * address defined below when device is open.
+ */
 static struct i2c_board_info ar0832_i2c2_boardinfo[] = {
        {
+               /* 0x30: alternative slave address */
                I2C_BOARD_INFO("ar0832", 0x36),
-               .platform_data = &enterprise_ar0832_data,
+               .platform_data = &enterprise_ar0832_ri_data,
        },
        {
-               I2C_BOARD_INFO("ar0832_focuser", 0x36),
+               /* 0x31: alternative slave address */
+               I2C_BOARD_INFO("ar0832", 0x32),
+               .platform_data = &enterprise_ar0832_le_data,
        },
 };
 
@@ -312,4 +384,4 @@ int __init enterprise_sensors_init(void)
        enterprise_cam_init();
 
        return 0;
-}
+}
\ No newline at end of file