diff --git a/drivers/leds/trigger/ledtrig-sol.c b/drivers/leds/trigger/ledtrig-sol.c index a1d2c299f76b..ffb0ac1eb342 100644 --- a/drivers/leds/trigger/ledtrig-sol.c +++ b/drivers/leds/trigger/ledtrig-sol.c @@ -28,6 +28,7 @@ #include #include #include +#include #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 : 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);