Sol led: Handle power supply states

Handle power-supply states for Charging/Discharging
Set blink/solid Led settings as below

LED Brighness depend on Device Charging State
----------------------------------------------
-- Full while Device Charging
-- Half Brighness while not Charging

Led Functional Mode Depend on the Battery capacity
--------------------------------------------------
Battery Level < LOW_CAP_THRESHOLD_DEFAULT
-- Fast Blink "charging_low" led node(s)

LOW_CAP_THRESHOLD_DEFAULT < Battery Level < BATT_CAP_THRESHOLD_HIGH
-- Slow Blink "charging" led node(s) (If device charging)
-- Enable Solid 50% brightness for "charging" led node(s) (If device not charging)

BATT_CAP_THRESHOLD_HIGH < Battery Level < BATT_CAP_THRESHOLD_FULL
-- Slow Blink "charging_full" led node(s) (If device charging)
-- Enable Solid 50% brightness for "charging_full" led node(s) (If device not charging)

Battery Level ==  BATT_CAP_THRESHOLD_FULL
-- Enable Solid 100% brightness for "charging_full" led node(s)

Change-Id: I0abf35ea5ee51ade808ac196d8e56d7dcac33d9c
Signed-off-by: Srihari Sathyanarayana <sriharis@motorola.com>
Signed-off-by: Vijayakumar Gn <vijaygn@motorola.com>
Reviewed-on: https://gerrit.mot.com/2516362
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Perry White <awhite6@motorola.com>
Reviewed-by: Qing Chang <qing@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Srihari Sathyanarayana 2023-02-03 19:07:28 +05:30
commit 2d2ff4b594

View file

