arch: arm: ardbeg: ar0261 power regulators
Amey Asgaonkar [Wed, 26 Jun 2013 21:12:17 +0000 (14:12 -0700)]
Adds power regulators and power on/off routines
for ar0261 camera sensor.

Bug 1256440

Change-Id: I0ff6aab5a2975a76a1f4c7acb893c7dc0ed552d9
Signed-off-by: Amey Asgaonkar <aasgaonkar@nvidia.com>
Reviewed-on: http://git-master/r/242572
Reviewed-by: Amit Arora <amita@nvidia.com>
Tested-by: Amit Arora <amita@nvidia.com>

arch/arm/mach-tegra/board-ardbeg-power.c
arch/arm/mach-tegra/board-ardbeg-sensors.c
arch/arm/mach-tegra/board-ardbeg.h

index 65fc464..7e70fae 100644 (file)
@@ -76,6 +76,7 @@ static struct regulator_consumer_supply as3722_ldo1_supply[] = {
        REGULATOR_SUPPLY("vdd_cam1_1v8_cam", NULL),
        REGULATOR_SUPPLY("vdd_cam2_1v8_cam", NULL),
        REGULATOR_SUPPLY("vif", "2-0010"),
+       REGULATOR_SUPPLY("vif", "2-0036"),
        REGULATOR_SUPPLY("vdd_i2c", "2-000e"),
 
 };
