leds: qpnp-flash-v2: Add support for dynamic torch current update

Add support to update torch current for all torch devices under
a switch if switch has already been enabled, without requiring
disablement of switch before updating new value.

Change-Id: I51e8d5701395fa095e3623cba0d2aaeae7c910ef
Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org>
This commit is contained in:
Jishnu Prakash 2021-10-28 00:30:51 +05:30
parent 666f50fb93
commit 707b831567

View file

@ -26,6 +26,8 @@
#include <linux/log2.h> #include <linux/log2.h>
#include "leds.h" #include "leds.h"
#define FLASH_LED_REG_PERPH_SUBTYPE(base) (base + 0x05)
#define FLASH_LED_REG_LED_STATUS1(base) (base + 0x08) #define FLASH_LED_REG_LED_STATUS1(base) (base + 0x08)
#define FLASH_LED_REG_LED_STATUS2(base) (base + 0x09) #define FLASH_LED_REG_LED_STATUS2(base) (base + 0x09)
@ -133,6 +135,9 @@
#define FLASH_LED_REG_CURRENT_DERATE_EN(base) (base + 0x76) #define FLASH_LED_REG_CURRENT_DERATE_EN(base) (base + 0x76)
#define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0) #define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0)
#define FLASH_LED_REG_CHICKEN_BITS(base) (base + 0x87)
#define FLASH_LED_EN_ITAR_FLY_BIT BIT(0)
#define VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us) (val_us / 8) #define VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us) (val_us / 8)
#define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25) #define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25)
#define VPH_DROOP_THRESH_VAL_TO_UV(val) ((val + 25) * 100000) #define VPH_DROOP_THRESH_VAL_TO_UV(val) ((val + 25) * 100000)
@ -196,6 +201,13 @@
/* notifier call chain for flash-led irqs */ /* notifier call chain for flash-led irqs */
static ATOMIC_NOTIFIER_HEAD(irq_notifier_list); static ATOMIC_NOTIFIER_HEAD(irq_notifier_list);
enum flash_led_subtype {
PMI8998_FLASH_SUBTYPE = 3,
PM660L_FLASH_SUBTYPE = 3,
PM6150L_FLASH_SUBTYPE,
PMI632_FLASH_SUBTYPE,
};
enum flash_charger_mitigation { enum flash_charger_mitigation {
FLASH_DISABLE_CHARGER_MITIGATION, FLASH_DISABLE_CHARGER_MITIGATION,
FLASH_HW_CHARGER_MITIGATION_BY_ILED_THRSHLD, FLASH_HW_CHARGER_MITIGATION_BY_ILED_THRSHLD,
@ -331,6 +343,7 @@ struct qpnp_flash_led {
u16 base; u16 base;
bool trigger_lmh; bool trigger_lmh;
bool trigger_chgr; bool trigger_chgr;
bool torch_current_update;
}; };
static int thermal_derate_slow_table[] = { static int thermal_derate_slow_table[] = {
@ -702,6 +715,27 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
if (rc < 0) if (rc < 0)
return rc; return rc;
rc = qpnp_flash_led_read(led,
FLASH_LED_REG_PERPH_SUBTYPE(led->base),
&val);
if (rc < 0)
return rc;
/*
* Updating torch current on-the-fly is possible
* from PM6150L onwards.
*/
if (val >= PM6150L_FLASH_SUBTYPE) {
rc = qpnp_flash_led_masked_read(led,
FLASH_LED_REG_CHICKEN_BITS(led->base),
FLASH_LED_EN_ITAR_FLY_BIT,
&val);
if (rc < 0)
return rc;
led->torch_current_update = !!val;
}
if (led->pdata->led1n2_iclamp_low_ma) { if (led->pdata->led1n2_iclamp_low_ma) {
val = get_current_reg_code(led->pdata->led1n2_iclamp_low_ma, val = get_current_reg_code(led->pdata->led1n2_iclamp_low_ma,
led->fnode[LED1].ires_ua); led->fnode[LED1].ires_ua);
@ -1580,13 +1614,28 @@ static int qpnp_flash_led_module_enable(struct flash_switch_data *snode)
static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
{ {
struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev); struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
struct flash_node_data fnode;
int rc, i, addr_offset; int rc, i, addr_offset;
u8 val, mask; u8 val, mask;
bool torch_current_update = false;
if (snode->enabled == on) { if (snode->enabled == on) {
pr_debug("Switch node is already %s!\n", if (on && led->torch_current_update) {
on ? "enabled" : "disabled"); for (i = 0; i < led->num_fnodes; i++) {
return 0; fnode = led->fnode[i];
if (snode->led_mask & BIT(fnode.id) &&
fnode.led_on) {
torch_current_update = (fnode.type ==
FLASH_LED_TYPE_TORCH);
}
}
}
if (!torch_current_update) {
pr_debug("Switch node is already %s!\n",
on ? "enabled" : "disabled");
return 0;
}
} }
if (!on) { if (!on) {
@ -1615,6 +1664,22 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
if (rc < 0) if (rc < 0)
return rc; return rc;
if (torch_current_update) {
for (i = 0; i < led->num_fnodes; i++) {
if (snode->led_mask & BIT(led->fnode[i].id) &&
led->fnode[i].led_on) {
addr_offset = led->fnode[i].id;
rc = qpnp_flash_led_masked_write(led,
FLASH_LED_REG_TGR_CURRENT(led->base +
addr_offset), FLASH_LED_CURRENT_MASK,
led->fnode[i].current_reg_val);
if (rc < 0)
return rc;
}
}
return 0;
}
val = 0; val = 0;
for (i = 0; i < led->num_fnodes; i++) { for (i = 0; i < led->num_fnodes; i++) {
if (!led->fnode[i].led_on || if (!led->fnode[i].led_on ||