diff options
Diffstat (limited to 'drivers/leds/leds-pwm.c')
-rw-r--r-- | drivers/leds/leds-pwm.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index d71e9fa5c8de..6832180c1c54 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -17,10 +17,12 @@ #include <linux/err.h> #include <linux/pwm.h> #include <linux/slab.h> +#include "leds.h" struct led_pwm { const char *name; u8 active_low; + u8 default_state; unsigned int max_brightness; }; @@ -77,7 +79,38 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, led_data->cdev.brightness_set_blocking = led_pwm_set; - pwm_init_state(led_data->pwm, &led_data->pwmstate); + /* init PWM state */ + switch (led->default_state) { + case LEDS_DEFSTATE_KEEP: + pwm_get_state(led_data->pwm, &led_data->pwmstate); + if (led_data->pwmstate.period) + break; + led->default_state = LEDS_DEFSTATE_OFF; + dev_warn(dev, + "failed to read period for %s, default to off", + led->name); + fallthrough; + default: + pwm_init_state(led_data->pwm, &led_data->pwmstate); + break; + } + + /* set brightness */ + switch (led->default_state) { + case LEDS_DEFSTATE_ON: + led_data->cdev.brightness = led->max_brightness; + break; + case LEDS_DEFSTATE_KEEP: + { + uint64_t brightness; + + brightness = led->max_brightness; + brightness *= led_data->pwmstate.duty_cycle; + do_div(brightness, led_data->pwmstate.period); + led_data->cdev.brightness = brightness; + } + break; + } ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data); if (ret) { @@ -86,11 +119,13 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, return ret; } - ret = led_pwm_set(&led_data->cdev, led_data->cdev.brightness); - if (ret) { - dev_err(dev, "failed to set led PWM value for %s: %d", - led->name, ret); - return ret; + if (led->default_state != LEDS_DEFSTATE_KEEP) { + ret = led_pwm_set(&led_data->cdev, led_data->cdev.brightness); + if (ret) { + dev_err(dev, "failed to set led PWM value for %s: %d", + led->name, ret); + return ret; + } } priv->num_leds++; @@ -120,6 +155,8 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv) fwnode_property_read_u32(fwnode, "max-brightness", &led.max_brightness); + led.default_state = led_init_default_state_get(fwnode); + ret = led_pwm_add(dev, priv, &led, fwnode); if (ret) goto err_child_out; |