diff mbox series

[v2] leds: flash: leds-qcom-flash: limit LED current based on thermal condition

Message ID 20240513-qcom_flash_thermal_derating-v2-1-e41a07d0eb83@quicinc.com
State New
Headers show
Series [v2] leds: flash: leds-qcom-flash: limit LED current based on thermal condition | expand

Commit Message

Fenglin Wu via B4 Relay May 13, 2024, 7:36 a.m. UTC
From: Fenglin Wu <quic_fenglinw@quicinc.com>

The flash module has status bits to indicate different thermal
conditions which are called as OTSTx. For each OTSTx status,
there is a recommended total flash current for all channels to
prevent the flash module entering into higher thermal level.
For example, the total flash current should be limited to 1000mA/500mA
respectively when the HW reaches the OTST1/OTST2 thermal level.

Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
---
Changes in v2:
- Update thermal threshold level 2 register definition for mvflash_4ch_regs.
    Mvflash_4ch module thermal threshold level 2 configuration register
    offset is 0x78, not succeeding from thermal threshold level 1 register 0x7a.
    Hence it is not appropriate to use REG_FIELD_ID to define thermal threshold
    register fileds like mvflash_3ch. Update to use REG_FIELD instead.

- Link to v1: https://lore.kernel.org/r/20240509-qcom_flash_thermal_derating-v1-1-1d5e68e5d71c@quicinc.com
---
 drivers/leds/flash/leds-qcom-flash.c | 156 ++++++++++++++++++++++++++++++++++-
 1 file changed, 155 insertions(+), 1 deletion(-)


---
base-commit: ca66b10a11da3c445c9c0ca1184f549bbe9061f2
change-id: 20240507-qcom_flash_thermal_derating-260b1f3c757c

Best regards,

Comments

Lee Jones May 31, 2024, 1:28 p.m. UTC | #1
On Mon, 13 May 2024, Fenglin Wu via B4 Relay wrote:

