Skip to content

Commit 447bbf7

Browse files
committed
Merge tag 'ib-leds-platform-power-v6.11'
Immutable branch between LEDs, Power and RGB due for the v6.11 merge window. Merge it to provide functionality required by power-supply specific LED handler cleanups depending on the newly added (multi-colour) LED features. Signed-off-by: Sebastian Reichel <[email protected]>
2 parents ebacfa1 + 9af12f5 commit 447bbf7

File tree

8 files changed

+149
-35
lines changed

8 files changed

+149
-35
lines changed

drivers/leds/led-class-multicolor.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ int led_classdev_multicolor_register_ext(struct device *parent,
134134
return -EINVAL;
135135

136136
led_cdev = &mcled_cdev->led_cdev;
137+
led_cdev->flags |= LED_MULTI_COLOR;
137138
mcled_cdev->led_cdev.groups = led_multicolor_groups;
138139

139140
return led_classdev_register_ext(parent, led_cdev, init_data);

drivers/leds/led-core.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
#include <linux/kernel.h>
11+
#include <linux/led-class-multicolor.h>
1112
#include <linux/leds.h>
1213
#include <linux/list.h>
1314
#include <linux/module.h>
@@ -362,6 +363,36 @@ int led_set_brightness_sync(struct led_classdev *led_cdev, unsigned int value)
362363
}
363364
EXPORT_SYMBOL_GPL(led_set_brightness_sync);
364365

366+
/*
367+
* This is a led-core function because just like led_set_brightness()
368+
* it is used in the kernel by e.g. triggers.
369+
*/
370+
void led_mc_set_brightness(struct led_classdev *led_cdev,
371+
unsigned int *intensity_value, unsigned int num_colors,
372+
unsigned int brightness)
373+
{
374+
struct led_classdev_mc *mcled_cdev;
375+
unsigned int i;
376+
377+
if (!(led_cdev->flags & LED_MULTI_COLOR)) {
378+
dev_err_once(led_cdev->dev, "error not a multi-color LED\n");
379+
return;
380+
}
381+
382+
mcled_cdev = lcdev_to_mccdev(led_cdev);
383+
if (num_colors != mcled_cdev->num_colors) {
384+
dev_err_once(led_cdev->dev, "error num_colors mismatch %u != %u\n",
385+
num_colors, mcled_cdev->num_colors);
386+
return;
387+
}
388+
389+
for (i = 0; i < mcled_cdev->num_colors; i++)
390+
mcled_cdev->subled_info[i].intensity = intensity_value[i];
391+
392+
led_set_brightness(led_cdev, brightness);
393+
}
394+
EXPORT_SYMBOL_GPL(led_mc_set_brightness);
395+
365396
int led_update_brightness(struct led_classdev *led_cdev)
366397
{
367398
int ret;

drivers/leds/led-triggers.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,26 @@ void led_trigger_event(struct led_trigger *trig,
396396
}
397397
EXPORT_SYMBOL_GPL(led_trigger_event);
398398

399+
void led_mc_trigger_event(struct led_trigger *trig,
400+
unsigned int *intensity_value, unsigned int num_colors,
401+
enum led_brightness brightness)
402+
{
403+
struct led_classdev *led_cdev;
404+
405+
if (!trig)
406+
return;
407+
408+
rcu_read_lock();
409+
list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list) {
410+
if (!(led_cdev->flags & LED_MULTI_COLOR))
411+
continue;
412+
413+
led_mc_set_brightness(led_cdev, intensity_value, num_colors, brightness);
414+
}
415+
rcu_read_unlock();
416+
}
417+
EXPORT_SYMBOL_GPL(led_mc_trigger_event);
418+
399419
static void led_trigger_blink_setup(struct led_trigger *trig,
400420
unsigned long delay_on,
401421
unsigned long delay_off,

drivers/leds/rgb/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ config LEDS_GROUP_MULTICOLOR
1717
config LEDS_KTD202X
1818
tristate "LED support for KTD202x Chips"
1919
depends on I2C
20-
depends on OF
2120
select REGMAP_I2C
2221
help
2322
This option enables support for the Kinetic KTD2026/KTD2027

drivers/leds/rgb/leds-ktd202x.c

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ struct ktd202x {
9999
struct device *dev;
100100
struct regmap *regmap;
101101
bool enabled;
102-
int num_leds;
102+
unsigned long num_leds;
103103
struct ktd202x_led leds[] __counted_by(num_leds);
104104
};
105105

@@ -381,39 +381,42 @@ static int ktd202x_blink_mc_set(struct led_classdev *cdev,
381381
mc->num_colors);
382382
}
383383

