summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevesh Jhunjhunwala <deveshj@codeaurora.org>2016-06-29 17:48:12 -0700
committerKyle Yan <kyan@codeaurora.org>2016-07-08 11:52:36 -0700
commit154574cfc68dc28ca6a04b5bcf58c77adc67f73c (patch)
tree0b6c2de69de77e209db61f1fd492225baab24c6d
parent69feba98b2050d93ae0de0e359125fa5a31dd4de (diff)
leds: qpnp-flash-v2: Add operational current property
Add the qcom,current-ma property to specify the operational current for the flash led. Also limit the minimum flash current to 25mA since currents below this value cause unstable flash operation. CRs-Fixed: 1033071 Change-Id: Ia133b6c0cf0c21484f61631f04cba0d1112c9d48 Signed-off-by: Devesh Jhunjhunwala <deveshj@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt8
-rw-r--r--drivers/leds/leds-qpnp-flash-v2.c63
-rw-r--r--include/linux/leds-qpnp-flash-v2.h5
3 files changed, 58 insertions, 18 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
index ce2cec5582f3..f1a8c77c8387 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
@@ -36,6 +36,8 @@ serve as an overall switch.
10ms resolution. This is not required for switch node.
Optional properties inside child node:
+- qcom,current-ma : operational current intensity for LED in mA. Accepted values are a
+ positive integer in the range of 0 to qcom,max-current inclusive.
- qcom,ires-ua : Integer type to specify current resolution. Accepted values should be
12500, 10000, 7500, and 5000. Unit is uA.
- qcom,hdrm-voltage-mv : Integer type specifying headroom voltage. Values are from 125mV to 500mV
@@ -69,6 +71,7 @@ Example:
qcom,default-led-trigger =
"flash0_trigger";
qcom,id = <0>;
+ qcom,current-ma = <1000>;
qcom,duration-ms = <1280>;
qcom,ires-ua = <12500>;
qcom,hdrm-voltage-mv = <325>;
@@ -82,6 +85,7 @@ Example:
qcom,default-led-trigger =
"flash1_trigger";
qcom,id = <1>;
+ qcom,current-ma = <1000>;
qcom,duration-ms = <1280>;
qcom,ires-ua = <12500>;
qcom,hdrm-voltage-mv = <325>;
@@ -95,6 +99,7 @@ Example:
qcom,default-led-trigger =
"flash2_trigger";
qcom,id = <2>;
+ qcom,current-ma = <500>;
qcom,duration-ms = <1280>;
qcom,ires-ua = <12500>;
qcom,hdrm-voltage-mv = <325>;
@@ -111,6 +116,7 @@ Example:
qcom,default-led-trigger =
"torch0_trigger";
qcom,id = <0>;
+ qcom,current-ma = <300>;
qcom,ires-ua = <12500>;
qcom,hdrm-voltage-mv = <325>;
qcom,hdrm-vol-hi-lo-win-mv = <100>;
@@ -123,6 +129,7 @@ Example:
qcom,default-led-trigger =
"torch1_trigger";
qcom,id = <1>;
+ qcom,current-ma = <300>;
qcom,ires-ua = <12500>;
qcom,hdrm-voltage-mv = <325>;
qcom,hdrm-vol-hi-lo-win-mv = <100>;
@@ -135,6 +142,7 @@ Example:
qcom,default-led-trigger =
"torch2_trigger";
qcom,id = <2>;
+ qcom,current-ma = <300>;
qcom,ires-ua = <12500>;
qcom,hdrm-voltage-mv = <325>;
qcom,hdrm-vol-hi-lo-win-mv = <100>;
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index 89636557dec1..6f7ba0461800 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -38,8 +38,6 @@
#define FLASH_LED_MOD_CTRL_MASK 0x80
#define FLASH_LED_ISC_DELAY_MASK 0x03
-#define FLASH_LED_TYPE_FLASH 0
-#define FLASH_LED_TYPE_TORCH 1
#define FLASH_LED_HEADROOM_AUTO_MODE_ENABLED true
#define FLASH_LED_ISC_DELAY_SHIFT 6
#define FLASH_LED_ISC_DELAY_DEFAULT_US 3
@@ -60,6 +58,12 @@
#define FLASH_LED_MOD_ENABLE 0x80
#define FLASH_LED_DISABLE 0x00
#define FLASH_LED_SAFETY_TMR_DISABLED 0x13
+#define FLASH_LED_MIN_CURRENT_MA 25
+
+enum flash_led_type {
+ FLASH_LED_TYPE_FLASH,
+ FLASH_LED_TYPE_TORCH,
+};
/*
* Flash LED configuration read from device tree
@@ -141,13 +145,17 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value)
{
- int prgm_current_ma;
+ int prgm_current_ma = value;
- prgm_current_ma = value < 0 ? 0 : value;
- prgm_current_ma = value > fnode->cdev.max_brightness ?
- fnode->cdev.max_brightness : value;
+ if (value <= 0)
+ prgm_current_ma = 0;
+ else if (value < FLASH_LED_MIN_CURRENT_MA)
+ prgm_current_ma = FLASH_LED_MIN_CURRENT_MA;
+
+ prgm_current_ma = min(prgm_current_ma, fnode->max_current);
+ fnode->current_ma = prgm_current_ma;
fnode->cdev.brightness = prgm_current_ma;
- fnode->brightness = prgm_current_ma * 1000 / fnode->ires_ua + 1;
+ fnode->current_reg_val = prgm_current_ma * 1000 / fnode->ires_ua + 1;
fnode->led_on = prgm_current_ma != 0;
}
@@ -182,7 +190,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
rc = qpnp_flash_led_masked_write(led,
FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
- FLASH_LED_CURRENT_MASK, led->fnode[i].brightness);
+ FLASH_LED_CURRENT_MASK, led->fnode[i].current_reg_val);
if (rc)
return rc;
@@ -240,6 +248,7 @@ leds_turn_off:
FLASH_LED_CURRENT_MASK, 0);
if (rc)
return rc;
+
led->fnode[i].led_on = false;
if (led->fnode[i].pinctrl) {
@@ -305,14 +314,6 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
return rc;
}
- rc = of_property_read_u32(node, "qcom,max-current", &val);
- if (!rc) {
- fnode->cdev.max_brightness = val;
- } else {
- dev_err(&led->pdev->dev, "Unable to read max current\n");
- return rc;
- }
-
rc = of_property_read_string(node, "label", &temp_string);
if (!rc) {
if (!strcmp(temp_string, "flash"))
@@ -355,6 +356,36 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
return rc;
}
+ rc = of_property_read_u32(node, "qcom,max-current", &val);
+ if (!rc) {
+ if (val < FLASH_LED_MIN_CURRENT_MA)
+ val = FLASH_LED_MIN_CURRENT_MA;
+ fnode->max_current = val;
+ fnode->cdev.max_brightness = val;
+ } else {
+ dev_err(&led->pdev->dev,
+ "Unable to read max current, rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,current-ma", &val);
+ if (!rc) {
+ if (val < FLASH_LED_MIN_CURRENT_MA ||
+ val > fnode->max_current)
+ dev_warn(&led->pdev->dev,
+ "Invalid operational current specified, capping it\n");
+ if (val < FLASH_LED_MIN_CURRENT_MA)
+ val = FLASH_LED_MIN_CURRENT_MA;
+ if (val > fnode->max_current)
+ val = fnode->max_current;
+ fnode->current_ma = val;
+ fnode->cdev.brightness = val;
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev,
+ "Unable to read operational current, rc=%d\n", rc);
+ return rc;
+ }
+
fnode->duration = FLASH_LED_SAFETY_TMR_DISABLED;
rc = of_property_read_u32(node, "qcom,duration-ms", &val);
if (!rc) {
diff --git a/include/linux/leds-qpnp-flash-v2.h b/include/linux/leds-qpnp-flash-v2.h
index 353466f6c108..ae36a163ed21 100644
--- a/include/linux/leds-qpnp-flash-v2.h
+++ b/include/linux/leds-qpnp-flash-v2.h
@@ -26,13 +26,14 @@ struct flash_node_data {
struct pinctrl_state *gpio_state_active;
struct pinctrl_state *gpio_state_suspend;
int ires_ua;
- u16 prgm_current;
+ int max_current;
+ int current_ma;
u8 duration;
u8 id;
u8 type;
u8 ires;
u8 hdrm_val;
- u8 brightness;
+ u8 current_reg_val;
bool led_on;
};