msm: camera: enabled flash driver support with TPS61310
The tps61310 drives the LED flash in the target 8930.
The driver support for the same is enabled with sensor 3L1.
CRs-Fixed: 359982
Change-Id: I2c3027cbb7bc9db57e081840de9972e3ac802e88
Signed-off-by: Jeyaprakash Soundrapandian <jsound@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 36953ef..114b271 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -188,6 +188,7 @@
.flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
._fsrc.ext_driver_src.led_en = VFE_CAMIF_TIMER1_GPIO,
._fsrc.ext_driver_src.led_flash_en = VFE_CAMIF_TIMER2_GPIO,
+ ._fsrc.ext_driver_src.flash_id = MAM_CAMERA_EXT_LED_FLASH_SC628A,
};
static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index cc5b13c..c9d720c 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -198,12 +198,9 @@
#ifdef CONFIG_MSM_CAMERA_FLASH
static struct msm_camera_sensor_flash_src msm_flash_src = {
.flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
- ._fsrc.ext_driver_src.led_en = GPIO_CAM_GP_LED_EN1,
- ._fsrc.ext_driver_src.led_flash_en = GPIO_CAM_GP_LED_EN2,
-#if defined(CONFIG_I2C) && (defined(CONFIG_GPIO_SX150X) || \
- defined(CONFIG_GPIO_SX150X_MODULE))
- ._fsrc.ext_driver_src.expander_info = cam_expander_info,
-#endif
+ ._fsrc.ext_driver_src.led_en = VFE_CAMIF_TIMER1_GPIO,
+ ._fsrc.ext_driver_src.led_flash_en = VFE_CAMIF_TIMER2_GPIO,
+ ._fsrc.ext_driver_src.flash_id = MAM_CAMERA_EXT_LED_FLASH_TPS61310,
};
#endif
@@ -536,7 +533,8 @@
};
static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
- .flash_type = MSM_CAMERA_FLASH_NONE,
+ .flash_type = MSM_CAMERA_FLASH_LED,
+ .flash_src = &msm_flash_src
};
static struct msm_camera_csi_lane_params s5k3l1yx_csi_lane_params = {
@@ -585,6 +583,15 @@
struct msm_camera_sensor_info *s_info;
s_info = &msm_camera_sensor_s5k3l1yx_data;
s_info->sensor_platform_info->mount_angle = 0;
+ msm_flash_src._fsrc.ext_driver_src.led_en =
+ GPIO_CAM_GP_LED_EN1;
+ msm_flash_src._fsrc.ext_driver_src.led_flash_en =
+ GPIO_CAM_GP_LED_EN2;
+#if defined(CONFIG_I2C) && (defined(CONFIG_GPIO_SX150X) || \
+ defined(CONFIG_GPIO_SX150X_MODULE))
+ msm_flash_src._fsrc.ext_driver_src.expander_info =
+ cam_expander_info;
+#endif
}
platform_device_register(&msm_camera_server);
@@ -615,11 +622,9 @@
I2C_BOARD_INFO("s5k3l1yx", 0x20),
.platform_data = &msm_camera_sensor_s5k3l1yx_data,
},
-#ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
{
- I2C_BOARD_INFO("sc628a", 0x6E),
+ I2C_BOARD_INFO("tps61310", 0x66),
},
-#endif
};
struct msm_camera_board_info msm8930_camera_board_info = {
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 371bb53..ad9b03d 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -197,6 +197,7 @@
.flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
._fsrc.ext_driver_src.led_en = VFE_CAMIF_TIMER1_GPIO,
._fsrc.ext_driver_src.led_flash_en = VFE_CAMIF_TIMER2_GPIO,
+ ._fsrc.ext_driver_src.flash_id = MAM_CAMERA_EXT_LED_FLASH_SC628A,
};
#endif
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 56210d5..17ac3ac 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -125,9 +125,15 @@
const struct pmic8058_leds_platform_data *driver_channel;
};
+enum msm_camera_ext_led_flash_id {
+ MAM_CAMERA_EXT_LED_FLASH_SC628A,
+ MAM_CAMERA_EXT_LED_FLASH_TPS61310,
+};
+
struct msm_camera_sensor_flash_external {
uint32_t led_en;
uint32_t led_flash_en;
+ enum msm_camera_ext_led_flash_id flash_id;
struct msm_cam_expander_info *expander_info;
};
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index b602c37..ab4a6f2 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -177,6 +177,15 @@
supports spotlight and flash light modes with
differrent current levels.
+config MSM_CAMERA_FLASH_TPS61310
+ bool "Qualcomm MSM camera tps61310 flash support"
+ depends on MSM_CAMERA
+ default n
+ ---help---
+ Enable support for LED flash for msm camera.
+ It is a Texas Instruments multiple LED Flash
+ for camera flash and video light applications.
+
config IMX072
bool "Sensor imx072 (Sony 5M)"
default n
diff --git a/drivers/media/video/msm/flash.c b/drivers/media/video/msm/flash.c
index 0d17e13..ba86d8c 100644
--- a/drivers/media/video/msm/flash.c
+++ b/drivers/media/video/msm/flash.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -30,54 +30,54 @@
MSM_CAM_FLASH_ON,
};
-#if defined CONFIG_MSM_CAMERA_FLASH_SC628A
static struct i2c_client *sc628a_client;
-static const struct i2c_device_id sc628a_i2c_id[] = {
- {"sc628a", 0},
- { }
-};
-
-static int32_t sc628a_i2c_txdata(unsigned short saddr,
+static int32_t flash_i2c_txdata(struct i2c_client *client,
unsigned char *txdata, int length)
{
struct i2c_msg msg[] = {
{
- .addr = saddr,
+ .addr = client->addr >> 1,
.flags = 0,
.len = length,
.buf = txdata,
},
};
- if (i2c_transfer(sc628a_client->adapter, msg, 1) < 0) {
- CDBG("sc628a_i2c_txdata faild 0x%x\n", saddr);
+ if (i2c_transfer(client->adapter, msg, 1) < 0) {
+ CDBG("flash_i2c_txdata faild 0x%x\n", client->addr >> 1);
return -EIO;
}
return 0;
}
-static int32_t sc628a_i2c_write_b_flash(uint8_t waddr, uint8_t bdata)
+static int32_t flash_i2c_write_b(struct i2c_client *client,
+ uint8_t baddr, uint8_t bdata)
{
int32_t rc = -EFAULT;
unsigned char buf[2];
- if (!sc628a_client)
+ if (!client)
return -ENOTSUPP;
memset(buf, 0, sizeof(buf));
- buf[0] = waddr;
+ buf[0] = baddr;
buf[1] = bdata;
- rc = sc628a_i2c_txdata(sc628a_client->addr>>1, buf, 2);
+ rc = flash_i2c_txdata(client, buf, 2);
if (rc < 0) {
CDBG("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
- waddr, bdata);
+ baddr, bdata);
}
usleep_range(4000, 5000);
return rc;
}
+static const struct i2c_device_id sc628a_i2c_id[] = {
+ {"sc628a", 0},
+ { }
+};
+
static int sc628a_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -91,7 +91,7 @@
sc628a_client = client;
- CDBG("sc628a_probe successed! rc = %d\n", rc);
+ CDBG("sc628a_probe success rc = %d\n", rc);
return 0;
probe_failure:
@@ -107,7 +107,49 @@
.name = "sc628a",
},
};
-#endif
+
+static struct i2c_client *tps61310_client;
+
+static const struct i2c_device_id tps61310_i2c_id[] = {
+ {"tps61310", 0},
+ { }
+};
+
+static int tps61310_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ CDBG("%s enter\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("i2c_check_functionality failed\n");
+ goto probe_failure;
+ }
+
+ tps61310_client = client;
+
+ rc = flash_i2c_write_b(tps61310_client, 0x01, 0x00);
+ if (rc < 0) {
+ tps61310_client = NULL;
+ goto probe_failure;
+ }
+
+ CDBG("%s success! rc = %d\n", __func__, rc);
+ return 0;
+
+probe_failure:
+ pr_err("%s failed! rc = %d\n", __func__, rc);
+ return rc;
+}
+
+static struct i2c_driver tps61310_i2c_driver = {
+ .id_table = tps61310_i2c_id,
+ .probe = tps61310_i2c_probe,
+ .remove = __exit_p(tps61310_i2c_remove),
+ .driver = {
+ .name = "tps61310",
+ },
+};
static int config_flash_gpio_table(enum msm_cam_flash_stat stat,
struct msm_camera_sensor_strobe_flash_data *sfdata)
@@ -278,18 +320,34 @@
{
int rc = 0;
-#if defined CONFIG_MSM_CAMERA_FLASH_SC628A
switch (led_state) {
case MSM_CAMERA_LED_INIT:
- if (!sc628a_client) {
- rc = i2c_add_driver(&sc628a_i2c_driver);
- if (rc < 0 || sc628a_client == NULL) {
- rc = -ENOTSUPP;
- CDBG("I2C add driver failed");
- return rc;
+ if (external->flash_id == MAM_CAMERA_EXT_LED_FLASH_SC628A) {
+ if (!sc628a_client) {
+ rc = i2c_add_driver(&sc628a_i2c_driver);
+ if (rc < 0 || sc628a_client == NULL) {
+ pr_err("sc628a_i2c_driver add failed\n");
+ rc = -ENOTSUPP;
+ return rc;
+ }
}
+ } else if (external->flash_id ==
+ MAM_CAMERA_EXT_LED_FLASH_TPS61310) {
+ if (!tps61310_client) {
+ rc = i2c_add_driver(&tps61310_i2c_driver);
+ if (rc < 0 || tps61310_client == NULL) {
+ pr_err("tps61310_i2c_driver add failed\n");
+ rc = -ENOTSUPP;
+ return rc;
+ }
+ }
+ } else {
+ pr_err("Flash id not supported\n");
+ rc = -ENOTSUPP;
+ return rc;
}
+
#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
if (external->expander_info && !sx150x_client) {
struct i2c_adapter *adapter =
@@ -298,20 +356,37 @@
sx150x_client = i2c_new_device(adapter,
external->expander_info->board_info);
if (!sx150x_client || !adapter) {
+ pr_err("sx150x_client is not available\n");
rc = -ENOTSUPP;
- i2c_del_driver(&sc628a_i2c_driver);
- sc628a_client = NULL;
+ if (sc628a_client) {
+ i2c_del_driver(&sc628a_i2c_driver);
+ sc628a_client = NULL;
+ }
+ if (tps61310_client) {
+ i2c_del_driver(&tps61310_i2c_driver);
+ tps61310_client = NULL;
+ }
return rc;
}
+ i2c_put_adapter(adapter);
}
#endif
- rc = gpio_request(external->led_en, "sc628a");
+ if (sc628a_client)
+ rc = gpio_request(external->led_en, "sc628a");
+ if (tps61310_client)
+ rc = gpio_request(external->led_en, "tps61310");
+
if (!rc) {
gpio_direction_output(external->led_en, 0);
} else {
- goto err1;
+ goto error;
}
- rc = gpio_request(external->led_flash_en, "sc628a");
+
+ if (sc628a_client)
+ rc = gpio_request(external->led_flash_en, "sc628a");
+ if (tps61310_client)
+ rc = gpio_request(external->led_flash_en, "tps61310");
+
if (!rc) {
gpio_direction_output(external->led_flash_en, 0);
break;
@@ -319,19 +394,32 @@
gpio_set_value_cansleep(external->led_en, 0);
gpio_free(external->led_en);
-
-err1:
- i2c_del_driver(&sc628a_i2c_driver);
- sc628a_client = NULL;
-
+error:
+ pr_err("%s gpio request failed\n", __func__);
+ if (sc628a_client) {
+ i2c_del_driver(&sc628a_i2c_driver);
+ sc628a_client = NULL;
+ }
+ if (tps61310_client) {
+ i2c_del_driver(&tps61310_i2c_driver);
+ tps61310_client = NULL;
+ }
break;
case MSM_CAMERA_LED_RELEASE:
- if (sc628a_client) {
+ if (sc628a_client || tps61310_client) {
gpio_set_value_cansleep(external->led_en, 0);
gpio_free(external->led_en);
gpio_set_value_cansleep(external->led_flash_en, 0);
gpio_free(external->led_flash_en);
+ if (sc628a_client) {
+ i2c_del_driver(&sc628a_i2c_driver);
+ sc628a_client = NULL;
+ }
+ if (tps61310_client) {
+ i2c_del_driver(&tps61310_i2c_driver);
+ tps61310_client = NULL;
+ }
}
#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
if (external->expander_info && sx150x_client) {
@@ -342,37 +430,38 @@
break;
case MSM_CAMERA_LED_OFF:
- rc = sc628a_i2c_write_b_flash(0x02, 0x0);
- if (sc628a_client) {
- gpio_set_value_cansleep(external->led_en, 0);
- gpio_set_value_cansleep(external->led_flash_en, 0);
- }
+ if (sc628a_client)
+ rc = flash_i2c_write_b(sc628a_client, 0x02, 0x00);
+ if (tps61310_client)
+ rc = flash_i2c_write_b(tps61310_client, 0x01, 0x00);
+ gpio_set_value_cansleep(external->led_en, 0);
+ gpio_set_value_cansleep(external->led_flash_en, 0);
break;
case MSM_CAMERA_LED_LOW:
- if (sc628a_client) {
- gpio_set_value_cansleep(external->led_en, 1);
- gpio_set_value_cansleep(external->led_flash_en, 1);
- usleep_range(2000, 3000);
- }
- rc = sc628a_i2c_write_b_flash(0x02, 0x06);
+ gpio_set_value_cansleep(external->led_en, 1);
+ gpio_set_value_cansleep(external->led_flash_en, 1);
+ usleep_range(2000, 3000);
+ if (sc628a_client)
+ rc = flash_i2c_write_b(sc628a_client, 0x02, 0x06);
+ if (tps61310_client)
+ rc = flash_i2c_write_b(tps61310_client, 0x01, 0x86);
break;
case MSM_CAMERA_LED_HIGH:
- if (sc628a_client) {
- gpio_set_value_cansleep(external->led_en, 1);
- gpio_set_value_cansleep(external->led_flash_en, 1);
- usleep_range(2000, 3000);
- }
- rc = sc628a_i2c_write_b_flash(0x02, 0x49);
+ gpio_set_value_cansleep(external->led_en, 1);
+ gpio_set_value_cansleep(external->led_flash_en, 1);
+ usleep_range(2000, 3000);
+ if (sc628a_client)
+ rc = flash_i2c_write_b(sc628a_client, 0x02, 0x49);
+ if (tps61310_client)
+ rc = flash_i2c_write_b(tps61310_client, 0x01, 0x8B);
break;
default:
rc = -EFAULT;
break;
}
-#endif
-
return rc;
}