384-
static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct device_node *np,
384+
static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct fwnode_handle *fwnode,
385385
struct ktd202x_led *led, struct led_init_data *init_data)
386386
{
387+
struct fwnode_handle *child;
387388
struct led_classdev *cdev;
388-
struct device_node *child;
389389
struct mc_subled *info;
390390
int num_channels;
391391
int i = 0;
392392

393-
num_channels = of_get_available_child_count(np);
393+
num_channels = 0;
394+
fwnode_for_each_available_child_node(fwnode, child)
395+
num_channels++;
396+
394397
if (!num_channels || num_channels > chip->num_leds)
395398
return -EINVAL;
396399

397400
info = devm_kcalloc(chip->dev, num_channels, sizeof(*info), GFP_KERNEL);
398401
if (!info)
399402
return -ENOMEM;
400403

401-
for_each_available_child_of_node(np, child) {
404+
fwnode_for_each_available_child_node(fwnode, child) {
402405
u32 mono_color;
403406
u32 reg;
404407
int ret;
405408

406-
ret = of_property_read_u32(child, "reg", &reg);
409+
ret = fwnode_property_read_u32(child, "reg", &reg);
407410
if (ret != 0 || reg >= chip->num_leds) {
408-
dev_err(chip->dev, "invalid 'reg' of %pOFn\n", child);
409-
of_node_put(child);
410-
return -EINVAL;
411+
dev_err(chip->dev, "invalid 'reg' of %pfw\n", child);
412+
fwnode_handle_put(child);
413+
return ret;
411414
}
412415

413-
ret = of_property_read_u32(child, "color", &mono_color);
416+
ret = fwnode_property_read_u32(child, "color", &mono_color);
414417
if (ret < 0 && ret != -EINVAL) {
415-
dev_err(chip->dev, "failed to parse 'color' of %pOF\n", child);
416-
of_node_put(child);
418+
dev_err(chip->dev, "failed to parse 'color' of %pfw\n", child);
419+
fwnode_handle_put(child);
417420
return ret;
418421
}
419422

@@ -433,16 +436,16 @@ static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct device_node *np,
433436
return devm_led_classdev_multicolor_register_ext(chip->dev, &led->mcdev, init_data);
434437
}
435438

436-
static int ktd202x_setup_led_single(struct ktd202x *chip, struct device_node *np,
439+
static int ktd202x_setup_led_single(struct ktd202x *chip, struct fwnode_handle *fwnode,
437440
struct ktd202x_led *led, struct led_init_data *init_data)
438441
{
439442
struct led_classdev *cdev;
440443
u32 reg;
441444
int ret;
442445

443-
ret = of_property_read_u32(np, "reg", &reg);
446+
ret = fwnode_property_read_u32(fwnode, "reg", &reg);
444447
if (ret != 0 || reg >= chip->num_leds) {
445-
dev_err(chip->dev, "invalid 'reg' of %pOFn\n", np);
448+
dev_err(chip->dev, "invalid 'reg' of %pfw\n", fwnode);
446449
return -EINVAL;
447450
}
448451
led->index = reg;
@@ -454,7 +457,7 @@ static int ktd202x_setup_led_single(struct ktd202x *chip, struct device_node *np
454457
return devm_led_classdev_register_ext(chip->dev, &led->cdev, init_data);
455458
}
456459

457-
static int ktd202x_add_led(struct ktd202x *chip, struct device_node *np, unsigned int index)
460+
static int ktd202x_add_led(struct ktd202x *chip, struct fwnode_handle *fwnode, unsigned int index)
458461
{
459462
struct ktd202x_led *led = &chip->leds[index];
460463
struct led_init_data init_data = {};
@@ -463,21 +466,21 @@ static int ktd202x_add_led(struct ktd202x *chip, struct device_node *np, unsigne
463466
int ret;
464467

465468
/* Color property is optional in single color case */
466-
ret = of_property_read_u32(np, "color", &color);
469+
ret = fwnode_property_read_u32(fwnode, "color", &color);
467470
if (ret < 0 && ret != -EINVAL) {
468-
dev_err(chip->dev, "failed to parse 'color' of %pOF\n", np);
471+
dev_err(chip->dev, "failed to parse 'color' of %pfw\n", fwnode);
469472
return ret;
470473
}
471474

472475
led->chip = chip;
473-
init_data.fwnode = of_fwnode_handle(np);
476+
init_data.fwnode = fwnode;
474477

475478
if (color == LED_COLOR_ID_RGB) {
476479
cdev = &led->mcdev.led_cdev;
477-
ret = ktd202x_setup_led_rgb(chip, np, led, &init_data);
480+
ret = ktd202x_setup_led_rgb(chip, fwnode, led, &init_data);
478481
} else {
479482
cdev = &led->cdev;
480-
ret = ktd202x_setup_led_single(chip, np, led, &init_data);
483+
ret = ktd202x_setup_led_single(chip, fwnode, led, &init_data);
481484
}
482485

483486
if (ret) {
@@ -490,15 +493,14 @@ static int ktd202x_add_led(struct ktd202x *chip, struct device_node *np, unsigne
490493
return 0;
491494
}
492495

493-
static int ktd202x_probe_dt(struct ktd202x *chip)
496+
static int ktd202x_probe_fw(struct ktd202x *chip)
494497
{
495-
struct device_node *np = dev_of_node(chip->dev), *child;
498+
struct fwnode_handle *child;
499+
struct device *dev = chip->dev;
496500
int count;
497501
int i = 0;
498502

499-
chip->num_leds = (int)(unsigned long)of_device_get_match_data(chip->dev);
500-
501-
count = of_get_available_child_count(np);
503+
count = device_get_child_node_count(dev);
502504
if (!count || count > chip->num_leds)
503505
return -EINVAL;
504506

@@ -507,11 +509,11 @@ static int ktd202x_probe_dt(struct ktd202x *chip)
507509
/* Allow the device to execute the complete reset */
508510
usleep_range(200, 300);
509511

510-
for_each_available_child_of_node(np, child) {
512+
device_for_each_child_node(dev, child) {
511513
int ret = ktd202x_add_led(chip, child, i);
512514

513515
if (ret) {
514-
of_node_put(child);
516+
fwnode_handle_put(child);
515517
return ret;
516518
}
517519
i++;
@@ -554,6 +556,12 @@ static int ktd202x_probe(struct i2c_client *client)
554556
return ret;
555557
}
556558

559+
ret = devm_mutex_init(dev, &chip->mutex);
560+
if (ret)
561+
return ret;
562+
563+
chip->num_leds = (unsigned long)i2c_get_match_data(client);
564+
557565
chip->regulators[0].supply = "vin";
558566
chip->regulators[1].supply = "vio";
559567
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(chip->regulators), chip->regulators);
@@ -568,7 +576,7 @@ static int ktd202x_probe(struct i2c_client *client)
568576
return ret;
569577
}
570578

571-
ret = ktd202x_probe_dt(chip);
579+
ret = ktd202x_probe_fw(chip);
572580
if (ret < 0) {
573581
regulator_bulk_disable(ARRAY_SIZE(chip->regulators), chip->regulators);
574582
return ret;
@@ -580,8 +588,6 @@ static int ktd202x_probe(struct i2c_client *client)
580588
return ret;
581589
}
582590

583-
mutex_init(&chip->mutex);
584-
585591
return 0;
586592
}
587593

@@ -590,8 +596,6 @@ static void ktd202x_remove(struct i2c_client *client)
590596
struct ktd202x *chip = i2c_get_clientdata(client);
591597

592598
ktd202x_chip_disable(chip);
593-
594-
mutex_destroy(&chip->mutex);
595599
}
596600

597601
static void ktd202x_shutdown(struct i2c_client *client)
@@ -602,10 +606,17 @@ static void ktd202x_shutdown(struct i2c_client *client)
602606
regmap_write(chip->regmap, KTD202X_REG_RESET_CONTROL, KTD202X_RSTR_RESET);
603607
}
604608

609+
static const struct i2c_device_id ktd202x_id[] = {
610+
{"ktd2026", KTD2026_NUM_LEDS},
611+
{"ktd2027", KTD2027_NUM_LEDS},
612+
{}
613+
};
614+
MODULE_DEVICE_TABLE(i2c, ktd202x_id);
615+
605616
static const struct of_device_id ktd202x_match_table[] = {
606617
{ .compatible = "kinetic,ktd2026", .data = (void *)KTD2026_NUM_LEDS },
607618
{ .compatible = "kinetic,ktd2027", .data = (void *)KTD2027_NUM_LEDS },
608-
{},
619+
{}
609620
};
610621
MODULE_DEVICE_TABLE(of, ktd202x_match_table);
611622

@@ -617,6 +628,7 @@ static struct i2c_driver ktd202x_driver = {
617628
.probe = ktd202x_probe,
618629
.remove = ktd202x_remove,
619630
.shutdown = ktd202x_shutdown,
631+
.id_table = ktd202x_id,
620632
};
621633
module_i2c_driver(ktd202x_driver);
622634

drivers/power/supply/power_supply_leds.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
static void power_supply_update_bat_leds(struct power_supply *psy)
2323
{
2424
union power_supply_propval status;
25+
unsigned int intensity_green[3] = { 0, 255, 0 };
26+
unsigned int intensity_orange[3] = { 255, 128, 0 };
2527

2628
if (power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
2729
return;
@@ -36,19 +38,29 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
3638
/* Going from blink to LED on requires a LED_OFF event to stop blink */
3739
led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF);
3840
led_trigger_event(psy->charging_blink_full_solid_trig, LED_FULL);
41+
led_mc_trigger_event(psy->charging_orange_full_green_trig,
42+
intensity_green,
43+
ARRAY_SIZE(intensity_green),
44+
LED_FULL);
3945
break;
4046
case POWER_SUPPLY_STATUS_CHARGING:
4147
led_trigger_event(psy->charging_full_trig, LED_FULL);
4248
led_trigger_event(psy->charging_trig, LED_FULL);
4349
led_trigger_event(psy->full_trig, LED_OFF);
4450
led_trigger_blink(psy->charging_blink_full_solid_trig, 0, 0);
51+
led_mc_trigger_event(psy->charging_orange_full_green_trig,
52+
intensity_orange,
53+
ARRAY_SIZE(intensity_orange),
54+
LED_FULL);
4555
break;
4656
default:
4757
led_trigger_event(psy->charging_full_trig, LED_OFF);
4858
led_trigger_event(psy->charging_trig, LED_OFF);
4959
led_trigger_event(psy->full_trig, LED_OFF);
5060
led_trigger_event(psy->charging_blink_full_solid_trig,
5161
LED_OFF);
62+
led_trigger_event(psy->charging_orange_full_green_trig,
63+
LED_OFF);
5264
break;
5365
}
5466
}
@@ -74,6 +86,11 @@ static int power_supply_create_bat_triggers(struct power_supply *psy)
7486
if (!psy->charging_blink_full_solid_trig_name)
7587
goto charging_blink_full_solid_failed;
7688

89+
psy->charging_orange_full_green_trig_name = kasprintf(GFP_KERNEL,
90+
"%s-charging-orange-full-green", psy->desc->name);
91+
if (!psy->charging_orange_full_green_trig_name)
92+
goto charging_red_full_green_failed;
93+
7794
led_trigger_register_simple(psy->charging_full_trig_name,
7895
&psy->charging_full_trig);
7996
led_trigger_register_simple(psy->charging_trig_name,
@@ -82,9 +99,13 @@ static int power_supply_create_bat_triggers(struct power_supply *psy)
8299
&psy->full_trig);
83100
led_trigger_register_simple(psy->charging_blink_full_solid_trig_name,
84101
&psy->charging_blink_full_solid_trig);
102+
led_trigger_register_simple(psy->charging_orange_full_green_trig_name,
103+
&psy->charging_orange_full_green_trig);
85104

86105
return 0;
87106

107+
charging_red_full_green_failed:
108+
kfree(psy->charging_blink_full_solid_trig_name);
88109
charging_blink_full_solid_failed:
89110
kfree(psy->full_trig_name);
90111
full_failed:
@@ -101,10 +122,12 @@ static void power_supply_remove_bat_triggers(struct power_supply *psy)
101122
led_trigger_unregister_simple(psy->charging_trig);
102123
led_trigger_unregister_simple(psy->full_trig);
103124
led_trigger_unregister_simple(psy->charging_blink_full_solid_trig);
125+
led_trigger_unregister_simple(psy->charging_orange_full_green_trig);
104126
kfree(psy->charging_blink_full_solid_trig_name);
105127
kfree(psy->full_trig_name);
106128
kfree(psy->charging_trig_name);
107129
kfree(psy->charging_full_trig_name);
130+
kfree(psy->charging_orange_full_green_trig_name);
108131
}
109132

110133
/* Generated power specific LEDs triggers. */

0 commit comments

Comments
 (0)