> From: Fenglin Wu <quic_fenglinw@quicinc.com>
> 
> The flash module has status bits to indicate different thermal
> conditions which are called as OTSTx. For each OTSTx status,
> there is a recommended total flash current for all channels to
> prevent the flash module entering into higher thermal level.
> For example, the total flash current should be limited to 1000mA/500mA
> respectively when the HW reaches the OTST1/OTST2 thermal level.
> 
> Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
> ---
> Changes in v2:
> - Update thermal threshold level 2 register definition for mvflash_4ch_regs.
>     Mvflash_4ch module thermal threshold level 2 configuration register
>     offset is 0x78, not succeeding from thermal threshold level 1 register 0x7a.
>     Hence it is not appropriate to use REG_FIELD_ID to define thermal threshold
>     register fileds like mvflash_3ch. Update to use REG_FIELD instead.
> 
> - Link to v1: https://lore.kernel.org/r/20240509-qcom_flash_thermal_derating-v1-1-1d5e68e5d71c@quicinc.com
> ---
>  drivers/leds/flash/leds-qcom-flash.c | 156 ++++++++++++++++++++++++++++++++++-
>  1 file changed, 155 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c
> index 7c99a3039171..d7c03c25941a 100644
> --- a/drivers/leds/flash/leds-qcom-flash.c
> +++ b/drivers/leds/flash/leds-qcom-flash.c
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: GPL-2.0-only
>  /*
> - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
>   */
>  
>  #include <linux/bitfield.h>
> @@ -14,6 +14,9 @@
>  #include <media/v4l2-flash-led-class.h>
>  
>  /* registers definitions */
> +#define FLASH_REVISION_REG		0x00
> +#define FLASH_4CH_REVISION_V0P1		0x01
> +
>  #define FLASH_TYPE_REG			0x04
>  #define FLASH_TYPE_VAL			0x18
>  
> @@ -73,6 +76,16 @@
>  
>  #define UA_PER_MA			1000
>  
> +/* thermal threshold constants */
> +#define OTST_3CH_MIN_VAL		3
> +#define OTST1_4CH_MIN_VAL		0
> +#define OTST1_4CH_V0P1_MIN_VAL		3
> +#define OTST2_4CH_MIN_VAL		0
> +
> +#define OTST1_MAX_CURRENT_MA		1000
> +#define OTST2_MAX_CURRENT_MA		500
> +#define OTST3_MAX_CURRENT_MA		200
> +
>  enum hw_type {
>  	QCOM_MVFLASH_3CH,
>  	QCOM_MVFLASH_4CH,
> @@ -98,6 +111,9 @@ enum {
>  	REG_IRESOLUTION,
>  	REG_CHAN_STROBE,
>  	REG_CHAN_EN,
> +	REG_THERM_THRSH1,
> +	REG_THERM_THRSH2,
> +	REG_THERM_THRSH3,
>  	REG_MAX_COUNT,
>  };
>  
> @@ -111,6 +127,9 @@ static struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {
>  	REG_FIELD(0x47, 0, 5),                  /* iresolution	*/
>  	REG_FIELD_ID(0x49, 0, 2, 3, 1),         /* chan_strobe	*/
>  	REG_FIELD(0x4c, 0, 2),                  /* chan_en	*/
> +	REG_FIELD(0x56, 0, 2),			/* therm_thrsh1 */
> +	REG_FIELD(0x57, 0, 2),			/* therm_thrsh2 */
> +	REG_FIELD(0x58, 0, 2),			/* therm_thrsh3 */
>  };
>  
>  static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
> @@ -123,6 +142,8 @@ static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
>  	REG_FIELD(0x49, 0, 3),			/* iresolution	*/
>  	REG_FIELD_ID(0x4a, 0, 6, 4, 1),		/* chan_strobe	*/
>  	REG_FIELD(0x4e, 0, 3),			/* chan_en	*/
> +	REG_FIELD(0x7a, 0, 2),			/* therm_thrsh1 */
> +	REG_FIELD(0x78, 0, 2),			/* therm_thrsh2 */
>  };
>  
>  struct qcom_flash_data {
> @@ -130,9 +151,11 @@ struct qcom_flash_data {
>  	struct regmap_field     *r_fields[REG_MAX_COUNT];
>  	struct mutex		lock;
>  	enum hw_type		hw_type;
> +	u32			total_ma;
>  	u8			leds_count;
>  	u8			max_channels;
>  	u8			chan_en_bits;
> +	u8			revision;
>  };
>  
>  struct qcom_flash_led {
> @@ -143,6 +166,7 @@ struct qcom_flash_led {
>  	u32				max_timeout_ms;
>  	u32				flash_current_ma;
>  	u32				flash_timeout_ms;
> +	u32				current_in_use_ma;
>  	u8				*chan_id;
>  	u8				chan_count;
>  	bool				enabled;
> @@ -172,6 +196,121 @@ static int set_flash_module_en(struct qcom_flash_led *led, bool en)
>  	return rc;
>  }
>  
> +static int update_allowed_flash_current(struct qcom_flash_led *led, u32 *current_ma, bool strobe)
> +{
> +	struct qcom_flash_data *flash_data = led->flash_data;
> +	u32 therm_ma, avail_ma, thrsh[3], min_thrsh, sts;
> +	int rc;
> +
> +	mutex_lock(&flash_data->lock);
> +	/*
> +	 * Put previously allocated current into allowed budget in either of these two cases:
> +	 * 1) LED is disabled;
> +	 * 2) LED is enabled repeatedly
> +	 */
> +	if (!strobe || (strobe && led->current_in_use_ma != 0)) {

Isn't the check for 'strobe' here redundant?

> +		if (flash_data->total_ma >= led->current_in_use_ma)
> +			flash_data->total_ma -= led->current_in_use_ma;
> +		else
> +			flash_data->total_ma = 0;
> +
> +		led->current_in_use_ma = 0;
> +		if (!strobe) {
> +			mutex_unlock(&flash_data->lock);
> +			return 0;

Pre-initialise 'rc = 0' during the declaration, then 'goto unlock' here.

> +		}
> +	}
> +
> +	/*
> +	 * Cache the default thermal threshold settings, and set them to the lowest levels before
> +	 * reading over-temp real time status. If over-temp has been triggered at the lowest
> +	 * threshold, it's very likely that it would be triggered at a higher (default) threshold
> +	 * when more flash current is requested. Prevent device from triggering over-temp condition
> +	 * by limiting the flash current for the new request.
> +	 */
> +	rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH1], &thrsh[0]);
> +	if (rc < 0)
> +		goto unlock;
> +
> +	rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH2], &thrsh[1]);
> +	if (rc < 0)
> +		goto unlock;
> +
> +	if (flash_data->hw_type == QCOM_MVFLASH_3CH) {
> +		rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH3], &thrsh[2]);
> +		if (rc < 0)
> +			goto unlock;
> +	}
> +
> +	min_thrsh = OTST_3CH_MIN_VAL;
> +	if (flash_data->hw_type == QCOM_MVFLASH_4CH)
> +		min_thrsh = (flash_data->revision == FLASH_4CH_REVISION_V0P1) ?
> +			OTST1_4CH_V0P1_MIN_VAL : OTST1_4CH_MIN_VAL;

