Skip to content

Commit

Permalink
msm: camera: add lm3643 flash driver
Browse files Browse the repository at this point in the history
Add flash driver support for lm3643.
Torch and rear camera flash.

Change-Id: I5dc3d6f19074b371d4416fe2cb0bc94f65c5aa26
Signed-off-by: chenglong1 <chenglong1@lenovo.com>
Reviewed-on: http://gerrit.mot.com/822801
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver <sltawvr@motorola.com>
Tested-by: Jira Key <jirakey@motorola.com>
Reviewed-by: Satya Prasad Kottisa <fvgm76@motorola.com>
Reviewed-by: Christopher Fries <cfries@motorola.com>
Submit-Approved: Jira Key <jirakey@motorola.com>
  • Loading branch information
chenglong1 authored and nickdoherty81 committed Dec 13, 2016
1 parent 375200f commit 21744fe
Show file tree
Hide file tree
Showing 3 changed files with 382 additions and 0 deletions.
48 changes: 48 additions & 0 deletions Documentation/devicetree/bindings/leds/leds-lm3643.txt
@@ -0,0 +1,48 @@
* TI LM3643 Flash Led driver

Required properties:
- cell-index : Should contain flash source index to diffentiate
between different flash devices. These indexes represent flash devices
for multiple flashes.
- 0, 1, 2, 3
- compatible : should be "ti,lm3643"
- gpios : contain phandle to gpio controller node and array of
#gpio-cells specifying specific gpio (controller specific)
- qcom,gpio-req-tbl-num : contain index to gpios specific to this flash
- qcom,gpio-req-tbl-flags : contain direction of gpios present in
qcom,gpio-req-tbl-num property (in the same order)
- qcom,gpio-req-tbl-label : contain name of gpios present in
qcom,gpio-req-tbl-num property (in the same order)
- qcom,gpio-flash-reset : contain index to gpio used by flash's "flash reset" pin.
- qcom,gpio-flash-en : contain index to gpio used by flash's "flash enable" pin.
- qcom,gpio-flash-now : contain index to gpio used by flash's "flash now" pin.
- label : contain unique flash name to differentiate from other flash
- shoule be "lm3643"
- qcom,flash-type : type of flash device should be:
- 1 for LED flash.
- qcom,cci-master : should contain i2c master id to be used for this flash.
- 0 -> MASTER 0
- 1 -> MASTER 1

Example:

led_flash0: ti,lm3643@c6 {
cell-index = <0>;
qcom,slave-id = <0xc6 0x0c 0x02>;
compatible = "ti,lm3643";
label = "lm3643";
qcom,flash-type = <1>;
qcom,gpio-no-mux = <0>;
gpios = <&msm_gpio 32 0>, /*FLASH_RST(HW_EN)*/
<&msm_gpio 114 0>, /*TORCH_EN*/
<&msm_gpio 31 0>; /*FLASH_NOW*/
qcom,gpio-flash-reset = <0>;
qcom,gpio-flash-en = <1>;
qcom,gpio-flash-now = <2>;
qcom,gpio-req-tbl-num = <0 1 2>;
qcom,gpio-req-tbl-flags = <0 0 0>;
qcom,gpio-req-tbl-label = "FLASH_RST",
"FLASH_EN",
"FLASH_NOW";
qcom,cci-master = <0>;
};
1 change: 1 addition & 0 deletions drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
Expand Up @@ -10,3 +10,4 @@ obj-$(CONFIG_MSMB_CAMERA) += sky81296.o
obj-$(CONFIG_MSMB_CAMERA) += msm_led_torch.o
obj-$(CONFIG_MSMB_CAMERA) += msm_flash.o
obj-$(CONFIG_MSMB_CAMERA) += lm3642.o
obj-$(CONFIG_MSMB_CAMERA) += lm3643.o
333 changes: 333 additions & 0 deletions drivers/media/platform/msm/camera_v2/sensor/flash/lm3643.c
@@ -0,0 +1,333 @@
/* Copyright (c) 2016, The Linux Foundation. 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
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/export.h>
#include "msm_led_flash.h"

/* Logging macro */
/*#define LM3643_DRIVER_DEBUG*/

