diff options
author | Charlie Huang <chahuang@nvidia.com> | 2012-10-08 18:12:30 -0700 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-10-29 15:12:36 -0700 |
commit | 359d88c8606bf2aba16f7ce5f73fe259296d41c5 (patch) | |
tree | 90cf99ff730e3d4b5a463b6399d75c7d02a1b087 /arch/arm/mach-tegra/board-dalmore-sensors.c | |
parent | 123901e38b650c6c1f40ad4046b8c6eac63c1c31 (diff) |
ARM: tegra: pluto/dalmore: power sequence updates
use pinmux enable/disable ALT funtion to enable/disable MCLK/PBB0 sensor
mclk output.
modify imx091/imx132/ov9772 power on/off sequences according to their specs.
enable the AF regulator whenever a sensor is on (rear/front) as a workaround,
as this is required by the focuser ad5816 in the rear sensor module.
put gpio initialization into lateinit stage.
update the both dalmore/pluto board power files to adapt with the
sensor/focuser/flash kernel drivers.
bug 1060778
bug 1059684
bug 1054873
Change-Id: If67c1ad1d4ff15e04446f6d93dc75d07cda97052
Signed-off-by: Charlie Huang <chahuang@nvidia.com>
Reviewed-on: http://git-master/r/147648
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/board-dalmore-sensors.c')
-rw-r--r-- | arch/arm/mach-tegra/board-dalmore-sensors.c | 316 |
1 files changed, 169 insertions, 147 deletions
diff --git a/arch/arm/mach-tegra/board-dalmore-sensors.c b/arch/arm/mach-tegra/board-dalmore-sensors.c index f7fa7aeb02f2..6257c4e7c955 100644 --- a/arch/arm/mach-tegra/board-dalmore-sensors.c +++ b/arch/arm/mach-tegra/board-dalmore-sensors.c @@ -37,9 +37,12 @@ #include <linux/nct1008.h> #include <mach/edp.h> #include <mach/gpio-tegra.h> +#include <mach/pinmux-t11.h> +#include <mach/pinmux.h> #include <media/imx091.h> #include <media/ov9772.h> #include <media/as364x.h> +#include <media/ad5816.h> #include <generated/mach-types.h> #include "gpio-names.h" @@ -51,17 +54,6 @@ static struct board_info board_info; -static char *dalmore_cam_reg_name[] = { - "vdd_sensor_2v85", /* 2.85V */ - "avddio_usb", /* VDDIO USB CAM */ - "dvdd_cam", /* DVDD CAM */ - "vddio_cam", /* Tegra CAM_I2C, CAM_MCLK, VDD 1.8V */ - "avdd_cam1", /* Analog VDD 2.7V */ - "avdd_cam2", /* Analog VDD 2.7V */ -}; - -static struct regulator *dalmore_cam_reg[ARRAY_SIZE(dalmore_cam_reg_name)]; - static struct balanced_throttle tj_throttle = { .throt_tab_size = 10, .throt_tab = { @@ -106,59 +98,113 @@ static struct i2c_board_info dalmore_i2c4_nct1008_board_info[] = { } }; +#define VI_PINMUX(_pingroup, _mux, _pupd, _tri, _io, _lock, _ioreset) \ + { \ + .pingroup = TEGRA_PINGROUP_##_pingroup, \ + .func = TEGRA_MUX_##_mux, \ + .pupd = TEGRA_PUPD_##_pupd, \ + .tristate = TEGRA_TRI_##_tri, \ + .io = TEGRA_PIN_##_io, \ + .lock = TEGRA_PIN_LOCK_##_lock, \ + .od = TEGRA_PIN_OD_DEFAULT, \ + .ioreset = TEGRA_PIN_IO_RESET_##_ioreset \ + } + +static struct tegra_pingroup_config mclk_disable = + VI_PINMUX(CAM_MCLK, VI, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT); + +static struct tegra_pingroup_config mclk_enable = + VI_PINMUX(CAM_MCLK, VI_ALT3, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT); + +static struct tegra_pingroup_config pbb0_disable = + VI_PINMUX(GPIO_PBB0, VI, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT); + +static struct tegra_pingroup_config pbb0_enable = + VI_PINMUX(GPIO_PBB0, VI_ALT3, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT); + +/* + * As a workaround, dalmore_vcmvdd need to be allocated to activate the + * sensor devices. This is due to the focuser device(AD5816) will hook up + * the i2c bus if it is not powered up. +*/ static struct regulator *dalmore_vcmvdd; -static int dalmore_imx091_power_on(struct device *dev) +static int dalmore_get_vcmvdd(void) { - int i; - for (i = 0; i < ARRAY_SIZE(dalmore_cam_reg_name); i++) { - if (!dalmore_cam_reg[i]) { - dalmore_cam_reg[i] = regulator_get(dev, - dalmore_cam_reg_name[i]); - if (WARN_ON(IS_ERR(dalmore_cam_reg[i]))) { - pr_err("%s: didn't get regulator #%d: %ld\n", - __func__, i, PTR_ERR(dalmore_cam_reg[i])); - goto reg_alloc_fail; - } + if (!dalmore_vcmvdd) { + dalmore_vcmvdd = regulator_get(NULL, "vdd_af_cam1"); + if (unlikely(WARN_ON(IS_ERR(dalmore_vcmvdd)))) { + pr_err("%s: can't get regulator vcmvdd: %ld\n", + __func__, PTR_ERR(dalmore_vcmvdd)); + dalmore_vcmvdd = NULL; + return -ENODEV; } - regulator_enable(dalmore_cam_reg[i]); } + return 0; +} - gpio_direction_output(CAM_RSTN, 0); - mdelay(10); - gpio_direction_output(CAM_AF_PWDN, 1); - gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); - gpio_direction_output(CAM1_POWER_DWN_GPIO, 1); - gpio_direction_output(CAM_RSTN, 1); +static int dalmore_imx091_power_on(struct imx091_power_rail *pw) +{ + int err; - return 0; + if (unlikely(!pw || !pw->avdd || !pw->iovdd)) + return -EFAULT; -reg_alloc_fail: + if (dalmore_get_vcmvdd()) + goto imx091_poweron_fail; - for (i = ARRAY_SIZE(dalmore_cam_reg_name) - 1; i >= 0; i--) { - if (dalmore_cam_reg[i]) { - regulator_put(dalmore_cam_reg[i]); - dalmore_cam_reg[i] = NULL; - } - } + gpio_set_value(CAM1_POWER_DWN_GPIO, 0); + usleep_range(10, 20); + err = regulator_enable(pw->avdd); + if (err) + goto imx091_avdd_fail; + + err = regulator_enable(pw->iovdd); + if (err) + goto imx091_iovdd_fail; + + usleep_range(1, 2); + gpio_set_value(CAM1_POWER_DWN_GPIO, 1); + + err = regulator_enable(dalmore_vcmvdd); + if (unlikely(err)) + goto imx091_vcmvdd_fail; + + tegra_pinmux_config_table(&mclk_enable, 1); + usleep_range(300, 310); + + return 1; + +imx091_vcmvdd_fail: + regulator_disable(pw->iovdd); + +imx091_iovdd_fail: + regulator_disable(pw->avdd); + +imx091_avdd_fail: + gpio_set_value(CAM1_POWER_DWN_GPIO, 0); + +imx091_poweron_fail: + pr_err("%s FAILED\n", __func__); return -ENODEV; } -static int dalmore_imx091_power_off(struct device *dev) +static int dalmore_imx091_power_off(struct imx091_power_rail *pw) { - int i; - gpio_direction_output(CAM1_POWER_DWN_GPIO, 0); - - for (i = ARRAY_SIZE(dalmore_cam_reg_name) - 1; i >= 0; i--) { - if (dalmore_cam_reg[i]) { - regulator_disable(dalmore_cam_reg[i]); - regulator_put(dalmore_cam_reg[i]); - dalmore_cam_reg[i] = NULL; - } - } + if (unlikely(!pw || !dalmore_vcmvdd || !pw->avdd || !pw->iovdd)) + return -EFAULT; - return 0; + usleep_range(1, 2); + tegra_pinmux_config_table(&mclk_disable, 1); + gpio_set_value(CAM1_POWER_DWN_GPIO, 0); + usleep_range(1, 2); + + regulator_disable(dalmore_vcmvdd); + regulator_disable(pw->iovdd); + regulator_disable(pw->avdd); + + return 1; } struct imx091_platform_data dalmore_imx091_data = { @@ -166,62 +212,77 @@ struct imx091_platform_data dalmore_imx091_data = { .power_off = dalmore_imx091_power_off, }; -static int dalmore_ov9772_power_on(struct device *dev) +static int dalmore_ov9772_power_on(struct ov9772_power_rail *pw) { - int i; - for (i = 0; i < ARRAY_SIZE(dalmore_cam_reg_name); i++) { - if (!dalmore_cam_reg[i]) { - dalmore_cam_reg[i] = regulator_get(dev, - dalmore_cam_reg_name[i]); - if (WARN_ON(IS_ERR(dalmore_cam_reg[i]))) { - pr_err("%s: didn't get regulator #%d: %ld\n", - __func__, i, PTR_ERR(dalmore_cam_reg[i])); - goto reg_alloc_fail; - } - } - regulator_enable(dalmore_cam_reg[i]); - } + int err; - gpio_direction_output(CAM_RSTN, 0); - mdelay(10); - gpio_direction_output(CAM_AF_PWDN, 1); - gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); - gpio_direction_output(CAM1_POWER_DWN_GPIO, 1); - gpio_direction_output(CAM_RSTN, 1); + if (unlikely(!pw || !pw->avdd || !pw->dovdd)) + return -EFAULT; - return 0; + if (dalmore_get_vcmvdd()) + goto ov9772_get_vcmvdd_fail; -reg_alloc_fail: + gpio_set_value(CAM2_POWER_DWN_GPIO, 0); + gpio_set_value(CAM_RSTN, 0); - for (i = ARRAY_SIZE(dalmore_cam_reg_name) - 1; i >= 0; i--) { - if (dalmore_cam_reg[i]) { - regulator_put(dalmore_cam_reg[i]); - dalmore_cam_reg[i] = NULL; - } - } + err = regulator_enable(pw->avdd); + if (unlikely(err)) + goto ov9772_avdd_fail; + + err = regulator_enable(pw->dovdd); + if (unlikely(err)) + goto ov9772_dovdd_fail; + + gpio_set_value(CAM_RSTN, 1); + gpio_set_value(CAM2_POWER_DWN_GPIO, 1); + err = regulator_enable(dalmore_vcmvdd); + if (unlikely(err)) + goto ov9772_vcmvdd_fail; + + tegra_pinmux_config_table(&pbb0_enable, 1); + usleep_range(340, 380); + + /* return 1 to skip the in-driver power_on sequence */ + return 1; + +ov9772_vcmvdd_fail: + regulator_disable(pw->dovdd); + +ov9772_dovdd_fail: + regulator_disable(pw->avdd); + +ov9772_avdd_fail: + gpio_set_value(CAM_RSTN, 0); + gpio_set_value(CAM2_POWER_DWN_GPIO, 0); + +ov9772_get_vcmvdd_fail: + pr_err("%s FAILED\n", __func__); return -ENODEV; } -static int dalmore_ov9772_power_off(struct device *dev) +static int dalmore_ov9772_power_off(struct ov9772_power_rail *pw) { - int i; - gpio_direction_output(CAM1_POWER_DWN_GPIO, 0); - - for (i = ARRAY_SIZE(dalmore_cam_reg_name) - 1; i >= 0; i--) { - if (dalmore_cam_reg[i]) { - regulator_disable(dalmore_cam_reg[i]); - regulator_put(dalmore_cam_reg[i]); - dalmore_cam_reg[i] = NULL; - } - } + if (unlikely(!pw || !dalmore_vcmvdd || !pw->avdd || !pw->dovdd)) + return -EFAULT; - return 0; + usleep_range(21, 25); + tegra_pinmux_config_table(&pbb0_disable, 1); + + gpio_set_value(CAM2_POWER_DWN_GPIO, 0); + gpio_set_value(CAM_RSTN, 0); + + regulator_disable(dalmore_vcmvdd); + regulator_disable(pw->dovdd); + regulator_disable(pw->avdd); + + /* return 1 to skip the in-driver power_off sequence */ + return 1; } static struct nvc_gpio_pdata ov9772_gpio_pdata[] = { - { OV9772_GPIO_TYPE_SHTDN, TEGRA_GPIO_PBB5, true, 0, }, - { OV9772_GPIO_TYPE_PWRDN, TEGRA_GPIO_PBB3, true, 0, }, + { OV9772_GPIO_TYPE_SHTDN, CAM2_POWER_DWN_GPIO, true, 0, }, + { OV9772_GPIO_TYPE_PWRDN, CAM_RSTN, true, 0, }, }; static struct ov9772_platform_data dalmore_ov9772_pdata = { @@ -235,15 +296,10 @@ static struct ov9772_platform_data dalmore_ov9772_pdata = { static int dalmore_as3648_power_on(struct as364x_power_rail *pw) { - if (!dalmore_vcmvdd) { - dalmore_vcmvdd = regulator_get(NULL, "vdd_af_cam1"); - if (unlikely(WARN_ON(IS_ERR(dalmore_vcmvdd)))) { - pr_err("%s: can't get regulator vdd_af_cam1: %ld\n", - __func__, PTR_ERR(dalmore_vcmvdd)); - dalmore_vcmvdd = NULL; - return -ENODEV; - } - } + int err = dalmore_get_vcmvdd(); + + if (err) + return err; return regulator_enable(dalmore_vcmvdd); } @@ -275,6 +331,13 @@ static struct as364x_platform_data dalmore_as3648_pdata = { .power_off_callback = dalmore_as3648_power_off, }; +static struct ad5816_platform_data pluto_ad5816_pdata = { + .cfg = 0, + .num = 0, + .sync = 0, + .dev_name = "focuser", +}; + static struct i2c_board_info dalmore_i2c_board_info_e1625[] = { { I2C_BOARD_INFO("imx091", 0x36), @@ -288,63 +351,22 @@ static struct i2c_board_info dalmore_i2c_board_info_e1625[] = { I2C_BOARD_INFO("as3648", 0x30), .platform_data = &dalmore_as3648_pdata, }, -}; - -struct dalmore_cam_gpio { - int gpio; - const char *label; - int value; -}; - -#define TEGRA_CAMERA_GPIO(_gpio, _label, _value) \ - { \ - .gpio = _gpio, \ - .label = _label, \ - .value = _value, \ - } - -static struct dalmore_cam_gpio dalmore_cam_gpio_data[] = { - [0] = TEGRA_CAMERA_GPIO(CAM1_POWER_DWN_GPIO, "camera_power_en", 0), - [1] = TEGRA_CAMERA_GPIO(CAM2_POWER_DWN_GPIO, "camera2_power_en", 0), - [2] = TEGRA_CAMERA_GPIO(CAM_GPIO1, "camera_gpio1", 0), - [3] = TEGRA_CAMERA_GPIO(CAM_GPIO2, "camera_gpio2", 0), - [4] = TEGRA_CAMERA_GPIO(CAM_RSTN, "camera_rstn", 1), - [5] = TEGRA_CAMERA_GPIO(CAM_AF_PWDN, "camera_af_pwdn", 1), + { + I2C_BOARD_INFO("ad5816", 0x0E), + .platform_data = &pluto_ad5816_pdata, + }, }; static int dalmore_camera_init(void) { - - int ret; - int i; - - pr_debug("%s: ++\n", __func__); - - for (i = 0; i < ARRAY_SIZE(dalmore_cam_gpio_data); i++) { - ret = gpio_request(dalmore_cam_gpio_data[i].gpio, - dalmore_cam_gpio_data[i].label); - if (ret < 0) { - pr_err("%s: gpio_request failed for gpio #%d\n", - __func__, i); - goto fail_free_gpio; - } - gpio_direction_output(dalmore_cam_gpio_data[i].gpio, - dalmore_cam_gpio_data[i].value); - gpio_export(dalmore_cam_gpio_data[i].gpio, false); - } + tegra_pinmux_config_table(&mclk_disable, 1); + tegra_pinmux_config_table(&pbb0_disable, 1); i2c_register_board_info(2, dalmore_i2c_board_info_e1625, ARRAY_SIZE(dalmore_i2c_board_info_e1625)); return 0; -fail_free_gpio: - - while (i--) - gpio_free(dalmore_cam_gpio_data[i].gpio); - return ret; - } - /* MPU board file definition */ static struct mpu_platform_data mpu9150_gyro_data = { .int_config = 0x10, |