Bunching up code decreases readability.

'\n'

> +	rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH1], min_thrsh);
> +	if (rc < 0)
> +		goto unlock;
> +
> +	if (flash_data->hw_type == QCOM_MVFLASH_4CH)
> +		min_thrsh = OTST2_4CH_MIN_VAL;

'\n'

> +	rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH2], min_thrsh);
> +	if (rc < 0)
> +		goto restore;

Maybe detail why you're jumping ahead here.

> +	if (flash_data->hw_type == QCOM_MVFLASH_3CH) {
> +		rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH3], min_thrsh);
> +		if (rc < 0)
> +			goto restore;
> +	}
> +
> +	/* read thermal level status to get corresponding derating flash current */

Sentences start with upper case chars.

> +	rc = regmap_field_read(flash_data->r_fields[REG_STATUS2], &sts);
> +	if (rc)
> +		goto restore;
> +
> +	therm_ma = FLASH_TOTAL_CURRENT_MAX_UA / 1000;
> +	if (flash_data->hw_type == QCOM_MVFLASH_3CH) {
> +		if (sts & FLASH_STS_3CH_OTST3)
> +			therm_ma = OTST3_MAX_CURRENT_MA;
> +		else if (sts & FLASH_STS_3CH_OTST2)
> +			therm_ma = OTST2_MAX_CURRENT_MA;
> +		else if (sts & FLASH_STS_3CH_OTST1)
> +			therm_ma = OTST1_MAX_CURRENT_MA;
> +	} else {
> +		if (sts & FLASH_STS_4CH_OTST2)
> +			therm_ma = OTST2_MAX_CURRENT_MA;
> +		else if (sts & FLASH_STS_4CH_OTST1)
> +			therm_ma = OTST1_MAX_CURRENT_MA;
> +	}
> +
> +	/* calculate the allowed flash current for the request */

As above and throughout.

> +	if (therm_ma <= flash_data->total_ma)
> +		avail_ma = 0;
> +	else
> +		avail_ma = therm_ma - flash_data->total_ma;

'\n'

> +	*current_ma = min_t(u32, *current_ma, avail_ma);
> +	led->current_in_use_ma = *current_ma;
> +	flash_data->total_ma += led->current_in_use_ma;
> +
> +	dev_dbg(led->flash.led_cdev.dev, "allowed flash current: %dmA, total current: %dmA\n",
> +					led->current_in_use_ma, flash_data->total_ma);


'\n'