#undef CDBG
#ifdef LM3643_DRIVER_DEBUG
#define CDBG(fmt, args...) pr_err(fmt, ##args)
#else
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#endif

#define FLASH_NAME "ti,lm3643"

#define LED_NUM_CONNECTED 2

#define LED_TORCH_CURRENT_REG 0x03
#define LED1_STROBE_CURRENT_REG 0x00
#define LED2_STROBE_CURRENT_REG 0x01

#define LED_MAX_STROBE_CURRENT 1500
#define LED_STROBE_CURRENT_250 0x00
#define LED_DEFAULT_STROBE_CURRENT 0x0A /* 750 mA */
#define LED_STROBE_EN_DEFAULT 0x22 /* both enabled */

#define LED_MAX_TORCH_CURRENT 250
#define LED_DEFAULT_TORCH_CURRENT 0x22 /* 75 mA each */
#define LED_TORCH_EN_DEFAULT 0x11 /* both enabled */

#define LED_MAX_TOTAL_STROBE_CURRENT 1500
#define LED_MAX_TOTAL_TORCH_CURRENT 179


static struct msm_led_flash_ctrl_t fctrl;
static struct i2c_driver lm3643_i2c_driver;

struct lm3643_current_to_reg {
uint16_t current_level;
uint16_t reg_value;
};

static struct msm_camera_i2c_reg_array lm3643_init_array[] = {
{0x01, 0xF3}, /*gpio enable & led on*/
{0x08, 0x0F}, /*set flash time-out duration to 400ms*/
};

static struct msm_camera_i2c_reg_array lm3643_off_array[] = {
{0x01, 0xF0},
};

static struct msm_camera_i2c_reg_array lm3643_release_array[] = {
{0x01, 0xF0},
};

static struct msm_camera_i2c_reg_array lm3643_low_array[] = {
{0x05, 0x3F}, /*LED1 torch current*/
{0x06, 0x3F}, /*LED2 torch current*/
{0x01, 0xDB},
};

static struct msm_camera_i2c_reg_array lm3643_high_array[] = {
{0x03, 0x3F}, /*LED1 flash current */
{0x04, 0x3F}, /*LED2 flash current*/
{0x01, 0xEF},
{0x08, 0x0F}, /*set flash time-out duration to 400ms*/
};

static void __exit msm_flash_lm3643_i2c_remove(void)
{
i2c_del_driver(&lm3643_i2c_driver);
return;
}

static const struct of_device_id lm3643_trigger_dt_match[] = {
{.compatible = "ti,lm3643", .data = &fctrl},
{}
};

MODULE_DEVICE_TABLE(of, lm3643_trigger_dt_match);

static const struct i2c_device_id flash_i2c_id[] = {
{"ti,lm3643", (kernel_ulong_t)&fctrl},
{ }
};

static const struct i2c_device_id lm3643_i2c_id[] = {
{FLASH_NAME, (kernel_ulong_t)&fctrl},
{ }
};