@ -28,6 +28,7 @@
#include <linux/leds.h>
#include <linux/power_supply.h>
#include <linux/device/class.h>
#include <linux/delay.h>
#define CHARGING_DELAY_ON_DEFAULT (700)
#define CHARGING_DELAY_OFF_DEFAULT (700)
@ -35,6 +36,9 @@
#define LOW_CAP_DELAY_OFF_DEFAULT (200)
#define LOW_CAP_THRESHOLD_DEFAULT (15)
#define BATT_CAP_THRESHOLD_HALF (50)
#define BATT_CAP_THRESHOLD_HIGH (75)
#define BATT_CAP_THRESHOLD_FULL (100)
struct sol_trig_data {
struct led_classdev *led_cdev;
@ -197,6 +201,63 @@ static struct attribute *sol_trig_attrs[] = {
};
ATTRIBUTE_GROUPS(sol_trig);
static int sol_trig_activate(struct led_classdev *led_cdev);
static void sol_trig_deactivate(struct led_classdev *led_cdev);
static struct led_trigger sol_led_trigger = {
.name = "sign-of-life",
.activate = sol_trig_activate,
.deactivate = sol_trig_deactivate,
.groups = sol_trig_groups,
};
static int is_multi_led_enabled () {
return 0x01;
}
/* API to set sol led colour, brightness etc based on battery status */
static int sol_led_update_status(const char *led_name, bool blink, unsigned int brightness, struct sol_trig_data *sol_data)
{
struct led_classdev *led_cdev = sol_data->led_cdev;
dev_dbg(led_cdev->dev, "Entry sol_led_update_status name:%s, blink = %d, brightness = %u\n",led_name,blink,brightness);
if(!strcmp(led_name, "charging_full") && !strcmp(led_cdev->name, "charging_full")) {
dev_dbg(led_cdev->dev, "POWER_STATUS_FULL\n");
led_trigger_event(&sol_led_trigger, LED_OFF);
msleep(10); /* MMI_TODO <kernel>: set delay to sync led-trigger with core-led calls */
led_set_brightness(led_cdev, brightness);
if(blink){
led_blink_set(led_cdev, &sol_data->charging_delay_on, &sol_data->charging_delay_off);
dev_dbg(led_cdev->dev, "SETTING DONE FOR charging full blink delay_on=%lu,delay_off=%lu\n",sol_data->charging_delay_on, sol_data->charging_delay_off);
}
}
if(!strcmp(led_name, "charging") && !strcmp(led_cdev->name, "charging")) {
dev_dbg(led_cdev->dev, "POWER_STATUS_CHARGING\n");
led_trigger_event(&sol_led_trigger, LED_OFF);
msleep(10); /* set delay to sync led-trigger with core-led calls */
led_set_brightness(led_cdev, brightness);
if(blink){
led_blink_set(led_cdev, &sol_data->charging_delay_on, &sol_data->charging_delay_off);
dev_dbg(led_cdev->dev, "SETTING DONE FOR charging blink delay_on=%lu,delay_off=%lu\n",sol_data->charging_delay_on, sol_data->charging_delay_off);
}
}
if(!strcmp(led_name, "charging_low") && !strcmp(led_cdev->name, "charging_low")) {
dev_dbg(led_cdev->dev, "POWER_STATUS_LOW\n");
led_trigger_event(&sol_led_trigger, LED_OFF);
msleep(10); /* set delay to sync led-trigger with core-led calls */
led_set_brightness(led_cdev, brightness);
if(blink){
led_blink_set(led_cdev, &sol_data->low_cap_delay_on, &sol_data->low_cap_delay_off);
dev_dbg(led_cdev->dev, "SETTING DONE FOR low cap blink delay_on= %lu,delay_off=%lu\n",sol_data->low_cap_delay_on,sol_data->low_cap_delay_off);
}
}
return 0;
}
static int sol_trig_notifier_fn(struct notifier_block *nb, unsigned long action, void *data)
{
union power_supply_propval status;
@ -233,11 +294,34 @@ static int sol_trig_notifier_fn(struct notifier_block *nb, unsigned long action,
switch (status.intval) {
case POWER_SUPPLY_STATUS_UNKNOWN: /* Fall-through */
case POWER_SUPPLY_STATUS_FULL:
led_set_brightness(led_cdev, LED_FULL);
if(is_multi_led_enabled())
sol_led_update_status("charging_full", false, LED_FULL, sol_data);
else
led_set_brightness(led_cdev, LED_FULL);
break;
case POWER_SUPPLY_STATUS_CHARGING:
led_blink_set(led_cdev, &sol_data->charging_delay_on, &sol_data->charging_delay_off);
if(is_multi_led_enabled()) {
if (!power_supply_get_property(psy, POWER_SUPPLY_PROP_CAPACITY, &capacity))
dev_err(led_cdev->dev, "%s: Battery capacity: %d\n", __func__, capacity.intval);
/* charging_low led blink: Charging capacity <= 15% */
if (capacity.intval <= sol_data->low_cap_threshold)
sol_led_update_status("charging_low", true, LED_FULL, sol_data);
/* charging led blink: Charging capacity >15% and <75% */
if (capacity.intval > sol_data->low_cap_threshold && capacity.intval < BATT_CAP_THRESHOLD_HIGH)
sol_led_update_status("charging", true, LED_FULL, sol_data);
/* charging_full led blink: Charging capacity >=75 and < 100% */
if (capacity.intval >= BATT_CAP_THRESHOLD_HIGH && capacity.intval <= BATT_CAP_THRESHOLD_FULL)
sol_led_update_status("charging_full", true, LED_FULL, sol_data);
} else
led_blink_set(led_cdev, &sol_data->charging_delay_on, &sol_data->charging_delay_off);
break;
case POWER_SUPPLY_STATUS_DISCHARGING: /* Fall-through */
case POWER_SUPPLY_STATUS_NOT_CHARGING: /* Fall-through */
default:
@ -245,11 +329,28 @@ static int sol_trig_notifier_fn(struct notifier_block *nb, unsigned long action,
* If PSY capacity is equal-to or below a specified threshold, use a special low-capacity blink pattern.
* Otherwise, set LED to full brightness by default.
*/
if (!power_supply_get_property(psy, POWER_SUPPLY_PROP_CAPACITY, &capacity) &&
capacity.intval <= sol_data->low_cap_threshold)
led_blink_set(led_cdev, &sol_data->low_cap_delay_on, &sol_data->low_cap_delay_off);
if (!power_supply_get_property(psy, POWER_SUPPLY_PROP_CAPACITY, &capacity))
dev_dbg(led_cdev->dev, "%s: Battery capacity: %d\n", __func__, capacity.intval);
if(is_multi_led_enabled()) {
/* charging_low led blink: Charging capacity <= 15% */
if (capacity.intval <= sol_data->low_cap_threshold)
sol_led_update_status("charging_low", true, LED_FULL, sol_data);
/* charging led solid: Charging capacity >15% and <75% */
if (capacity.intval > sol_data->low_cap_threshold && capacity.intval < BATT_CAP_THRESHOLD_HIGH)
sol_led_update_status("charging", false, LED_HALF, sol_data);
/* charging_full led solid: Charging capacity >=75 and < 100% */
if (capacity.intval >= BATT_CAP_THRESHOLD_HIGH && capacity.intval <= BATT_CAP_THRESHOLD_FULL)
sol_led_update_status("charging_full", false, LED_HALF, sol_data);
}
else
led_set_brightness(led_cdev, LED_FULL);
if(capacity.intval <= sol_data->low_cap_threshold)
led_blink_set(led_cdev, &sol_data->low_cap_delay_on, &sol_data->low_cap_delay_off);
else
led_set_brightness(led_cdev, LED_FULL);
break;
}
@ -297,6 +398,7 @@ static int sol_trig_activate(struct led_classdev *led_cdev)
sol_data->battery_psy_present = false;
class_for_each_device(power_supply_class, NULL, sol_data, sol_trig_identify_psy);
dev_err(led_cdev->dev, " %s, Initial brightness = %d\n",sol_data->led_cdev->name, sol_data->led_cdev->brightness);
led_set_trigger_data(led_cdev, sol_data);
@ -320,13 +422,6 @@ static void sol_trig_deactivate(struct led_classdev *led_cdev)
return;
}
static struct led_trigger sol_led_trigger = {
.name = "sign-of-life",
.activate = sol_trig_activate,
.deactivate = sol_trig_deactivate,
.groups = sol_trig_groups,
};
static int __init sol_trig_init(void)
{
return led_trigger_register(&sol_led_trigger);