> +restore:
> +	/* Restore to default thermal threshold settings */
> +	rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH1], thrsh[0]);
> +	if (rc < 0)
> +		goto unlock;
> +
> +	rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH2], thrsh[1]);
> +	if (rc < 0)
> +		goto unlock;
> +
> +	if (flash_data->hw_type == QCOM_MVFLASH_3CH)
> +		rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH3], thrsh[2]);
> +
> +unlock:
> +	mutex_unlock(&flash_data->lock);
> +	return rc;
> +}
> +
>  static int set_flash_current(struct qcom_flash_led *led, u32 current_ma, enum led_mode mode)
>  {
>  	struct qcom_flash_data *flash_data = led->flash_data;
> @@ -313,6 +452,10 @@ static int qcom_flash_strobe_set(struct led_classdev_flash *fled_cdev, bool stat
>  	if (rc)
>  		return rc;
>  
> +	rc = update_allowed_flash_current(led, &led->flash_current_ma, state);
> +	if (rc < 0)
> +		return rc;
> +
>  	rc = set_flash_current(led, led->flash_current_ma, FLASH_MODE);
>  	if (rc)
>  		return rc;
> @@ -429,6 +572,10 @@ static int qcom_flash_led_brightness_set(struct led_classdev *led_cdev,
>  	if (rc)
>  		return rc;
>  
> +	rc = update_allowed_flash_current(led, &current_ma, enable);
> +	if (rc < 0)
> +		return rc;
> +
>  	rc = set_flash_current(led, current_ma, TORCH_MODE);
>  	if (rc)
>  		return rc;
> @@ -703,6 +850,13 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
>  		flash_data->hw_type = QCOM_MVFLASH_4CH;
>  		flash_data->max_channels = 4;
>  		regs = mvflash_4ch_regs;

'\n'

> +		rc = regmap_read(regmap, reg_base + FLASH_REVISION_REG, &val);
> +		if (rc < 0) {
> +			dev_err(dev, "Read flash LED module revision failed, rc=%d\n", rc);

"Failed to read flash LED module revision"

> +			return rc;
> +		}
> +
> +		flash_data->revision = val;
>  	} else {
>  		dev_err(dev, "flash LED subtype %#x is not yet supported\n", val);
>  		return -ENODEV;
> 
> ---
> base-commit: ca66b10a11da3c445c9c0ca1184f549bbe9061f2
> change-id: 20240507-qcom_flash_thermal_derating-260b1f3c757c
> 
> Best regards,
> -- 
> Fenglin Wu <quic_fenglinw@quicinc.com>
diff mbox series

Patch

diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c
index 7c99a3039171..d7c03c25941a 100644
--- a/drivers/leds/flash/leds-qcom-flash.c
+++ b/drivers/leds/flash/leds-qcom-flash.c
@@ -1,6 +1,6 @@ 
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/bitfield.h>
@@ -14,6 +14,9 @@ 
 #include <media/v4l2-flash-led-class.h>
 
 /* registers definitions */
+#define FLASH_REVISION_REG		0x00
+#define FLASH_4CH_REVISION_V0P1		0x01
+
 #define FLASH_TYPE_REG			0x04
 #define FLASH_TYPE_VAL			0x18
 
@@ -73,6 +76,16 @@ 
 
 #define UA_PER_MA			1000
 
+/* thermal threshold constants */
+#define OTST_3CH_MIN_VAL		3
+#define OTST1_4CH_MIN_VAL		0
+#define OTST1_4CH_V0P1_MIN_VAL		3
+#define OTST2_4CH_MIN_VAL		0
+
+#define OTST1_MAX_CURRENT_MA		1000
+#define OTST2_MAX_CURRENT_MA		500
+#define OTST3_MAX_CURRENT_MA		200
+
 enum hw_type {
 	QCOM_MVFLASH_3CH,
 	QCOM_MVFLASH_4CH,
@@ -98,6 +111,9 @@  enum {
 	REG_IRESOLUTION,
 	REG_CHAN_STROBE,
 	REG_CHAN_EN,
+	REG_THERM_THRSH1,
+	REG_THERM_THRSH2,
+	REG_THERM_THRSH3,
 	REG_MAX_COUNT,
 };
 
@@ -111,6 +127,9 @@  static struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {
 	REG_FIELD(0x47, 0, 5),                  /* iresolution	*/
 	REG_FIELD_ID(0x49, 0, 2, 3, 1),         /* chan_strobe	*/
 	REG_FIELD(0x4c, 0, 2),                  /* chan_en	*/
+	REG_FIELD(0x56, 0, 2),			/* therm_thrsh1 */
+	REG_FIELD(0x57, 0, 2),			/* therm_thrsh2 */
+	REG_FIELD(0x58, 0, 2),			/* therm_thrsh3 */
 };
 
 static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
@@ -123,6 +142,8 @@  static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
 	REG_FIELD(0x49, 0, 3),			/* iresolution	*/
 	REG_FIELD_ID(0x4a, 0, 6, 4, 1),		/* chan_strobe	*/
 	REG_FIELD(0x4e, 0, 3),			/* chan_en	*/
+	REG_FIELD(0x7a, 0, 2),			/* therm_thrsh1 */
+	REG_FIELD(0x78, 0, 2),			/* therm_thrsh2 */
 };
 
 struct qcom_flash_data {
@@ -130,9 +151,11 @@  struct qcom_flash_data {
 	struct regmap_field     *r_fields[REG_MAX_COUNT];
 	struct mutex		lock;
 	enum hw_type		hw_type;
+	u32			total_ma;
 	u8			leds_count;
 	u8			max_channels;
 	u8			chan_en_bits;
+	u8			revision;
 };
 
 struct qcom_flash_led {
@@ -143,6 +166,7 @@  struct qcom_flash_led {
 	u32				max_timeout_ms;
 	u32				flash_current_ma;
 	u32				flash_timeout_ms;
+	u32				current_in_use_ma;
 	u8				*chan_id;
 	u8				chan_count;
 	bool				enabled;
@@ -172,6 +196,121 @@  static int set_flash_module_en(struct qcom_flash_led *led, bool en)
 	return rc;
 }
 
+static int update_allowed_flash_current(struct qcom_flash_led *led, u32 *current_ma, bool strobe)
+{
+	struct qcom_flash_data *flash_data = led->flash_data;
+	u32 therm_ma, avail_ma, thrsh[3], min_thrsh, sts;
+	int rc;
+
+	mutex_lock(&flash_data->lock);
+	/*
+	 * Put previously allocated current into allowed budget in either of these two cases:
+	 * 1) LED is disabled;
+	 * 2) LED is enabled repeatedly
+	 */
+	if (!strobe || (strobe && led->current_in_use_ma != 0)) {
+		if (flash_data->total_ma >= led->current_in_use_ma)
+			flash_data->total_ma -= led->current_in_use_ma;
+		else
+			flash_data->total_ma = 0;
+
+		led->current_in_use_ma = 0;
+		if (!strobe) {
+			mutex_unlock(&flash_data->lock);
+			return 0;
+		}
+	}
+
+	/*
+	 * Cache the default thermal threshold settings, and set them to the lowest levels before
+	 * reading over-temp real time status. If over-temp has been triggered at the lowest
+	 * threshold, it's very likely that it would be triggered at a higher (default) threshold
+	 * when more flash current is requested. Prevent device from triggering over-temp condition
+	 * by limiting the flash current for the new request.
+	 */
+	rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH1], &thrsh[0]);
+	if (rc < 0)
+		goto unlock;
+
+	rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH2], &thrsh[1]);
+	if (rc < 0)
+		goto unlock;
+
+	if (flash_data->hw_type == QCOM_MVFLASH_3CH) {
+		rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH3], &thrsh[2]);
+		if (rc < 0)
+			goto unlock;
+	}
+
+	min_thrsh = OTST_3CH_MIN_VAL;
+	if (flash_data->hw_type == QCOM_MVFLASH_4CH)
+		min_thrsh = (flash_data->revision == FLASH_4CH_REVISION_V0P1) ?
+			OTST1_4CH_V0P1_MIN_VAL : OTST1_4CH_MIN_VAL;
+	rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH1], min_thrsh);
+	if (rc < 0)
+		goto unlock;
+
+	if (flash_data->hw_type == QCOM_MVFLASH_4CH)
+		min_thrsh = OTST2_4CH_MIN_VAL;
+	rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH2], min_thrsh);
+	if (rc < 0)
+		goto restore;
+
+	if (flash_data->hw_type == QCOM_MVFLASH_3CH) {
+		rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH3], min_thrsh);
+		if (rc < 0)
+			goto restore;
+	}
+
+	/* read thermal level status to get corresponding derating flash current */
+	rc = regmap_field_read(flash_data->r_fields[REG_STATUS2], &sts);
+	if (rc)
+		goto restore;
+
+	therm_ma = FLASH_TOTAL_CURRENT_MAX_UA / 1000;
+	if (flash_data->hw_type == QCOM_MVFLASH_3CH) {
+		if (sts & FLASH_STS_3CH_OTST3)
+			therm_ma = OTST3_MAX_CURRENT_MA;
+		else if (sts & FLASH_STS_3CH_OTST2)
+			therm_ma = OTST2_MAX_CURRENT_MA;
+		else if (sts & FLASH_STS_3CH_OTST1)
+			therm_ma = OTST1_MAX_CURRENT_MA;
+	} else {
+		if (sts & FLASH_STS_4CH_OTST2)
+			therm_ma = OTST2_MAX_CURRENT_MA;
+		else if (sts & FLASH_STS_4CH_OTST1)
+			therm_ma = OTST1_MAX_CURRENT_MA;
+	}
+
+	/* calculate the allowed flash current for the request */
+	if (therm_ma <= flash_data->total_ma)
+		avail_ma = 0;
+	else
+		avail_ma = therm_ma - flash_data->total_ma;
+	*current_ma = min_t(u32, *current_ma, avail_ma);
+	led->current_in_use_ma = *current_ma;
+	flash_data->total_ma += led->current_in_use_ma;
+
+	dev_dbg(led->flash.led_cdev.dev, "allowed flash current: %dmA, total current: %dmA\n",
+					led->current_in_use_ma, flash_data->total_ma);
+restore:
+	/* Restore to default thermal threshold settings */
+	rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH1], thrsh[0]);
+	if (rc < 0)
+		goto unlock;
+
+	rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH2], thrsh[1]);
+	if (rc < 0)
+		goto unlock;
+
+	if (flash_data->hw_type == QCOM_MVFLASH_3CH)
+		rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH3], thrsh[2]);
+
+unlock:
+	mutex_unlock(&flash_data->lock);
+	return rc;
+}
+
 static int set_flash_current(struct qcom_flash_led *led, u32 current_ma, enum led_mode mode)
 {
 	struct qcom_flash_data *flash_data = led->flash_data;
@@ -313,6 +452,10 @@  static int qcom_flash_strobe_set(struct led_classdev_flash *fled_cdev, bool stat
 	if (rc)
 		return rc;
 
+	rc = update_allowed_flash_current(led, &led->flash_current_ma, state);
+	if (rc < 0)
+		return rc;
+
 	rc = set_flash_current(led, led->flash_current_ma, FLASH_MODE);
 	if (rc)
 		return rc;
@@ -429,6 +572,10 @@  static int qcom_flash_led_brightness_set(struct led_classdev *led_cdev,
 	if (rc)
 		return rc;
 
+	rc = update_allowed_flash_current(led, &current_ma, enable);
+	if (rc < 0)
+		return rc;
+
 	rc = set_flash_current(led, current_ma, TORCH_MODE);
 	if (rc)
 		return rc;
@@ -703,6 +850,13 @@  static int qcom_flash_led_probe(struct platform_device *pdev)
 		flash_data->hw_type = QCOM_MVFLASH_4CH;
 		flash_data->max_channels = 4;
 		regs = mvflash_4ch_regs;
+		rc = regmap_read(regmap, reg_base + FLASH_REVISION_REG, &val);
+		if (rc < 0) {
+			dev_err(dev, "Read flash LED module revision failed, rc=%d\n", rc);
+			return rc;
+		}
+
+		flash_data->revision = val;
 	} else {
 		dev_err(dev, "flash LED subtype %#x is not yet supported\n", val);
 		return -ENODEV;