leds: is31fl319x: Modernize registration

Use _ext version to have properties parsed to avoid needing to parse
them in the driver itself. More modern properties are recognized and
the LEDs can be referenced via phandle.

Due to the maximum current mechanics, LEDs are not registered right
in the first iteration over the nodes.

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
Link: https://patch.msgid.link/20260806-led-modern-v4-1-eed715baab2e@kemnade.info
Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
Andreas Kemnade 2026-08-06 13:51:36 +02:00 committed by Lee Jones
parent e36f882561
commit f8cca63a0a

View File

@ -98,7 +98,7 @@ struct is31fl319x_chip {
struct is31fl319x_chip *chip;
struct led_classdev cdev;
u32 max_microamp;
bool configured;
struct fwnode_handle *fwnode;
} leds[IS31FL319X_MAX_LEDS];
};
@ -363,31 +363,17 @@ static const struct of_device_id of_is31fl319x_match[] = {
};
MODULE_DEVICE_TABLE(of, of_is31fl319x_match);
static int is31fl319x_parse_child_fw(const struct device *dev,
const struct fwnode_handle *child,
struct is31fl319x_led *led,
struct is31fl319x_chip *is31)
static void is31_free_fwnode(void *data)
{
struct led_classdev *cdev = &led->cdev;
int ret;
struct is31fl319x_chip *is31 = data;
int i;
if (fwnode_property_read_string(child, "label", &cdev->name))
cdev->name = fwnode_get_name(child);
for (i = 0; i < is31->cdef->num_leds; i++) {
if (is31->leds[i].fwnode)
fwnode_handle_put(is31->leds[i].fwnode);
ret = fwnode_property_read_string(child, "linux,default-trigger", &cdev->default_trigger);
if (ret < 0 && ret != -EINVAL) /* is optional */
return ret;
led->max_microamp = is31->cdef->current_default;
ret = fwnode_property_read_u32(child, "led-max-microamp", &led->max_microamp);
if (!ret) {
if (led->max_microamp < is31->cdef->current_min)
return -EINVAL; /* not supported */
led->max_microamp = min(led->max_microamp,
is31->cdef->current_max);
is31->leds[i].fwnode = NULL;
}
return 0;
}
static int is31fl319x_parse_fw(struct device *dev, struct is31fl319x_chip *is31)
@ -402,6 +388,12 @@ static int is31fl319x_parse_fw(struct device *dev, struct is31fl319x_chip *is31)
"Failed to get shutdown gpio\n");
is31->cdef = device_get_match_data(dev);
if (!is31->cdef)
return -ENODEV;
ret = devm_add_action_or_reset(dev, is31_free_fwnode, is31);
if (ret)
return ret;
count = 0;
device_for_each_child_node_scoped(dev, child)
@ -427,14 +419,20 @@ static int is31fl319x_parse_fw(struct device *dev, struct is31fl319x_chip *is31)
led = &is31->leds[reg - 1];
if (led->configured)
if (led->fwnode)
return dev_err_probe(dev, -EINVAL, "led %u is already configured\n", reg);
ret = is31fl319x_parse_child_fw(dev, child, led, is31);
if (ret)
return dev_err_probe(dev, ret, "led %u DT parsing failed\n", reg);
led->max_microamp = is31->cdef->current_default;
ret = fwnode_property_read_u32(child, "led-max-microamp", &led->max_microamp);
if (!ret) {
if (led->max_microamp < is31->cdef->current_min)
return dev_err_probe(dev, -EINVAL, "invalid maximum current\n");
led->configured = true;
led->max_microamp = min(led->max_microamp,
is31->cdef->current_max);
}
led->fwnode = fwnode_handle_get(child);
}
is31->audio_gain_db = 0;
@ -531,7 +529,7 @@ static int is31fl319x_probe(struct i2c_client *client)
*/
aggregated_led_microamp = is31->cdef->current_max;
for (i = 0; i < is31->cdef->num_leds; i++)
if (is31->leds[i].configured &&
if (is31->leds[i].fwnode &&
is31->leds[i].max_microamp < aggregated_led_microamp)
aggregated_led_microamp = is31->leds[i].max_microamp;
@ -545,14 +543,17 @@ static int is31fl319x_probe(struct i2c_client *client)
for (i = 0; i < is31->cdef->num_leds; i++) {
struct is31fl319x_led *led = &is31->leds[i];
struct led_init_data init_data = {};
if (!led->configured)
if (!led->fwnode)
continue;
init_data.fwnode = led->fwnode;
led->chip = is31;
led->cdev.brightness_set_blocking = is31->cdef->brightness_set;
err = devm_led_classdev_register(&client->dev, &led->cdev);
err = devm_led_classdev_register_ext(&client->dev, &led->cdev, &init_data);
if (err < 0)
return err;
}