···503503 ret = led_classdev_next_name(proposed_name, final_name, sizeof(final_name));504504 if (ret < 0)505505 return ret;506506+ else if (ret && led_cdev->flags & LED_REJECT_NAME_CONFLICT)507507+ return -EEXIST;508508+ else if (ret)509509+ dev_warn(parent, "Led %s renamed to %s due to name collision\n",510510+ proposed_name, final_name);506511507512 if (led_cdev->color >= LED_COLOR_ID_MAX)508513 dev_warn(parent, "LED %s color identifier out of range\n", final_name);···522517 }523518 if (init_data && init_data->fwnode)524519 device_set_node(led_cdev->dev, init_data->fwnode);525525-526526- if (ret)527527- dev_warn(parent, "Led %s renamed to %s due to name collision",528528- proposed_name, dev_name(led_cdev->dev));529520530521 if (led_cdev->flags & LED_BRIGHT_HW_CHANGED) {531522 ret = led_add_brightness_hw_changed(led_cdev);
+31
drivers/leds/led-core.c
···88 */991010#include <linux/kernel.h>1111+#include <linux/led-class-multicolor.h>1112#include <linux/leds.h>1213#include <linux/list.h>1314#include <linux/module.h>···361360 return __led_set_brightness_blocking(led_cdev, led_cdev->brightness);362361}363362EXPORT_SYMBOL_GPL(led_set_brightness_sync);363363+364364+/*365365+ * This is a led-core function because just like led_set_brightness()366366+ * it is used in the kernel by e.g. triggers.367367+ */368368+void led_mc_set_brightness(struct led_classdev *led_cdev,369369+ unsigned int *intensity_value, unsigned int num_colors,370370+ unsigned int brightness)371371+{372372+ struct led_classdev_mc *mcled_cdev;373373+ unsigned int i;374374+375375+ if (!(led_cdev->flags & LED_MULTI_COLOR)) {376376+ dev_err_once(led_cdev->dev, "error not a multi-color LED\n");377377+ return;378378+ }379379+380380+ mcled_cdev = lcdev_to_mccdev(led_cdev);381381+ if (num_colors != mcled_cdev->num_colors) {382382+ dev_err_once(led_cdev->dev, "error num_colors mismatch %u != %u\n",383383+ num_colors, mcled_cdev->num_colors);384384+ return;385385+ }386386+387387+ for (i = 0; i < mcled_cdev->num_colors; i++)388388+ mcled_cdev->subled_info[i].intensity = intensity_value[i];389389+390390+ led_set_brightness(led_cdev, brightness);391391+}392392+EXPORT_SYMBOL_GPL(led_mc_set_brightness);364393365394int led_update_brightness(struct led_classdev *led_cdev)366395{
+20
drivers/leds/led-triggers.c
···396396}397397EXPORT_SYMBOL_GPL(led_trigger_event);398398399399+void led_mc_trigger_event(struct led_trigger *trig,400400+ unsigned int *intensity_value, unsigned int num_colors,401401+ enum led_brightness brightness)402402+{403403+ struct led_classdev *led_cdev;404404+405405+ if (!trig)406406+ return;407407+408408+ rcu_read_lock();409409+ list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list) {410410+ if (!(led_cdev->flags & LED_MULTI_COLOR))411411+ continue;412412+413413+ led_mc_set_brightness(led_cdev, intensity_value, num_colors, brightness);414414+ }415415+ rcu_read_unlock();416416+}417417+EXPORT_SYMBOL_GPL(led_mc_trigger_event);418418+399419static void led_trigger_blink_setup(struct led_trigger *trig,400420 unsigned long delay_on,401421 unsigned long delay_off,
-1
drivers/leds/rgb/Kconfig
···1717config LEDS_KTD202X1818 tristate "LED support for KTD202x Chips"1919 depends on I2C2020- depends on OF2120 select REGMAP_I2C2221 help2322 This option enables support for the Kinetic KTD2026/KTD2027
+46-34
drivers/leds/rgb/leds-ktd202x.c
···9999 struct device *dev;100100 struct regmap *regmap;101101 bool enabled;102102- int num_leds;102102+ unsigned long num_leds;103103 struct ktd202x_led leds[] __counted_by(num_leds);104104};105105···381381 mc->num_colors);382382}383383384384-static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct device_node *np,384384+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{387387+ struct fwnode_handle *child;387388 struct led_classdev *cdev;388388- struct device_node *child;389389 struct mc_subled *info;390390 int num_channels;391391 int i = 0;392392393393- num_channels = of_get_available_child_count(np);393393+ num_channels = 0;394394+ fwnode_for_each_available_child_node(fwnode, child)395395+ num_channels++;396396+394397 if (!num_channels || num_channels > chip->num_leds)395398 return -EINVAL;396399···401398 if (!info)402399 return -ENOMEM;403400404404- for_each_available_child_of_node(np, child) {401401+ fwnode_for_each_available_child_node(fwnode, child) {405402 u32 mono_color;406403 u32 reg;407404 int ret;408405409409- ret = of_property_read_u32(child, "reg", ®);406406+ ret = fwnode_property_read_u32(child, "reg", ®);410407 if (ret != 0 || reg >= chip->num_leds) {411411- dev_err(chip->dev, "invalid 'reg' of %pOFn\n", child);412412- of_node_put(child);413413- return -EINVAL;408408+ dev_err(chip->dev, "invalid 'reg' of %pfw\n", child);409409+ fwnode_handle_put(child);410410+ return ret;414411 }415412416416- ret = of_property_read_u32(child, "color", &mono_color);413413+ ret = fwnode_property_read_u32(child, "color", &mono_color);417414 if (ret < 0 && ret != -EINVAL) {418418- dev_err(chip->dev, "failed to parse 'color' of %pOF\n", child);419419- of_node_put(child);415415+ dev_err(chip->dev, "failed to parse 'color' of %pfw\n", child);416416+ fwnode_handle_put(child);420417 return ret;421418 }422419···436433 return devm_led_classdev_multicolor_register_ext(chip->dev, &led->mcdev, init_data);437434}438435439439-static int ktd202x_setup_led_single(struct ktd202x *chip, struct device_node *np,436436+static int ktd202x_setup_led_single(struct ktd202x *chip, struct fwnode_handle *fwnode,440437 struct ktd202x_led *led, struct led_init_data *init_data)441438{442439 struct led_classdev *cdev;443440 u32 reg;444441 int ret;445442446446- ret = of_property_read_u32(np, "reg", ®);443443+ ret = fwnode_property_read_u32(fwnode, "reg", ®);447444 if (ret != 0 || reg >= chip->num_leds) {448448- dev_err(chip->dev, "invalid 'reg' of %pOFn\n", np);445445+ dev_err(chip->dev, "invalid 'reg' of %pfw\n", fwnode);449446 return -EINVAL;450447 }451448 led->index = reg;···457454 return devm_led_classdev_register_ext(chip->dev, &led->cdev, init_data);458455}459456460460-static int ktd202x_add_led(struct ktd202x *chip, struct device_node *np, unsigned int index)457457+static int ktd202x_add_led(struct ktd202x *chip, struct fwnode_handle *fwnode, unsigned int index)461458{462459 struct ktd202x_led *led = &chip->leds[index];463460 struct led_init_data init_data = {};···466463 int ret;467464468465 /* Color property is optional in single color case */469469- ret = of_property_read_u32(np, "color", &color);466466+ ret = fwnode_property_read_u32(fwnode, "color", &color);470467 if (ret < 0 && ret != -EINVAL) {471471- dev_err(chip->dev, "failed to parse 'color' of %pOF\n", np);468468+ dev_err(chip->dev, "failed to parse 'color' of %pfw\n", fwnode);472469 return ret;473470 }474471475472 led->chip = chip;476476- init_data.fwnode = of_fwnode_handle(np);473473+ init_data.fwnode = fwnode;477474478475 if (color == LED_COLOR_ID_RGB) {479476 cdev = &led->mcdev.led_cdev;480480- ret = ktd202x_setup_led_rgb(chip, np, led, &init_data);477477+ ret = ktd202x_setup_led_rgb(chip, fwnode, led, &init_data);481478 } else {482479 cdev = &led->cdev;483483- ret = ktd202x_setup_led_single(chip, np, led, &init_data);480480+ ret = ktd202x_setup_led_single(chip, fwnode, led, &init_data);484481 }485482486483 if (ret) {···493490 return 0;494491}495492496496-static int ktd202x_probe_dt(struct ktd202x *chip)493493+static int ktd202x_probe_fw(struct ktd202x *chip)497494{498498- struct device_node *np = dev_of_node(chip->dev), *child;495495+ struct fwnode_handle *child;496496+ struct device *dev = chip->dev;499497 int count;500498 int i = 0;501499502502- chip->num_leds = (int)(unsigned long)of_device_get_match_data(chip->dev);503503-504504- count = of_get_available_child_count(np);500500+ count = device_get_child_node_count(dev);505501 if (!count || count > chip->num_leds)506502 return -EINVAL;507503···509507 /* Allow the device to execute the complete reset */510508 usleep_range(200, 300);511509512512- for_each_available_child_of_node(np, child) {510510+ device_for_each_child_node(dev, child) {513511 int ret = ktd202x_add_led(chip, child, i);514512515513 if (ret) {516516- of_node_put(child);514514+ fwnode_handle_put(child);517515 return ret;518516 }519517 i++;···556554 return ret;557555 }558556557557+ ret = devm_mutex_init(dev, &chip->mutex);558558+ if (ret)559559+ return ret;560560+561561+ chip->num_leds = (unsigned long)i2c_get_match_data(client);562562+559563 chip->regulators[0].supply = "vin";560564 chip->regulators[1].supply = "vio";561565 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(chip->regulators), chip->regulators);···576568 return ret;577569 }578570579579- ret = ktd202x_probe_dt(chip);571571+ ret = ktd202x_probe_fw(chip);580572 if (ret < 0) {581573 regulator_bulk_disable(ARRAY_SIZE(chip->regulators), chip->regulators);582574 return ret;···588580 return ret;589581 }590582591591- mutex_init(&chip->mutex);592592-593583 return 0;594584}595585···596590 struct ktd202x *chip = i2c_get_clientdata(client);597591598592 ktd202x_chip_disable(chip);599599-600600- mutex_destroy(&chip->mutex);601593}602594603595static void ktd202x_shutdown(struct i2c_client *client)···606602 regmap_write(chip->regmap, KTD202X_REG_RESET_CONTROL, KTD202X_RSTR_RESET);607603}608604605605+static const struct i2c_device_id ktd202x_id[] = {606606+ {"ktd2026", KTD2026_NUM_LEDS},607607+ {"ktd2027", KTD2027_NUM_LEDS},608608+ {}609609+};610610+MODULE_DEVICE_TABLE(i2c, ktd202x_id);611611+609612static const struct of_device_id ktd202x_match_table[] = {610613 { .compatible = "kinetic,ktd2026", .data = (void *)KTD2026_NUM_LEDS },611614 { .compatible = "kinetic,ktd2027", .data = (void *)KTD2027_NUM_LEDS },612612- {},615615+ {}613616};614617MODULE_DEVICE_TABLE(of, ktd202x_match_table);615618···628617 .probe = ktd202x_probe,629618 .remove = ktd202x_remove,630619 .shutdown = ktd202x_shutdown,620620+ .id_table = ktd202x_id,631621};632622module_i2c_driver(ktd202x_driver);633623
···150150151151config CROS_KBD_LED_BACKLIGHT152152 tristate "Backlight LED support for Chrome OS keyboards"153153- depends on LEDS_CLASS && (ACPI || CROS_EC)153153+ depends on LEDS_CLASS && (ACPI || CROS_EC || MFD_CROS_EC_DEV)154154 help155155 This option enables support for the keyboard backlight LEDs on156156 select Chrome OS systems.
···2222static void power_supply_update_bat_leds(struct power_supply *psy)2323{2424 union power_supply_propval status;2525+ unsigned int intensity_green[3] = { 0, 255, 0 };2626+ unsigned int intensity_orange[3] = { 255, 128, 0 };25272628 if (power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))2729 return;···3836 /* Going from blink to LED on requires a LED_OFF event to stop blink */3937 led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF);4038 led_trigger_event(psy->charging_blink_full_solid_trig, LED_FULL);3939+ led_mc_trigger_event(psy->charging_orange_full_green_trig,4040+ intensity_green,4141+ ARRAY_SIZE(intensity_green),4242+ LED_FULL);4143 break;4244 case POWER_SUPPLY_STATUS_CHARGING:4345 led_trigger_event(psy->charging_full_trig, LED_FULL);4446 led_trigger_event(psy->charging_trig, LED_FULL);4547 led_trigger_event(psy->full_trig, LED_OFF);4648 led_trigger_blink(psy->charging_blink_full_solid_trig, 0, 0);4949+ led_mc_trigger_event(psy->charging_orange_full_green_trig,5050+ intensity_orange,5151+ ARRAY_SIZE(intensity_orange),5252+ LED_FULL);4753 break;4854 default:4955 led_trigger_event(psy->charging_full_trig, LED_OFF);5056 led_trigger_event(psy->charging_trig, LED_OFF);5157 led_trigger_event(psy->full_trig, LED_OFF);5258 led_trigger_event(psy->charging_blink_full_solid_trig,5959+ LED_OFF);6060+ led_trigger_event(psy->charging_orange_full_green_trig,5361 LED_OFF);5462 break;5563 }···8674 if (!psy->charging_blink_full_solid_trig_name)8775 goto charging_blink_full_solid_failed;88767777+ psy->charging_orange_full_green_trig_name = kasprintf(GFP_KERNEL,7878+ "%s-charging-orange-full-green", psy->desc->name);7979+ if (!psy->charging_orange_full_green_trig_name)8080+ goto charging_red_full_green_failed;8181+8982 led_trigger_register_simple(psy->charging_full_trig_name,9083 &psy->charging_full_trig);9184 led_trigger_register_simple(psy->charging_trig_name,···9982 &psy->full_trig);10083 led_trigger_register_simple(psy->charging_blink_full_solid_trig_name,10184 &psy->charging_blink_full_solid_trig);8585+ led_trigger_register_simple(psy->charging_orange_full_green_trig_name,8686+ &psy->charging_orange_full_green_trig);1028710388 return 0;104899090+charging_red_full_green_failed:9191+ kfree(psy->charging_blink_full_solid_trig_name);10592charging_blink_full_solid_failed:10693 kfree(psy->full_trig_name);10794full_failed:···122101 led_trigger_unregister_simple(psy->charging_trig);123102 led_trigger_unregister_simple(psy->full_trig);124103 led_trigger_unregister_simple(psy->charging_blink_full_solid_trig);104104+ led_trigger_unregister_simple(psy->charging_orange_full_green_trig);125105 kfree(psy->charging_blink_full_solid_trig_name);126106 kfree(psy->full_trig_name);127107 kfree(psy->charging_trig_name);128108 kfree(psy->charging_full_trig_name);109109+ kfree(psy->charging_orange_full_green_trig_name);129110}130111131112/* Generated power specific LEDs triggers. */
+27
include/linux/leds.h
···107107#define LED_BRIGHT_HW_CHANGED BIT(21)108108#define LED_RETAIN_AT_SHUTDOWN BIT(22)109109#define LED_INIT_DEFAULT_TRIGGER BIT(23)110110+#define LED_REJECT_NAME_CONFLICT BIT(24)111111+#define LED_MULTI_COLOR BIT(25)110112111113 /* set_brightness_work / blink_timer flags, atomic, private. */112114 unsigned long work_flags;···376374int led_set_brightness_sync(struct led_classdev *led_cdev, unsigned int value);377375378376/**377377+ * led_mc_set_brightness - set mc LED color intensity values and brightness378378+ * @led_cdev: the LED to set379379+ * @intensity_value: array of per color intensity values to set380380+ * @num_colors: amount of entries in intensity_value array381381+ * @brightness: the brightness to set the LED to382382+ *383383+ * Set a multi-color LED's per color intensity values and brightness.384384+ * If necessary, this cancels the software blink timer. This function is385385+ * guaranteed not to sleep.386386+ *387387+ * Calling this function on a non multi-color led_classdev or with the wrong388388+ * num_colors value is an error. In this case an error will be logged once389389+ * and the call will do nothing.390390+ */391391+void led_mc_set_brightness(struct led_classdev *led_cdev,392392+ unsigned int *intensity_value, unsigned int num_colors,393393+ unsigned int brightness);394394+395395+/**379396 * led_update_brightness - update LED brightness380397 * @led_cdev: the LED to query381398 *···521500 struct led_trigger **trigger);522501void led_trigger_unregister_simple(struct led_trigger *trigger);523502void led_trigger_event(struct led_trigger *trigger, enum led_brightness event);503503+void led_mc_trigger_event(struct led_trigger *trig,504504+ unsigned int *intensity_value, unsigned int num_colors,505505+ enum led_brightness brightness);524506void led_trigger_blink(struct led_trigger *trigger, unsigned long delay_on,525507 unsigned long delay_off);526508void led_trigger_blink_oneshot(struct led_trigger *trigger,···566542static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {}567543static inline void led_trigger_event(struct led_trigger *trigger,568544 enum led_brightness event) {}545545+static inline void led_mc_trigger_event(struct led_trigger *trig,546546+ unsigned int *intensity_value, unsigned int num_colors,547547+ enum led_brightness brightness) {}569548static inline void led_trigger_blink(struct led_trigger *trigger,570549 unsigned long delay_on,571550 unsigned long delay_off) {}