aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/leds/common.txt30
-rw-r--r--drivers/leds/Kconfig10
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/led-class-flash.c486
-rw-r--r--drivers/leds/led-class.c9
-rw-r--r--drivers/leds/leds-gpio.c3
-rw-r--r--drivers/leds/leds-mc13783.c4
-rw-r--r--drivers/leds/leds.h3
-rw-r--r--include/linux/led-class-flash.h207
-rw-r--r--include/linux/leds.h3
10 files changed, 748 insertions, 8 deletions
diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
index 2d88816dd550..34811c57db69 100644
--- a/Documentation/devicetree/bindings/leds/common.txt
+++ b/Documentation/devicetree/bindings/leds/common.txt
@@ -1,6 +1,19 @@
1Common leds properties. 1Common leds properties.
2 2
3LED and flash LED devices provide the same basic functionality as current
4regulators, but extended with LED and flash LED specific features like
5blinking patterns, flash timeout, flash faults and external flash strobe mode.
6
7Many LED devices expose more than one current output that can be connected
8to one or more discrete LED component. Since the arrangement of connections
9can influence the way of the LED device initialization, the LED components
10have to be tightly coupled with the LED device binding. They are represented
11by child nodes of the parent LED device binding.
12
3Optional properties for child nodes: 13Optional properties for child nodes:
14- led-sources : List of device current outputs the LED is connected to. The
15 outputs are identified by the numbers that must be defined
16 in the LED device binding documentation.
4- label : The label for this LED. If omitted, the label is 17- label : The label for this LED. If omitted, the label is
5 taken from the node name (excluding the unit address). 18 taken from the node name (excluding the unit address).
6 19
@@ -14,6 +27,15 @@ Optional properties for child nodes:
14 "ide-disk" - LED indicates disk activity 27 "ide-disk" - LED indicates disk activity
15 "timer" - LED flashes at a fixed, configurable rate 28 "timer" - LED flashes at a fixed, configurable rate
16 29
30- max-microamp : maximum intensity in microamperes of the LED
31 (torch LED for flash devices)
32- flash-max-microamp : maximum intensity in microamperes of the
33 flash LED; it is mandatory if the LED should
34 support the flash mode
35- flash-timeout-us : timeout in microseconds after which the flash
36 LED is turned off
37
38
17Examples: 39Examples:
18 40
19system-status { 41system-status {
@@ -21,3 +43,11 @@ system-status {
21 linux,default-trigger = "heartbeat"; 43 linux,default-trigger = "heartbeat";
22 ... 44 ...
23}; 45};
46
47camera-flash {
48 label = "Flash";
49 led-sources = <0>, <1>;
50 max-microamp = <50000>;
51 flash-max-microamp = <320000>;
52 flash-timeout-us = <500000>;
53};
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a6c3d2f153f3..25b320d64e26 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -22,6 +22,16 @@ config LEDS_CLASS
22 This option enables the led sysfs class in /sys/class/leds. You'll 22 This option enables the led sysfs class in /sys/class/leds. You'll
23 need this to do anything useful with LEDs. If unsure, say N. 23 need this to do anything useful with LEDs. If unsure, say N.
24 24
25config LEDS_CLASS_FLASH
26 tristate "LED Flash Class Support"
27 depends on LEDS_CLASS
28 help
29 This option enables the flash led sysfs class in /sys/class/leds.
30 It wrapps LED Class and adds flash LEDs specific sysfs attributes
31 and kernel internal API to it. You'll need this to provide support
32 for the flash related features of a LED device. It can be built
33 as a module.
34
25comment "LED drivers" 35comment "LED drivers"
26 36
27config LEDS_88PM860X 37config LEDS_88PM860X
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 1c65a191d907..cbba921b6f1c 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -2,6 +2,7 @@
2# LED Core 2# LED Core
3obj-$(CONFIG_NEW_LEDS) += led-core.o 3obj-$(CONFIG_NEW_LEDS) += led-core.o
4obj-$(CONFIG_LEDS_CLASS) += led-class.o 4obj-$(CONFIG_LEDS_CLASS) += led-class.o
5obj-$(CONFIG_LEDS_CLASS_FLASH) += led-class-flash.o
5obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o 6obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
6 7
7# LED Platform Drivers 8# LED Platform Drivers
diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
new file mode 100644
index 000000000000..4a19fd44f93f
--- /dev/null
+++ b/drivers/leds/led-class-flash.c
@@ -0,0 +1,486 @@
1/*
2 * LED Flash class interface
3 *
4 * Copyright (C) 2015 Samsung Electronics Co., Ltd.
5 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/device.h>
13#include <linux/init.h>
14#include <linux/led-class-flash.h>
15#include <linux/leds.h>
16#include <linux/module.h>
17#include <linux/slab.h>
18#include "leds.h"
19
20#define has_flash_op(fled_cdev, op) \
21 (fled_cdev && fled_cdev->ops->op)
22
23#define call_flash_op(fled_cdev, op, args...) \
24 ((has_flash_op(fled_cdev, op)) ? \
25 (fled_cdev->ops->op(fled_cdev, args)) : \
26 -EINVAL)
27
28static const char * const led_flash_fault_names[] = {
29 "led-over-voltage",
30 "flash-timeout-exceeded",
31 "controller-over-temperature",
32 "controller-short-circuit",
33 "led-power-supply-over-current",
34 "indicator-led-fault",
35 "led-under-voltage",
36 "controller-under-voltage",
37 "led-over-temperature",
38};
39
40static ssize_t flash_brightness_store(struct device *dev,
41 struct device_attribute *attr, const char *buf, size_t size)
42{
43 struct led_classdev *led_cdev = dev_get_drvdata(dev);
44 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
45 unsigned long state;
46 ssize_t ret;
47
48 mutex_lock(&led_cdev->led_access);
49
50 if (led_sysfs_is_disabled(led_cdev)) {
51 ret = -EBUSY;
52 goto unlock;
53 }
54
55 ret = kstrtoul(buf, 10, &state);
56 if (ret)
57 goto unlock;
58
59 ret = led_set_flash_brightness(fled_cdev, state);
60 if (ret < 0)
61 goto unlock;
62
63 ret = size;
64unlock:
65 mutex_unlock(&led_cdev->led_access);
66 return ret;
67}
68
69static ssize_t flash_brightness_show(struct device *dev,
70 struct device_attribute *attr, char *buf)
71{
72 struct led_classdev *led_cdev = dev_get_drvdata(dev);
73 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
74
75 /* no lock needed for this */
76 led_update_flash_brightness(fled_cdev);
77
78 return sprintf(buf, "%u\n", fled_cdev->brightness.val);
79}
80static DEVICE_ATTR_RW(flash_brightness);
81
82static ssize_t max_flash_brightness_show(struct device *dev,
83 struct device_attribute *attr, char *buf)
84{
85 struct led_classdev *led_cdev = dev_get_drvdata(dev);
86 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
87
88 return sprintf(buf, "%u\n", fled_cdev->brightness.max);
89}
90static DEVICE_ATTR_RO(max_flash_brightness);
91
92static ssize_t flash_strobe_store(struct device *dev,
93 struct device_attribute *attr, const char *buf, size_t size)
94{
95 struct led_classdev *led_cdev = dev_get_drvdata(dev);
96 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
97 unsigned long state;
98 ssize_t ret = -EINVAL;
99
100 mutex_lock(&led_cdev->led_access);
101
102 if (led_sysfs_is_disabled(led_cdev)) {
103 ret = -EBUSY;
104 goto unlock;
105 }
106
107 ret = kstrtoul(buf, 10, &state);
108 if (ret)
109 goto unlock;
110
111 if (state < 0 || state > 1) {
112 ret = -EINVAL;
113 goto unlock;
114 }
115
116 ret = led_set_flash_strobe(fled_cdev, state);
117 if (ret < 0)
118 goto unlock;
119 ret = size;
120unlock:
121 mutex_unlock(&led_cdev->led_access);
122 return ret;
123}
124
125static ssize_t flash_strobe_show(struct device *dev,
126 struct device_attribute *attr, char *buf)
127{
128 struct led_classdev *led_cdev = dev_get_drvdata(dev);
129 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
130 bool state;
131 int ret;
132
133 /* no lock needed for this */
134 ret = led_get_flash_strobe(fled_cdev, &state);
135 if (ret < 0)
136 return ret;
137
138 return sprintf(buf, "%u\n", state);
139}
140static DEVICE_ATTR_RW(flash_strobe);
141
142static ssize_t flash_timeout_store(struct device *dev,
143 struct device_attribute *attr, const char *buf, size_t size)
144{
145 struct led_classdev *led_cdev = dev_get_drvdata(dev);
146 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
147 unsigned long flash_timeout;
148 ssize_t ret;
149
150 mutex_lock(&led_cdev->led_access);
151
152 if (led_sysfs_is_disabled(led_cdev)) {
153 ret = -EBUSY;
154 goto unlock;
155 }
156
157 ret = kstrtoul(buf, 10, &flash_timeout);
158 if (ret)
159 goto unlock;
160
161 ret = led_set_flash_timeout(fled_cdev, flash_timeout);
162 if (ret < 0)
163 goto unlock;
164
165 ret = size;
166unlock:
167 mutex_unlock(&led_cdev->led_access);
168 return ret;
169}
170
171static ssize_t flash_timeout_show(struct device *dev,
172 struct device_attribute *attr, char *buf)
173{
174 struct led_classdev *led_cdev = dev_get_drvdata(dev);
175 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
176
177 return sprintf(buf, "%u\n", fled_cdev->timeout.val);
178}
179static DEVICE_ATTR_RW(flash_timeout);
180
181static ssize_t max_flash_timeout_show(struct device *dev,
182 struct device_attribute *attr, char *buf)
183{
184 struct led_classdev *led_cdev = dev_get_drvdata(dev);
185 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
186
187 return sprintf(buf, "%u\n", fled_cdev->timeout.max);
188}
189static DEVICE_ATTR_RO(max_flash_timeout);
190
191static ssize_t flash_fault_show(struct device *dev,
192 struct device_attribute *attr, char *buf)
193{
194 struct led_classdev *led_cdev = dev_get_drvdata(dev);
195 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
196 u32 fault, mask = 0x1;
197 char *pbuf = buf;
198 int i, ret, buf_len;
199
200 ret = led_get_flash_fault(fled_cdev, &fault);
201 if (ret < 0)
202 return -EINVAL;
203
204 *buf = '\0';
205
206 for (i = 0; i < LED_NUM_FLASH_FAULTS; ++i) {
207 if (fault & mask) {
208 buf_len = sprintf(pbuf, "%s ",
209 led_flash_fault_names[i]);
210 pbuf += buf_len;
211 }
212 mask <<= 1;
213 }
214
215 return sprintf(buf, "%s\n", buf);
216}
217static DEVICE_ATTR_RO(flash_fault);
218
219static ssize_t available_sync_leds_show(struct device *dev,
220 struct device_attribute *attr, char *buf)
221{
222 struct led_classdev *led_cdev = dev_get_drvdata(dev);
223 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
224 char *pbuf = buf;
225 int i, buf_len;
226
227 buf_len = sprintf(pbuf, "[0: none] ");
228 pbuf += buf_len;
229
230 for (i = 0; i < fled_cdev->num_sync_leds; ++i) {
231 buf_len = sprintf(pbuf, "[%d: %s] ", i + 1,
232 fled_cdev->sync_leds[i]->led_cdev.name);
233 pbuf += buf_len;
234 }
235
236 return sprintf(buf, "%s\n", buf);
237}
238static DEVICE_ATTR_RO(available_sync_leds);
239
240static ssize_t flash_sync_strobe_store(struct device *dev,
241 struct device_attribute *attr, const char *buf, size_t size)
242{
243 struct led_classdev *led_cdev = dev_get_drvdata(dev);
244 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
245 unsigned long led_id;
246 ssize_t ret;
247
248 mutex_lock(&led_cdev->led_access);
249
250 if (led_sysfs_is_disabled(led_cdev)) {
251 ret = -EBUSY;
252 goto unlock;
253 }
254
255 ret = kstrtoul(buf, 10, &led_id);
256 if (ret)
257 goto unlock;
258
259 if (led_id > fled_cdev->num_sync_leds) {
260 ret = -ERANGE;
261 goto unlock;
262 }
263
264 fled_cdev->sync_led_id = led_id;
265
266 ret = size;
267unlock:
268 mutex_unlock(&led_cdev->led_access);
269 return ret;
270}
271
272static ssize_t flash_sync_strobe_show(struct device *dev,
273 struct device_attribute *attr, char *buf)
274{
275 struct led_classdev *led_cdev = dev_get_drvdata(dev);
276 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
277 int sled_id = fled_cdev->sync_led_id;
278 char *sync_led_name = "none";
279
280 if (fled_cdev->sync_led_id > 0)
281 sync_led_name = (char *)
282 fled_cdev->sync_leds[sled_id - 1]->led_cdev.name;
283
284 return sprintf(buf, "[%d: %s]\n", sled_id, sync_led_name);
285}
286static DEVICE_ATTR_RW(flash_sync_strobe);
287
288static struct attribute *led_flash_strobe_attrs[] = {
289 &dev_attr_flash_strobe.attr,
290 NULL,
291};
292
293static struct attribute *led_flash_timeout_attrs[] = {
294 &dev_attr_flash_timeout.attr,
295 &dev_attr_max_flash_timeout.attr,
296 NULL,
297};
298
299static struct attribute *led_flash_brightness_attrs[] = {
300 &dev_attr_flash_brightness.attr,
301 &dev_attr_max_flash_brightness.attr,
302 NULL,
303};
304
305static struct attribute *led_flash_fault_attrs[] = {
306 &dev_attr_flash_fault.attr,
307 NULL,
308};
309
310static struct attribute *led_flash_sync_strobe_attrs[] = {
311 &dev_attr_available_sync_leds.attr,
312 &dev_attr_flash_sync_strobe.attr,
313 NULL,
314};
315
316static const struct attribute_group led_flash_strobe_group = {
317 .attrs = led_flash_strobe_attrs,
318};
319
320static const struct attribute_group led_flash_timeout_group = {
321 .attrs = led_flash_timeout_attrs,
322};
323
324static const struct attribute_group led_flash_brightness_group = {
325 .attrs = led_flash_brightness_attrs,
326};
327
328static const struct attribute_group led_flash_fault_group = {
329 .attrs = led_flash_fault_attrs,
330};
331
332static const struct attribute_group led_flash_sync_strobe_group = {
333 .attrs = led_flash_sync_strobe_attrs,
334};
335
336static void led_flash_resume(struct led_classdev *led_cdev)
337{
338 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
339
340 call_flash_op(fled_cdev, flash_brightness_set,
341 fled_cdev->brightness.val);
342 call_flash_op(fled_cdev, timeout_set, fled_cdev->timeout.val);
343}
344
345static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev)
346{
347 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
348 const struct led_flash_ops *ops = fled_cdev->ops;
349 const struct attribute_group **flash_groups = fled_cdev->sysfs_groups;
350
351 int num_sysfs_groups = 0;
352
353 flash_groups[num_sysfs_groups++] = &led_flash_strobe_group;
354
355 if (ops->flash_brightness_set)
356 flash_groups[num_sysfs_groups++] = &led_flash_brightness_group;
357
358 if (ops->timeout_set)
359 flash_groups[num_sysfs_groups++] = &led_flash_timeout_group;
360
361 if (ops->fault_get)
362 flash_groups[num_sysfs_groups++] = &led_flash_fault_group;
363
364 if (led_cdev->flags & LED_DEV_CAP_SYNC_STROBE)
365 flash_groups[num_sysfs_groups++] = &led_flash_sync_strobe_group;
366
367 led_cdev->groups = flash_groups;
368}
369
370int led_classdev_flash_register(struct device *parent,
371 struct led_classdev_flash *fled_cdev)
372{
373 struct led_classdev *led_cdev;
374 const struct led_flash_ops *ops;
375 int ret;
376
377 if (!fled_cdev)
378 return -EINVAL;
379
380 led_cdev = &fled_cdev->led_cdev;
381
382 if (led_cdev->flags & LED_DEV_CAP_FLASH) {
383 if (!led_cdev->brightness_set_sync)
384 return -EINVAL;
385
386 ops = fled_cdev->ops;
387 if (!ops || !ops->strobe_set)
388 return -EINVAL;
389
390 led_cdev->flash_resume = led_flash_resume;
391
392 /* Select the sysfs attributes to be created for the device */
393 led_flash_init_sysfs_groups(fled_cdev);
394 }
395
396 /* Register led class device */
397 ret = led_classdev_register(parent, led_cdev);
398 if (ret < 0)
399 return ret;
400
401 /* Setting a torch brightness needs to have immediate effect */
402 led_cdev->flags &= ~SET_BRIGHTNESS_ASYNC;
403 led_cdev->flags |= SET_BRIGHTNESS_SYNC;
404
405 return 0;
406}
407EXPORT_SYMBOL_GPL(led_classdev_flash_register);
408
409void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev)
410{
411 if (!fled_cdev)
412 return;
413
414 led_classdev_unregister(&fled_cdev->led_cdev);
415}
416EXPORT_SYMBOL_GPL(led_classdev_flash_unregister);
417
418static void led_clamp_align(struct led_flash_setting *s)
419{
420 u32 v, offset;
421
422 v = s->val + s->step / 2;
423 v = clamp(v, s->min, s->max);
424 offset = v - s->min;
425 offset = s->step * (offset / s->step);
426 s->val = s->min + offset;
427}
428
429int led_set_flash_timeout(struct led_classdev_flash *fled_cdev, u32 timeout)
430{
431 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
432 struct led_flash_setting *s = &fled_cdev->timeout;
433
434 s->val = timeout;
435 led_clamp_align(s);
436
437 if (!(led_cdev->flags & LED_SUSPENDED))
438 return call_flash_op(fled_cdev, timeout_set, s->val);
439
440 return 0;
441}
442EXPORT_SYMBOL_GPL(led_set_flash_timeout);
443
444int led_get_flash_fault(struct led_classdev_flash *fled_cdev, u32 *fault)
445{
446 return call_flash_op(fled_cdev, fault_get, fault);
447}
448EXPORT_SYMBOL_GPL(led_get_flash_fault);
449
450int led_set_flash_brightness(struct led_classdev_flash *fled_cdev,
451 u32 brightness)
452{
453 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
454 struct led_flash_setting *s = &fled_cdev->brightness;
455
456 s->val = brightness;
457 led_clamp_align(s);
458
459 if (!(led_cdev->flags & LED_SUSPENDED))
460 return call_flash_op(fled_cdev, flash_brightness_set, s->val);
461
462 return 0;
463}
464EXPORT_SYMBOL_GPL(led_set_flash_brightness);
465
466int led_update_flash_brightness(struct led_classdev_flash *fled_cdev)
467{
468 struct led_flash_setting *s = &fled_cdev->brightness;
469 u32 brightness;
470
471 if (has_flash_op(fled_cdev, flash_brightness_get)) {
472 int ret = call_flash_op(fled_cdev, flash_brightness_get,
473 &brightness);
474 if (ret < 0)
475 return ret;
476
477 s->val = brightness;
478 }
479
480 return 0;
481}
482EXPORT_SYMBOL_GPL(led_update_flash_brightness);
483
484MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
485MODULE_DESCRIPTION("LED Flash class interface");
486MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index dbeebac38d31..795ec994c663 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -179,6 +179,10 @@ EXPORT_SYMBOL_GPL(led_classdev_suspend);
179void led_classdev_resume(struct led_classdev *led_cdev) 179void led_classdev_resume(struct led_classdev *led_cdev)
180{ 180{
181 led_cdev->brightness_set(led_cdev, led_cdev->brightness); 181 led_cdev->brightness_set(led_cdev, led_cdev->brightness);
182
183 if (led_cdev->flash_resume)
184 led_cdev->flash_resume(led_cdev);
185
182 led_cdev->flags &= ~LED_SUSPENDED; 186 led_cdev->flags &= ~LED_SUSPENDED;
183} 187}
184EXPORT_SYMBOL_GPL(led_classdev_resume); 188EXPORT_SYMBOL_GPL(led_classdev_resume);
@@ -239,9 +243,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
239 243
240 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); 244 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
241 245
242 init_timer(&led_cdev->blink_timer); 246 setup_timer(&led_cdev->blink_timer, led_timer_function,
243 led_cdev->blink_timer.function = led_timer_function; 247 (unsigned long)led_cdev);
244 led_cdev->blink_timer.data = (unsigned long)led_cdev;
245 248
246#ifdef CONFIG_LEDS_TRIGGERS 249#ifdef CONFIG_LEDS_TRIGGERS
247 led_trigger_set_default(led_cdev); 250 led_trigger_set_default(led_cdev);
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 7ea1ea42c2d2..d26af0a79a90 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -187,6 +187,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
187 led.gpiod = devm_get_gpiod_from_child(dev, child); 187 led.gpiod = devm_get_gpiod_from_child(dev, child);
188 if (IS_ERR(led.gpiod)) { 188 if (IS_ERR(led.gpiod)) {
189 fwnode_handle_put(child); 189 fwnode_handle_put(child);
190 ret = PTR_ERR(led.gpiod);
190 goto err; 191 goto err;
191 } 192 }
192 193
@@ -229,7 +230,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
229err: 230err:
230 for (count = priv->num_leds - 2; count >= 0; count--) 231 for (count = priv->num_leds - 2; count >= 0; count--)
231 delete_gpio_led(&priv->leds[count]); 232 delete_gpio_led(&priv->leds[count]);
232 return ERR_PTR(-ENODEV); 233 return ERR_PTR(ret);
233} 234}
234 235
235static const struct of_device_id of_gpio_leds_match[] = { 236static const struct of_device_id of_gpio_leds_match[] = {
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index 85c3714e1b5a..e2b847fe22a1 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -134,9 +134,7 @@ static struct mc13xxx_leds_platform_data __init *mc13xxx_led_probe_dt(
134 if (!pdata) 134 if (!pdata)
135 return ERR_PTR(-ENOMEM); 135 return ERR_PTR(-ENOMEM);
136 136
137 of_node_get(dev->parent->of_node); 137 parent = of_get_child_by_name(dev->parent->of_node, "leds");
138
139 parent = of_find_node_by_name(dev->parent->of_node, "leds");
140 if (!parent) 138 if (!parent)
141 goto out_node_put; 139 goto out_node_put;
142 140
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index 2348dbda5269..79efe57c7405 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -20,7 +20,8 @@
20static inline void led_set_brightness_async(struct led_classdev *led_cdev, 20static inline void led_set_brightness_async(struct led_classdev *led_cdev,
21 enum led_brightness value) 21 enum led_brightness value)
22{ 22{
23 led_cdev->brightness = min(value, led_cdev->max_brightness); 23 value = min(value, led_cdev->max_brightness);
24 led_cdev->brightness = value;
24 25
25 if (!(led_cdev->flags & LED_SUSPENDED)) 26 if (!(led_cdev->flags & LED_SUSPENDED))
26 led_cdev->brightness_set(led_cdev, value); 27 led_cdev->brightness_set(led_cdev, value);
diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h
new file mode 100644
index 000000000000..5ba2facd7a51
--- /dev/null
+++ b/include/linux/led-class-flash.h
@@ -0,0 +1,207 @@
1/*
2 * LED Flash class interface
3 *
4 * Copyright (C) 2015 Samsung Electronics Co., Ltd.
5 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12#ifndef __LINUX_FLASH_LEDS_H_INCLUDED
13#define __LINUX_FLASH_LEDS_H_INCLUDED
14
15#include <linux/leds.h>
16#include <uapi/linux/v4l2-controls.h>
17
18struct device_node;
19struct led_classdev_flash;
20
21/*
22 * Supported led fault bits - must be kept in synch
23 * with V4L2_FLASH_FAULT bits.
24 */
25#define LED_FAULT_OVER_VOLTAGE (1 << 0)
26#define LED_FAULT_TIMEOUT (1 << 1)
27#define LED_FAULT_OVER_TEMPERATURE (1 << 2)
28#define LED_FAULT_SHORT_CIRCUIT (1 << 3)
29#define LED_FAULT_OVER_CURRENT (1 << 4)
30#define LED_FAULT_INDICATOR (1 << 5)
31#define LED_FAULT_UNDER_VOLTAGE (1 << 6)
32#define LED_FAULT_INPUT_VOLTAGE (1 << 7)
33#define LED_FAULT_LED_OVER_TEMPERATURE (1 << 8)
34#define LED_NUM_FLASH_FAULTS 9
35
36#define LED_FLASH_MAX_SYSFS_GROUPS 7
37
38struct led_flash_ops {
39 /* set flash brightness */
40 int (*flash_brightness_set)(struct led_classdev_flash *fled_cdev,
41 u32 brightness);
42 /* get flash brightness */
43 int (*flash_brightness_get)(struct led_classdev_flash *fled_cdev,
44 u32 *brightness);
45 /* set flash strobe state */
46 int (*strobe_set)(struct led_classdev_flash *fled_cdev, bool state);
47 /* get flash strobe state */
48 int (*strobe_get)(struct led_classdev_flash *fled_cdev, bool *state);
49 /* set flash timeout */
50 int (*timeout_set)(struct led_classdev_flash *fled_cdev, u32 timeout);
51 /* get the flash LED fault */
52 int (*fault_get)(struct led_classdev_flash *fled_cdev, u32 *fault);
53};
54
55/*
56 * Current value of a flash setting along
57 * with its constraints.
58 */
59struct led_flash_setting {
60 /* maximum allowed value */
61 u32 min;
62 /* maximum allowed value */
63 u32 max;
64 /* step value */
65 u32 step;
66 /* current value */
67 u32 val;
68};
69
70struct led_classdev_flash {
71 /* led class device */
72 struct led_classdev led_cdev;
73
74 /* flash led specific ops */
75 const struct led_flash_ops *ops;
76
77 /* flash brightness value in microamperes along with its constraints */
78 struct led_flash_setting brightness;
79
80 /* flash timeout value in microseconds along with its constraints */
81 struct led_flash_setting timeout;
82
83 /* LED Flash class sysfs groups */
84 const struct attribute_group *sysfs_groups[LED_FLASH_MAX_SYSFS_GROUPS];
85
86 /* LEDs available for flash strobe synchronization */
87 struct led_classdev_flash **sync_leds;
88
89 /* Number of LEDs available for flash strobe synchronization */
90 int num_sync_leds;
91
92 /*
93 * The identifier of the sub-led to synchronize the flash strobe with.
94 * Identifiers start from 1, which reflects the first element from the
95 * sync_leds array. 0 means that the flash strobe should not be
96 * synchronized.
97 */
98 u32 sync_led_id;
99};
100
101static inline struct led_classdev_flash *lcdev_to_flcdev(
102 struct led_classdev *lcdev)
103{
104 return container_of(lcdev, struct led_classdev_flash, led_cdev);
105}
106
107/**
108 * led_classdev_flash_register - register a new object of led_classdev class
109 * with support for flash LEDs
110 * @parent: the flash LED to register
111 * @fled_cdev: the led_classdev_flash structure for this device
112 *
113 * Returns: 0 on success or negative error value on failure
114 */
115extern int led_classdev_flash_register(struct device *parent,
116 struct led_classdev_flash *fled_cdev);
117
118/**
119 * led_classdev_flash_unregister - unregisters an object of led_classdev class
120 * with support for flash LEDs
121 * @fled_cdev: the flash LED to unregister
122 *
123 * Unregister a previously registered via led_classdev_flash_register object
124 */
125extern void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev);
126
127/**
128 * led_set_flash_strobe - setup flash strobe
129 * @fled_cdev: the flash LED to set strobe on
130 * @state: 1 - strobe flash, 0 - stop flash strobe
131 *
132 * Strobe the flash LED.
133 *
134 * Returns: 0 on success or negative error value on failure
135 */
136static inline int led_set_flash_strobe(struct led_classdev_flash *fled_cdev,
137 bool state)
138{
139 return fled_cdev->ops->strobe_set(fled_cdev, state);
140}
141
142/**
143 * led_get_flash_strobe - get flash strobe status
144 * @fled_cdev: the flash LED to query
145 * @state: 1 - flash is strobing, 0 - flash is off
146 *
147 * Check whether the flash is strobing at the moment.
148 *
149 * Returns: 0 on success or negative error value on failure
150 */
151static inline int led_get_flash_strobe(struct led_classdev_flash *fled_cdev,
152 bool *state)
153{
154 if (fled_cdev->ops->strobe_get)
155 return fled_cdev->ops->strobe_get(fled_cdev, state);
156
157 return -EINVAL;
158}
159
160/**
161 * led_set_flash_brightness - set flash LED brightness
162 * @fled_cdev: the flash LED to set
163 * @brightness: the brightness to set it to
164 *
165 * Set a flash LED's brightness.
166 *
167 * Returns: 0 on success or negative error value on failure
168 */
169extern int led_set_flash_brightness(struct led_classdev_flash *fled_cdev,
170 u32 brightness);
171
172/**
173 * led_update_flash_brightness - update flash LED brightness
174 * @fled_cdev: the flash LED to query
175 *
176 * Get a flash LED's current brightness and update led_flash->brightness
177 * member with the obtained value.
178 *
179 * Returns: 0 on success or negative error value on failure
180 */
181extern int led_update_flash_brightness(struct led_classdev_flash *fled_cdev);
182
183/**
184 * led_set_flash_timeout - set flash LED timeout
185 * @fled_cdev: the flash LED to set
186 * @timeout: the flash timeout to set it to
187 *
188 * Set the flash strobe duration.
189 *
190 * Returns: 0 on success or negative error value on failure
191 */
192extern int led_set_flash_timeout(struct led_classdev_flash *fled_cdev,
193 u32 timeout);
194
195/**
196 * led_get_flash_fault - get the flash LED fault
197 * @fled_cdev: the flash LED to query
198 * @fault: bitmask containing flash faults
199 *
200 * Get the flash LED fault.
201 *
202 * Returns: 0 on success or negative error value on failure
203 */
204extern int led_get_flash_fault(struct led_classdev_flash *fled_cdev,
205 u32 *fault);
206
207#endif /* __LINUX_FLASH_LEDS_H_INCLUDED */
diff --git a/include/linux/leds.h b/include/linux/leds.h
index cfceef32c9b3..f70f84f35674 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -46,6 +46,8 @@ struct led_classdev {
46#define LED_SYSFS_DISABLE (1 << 20) 46#define LED_SYSFS_DISABLE (1 << 20)
47#define SET_BRIGHTNESS_ASYNC (1 << 21) 47#define SET_BRIGHTNESS_ASYNC (1 << 21)
48#define SET_BRIGHTNESS_SYNC (1 << 22) 48#define SET_BRIGHTNESS_SYNC (1 << 22)
49#define LED_DEV_CAP_FLASH (1 << 23)
50#define LED_DEV_CAP_SYNC_STROBE (1 << 24)
49 51
50 /* Set LED brightness level */ 52 /* Set LED brightness level */
51 /* Must not sleep, use a workqueue if needed */ 53 /* Must not sleep, use a workqueue if needed */
@@ -81,6 +83,7 @@ struct led_classdev {
81 unsigned long blink_delay_on, blink_delay_off; 83 unsigned long blink_delay_on, blink_delay_off;
82 struct timer_list blink_timer; 84 struct timer_list blink_timer;
83 int blink_brightness; 85 int blink_brightness;
86 void (*flash_resume)(struct led_classdev *led_cdev);
84 87
85 struct work_struct set_brightness_work; 88 struct work_struct set_brightness_work;
86 int delayed_set_value; 89 int delayed_set_value;