static int msm_flash_lm3643_led_low(struct msm_led_flash_ctrl_t *fctrl)
{
uint8_t led1_reg_val = 0x00;
uint8_t led2_reg_val = 0x00;

/* set defaults */
lm3643_low_array[0].reg_data = LED_DEFAULT_TORCH_CURRENT;
lm3643_low_array[1].reg_data = LED_TORCH_EN_DEFAULT;

if ((fctrl->torch_op_current[0] > LED_MAX_TOTAL_TORCH_CURRENT) ||
(fctrl->torch_op_current[1] > LED_MAX_TOTAL_TORCH_CURRENT) ||
(fctrl->torch_op_current[0] == 0 &&
fctrl->torch_op_current[1] == 0)) {
CDBG("%s:%d - use default current reg:0x%x\n",
__func__, __LINE__,
lm3643_low_array[0].reg_data);
} else {
led1_reg_val = (fctrl->torch_op_current[0] >= 1) ?
((fctrl->torch_op_current[0] * 1000 - 977) / 1400) : 0;
led2_reg_val = (fctrl->torch_op_current[1] >= 1) ?
((fctrl->torch_op_current[1] * 1000 - 977) / 1400) : 0;

CDBG("%s:%d - current level %d %d\n",
__func__, __LINE__,
fctrl->torch_op_current[0],
fctrl->torch_op_current[1]);

lm3643_low_array[0].reg_data = led1_reg_val;
lm3643_low_array[0].reg_data = led2_reg_val;

/* if current level is 0, then turn off LED */
if (fctrl->torch_op_current[1] == 0)
lm3643_low_array[2].reg_data &= 0xFD;
else
lm3643_low_array[2].reg_data |= 0x02;

if (fctrl->torch_op_current[0] == 0)
lm3643_low_array[2].reg_data &= 0xFE;
else
lm3643_low_array[2].reg_data |= 0x01;
}
return msm_flash_led_low(fctrl);
}

static int msm_flash_lm3643_led_high(struct msm_led_flash_ctrl_t *fctrl)
{
uint8_t led1_reg_val = 0x00;
uint8_t led2_reg_val = 0x00;

/* set defaults */
lm3643_high_array[0].reg_data = LED_DEFAULT_STROBE_CURRENT;
lm3643_high_array[1].reg_data = LED_DEFAULT_STROBE_CURRENT;

if ((fctrl->flash_op_current[0] > LED_MAX_TOTAL_STROBE_CURRENT) ||
(fctrl->flash_op_current[1] > LED_MAX_TOTAL_STROBE_CURRENT) ||
(fctrl->flash_op_current[0] == 0 &&
fctrl->flash_op_current[1] == 0)) {
CDBG("%s:%d - use default current reg:0x%x\n",
__func__, __LINE__,
lm3643_high_array[0].reg_data);
} else {
led1_reg_val = (fctrl->flash_op_current[0] >= 11) ?
((fctrl->flash_op_current[0] * 1000-10900) / 11725) : 0;
led2_reg_val = (fctrl->flash_op_current[1] >= 11) ?
((fctrl->flash_op_current[1] * 1000-10900) / 11725) : 0;

lm3643_high_array[0].reg_data = led1_reg_val;
lm3643_high_array[1].reg_data = led2_reg_val;

/* if current level is 0, then turn off LED */
if (fctrl->flash_op_current[1] == 0)
lm3643_high_array[2].reg_data &= 0xFD;
else
lm3643_high_array[2].reg_data |= 0x02;

if (fctrl->flash_op_current[0] == 0)
lm3643_high_array[2].reg_data &= 0xFE;
else
lm3643_high_array[2].reg_data |= 0x01;

CDBG("%s:%d - current level %d %d reg:0x%x 0x%x 0x%x 0x%x\n",
__func__, __LINE__,
fctrl->flash_op_current[0],
fctrl->flash_op_current[1],
lm3643_high_array[0].reg_data,
lm3643_high_array[1].reg_data,
lm3643_high_array[2].reg_data,
lm3643_high_array[3].reg_data);
}
return msm_flash_led_high(fctrl);
}

static int msm_flash_lm3643_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!id) {
pr_err("msm_flash_lm3643_i2c_probe: id is NULL");
id = lm3643_i2c_id;
}

return msm_flash_i2c_probe(client, id);
}

static struct i2c_driver lm3643_i2c_driver = {
.id_table = lm3643_i2c_id,
.probe = msm_flash_lm3643_i2c_probe,
.remove = __exit_p(msm_flash_lm3643_i2c_remove),
.driver = {
.name = FLASH_NAME,
.owner = THIS_MODULE,
.of_match_table = lm3643_trigger_dt_match,
},
};

static int msm_flash_lm3643_platform_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
match = of_match_device(lm3643_trigger_dt_match, &pdev->dev);
if (!match)
return -EFAULT;
return msm_flash_probe(pdev, match->data);
}

