diff options
author | Jihoon Bang <jbang@nvidia.com> | 2011-06-24 10:12:47 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:47:40 -0800 |
commit | 408123bfd6d823c4b3e8367dc7fdb6a0d3592f32 (patch) | |
tree | f2daa6a3686075f1fd79aa706de13af91fcadc81 /arch/arm/mach-tegra/board-enterprise-sensors.c | |
parent | 1e66c11f6b40ab5ab6977d932fc502d9a791a638 (diff) |
arm: tegra: enterprise: support stereo sensor
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
Diffstat (limited to 'arch/arm/mach-tegra/board-enterprise-sensors.c')
-rw-r--r-- | arch/arm/mach-tegra/board-enterprise-sensors.c | 216 |
1 files changed, 144 insertions, 72 deletions
diff --git a/arch/arm/mach-tegra/board-enterprise-sensors.c b/arch/arm/mach-tegra/board-enterprise-sensors.c index 21f30efe0f97..9365733cd953 100644 --- a/arch/arm/mach-tegra/board-enterprise-sensors.c +++ b/arch/arm/mach-tegra/board-enterprise-sensors.c @@ -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 |