1a63a5fa9SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28c0984e5SSebastian Reichel /*
38c0984e5SSebastian Reichel * LEDs triggers for power supply class
48c0984e5SSebastian Reichel *
58c0984e5SSebastian Reichel * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
68c0984e5SSebastian Reichel * Copyright © 2004 Szabolcs Gyurko
78c0984e5SSebastian Reichel * Copyright © 2003 Ian Molton <spyro@f2s.com>
88c0984e5SSebastian Reichel *
98c0984e5SSebastian Reichel * Modified: 2004, Oct Szabolcs Gyurko
108c0984e5SSebastian Reichel */
118c0984e5SSebastian Reichel
128c0984e5SSebastian Reichel #include <linux/kernel.h>
138c0984e5SSebastian Reichel #include <linux/device.h>
148c0984e5SSebastian Reichel #include <linux/power_supply.h>
158c0984e5SSebastian Reichel #include <linux/slab.h>
169de10a51SThomas Weißschuh #include <linux/leds.h>
178c0984e5SSebastian Reichel
188c0984e5SSebastian Reichel #include "power_supply.h"
198c0984e5SSebastian Reichel
208c0984e5SSebastian Reichel /* Battery specific LEDs triggers. */
218c0984e5SSebastian Reichel
power_supply_update_bat_leds(struct power_supply * psy)228c0984e5SSebastian Reichel static void power_supply_update_bat_leds(struct power_supply *psy)
238c0984e5SSebastian Reichel {
248c0984e5SSebastian Reichel union power_supply_propval status;
258c0984e5SSebastian Reichel
268c0984e5SSebastian Reichel if (power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
278c0984e5SSebastian Reichel return;
288c0984e5SSebastian Reichel
298c0984e5SSebastian Reichel dev_dbg(&psy->dev, "%s %d\n", __func__, status.intval);
308c0984e5SSebastian Reichel
318c0984e5SSebastian Reichel switch (status.intval) {
328c0984e5SSebastian Reichel case POWER_SUPPLY_STATUS_FULL:
338c0984e5SSebastian Reichel led_trigger_event(psy->charging_full_trig, LED_FULL);
348c0984e5SSebastian Reichel led_trigger_event(psy->charging_trig, LED_OFF);
358c0984e5SSebastian Reichel led_trigger_event(psy->full_trig, LED_FULL);
368c0984e5SSebastian Reichel /* Going from blink to LED on requires a LED_OFF event to stop blink */
378c0984e5SSebastian Reichel led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF);
388c0984e5SSebastian Reichel led_trigger_event(psy->charging_blink_full_solid_trig, LED_FULL);
398c0984e5SSebastian Reichel break;
408c0984e5SSebastian Reichel case POWER_SUPPLY_STATUS_CHARGING:
418c0984e5SSebastian Reichel led_trigger_event(psy->charging_full_trig, LED_FULL);
428c0984e5SSebastian Reichel led_trigger_event(psy->charging_trig, LED_FULL);
43*e298d8a3SHans de Goede led_trigger_event(psy->full_trig, LED_OFF);
448c0984e5SSebastian Reichel led_trigger_blink(psy->charging_blink_full_solid_trig, 0, 0);
458c0984e5SSebastian Reichel break;
468c0984e5SSebastian Reichel default:
478c0984e5SSebastian Reichel led_trigger_event(psy->charging_full_trig, LED_OFF);
488c0984e5SSebastian Reichel led_trigger_event(psy->charging_trig, LED_OFF);
498c0984e5SSebastian Reichel led_trigger_event(psy->full_trig, LED_OFF);
508c0984e5SSebastian Reichel led_trigger_event(psy->charging_blink_full_solid_trig,
518c0984e5SSebastian Reichel LED_OFF);
528c0984e5SSebastian Reichel break;
538c0984e5SSebastian Reichel }
548c0984e5SSebastian Reichel }
558c0984e5SSebastian Reichel
power_supply_create_bat_triggers(struct power_supply * psy)568c0984e5SSebastian Reichel static int power_supply_create_bat_triggers(struct power_supply *psy)
578c0984e5SSebastian Reichel {
588c0984e5SSebastian Reichel psy->charging_full_trig_name = kasprintf(GFP_KERNEL,
598c0984e5SSebastian Reichel "%s-charging-or-full", psy->desc->name);
608c0984e5SSebastian Reichel if (!psy->charging_full_trig_name)
618c0984e5SSebastian Reichel goto charging_full_failed;
628c0984e5SSebastian Reichel
638c0984e5SSebastian Reichel psy->charging_trig_name = kasprintf(GFP_KERNEL,
648c0984e5SSebastian Reichel "%s-charging", psy->desc->name);
658c0984e5SSebastian Reichel if (!psy->charging_trig_name)
668c0984e5SSebastian Reichel goto charging_failed;
678c0984e5SSebastian Reichel
688c0984e5SSebastian Reichel psy->full_trig_name = kasprintf(GFP_KERNEL, "%s-full", psy->desc->name);
698c0984e5SSebastian Reichel if (!psy->full_trig_name)
708c0984e5SSebastian Reichel goto full_failed;
718c0984e5SSebastian Reichel
728c0984e5SSebastian Reichel psy->charging_blink_full_solid_trig_name = kasprintf(GFP_KERNEL,
738c0984e5SSebastian Reichel "%s-charging-blink-full-solid", psy->desc->name);
748c0984e5SSebastian Reichel if (!psy->charging_blink_full_solid_trig_name)
758c0984e5SSebastian Reichel goto charging_blink_full_solid_failed;
768c0984e5SSebastian Reichel
778c0984e5SSebastian Reichel led_trigger_register_simple(psy->charging_full_trig_name,
788c0984e5SSebastian Reichel &psy->charging_full_trig);
798c0984e5SSebastian Reichel led_trigger_register_simple(psy->charging_trig_name,
808c0984e5SSebastian Reichel &psy->charging_trig);
818c0984e5SSebastian Reichel led_trigger_register_simple(psy->full_trig_name,
828c0984e5SSebastian Reichel &psy->full_trig);
838c0984e5SSebastian Reichel led_trigger_register_simple(psy->charging_blink_full_solid_trig_name,
848c0984e5SSebastian Reichel &psy->charging_blink_full_solid_trig);
858c0984e5SSebastian Reichel
868c0984e5SSebastian Reichel return 0;
878c0984e5SSebastian Reichel
888c0984e5SSebastian Reichel charging_blink_full_solid_failed:
898c0984e5SSebastian Reichel kfree(psy->full_trig_name);
908c0984e5SSebastian Reichel full_failed:
918c0984e5SSebastian Reichel kfree(psy->charging_trig_name);
928c0984e5SSebastian Reichel charging_failed:
938c0984e5SSebastian Reichel kfree(psy->charging_full_trig_name);
948c0984e5SSebastian Reichel charging_full_failed:
958c0984e5SSebastian Reichel return -ENOMEM;
968c0984e5SSebastian Reichel }
978c0984e5SSebastian Reichel
power_supply_remove_bat_triggers(struct power_supply * psy)988c0984e5SSebastian Reichel static void power_supply_remove_bat_triggers(struct power_supply *psy)
998c0984e5SSebastian Reichel {
1008c0984e5SSebastian Reichel led_trigger_unregister_simple(psy->charging_full_trig);
1018c0984e5SSebastian Reichel led_trigger_unregister_simple(psy->charging_trig);
1028c0984e5SSebastian Reichel led_trigger_unregister_simple(psy->full_trig);
1038c0984e5SSebastian Reichel led_trigger_unregister_simple(psy->charging_blink_full_solid_trig);
1048c0984e5SSebastian Reichel kfree(psy->charging_blink_full_solid_trig_name);
1058c0984e5SSebastian Reichel kfree(psy->full_trig_name);
1068c0984e5SSebastian Reichel kfree(psy->charging_trig_name);
1078c0984e5SSebastian Reichel kfree(psy->charging_full_trig_name);
1088c0984e5SSebastian Reichel }
1098c0984e5SSebastian Reichel
1108c0984e5SSebastian Reichel /* Generated power specific LEDs triggers. */
1118c0984e5SSebastian Reichel
power_supply_update_gen_leds(struct power_supply * psy)1128c0984e5SSebastian Reichel static void power_supply_update_gen_leds(struct power_supply *psy)
1138c0984e5SSebastian Reichel {
1148c0984e5SSebastian Reichel union power_supply_propval online;
1158c0984e5SSebastian Reichel
1168c0984e5SSebastian Reichel if (power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
1178c0984e5SSebastian Reichel return;
1188c0984e5SSebastian Reichel
1198c0984e5SSebastian Reichel dev_dbg(&psy->dev, "%s %d\n", __func__, online.intval);
1208c0984e5SSebastian Reichel
1218c0984e5SSebastian Reichel if (online.intval)
1228c0984e5SSebastian Reichel led_trigger_event(psy->online_trig, LED_FULL);
1238c0984e5SSebastian Reichel else
1248c0984e5SSebastian Reichel led_trigger_event(psy->online_trig, LED_OFF);
1258c0984e5SSebastian Reichel }
1268c0984e5SSebastian Reichel
power_supply_create_gen_triggers(struct power_supply * psy)1278c0984e5SSebastian Reichel static int power_supply_create_gen_triggers(struct power_supply *psy)
1288c0984e5SSebastian Reichel {
1298c0984e5SSebastian Reichel psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online",
1308c0984e5SSebastian Reichel psy->desc->name);
1318c0984e5SSebastian Reichel if (!psy->online_trig_name)
1328c0984e5SSebastian Reichel return -ENOMEM;
1338c0984e5SSebastian Reichel
1348c0984e5SSebastian Reichel led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
1358c0984e5SSebastian Reichel
1368c0984e5SSebastian Reichel return 0;
1378c0984e5SSebastian Reichel }
1388c0984e5SSebastian Reichel
power_supply_remove_gen_triggers(struct power_supply * psy)1398c0984e5SSebastian Reichel static void power_supply_remove_gen_triggers(struct power_supply *psy)
1408c0984e5SSebastian Reichel {
1418c0984e5SSebastian Reichel led_trigger_unregister_simple(psy->online_trig);
1428c0984e5SSebastian Reichel kfree(psy->online_trig_name);
1438c0984e5SSebastian Reichel }
1448c0984e5SSebastian Reichel
1458c0984e5SSebastian Reichel /* Choice what triggers to create&update. */
1468c0984e5SSebastian Reichel
power_supply_update_leds(struct power_supply * psy)1478c0984e5SSebastian Reichel void power_supply_update_leds(struct power_supply *psy)
1488c0984e5SSebastian Reichel {
1498c0984e5SSebastian Reichel if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
1508c0984e5SSebastian Reichel power_supply_update_bat_leds(psy);
1518c0984e5SSebastian Reichel else
1528c0984e5SSebastian Reichel power_supply_update_gen_leds(psy);
1538c0984e5SSebastian Reichel }
1548c0984e5SSebastian Reichel
power_supply_create_triggers(struct power_supply * psy)1558c0984e5SSebastian Reichel int power_supply_create_triggers(struct power_supply *psy)
1568c0984e5SSebastian Reichel {
1578c0984e5SSebastian Reichel if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
1588c0984e5SSebastian Reichel return power_supply_create_bat_triggers(psy);
1598c0984e5SSebastian Reichel return power_supply_create_gen_triggers(psy);
1608c0984e5SSebastian Reichel }
1618c0984e5SSebastian Reichel
power_supply_remove_triggers(struct power_supply * psy)1628c0984e5SSebastian Reichel void power_supply_remove_triggers(struct power_supply *psy)
1638c0984e5SSebastian Reichel {
1648c0984e5SSebastian Reichel if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
1658c0984e5SSebastian Reichel power_supply_remove_bat_triggers(psy);
1668c0984e5SSebastian Reichel else
1678c0984e5SSebastian Reichel power_supply_remove_gen_triggers(psy);
168 }
169