static struct platform_driver lm3643_platform_driver = {
.probe = msm_flash_lm3643_platform_probe,
.driver = {
.name = "ti,lm3643",
.owner = THIS_MODULE,
.of_match_table = lm3643_trigger_dt_match,
},
};

static int __init msm_flash_lm3643_init_module(void)
{
int32_t rc = 0;
rc = platform_driver_register(&lm3643_platform_driver);
if (!rc)
return rc;
pr_err("%s:%d rc %d\n", __func__, __LINE__, rc);
return i2c_add_driver(&lm3643_i2c_driver);
}

static void __exit msm_flash_lm3643_exit_module(void)
{
if (fctrl.pdev)
platform_driver_unregister(&lm3643_platform_driver);
else
i2c_del_driver(&lm3643_i2c_driver);
}

static struct msm_camera_i2c_client lm3643_i2c_client = {
.addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
};

static struct msm_camera_i2c_reg_setting lm3643_init_setting = {
.reg_setting = lm3643_init_array,
.size = ARRAY_SIZE(lm3643_init_array),
.addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
.data_type = MSM_CAMERA_I2C_BYTE_DATA,
.delay = 0,
};

static struct msm_camera_i2c_reg_setting lm3643_off_setting = {
.reg_setting = lm3643_off_array,
.size = ARRAY_SIZE(lm3643_off_array),
.addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
.data_type = MSM_CAMERA_I2C_BYTE_DATA,
.delay = 0,
};

static struct msm_camera_i2c_reg_setting lm3643_release_setting = {
.reg_setting = lm3643_release_array,
.size = ARRAY_SIZE(lm3643_release_array),
.addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
.data_type = MSM_CAMERA_I2C_BYTE_DATA,
.delay = 0,
};

static struct msm_camera_i2c_reg_setting lm3643_low_setting = {
.reg_setting = lm3643_low_array,
.size = ARRAY_SIZE(lm3643_low_array),
.addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
.data_type = MSM_CAMERA_I2C_BYTE_DATA,
.delay = 0,
};

static struct msm_camera_i2c_reg_setting lm3643_high_setting = {
.reg_setting = lm3643_high_array,
.size = ARRAY_SIZE(lm3643_high_array),
.addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
.data_type = MSM_CAMERA_I2C_BYTE_DATA,
.delay = 0,
};

static struct msm_led_flash_reg_t lm3643_regs = {
.init_setting = &lm3643_init_setting,
.off_setting = &lm3643_off_setting,
.low_setting = &lm3643_low_setting,
.high_setting = &lm3643_high_setting,
.release_setting = &lm3643_release_setting,
};

static struct msm_flash_fn_t lm3643_func_tbl = {
.flash_get_subdev_id = msm_led_i2c_trigger_get_subdev_id,
.flash_led_config = msm_led_i2c_trigger_config,
.flash_led_init = msm_flash_led_init,
.flash_led_release = msm_flash_led_release,
.flash_led_off = msm_flash_led_off,
.flash_led_low = msm_flash_lm3643_led_low,
.flash_led_high = msm_flash_lm3643_led_high,
};

static struct msm_led_flash_ctrl_t fctrl = {
.flash_i2c_client = &lm3643_i2c_client,
.reg_setting = &lm3643_regs,
.func_tbl = &lm3643_func_tbl,
.flash_num_sources = LED_NUM_CONNECTED,
.flash_max_current[0] = LED_MAX_STROBE_CURRENT,
.flash_max_current[1] = LED_MAX_STROBE_CURRENT,
.torch_num_sources = LED_NUM_CONNECTED,
.torch_max_current[0] = LED_MAX_TORCH_CURRENT,
.torch_max_current[1] = LED_MAX_TORCH_CURRENT,
};

/*subsys_initcall(msm_flash_i2c_add_driver);*/
module_init(msm_flash_lm3643_init_module);
module_exit(msm_flash_lm3643_exit_module);
MODULE_DESCRIPTION("lm3643 FLASH");
MODULE_LICENSE("GPL v2");

0 comments on commit 21744fe

Please sign in to comment.