Skip to content

Commit 3d3d65b

Browse files
OsterlaDpavelmachek
authored andcommitted
leds: pwm: add support for default-state device property
This patch adds support for "default-state" devicetree property, which allows to defer pwm init to first use of led. This allows to configure the PWM early in bootloader to let the LED blink until an application in Linux userspace sets something different. Signed-off-by: Denis Osterland-Heim <[email protected]> Signed-off-by: Pavel Machek <[email protected]>
1 parent 791bc41 commit 3d3d65b

File tree

1 file changed

+43
-6
lines changed

1 file changed

+43
-6
lines changed

drivers/leds/leds-pwm.c

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
#include <linux/err.h>
1818
#include <linux/pwm.h>
1919
#include <linux/slab.h>
20+
#include "leds.h"
2021

2122
struct led_pwm {
2223
const char *name;
2324
u8 active_low;
25+
u8 default_state;
2426
unsigned int max_brightness;
2527
};
2628

@@ -77,7 +79,38 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
7779

7880
led_data->cdev.brightness_set_blocking = led_pwm_set;
7981

80-
pwm_init_state(led_data->pwm, &led_data->pwmstate);
82+
/* init PWM state */
83+
switch (led->default_state) {
84+
case LEDS_DEFSTATE_KEEP:
85+
pwm_get_state(led_data->pwm, &led_data->pwmstate);
86+
if (led_data->pwmstate.period)
87+
break;
88+
led->default_state = LEDS_DEFSTATE_OFF;
89+
dev_warn(dev,
90+
"failed to read period for %s, default to off",
91+
led->name);
92+
fallthrough;
93+
default:
94+
pwm_init_state(led_data->pwm, &led_data->pwmstate);
95+
break;
96+
}
97+
98+
/* set brightness */
99+
switch (led->default_state) {
100+
case LEDS_DEFSTATE_ON:
101+
led_data->cdev.brightness = led->max_brightness;
102+
break;
103+
case LEDS_DEFSTATE_KEEP:
104+
{
105+
uint64_t brightness;
106+
107+
brightness = led->max_brightness;
108+
brightness *= led_data->pwmstate.duty_cycle;
109+
do_div(brightness, led_data->pwmstate.period);
110+
led_data->cdev.brightness = brightness;
111+
}
112+
break;
113+
}
81114

82115
ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data);
83116
if (ret) {
@@ -86,11 +119,13 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
86119
return ret;
87120
}
88121

89-
ret = led_pwm_set(&led_data->cdev, led_data->cdev.brightness);
90-
if (ret) {
91-
dev_err(dev, "failed to set led PWM value for %s: %d",
92-
led->name, ret);
93-
return ret;
122+
if (led->default_state != LEDS_DEFSTATE_KEEP) {
123+
ret = led_pwm_set(&led_data->cdev, led_data->cdev.brightness);
124+
if (ret) {
125+
dev_err(dev, "failed to set led PWM value for %s: %d",
126+
led->name, ret);
127+
return ret;
128+
}
94129
}
95130

96131
priv->num_leds++;
@@ -120,6 +155,8 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
120155
fwnode_property_read_u32(fwnode, "max-brightness",
121156
&led.max_brightness);
122157

158+
led.default_state = led_init_default_state_get(fwnode);
159+
123160
ret = led_pwm_add(dev, priv, &led, fwnode);
124161
if (ret)
125162
goto err_child_out;

0 commit comments

Comments
 (0)