From 8dfab2b485a1aee06aec94d8320c88d7dbb3c480 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Wed, 22 Jul 2020 10:42:34 -0700 Subject: [PATCH] leds: qti-flash: Allow dynamic symmetry current redistribution Currently, when symmetry is enabled, current redistribution occurs only when a switch is turned on after being disabled initially. Enable current redistribution to occur on the fly as long as a switch is enabled. This applies to both torch and flash devices. Illustrative example: user0 user3 Torch0 Torch3 Comment 500 0 250 250 (average of user set values) 150 0 75 75 (150 + 0 / 2) 150 100 125 125 (150 + 100 / 2). Change-Id: I5f832e4fa669a9662d45592c5c3a512df07f7255 Signed-off-by: Guru Das Srinagesh --- drivers/leds/leds-qti-flash.c | 48 ++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/drivers/leds/leds-qti-flash.c b/drivers/leds/leds-qti-flash.c index 646a2aac058f..e0483fca515a 100644 --- a/drivers/leds/leds-qti-flash.c +++ b/drivers/leds/leds-qti-flash.c @@ -117,6 +117,7 @@ struct flash_node_data { struct led_classdev_flash fdev; u32 ires_ua; u32 default_ires_ua; + u32 user_current_ma; u32 current_ma; u32 max_current; u8 duration; @@ -438,6 +439,7 @@ static int qti_flash_led_disable(struct flash_node_data *fnode) fnode->configured = false; fnode->current_ma = 0; + fnode->user_current_ma = 0; out: spin_unlock(&led->lock); @@ -450,10 +452,9 @@ static enum led_brightness qti_flash_led_brightness_get( return led_cdev->brightness; } -static void qti_flash_led_brightness_set(struct led_classdev *led_cdev, +static int __qti_flash_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct qti_flash_led *led = NULL; struct flash_node_data *fnode = NULL; struct led_classdev_flash *fdev = NULL; int rc; @@ -462,21 +463,20 @@ static void qti_flash_led_brightness_set(struct led_classdev *led_cdev, fdev = container_of(led_cdev, struct led_classdev_flash, led_cdev); fnode = container_of(fdev, struct flash_node_data, fdev); - led = fnode->led; if (!brightness) { rc = qti_flash_led_strobe(fnode->led, NULL, FLASH_LED_ENABLE(fnode->id), 0); if (rc < 0) { pr_err("Failed to destrobe LED, rc=%d\n", rc); - return; + return rc; } rc = qti_flash_led_disable(fnode); if (rc < 0) pr_err("Failed to disable LED\n"); - return; + return rc; } min_current_ma = DIV_ROUND_CLOSEST(fnode->ires_ua, 1000); @@ -501,10 +501,11 @@ static void qti_flash_led_brightness_set(struct led_classdev *led_cdev, rc = qti_flash_led_enable(fnode); if (rc < 0) pr_err("Failed to set brightness %d to LED\n", brightness); + + return rc; } -static int qti_flash_led_symmetry_config( - struct flash_switch_data *snode) +static int qti_flash_led_symmetry_config(struct flash_switch_data *snode) { struct qti_flash_led *led = snode->led; int i, total_curr_ma = 0, symmetric_leds = 0, per_led_curr_ma; @@ -525,7 +526,7 @@ static int qti_flash_led_symmetry_config( for (i = 0; i < led->num_fnodes; i++) { if ((snode->led_mask & BIT(led->fnode[i].id)) && (led->fnode[i].type == type)) { - total_curr_ma += led->fnode[i].current_ma; + total_curr_ma += led->fnode[i].user_current_ma; symmetric_leds++; } } @@ -549,7 +550,7 @@ static int qti_flash_led_symmetry_config( for (i = 0; i < led->num_fnodes; i++) { if (snode->led_mask & BIT(led->fnode[i].id) && led->fnode[i].type == type) { - qti_flash_led_brightness_set( + __qti_flash_led_brightness_set( &led->fnode[i].fdev.led_cdev, per_led_curr_ma); } } @@ -557,6 +558,35 @@ static int qti_flash_led_symmetry_config( return 0; } +static void qti_flash_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct led_classdev_flash *fdev; + struct flash_node_data *fnode; + struct qti_flash_led *led; + int i, rc; + + fdev = container_of(led_cdev, struct led_classdev_flash, led_cdev); + fnode = container_of(fdev, struct flash_node_data, fdev); + led = fnode->led; + + rc = __qti_flash_led_brightness_set(led_cdev, brightness); + if (!rc) + fnode->user_current_ma = brightness; + else + return; + + for (i = 0; i < led->num_snodes; i++) { + pr_debug("snode[%d] symm %d, enabled %d\n", i, + led->snode[i].symmetry_en, + led->snode[i].enabled); + if (led->snode[i].symmetry_en && led->snode[i].enabled) { + qti_flash_led_symmetry_config(&led->snode[i]); + break; + } + } +} + static int qti_flash_switch_enable(struct flash_switch_data *snode) { struct qti_flash_led *led = snode->led;