aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-01 16:12:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-01 16:12:49 -0400
commit85724edecbdc19f53ed4b902fc3a32e4d1b61c9b (patch)
treeec44080accc2ea5571f28feef21488af97ee8d9a
parent477d7caeede0e3a933368440fc877b12c25dbb6d (diff)
parent28c5fe99016d28f15d1b825df8acb1558a3a63a1 (diff)
Merge tag 'leds_for_4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds
Pull LED updates from Jacek Anaszewski: "New drivers: - add LED support for MT6323 PMIC - add LED support for Motorola CPCAP PMIC New features and improvements: - add LED trigger for all CPUs aggregated which is useful on tiny boards with more CPU cores than LED pins - add OF variants of LED registering functions as a preparation for adding generic support for Device Tree parsing - dell-led improvements and cleanups, followed by moving it to the x86 platform driver subsystem which is a more appropriate place for it - extend pca9532 Device Tree support by adding the LEDs 'default-state' property - extend pca963x Device Tree support by adding nxp,inverted-out property for inverting the polarity of the output - remove ACPI support for lp3952 since it relied on a non-official ACPI IDs" * tag 'leds_for_4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds: leds: pca9532: Extend pca9532 device tree support leds: cpcap: new driver mfd: cpcap: Add missing include dependencies leds: lp3952: Use 'if (ret)' pattern leds: lp3952: Remove ACPI support for lp3952 leds: mt6323: Fix an off by one bug in probe dt-bindings: leds: Add document bindings for leds-mt6323 leds: Add LED support for MT6323 PMIC leds: gpio: use OF variant of LED registering function leds: core: add OF variants of LED registering functions platform/x86: dell-wmi-led: fix coding style issues dell-led: move driver to drivers/platform/x86/dell-wmi-led.c dell-led: remove code related to mic mute LED platform/x86: dell-laptop: import dell_micmute_led_set() from drivers/leds/dell-led.c ALSA: hda - rename dell_led_set_func to dell_micmute_led_set_func ALSA: hda - use dell_micmute_led_set() instead of dell_app_wmi_led_set() dell-led: remove GUID check from dell_micmute_led_set() leds/trigger/cpu: Add LED trigger for all CPUs aggregated
-rw-r--r--Documentation/devicetree/bindings/leds/leds-cpcap.txt29
-rw-r--r--Documentation/devicetree/bindings/leds/leds-mt6323.txt60
-rw-r--r--Documentation/devicetree/bindings/leds/leds-pca9532.txt10
-rw-r--r--drivers/leds/Kconfig27
-rw-r--r--drivers/leds/Makefile3
-rw-r--r--drivers/leds/led-class.c26
-rw-r--r--drivers/leds/leds-cpcap.c239
-rw-r--r--drivers/leds/leds-gpio.c12
-rw-r--r--drivers/leds/leds-lp3952.c18
-rw-r--r--drivers/leds/leds-mt6323.c502
-rw-r--r--drivers/leds/leds-pca9532.c27
-rw-r--r--drivers/leds/trigger/ledtrig-cpu.c33
-rw-r--r--drivers/platform/x86/Kconfig8
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/dell-laptop.c28
-rw-r--r--drivers/platform/x86/dell-wmi-led.c (renamed from drivers/leds/dell-led.c)141
-rw-r--r--include/linux/dell-led.h6
-rw-r--r--include/linux/leds-pca9532.h4
-rw-r--r--include/linux/leds.h14
-rw-r--r--include/linux/mfd/motorola-cpcap.h3
-rw-r--r--sound/pci/hda/dell_wmi_helper.c30
21 files changed, 1043 insertions, 178 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-cpcap.txt b/Documentation/devicetree/bindings/leds/leds-cpcap.txt
new file mode 100644
index 000000000000..ebf7cdc7f70c
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-cpcap.txt
@@ -0,0 +1,29 @@
1Motorola CPCAP PMIC LEDs
2------------------------
3
4This module is part of the CPCAP. For more details about the whole
5chip see Documentation/devicetree/bindings/mfd/motorola-cpcap.txt.
6
7Requires node properties:
8- compatible: should be one of
9 * "motorola,cpcap-led-mdl" (Main Display Lighting)
10 * "motorola,cpcap-led-kl" (Keyboard Lighting)
11 * "motorola,cpcap-led-adl" (Aux Display Lighting)
12 * "motorola,cpcap-led-red" (Red Triode)
13 * "motorola,cpcap-led-green" (Green Triode)
14 * "motorola,cpcap-led-blue" (Blue Triode)
15 * "motorola,cpcap-led-cf" (Camera Flash)
16 * "motorola,cpcap-led-bt" (Bluetooth)
17 * "motorola,cpcap-led-cp" (Camera Privacy LED)
18- label: see Documentation/devicetree/bindings/leds/common.txt
19- vdd-supply: A phandle to the regulator powering the LED
20
21Example:
22
23&cpcap {
24 cpcap_led_red: red-led {
25 compatible = "motorola,cpcap-led-red";
26 label = "cpcap:red";
27 vdd-supply = <&sw5>;
28 };
29};
diff --git a/Documentation/devicetree/bindings/leds/leds-mt6323.txt b/Documentation/devicetree/bindings/leds/leds-mt6323.txt
new file mode 100644
index 000000000000..45bf9f7d85f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-mt6323.txt
@@ -0,0 +1,60 @@
1Device Tree Bindings for LED support on MT6323 PMIC
2
3MT6323 LED controller is subfunction provided by MT6323 PMIC, so the LED
4controllers are defined as the subnode of the function node provided by MT6323
5PMIC controller that is being defined as one kind of Muti-Function Device (MFD)
6using shared bus called PMIC wrapper for each subfunction to access remote
7MT6323 PMIC hardware.
8
9For MT6323 MFD bindings see:
10Documentation/devicetree/bindings/mfd/mt6397.txt
11For MediaTek PMIC wrapper bindings see:
12Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
13
14Required properties:
15- compatible : Must be "mediatek,mt6323-led"
16- address-cells : Must be 1
17- size-cells : Must be 0
18
19Each led is represented as a child node of the mediatek,mt6323-led that
20describes the initial behavior for each LED physically and currently only four
21LED child nodes can be supported.
22
23Required properties for the LED child node:
24- reg : LED channel number (0..3)
25
26Optional properties for the LED child node:
27- label : See Documentation/devicetree/bindings/leds/common.txt
28- linux,default-trigger : See Documentation/devicetree/bindings/leds/common.txt
29- default-state: See Documentation/devicetree/bindings/leds/common.txt
30
31Example:
32
33 mt6323: pmic {
34 compatible = "mediatek,mt6323";
35
36 ...
37
38 mt6323led: leds {
39 compatible = "mediatek,mt6323-led";
40 #address-cells = <1>;
41 #size-cells = <0>;
42
43 led@0 {
44 reg = <0>;
45 label = "LED0";
46 linux,default-trigger = "timer";
47 default-state = "on";
48 };
49 led@1 {
50 reg = <1>;
51 label = "LED1";
52 default-state = "off";
53 };
54 led@2 {
55 reg = <2>;
56 label = "LED2";
57 default-state = "on";
58 };
59 };
60 };
diff --git a/Documentation/devicetree/bindings/leds/leds-pca9532.txt b/Documentation/devicetree/bindings/leds/leds-pca9532.txt
index 198f3ba0e01f..f769c52e3643 100644
--- a/Documentation/devicetree/bindings/leds/leds-pca9532.txt
+++ b/Documentation/devicetree/bindings/leds/leds-pca9532.txt
@@ -17,6 +17,8 @@ Optional sub-node properties:
17 - label: see Documentation/devicetree/bindings/leds/common.txt 17 - label: see Documentation/devicetree/bindings/leds/common.txt
18 - type: Output configuration, see dt-bindings/leds/leds-pca9532.h (default NONE) 18 - type: Output configuration, see dt-bindings/leds/leds-pca9532.h (default NONE)
19 - linux,default-trigger: see Documentation/devicetree/bindings/leds/common.txt 19 - linux,default-trigger: see Documentation/devicetree/bindings/leds/common.txt
20 - default-state: see Documentation/devicetree/bindings/leds/common.txt
21 This property is only valid for sub-nodes of type <PCA9532_TYPE_LED>.
20 22
21Example: 23Example:
22 #include <dt-bindings/leds/leds-pca9532.h> 24 #include <dt-bindings/leds/leds-pca9532.h>
@@ -33,6 +35,14 @@ Example:
33 label = "pca:green:power"; 35 label = "pca:green:power";
34 type = <PCA9532_TYPE_LED>; 36 type = <PCA9532_TYPE_LED>;
35 }; 37 };
38 kernel-booting {
39 type = <PCA9532_TYPE_LED>;
40 default-state = "on";
41 };
42 sys-stat {
43 type = <PCA9532_TYPE_LED>;
44 default-state = "keep"; // don't touch, was set by U-Boot
45 };
36 }; 46 };
37 47
38For more product information please see the link below: 48For more product information please see the link below:
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 275f467956ee..6c2999872090 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -76,6 +76,15 @@ config LEDS_BCM6358
76 This option enables support for LEDs connected to the BCM6358 76 This option enables support for LEDs connected to the BCM6358
77 LED HW controller accessed via MMIO registers. 77 LED HW controller accessed via MMIO registers.
78 78
79config LEDS_CPCAP
80 tristate "LED Support for Motorola CPCAP"
81 depends on LEDS_CLASS
82 depends on MFD_CPCAP
83 depends on OF
84 help
85 This option enables support for LEDs offered by Motorola's
86 CPCAP PMIC.
87
79config LEDS_LM3530 88config LEDS_LM3530
80 tristate "LCD Backlight driver for LM3530" 89 tristate "LCD Backlight driver for LM3530"
81 depends on LEDS_CLASS 90 depends on LEDS_CLASS
@@ -126,6 +135,14 @@ config LEDS_MIKROTIK_RB532
126 This option enables support for the so called "User LED" of 135 This option enables support for the so called "User LED" of
127 Mikrotik's Routerboard 532. 136 Mikrotik's Routerboard 532.
128 137
138config LEDS_MT6323
139 tristate "LED Support for Mediatek MT6323 PMIC"
140 depends on LEDS_CLASS
141 depends on MFD_MT6397
142 help
143 This option enables support for on-chip LED drivers found on
144 Mediatek MT6323 PMIC.
145
129config LEDS_S3C24XX 146config LEDS_S3C24XX
130 tristate "LED Support for Samsung S3C24XX GPIO LEDs" 147 tristate "LED Support for Samsung S3C24XX GPIO LEDs"
131 depends on LEDS_CLASS 148 depends on LEDS_CLASS
@@ -241,7 +258,6 @@ config LEDS_LP3952
241 tristate "LED Support for TI LP3952 2 channel LED driver" 258 tristate "LED Support for TI LP3952 2 channel LED driver"
242 depends on LEDS_CLASS 259 depends on LEDS_CLASS
243 depends on I2C 260 depends on I2C
244 depends on ACPI
245 depends on GPIOLIB 261 depends on GPIOLIB
246 select REGMAP_I2C 262 select REGMAP_I2C
247 help 263 help
@@ -463,15 +479,6 @@ config LEDS_ADP5520
463 To compile this driver as a module, choose M here: the module will 479 To compile this driver as a module, choose M here: the module will
464 be called leds-adp5520. 480 be called leds-adp5520.
465 481
466config LEDS_DELL_NETBOOKS
467 tristate "External LED on Dell Business Netbooks"
468 depends on LEDS_CLASS
469 depends on X86 && ACPI_WMI
470 depends on DELL_SMBIOS
471 help
472 This adds support for the Latitude 2100 and similar
473 notebooks that have an external LED.
474
475config LEDS_MC13783 482config LEDS_MC13783
476 tristate "LED Support for MC13XXX PMIC" 483 tristate "LED Support for MC13XXX PMIC"
477 depends on LEDS_CLASS 484 depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 6b8273736478..45f133962ed8 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o
11obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o 11obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o
12obj-$(CONFIG_LEDS_BCM6358) += leds-bcm6358.o 12obj-$(CONFIG_LEDS_BCM6358) += leds-bcm6358.o
13obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o 13obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
14obj-$(CONFIG_LEDS_CPCAP) += leds-cpcap.o
14obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o 15obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
15obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o 16obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o
16obj-$(CONFIG_LEDS_LM3533) += leds-lm3533.o 17obj-$(CONFIG_LEDS_LM3533) += leds-lm3533.o
@@ -52,7 +53,6 @@ obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o
52obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o 53obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o
53obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o 54obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
54obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o 55obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o
55obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o
56obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o 56obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
57obj-$(CONFIG_LEDS_NS2) += leds-ns2.o 57obj-$(CONFIG_LEDS_NS2) += leds-ns2.o
58obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o 58obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
@@ -72,6 +72,7 @@ obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o
72obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o 72obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o
73obj-$(CONFIG_LEDS_MLXCPLD) += leds-mlxcpld.o 73obj-$(CONFIG_LEDS_MLXCPLD) += leds-mlxcpld.o
74obj-$(CONFIG_LEDS_NIC78BX) += leds-nic78bx.o 74obj-$(CONFIG_LEDS_NIC78BX) += leds-nic78bx.o
75obj-$(CONFIG_LEDS_MT6323) += leds-mt6323.o
75 76
76# LED SPI Drivers 77# LED SPI Drivers
77obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 78obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index f2b0a80a62b4..b0e2d55acbd6 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -244,11 +244,14 @@ static int led_classdev_next_name(const char *init_name, char *name,
244} 244}
245 245
246/** 246/**
247 * led_classdev_register - register a new object of led_classdev class. 247 * of_led_classdev_register - register a new object of led_classdev class.
248 * @parent: The device to register. 248 *
249 * @parent: parent of LED device
249 * @led_cdev: the led_classdev structure for this device. 250 * @led_cdev: the led_classdev structure for this device.
251 * @np: DT node describing this LED
250 */ 252 */
251int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) 253int of_led_classdev_register(struct device *parent, struct device_node *np,
254 struct led_classdev *led_cdev)
252{ 255{
253 char name[LED_MAX_NAME_SIZE]; 256 char name[LED_MAX_NAME_SIZE];
254 int ret; 257 int ret;
@@ -261,6 +264,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
261 led_cdev, led_cdev->groups, "%s", name); 264 led_cdev, led_cdev->groups, "%s", name);
262 if (IS_ERR(led_cdev->dev)) 265 if (IS_ERR(led_cdev->dev))
263 return PTR_ERR(led_cdev->dev); 266 return PTR_ERR(led_cdev->dev);
267 led_cdev->dev->of_node = np;
264 268
265 if (ret) 269 if (ret)
266 dev_warn(parent, "Led %s renamed to %s due to name collision", 270 dev_warn(parent, "Led %s renamed to %s due to name collision",
@@ -303,7 +307,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
303 307
304 return 0; 308 return 0;
305} 309}
306EXPORT_SYMBOL_GPL(led_classdev_register); 310EXPORT_SYMBOL_GPL(of_led_classdev_register);
307 311
308/** 312/**
309 * led_classdev_unregister - unregisters a object of led_properties class. 313 * led_classdev_unregister - unregisters a object of led_properties class.
@@ -348,12 +352,14 @@ static void devm_led_classdev_release(struct device *dev, void *res)
348} 352}
349 353
350/** 354/**
351 * devm_led_classdev_register - resource managed led_classdev_register() 355 * devm_of_led_classdev_register - resource managed led_classdev_register()
352 * @parent: The device to register. 356 *
357 * @parent: parent of LED device
353 * @led_cdev: the led_classdev structure for this device. 358 * @led_cdev: the led_classdev structure for this device.
354 */ 359 */
355int devm_led_classdev_register(struct device *parent, 360int devm_of_led_classdev_register(struct device *parent,
356 struct led_classdev *led_cdev) 361 struct device_node *np,
362 struct led_classdev *led_cdev)
357{ 363{
358 struct led_classdev **dr; 364 struct led_classdev **dr;
359 int rc; 365 int rc;
@@ -362,7 +368,7 @@ int devm_led_classdev_register(struct device *parent,
362 if (!dr) 368 if (!dr)
363 return -ENOMEM; 369 return -ENOMEM;
364 370
365 rc = led_classdev_register(parent, led_cdev); 371 rc = of_led_classdev_register(parent, np, led_cdev);
366 if (rc) { 372 if (rc) {
367 devres_free(dr); 373 devres_free(dr);
368 return rc; 374 return rc;
@@ -373,7 +379,7 @@ int devm_led_classdev_register(struct device *parent,
373 379
374 return 0; 380 return 0;
375} 381}
376EXPORT_SYMBOL_GPL(devm_led_classdev_register); 382EXPORT_SYMBOL_GPL(devm_of_led_classdev_register);
377 383
378static int devm_led_classdev_match(struct device *dev, void *res, void *data) 384static int devm_led_classdev_match(struct device *dev, void *res, void *data)
379{ 385{
diff --git a/drivers/leds/leds-cpcap.c b/drivers/leds/leds-cpcap.c
new file mode 100644
index 000000000000..f0f28c442807
--- /dev/null
+++ b/drivers/leds/leds-cpcap.c
@@ -0,0 +1,239 @@
1/*
2 * Copyright (c) 2017 Sebastian Reichel <sre@kernel.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 or
6 * later as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/leds.h>
15#include <linux/mfd/motorola-cpcap.h>
16#include <linux/module.h>
17#include <linux/mutex.h>
18#include <linux/of_device.h>
19#include <linux/platform_device.h>
20#include <linux/regmap.h>
21#include <linux/regulator/consumer.h>
22
23#define CPCAP_LED_NO_CURRENT 0x0001
24
25struct cpcap_led_info {
26 u16 reg;
27 u16 mask;
28 u16 limit;
29 u16 init_mask;
30 u16 init_val;
31};
32
33static const struct cpcap_led_info cpcap_led_red = {
34 .reg = CPCAP_REG_REDC,
35 .mask = 0x03FF,
36 .limit = 31,
37};
38
39static const struct cpcap_led_info cpcap_led_green = {
40 .reg = CPCAP_REG_GREENC,
41 .mask = 0x03FF,
42 .limit = 31,
43};
44
45static const struct cpcap_led_info cpcap_led_blue = {
46 .reg = CPCAP_REG_BLUEC,
47 .mask = 0x03FF,
48 .limit = 31,
49};
50
51/* aux display light */
52static const struct cpcap_led_info cpcap_led_adl = {
53 .reg = CPCAP_REG_ADLC,
54 .mask = 0x000F,
55 .limit = 1,
56 .init_mask = 0x7FFF,
57 .init_val = 0x5FF0,
58};
59
60/* camera privacy led */
61static const struct cpcap_led_info cpcap_led_cp = {
62 .reg = CPCAP_REG_CLEDC,
63 .mask = 0x0007,
64 .limit = 1,
65 .init_mask = 0x03FF,
66 .init_val = 0x0008,
67};
68
69struct cpcap_led {
70 struct led_classdev led;
71 const struct cpcap_led_info *info;
72 struct device *dev;
73 struct regmap *regmap;
74 struct mutex update_lock;
75 struct regulator *vdd;
76 bool powered;
77
78 u32 current_limit;
79};
80
81static u16 cpcap_led_val(u8 current_limit, u8 duty_cycle)
82{
83 current_limit &= 0x1f; /* 5 bit */
84 duty_cycle &= 0x0f; /* 4 bit */
85
86 return current_limit << 4 | duty_cycle;
87}
88
89static int cpcap_led_set_power(struct cpcap_led *led, bool status)
90{
91 int err;
92
93 if (status == led->powered)
94 return 0;
95
96 if (status)
97 err = regulator_enable(led->vdd);
98 else
99 err = regulator_disable(led->vdd);
100
101 if (err) {
102 dev_err(led->dev, "regulator failure: %d", err);
103 return err;
104 }
105
106 led->powered = status;
107
108 return 0;
109}
110
111static int cpcap_led_set(struct led_classdev *ledc, enum led_brightness value)
112{
113 struct cpcap_led *led = container_of(ledc, struct cpcap_led, led);
114 int brightness;
115 int err;
116
117 mutex_lock(&led->update_lock);
118
119 if (value > LED_OFF) {
120 err = cpcap_led_set_power(led, true);
121 if (err)
122 goto exit;
123 }
124
125 if (value == LED_OFF) {
126 /* Avoid HW issue by turning off current before duty cycle */
127 err = regmap_update_bits(led->regmap,
128 led->info->reg, led->info->mask, CPCAP_LED_NO_CURRENT);
129 if (err) {
130 dev_err(led->dev, "regmap failed: %d", err);
131 goto exit;
132 }
133
134 brightness = cpcap_led_val(value, LED_OFF);
135 } else {
136 brightness = cpcap_led_val(value, LED_ON);
137 }
138
139 err = regmap_update_bits(led->regmap, led->info->reg, led->info->mask,
140 brightness);
141 if (err) {
142 dev_err(led->dev, "regmap failed: %d", err);
143 goto exit;
144 }
145
146 if (value == LED_OFF) {
147 err = cpcap_led_set_power(led, false);
148 if (err)
149 goto exit;
150 }
151
152exit:
153 mutex_unlock(&led->update_lock);
154 return err;
155}
156
157static const struct of_device_id cpcap_led_of_match[] = {
158 { .compatible = "motorola,cpcap-led-red", .data = &cpcap_led_red },
159 { .compatible = "motorola,cpcap-led-green", .data = &cpcap_led_green },
160 { .compatible = "motorola,cpcap-led-blue", .data = &cpcap_led_blue },
161 { .compatible = "motorola,cpcap-led-adl", .data = &cpcap_led_adl },
162 { .compatible = "motorola,cpcap-led-cp", .data = &cpcap_led_cp },
163 {},
164};
165MODULE_DEVICE_TABLE(of, cpcap_led_of_match);
166
167static int cpcap_led_probe(struct platform_device *pdev)
168{
169 const struct of_device_id *match;
170 struct cpcap_led *led;
171 int err;
172
173 match = of_match_device(of_match_ptr(cpcap_led_of_match), &pdev->dev);
174 if (!match || !match->data)
175 return -EINVAL;
176
177 led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
178 if (!led)
179 return -ENOMEM;
180 platform_set_drvdata(pdev, led);
181 led->info = match->data;
182 led->dev = &pdev->dev;
183
184 if (led->info->reg == 0x0000) {
185 dev_err(led->dev, "Unsupported LED");
186 return -ENODEV;
187 }
188
189 led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
190 if (!led->regmap)
191 return -ENODEV;
192
193 led->vdd = devm_regulator_get(&pdev->dev, "vdd");
194 if (IS_ERR(led->vdd)) {
195 err = PTR_ERR(led->vdd);
196 dev_err(led->dev, "Couldn't get regulator: %d", err);
197 return err;
198 }
199
200 err = device_property_read_string(&pdev->dev, "label", &led->led.name);
201 if (err) {
202 dev_err(led->dev, "Couldn't read LED label: %d", err);
203 return err;
204 }
205
206 if (led->info->init_mask) {
207 err = regmap_update_bits(led->regmap, led->info->reg,
208 led->info->init_mask, led->info->init_val);
209 if (err) {
210 dev_err(led->dev, "regmap failed: %d", err);
211 return err;
212 }
213 }
214
215 mutex_init(&led->update_lock);
216
217 led->led.max_brightness = led->info->limit;
218 led->led.brightness_set_blocking = cpcap_led_set;
219 err = devm_led_classdev_register(&pdev->dev, &led->led);
220 if (err) {
221 dev_err(led->dev, "Couldn't register LED: %d", err);
222 return err;
223 }
224
225 return 0;
226}
227
228static struct platform_driver cpcap_led_driver = {
229 .probe = cpcap_led_probe,
230 .driver = {
231 .name = "cpcap-led",
232 .of_match_table = cpcap_led_of_match,
233 },
234};
235module_platform_driver(cpcap_led_driver);
236
237MODULE_DESCRIPTION("CPCAP LED driver");
238MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
239MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 066fc7590729..e753ba93ba1e 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -77,7 +77,7 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
77 77
78static int create_gpio_led(const struct gpio_led *template, 78static int create_gpio_led(const struct gpio_led *template,
79 struct gpio_led_data *led_dat, struct device *parent, 79 struct gpio_led_data *led_dat, struct device *parent,
80 gpio_blink_set_t blink_set) 80 struct device_node *np, gpio_blink_set_t blink_set)
81{ 81{
82 int ret, state; 82 int ret, state;
83 83
@@ -139,7 +139,7 @@ static int create_gpio_led(const struct gpio_led *template,
139 if (ret < 0) 139 if (ret < 0)
140 return ret; 140 return ret;
141 141
142 return devm_led_classdev_register(parent, &led_dat->cdev); 142 return devm_of_led_classdev_register(parent, np, &led_dat->cdev);
143} 143}
144 144
145struct gpio_leds_priv { 145struct gpio_leds_priv {
@@ -208,7 +208,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
208 if (fwnode_property_present(child, "panic-indicator")) 208 if (fwnode_property_present(child, "panic-indicator"))
209 led.panic_indicator = 1; 209 led.panic_indicator = 1;
210 210
211 ret = create_gpio_led(&led, led_dat, dev, NULL); 211 ret = create_gpio_led(&led, led_dat, dev, np, NULL);
212 if (ret < 0) { 212 if (ret < 0) {
213 fwnode_handle_put(child); 213 fwnode_handle_put(child);
214 return ERR_PTR(ret); 214 return ERR_PTR(ret);
@@ -242,9 +242,9 @@ static int gpio_led_probe(struct platform_device *pdev)
242 242
243 priv->num_leds = pdata->num_leds; 243 priv->num_leds = pdata->num_leds;
244 for (i = 0; i < priv->num_leds; i++) { 244 for (i = 0; i < priv->num_leds; i++) {
245 ret = create_gpio_led(&pdata->leds[i], 245 ret = create_gpio_led(&pdata->leds[i], &priv->leds[i],
246 &priv->leds[i], 246 &pdev->dev, NULL,
247 &pdev->dev, pdata->gpio_blink_set); 247 pdata->gpio_blink_set);
248 if (ret < 0) 248 if (ret < 0)
249 return ret; 249 return ret;
250 } 250 }
diff --git a/drivers/leds/leds-lp3952.c b/drivers/leds/leds-lp3952.c
index 4847e89883a7..847f7f282126 100644
--- a/drivers/leds/leds-lp3952.c
+++ b/drivers/leds/leds-lp3952.c
@@ -10,7 +10,6 @@
10 * 10 *
11 */ 11 */
12 12
13#include <linux/acpi.h>
14#include <linux/delay.h> 13#include <linux/delay.h>
15#include <linux/gpio.h> 14#include <linux/gpio.h>
16#include <linux/i2c.h> 15#include <linux/i2c.h>
@@ -103,10 +102,11 @@ static int lp3952_get_label(struct device *dev, const char *label, char *dest)
103 const char *str; 102 const char *str;
104 103
105 ret = device_property_read_string(dev, label, &str); 104 ret = device_property_read_string(dev, label, &str);
106 if (!ret) 105 if (ret)
107 strncpy(dest, str, LP3952_LABEL_MAX_LEN); 106 return ret;
108 107
109 return ret; 108 strncpy(dest, str, LP3952_LABEL_MAX_LEN);
109 return 0;
110} 110}
111 111
112static int lp3952_register_led_classdev(struct lp3952_led_array *priv) 112static int lp3952_register_led_classdev(struct lp3952_led_array *priv)
@@ -276,19 +276,9 @@ static const struct i2c_device_id lp3952_id[] = {
276}; 276};
277MODULE_DEVICE_TABLE(i2c, lp3952_id); 277MODULE_DEVICE_TABLE(i2c, lp3952_id);
278 278
279#ifdef CONFIG_ACPI
280static const struct acpi_device_id lp3952_acpi_match[] = {
281 {"TXNW3952", 0},
282 {}
283};
284
285MODULE_DEVICE_TABLE(acpi, lp3952_acpi_match);
286#endif
287
288static struct i2c_driver lp3952_i2c_driver = { 279static struct i2c_driver lp3952_i2c_driver = {
289 .driver = { 280 .driver = {
290 .name = LP3952_NAME, 281 .name = LP3952_NAME,
291 .acpi_match_table = ACPI_PTR(lp3952_acpi_match),
292 }, 282 },
293 .probe = lp3952_probe, 283 .probe = lp3952_probe,
294 .remove = lp3952_remove, 284 .remove = lp3952_remove,
diff --git a/drivers/leds/leds-mt6323.c b/drivers/leds/leds-mt6323.c
new file mode 100644
index 000000000000..8893c74e9a1f
--- /dev/null
+++ b/drivers/leds/leds-mt6323.c
@@ -0,0 +1,502 @@
1/*
2 * LED driver for Mediatek MT6323 PMIC
3 *
4 * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16#include <linux/kernel.h>
17#include <linux/leds.h>
18#include <linux/mfd/mt6323/registers.h>
19#include <linux/mfd/mt6397/core.h>
20#include <linux/module.h>
21#include <linux/of.h>
22#include <linux/platform_device.h>
23#include <linux/regmap.h>
24
25/*
26 * Register field for MT6323_TOP_CKPDN0 to enable
27 * 32K clock common for LED device.
28 */
29#define MT6323_RG_DRV_32K_CK_PDN BIT(11)
30#define MT6323_RG_DRV_32K_CK_PDN_MASK BIT(11)
31
32/*
33 * Register field for MT6323_TOP_CKPDN2 to enable
34 * individual clock for LED device.
35 */
36#define MT6323_RG_ISINK_CK_PDN(i) BIT(i)
37#define MT6323_RG_ISINK_CK_PDN_MASK(i) BIT(i)
38
39/*
40 * Register field for MT6323_TOP_CKCON1 to select
41 * clock source.
42 */
43#define MT6323_RG_ISINK_CK_SEL_MASK(i) (BIT(10) << (i))
44
45/*
46 * Register for MT6323_ISINK_CON0 to setup the
47 * duty cycle of the blink.
48 */
49#define MT6323_ISINK_CON0(i) (MT6323_ISINK0_CON0 + 0x8 * (i))
50#define MT6323_ISINK_DIM_DUTY_MASK (0x1f << 8)
51#define MT6323_ISINK_DIM_DUTY(i) (((i) << 8) & \
52 MT6323_ISINK_DIM_DUTY_MASK)
53
54/* Register to setup the period of the blink. */
55#define MT6323_ISINK_CON1(i) (MT6323_ISINK0_CON1 + 0x8 * (i))
56#define MT6323_ISINK_DIM_FSEL_MASK (0xffff)
57#define MT6323_ISINK_DIM_FSEL(i) ((i) & MT6323_ISINK_DIM_FSEL_MASK)
58
59/* Register to control the brightness. */
60#define MT6323_ISINK_CON2(i) (MT6323_ISINK0_CON2 + 0x8 * (i))
61#define MT6323_ISINK_CH_STEP_SHIFT 12
62#define MT6323_ISINK_CH_STEP_MASK (0x7 << 12)
63#define MT6323_ISINK_CH_STEP(i) (((i) << 12) & \
64 MT6323_ISINK_CH_STEP_MASK)
65#define MT6323_ISINK_SFSTR0_TC_MASK (0x3 << 1)
66#define MT6323_ISINK_SFSTR0_TC(i) (((i) << 1) & \
67 MT6323_ISINK_SFSTR0_TC_MASK)
68#define MT6323_ISINK_SFSTR0_EN_MASK BIT(0)
69#define MT6323_ISINK_SFSTR0_EN BIT(0)
70
71/* Register to LED channel enablement. */
72#define MT6323_ISINK_CH_EN_MASK(i) BIT(i)
73#define MT6323_ISINK_CH_EN(i) BIT(i)
74
75#define MT6323_MAX_PERIOD 10000
76#define MT6323_MAX_LEDS 4
77#define MT6323_MAX_BRIGHTNESS 6
78#define MT6323_UNIT_DUTY 3125
79#define MT6323_CAL_HW_DUTY(o, p) DIV_ROUND_CLOSEST((o) * 100000ul,\
80 (p) * MT6323_UNIT_DUTY)
81
82struct mt6323_leds;
83
84/**
85 * struct mt6323_led - state container for the LED device
86 * @id: the identifier in MT6323 LED device
87 * @parent: the pointer to MT6323 LED controller
88 * @cdev: LED class device for this LED device
89 * @current_brightness: current state of the LED device
90 */
91struct mt6323_led {
92 int id;
93 struct mt6323_leds *parent;
94 struct led_classdev cdev;
95 enum led_brightness current_brightness;
96};
97
98/**
99 * struct mt6323_leds - state container for holding LED controller
100 * of the driver
101 * @dev: the device pointer
102 * @hw: the underlying hardware providing shared
103 * bus for the register operations
104 * @lock: the lock among process context
105 * @led: the array that contains the state of individual
106 * LED device
107 */
108struct mt6323_leds {
109 struct device *dev;
110 struct mt6397_chip *hw;
111 /* protect among process context */
112 struct mutex lock;
113 struct mt6323_led *led[MT6323_MAX_LEDS];
114};
115
116static int mt6323_led_hw_brightness(struct led_classdev *cdev,
117 enum led_brightness brightness)
118{
119 struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
120 struct mt6323_leds *leds = led->parent;
121 struct regmap *regmap = leds->hw->regmap;
122 u32 con2_mask = 0, con2_val = 0;
123 int ret;
124
125 /*
126 * Setup current output for the corresponding
127 * brightness level.
128 */
129 con2_mask |= MT6323_ISINK_CH_STEP_MASK |
130 MT6323_ISINK_SFSTR0_TC_MASK |
131 MT6323_ISINK_SFSTR0_EN_MASK;
132 con2_val |= MT6323_ISINK_CH_STEP(brightness - 1) |
133 MT6323_ISINK_SFSTR0_TC(2) |
134 MT6323_ISINK_SFSTR0_EN;
135
136 ret = regmap_update_bits(regmap, MT6323_ISINK_CON2(led->id),
137 con2_mask, con2_val);
138 return ret;
139}
140
141static int mt6323_led_hw_off(struct led_classdev *cdev)
142{
143 struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
144 struct mt6323_leds *leds = led->parent;
145 struct regmap *regmap = leds->hw->regmap;
146 unsigned int status;
147 int ret;
148
149 status = MT6323_ISINK_CH_EN(led->id);
150 ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL,
151 MT6323_ISINK_CH_EN_MASK(led->id), ~status);
152 if (ret < 0)
153 return ret;
154
155 usleep_range(100, 300);
156 ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2,
157 MT6323_RG_ISINK_CK_PDN_MASK(led->id),
158 MT6323_RG_ISINK_CK_PDN(led->id));
159 if (ret < 0)
160 return ret;
161
162 return 0;
163}
164
165static enum led_brightness
166mt6323_get_led_hw_brightness(struct led_classdev *cdev)
167{
168 struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
169 struct mt6323_leds *leds = led->parent;
170 struct regmap *regmap = leds->hw->regmap;
171 unsigned int status;
172 int ret;
173
174 ret = regmap_read(regmap, MT6323_TOP_CKPDN2, &status);
175 if (ret < 0)
176 return ret;
177
178 if (status & MT6323_RG_ISINK_CK_PDN_MASK(led->id))
179 return 0;
180
181 ret = regmap_read(regmap, MT6323_ISINK_EN_CTRL, &status);
182 if (ret < 0)
183 return ret;
184
185 if (!(status & MT6323_ISINK_CH_EN(led->id)))
186 return 0;
187
188 ret = regmap_read(regmap, MT6323_ISINK_CON2(led->id), &status);
189 if (ret < 0)
190 return ret;
191
192 return ((status & MT6323_ISINK_CH_STEP_MASK)
193 >> MT6323_ISINK_CH_STEP_SHIFT) + 1;
194}
195
196static int mt6323_led_hw_on(struct led_classdev *cdev,
197 enum led_brightness brightness)
198{
199 struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
200 struct mt6323_leds *leds = led->parent;
201 struct regmap *regmap = leds->hw->regmap;
202 unsigned int status;
203 int ret;
204
205 /*
206 * Setup required clock source, enable the corresponding
207 * clock and channel and let work with continuous blink as
208 * the default.
209 */
210 ret = regmap_update_bits(regmap, MT6323_TOP_CKCON1,
211 MT6323_RG_ISINK_CK_SEL_MASK(led->id), 0);
212 if (ret < 0)
213 return ret;
214
215 status = MT6323_RG_ISINK_CK_PDN(led->id);
216 ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2,
217 MT6323_RG_ISINK_CK_PDN_MASK(led->id),
218 ~status);
219 if (ret < 0)
220 return ret;
221
222 usleep_range(100, 300);
223
224 ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL,
225 MT6323_ISINK_CH_EN_MASK(led->id),
226 MT6323_ISINK_CH_EN(led->id));
227 if (ret < 0)
228 return ret;
229
230 ret = mt6323_led_hw_brightness(cdev, brightness);
231 if (ret < 0)
232 return ret;
233
234 ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id),
235 MT6323_ISINK_DIM_DUTY_MASK,
236 MT6323_ISINK_DIM_DUTY(31));
237 if (ret < 0)
238 return ret;
239
240 ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id),
241 MT6323_ISINK_DIM_FSEL_MASK,
242 MT6323_ISINK_DIM_FSEL(1000));
243 if (ret < 0)
244 return ret;
245
246 return 0;
247}
248
249static int mt6323_led_set_blink(struct led_classdev *cdev,
250 unsigned long *delay_on,
251 unsigned long *delay_off)
252{
253 struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
254 struct mt6323_leds *leds = led->parent;
255 struct regmap *regmap = leds->hw->regmap;
256 unsigned long period;
257 u8 duty_hw;
258 int ret;
259
260 /*
261 * Units are in ms, if over the hardware able
262 * to support, fallback into software blink
263 */
264 period = *delay_on + *delay_off;
265
266 if (period > MT6323_MAX_PERIOD)
267 return -EINVAL;
268
269 /*
270 * LED subsystem requires a default user
271 * friendly blink pattern for the LED so using
272 * 1Hz duty cycle 50% here if without specific
273 * value delay_on and delay off being assigned.
274 */
275 if (!*delay_on && !*delay_off) {
276 *delay_on = 500;
277 *delay_off = 500;
278 }
279
280 /*
281 * Calculate duty_hw based on the percentage of period during
282 * which the led is ON.
283 */
284 duty_hw = MT6323_CAL_HW_DUTY(*delay_on, period);
285
286 /* hardware doesn't support zero duty cycle. */
287 if (!duty_hw)
288 return -EINVAL;
289
290 mutex_lock(&leds->lock);
291 /*
292 * Set max_brightness as the software blink behavior
293 * when no blink brightness.
294 */
295 if (!led->current_brightness) {
296 ret = mt6323_led_hw_on(cdev, cdev->max_brightness);
297 if (ret < 0)
298 goto out;
299 led->current_brightness = cdev->max_brightness;
300 }
301
302 ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id),
303 MT6323_ISINK_DIM_DUTY_MASK,
304 MT6323_ISINK_DIM_DUTY(duty_hw - 1));
305 if (ret < 0)
306 goto out;
307
308 ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id),
309 MT6323_ISINK_DIM_FSEL_MASK,
310 MT6323_ISINK_DIM_FSEL(period - 1));
311out:
312 mutex_unlock(&leds->lock);
313
314 return ret;
315}
316
317static int mt6323_led_set_brightness(struct led_classdev *cdev,
318 enum led_brightness brightness)
319{
320 struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
321 struct mt6323_leds *leds = led->parent;
322 int ret;
323
324 mutex_lock(&leds->lock);
325
326 if (!led->current_brightness && brightness) {
327 ret = mt6323_led_hw_on(cdev, brightness);
328 if (ret < 0)
329 goto out;
330 } else if (brightness) {
331 ret = mt6323_led_hw_brightness(cdev, brightness);
332 if (ret < 0)
333 goto out;
334 } else {
335 ret = mt6323_led_hw_off(cdev);
336 if (ret < 0)
337 goto out;
338 }
339
340 led->current_brightness = brightness;
341out:
342 mutex_unlock(&leds->lock);
343
344 return ret;
345}
346
347static int mt6323_led_set_dt_default(struct led_classdev *cdev,
348 struct device_node *np)
349{
350 struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
351 const char *state;
352 int ret = 0;
353
354 led->cdev.name = of_get_property(np, "label", NULL) ? : np->name;
355 led->cdev.default_trigger = of_get_property(np,
356 "linux,default-trigger",
357 NULL);
358
359 state = of_get_property(np, "default-state", NULL);
360 if (state) {
361 if (!strcmp(state, "keep")) {
362 ret = mt6323_get_led_hw_brightness(cdev);
363 if (ret < 0)
364 return ret;
365 led->current_brightness = ret;
366 ret = 0;
367 } else if (!strcmp(state, "on")) {
368 ret =
369 mt6323_led_set_brightness(cdev, cdev->max_brightness);
370 } else {
371 ret = mt6323_led_set_brightness(cdev, LED_OFF);
372 }
373 }
374
375 return ret;
376}
377
378static int mt6323_led_probe(struct platform_device *pdev)
379{
380 struct device *dev = &pdev->dev;
381 struct device_node *np = pdev->dev.of_node;
382 struct device_node *child;
383 struct mt6397_chip *hw = dev_get_drvdata(pdev->dev.parent);
384 struct mt6323_leds *leds;
385 struct mt6323_led *led;
386 int ret;
387 unsigned int status;
388 u32 reg;
389
390 leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL);
391 if (!leds)
392 return -ENOMEM;
393
394 platform_set_drvdata(pdev, leds);
395 leds->dev = dev;
396
397 /*
398 * leds->hw points to the underlying bus for the register
399 * controlled.
400 */
401 leds->hw = hw;
402 mutex_init(&leds->lock);
403
404 status = MT6323_RG_DRV_32K_CK_PDN;
405 ret = regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0,
406 MT6323_RG_DRV_32K_CK_PDN_MASK, ~status);
407 if (ret < 0) {
408 dev_err(leds->dev,
409 "Failed to update MT6323_TOP_CKPDN0 Register\n");
410 return ret;
411 }
412
413 for_each_available_child_of_node(np, child) {
414 ret = of_property_read_u32(child, "reg", &reg);
415 if (ret) {
416 dev_err(dev, "Failed to read led 'reg' property\n");
417 goto put_child_node;
418 }
419
420 if (reg >= MT6323_MAX_LEDS || leds->led[reg]) {
421 dev_err(dev, "Invalid led reg %u\n", reg);
422 ret = -EINVAL;
423 goto put_child_node;
424 }
425
426 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
427 if (!led) {
428 ret = -ENOMEM;
429 goto put_child_node;
430 }
431
432 leds->led[reg] = led;
433 leds->led[reg]->id = reg;
434 leds->led[reg]->cdev.max_brightness = MT6323_MAX_BRIGHTNESS;
435 leds->led[reg]->cdev.brightness_set_blocking =
436 mt6323_led_set_brightness;
437 leds->led[reg]->cdev.blink_set = mt6323_led_set_blink;
438 leds->led[reg]->cdev.brightness_get =
439 mt6323_get_led_hw_brightness;
440 leds->led[reg]->parent = leds;
441
442 ret = mt6323_led_set_dt_default(&leds->led[reg]->cdev, child);
443 if (ret < 0) {
444 dev_err(leds->dev,
445 "Failed to LED set default from devicetree\n");
446 goto put_child_node;
447 }
448
449 ret = devm_led_classdev_register(dev, &leds->led[reg]->cdev);
450 if (ret) {
451 dev_err(&pdev->dev, "Failed to register LED: %d\n",
452 ret);
453 goto put_child_node;
454 }
455 leds->led[reg]->cdev.dev->of_node = child;
456 }
457
458 return 0;
459
460put_child_node:
461 of_node_put(child);
462 return ret;
463}
464
465static int mt6323_led_remove(struct platform_device *pdev)
466{
467 struct mt6323_leds *leds = platform_get_drvdata(pdev);
468 int i;
469
470 /* Turn the LEDs off on driver removal. */
471 for (i = 0 ; leds->led[i] ; i++)
472 mt6323_led_hw_off(&leds->led[i]->cdev);
473
474 regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0,
475 MT6323_RG_DRV_32K_CK_PDN_MASK,
476 MT6323_RG_DRV_32K_CK_PDN);
477
478 mutex_destroy(&leds->lock);
479
480 return 0;
481}
482
483static const struct of_device_id mt6323_led_dt_match[] = {
484 { .compatible = "mediatek,mt6323-led" },
485 {},
486};
487MODULE_DEVICE_TABLE(of, mt6323_led_dt_match);
488
489static struct platform_driver mt6323_led_driver = {
490 .probe = mt6323_led_probe,
491 .remove = mt6323_led_remove,
492 .driver = {
493 .name = "mt6323-led",
494 .of_match_table = mt6323_led_dt_match,
495 },
496};
497
498module_platform_driver(mt6323_led_driver);
499
500MODULE_DESCRIPTION("LED driver for Mediatek MT6323 PMIC");
501MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
502MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 06e63106ae1e..7fea18b0c15d 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -254,6 +254,21 @@ static void pca9532_input_work(struct work_struct *work)
254 mutex_unlock(&data->update_lock); 254 mutex_unlock(&data->update_lock);
255} 255}
256 256
257static enum pca9532_state pca9532_getled(struct pca9532_led *led)
258{
259 struct i2c_client *client = led->client;
260 struct pca9532_data *data = i2c_get_clientdata(client);
261 u8 maxleds = data->chip_info->num_leds;
262 char reg;
263 enum pca9532_state ret;
264
265 mutex_lock(&data->update_lock);
266 reg = i2c_smbus_read_byte_data(client, LED_REG(maxleds, led->id));
267 ret = reg >> LED_NUM(led->id)/2;
268 mutex_unlock(&data->update_lock);
269 return ret;
270}
271
257#ifdef CONFIG_LEDS_PCA9532_GPIO 272#ifdef CONFIG_LEDS_PCA9532_GPIO
258static int pca9532_gpio_request_pin(struct gpio_chip *gc, unsigned offset) 273static int pca9532_gpio_request_pin(struct gpio_chip *gc, unsigned offset)
259{ 274{
@@ -366,7 +381,10 @@ static int pca9532_configure(struct i2c_client *client,
366 gpios++; 381 gpios++;
367 break; 382 break;
368 case PCA9532_TYPE_LED: 383 case PCA9532_TYPE_LED:
369 led->state = pled->state; 384 if (pled->state == PCA9532_KEEP)
385 led->state = pca9532_getled(led);
386 else
387 led->state = pled->state;
370 led->name = pled->name; 388 led->name = pled->name;
371 led->ldev.name = led->name; 389 led->ldev.name = led->name;
372 led->ldev.default_trigger = pled->default_trigger; 390 led->ldev.default_trigger = pled->default_trigger;
@@ -456,6 +474,7 @@ pca9532_of_populate_pdata(struct device *dev, struct device_node *np)
456 const struct of_device_id *match; 474 const struct of_device_id *match;
457 int devid, maxleds; 475 int devid, maxleds;
458 int i = 0; 476 int i = 0;
477 const char *state;
459 478
460 match = of_match_device(of_pca9532_leds_match, dev); 479 match = of_match_device(of_pca9532_leds_match, dev);
461 if (!match) 480 if (!match)
@@ -475,6 +494,12 @@ pca9532_of_populate_pdata(struct device *dev, struct device_node *np)
475 of_property_read_u32(child, "type", &pdata->leds[i].type); 494 of_property_read_u32(child, "type", &pdata->leds[i].type);
476 of_property_read_string(child, "linux,default-trigger", 495 of_property_read_string(child, "linux,default-trigger",
477 &pdata->leds[i].default_trigger); 496 &pdata->leds[i].default_trigger);
497 if (!of_property_read_string(child, "default-state", &state)) {
498 if (!strcmp(state, "on"))
499 pdata->leds[i].state = PCA9532_ON;
500 else if (!strcmp(state, "keep"))
501 pdata->leds[i].state = PCA9532_KEEP;
502 }
478 if (++i >= maxleds) { 503 if (++i >= maxleds) {
479 of_node_put(child); 504 of_node_put(child);
480 break; 505 break;
diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c
index a41896468cb3..66a626091936 100644
--- a/drivers/leds/trigger/ledtrig-cpu.c
+++ b/drivers/leds/trigger/ledtrig-cpu.c
@@ -31,12 +31,16 @@
31#define MAX_NAME_LEN 8 31#define MAX_NAME_LEN 8
32 32
33struct led_trigger_cpu { 33struct led_trigger_cpu {
34 bool is_active;
34 char name[MAX_NAME_LEN]; 35 char name[MAX_NAME_LEN];
35 struct led_trigger *_trig; 36 struct led_trigger *_trig;
36}; 37};
37 38
38static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); 39static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
39 40
41static struct led_trigger *trig_cpu_all;
42static atomic_t num_active_cpus = ATOMIC_INIT(0);
43
40/** 44/**
41 * ledtrig_cpu - emit a CPU event as a trigger 45 * ledtrig_cpu - emit a CPU event as a trigger
42 * @evt: CPU event to be emitted 46 * @evt: CPU event to be emitted
@@ -47,26 +51,46 @@ static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
47void ledtrig_cpu(enum cpu_led_event ledevt) 51void ledtrig_cpu(enum cpu_led_event ledevt)
48{ 52{
49 struct led_trigger_cpu *trig = this_cpu_ptr(&cpu_trig); 53 struct led_trigger_cpu *trig = this_cpu_ptr(&cpu_trig);
54 bool is_active = trig->is_active;
50 55
51 /* Locate the correct CPU LED */ 56 /* Locate the correct CPU LED */
52 switch (ledevt) { 57 switch (ledevt) {
53 case CPU_LED_IDLE_END: 58 case CPU_LED_IDLE_END:
54 case CPU_LED_START: 59 case CPU_LED_START:
55 /* Will turn the LED on, max brightness */ 60 /* Will turn the LED on, max brightness */
56 led_trigger_event(trig->_trig, LED_FULL); 61 is_active = true;
57 break; 62 break;
58 63
59 case CPU_LED_IDLE_START: 64 case CPU_LED_IDLE_START:
60 case CPU_LED_STOP: 65 case CPU_LED_STOP:
61 case CPU_LED_HALTED: 66 case CPU_LED_HALTED:
62 /* Will turn the LED off */ 67 /* Will turn the LED off */
63 led_trigger_event(trig->_trig, LED_OFF); 68 is_active = false;
64 break; 69 break;
65 70
66 default: 71 default:
67 /* Will leave the LED as it is */ 72 /* Will leave the LED as it is */
68 break; 73 break;
69 } 74 }
75
76 if (is_active != trig->is_active) {
77 unsigned int active_cpus;
78 unsigned int total_cpus;
79
80 /* Update trigger state */
81 trig->is_active = is_active;
82 atomic_add(is_active ? 1 : -1, &num_active_cpus);
83 active_cpus = atomic_read(&num_active_cpus);
84 total_cpus = num_present_cpus();
85
86 led_trigger_event(trig->_trig,
87 is_active ? LED_FULL : LED_OFF);
88
89
90 led_trigger_event(trig_cpu_all,
91 DIV_ROUND_UP(LED_FULL * active_cpus, total_cpus));
92
93 }
70} 94}
71EXPORT_SYMBOL(ledtrig_cpu); 95EXPORT_SYMBOL(ledtrig_cpu);
72 96
@@ -113,6 +137,11 @@ static int __init ledtrig_cpu_init(void)
113 BUILD_BUG_ON(CONFIG_NR_CPUS > 9999); 137 BUILD_BUG_ON(CONFIG_NR_CPUS > 9999);
114 138
115 /* 139 /*
140 * Registering a trigger for all CPUs.
141 */
142 led_trigger_register_simple("cpu", &trig_cpu_all);
143
144 /*
116 * Registering CPU led trigger for each CPU core here 145 * Registering CPU led trigger for each CPU core here
117 * ignores CPU hotplug, but after this CPU hotplug works 146 * ignores CPU hotplug, but after this CPU hotplug works
118 * fine with this trigger. 147 * fine with this trigger.
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 4bc88eb52712..e1bffc9bb194 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -141,6 +141,14 @@ config DELL_WMI_AIO
141 To compile this driver as a module, choose M here: the module will 141 To compile this driver as a module, choose M here: the module will
142 be called dell-wmi-aio. 142 be called dell-wmi-aio.
143 143
144config DELL_WMI_LED
145 tristate "External LED on Dell Business Netbooks"
146 depends on LEDS_CLASS
147 depends on ACPI_WMI
148 help
149 This adds support for the Latitude 2100 and similar
150 notebooks that have an external LED.
151
144config DELL_SMO8800 152config DELL_SMO8800
145 tristate "Dell Latitude freefall driver (ACPI SMO88XX)" 153 tristate "Dell Latitude freefall driver (ACPI SMO88XX)"
146 depends on ACPI 154 depends on ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 299d0f9e40f7..776b3a7a4984 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
15obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o 15obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
16obj-$(CONFIG_DELL_WMI) += dell-wmi.o 16obj-$(CONFIG_DELL_WMI) += dell-wmi.o
17obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o 17obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
18obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
18obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o 19obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
19obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o 20obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
20obj-$(CONFIG_ACER_WMI) += acer-wmi.o 21obj-$(CONFIG_ACER_WMI) += acer-wmi.o
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index f57dd282a002..2e237bad4995 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -29,6 +29,7 @@
29#include <linux/mm.h> 29#include <linux/mm.h>
30#include <linux/i8042.h> 30#include <linux/i8042.h>
31#include <linux/debugfs.h> 31#include <linux/debugfs.h>
32#include <linux/dell-led.h>
32#include <linux/seq_file.h> 33#include <linux/seq_file.h>
33#include <acpi/video.h> 34#include <acpi/video.h>
34#include "dell-rbtn.h" 35#include "dell-rbtn.h"
@@ -42,6 +43,8 @@
42#define KBD_LED_AUTO_50_TOKEN 0x02EB 43#define KBD_LED_AUTO_50_TOKEN 0x02EB
43#define KBD_LED_AUTO_75_TOKEN 0x02EC 44#define KBD_LED_AUTO_75_TOKEN 0x02EC
44#define KBD_LED_AUTO_100_TOKEN 0x02F6 45#define KBD_LED_AUTO_100_TOKEN 0x02F6
46#define GLOBAL_MIC_MUTE_ENABLE 0x0364
47#define GLOBAL_MIC_MUTE_DISABLE 0x0365
45 48
46struct quirk_entry { 49struct quirk_entry {
47 u8 touchpad_led; 50 u8 touchpad_led;
@@ -1978,6 +1981,31 @@ static void kbd_led_exit(void)
1978 led_classdev_unregister(&kbd_led); 1981 led_classdev_unregister(&kbd_led);
1979} 1982}
1980 1983
1984int dell_micmute_led_set(int state)
1985{
1986 struct calling_interface_buffer *buffer;
1987 struct calling_interface_token *token;
1988
1989 if (state == 0)
1990 token = dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE);
1991 else if (state == 1)
1992 token = dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE);
1993 else
1994 return -EINVAL;
1995
1996 if (!token)
1997 return -ENODEV;
1998
1999 buffer = dell_smbios_get_buffer();
2000 buffer->input[0] = token->location;
2001 buffer->input[1] = token->value;
2002 dell_smbios_send_request(1, 0);
2003 dell_smbios_release_buffer();
2004
2005 return state;
2006}
2007EXPORT_SYMBOL_GPL(dell_micmute_led_set);
2008
1981static int __init dell_init(void) 2009static int __init dell_init(void)
1982{ 2010{
1983 struct calling_interface_buffer *buffer; 2011 struct calling_interface_buffer *buffer;
diff --git a/drivers/leds/dell-led.c b/drivers/platform/x86/dell-wmi-led.c
index b3d6e9c15cf9..a0c7e99530ef 100644
--- a/drivers/leds/dell-led.c
+++ b/drivers/platform/x86/dell-wmi-led.c
@@ -1,6 +1,4 @@
1/* 1/*
2 * dell_led.c - Dell LED Driver
3 *
4 * Copyright (C) 2010 Dell Inc. 2 * Copyright (C) 2010 Dell Inc.
5 * Louis Davis <louis_davis@dell.com> 3 * Louis Davis <louis_davis@dell.com>
6 * Jim Dailey <jim_dailey@dell.com> 4 * Jim Dailey <jim_dailey@dell.com>
@@ -15,16 +13,12 @@
15#include <linux/leds.h> 13#include <linux/leds.h>
16#include <linux/slab.h> 14#include <linux/slab.h>
17#include <linux/module.h> 15#include <linux/module.h>
18#include <linux/dmi.h>
19#include <linux/dell-led.h>
20#include "../platform/x86/dell-smbios.h"
21 16
22MODULE_AUTHOR("Louis Davis/Jim Dailey"); 17MODULE_AUTHOR("Louis Davis/Jim Dailey");
23MODULE_DESCRIPTION("Dell LED Control Driver"); 18MODULE_DESCRIPTION("Dell LED Control Driver");
24MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
25 20
26#define DELL_LED_BIOS_GUID "F6E4FE6E-909D-47cb-8BAB-C9F6F2F8D396" 21#define DELL_LED_BIOS_GUID "F6E4FE6E-909D-47cb-8BAB-C9F6F2F8D396"
27#define DELL_APP_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
28MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID); 22MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID);
29 23
30/* Error Result Codes: */ 24/* Error Result Codes: */
@@ -43,53 +37,6 @@ MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID);
43#define CMD_LED_OFF 17 37#define CMD_LED_OFF 17
44#define CMD_LED_BLINK 18 38#define CMD_LED_BLINK 18
45 39
46#define GLOBAL_MIC_MUTE_ENABLE 0x364
47#define GLOBAL_MIC_MUTE_DISABLE 0x365
48
49static int dell_micmute_led_set(int state)
50{
51 struct calling_interface_buffer *buffer;
52 struct calling_interface_token *token;
53
54 if (!wmi_has_guid(DELL_APP_GUID))
55 return -ENODEV;
56
57 if (state == 0)
58 token = dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE);
59 else if (state == 1)
60 token = dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE);
61 else
62 return -EINVAL;
63
64 if (!token)
65 return -ENODEV;
66
67 buffer = dell_smbios_get_buffer();
68 buffer->input[0] = token->location;
69 buffer->input[1] = token->value;
70 dell_smbios_send_request(1, 0);
71 dell_smbios_release_buffer();
72
73 return state;
74}
75
76int dell_app_wmi_led_set(int whichled, int on)
77{
78 int state = 0;
79
80 switch (whichled) {
81 case DELL_LED_MICMUTE:
82 state = dell_micmute_led_set(on);
83 break;
84 default:
85 pr_warn("led type %x is not supported\n", whichled);
86 break;
87 }
88
89 return state;
90}
91EXPORT_SYMBOL_GPL(dell_app_wmi_led_set);
92
93struct bios_args { 40struct bios_args {
94 unsigned char length; 41 unsigned char length;
95 unsigned char result_code; 42 unsigned char result_code;
@@ -99,37 +46,29 @@ struct bios_args {
99 unsigned char off_time; 46 unsigned char off_time;
100}; 47};
101 48
102static int dell_led_perform_fn(u8 length, 49static int dell_led_perform_fn(u8 length, u8 result_code, u8 device_id,
103 u8 result_code, 50 u8 command, u8 on_time, u8 off_time)
104 u8 device_id,
105 u8 command,
106 u8 on_time,
107 u8 off_time)
108{ 51{
109 struct bios_args *bios_return;
110 u8 return_code;
111 union acpi_object *obj;
112 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 52 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
53 struct bios_args *bios_return;
113 struct acpi_buffer input; 54 struct acpi_buffer input;
55 union acpi_object *obj;
114 acpi_status status; 56 acpi_status status;
57 u8 return_code;
115 58
116 struct bios_args args; 59 struct bios_args args = {
117 args.length = length; 60 .length = length,
118 args.result_code = result_code; 61 .result_code = result_code,
119 args.device_id = device_id; 62 .device_id = device_id,
120 args.command = command; 63 .command = command,
121 args.on_time = on_time; 64 .on_time = on_time,
122 args.off_time = off_time; 65 .off_time = off_time
66 };
123 67
124 input.length = sizeof(struct bios_args); 68 input.length = sizeof(struct bios_args);
125 input.pointer = &args; 69 input.pointer = &args;
126 70
127 status = wmi_evaluate_method(DELL_LED_BIOS_GUID, 71 status = wmi_evaluate_method(DELL_LED_BIOS_GUID, 1, 1, &input, &output);
128 1,
129 1,
130 &input,
131 &output);
132
133 if (ACPI_FAILURE(status)) 72 if (ACPI_FAILURE(status))
134 return status; 73 return status;
135 74
@@ -137,7 +76,7 @@ static int dell_led_perform_fn(u8 length,
137 76
138 if (!obj) 77 if (!obj)
139 return -EINVAL; 78 return -EINVAL;
140 else if (obj->type != ACPI_TYPE_BUFFER) { 79 if (obj->type != ACPI_TYPE_BUFFER) {
141 kfree(obj); 80 kfree(obj);
142 return -EINVAL; 81 return -EINVAL;
143 } 82 }
@@ -170,8 +109,7 @@ static int led_off(void)
170 0); /* not used */ 109 0); /* not used */
171} 110}
172 111
173static int led_blink(unsigned char on_eighths, 112static int led_blink(unsigned char on_eighths, unsigned char off_eighths)
174 unsigned char off_eighths)
175{ 113{
176 return dell_led_perform_fn(5, /* Length of command */ 114 return dell_led_perform_fn(5, /* Length of command */
177 INTERFACE_ERROR, /* Init to INTERFACE_ERROR */ 115 INTERFACE_ERROR, /* Init to INTERFACE_ERROR */
@@ -182,7 +120,7 @@ static int led_blink(unsigned char on_eighths,
182} 120}
183 121
184static void dell_led_set(struct led_classdev *led_cdev, 122static void dell_led_set(struct led_classdev *led_cdev,
185 enum led_brightness value) 123 enum led_brightness value)
186{ 124{
187 if (value == LED_OFF) 125 if (value == LED_OFF)
188 led_off(); 126 led_off();
@@ -191,27 +129,22 @@ static void dell_led_set(struct led_classdev *led_cdev,
191} 129}
192 130
193static int dell_led_blink(struct led_classdev *led_cdev, 131static int dell_led_blink(struct led_classdev *led_cdev,
194 unsigned long *delay_on, 132 unsigned long *delay_on, unsigned long *delay_off)
195 unsigned long *delay_off)
196{ 133{
197 unsigned long on_eighths; 134 unsigned long on_eighths;
198 unsigned long off_eighths; 135 unsigned long off_eighths;
199 136
200 /* The Dell LED delay is based on 125ms intervals. 137 /*
201 Need to round up to next interval. */ 138 * The Dell LED delay is based on 125ms intervals.
139 * Need to round up to next interval.
140 */
202 141
203 on_eighths = (*delay_on + 124) / 125; 142 on_eighths = DIV_ROUND_UP(*delay_on, 125);
204 if (0 == on_eighths) 143 on_eighths = clamp_t(unsigned long, on_eighths, 1, 255);
205 on_eighths = 1;
206 if (on_eighths > 255)
207 on_eighths = 255;
208 *delay_on = on_eighths * 125; 144 *delay_on = on_eighths * 125;
209 145
210 off_eighths = (*delay_off + 124) / 125; 146 off_eighths = DIV_ROUND_UP(*delay_off, 125);
211 if (0 == off_eighths) 147 off_eighths = clamp_t(unsigned long, off_eighths, 1, 255);
212 off_eighths = 1;
213 if (off_eighths > 255)
214 off_eighths = 255;
215 *delay_off = off_eighths * 125; 148 *delay_off = off_eighths * 125;
216 149
217 led_blink(on_eighths, off_eighths); 150 led_blink(on_eighths, off_eighths);
@@ -232,29 +165,21 @@ static int __init dell_led_init(void)
232{ 165{
233 int error = 0; 166 int error = 0;
234 167
235 if (!wmi_has_guid(DELL_LED_BIOS_GUID) && !wmi_has_guid(DELL_APP_GUID)) 168 if (!wmi_has_guid(DELL_LED_BIOS_GUID))
236 return -ENODEV; 169 return -ENODEV;
237 170
238 if (wmi_has_guid(DELL_LED_BIOS_GUID)) { 171 error = led_off();
239 error = led_off(); 172 if (error != 0)
240 if (error != 0) 173 return -ENODEV;
241 return -ENODEV;
242
243 error = led_classdev_register(NULL, &dell_led);
244 }
245 174
246 return error; 175 return led_classdev_register(NULL, &dell_led);
247} 176}
248 177
249static void __exit dell_led_exit(void) 178static void __exit dell_led_exit(void)
250{ 179{
251 int error = 0; 180 led_classdev_unregister(&dell_led);
252 181
253 if (wmi_has_guid(DELL_LED_BIOS_GUID)) { 182 led_off();
254 error = led_off();
255 if (error == 0)
256 led_classdev_unregister(&dell_led);
257 }
258} 183}
259 184
260module_init(dell_led_init); 185module_init(dell_led_init);
diff --git a/include/linux/dell-led.h b/include/linux/dell-led.h
index 7009b8bec77b..3f033c48071e 100644
--- a/include/linux/dell-led.h
+++ b/include/linux/dell-led.h
@@ -1,10 +1,6 @@
1#ifndef __DELL_LED_H__ 1#ifndef __DELL_LED_H__
2#define __DELL_LED_H__ 2#define __DELL_LED_H__
3 3
4enum { 4int dell_micmute_led_set(int on);
5 DELL_LED_MICMUTE,
6};
7
8int dell_app_wmi_led_set(int whichled, int on);
9 5
10#endif 6#endif
diff --git a/include/linux/leds-pca9532.h b/include/linux/leds-pca9532.h
index d215b4561180..5e240b2b4d58 100644
--- a/include/linux/leds-pca9532.h
+++ b/include/linux/leds-pca9532.h
@@ -22,7 +22,8 @@ enum pca9532_state {
22 PCA9532_OFF = 0x0, 22 PCA9532_OFF = 0x0,
23 PCA9532_ON = 0x1, 23 PCA9532_ON = 0x1,
24 PCA9532_PWM0 = 0x2, 24 PCA9532_PWM0 = 0x2,
25 PCA9532_PWM1 = 0x3 25 PCA9532_PWM1 = 0x3,
26 PCA9532_KEEP = 0xff,
26}; 27};
27 28
28struct pca9532_led { 29struct pca9532_led {
@@ -44,4 +45,3 @@ struct pca9532_platform_data {
44}; 45};
45 46
46#endif /* __LINUX_PCA9532_H */ 47#endif /* __LINUX_PCA9532_H */
47
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 38c0bd7ca107..64c56d454f7d 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -122,10 +122,16 @@ struct led_classdev {
122 struct mutex led_access; 122 struct mutex led_access;
123}; 123};
124 124
125extern int led_classdev_register(struct device *parent, 125extern int of_led_classdev_register(struct device *parent,
126 struct led_classdev *led_cdev); 126 struct device_node *np,
127extern int devm_led_classdev_register(struct device *parent, 127 struct led_classdev *led_cdev);
128 struct led_classdev *led_cdev); 128#define led_classdev_register(parent, led_cdev) \
129 of_led_classdev_register(parent, NULL, led_cdev)
130extern int devm_of_led_classdev_register(struct device *parent,
131 struct device_node *np,
132 struct led_classdev *led_cdev);
133#define devm_led_classdev_register(parent, led_cdev) \
134 devm_of_led_classdev_register(parent, NULL, led_cdev)
129extern void led_classdev_unregister(struct led_classdev *led_cdev); 135extern void led_classdev_unregister(struct led_classdev *led_cdev);
130extern void devm_led_classdev_unregister(struct device *parent, 136extern void devm_led_classdev_unregister(struct device *parent,
131 struct led_classdev *led_cdev); 137 struct led_classdev *led_cdev);
diff --git a/include/linux/mfd/motorola-cpcap.h b/include/linux/mfd/motorola-cpcap.h
index b4031c2b2214..53758a7d7c32 100644
--- a/include/linux/mfd/motorola-cpcap.h
+++ b/include/linux/mfd/motorola-cpcap.h
@@ -14,6 +14,9 @@
14 * published by the Free Software Foundation. 14 * published by the Free Software Foundation.
15 */ 15 */
16 16
17#include <linux/device.h>
18#include <linux/regmap.h>
19
17#define CPCAP_VENDOR_ST 0 20#define CPCAP_VENDOR_ST 0
18#define CPCAP_VENDOR_TI 1 21#define CPCAP_VENDOR_TI 1
19 22
diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
index 19d41da79f93..7efa7bd7acb2 100644
--- a/sound/pci/hda/dell_wmi_helper.c
+++ b/sound/pci/hda/dell_wmi_helper.c
@@ -2,11 +2,11 @@
2 * to be included from codec driver 2 * to be included from codec driver
3 */ 3 */
4 4
5#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS) 5#if IS_ENABLED(CONFIG_DELL_LAPTOP)
6#include <linux/dell-led.h> 6#include <linux/dell-led.h>
7 7
8static int dell_led_value; 8static int dell_led_value;
9static int (*dell_led_set_func)(int, int); 9static int (*dell_micmute_led_set_func)(int);
10static void (*dell_old_cap_hook)(struct hda_codec *, 10static void (*dell_old_cap_hook)(struct hda_codec *,
11 struct snd_kcontrol *, 11 struct snd_kcontrol *,
12 struct snd_ctl_elem_value *); 12 struct snd_ctl_elem_value *);
@@ -18,7 +18,7 @@ static void update_dell_wmi_micmute_led(struct hda_codec *codec,
18 if (dell_old_cap_hook) 18 if (dell_old_cap_hook)
19 dell_old_cap_hook(codec, kcontrol, ucontrol); 19 dell_old_cap_hook(codec, kcontrol, ucontrol);
20 20
21 if (!ucontrol || !dell_led_set_func) 21 if (!ucontrol || !dell_micmute_led_set_func)
22 return; 22 return;
23 if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { 23 if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
24 /* TODO: How do I verify if it's a mono or stereo here? */ 24 /* TODO: How do I verify if it's a mono or stereo here? */
@@ -26,8 +26,8 @@ static void update_dell_wmi_micmute_led(struct hda_codec *codec,
26 if (val == dell_led_value) 26 if (val == dell_led_value)
27 return; 27 return;
28 dell_led_value = val; 28 dell_led_value = val;
29 if (dell_led_set_func) 29 if (dell_micmute_led_set_func)
30 dell_led_set_func(DELL_LED_MICMUTE, dell_led_value); 30 dell_micmute_led_set_func(dell_led_value);
31 } 31 }
32} 32}
33 33
@@ -39,15 +39,15 @@ static void alc_fixup_dell_wmi(struct hda_codec *codec,
39 bool removefunc = false; 39 bool removefunc = false;
40 40
41 if (action == HDA_FIXUP_ACT_PROBE) { 41 if (action == HDA_FIXUP_ACT_PROBE) {
42 if (!dell_led_set_func) 42 if (!dell_micmute_led_set_func)
43 dell_led_set_func = symbol_request(dell_app_wmi_led_set); 43 dell_micmute_led_set_func = symbol_request(dell_micmute_led_set);
44 if (!dell_led_set_func) { 44 if (!dell_micmute_led_set_func) {
45 codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n"); 45 codec_warn(codec, "Failed to find dell wmi symbol dell_micmute_led_set\n");
46 return; 46 return;
47 } 47 }
48 48
49 removefunc = true; 49 removefunc = true;
50 if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) { 50 if (dell_micmute_led_set_func(false) >= 0) {
51 dell_led_value = 0; 51 dell_led_value = 0;
52 if (spec->gen.num_adc_nids > 1 && !spec->gen.dyn_adc_switch) 52 if (spec->gen.num_adc_nids > 1 && !spec->gen.dyn_adc_switch)
53 codec_dbg(codec, "Skipping micmute LED control due to several ADCs"); 53 codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
@@ -60,17 +60,17 @@ static void alc_fixup_dell_wmi(struct hda_codec *codec,
60 60
61 } 61 }
62 62
63 if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { 63 if (dell_micmute_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
64 symbol_put(dell_app_wmi_led_set); 64 symbol_put(dell_micmute_led_set);
65 dell_led_set_func = NULL; 65 dell_micmute_led_set_func = NULL;
66 dell_old_cap_hook = NULL; 66 dell_old_cap_hook = NULL;
67 } 67 }
68} 68}
69 69
70#else /* CONFIG_LEDS_DELL_NETBOOKS */ 70#else /* CONFIG_DELL_LAPTOP */
71static void alc_fixup_dell_wmi(struct hda_codec *codec, 71static void alc_fixup_dell_wmi(struct hda_codec *codec,
72 const struct hda_fixup *fix, int action) 72 const struct hda_fixup *fix, int action)
73{ 73{
74} 74}
75 75
76#endif /* CONFIG_LEDS_DELL_NETBOOKS */ 76#endif /* CONFIG_DELL_LAPTOP */