@@ -102,11 +103,13 @@ static struct regulator_consumer_supply as3722_ldo4_supply[] = {
        REGULATOR_SUPPLY("avdd_cam2_cam", NULL),
        REGULATOR_SUPPLY("avdd_cam3_cam", NULL),
        REGULATOR_SUPPLY("vana", "2-0010"),
+       REGULATOR_SUPPLY("vana", "2-0036"),
 };
 
 static struct regulator_consumer_supply as3722_ldo5_supply[] = {
        REGULATOR_SUPPLY("vdd_1v2_cam", NULL),
        REGULATOR_SUPPLY("vdig", "2-0010"),
+       REGULATOR_SUPPLY("vdig", "2-0036"),
 };
 
 static struct regulator_consumer_supply as3722_ldo6_supply[] = {
@@ -606,12 +609,14 @@ static struct regulator_consumer_supply palmas_ldo3_supply[] = {
        REGULATOR_SUPPLY("vddio_cam_mb", NULL),
        REGULATOR_SUPPLY("vdd_cam_1v8_cam", NULL),
        REGULATOR_SUPPLY("vif", "2-0010"),
+       REGULATOR_SUPPLY("vif", "2-0036"),
        REGULATOR_SUPPLY("vdd_i2c", "2-000e"),
 };
 
 static struct regulator_consumer_supply palmas_ldo4_supply[] = {
        REGULATOR_SUPPLY("vdd_1v2_cam", NULL),
        REGULATOR_SUPPLY("vdig", "2-0010"),
+       REGULATOR_SUPPLY("vdig", "2-0036"),
 };
 
 static struct regulator_consumer_supply palmas_ldo5_supply[] = {
@@ -625,6 +630,7 @@ static struct regulator_consumer_supply palmas_ldo6_supply[] = {
 
 static struct regulator_consumer_supply palmas_ldo7_supply[] = {
        REGULATOR_SUPPLY("avdd_cam2_cam", NULL),
+       REGULATOR_SUPPLY("vana", "2-0036"),
 };
 
 static struct regulator_consumer_supply palmas_ldo8_supply[] = {
index 4ad633c..f3ea8dd 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/mpu.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <media/ar0261.h>
 
 #include "board-ardbeg.h"
 
@@ -98,12 +101,129 @@ static void mpuirq_init(void)
                ARRAY_SIZE(inv_mpu9250_i2c0_board_info));
 }
 
+static struct regulator *ardbeg_vcmvdd;
+
+static int ardbeg_get_extra_regulators(void)
+{
+       if (!ardbeg_vcmvdd) {
+               ardbeg_vcmvdd = regulator_get(NULL, "avdd_af1_cam");
+               if (WARN_ON(IS_ERR(ardbeg_vcmvdd))) {
+                       pr_err("%s: can't get regulator avdd_af1_cam: %ld\n",
+                                       __func__, PTR_ERR(ardbeg_vcmvdd));
+                       regulator_put(ardbeg_vcmvdd);
+                       ardbeg_vcmvdd = NULL;
+                       return -ENODEV;
+               }
+       }
+
+       return 0;
+}
+
+
+static int ardbeg_ar0261_power_on(struct ar0261_power_rail *pw)
+{
+       int err;
+
+       if (unlikely(WARN_ON(!pw || !pw->avdd || !pw->iovdd || !pw->dvdd)))
+               return -EFAULT;
+
+       if (ardbeg_get_extra_regulators())
+               goto ardbeg_ar0261_poweron_fail;
+
+       gpio_set_value(CAM_RSTN, 0);
+       gpio_set_value(CAM_AF_PWDN, 1);
+
+
+       err = regulator_enable(ardbeg_vcmvdd);
+       if (unlikely(err))
+               goto ar0261_vcm_fail;
+
+       err = regulator_enable(pw->dvdd);
+       if (unlikely(err))
+               goto ar0261_dvdd_fail;
+
+       err = regulator_enable(pw->avdd);
+       if (unlikely(err))
+               goto ar0261_avdd_fail;
+
+       err = regulator_enable(pw->iovdd);
+       if (unlikely(err))
+               goto ar0261_iovdd_fail;
+
+       usleep_range(1, 2);
+       gpio_set_value(CAM2_PWDN, 1);
+
+       gpio_set_value(CAM_RSTN, 1);
+
+       return 0;
+ar0261_iovdd_fail:
+       regulator_disable(pw->dvdd);
+
+ar0261_dvdd_fail:
+       regulator_disable(pw->avdd);
+
+ar0261_avdd_fail:
+       regulator_disable(ardbeg_vcmvdd);
+
+ar0261_vcm_fail:
+       pr_err("%s vcmvdd failed.\n", __func__);
+       return -ENODEV;
+
+ardbeg_ar0261_poweron_fail:
+       pr_err("%s failed.\n", __func__);
+       return -ENODEV;
+}
+
+static int ardbeg_ar0261_power_off(struct ar0261_power_rail *pw)
+{
+       if (unlikely(WARN_ON(!pw || !pw->avdd || !pw->iovdd || !pw->dvdd ||
+                                       !ardbeg_vcmvdd)))
+               return -EFAULT;
+
+       gpio_set_value(CAM_RSTN, 0);
+
+       usleep_range(1, 2);
+
+       regulator_disable(pw->iovdd);
+       regulator_disable(pw->dvdd);
+       regulator_disable(pw->avdd);
+
+
+       regulator_disable(ardbeg_vcmvdd);
+
+       return 0;
+}
+
+struct ar0261_platform_data ardbeg_ar0261_data = {
+       .power_on = ardbeg_ar0261_power_on,
+       .power_off = ardbeg_ar0261_power_off,
+};
+
+static struct i2c_board_info ardbeg_i2c_board_info_e1823[] = {
+       {
+               I2C_BOARD_INFO("ar0261", 0x36),
+               .platform_data = &ardbeg_ar0261_data,
+       },
+};
+
+
+static int ardbeg_camera_init(void)
+{
+       pr_debug("%s: ++\n", __func__);
+
+
+       i2c_register_board_info(2, ardbeg_i2c_board_info_e1823,
+                       ARRAY_SIZE(ardbeg_i2c_board_info_e1823));
+       return 0;
+}
+
 int __init ardbeg_sensors_init(void)
 {
        mpuirq_init();
+       ardbeg_camera_init();
 /*
        i2c_register_board_info(0, ardbeg_i2c_board_info_cm32181,
-               ARRAY_SIZE(ardbeg_i2c_board_info_cm32181));
+                       ARRAY_SIZE(ardbeg_i2c_board_info_cm32181));
 */
        return 0;
 }
index a3e7916..949a08a 100644 (file)
@@ -67,6 +67,9 @@ int ardbeg_pmon_init(void);
 /* AS3720 IRQs */
 #define AS3722_IRQ_BASE         TEGRA_NR_IRQS
 
+#define CAM_RSTN TEGRA_GPIO_PBB3
+#define CAM2_PWDN TEGRA_GPIO_PBB6
+#define CAM_AF_PWDN TEGRA_GPIO_PBB7
 /* Baseband IDs */
 enum tegra_bb_type {
        TEGRA_BB_NEMO = 1,