summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Huang <chahuang@nvidia.com>2011-06-29 10:40:07 -0700
committerJeremy Wyman <jwyman@nvidia.com>2011-06-30 17:17:32 -0700
commit8d4a42336fd1bc90f8e4543e82b7494181225eb9 (patch)
treead3dc52132e6b378cfe33056af728cfe8168840e
parentbcad42d1a0aadaebaaf56fbe4b480cad63fadb3a (diff)
ARM: tegra: enterprise: Add front camera
bug 829399 - add front camera ov9726 Change-Id: Iea0db38d3d2a55acf89e9e49a870ecfc4ad0e109 Reviewed-on: http://git-master/r/39003 Reviewed-by: Jihoon Bang <jbang@nvidia.com> Tested-by: Jihoon Bang <jbang@nvidia.com> Reviewed-by: Chonglei Huang <chahuang@nvidia.com> Reviewed-by: Jeremy Wyman <jwyman@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/board-enterprise-sensors.c180
-rw-r--r--arch/arm/mach-tegra/board-enterprise.h6
2 files changed, 177 insertions, 9 deletions
diff --git a/arch/arm/mach-tegra/board-enterprise-sensors.c b/arch/arm/mach-tegra/board-enterprise-sensors.c
index bc6c146c03c0..cb100534987b 100644
--- a/arch/arm/mach-tegra/board-enterprise-sensors.c
+++ b/arch/arm/mach-tegra/board-enterprise-sensors.c
@@ -28,6 +28,7 @@
#include <mach/gpio.h>
#include <media/ar0832_main.h>
+#include <media/ov9726.h>
#include "cpu-tegra.h"
#include "gpio-names.h"
#include "board-enterprise.h"
@@ -153,14 +154,106 @@ static void enterprise_isl_init(void)
ARRAY_SIZE(enterprise_i2c0_isl_board_info));
}
+typedef enum {
+ CAM_REAR_LEFT,
+ CAM_REAR_RIGHT,
+ CAM_FRONT,
+ NUM_OF_CAM
+} CAMERA_INDEX;
+
+struct ent_camera_regulators {
+ struct regulator *cam_reg;
+ struct regulator *csi_reg;
+ bool cam_pwr_state[NUM_OF_CAM];
+};
-static struct regulator *cam_reg;
-static struct regulator *csi_reg;
+static struct ent_camera_regulators ent_cam_pwr;
-static int enterprise_ar0832_power_on(void)
+static int enterprise_cam_pwr(CAMERA_INDEX cam, bool pwr_on)
{
int ret = 0;
+ bool *pwr_ptr = ent_cam_pwr.cam_pwr_state;
+
+ /*
+ * SW must turn on 1.8V first then 2.8V
+ * SW must turn off 2.8V first then 1.8V
+ */
+ if (pwr_on) {
+ if (!pwr_ptr[CAM_REAR_LEFT] &&
+ !pwr_ptr[CAM_REAR_RIGHT] &&
+ !pwr_ptr[CAM_REAR_RIGHT]) {
+ if (ent_cam_pwr.csi_reg == NULL) {
+ ent_cam_pwr.csi_reg = regulator_get(NULL, "avdd_dsi_csi");
+ if (IS_ERR_OR_NULL(ent_cam_pwr.csi_reg)) {
+ pr_err("%s: get csi pwr err\n", __func__);
+ ret = PTR_ERR(ent_cam_pwr.csi_reg);
+ goto enterprise_cam_pwr_fail;
+ }
+ }
+
+ ret = regulator_enable(ent_cam_pwr.csi_reg);
+ if (ret) {
+ pr_err("%s: enable csi pwr err\n", __func__);
+ goto enterprise_cam_pwr_fail;
+ }
+
+ if (ent_cam_pwr.cam_reg == NULL) {
+ ent_cam_pwr.cam_reg = regulator_get(NULL, "vddio_cam");
+ if (IS_ERR_OR_NULL(ent_cam_pwr.cam_reg)) {
+ pr_err("%s: get cam pwr err\n", __func__);
+ ret = PTR_ERR(ent_cam_pwr.cam_reg);
+ goto enterprise_cam_pwr_fail;
+ }
+ }
+
+ ret = regulator_enable(ent_cam_pwr.cam_reg);
+ if (ret) {
+ pr_err("%s: enable cam pwr err\n", __func__);
+ goto enterprise_cam_pwr_fail;
+ }
+ }
+
+ // turn on powers
+ gpio_set_value(CAM_LDO_1V8_EN_L_GPIO, 1);
+ enterprise_msleep(20);
+ gpio_set_value(CAM_LDO_2V8_EN_L_GPIO, 1);
+ pwr_ptr[cam] = true;
+ }
+ else {
+ pwr_ptr[cam] = false;
+ if (!pwr_ptr[CAM_REAR_LEFT] &&
+ !pwr_ptr[CAM_REAR_RIGHT] &&
+ !pwr_ptr[CAM_REAR_RIGHT]) {
+ if (ent_cam_pwr.cam_reg)
+ regulator_disable(ent_cam_pwr.cam_reg);
+
+ if (ent_cam_pwr.csi_reg)
+ regulator_disable(ent_cam_pwr.csi_reg);
+
+ // turn powers off
+ gpio_set_value(CAM_LDO_2V8_EN_L_GPIO, 0);
+ enterprise_msleep(20);
+ gpio_set_value(CAM_LDO_1V8_EN_L_GPIO, 0);
+ }
+ }
+ return 0;
+
+enterprise_cam_pwr_fail:
+ if (!IS_ERR_OR_NULL(ent_cam_pwr.cam_reg))
+ regulator_put(ent_cam_pwr.cam_reg);
+ ent_cam_pwr.cam_reg = NULL;
+
+ if (!IS_ERR_OR_NULL(ent_cam_pwr.csi_reg))
+ regulator_put(ent_cam_pwr.csi_reg);
+ ent_cam_pwr.csi_reg = NULL;
+ return ret;
+}
+
+static int enterprise_ar0832_power_on(void)
+{
+ int ret = 0;
+#if 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__);
@@ -190,10 +283,19 @@ static int enterprise_ar0832_power_on(void)
enterprise_msleep(20);
pr_info("%s: enable 2.8V...\n", __func__);
gpio_set_value(CAM_LDO_2V8_EN_L_GPIO, 1);
+#else
+ ret = enterprise_cam_pwr(CAM_REAR_RIGHT, true);
+ if (ret)
+ return ret;
+#endif
gpio_set_value(CAM1_PWDN_GPIO, 1);
enterprise_msleep(5);
gpio_set_value(CAM1_RST_L_GPIO, 1);
+
+ // switch mipi mux to rear camera
+ gpio_set_value(CAM_CSI_MUX_SEL_GPIO, CAM_CSI_MUX_SEL_REAR);
+
/*
It takes 2400 EXTCLK for ar0832 to be ready for I2c.
EXTCLK is 10 ~ 24MCK. 1 ms should be enough to cover
@@ -201,17 +303,19 @@ static int enterprise_ar0832_power_on(void)
*/
enterprise_msleep(1);
return 0;
-
+#if 0
fail_regulator_cam_reg:
regulator_put(cam_reg);
fail_regulator_csi_reg:
regulator_put(csi_reg);
return ret;
+#endif
}
static int enterprise_ar0832_power_off(void)
{
+#if 0
if (cam_reg) {
regulator_disable(cam_reg);
regulator_put(cam_reg);
@@ -224,6 +328,9 @@ static int enterprise_ar0832_power_off(void)
gpio_set_value(CAM_LDO_2V8_EN_L_GPIO, 0);
mdelay(20);
gpio_set_value(CAM_LDO_1V8_EN_L_GPIO, 0);
+#else
+ enterprise_cam_pwr(CAM_REAR_RIGHT, true);
+#endif
return 0;
}
@@ -261,7 +368,55 @@ struct ar0832_platform_data enterprise_ar0832_data = {
.power_off = enterprise_ar0832_power_off,
};
-static struct i2c_board_info ar0832_i2c2_boardinfo[] = {
+static int enterprise_ov9726_power_on(void)
+{
+ pr_info("ov9726 power on\n");
+
+ enterprise_cam_pwr(CAM_FRONT, true);
+ enterprise_msleep(1);
+ gpio_set_value(CAM3_PWDN_GPIO, CAM3_PWDN_FALSE); // turn on ov9726
+
+ enterprise_msleep(5);
+
+ gpio_set_value(CAM3_RST_L_GPIO, CAM3_RST_L_TRUE);
+ enterprise_msleep(5);
+ gpio_set_value(CAM3_RST_L_GPIO, CAM3_RST_L_FALSE);
+ enterprise_msleep(20);
+
+ // switch mipi mux to front camera
+ gpio_set_value(CAM_CSI_MUX_SEL_GPIO, CAM_CSI_MUX_SEL_FRONT);
+
+ pr_info("cs0n: %x %x %x\n",
+ gpio_get_value(CAM3_PWDN_GPIO),
+ gpio_get_value(CAM_LDO_1V8_EN_L_GPIO),
+ gpio_get_value(CAM_CSI_MUX_SEL_GPIO));
+
+ return 0;
+}
+
+static int enterprise_ov9726_power_off(void)
+{
+ pr_info("ov9726 power off\n");
+
+ gpio_set_value(CAM3_RST_L_GPIO, CAM3_RST_L_TRUE); // pull low the RST pin of ov9726
+ enterprise_msleep(1);
+ gpio_set_value(CAM3_PWDN_GPIO, CAM3_PWDN_TRUE); // turn off ov9726
+ enterprise_msleep(1);
+ enterprise_cam_pwr(CAM_FRONT, false);
+ pr_info("cs0n: %x %x %x\n",
+ gpio_get_value(CAM3_PWDN_GPIO),
+ gpio_get_value(CAM_LDO_1V8_EN_L_GPIO),
+ gpio_get_value(CAM_CSI_MUX_SEL_GPIO));
+
+ return 0;
+}
+
+struct ov9726_platform_data enterprise_ov9726_data = {
+ .power_on = enterprise_ov9726_power_on,
+ .power_off = enterprise_ov9726_power_off,
+};
+
+static struct i2c_board_info enterprise_i2c2_board_info[] = {
{
I2C_BOARD_INFO("ar0832", 0x36),
.platform_data = &enterprise_ar0832_data,
@@ -269,6 +424,10 @@ static struct i2c_board_info ar0832_i2c2_boardinfo[] = {
{
I2C_BOARD_INFO("ar0832_focuser", 0x36),
},
+ {
+ I2C_BOARD_INFO("ov9726", OV9726_I2C_ADDR >> 1 ),
+ .platform_data = &enterprise_ov9726_data,
+ },
};
static int enterprise_cam_init(void)
@@ -278,6 +437,8 @@ static int enterprise_cam_init(void)
pr_info("%s:++\n", __func__);
+ memset(&ent_cam_pwr, sizeof(struct ent_camera_regulators), 0);
+
for (i = 0; i < ARRAY_SIZE(enterprise_cam_gpio_data); i++) {
ret = gpio_request(enterprise_cam_gpio_data[i].gpio,
enterprise_cam_gpio_data[i].label);
@@ -292,8 +453,8 @@ static int enterprise_cam_init(void)
tegra_gpio_enable(enterprise_cam_gpio_data[i].gpio);
}
- i2c_register_board_info(2, ar0832_i2c2_boardinfo,
- ARRAY_SIZE(ar0832_i2c2_boardinfo));
+ i2c_register_board_info(2, enterprise_i2c2_board_info,
+ ARRAY_SIZE(enterprise_i2c2_board_info));
return 0;
@@ -306,10 +467,11 @@ fail_free_gpio:
int __init enterprise_sensors_init(void)
{
+ int ret;
enterprise_isl_init();
enterprise_nct1008_init();
enterprise_mpuirq_init();
- enterprise_cam_init();
+ ret = enterprise_cam_init();
- return 0;
+ return ret;
}
diff --git a/arch/arm/mach-tegra/board-enterprise.h b/arch/arm/mach-tegra/board-enterprise.h
index c7270e6ea6f2..2713790605a3 100644
--- a/arch/arm/mach-tegra/board-enterprise.h
+++ b/arch/arm/mach-tegra/board-enterprise.h
@@ -56,6 +56,8 @@ int enterprise_suspend_init(void);
/*****************Camera GPIOs ******************/
#define CAM_CSI_MUX_SEL_GPIO TEGRA_GPIO_PM3
+#define CAM_CSI_MUX_SEL_REAR 1
+#define CAM_CSI_MUX_SEL_FRONT 0
#define CAM_LDO_1V8_EN_L_GPIO TEGRA_GPIO_PF1
#define CAM_LDO_2V8_EN_L_GPIO TEGRA_GPIO_PM7
#define CAM1_RST_L_GPIO TEGRA_GPIO_PM5 /*REAR RIGHT*/
@@ -63,7 +65,11 @@ int enterprise_suspend_init(void);
#define CAM2_RST_L_GPIO TEGRA_GPIO_PF4 /*REAR LEFT*/
#define CAM2_PWDN_GPIO TEGRA_GPIO_PF2 /*REAR LEFT*/
#define CAM3_RST_L_GPIO TEGRA_GPIO_PM2 /*FRONT*/
+#define CAM3_RST_L_TRUE 0
+#define CAM3_RST_L_FALSE 1
#define CAM3_PWDN_GPIO TEGRA_GPIO_PN4 /*FRONT*/
+#define CAM3_PWDN_TRUE 1
+#define CAM3_PWDN_FALSE 0
#define CAM_FLASH_EN_GPIO TEGRA_GPIO_PBB3
#define CAM_FLASH_MAX_TORCH_AMP 7
#define CAM_FLASH_MAX_FLASH_AMP 7