mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
leds: qti-flash: Handle all-enabled led mask separately
In certain devices, LED channels are paired and connected to two separate LEDs. Due to symmetrical configuration, a switch that controls all four channels sets the same brightness value to both LEDs, which is not the intended behaviour; hence, handle this case separately. E.g. If flash0 (group 1) is set to 144 and flash1 (group 2) is set to 1056, current will be distributed evenly to all 4 channels like so: 300 mA would be set on all channels (as 144 + 1056 = 1200; 1200 / 4 = 300). Change this to: 144 / 2 = 72 on channels 0 and 3 (group 1) 1056 / 2 = 528 on channels 1 and 2 (group 2). Change-Id: Ie135811d59104cfa5551d17ebbb729a57c101099 Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org>
This commit is contained in:
parent
76a04e42a5
commit
568fc7ac9b
1 changed files with 59 additions and 23 deletions
|
|
@ -89,6 +89,8 @@
|
|||
#define OTST2_CURR_LIM_MA 500
|
||||
#define VLED_MAX_DEFAULT_UV 3500000
|
||||
|
||||
#define LED_MASK_ALL(led) GENMASK(led->max_channels - 1, 0)
|
||||
|
||||
enum flash_led_type {
|
||||
FLASH_LED_TYPE_UNKNOWN,
|
||||
FLASH_LED_TYPE_FLASH,
|
||||
|
|
@ -170,6 +172,7 @@ struct flash_switch_data {
|
|||
* @chan_en_map: Bit map of individual channel enable
|
||||
* @module_en: Flag used to enable/disable flash LED module
|
||||
* @trigger_lmh: Flag to enable lmh mitigation
|
||||
* @non_all_mask_switch_present: Used in handling symmetry for all_mask switch
|
||||
*/
|
||||
struct qti_flash_led {
|
||||
struct platform_device *pdev;
|
||||
|
|
@ -193,6 +196,7 @@ struct qti_flash_led {
|
|||
u8 chan_en_map;
|
||||
bool module_en;
|
||||
bool trigger_lmh;
|
||||
bool non_all_mask_switch_present;
|
||||
};
|
||||
|
||||
struct flash_current_headroom {
|
||||
|
|
@ -545,26 +549,14 @@ static int __qti_flash_led_brightness_set(struct led_classdev *led_cdev,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int qti_flash_led_symmetry_config(struct flash_switch_data *snode)
|
||||
static int qti_flash_config_group_symmetry(struct qti_flash_led *led,
|
||||
enum flash_led_type type,
|
||||
u32 led_mask)
|
||||
{
|
||||
struct qti_flash_led *led = snode->led;
|
||||
int i, total_curr_ma = 0, symmetric_leds = 0, per_led_curr_ma;
|
||||
enum flash_led_type type = FLASH_LED_TYPE_UNKNOWN;
|
||||
|
||||
/* Determine which LED type has triggered switch ON */
|
||||
for (i = 0; i < led->num_fnodes; i++) {
|
||||
if ((snode->led_mask & BIT(led->fnode[i].id)) &&
|
||||
(led->fnode[i].configured))
|
||||
type = led->fnode[i].type;
|
||||
}
|
||||
|
||||
if (type == FLASH_LED_TYPE_UNKNOWN) {
|
||||
/* No channels are configured */
|
||||
return 0;
|
||||
}
|
||||
int i, rc = 0, total_curr_ma = 0, symmetric_leds = 0, per_led_curr_ma;
|
||||
|
||||
for (i = 0; i < led->num_fnodes; i++) {
|
||||
if ((snode->led_mask & BIT(led->fnode[i].id)) &&
|
||||
if ((led_mask & BIT(led->fnode[i].id)) &&
|
||||
(led->fnode[i].type == type)) {
|
||||
total_curr_ma += led->fnode[i].user_current_ma;
|
||||
symmetric_leds++;
|
||||
|
|
@ -584,18 +576,60 @@ static int qti_flash_led_symmetry_config(struct flash_switch_data *snode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
pr_debug("symmetric_leds: %d total: %d per_led_curr_ma: %d\n",
|
||||
symmetric_leds, total_curr_ma, per_led_curr_ma);
|
||||
pr_debug("mask: %#x symmetric_leds: %d total: %d per_led_curr_ma: %d\n",
|
||||
led_mask, symmetric_leds, total_curr_ma, per_led_curr_ma);
|
||||
|
||||
for (i = 0; i < led->num_fnodes; i++) {
|
||||
if (snode->led_mask & BIT(led->fnode[i].id) &&
|
||||
if (led_mask & BIT(led->fnode[i].id) &&
|
||||
led->fnode[i].type == type) {
|
||||
__qti_flash_led_brightness_set(
|
||||
rc = __qti_flash_led_brightness_set(
|
||||
&led->fnode[i].fdev.led_cdev, per_led_curr_ma);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qti_flash_led_symmetry_config(struct flash_switch_data *snode)
|
||||
{
|
||||
struct qti_flash_led *led = snode->led;
|
||||
enum flash_led_type type = FLASH_LED_TYPE_UNKNOWN;
|
||||
int i, rc;
|
||||
|
||||
/* Determine which LED type has triggered switch ON */
|
||||
for (i = 0; i < led->num_fnodes; i++) {
|
||||
if ((snode->led_mask & BIT(led->fnode[i].id)) &&
|
||||
(led->fnode[i].configured))
|
||||
type = led->fnode[i].type;
|
||||
}
|
||||
|
||||
if (type == FLASH_LED_TYPE_UNKNOWN) {
|
||||
/* No channels are configured */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (snode->led_mask == LED_MASK_ALL(led) &&
|
||||
led->non_all_mask_switch_present) {
|
||||
/*
|
||||
* Gather masks from the other switches and configure symmetry
|
||||
* accordingly.
|
||||
*/
|
||||
for (i = 0; i < led->num_snodes; i++) {
|
||||
if (led->snode[i].led_mask != LED_MASK_ALL(led)) {
|
||||
rc = qti_flash_config_group_symmetry(led, type,
|
||||
led->snode[i].led_mask);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rc = qti_flash_config_group_symmetry(led, type,
|
||||
snode->led_mask);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void qti_flash_led_brightness_set(struct led_classdev *led_cdev,
|
||||
|
|
@ -1403,10 +1437,12 @@ static int register_switch_device(struct qti_flash_led *led,
|
|||
pr_err("Failed to read led mask rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
if ((snode->led_mask > ((1 << led->max_channels) - 1))) {
|
||||
if (snode->led_mask > LED_MASK_ALL(led)) {
|
||||
pr_err("Error, Invalid value for led-mask mask=0x%x\n",
|
||||
snode->led_mask);
|
||||
return -EINVAL;
|
||||
} else if (snode->led_mask < LED_MASK_ALL(led)) {
|
||||
led->non_all_mask_switch_present = true;
|
||||
}
|
||||
|
||||
snode->symmetry_en = of_property_read_bool(node, "qcom,symmetry-en");
|
||||
|
|
|
|||
Loading…
Reference in a new issue