aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-class-led-flash80
-rw-r--r--Documentation/devicetree/bindings/leds/common.txt6
-rw-r--r--Documentation/devicetree/bindings/leds/leds-gpio.txt12
-rw-r--r--Documentation/devicetree/bindings/leds/leds-pm8941-wled.txt43
-rw-r--r--Documentation/driver-model/devres.txt4
-rw-r--r--Documentation/leds/leds-class-flash.txt22
-rw-r--r--drivers/leds/Kconfig8
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/led-class-flash.c82
-rw-r--r--drivers/leds/led-class.c96
-rw-r--r--drivers/leds/leds-lp8501.c2
-rw-r--r--drivers/leds/leds-lp8860.c14
-rw-r--r--drivers/leds/leds-pca963x.c2
-rw-r--r--drivers/leds/leds-pm8941-wled.c435
-rw-r--r--drivers/leds/leds-pwm.c3
-rw-r--r--include/dt-bindings/leds/common.h21
-rw-r--r--include/linux/led-class-flash.h19
-rw-r--r--include/linux/leds.h5
18 files changed, 735 insertions, 120 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-led-flash b/Documentation/ABI/testing/sysfs-class-led-flash
new file mode 100644
index 000000000000..220a0270b47b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-flash
@@ -0,0 +1,80 @@
1What: /sys/class/leds/<led>/flash_brightness
2Date: March 2015
3KernelVersion: 4.0
4Contact: Jacek Anaszewski <j.anaszewski@samsung.com>
5Description: read/write
6 Set the brightness of this LED in the flash strobe mode, in
7 microamperes. The file is created only for the flash LED devices
8 that support setting flash brightness.
9
10 The value is between 0 and
11 /sys/class/leds/<led>/max_flash_brightness.
12
13What: /sys/class/leds/<led>/max_flash_brightness
14Date: March 2015
15KernelVersion: 4.0
16Contact: Jacek Anaszewski <j.anaszewski@samsung.com>
17Description: read only
18 Maximum brightness level for this LED in the flash strobe mode,
19 in microamperes.
20
21What: /sys/class/leds/<led>/flash_timeout
22Date: March 2015
23KernelVersion: 4.0
24Contact: Jacek Anaszewski <j.anaszewski@samsung.com>
25Description: read/write
26 Hardware timeout for flash, in microseconds. The flash strobe
27 is stopped after this period of time has passed from the start
28 of the strobe. The file is created only for the flash LED
29 devices that support setting flash timeout.
30
31What: /sys/class/leds/<led>/max_flash_timeout
32Date: March 2015
33KernelVersion: 4.0
34Contact: Jacek Anaszewski <j.anaszewski@samsung.com>
35Description: read only
36 Maximum flash timeout for this LED, in microseconds.
37
38What: /sys/class/leds/<led>/flash_strobe
39Date: March 2015
40KernelVersion: 4.0
41Contact: Jacek Anaszewski <j.anaszewski@samsung.com>
42Description: read/write
43 Flash strobe state. When written with 1 it triggers flash strobe
44 and when written with 0 it turns the flash off.
45
46 On read 1 means that flash is currently strobing and 0 means
47 that flash is off.
48
49What: /sys/class/leds/<led>/flash_fault
50Date: March 2015
51KernelVersion: 4.0
52Contact: Jacek Anaszewski <j.anaszewski@samsung.com>
53Description: read only
54 Space separated list of flash faults that may have occurred.
55 Flash faults are re-read after strobing the flash. Possible
56 flash faults:
57
58 * led-over-voltage - flash controller voltage to the flash LED
59 has exceeded the limit specific to the flash controller
60 * flash-timeout-exceeded - the flash strobe was still on when
61 the timeout set by the user has expired; not all flash
62 controllers may set this in all such conditions
63 * controller-over-temperature - the flash controller has
64 overheated
65 * controller-short-circuit - the short circuit protection
66 of the flash controller has been triggered
67 * led-power-supply-over-current - current in the LED power
68 supply has exceeded the limit specific to the flash
69 controller
70 * indicator-led-fault - the flash controller has detected
71 a short or open circuit condition on the indicator LED
72 * led-under-voltage - flash controller voltage to the flash
73 LED has been below the minimum limit specific to
74 the flash
75 * controller-under-voltage - the input voltage of the flash
76 controller is below the limit under which strobing the
77 flash at full current will not be possible;
78 the condition persists until this flag is no longer set
79 * led-over-temperature - the temperature of the LED has exceeded
80 its allowed upper limit
diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
index 34811c57db69..747c53805eec 100644
--- a/Documentation/devicetree/bindings/leds/common.txt
+++ b/Documentation/devicetree/bindings/leds/common.txt
@@ -14,8 +14,10 @@ Optional properties for child nodes:
14- led-sources : List of device current outputs the LED is connected to. The 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 15 outputs are identified by the numbers that must be defined
16 in the LED device binding documentation. 16 in the LED device binding documentation.
17- label : The label for this LED. If omitted, the label is 17- label : The label for this LED. If omitted, the label is taken from the node
18 taken from the node name (excluding the unit address). 18 name (excluding the unit address). It has to uniquely identify
19 a device, i.e. no other LED class device can be assigned the same
20 label.
19 21
20- linux,default-trigger : This parameter, if present, is a 22- linux,default-trigger : This parameter, if present, is a
21 string defining the trigger assigned to the LED. Current triggers are: 23 string defining the trigger assigned to the LED. Current triggers are:
diff --git a/Documentation/devicetree/bindings/leds/leds-gpio.txt b/Documentation/devicetree/bindings/leds/leds-gpio.txt
index f77148f372ea..fea1ebfe24a9 100644
--- a/Documentation/devicetree/bindings/leds/leds-gpio.txt
+++ b/Documentation/devicetree/bindings/leds/leds-gpio.txt
@@ -26,16 +26,18 @@ LED sub-node properties:
26 26
27Examples: 27Examples:
28 28
29#include <dt-bindings/gpio/gpio.h>
30
29leds { 31leds {
30 compatible = "gpio-leds"; 32 compatible = "gpio-leds";
31 hdd { 33 hdd {
32 label = "IDE Activity"; 34 label = "IDE Activity";
33 gpios = <&mcu_pio 0 1>; /* Active low */ 35 gpios = <&mcu_pio 0 GPIO_ACTIVE_LOW>;
34 linux,default-trigger = "ide-disk"; 36 linux,default-trigger = "ide-disk";
35 }; 37 };
36 38
37 fault { 39 fault {
38 gpios = <&mcu_pio 1 0>; 40 gpios = <&mcu_pio 1 GPIO_ACTIVE_HIGH>;
39 /* Keep LED on if BIOS detected hardware fault */ 41 /* Keep LED on if BIOS detected hardware fault */
40 default-state = "keep"; 42 default-state = "keep";
41 }; 43 };
@@ -44,11 +46,11 @@ leds {
44run-control { 46run-control {
45 compatible = "gpio-leds"; 47 compatible = "gpio-leds";
46 red { 48 red {
47 gpios = <&mpc8572 6 0>; 49 gpios = <&mpc8572 6 GPIO_ACTIVE_HIGH>;
48 default-state = "off"; 50 default-state = "off";
49 }; 51 };
50 green { 52 green {
51 gpios = <&mpc8572 7 0>; 53 gpios = <&mpc8572 7 GPIO_ACTIVE_HIGH>;
52 default-state = "on"; 54 default-state = "on";
53 }; 55 };
54}; 56};
@@ -57,7 +59,7 @@ leds {
57 compatible = "gpio-leds"; 59 compatible = "gpio-leds";
58 60
59 charger-led { 61 charger-led {
60 gpios = <&gpio1 2 0>; 62 gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
61 linux,default-trigger = "max8903-charger-charging"; 63 linux,default-trigger = "max8903-charger-charging";
62 retain-state-suspended; 64 retain-state-suspended;
63 }; 65 };
diff --git a/Documentation/devicetree/bindings/leds/leds-pm8941-wled.txt b/Documentation/devicetree/bindings/leds/leds-pm8941-wled.txt
new file mode 100644
index 000000000000..a85a964d61f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-pm8941-wled.txt
@@ -0,0 +1,43 @@
1Binding for Qualcomm PM8941 WLED driver
2
3Required properties:
4- compatible: should be "qcom,pm8941-wled"
5- reg: slave address
6
7Optional properties:
8- label: The label for this led
9 See Documentation/devicetree/bindings/leds/common.txt
10- linux,default-trigger: Default trigger assigned to the LED
11 See Documentation/devicetree/bindings/leds/common.txt
12- qcom,cs-out: bool; enable current sink output
13- qcom,cabc: bool; enable content adaptive backlight control
14- qcom,ext-gen: bool; use externally generated modulator signal to dim
15- qcom,current-limit: mA; per-string current limit; value from 0 to 25
16 default: 20mA
17- qcom,current-boost-limit: mA; boost current limit; one of:
18 105, 385, 525, 805, 980, 1260, 1400, 1680
19 default: 805mA
20- qcom,switching-freq: kHz; switching frequency; one of:
21 600, 640, 685, 738, 800, 872, 960, 1066, 1200, 1371,
22 1600, 1920, 2400, 3200, 4800, 9600,
23 default: 1600kHz
24- qcom,ovp: V; Over-voltage protection limit; one of:
25 27, 29, 32, 35
26 default: 29V
27- qcom,num-strings: #; number of led strings attached; value from 1 to 3
28 default: 2
29
30Example:
31
32pm8941-wled@d800 {
33 compatible = "qcom,pm8941-wled";
34 reg = <0xd800>;
35 label = "backlight";
36
37 qcom,cs-out;
38 qcom,current-limit = <20>;
39 qcom,current-boost-limit = <805>;
40 qcom,switching-freq = <1600>;
41 qcom,ovp = <29>;
42 qcom,num-strings = <2>;
43};
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 6d1e8eeb5990..e1e2bbd7a404 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -289,6 +289,10 @@ IRQ
289 devm_request_irq() 289 devm_request_irq()
290 devm_request_threaded_irq() 290 devm_request_threaded_irq()
291 291
292LED
293 devm_led_classdev_register()
294 devm_led_classdev_unregister()
295
292MDIO 296MDIO
293 devm_mdiobus_alloc() 297 devm_mdiobus_alloc()
294 devm_mdiobus_alloc_size() 298 devm_mdiobus_alloc_size()
diff --git a/Documentation/leds/leds-class-flash.txt b/Documentation/leds/leds-class-flash.txt
new file mode 100644
index 000000000000..19bb67355424
--- /dev/null
+++ b/Documentation/leds/leds-class-flash.txt
@@ -0,0 +1,22 @@
1
2Flash LED handling under Linux
3==============================
4
5Some LED devices provide two modes - torch and flash. In the LED subsystem
6those modes are supported by LED class (see Documentation/leds/leds-class.txt)
7and LED Flash class respectively. The torch mode related features are enabled
8by default and the flash ones only if a driver declares it by setting
9LED_DEV_CAP_FLASH flag.
10
11In order to enable the support for flash LEDs CONFIG_LEDS_CLASS_FLASH symbol
12must be defined in the kernel config. A LED Flash class driver must be
13registered in the LED subsystem with led_classdev_flash_register function.
14
15Following sysfs attributes are exposed for controlling flash LED devices:
16(see Documentation/ABI/testing/sysfs-class-led-flash)
17 - flash_brightness
18 - max_flash_brightness
19 - flash_timeout
20 - max_flash_timeout
21 - flash_strobe
22 - flash_fault
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 25b320d64e26..966b9605f5f0 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -526,6 +526,14 @@ config LEDS_VERSATILE
526 This option enabled support for the LEDs on the ARM Versatile 526 This option enabled support for the LEDs on the ARM Versatile
527 and RealView boards. Say Y to enabled these. 527 and RealView boards. Say Y to enabled these.
528 528
529config LEDS_PM8941_WLED
530 tristate "LED support for the Qualcomm PM8941 WLED block"
531 depends on LEDS_CLASS
532 select REGMAP
533 help
534 This option enables support for the 'White' LED block
535 on Qualcomm PM8941 PMICs.
536
529comment "LED Triggers" 537comment "LED Triggers"
530source "drivers/leds/trigger/Kconfig" 538source "drivers/leds/trigger/Kconfig"
531 539
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index cbba921b6f1c..bf4609338e10 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o
58obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o 58obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o
59obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o 59obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o
60obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o 60obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o
61obj-$(CONFIG_LEDS_PM8941_WLED) += leds-pm8941-wled.o
61 62
62# LED SPI Drivers 63# LED SPI Drivers
63obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 64obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
index 4a19fd44f93f..3b2573411a37 100644
--- a/drivers/leds/led-class-flash.c
+++ b/drivers/leds/led-class-flash.c
@@ -216,75 +216,6 @@ static ssize_t flash_fault_show(struct device *dev,
216} 216}
217static DEVICE_ATTR_RO(flash_fault); 217static DEVICE_ATTR_RO(flash_fault);
218 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[] = { 219static struct attribute *led_flash_strobe_attrs[] = {
289 &dev_attr_flash_strobe.attr, 220 &dev_attr_flash_strobe.attr,
290 NULL, 221 NULL,
@@ -307,12 +238,6 @@ static struct attribute *led_flash_fault_attrs[] = {
307 NULL, 238 NULL,
308}; 239};
309 240
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 = { 241static const struct attribute_group led_flash_strobe_group = {
317 .attrs = led_flash_strobe_attrs, 242 .attrs = led_flash_strobe_attrs,
318}; 243};
@@ -329,10 +254,6 @@ static const struct attribute_group led_flash_fault_group = {
329 .attrs = led_flash_fault_attrs, 254 .attrs = led_flash_fault_attrs,
330}; 255};
331 256
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) 257static void led_flash_resume(struct led_classdev *led_cdev)
337{ 258{
338 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev); 259 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
@@ -361,9 +282,6 @@ static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev)
361 if (ops->fault_get) 282 if (ops->fault_get)
362 flash_groups[num_sysfs_groups++] = &led_flash_fault_group; 283 flash_groups[num_sysfs_groups++] = &led_flash_fault_group;
363 284
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; 285 led_cdev->groups = flash_groups;
368} 286}
369 287
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 795ec994c663..728681debdbe 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -212,6 +212,31 @@ static const struct dev_pm_ops leds_class_dev_pm_ops = {
212 .resume = led_resume, 212 .resume = led_resume,
213}; 213};
214 214
215static int match_name(struct device *dev, const void *data)
216{
217 if (!dev_name(dev))
218 return 0;
219 return !strcmp(dev_name(dev), (char *)data);
220}
221
222static int led_classdev_next_name(const char *init_name, char *name,
223 size_t len)
224{
225 unsigned int i = 0;
226 int ret = 0;
227
228 strlcpy(name, init_name, len);
229
230 while (class_find_device(leds_class, NULL, name, match_name) &&
231 (ret < len))
232 ret = snprintf(name, len, "%s_%u", init_name, ++i);
233
234 if (ret >= len)
235 return -ENOMEM;
236
237 return i;
238}
239
215/** 240/**
216 * led_classdev_register - register a new object of led_classdev class. 241 * led_classdev_register - register a new object of led_classdev class.
217 * @parent: The device to register. 242 * @parent: The device to register.
@@ -219,12 +244,22 @@ static const struct dev_pm_ops leds_class_dev_pm_ops = {
219 */ 244 */
220int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) 245int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
221{ 246{
247 char name[64];
248 int ret;
249
250 ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
251 if (ret < 0)
252 return ret;
253
222 led_cdev->dev = device_create_with_groups(leds_class, parent, 0, 254 led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
223 led_cdev, led_cdev->groups, 255 led_cdev, led_cdev->groups, "%s", name);
224 "%s", led_cdev->name);
225 if (IS_ERR(led_cdev->dev)) 256 if (IS_ERR(led_cdev->dev))
226 return PTR_ERR(led_cdev->dev); 257 return PTR_ERR(led_cdev->dev);
227 258
259 if (ret)
260 dev_warn(parent, "Led %s renamed to %s due to name collision",
261 led_cdev->name, dev_name(led_cdev->dev));
262
228#ifdef CONFIG_LEDS_TRIGGERS 263#ifdef CONFIG_LEDS_TRIGGERS
229 init_rwsem(&led_cdev->trigger_lock); 264 init_rwsem(&led_cdev->trigger_lock);
230#endif 265#endif
@@ -288,6 +323,63 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
288} 323}
289EXPORT_SYMBOL_GPL(led_classdev_unregister); 324EXPORT_SYMBOL_GPL(led_classdev_unregister);
290 325
326static void devm_led_classdev_release(struct device *dev, void *res)
327{
328 led_classdev_unregister(*(struct led_classdev **)res);
329}
330
331/**
332 * devm_led_classdev_register - resource managed led_classdev_register()
333 * @parent: The device to register.
334 * @led_cdev: the led_classdev structure for this device.
335 */
336int devm_led_classdev_register(struct device *parent,
337 struct led_classdev *led_cdev)
338{
339 struct led_classdev **dr;
340 int rc;
341
342 dr = devres_alloc(devm_led_classdev_release, sizeof(*dr), GFP_KERNEL);
343 if (!dr)
344 return -ENOMEM;
345
346 rc = led_classdev_register(parent, led_cdev);
347 if (rc) {
348 devres_free(dr);
349 return rc;
350 }
351
352 *dr = led_cdev;
353 devres_add(parent, dr);
354
355 return 0;
356}
357EXPORT_SYMBOL_GPL(devm_led_classdev_register);
358
359static int devm_led_classdev_match(struct device *dev, void *res, void *data)
360{
361 struct led_cdev **p = res;
362
363 if (WARN_ON(!p || !*p))
364 return 0;
365
366 return *p == data;
367}
368
369/**
370 * devm_led_classdev_unregister() - resource managed led_classdev_unregister()
371 * @parent: The device to unregister.
372 * @led_cdev: the led_classdev structure for this device.
373 */
374void devm_led_classdev_unregister(struct device *dev,
375 struct led_classdev *led_cdev)
376{
377 WARN_ON(devres_release(dev,
378 devm_led_classdev_release,
379 devm_led_classdev_match, led_cdev));
380}
381EXPORT_SYMBOL_GPL(devm_led_classdev_unregister);
382
291static int __init leds_init(void) 383static int __init leds_init(void)
292{ 384{
293 leds_class = class_create(THIS_MODULE, "leds"); 385 leds_class = class_create(THIS_MODULE, "leds");
diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c
index 00f068b0fa6f..d3098e395fff 100644
--- a/drivers/leds/leds-lp8501.c
+++ b/drivers/leds/leds-lp8501.c
@@ -406,6 +406,6 @@ static struct i2c_driver lp8501_driver = {
406 406
407module_i2c_driver(lp8501_driver); 407module_i2c_driver(lp8501_driver);
408 408
409MODULE_DESCRIPTION("Texas Instruments LP8501 LED drvier"); 409MODULE_DESCRIPTION("Texas Instruments LP8501 LED driver");
410MODULE_AUTHOR("Milo Kim"); 410MODULE_AUTHOR("Milo Kim");
411MODULE_LICENSE("GPL"); 411MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c
index 840e93f3ab3e..8c2b7fbe2392 100644
--- a/drivers/leds/leds-lp8860.c
+++ b/drivers/leds/leds-lp8860.c
@@ -391,11 +391,13 @@ static int lp8860_probe(struct i2c_client *client,
391 } 391 }
392 } 392 }
393 393
394 led->enable_gpio = devm_gpiod_get(&client->dev, "enable"); 394 led->enable_gpio = devm_gpiod_get_optional(&client->dev,
395 if (IS_ERR(led->enable_gpio)) 395 "enable", GPIOD_OUT_LOW);
396 led->enable_gpio = NULL; 396 if (IS_ERR(led->enable_gpio)) {
397 else 397 ret = PTR_ERR(led->enable_gpio);
398 gpiod_direction_output(led->enable_gpio, 0); 398 dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret);
399 return ret;
400 }
399 401
400 led->regulator = devm_regulator_get(&client->dev, "vled"); 402 led->regulator = devm_regulator_get(&client->dev, "vled");
401 if (IS_ERR(led->regulator)) 403 if (IS_ERR(led->regulator))
@@ -486,6 +488,6 @@ static struct i2c_driver lp8860_driver = {
486}; 488};
487module_i2c_driver(lp8860_driver); 489module_i2c_driver(lp8860_driver);
488 490
489MODULE_DESCRIPTION("Texas Instruments LP8860 LED drvier"); 491MODULE_DESCRIPTION("Texas Instruments LP8860 LED driver");
490MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); 492MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
491MODULE_LICENSE("GPL"); 493MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c
index f110b4c456ba..bee3e1ab27fd 100644
--- a/drivers/leds/leds-pca963x.c
+++ b/drivers/leds/leds-pca963x.c
@@ -289,7 +289,7 @@ pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip)
289 return ERR_PTR(-ENOMEM); 289 return ERR_PTR(-ENOMEM);
290 290
291 for_each_child_of_node(np, child) { 291 for_each_child_of_node(np, child) {
292 struct led_info led; 292 struct led_info led = {};
293 u32 reg; 293 u32 reg;
294 int res; 294 int res;
295 295
diff --git a/drivers/leds/leds-pm8941-wled.c b/drivers/leds/leds-pm8941-wled.c
new file mode 100644
index 000000000000..bf64a593fbf1
--- /dev/null
+++ b/drivers/leds/leds-pm8941-wled.c
@@ -0,0 +1,435 @@
1/* Copyright (c) 2015, Sony Mobile Communications, AB.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/leds.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <linux/regmap.h>
19
20#define PM8941_WLED_REG_VAL_BASE 0x40
21#define PM8941_WLED_REG_VAL_MAX 0xFFF
22
23#define PM8941_WLED_REG_MOD_EN 0x46
24#define PM8941_WLED_REG_MOD_EN_BIT BIT(7)
25#define PM8941_WLED_REG_MOD_EN_MASK BIT(7)
26
27#define PM8941_WLED_REG_SYNC 0x47
28#define PM8941_WLED_REG_SYNC_MASK 0x07
29#define PM8941_WLED_REG_SYNC_LED1 BIT(0)
30#define PM8941_WLED_REG_SYNC_LED2 BIT(1)
31#define PM8941_WLED_REG_SYNC_LED3 BIT(2)
32#define PM8941_WLED_REG_SYNC_ALL 0x07
33#define PM8941_WLED_REG_SYNC_CLEAR 0x00
34
35#define PM8941_WLED_REG_FREQ 0x4c
36#define PM8941_WLED_REG_FREQ_MASK 0x0f
37
38#define PM8941_WLED_REG_OVP 0x4d
39#define PM8941_WLED_REG_OVP_MASK 0x03
40
41#define PM8941_WLED_REG_BOOST 0x4e
42#define PM8941_WLED_REG_BOOST_MASK 0x07
43
44#define PM8941_WLED_REG_SINK 0x4f
45#define PM8941_WLED_REG_SINK_MASK 0xe0
46#define PM8941_WLED_REG_SINK_SHFT 0x05
47
48/* Per-'string' registers below */
49#define PM8941_WLED_REG_STR_OFFSET 0x10
50
51#define PM8941_WLED_REG_STR_MOD_EN_BASE 0x60
52#define PM8941_WLED_REG_STR_MOD_MASK BIT(7)
53#define PM8941_WLED_REG_STR_MOD_EN BIT(7)
54
55#define PM8941_WLED_REG_STR_SCALE_BASE 0x62
56#define PM8941_WLED_REG_STR_SCALE_MASK 0x1f
57
58#define PM8941_WLED_REG_STR_MOD_SRC_BASE 0x63
59#define PM8941_WLED_REG_STR_MOD_SRC_MASK 0x01
60#define PM8941_WLED_REG_STR_MOD_SRC_INT 0x00
61#define PM8941_WLED_REG_STR_MOD_SRC_EXT 0x01
62
63#define PM8941_WLED_REG_STR_CABC_BASE 0x66
64#define PM8941_WLED_REG_STR_CABC_MASK BIT(7)
65#define PM8941_WLED_REG_STR_CABC_EN BIT(7)
66
67struct pm8941_wled_config {
68 u32 i_boost_limit;
69 u32 ovp;
70 u32 switch_freq;
71 u32 num_strings;
72 u32 i_limit;
73 bool cs_out_en;
74 bool ext_gen;
75 bool cabc_en;
76};
77
78struct pm8941_wled {
79 struct regmap *regmap;
80 u16 addr;
81
82 struct led_classdev cdev;
83
84 struct pm8941_wled_config cfg;
85};
86
87static int pm8941_wled_set(struct led_classdev *cdev,
88 enum led_brightness value)
89{
90 struct pm8941_wled *wled;
91 u8 ctrl = 0;
92 u16 val;
93 int rc;
94 int i;
95
96 wled = container_of(cdev, struct pm8941_wled, cdev);
97
98 if (value != 0)
99 ctrl = PM8941_WLED_REG_MOD_EN_BIT;
100
101 val = value * PM8941_WLED_REG_VAL_MAX / LED_FULL;
102
103 rc = regmap_update_bits(wled->regmap,
104 wled->addr + PM8941_WLED_REG_MOD_EN,
105 PM8941_WLED_REG_MOD_EN_MASK, ctrl);
106 if (rc)
107 return rc;
108
109 for (i = 0; i < wled->cfg.num_strings; ++i) {
110 u8 v[2] = { val & 0xff, (val >> 8) & 0xf };
111
112 rc = regmap_bulk_write(wled->regmap,
113 wled->addr + PM8941_WLED_REG_VAL_BASE + 2 * i,
114 v, 2);
115 if (rc)
116 return rc;
117 }
118
119 rc = regmap_update_bits(wled->regmap,
120 wled->addr + PM8941_WLED_REG_SYNC,
121 PM8941_WLED_REG_SYNC_MASK, PM8941_WLED_REG_SYNC_ALL);
122 if (rc)
123 return rc;
124
125 rc = regmap_update_bits(wled->regmap,
126 wled->addr + PM8941_WLED_REG_SYNC,
127 PM8941_WLED_REG_SYNC_MASK, PM8941_WLED_REG_SYNC_CLEAR);
128 return rc;
129}
130
131static void pm8941_wled_set_brightness(struct led_classdev *cdev,
132 enum led_brightness value)
133{
134 if (pm8941_wled_set(cdev, value)) {
135 dev_err(cdev->dev, "Unable to set brightness\n");
136 return;
137 }
138 cdev->brightness = value;
139}
140
141static int pm8941_wled_setup(struct pm8941_wled *wled)
142{
143 int rc;
144 int i;
145
146 rc = regmap_update_bits(wled->regmap,
147 wled->addr + PM8941_WLED_REG_OVP,
148 PM8941_WLED_REG_OVP_MASK, wled->cfg.ovp);
149 if (rc)
150 return rc;
151
152 rc = regmap_update_bits(wled->regmap,
153 wled->addr + PM8941_WLED_REG_BOOST,
154 PM8941_WLED_REG_BOOST_MASK, wled->cfg.i_boost_limit);
155 if (rc)
156 return rc;
157
158 rc = regmap_update_bits(wled->regmap,
159 wled->addr + PM8941_WLED_REG_FREQ,
160 PM8941_WLED_REG_FREQ_MASK, wled->cfg.switch_freq);
161 if (rc)
162 return rc;
163
164 if (wled->cfg.cs_out_en) {
165 u8 all = (BIT(wled->cfg.num_strings) - 1)
166 << PM8941_WLED_REG_SINK_SHFT;
167
168 rc = regmap_update_bits(wled->regmap,
169 wled->addr + PM8941_WLED_REG_SINK,
170 PM8941_WLED_REG_SINK_MASK, all);
171 if (rc)
172 return rc;
173 }
174
175 for (i = 0; i < wled->cfg.num_strings; ++i) {
176 u16 addr = wled->addr + PM8941_WLED_REG_STR_OFFSET * i;
177
178 rc = regmap_update_bits(wled->regmap,
179 addr + PM8941_WLED_REG_STR_MOD_EN_BASE,
180 PM8941_WLED_REG_STR_MOD_MASK,
181 PM8941_WLED_REG_STR_MOD_EN);
182 if (rc)
183 return rc;
184
185 if (wled->cfg.ext_gen) {
186 rc = regmap_update_bits(wled->regmap,
187 addr + PM8941_WLED_REG_STR_MOD_SRC_BASE,
188 PM8941_WLED_REG_STR_MOD_SRC_MASK,
189 PM8941_WLED_REG_STR_MOD_SRC_EXT);
190 if (rc)
191 return rc;
192 }
193
194 rc = regmap_update_bits(wled->regmap,
195 addr + PM8941_WLED_REG_STR_SCALE_BASE,
196 PM8941_WLED_REG_STR_SCALE_MASK,
197 wled->cfg.i_limit);
198 if (rc)
199 return rc;
200
201 rc = regmap_update_bits(wled->regmap,
202 addr + PM8941_WLED_REG_STR_CABC_BASE,
203 PM8941_WLED_REG_STR_CABC_MASK,
204 wled->cfg.cabc_en ?
205 PM8941_WLED_REG_STR_CABC_EN : 0);
206 if (rc)
207 return rc;
208 }
209
210 return 0;
211}
212
213static const struct pm8941_wled_config pm8941_wled_config_defaults = {
214 .i_boost_limit = 3,
215 .i_limit = 20,
216 .ovp = 2,
217 .switch_freq = 5,
218 .num_strings = 0,
219 .cs_out_en = false,
220 .ext_gen = false,
221 .cabc_en = false,
222};
223
224struct pm8941_wled_var_cfg {
225 const u32 *values;
226 u32 (*fn)(u32);
227 int size;
228};
229
230static const u32 pm8941_wled_i_boost_limit_values[] = {
231 105, 385, 525, 805, 980, 1260, 1400, 1680,
232};
233
234static const struct pm8941_wled_var_cfg pm8941_wled_i_boost_limit_cfg = {
235 .values = pm8941_wled_i_boost_limit_values,
236 .size = ARRAY_SIZE(pm8941_wled_i_boost_limit_values),
237};
238
239static const u32 pm8941_wled_ovp_values[] = {
240 35, 32, 29, 27,
241};
242
243static const struct pm8941_wled_var_cfg pm8941_wled_ovp_cfg = {
244 .values = pm8941_wled_ovp_values,
245 .size = ARRAY_SIZE(pm8941_wled_ovp_values),
246};
247
248static u32 pm8941_wled_num_strings_values_fn(u32 idx)
249{
250 return idx + 1;
251}
252
253static const struct pm8941_wled_var_cfg pm8941_wled_num_strings_cfg = {
254 .fn = pm8941_wled_num_strings_values_fn,
255 .size = 3,
256};
257
258static u32 pm8941_wled_switch_freq_values_fn(u32 idx)
259{
260 return 19200 / (2 * (1 + idx));
261}
262
263static const struct pm8941_wled_var_cfg pm8941_wled_switch_freq_cfg = {
264 .fn = pm8941_wled_switch_freq_values_fn,
265 .size = 16,
266};
267
268static const struct pm8941_wled_var_cfg pm8941_wled_i_limit_cfg = {
269 .size = 26,
270};
271
272static u32 pm8941_wled_values(const struct pm8941_wled_var_cfg *cfg, u32 idx)
273{
274 if (idx >= cfg->size)
275 return UINT_MAX;
276 if (cfg->fn)
277 return cfg->fn(idx);
278 if (cfg->values)
279 return cfg->values[idx];
280 return idx;
281}
282
283static int pm8941_wled_configure(struct pm8941_wled *wled, struct device *dev)
284{
285 struct pm8941_wled_config *cfg = &wled->cfg;
286 u32 val;
287 int rc;
288 u32 c;
289 int i;
290 int j;
291
292 const struct {
293 const char *name;
294 u32 *val_ptr;
295 const struct pm8941_wled_var_cfg *cfg;
296 } u32_opts[] = {
297 {
298 "qcom,current-boost-limit",
299 &cfg->i_boost_limit,
300 .cfg = &pm8941_wled_i_boost_limit_cfg,
301 },
302 {
303 "qcom,current-limit",
304 &cfg->i_limit,
305 .cfg = &pm8941_wled_i_limit_cfg,
306 },
307 {
308 "qcom,ovp",
309 &cfg->ovp,
310 .cfg = &pm8941_wled_ovp_cfg,
311 },
312 {
313 "qcom,switching-freq",
314 &cfg->switch_freq,
315 .cfg = &pm8941_wled_switch_freq_cfg,
316 },
317 {
318 "qcom,num-strings",
319 &cfg->num_strings,
320 .cfg = &pm8941_wled_num_strings_cfg,
321 },
322 };
323 const struct {
324 const char *name;
325 bool *val_ptr;
326 } bool_opts[] = {
327 { "qcom,cs-out", &cfg->cs_out_en, },
328 { "qcom,ext-gen", &cfg->ext_gen, },
329 { "qcom,cabc", &cfg->cabc_en, },
330 };
331
332 rc = of_property_read_u32(dev->of_node, "reg", &val);
333 if (rc || val > 0xffff) {
334 dev_err(dev, "invalid IO resources\n");
335 return rc ? rc : -EINVAL;
336 }
337 wled->addr = val;
338
339 rc = of_property_read_string(dev->of_node, "label", &wled->cdev.name);
340 if (rc)
341 wled->cdev.name = dev->of_node->name;
342
343 wled->cdev.default_trigger = of_get_property(dev->of_node,
344 "linux,default-trigger", NULL);
345
346 *cfg = pm8941_wled_config_defaults;
347 for (i = 0; i < ARRAY_SIZE(u32_opts); ++i) {
348 rc = of_property_read_u32(dev->of_node, u32_opts[i].name, &val);
349 if (rc == -EINVAL) {
350 continue;
351 } else if (rc) {
352 dev_err(dev, "error reading '%s'\n", u32_opts[i].name);
353 return rc;
354 }
355
356 c = UINT_MAX;
357 for (j = 0; c != val; j++) {
358 c = pm8941_wled_values(u32_opts[i].cfg, j);
359 if (c == UINT_MAX) {
360 dev_err(dev, "invalid value for '%s'\n",
361 u32_opts[i].name);
362 return -EINVAL;
363 }
364 }
365
366 dev_dbg(dev, "'%s' = %u\n", u32_opts[i].name, c);
367 *u32_opts[i].val_ptr = j;
368 }
369
370 for (i = 0; i < ARRAY_SIZE(bool_opts); ++i) {
371 if (of_property_read_bool(dev->of_node, bool_opts[i].name))
372 *bool_opts[i].val_ptr = true;
373 }
374
375 cfg->num_strings = cfg->num_strings + 1;
376
377 return 0;
378}
379
380static int pm8941_wled_probe(struct platform_device *pdev)
381{
382 struct pm8941_wled *wled;
383 struct regmap *regmap;
384 int rc;
385
386 regmap = dev_get_regmap(pdev->dev.parent, NULL);
387 if (!regmap) {
388 dev_err(&pdev->dev, "Unable to get regmap\n");
389 return -EINVAL;
390 }
391
392 wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL);
393 if (!wled)
394 return -ENOMEM;
395
396 wled->regmap = regmap;
397
398 rc = pm8941_wled_configure(wled, &pdev->dev);
399 if (rc)
400 return rc;
401
402 rc = pm8941_wled_setup(wled);
403 if (rc)
404 return rc;
405
406 wled->cdev.brightness_set = pm8941_wled_set_brightness;
407
408 rc = devm_led_classdev_register(&pdev->dev, &wled->cdev);
409 if (rc)
410 return rc;
411
412 platform_set_drvdata(pdev, wled);
413
414 return 0;
415};
416
417static const struct of_device_id pm8941_wled_match_table[] = {
418 { .compatible = "qcom,pm8941-wled" },
419 {}
420};
421MODULE_DEVICE_TABLE(of, pm8941_wled_match_table);
422
423static struct platform_driver pm8941_wled_driver = {
424 .probe = pm8941_wled_probe,
425 .driver = {
426 .name = "pm8941-wled",
427 .of_match_table = pm8941_wled_match_table,
428 },
429};
430
431module_platform_driver(pm8941_wled_driver);
432
433MODULE_DESCRIPTION("pm8941 wled driver");
434MODULE_LICENSE("GPL v2");
435MODULE_ALIAS("platform:pm8941-wled");
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index f668500a2157..1d07e3e83d29 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -121,9 +121,6 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
121 return ret; 121 return ret;
122 } 122 }
123 123
124 if (child)
125 led_data->period = pwm_get_period(led_data->pwm);
126
127 led_data->can_sleep = pwm_can_sleep(led_data->pwm); 124 led_data->can_sleep = pwm_can_sleep(led_data->pwm);
128 if (led_data->can_sleep) 125 if (led_data->can_sleep)
129 INIT_WORK(&led_data->work, led_pwm_work); 126 INIT_WORK(&led_data->work, led_pwm_work);
diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h
new file mode 100644
index 000000000000..79fcef72ef57
--- /dev/null
+++ b/include/dt-bindings/leds/common.h
@@ -0,0 +1,21 @@
1/*
2 * This header provides macros for the common LEDs device tree bindings.
3 *
4 * Copyright (C) 2015, Samsung Electronics Co., Ltd.
5 *
6 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
7 */
8
9#ifndef __DT_BINDINGS_LEDS_H__
10#define __DT_BINDINGS_LEDS_H
11
12/* External trigger type */
13#define LEDS_TRIG_TYPE_EDGE 0
14#define LEDS_TRIG_TYPE_LEVEL 1
15
16/* Boost modes */
17#define LEDS_BOOST_OFF 0
18#define LEDS_BOOST_ADAPTIVE 1
19#define LEDS_BOOST_FIXED 2
20
21#endif /* __DT_BINDINGS_LEDS_H */
diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h
index 5ba2facd7a51..e97966d1fb8d 100644
--- a/include/linux/led-class-flash.h
+++ b/include/linux/led-class-flash.h
@@ -13,7 +13,6 @@
13#define __LINUX_FLASH_LEDS_H_INCLUDED 13#define __LINUX_FLASH_LEDS_H_INCLUDED
14 14
15#include <linux/leds.h> 15#include <linux/leds.h>
16#include <uapi/linux/v4l2-controls.h>
17 16
18struct device_node; 17struct device_node;
19struct led_classdev_flash; 18struct led_classdev_flash;
@@ -33,7 +32,7 @@ struct led_classdev_flash;
33#define LED_FAULT_LED_OVER_TEMPERATURE (1 << 8) 32#define LED_FAULT_LED_OVER_TEMPERATURE (1 << 8)
34#define LED_NUM_FLASH_FAULTS 9 33#define LED_NUM_FLASH_FAULTS 9
35 34
36#define LED_FLASH_MAX_SYSFS_GROUPS 7 35#define LED_FLASH_SYSFS_GROUPS_SIZE 5
37 36
38struct led_flash_ops { 37struct led_flash_ops {
39 /* set flash brightness */ 38 /* set flash brightness */
@@ -81,21 +80,7 @@ struct led_classdev_flash {
81 struct led_flash_setting timeout; 80 struct led_flash_setting timeout;
82 81
83 /* LED Flash class sysfs groups */ 82 /* LED Flash class sysfs groups */
84 const struct attribute_group *sysfs_groups[LED_FLASH_MAX_SYSFS_GROUPS]; 83 const struct attribute_group *sysfs_groups[LED_FLASH_SYSFS_GROUPS_SIZE];
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}; 84};
100 85
101static inline struct led_classdev_flash *lcdev_to_flcdev( 86static inline struct led_classdev_flash *lcdev_to_flcdev(
diff --git a/include/linux/leds.h b/include/linux/leds.h
index f70f84f35674..9a2b000094cf 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -47,7 +47,6 @@ struct led_classdev {
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) 49#define LED_DEV_CAP_FLASH (1 << 23)
50#define LED_DEV_CAP_SYNC_STROBE (1 << 24)
51 50
52 /* Set LED brightness level */ 51 /* Set LED brightness level */
53 /* Must not sleep, use a workqueue if needed */ 52 /* Must not sleep, use a workqueue if needed */
@@ -105,7 +104,11 @@ struct led_classdev {
105 104
106extern int led_classdev_register(struct device *parent, 105extern int led_classdev_register(struct device *parent,
107 struct led_classdev *led_cdev); 106 struct led_classdev *led_cdev);
107extern int devm_led_classdev_register(struct device *parent,
108 struct led_classdev *led_cdev);
108extern void led_classdev_unregister(struct led_classdev *led_cdev); 109extern void led_classdev_unregister(struct led_classdev *led_cdev);
110extern void devm_led_classdev_unregister(struct device *parent,
111 struct led_classdev *led_cdev);
109extern void led_classdev_suspend(struct led_classdev *led_cdev); 112extern void led_classdev_suspend(struct led_classdev *led_cdev);
110extern void led_classdev_resume(struct led_classdev *led_cdev); 113extern void led_classdev_resume(struct led_classdev *led_cdev);
111 114