1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright 2005-2006 Openedhand Ltd.
7 * Author: Richard Purdie <rpurdie@openedhand.com>
10 #include <linux/kernel.h>
11 #include <linux/led-class-multicolor.h>
12 #include <linux/leds.h>
13 #include <linux/list.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
17 #include <linux/property.h>
18 #include <linux/rwsem.h>
19 #include <linux/slab.h>
20 #include <uapi/linux/uleds.h>
23 DECLARE_RWSEM(leds_list_lock
);
24 EXPORT_SYMBOL_GPL(leds_list_lock
);
27 EXPORT_SYMBOL_GPL(leds_list
);
29 static const char * const led_colors
[LED_COLOR_ID_MAX
] = {
30 [LED_COLOR_ID_WHITE
] = "white",
31 [LED_COLOR_ID_RED
] = "red",
32 [LED_COLOR_ID_GREEN
] = "green",
33 [LED_COLOR_ID_BLUE
] = "blue",
34 [LED_COLOR_ID_AMBER
] = "amber",
35 [LED_COLOR_ID_VIOLET
] = "violet",
36 [LED_COLOR_ID_YELLOW
] = "yellow",
37 [LED_COLOR_ID_IR
] = "ir",
38 [LED_COLOR_ID_MULTI
] = "multicolor",
39 [LED_COLOR_ID_RGB
] = "rgb",
40 [LED_COLOR_ID_PURPLE
] = "purple",
41 [LED_COLOR_ID_ORANGE
] = "orange",
42 [LED_COLOR_ID_PINK
] = "pink",
43 [LED_COLOR_ID_CYAN
] = "cyan",
44 [LED_COLOR_ID_LIME
] = "lime",
47 static int __led_set_brightness(struct led_classdev
*led_cdev
, unsigned int value
)
49 if (!led_cdev
->brightness_set
)
52 led_cdev
->brightness_set(led_cdev
, value
);
57 static int __led_set_brightness_blocking(struct led_classdev
*led_cdev
, unsigned int value
)
59 if (!led_cdev
->brightness_set_blocking
)
62 return led_cdev
->brightness_set_blocking(led_cdev
, value
);
65 static void led_timer_function(struct timer_list
*t
)
67 struct led_classdev
*led_cdev
= from_timer(led_cdev
, t
, blink_timer
);
68 unsigned long brightness
;
71 if (!led_cdev
->blink_delay_on
|| !led_cdev
->blink_delay_off
) {
72 led_set_brightness_nosleep(led_cdev
, LED_OFF
);
73 clear_bit(LED_BLINK_SW
, &led_cdev
->work_flags
);
77 if (test_and_clear_bit(LED_BLINK_ONESHOT_STOP
,
78 &led_cdev
->work_flags
)) {
79 clear_bit(LED_BLINK_SW
, &led_cdev
->work_flags
);
83 brightness
= led_get_brightness(led_cdev
);
85 /* Time to switch the LED on. */
86 if (test_and_clear_bit(LED_BLINK_BRIGHTNESS_CHANGE
,
87 &led_cdev
->work_flags
))
88 brightness
= led_cdev
->new_blink_brightness
;
90 brightness
= led_cdev
->blink_brightness
;
91 delay
= led_cdev
->blink_delay_on
;
93 /* Store the current brightness value to be able
94 * to restore it when the delay_off period is over.
96 led_cdev
->blink_brightness
= brightness
;
98 delay
= led_cdev
->blink_delay_off
;
101 led_set_brightness_nosleep(led_cdev
, brightness
);
103 /* Return in next iteration if led is in one-shot mode and we are in
104 * the final blink state so that the led is toggled each delay_on +
105 * delay_off milliseconds in worst case.
107 if (test_bit(LED_BLINK_ONESHOT
, &led_cdev
->work_flags
)) {
108 if (test_bit(LED_BLINK_INVERT
, &led_cdev
->work_flags
)) {
110 set_bit(LED_BLINK_ONESHOT_STOP
,
111 &led_cdev
->work_flags
);
114 set_bit(LED_BLINK_ONESHOT_STOP
,
115 &led_cdev
->work_flags
);
119 mod_timer(&led_cdev
->blink_timer
, jiffies
+ msecs_to_jiffies(delay
));
122 static void set_brightness_delayed_set_brightness(struct led_classdev
*led_cdev
,
127 ret
= __led_set_brightness(led_cdev
, value
);
128 if (ret
== -ENOTSUPP
) {
129 ret
= __led_set_brightness_blocking(led_cdev
, value
);
130 if (ret
== -ENOTSUPP
)
131 /* No back-end support to set a fixed brightness value */
135 /* LED HW might have been unplugged, therefore don't warn */
136 if (ret
== -ENODEV
&& led_cdev
->flags
& LED_UNREGISTERING
&&
137 led_cdev
->flags
& LED_HW_PLUGGABLE
)
141 dev_err(led_cdev
->dev
,
142 "Setting an LED's brightness failed (%d)\n", ret
);
145 static void set_brightness_delayed(struct work_struct
*ws
)
147 struct led_classdev
*led_cdev
=
148 container_of(ws
, struct led_classdev
, set_brightness_work
);
150 if (test_and_clear_bit(LED_BLINK_DISABLE
, &led_cdev
->work_flags
)) {
151 led_stop_software_blink(led_cdev
);
152 set_bit(LED_SET_BRIGHTNESS_OFF
, &led_cdev
->work_flags
);
156 * Triggers may call led_set_brightness(LED_OFF),
157 * led_set_brightness(LED_FULL) in quick succession to disable blinking
158 * and turn the LED on. Both actions may have been scheduled to run
159 * before this work item runs once. To make sure this works properly
160 * handle LED_SET_BRIGHTNESS_OFF first.
162 if (test_and_clear_bit(LED_SET_BRIGHTNESS_OFF
, &led_cdev
->work_flags
))
163 set_brightness_delayed_set_brightness(led_cdev
, LED_OFF
);
165 if (test_and_clear_bit(LED_SET_BRIGHTNESS
, &led_cdev
->work_flags
))
166 set_brightness_delayed_set_brightness(led_cdev
, led_cdev
->delayed_set_value
);
168 if (test_and_clear_bit(LED_SET_BLINK
, &led_cdev
->work_flags
)) {
169 unsigned long delay_on
= led_cdev
->delayed_delay_on
;
170 unsigned long delay_off
= led_cdev
->delayed_delay_off
;
172 led_blink_set(led_cdev
, &delay_on
, &delay_off
);
176 static void led_set_software_blink(struct led_classdev
*led_cdev
,
177 unsigned long delay_on
,
178 unsigned long delay_off
)
180 int current_brightness
;
182 current_brightness
= led_get_brightness(led_cdev
);
183 if (current_brightness
)
184 led_cdev
->blink_brightness
= current_brightness
;
185 if (!led_cdev
->blink_brightness
)
186 led_cdev
->blink_brightness
= led_cdev
->max_brightness
;
188 led_cdev
->blink_delay_on
= delay_on
;
189 led_cdev
->blink_delay_off
= delay_off
;
191 /* never on - just set to off */
193 led_set_brightness_nosleep(led_cdev
, LED_OFF
);
197 /* never off - just set to brightness */
199 led_set_brightness_nosleep(led_cdev
,
200 led_cdev
->blink_brightness
);
204 set_bit(LED_BLINK_SW
, &led_cdev
->work_flags
);
205 mod_timer(&led_cdev
->blink_timer
, jiffies
+ 1);
209 static void led_blink_setup(struct led_classdev
*led_cdev
,
210 unsigned long *delay_on
,
211 unsigned long *delay_off
)
213 if (!test_bit(LED_BLINK_ONESHOT
, &led_cdev
->work_flags
) &&
214 led_cdev
->blink_set
&&
215 !led_cdev
->blink_set(led_cdev
, delay_on
, delay_off
))
218 /* blink with 1 Hz as default if nothing specified */
219 if (!*delay_on
&& !*delay_off
)
220 *delay_on
= *delay_off
= 500;
222 led_set_software_blink(led_cdev
, *delay_on
, *delay_off
);
225 void led_init_core(struct led_classdev
*led_cdev
)
227 INIT_WORK(&led_cdev
->set_brightness_work
, set_brightness_delayed
);
229 timer_setup(&led_cdev
->blink_timer
, led_timer_function
, 0);
231 EXPORT_SYMBOL_GPL(led_init_core
);
233 void led_blink_set(struct led_classdev
*led_cdev
,
234 unsigned long *delay_on
,
235 unsigned long *delay_off
)
237 del_timer_sync(&led_cdev
->blink_timer
);
239 clear_bit(LED_BLINK_SW
, &led_cdev
->work_flags
);
240 clear_bit(LED_BLINK_ONESHOT
, &led_cdev
->work_flags
);
241 clear_bit(LED_BLINK_ONESHOT_STOP
, &led_cdev
->work_flags
);
243 led_blink_setup(led_cdev
, delay_on
, delay_off
);
245 EXPORT_SYMBOL_GPL(led_blink_set
);
247 void led_blink_set_oneshot(struct led_classdev
*led_cdev
,
248 unsigned long *delay_on
,
249 unsigned long *delay_off
,
252 if (test_bit(LED_BLINK_ONESHOT
, &led_cdev
->work_flags
) &&
253 timer_pending(&led_cdev
->blink_timer
))
256 set_bit(LED_BLINK_ONESHOT
, &led_cdev
->work_flags
);
257 clear_bit(LED_BLINK_ONESHOT_STOP
, &led_cdev
->work_flags
);
260 set_bit(LED_BLINK_INVERT
, &led_cdev
->work_flags
);
262 clear_bit(LED_BLINK_INVERT
, &led_cdev
->work_flags
);
264 led_blink_setup(led_cdev
, delay_on
, delay_off
);
266 EXPORT_SYMBOL_GPL(led_blink_set_oneshot
);
268 void led_blink_set_nosleep(struct led_classdev
*led_cdev
, unsigned long delay_on
,
269 unsigned long delay_off
)
271 /* If necessary delegate to a work queue task. */
272 if (led_cdev
->blink_set
&& led_cdev
->brightness_set_blocking
) {
273 led_cdev
->delayed_delay_on
= delay_on
;
274 led_cdev
->delayed_delay_off
= delay_off
;
275 set_bit(LED_SET_BLINK
, &led_cdev
->work_flags
);
276 queue_work(led_cdev
->wq
, &led_cdev
->set_brightness_work
);
280 led_blink_set(led_cdev
, &delay_on
, &delay_off
);
282 EXPORT_SYMBOL_GPL(led_blink_set_nosleep
);
284 void led_stop_software_blink(struct led_classdev
*led_cdev
)
286 del_timer_sync(&led_cdev
->blink_timer
);
287 led_cdev
->blink_delay_on
= 0;
288 led_cdev
->blink_delay_off
= 0;
289 clear_bit(LED_BLINK_SW
, &led_cdev
->work_flags
);
291 EXPORT_SYMBOL_GPL(led_stop_software_blink
);
293 void led_set_brightness(struct led_classdev
*led_cdev
, unsigned int brightness
)
296 * If software blink is active, delay brightness setting
297 * until the next timer tick.
299 if (test_bit(LED_BLINK_SW
, &led_cdev
->work_flags
)) {
301 * If we need to disable soft blinking delegate this to the
302 * work queue task to avoid problems in case we are called
303 * from hard irq context.
306 set_bit(LED_BLINK_DISABLE
, &led_cdev
->work_flags
);
307 queue_work(led_cdev
->wq
, &led_cdev
->set_brightness_work
);
309 set_bit(LED_BLINK_BRIGHTNESS_CHANGE
,
310 &led_cdev
->work_flags
);
311 led_cdev
->new_blink_brightness
= brightness
;
316 led_set_brightness_nosleep(led_cdev
, brightness
);
318 EXPORT_SYMBOL_GPL(led_set_brightness
);
320 void led_set_brightness_nopm(struct led_classdev
*led_cdev
, unsigned int value
)
322 /* Use brightness_set op if available, it is guaranteed not to sleep */
323 if (!__led_set_brightness(led_cdev
, value
))
327 * Brightness setting can sleep, delegate it to a work queue task.
328 * value 0 / LED_OFF is special, since it also disables hw-blinking
329 * (sw-blink disable is handled in led_set_brightness()).
330 * To avoid a hw-blink-disable getting lost when a second brightness
331 * change is done immediately afterwards (before the work runs),
332 * it uses a separate work_flag.
335 led_cdev
->delayed_set_value
= value
;
336 set_bit(LED_SET_BRIGHTNESS
, &led_cdev
->work_flags
);
338 clear_bit(LED_SET_BRIGHTNESS
, &led_cdev
->work_flags
);
339 clear_bit(LED_SET_BLINK
, &led_cdev
->work_flags
);
340 set_bit(LED_SET_BRIGHTNESS_OFF
, &led_cdev
->work_flags
);
343 queue_work(led_cdev
->wq
, &led_cdev
->set_brightness_work
);
345 EXPORT_SYMBOL_GPL(led_set_brightness_nopm
);
347 void led_set_brightness_nosleep(struct led_classdev
*led_cdev
, unsigned int value
)
349 led_cdev
->brightness
= min(value
, led_cdev
->max_brightness
);
351 if (led_cdev
->flags
& LED_SUSPENDED
)
354 led_set_brightness_nopm(led_cdev
, led_cdev
->brightness
);
356 EXPORT_SYMBOL_GPL(led_set_brightness_nosleep
);
358 int led_set_brightness_sync(struct led_classdev
*led_cdev
, unsigned int value
)
360 if (led_cdev
->blink_delay_on
|| led_cdev
->blink_delay_off
)
363 led_cdev
->brightness
= min(value
, led_cdev
->max_brightness
);
365 if (led_cdev
->flags
& LED_SUSPENDED
)
368 return __led_set_brightness_blocking(led_cdev
, led_cdev
->brightness
);
370 EXPORT_SYMBOL_GPL(led_set_brightness_sync
);
373 * This is a led-core function because just like led_set_brightness()
374 * it is used in the kernel by e.g. triggers.
376 void led_mc_set_brightness(struct led_classdev
*led_cdev
,
377 unsigned int *intensity_value
, unsigned int num_colors
,
378 unsigned int brightness
)
380 struct led_classdev_mc
*mcled_cdev
;
383 if (!(led_cdev
->flags
& LED_MULTI_COLOR
)) {
384 dev_err_once(led_cdev
->dev
, "error not a multi-color LED\n");
388 mcled_cdev
= lcdev_to_mccdev(led_cdev
);
389 if (num_colors
!= mcled_cdev
->num_colors
) {
390 dev_err_once(led_cdev
->dev
, "error num_colors mismatch %u != %u\n",
391 num_colors
, mcled_cdev
->num_colors
);
395 for (i
= 0; i
< mcled_cdev
->num_colors
; i
++)
396 mcled_cdev
->subled_info
[i
].intensity
= intensity_value
[i
];
398 led_set_brightness(led_cdev
, brightness
);
400 EXPORT_SYMBOL_GPL(led_mc_set_brightness
);
402 int led_update_brightness(struct led_classdev
*led_cdev
)
406 if (led_cdev
->brightness_get
) {
407 ret
= led_cdev
->brightness_get(led_cdev
);
411 led_cdev
->brightness
= ret
;
416 EXPORT_SYMBOL_GPL(led_update_brightness
);
418 u32
*led_get_default_pattern(struct led_classdev
*led_cdev
, unsigned int *size
)
420 struct fwnode_handle
*fwnode
= led_cdev
->dev
->fwnode
;
424 count
= fwnode_property_count_u32(fwnode
, "led-pattern");
428 pattern
= kcalloc(count
, sizeof(*pattern
), GFP_KERNEL
);
432 if (fwnode_property_read_u32_array(fwnode
, "led-pattern", pattern
, count
)) {
441 EXPORT_SYMBOL_GPL(led_get_default_pattern
);
443 /* Caller must ensure led_cdev->led_access held */
444 void led_sysfs_disable(struct led_classdev
*led_cdev
)
446 lockdep_assert_held(&led_cdev
->led_access
);
448 led_cdev
->flags
|= LED_SYSFS_DISABLE
;
450 EXPORT_SYMBOL_GPL(led_sysfs_disable
);
452 /* Caller must ensure led_cdev->led_access held */
453 void led_sysfs_enable(struct led_classdev
*led_cdev
)
455 lockdep_assert_held(&led_cdev
->led_access
);
457 led_cdev
->flags
&= ~LED_SYSFS_DISABLE
;
459 EXPORT_SYMBOL_GPL(led_sysfs_enable
);
461 static void led_parse_fwnode_props(struct device
*dev
,
462 struct fwnode_handle
*fwnode
,
463 struct led_properties
*props
)
470 if (fwnode_property_present(fwnode
, "label")) {
471 ret
= fwnode_property_read_string(fwnode
, "label", &props
->label
);
473 dev_err(dev
, "Error parsing 'label' property (%d)\n", ret
);
477 if (fwnode_property_present(fwnode
, "color")) {
478 ret
= fwnode_property_read_u32(fwnode
, "color", &props
->color
);
480 dev_err(dev
, "Error parsing 'color' property (%d)\n", ret
);
481 else if (props
->color
>= LED_COLOR_ID_MAX
)
482 dev_err(dev
, "LED color identifier out of range\n");
484 props
->color_present
= true;
488 if (!fwnode_property_present(fwnode
, "function"))
491 ret
= fwnode_property_read_string(fwnode
, "function", &props
->function
);
494 "Error parsing 'function' property (%d)\n",
498 if (!fwnode_property_present(fwnode
, "function-enumerator"))
501 ret
= fwnode_property_read_u32(fwnode
, "function-enumerator",
505 "Error parsing 'function-enumerator' property (%d)\n",
508 props
->func_enum_present
= true;
512 int led_compose_name(struct device
*dev
, struct led_init_data
*init_data
,
513 char *led_classdev_name
)
515 struct led_properties props
= {};
516 struct fwnode_handle
*fwnode
= init_data
->fwnode
;
517 const char *devicename
= init_data
->devicename
;
519 if (!led_classdev_name
)
522 led_parse_fwnode_props(dev
, fwnode
, &props
);
526 * If init_data.devicename is NULL, then it indicates that
527 * DT label should be used as-is for LED class device name.
528 * Otherwise the label is prepended with devicename to compose
529 * the final LED class device name.
532 strscpy(led_classdev_name
, props
.label
,
535 snprintf(led_classdev_name
, LED_MAX_NAME_SIZE
, "%s:%s",
536 devicename
, props
.label
);
538 } else if (props
.function
|| props
.color_present
) {
539 char tmp_buf
[LED_MAX_NAME_SIZE
];
541 if (props
.func_enum_present
) {
542 snprintf(tmp_buf
, LED_MAX_NAME_SIZE
, "%s:%s-%d",
543 props
.color_present
? led_colors
[props
.color
] : "",
544 props
.function
?: "", props
.func_enum
);
546 snprintf(tmp_buf
, LED_MAX_NAME_SIZE
, "%s:%s",
547 props
.color_present
? led_colors
[props
.color
] : "",
548 props
.function
?: "");
550 if (init_data
->devname_mandatory
) {
551 snprintf(led_classdev_name
, LED_MAX_NAME_SIZE
, "%s:%s",
552 devicename
, tmp_buf
);
554 strscpy(led_classdev_name
, tmp_buf
, LED_MAX_NAME_SIZE
);
557 } else if (init_data
->default_label
) {
559 dev_err(dev
, "Legacy LED naming requires devicename segment");
562 snprintf(led_classdev_name
, LED_MAX_NAME_SIZE
, "%s:%s",
563 devicename
, init_data
->default_label
);
564 } else if (is_of_node(fwnode
)) {
565 strscpy(led_classdev_name
, to_of_node(fwnode
)->name
,
572 EXPORT_SYMBOL_GPL(led_compose_name
);
574 const char *led_get_color_name(u8 color_id
)
576 if (color_id
>= ARRAY_SIZE(led_colors
))
579 return led_colors
[color_id
];
581 EXPORT_SYMBOL_GPL(led_get_color_name
);
583 enum led_default_state
led_init_default_state_get(struct fwnode_handle
*fwnode
)
585 const char *state
= NULL
;
587 if (!fwnode_property_read_string(fwnode
, "default-state", &state
)) {
588 if (!strcmp(state
, "keep"))
589 return LEDS_DEFSTATE_KEEP
;
590 if (!strcmp(state
, "on"))
591 return LEDS_DEFSTATE_ON
;
594 return LEDS_DEFSTATE_OFF
;
596 EXPORT_SYMBOL_GPL(led_init_default_state_get
);