diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 16:08:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 16:08:09 -0400 |
commit | 7c574cf6aeb75920ba4d3af937bb1b3c42785ac4 (patch) | |
tree | 336586614fcbba9fb8fc6095d23f87d8ce11b559 /drivers/leds | |
parent | af76004cf8b4f368583bda22d7e348e40a338b91 (diff) | |
parent | 0c9a03b68511daf078256367e7a98d7ff3b7dfcb (diff) |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds
Pull LED updates from Bryan Wu:
"I just found merge window is open and I'm quite busy and almost forget
to send out this pull request. Thanks Russell and Alexandre ping me
about this.
So basically we got some clean up and leds-pwm fixing patches from
Russell"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds:
leds: Remove duplicated OOM message for individual driver
drivers/leds: Replace __get_cpu_var use through this_cpu_ptr
leds: lp55xx: add DT bindings for LP55231
leds: 88pm860x: Fix missing refcount decrement for parent of_node
leds: 88pm860x: Use of_get_child_by_name
leds: leds-pwm: add DT support for LEDs wired to supply
leds: leds-pwm: implement PWM inversion
leds: leds-pwm: convert OF parsing code to use led_pwm_add()
leds: leds-pwm: provide a common function to setup a single led-pwm device
leds: pca9685: Remove leds-pca9685 driver
dell-led: add mic mute led interface
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/Kconfig | 10 | ||||
-rw-r--r-- | drivers/leds/Makefile | 1 | ||||
-rw-r--r-- | drivers/leds/dell-led.c | 171 | ||||
-rw-r--r-- | drivers/leds/leds-88pm860x.c | 5 | ||||
-rw-r--r-- | drivers/leds/leds-adp5520.c | 5 | ||||
-rw-r--r-- | drivers/leds/leds-bd2802.c | 4 | ||||
-rw-r--r-- | drivers/leds/leds-da903x.c | 4 | ||||
-rw-r--r-- | drivers/leds/leds-da9052.c | 3 | ||||
-rw-r--r-- | drivers/leds/leds-lp5523.c | 3 | ||||
-rw-r--r-- | drivers/leds/leds-pca9685.c | 213 | ||||
-rw-r--r-- | drivers/leds/leds-pwm.c | 150 | ||||
-rw-r--r-- | drivers/leds/leds-s3c24xx.c | 4 | ||||
-rw-r--r-- | drivers/leds/leds-sunfire.c | 4 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-cpu.c | 2 |
14 files changed, 248 insertions, 331 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 089841ca180f..a1b044e7eaad 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -300,16 +300,6 @@ config LEDS_PCA963X | |||
300 | LED driver chip accessed via the I2C bus. Supported | 300 | LED driver chip accessed via the I2C bus. Supported |
301 | devices include PCA9633 and PCA9634 | 301 | devices include PCA9633 and PCA9634 |
302 | 302 | ||
303 | config LEDS_PCA9685 | ||
304 | tristate "LED support for PCA9685 I2C chip" | ||
305 | depends on LEDS_CLASS | ||
306 | depends on I2C | ||
307 | help | ||
308 | This option enables support for LEDs connected to the PCA9685 | ||
309 | LED driver chip accessed via the I2C bus. | ||
310 | The PCA9685 offers 12-bit PWM (4095 levels of brightness) on | ||
311 | 16 individual channels. | ||
312 | |||
313 | config LEDS_WM831X_STATUS | 303 | config LEDS_WM831X_STATUS |
314 | tristate "LED support for status LEDs on WM831x PMICs" | 304 | tristate "LED support for status LEDs on WM831x PMICs" |
315 | depends on LEDS_CLASS | 305 | depends on LEDS_CLASS |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 8b4c956e11ba..79c5155199a7 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -36,7 +36,6 @@ obj-$(CONFIG_LEDS_OT200) += leds-ot200.o | |||
36 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o | 36 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o |
37 | obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o | 37 | obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o |
38 | obj-$(CONFIG_LEDS_PCA963X) += leds-pca963x.o | 38 | obj-$(CONFIG_LEDS_PCA963X) += leds-pca963x.o |
39 | obj-$(CONFIG_LEDS_PCA9685) += leds-pca9685.o | ||
40 | obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o | 39 | obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o |
41 | obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o | 40 | obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o |
42 | obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o | 41 | obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o |
diff --git a/drivers/leds/dell-led.c b/drivers/leds/dell-led.c index e5c57389efd6..c36acaf566a6 100644 --- a/drivers/leds/dell-led.c +++ b/drivers/leds/dell-led.c | |||
@@ -15,12 +15,15 @@ | |||
15 | #include <linux/leds.h> | 15 | #include <linux/leds.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/dmi.h> | ||
19 | #include <linux/dell-led.h> | ||
18 | 20 | ||
19 | MODULE_AUTHOR("Louis Davis/Jim Dailey"); | 21 | MODULE_AUTHOR("Louis Davis/Jim Dailey"); |
20 | MODULE_DESCRIPTION("Dell LED Control Driver"); | 22 | MODULE_DESCRIPTION("Dell LED Control Driver"); |
21 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
22 | 24 | ||
23 | #define DELL_LED_BIOS_GUID "F6E4FE6E-909D-47cb-8BAB-C9F6F2F8D396" | 25 | #define DELL_LED_BIOS_GUID "F6E4FE6E-909D-47cb-8BAB-C9F6F2F8D396" |
26 | #define DELL_APP_GUID "A80593CE-A997-11DA-B012-B622A1EF5492" | ||
24 | MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID); | 27 | MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID); |
25 | 28 | ||
26 | /* Error Result Codes: */ | 29 | /* Error Result Codes: */ |
@@ -39,6 +42,149 @@ MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID); | |||
39 | #define CMD_LED_OFF 17 | 42 | #define CMD_LED_OFF 17 |
40 | #define CMD_LED_BLINK 18 | 43 | #define CMD_LED_BLINK 18 |
41 | 44 | ||
45 | struct app_wmi_args { | ||
46 | u16 class; | ||
47 | u16 selector; | ||
48 | u32 arg1; | ||
49 | u32 arg2; | ||
50 | u32 arg3; | ||
51 | u32 arg4; | ||
52 | u32 res1; | ||
53 | u32 res2; | ||
54 | u32 res3; | ||
55 | u32 res4; | ||
56 | char dummy[92]; | ||
57 | }; | ||
58 | |||
59 | #define GLOBAL_MIC_MUTE_ENABLE 0x364 | ||
60 | #define GLOBAL_MIC_MUTE_DISABLE 0x365 | ||
61 | |||
62 | struct dell_bios_data_token { | ||
63 | u16 tokenid; | ||
64 | u16 location; | ||
65 | u16 value; | ||
66 | }; | ||
67 | |||
68 | struct __attribute__ ((__packed__)) dell_bios_calling_interface { | ||
69 | struct dmi_header header; | ||
70 | u16 cmd_io_addr; | ||
71 | u8 cmd_io_code; | ||
72 | u32 supported_cmds; | ||
73 | struct dell_bios_data_token damap[]; | ||
74 | }; | ||
75 | |||
76 | static struct dell_bios_data_token dell_mic_tokens[2]; | ||
77 | |||
78 | static int dell_wmi_perform_query(struct app_wmi_args *args) | ||
79 | { | ||
80 | struct app_wmi_args *bios_return; | ||
81 | union acpi_object *obj; | ||
82 | struct acpi_buffer input; | ||
83 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
84 | acpi_status status; | ||
85 | u32 rc = -EINVAL; | ||
86 | |||
87 | input.length = 128; | ||
88 | input.pointer = args; | ||
89 | |||
90 | status = wmi_evaluate_method(DELL_APP_GUID, 0, 1, &input, &output); | ||
91 | if (!ACPI_SUCCESS(status)) | ||
92 | goto err_out0; | ||
93 | |||
94 | obj = output.pointer; | ||
95 | if (!obj) | ||
96 | goto err_out0; | ||
97 | |||
98 | if (obj->type != ACPI_TYPE_BUFFER) | ||
99 | goto err_out1; | ||
100 | |||
101 | bios_return = (struct app_wmi_args *)obj->buffer.pointer; | ||
102 | rc = bios_return->res1; | ||
103 | if (rc) | ||
104 | goto err_out1; | ||
105 | |||
106 | memcpy(args, bios_return, sizeof(struct app_wmi_args)); | ||
107 | rc = 0; | ||
108 | |||
109 | err_out1: | ||
110 | kfree(obj); | ||
111 | err_out0: | ||
112 | return rc; | ||
113 | } | ||
114 | |||
115 | static void __init find_micmute_tokens(const struct dmi_header *dm, void *dummy) | ||
116 | { | ||
117 | struct dell_bios_calling_interface *calling_interface; | ||
118 | struct dell_bios_data_token *token; | ||
119 | int token_size = sizeof(struct dell_bios_data_token); | ||
120 | int i = 0; | ||
121 | |||
122 | if (dm->type == 0xda && dm->length > 17) { | ||
123 | calling_interface = container_of(dm, | ||
124 | struct dell_bios_calling_interface, header); | ||
125 | |||
126 | token = &calling_interface->damap[i]; | ||
127 | while (token->tokenid != 0xffff) { | ||
128 | if (token->tokenid == GLOBAL_MIC_MUTE_DISABLE) | ||
129 | memcpy(&dell_mic_tokens[0], token, token_size); | ||
130 | else if (token->tokenid == GLOBAL_MIC_MUTE_ENABLE) | ||
131 | memcpy(&dell_mic_tokens[1], token, token_size); | ||
132 | |||
133 | i++; | ||
134 | token = &calling_interface->damap[i]; | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int dell_micmute_led_set(int state) | ||
140 | { | ||
141 | struct app_wmi_args args; | ||
142 | struct dell_bios_data_token *token; | ||
143 | |||
144 | if (!wmi_has_guid(DELL_APP_GUID)) | ||
145 | return -ENODEV; | ||
146 | |||
147 | if (state == 0 || state == 1) | ||
148 | token = &dell_mic_tokens[state]; | ||
149 | else | ||
150 | return -EINVAL; | ||
151 | |||
152 | memset(&args, 0, sizeof(struct app_wmi_args)); | ||
153 | |||
154 | args.class = 1; | ||
155 | args.arg1 = token->location; | ||
156 | args.arg2 = token->value; | ||
157 | |||
158 | dell_wmi_perform_query(&args); | ||
159 | |||
160 | return state; | ||
161 | } | ||
162 | |||
163 | int dell_app_wmi_led_set(int whichled, int on) | ||
164 | { | ||
165 | int state = 0; | ||
166 | |||
167 | switch (whichled) { | ||
168 | case DELL_LED_MICMUTE: | ||
169 | state = dell_micmute_led_set(on); | ||
170 | break; | ||
171 | default: | ||
172 | pr_warn("led type %x is not supported\n", whichled); | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | return state; | ||
177 | } | ||
178 | EXPORT_SYMBOL_GPL(dell_app_wmi_led_set); | ||
179 | |||
180 | static int __init dell_micmute_led_init(void) | ||
181 | { | ||
182 | memset(dell_mic_tokens, 0, sizeof(struct dell_bios_data_token) * 2); | ||
183 | dmi_walk(find_micmute_tokens, NULL); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
42 | struct bios_args { | 188 | struct bios_args { |
43 | unsigned char length; | 189 | unsigned char length; |
44 | unsigned char result_code; | 190 | unsigned char result_code; |
@@ -181,21 +327,32 @@ static int __init dell_led_init(void) | |||
181 | { | 327 | { |
182 | int error = 0; | 328 | int error = 0; |
183 | 329 | ||
184 | if (!wmi_has_guid(DELL_LED_BIOS_GUID)) | 330 | if (!wmi_has_guid(DELL_LED_BIOS_GUID) && !wmi_has_guid(DELL_APP_GUID)) |
185 | return -ENODEV; | 331 | return -ENODEV; |
186 | 332 | ||
187 | error = led_off(); | 333 | if (wmi_has_guid(DELL_APP_GUID)) |
188 | if (error != 0) | 334 | error = dell_micmute_led_init(); |
189 | return -ENODEV; | ||
190 | 335 | ||
191 | return led_classdev_register(NULL, &dell_led); | 336 | if (wmi_has_guid(DELL_LED_BIOS_GUID)) { |
337 | error = led_off(); | ||
338 | if (error != 0) | ||
339 | return -ENODEV; | ||
340 | |||
341 | error = led_classdev_register(NULL, &dell_led); | ||
342 | } | ||
343 | |||
344 | return error; | ||
192 | } | 345 | } |
193 | 346 | ||
194 | static void __exit dell_led_exit(void) | 347 | static void __exit dell_led_exit(void) |
195 | { | 348 | { |
196 | led_classdev_unregister(&dell_led); | 349 | int error = 0; |
197 | 350 | ||
198 | led_off(); | 351 | if (wmi_has_guid(DELL_LED_BIOS_GUID)) { |
352 | error = led_off(); | ||
353 | if (error == 0) | ||
354 | led_classdev_unregister(&dell_led); | ||
355 | } | ||
199 | } | 356 | } |
200 | 357 | ||
201 | module_init(dell_led_init); | 358 | module_init(dell_led_init); |
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index d1e1bca90d11..c2def5551ce1 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -130,10 +130,9 @@ static int pm860x_led_dt_init(struct platform_device *pdev, | |||
130 | struct device_node *nproot, *np; | 130 | struct device_node *nproot, *np; |
131 | int iset = 0; | 131 | int iset = 0; |
132 | 132 | ||
133 | nproot = of_node_get(pdev->dev.parent->of_node); | 133 | if (!pdev->dev.parent->of_node) |
134 | if (!nproot) | ||
135 | return -ENODEV; | 134 | return -ENODEV; |
136 | nproot = of_find_node_by_name(nproot, "leds"); | 135 | nproot = of_get_child_by_name(pdev->dev.parent->of_node, "leds"); |
137 | if (!nproot) { | 136 | if (!nproot) { |
138 | dev_err(&pdev->dev, "failed to find leds node\n"); | 137 | dev_err(&pdev->dev, "failed to find leds node\n"); |
139 | return -ENODEV; | 138 | return -ENODEV; |
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c index 86b5bdb0c773..5036d7b4f82e 100644 --- a/drivers/leds/leds-adp5520.c +++ b/drivers/leds/leds-adp5520.c | |||
@@ -120,13 +120,10 @@ static int adp5520_led_probe(struct platform_device *pdev) | |||
120 | 120 | ||
121 | led = devm_kzalloc(&pdev->dev, sizeof(*led) * pdata->num_leds, | 121 | led = devm_kzalloc(&pdev->dev, sizeof(*led) * pdata->num_leds, |
122 | GFP_KERNEL); | 122 | GFP_KERNEL); |
123 | if (led == NULL) { | 123 | if (!led) |
124 | dev_err(&pdev->dev, "failed to alloc memory\n"); | ||
125 | return -ENOMEM; | 124 | return -ENOMEM; |
126 | } | ||
127 | 125 | ||
128 | ret = adp5520_led_prepare(pdev); | 126 | ret = adp5520_led_prepare(pdev); |
129 | |||
130 | if (ret) { | 127 | if (ret) { |
131 | dev_err(&pdev->dev, "failed to write\n"); | 128 | dev_err(&pdev->dev, "failed to write\n"); |
132 | return ret; | 129 | return ret; |
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index fb5a3472d614..6078c15d3452 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c | |||
@@ -678,10 +678,8 @@ static int bd2802_probe(struct i2c_client *client, | |||
678 | int ret, i; | 678 | int ret, i; |
679 | 679 | ||
680 | led = devm_kzalloc(&client->dev, sizeof(struct bd2802_led), GFP_KERNEL); | 680 | led = devm_kzalloc(&client->dev, sizeof(struct bd2802_led), GFP_KERNEL); |
681 | if (!led) { | 681 | if (!led) |
682 | dev_err(&client->dev, "failed to allocate driver data\n"); | ||
683 | return -ENOMEM; | 682 | return -ENOMEM; |
684 | } | ||
685 | 683 | ||
686 | led->client = client; | 684 | led->client = client; |
687 | pdata = led->pdata = dev_get_platdata(&client->dev); | 685 | pdata = led->pdata = dev_get_platdata(&client->dev); |
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c index 35dffb100388..54b8b5216b8b 100644 --- a/drivers/leds/leds-da903x.c +++ b/drivers/leds/leds-da903x.c | |||
@@ -108,10 +108,8 @@ static int da903x_led_probe(struct platform_device *pdev) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | led = devm_kzalloc(&pdev->dev, sizeof(struct da903x_led), GFP_KERNEL); | 110 | led = devm_kzalloc(&pdev->dev, sizeof(struct da903x_led), GFP_KERNEL); |
111 | if (led == NULL) { | 111 | if (!led) |
112 | dev_err(&pdev->dev, "failed to alloc memory for LED%d\n", id); | ||
113 | return -ENOMEM; | 112 | return -ENOMEM; |
114 | } | ||
115 | 113 | ||
116 | led->cdev.name = pdata->name; | 114 | led->cdev.name = pdata->name; |
117 | led->cdev.default_trigger = pdata->default_trigger; | 115 | led->cdev.default_trigger = pdata->default_trigger; |
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c index 01486adc7f8b..e4da1f460ac5 100644 --- a/drivers/leds/leds-da9052.c +++ b/drivers/leds/leds-da9052.c | |||
@@ -126,8 +126,7 @@ static int da9052_led_probe(struct platform_device *pdev) | |||
126 | led = devm_kzalloc(&pdev->dev, | 126 | led = devm_kzalloc(&pdev->dev, |
127 | sizeof(struct da9052_led) * pled->num_leds, | 127 | sizeof(struct da9052_led) * pled->num_leds, |
128 | GFP_KERNEL); | 128 | GFP_KERNEL); |
129 | if (led == NULL) { | 129 | if (!led) { |
130 | dev_err(&pdev->dev, "Failed to alloc memory\n"); | ||
131 | error = -ENOMEM; | 130 | error = -ENOMEM; |
132 | goto err; | 131 | goto err; |
133 | } | 132 | } |
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index cb5ed82994ba..9e1716f8098c 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * lp5523.c - LP5523 LED Driver | 2 | * lp5523.c - LP5523, LP55231 LED Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Nokia Corporation | 4 | * Copyright (C) 2010 Nokia Corporation |
5 | * Copyright (C) 2012 Texas Instruments | 5 | * Copyright (C) 2012 Texas Instruments |
@@ -814,6 +814,7 @@ MODULE_DEVICE_TABLE(i2c, lp5523_id); | |||
814 | #ifdef CONFIG_OF | 814 | #ifdef CONFIG_OF |
815 | static const struct of_device_id of_lp5523_leds_match[] = { | 815 | static const struct of_device_id of_lp5523_leds_match[] = { |
816 | { .compatible = "national,lp5523", }, | 816 | { .compatible = "national,lp5523", }, |
817 | { .compatible = "ti,lp55231", }, | ||
817 | {}, | 818 | {}, |
818 | }; | 819 | }; |
819 | 820 | ||
diff --git a/drivers/leds/leds-pca9685.c b/drivers/leds/leds-pca9685.c deleted file mode 100644 index 6e1ef3a9d6ef..000000000000 --- a/drivers/leds/leds-pca9685.c +++ /dev/null | |||
@@ -1,213 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Maximilian Güntner <maximilian.guentner@gmail.com> | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of version 2 of | ||
5 | * the GNU General Public License. See the file COPYING in the main | ||
6 | * directory of this archive for more details. | ||
7 | * | ||
8 | * Based on leds-pca963x.c driver by | ||
9 | * Peter Meerwald <p.meerwald@bct-electronic.com> | ||
10 | * | ||
11 | * Driver for the NXP PCA9685 12-Bit PWM LED driver chip. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/ctype.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/leds.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | |||
25 | #include <linux/platform_data/leds-pca9685.h> | ||
26 | |||
27 | /* Register Addresses */ | ||
28 | #define PCA9685_MODE1 0x00 | ||
29 | #define PCA9685_MODE2 0x01 | ||
30 | #define PCA9685_LED0_ON_L 0x06 | ||
31 | #define PCA9685_ALL_LED_ON_L 0xFA | ||
32 | |||
33 | /* MODE1 Register */ | ||
34 | #define PCA9685_ALLCALL 0x00 | ||
35 | #define PCA9685_SLEEP 0x04 | ||
36 | #define PCA9685_AI 0x05 | ||
37 | |||
38 | /* MODE2 Register */ | ||
39 | #define PCA9685_INVRT 0x04 | ||
40 | #define PCA9685_OUTDRV 0x02 | ||
41 | |||
42 | static const struct i2c_device_id pca9685_id[] = { | ||
43 | { "pca9685", 0 }, | ||
44 | { } | ||
45 | }; | ||
46 | MODULE_DEVICE_TABLE(i2c, pca9685_id); | ||
47 | |||
48 | struct pca9685_led { | ||
49 | struct i2c_client *client; | ||
50 | struct work_struct work; | ||
51 | u16 brightness; | ||
52 | struct led_classdev led_cdev; | ||
53 | int led_num; /* 0-15 */ | ||
54 | char name[32]; | ||
55 | }; | ||
56 | |||
57 | static void pca9685_write_msg(struct i2c_client *client, u8 *buf, u8 len) | ||
58 | { | ||
59 | struct i2c_msg msg = { | ||
60 | .addr = client->addr, | ||
61 | .flags = 0x00, | ||
62 | .len = len, | ||
63 | .buf = buf | ||
64 | }; | ||
65 | i2c_transfer(client->adapter, &msg, 1); | ||
66 | } | ||
67 | |||
68 | static void pca9685_all_off(struct i2c_client *client) | ||
69 | { | ||
70 | u8 i2c_buffer[5] = {PCA9685_ALL_LED_ON_L, 0x00, 0x00, 0x00, 0x10}; | ||
71 | pca9685_write_msg(client, i2c_buffer, 5); | ||
72 | } | ||
73 | |||
74 | static void pca9685_led_work(struct work_struct *work) | ||
75 | { | ||
76 | struct pca9685_led *pca9685; | ||
77 | u8 i2c_buffer[5]; | ||
78 | |||
79 | pca9685 = container_of(work, struct pca9685_led, work); | ||
80 | i2c_buffer[0] = PCA9685_LED0_ON_L + 4 * pca9685->led_num; | ||
81 | /* | ||
82 | * 4095 is the maximum brightness, so we set the ON time to 0x1000 | ||
83 | * which disables the PWM generator for that LED | ||
84 | */ | ||
85 | if (pca9685->brightness == 4095) | ||
86 | *((__le16 *)(i2c_buffer+1)) = cpu_to_le16(0x1000); | ||
87 | else | ||
88 | *((__le16 *)(i2c_buffer+1)) = 0x0000; | ||
89 | |||
90 | if (pca9685->brightness == 0) | ||
91 | *((__le16 *)(i2c_buffer+3)) = cpu_to_le16(0x1000); | ||
92 | else if (pca9685->brightness == 4095) | ||
93 | *((__le16 *)(i2c_buffer+3)) = 0x0000; | ||
94 | else | ||
95 | *((__le16 *)(i2c_buffer+3)) = cpu_to_le16(pca9685->brightness); | ||
96 | |||
97 | pca9685_write_msg(pca9685->client, i2c_buffer, 5); | ||
98 | } | ||
99 | |||
100 | static void pca9685_led_set(struct led_classdev *led_cdev, | ||
101 | enum led_brightness value) | ||
102 | { | ||
103 | struct pca9685_led *pca9685; | ||
104 | pca9685 = container_of(led_cdev, struct pca9685_led, led_cdev); | ||
105 | pca9685->brightness = value; | ||
106 | |||
107 | schedule_work(&pca9685->work); | ||
108 | } | ||
109 | |||
110 | static int pca9685_probe(struct i2c_client *client, | ||
111 | const struct i2c_device_id *id) | ||
112 | { | ||
113 | struct pca9685_led *pca9685; | ||
114 | struct pca9685_platform_data *pdata; | ||
115 | int err; | ||
116 | u8 i; | ||
117 | |||
118 | pdata = dev_get_platdata(&client->dev); | ||
119 | if (pdata) { | ||
120 | if (pdata->leds.num_leds < 1 || pdata->leds.num_leds > 15) { | ||
121 | dev_err(&client->dev, "board info must claim 1-16 LEDs"); | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | pca9685 = devm_kzalloc(&client->dev, 16 * sizeof(*pca9685), GFP_KERNEL); | ||
127 | if (!pca9685) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | i2c_set_clientdata(client, pca9685); | ||
131 | pca9685_all_off(client); | ||
132 | |||
133 | for (i = 0; i < 16; i++) { | ||
134 | pca9685[i].client = client; | ||
135 | pca9685[i].led_num = i; | ||
136 | pca9685[i].name[0] = '\0'; | ||
137 | if (pdata && i < pdata->leds.num_leds) { | ||
138 | if (pdata->leds.leds[i].name) | ||
139 | strncpy(pca9685[i].name, | ||
140 | pdata->leds.leds[i].name, | ||
141 | sizeof(pca9685[i].name)-1); | ||
142 | if (pdata->leds.leds[i].default_trigger) | ||
143 | pca9685[i].led_cdev.default_trigger = | ||
144 | pdata->leds.leds[i].default_trigger; | ||
145 | } | ||
146 | if (strlen(pca9685[i].name) == 0) { | ||
147 | /* | ||
148 | * Write adapter and address to the name as well. | ||
149 | * Otherwise multiple chips attached to one host would | ||
150 | * not work. | ||
151 | */ | ||
152 | snprintf(pca9685[i].name, sizeof(pca9685[i].name), | ||
153 | "pca9685:%d:x%.2x:%d", | ||
154 | client->adapter->nr, client->addr, i); | ||
155 | } | ||
156 | pca9685[i].led_cdev.name = pca9685[i].name; | ||
157 | pca9685[i].led_cdev.max_brightness = 0xfff; | ||
158 | pca9685[i].led_cdev.brightness_set = pca9685_led_set; | ||
159 | |||
160 | INIT_WORK(&pca9685[i].work, pca9685_led_work); | ||
161 | err = led_classdev_register(&client->dev, &pca9685[i].led_cdev); | ||
162 | if (err < 0) | ||
163 | goto exit; | ||
164 | } | ||
165 | |||
166 | if (pdata) | ||
167 | i2c_smbus_write_byte_data(client, PCA9685_MODE2, | ||
168 | pdata->outdrv << PCA9685_OUTDRV | | ||
169 | pdata->inverted << PCA9685_INVRT); | ||
170 | else | ||
171 | i2c_smbus_write_byte_data(client, PCA9685_MODE2, | ||
172 | PCA9685_TOTEM_POLE << PCA9685_OUTDRV); | ||
173 | /* Enable Auto-Increment, enable oscillator, ALLCALL/SUBADDR disabled */ | ||
174 | i2c_smbus_write_byte_data(client, PCA9685_MODE1, BIT(PCA9685_AI)); | ||
175 | |||
176 | return 0; | ||
177 | |||
178 | exit: | ||
179 | while (i--) { | ||
180 | led_classdev_unregister(&pca9685[i].led_cdev); | ||
181 | cancel_work_sync(&pca9685[i].work); | ||
182 | } | ||
183 | return err; | ||
184 | } | ||
185 | |||
186 | static int pca9685_remove(struct i2c_client *client) | ||
187 | { | ||
188 | struct pca9685_led *pca9685 = i2c_get_clientdata(client); | ||
189 | u8 i; | ||
190 | |||
191 | for (i = 0; i < 16; i++) { | ||
192 | led_classdev_unregister(&pca9685[i].led_cdev); | ||
193 | cancel_work_sync(&pca9685[i].work); | ||
194 | } | ||
195 | pca9685_all_off(client); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static struct i2c_driver pca9685_driver = { | ||
200 | .driver = { | ||
201 | .name = "leds-pca9685", | ||
202 | .owner = THIS_MODULE, | ||
203 | }, | ||
204 | .probe = pca9685_probe, | ||
205 | .remove = pca9685_remove, | ||
206 | .id_table = pca9685_id, | ||
207 | }; | ||
208 | |||
209 | module_i2c_driver(pca9685_driver); | ||
210 | |||
211 | MODULE_AUTHOR("Maximilian Güntner <maximilian.guentner@gmail.com>"); | ||
212 | MODULE_DESCRIPTION("PCA9685 LED Driver"); | ||
213 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index aa770ec1e892..d672bb4480f6 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c | |||
@@ -69,6 +69,10 @@ static void led_pwm_set(struct led_classdev *led_cdev, | |||
69 | 69 | ||
70 | duty *= brightness; | 70 | duty *= brightness; |
71 | do_div(duty, max); | 71 | do_div(duty, max); |
72 | |||
73 | if (led_dat->active_low) | ||
74 | duty = led_dat->period - duty; | ||
75 | |||
72 | led_dat->duty = duty; | 76 | led_dat->duty = duty; |
73 | 77 | ||
74 | if (led_dat->can_sleep) | 78 | if (led_dat->can_sleep) |
@@ -92,55 +96,78 @@ static void led_pwm_cleanup(struct led_pwm_priv *priv) | |||
92 | } | 96 | } |
93 | } | 97 | } |
94 | 98 | ||
95 | static int led_pwm_create_of(struct platform_device *pdev, | 99 | static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, |
96 | struct led_pwm_priv *priv) | 100 | struct led_pwm *led, struct device_node *child) |
97 | { | 101 | { |
98 | struct device_node *child; | 102 | struct led_pwm_data *led_data = &priv->leds[priv->num_leds]; |
99 | int ret; | 103 | int ret; |
100 | 104 | ||
101 | for_each_child_of_node(pdev->dev.of_node, child) { | 105 | led_data->active_low = led->active_low; |
102 | struct led_pwm_data *led_dat = &priv->leds[priv->num_leds]; | 106 | led_data->cdev.name = led->name; |
107 | led_data->cdev.default_trigger = led->default_trigger; | ||
108 | led_data->cdev.brightness_set = led_pwm_set; | ||
109 | led_data->cdev.brightness = LED_OFF; | ||
110 | led_data->cdev.max_brightness = led->max_brightness; | ||
111 | led_data->cdev.flags = LED_CORE_SUSPENDRESUME; | ||
103 | 112 | ||
104 | led_dat->cdev.name = of_get_property(child, "label", | 113 | if (child) |
105 | NULL) ? : child->name; | 114 | led_data->pwm = devm_of_pwm_get(dev, child, NULL); |
115 | else | ||
116 | led_data->pwm = devm_pwm_get(dev, led->name); | ||
117 | if (IS_ERR(led_data->pwm)) { | ||
118 | ret = PTR_ERR(led_data->pwm); | ||
119 | dev_err(dev, "unable to request PWM for %s: %d\n", | ||
120 | led->name, ret); | ||
121 | return ret; | ||
122 | } | ||
106 | 123 | ||
107 | led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL); | 124 | if (child) |
108 | if (IS_ERR(led_dat->pwm)) { | 125 | led_data->period = pwm_get_period(led_data->pwm); |
109 | dev_err(&pdev->dev, "unable to request PWM for %s\n", | ||
110 | led_dat->cdev.name); | ||
111 | ret = PTR_ERR(led_dat->pwm); | ||
112 | goto err; | ||
113 | } | ||
114 | /* Get the period from PWM core when n*/ | ||
115 | led_dat->period = pwm_get_period(led_dat->pwm); | ||
116 | 126 | ||
117 | led_dat->cdev.default_trigger = of_get_property(child, | 127 | led_data->can_sleep = pwm_can_sleep(led_data->pwm); |
118 | "linux,default-trigger", NULL); | 128 | if (led_data->can_sleep) |
119 | of_property_read_u32(child, "max-brightness", | 129 | INIT_WORK(&led_data->work, led_pwm_work); |
120 | &led_dat->cdev.max_brightness); | ||
121 | 130 | ||
122 | led_dat->cdev.brightness_set = led_pwm_set; | 131 | led_data->period = pwm_get_period(led_data->pwm); |
123 | led_dat->cdev.brightness = LED_OFF; | 132 | if (!led_data->period && (led->pwm_period_ns > 0)) |
124 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; | 133 | led_data->period = led->pwm_period_ns; |
125 | 134 | ||
126 | led_dat->can_sleep = pwm_can_sleep(led_dat->pwm); | 135 | ret = led_classdev_register(dev, &led_data->cdev); |
127 | if (led_dat->can_sleep) | 136 | if (ret == 0) { |
128 | INIT_WORK(&led_dat->work, led_pwm_work); | 137 | priv->num_leds++; |
138 | } else { | ||
139 | dev_err(dev, "failed to register PWM led for %s: %d\n", | ||
140 | led->name, ret); | ||
141 | } | ||
142 | |||
143 | return ret; | ||
144 | } | ||
129 | 145 | ||
130 | ret = led_classdev_register(&pdev->dev, &led_dat->cdev); | 146 | static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv) |
131 | if (ret < 0) { | 147 | { |
132 | dev_err(&pdev->dev, "failed to register for %s\n", | 148 | struct device_node *child; |
133 | led_dat->cdev.name); | 149 | struct led_pwm led; |
150 | int ret = 0; | ||
151 | |||
152 | memset(&led, 0, sizeof(led)); | ||
153 | |||
154 | for_each_child_of_node(dev->of_node, child) { | ||
155 | led.name = of_get_property(child, "label", NULL) ? : | ||
156 | child->name; | ||
157 | |||
158 | led.default_trigger = of_get_property(child, | ||
159 | "linux,default-trigger", NULL); | ||
160 | led.active_low = of_property_read_bool(child, "active-low"); | ||
161 | of_property_read_u32(child, "max-brightness", | ||
162 | &led.max_brightness); | ||
163 | |||
164 | ret = led_pwm_add(dev, priv, &led, child); | ||
165 | if (ret) { | ||
134 | of_node_put(child); | 166 | of_node_put(child); |
135 | goto err; | 167 | break; |
136 | } | 168 | } |
137 | priv->num_leds++; | ||
138 | } | 169 | } |
139 | 170 | ||
140 | return 0; | ||
141 | err: | ||
142 | led_pwm_cleanup(priv); | ||
143 | |||
144 | return ret; | 171 | return ret; |
145 | } | 172 | } |
146 | 173 | ||
@@ -166,54 +193,23 @@ static int led_pwm_probe(struct platform_device *pdev) | |||
166 | 193 | ||
167 | if (pdata) { | 194 | if (pdata) { |
168 | for (i = 0; i < count; i++) { | 195 | for (i = 0; i < count; i++) { |
169 | struct led_pwm *cur_led = &pdata->leds[i]; | 196 | ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i], |
170 | struct led_pwm_data *led_dat = &priv->leds[i]; | 197 | NULL); |
171 | 198 | if (ret) | |
172 | led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name); | 199 | break; |
173 | if (IS_ERR(led_dat->pwm)) { | ||
174 | ret = PTR_ERR(led_dat->pwm); | ||
175 | dev_err(&pdev->dev, | ||
176 | "unable to request PWM for %s\n", | ||
177 | cur_led->name); | ||
178 | goto err; | ||
179 | } | ||
180 | |||
181 | led_dat->cdev.name = cur_led->name; | ||
182 | led_dat->cdev.default_trigger = cur_led->default_trigger; | ||
183 | led_dat->active_low = cur_led->active_low; | ||
184 | led_dat->cdev.brightness_set = led_pwm_set; | ||
185 | led_dat->cdev.brightness = LED_OFF; | ||
186 | led_dat->cdev.max_brightness = cur_led->max_brightness; | ||
187 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; | ||
188 | |||
189 | led_dat->can_sleep = pwm_can_sleep(led_dat->pwm); | ||
190 | if (led_dat->can_sleep) | ||
191 | INIT_WORK(&led_dat->work, led_pwm_work); | ||
192 | |||
193 | led_dat->period = pwm_get_period(led_dat->pwm); | ||
194 | if (!led_dat->period && (cur_led->pwm_period_ns > 0)) | ||
195 | led_dat->period = cur_led->pwm_period_ns; | ||
196 | |||
197 | ret = led_classdev_register(&pdev->dev, &led_dat->cdev); | ||
198 | if (ret < 0) | ||
199 | goto err; | ||
200 | } | 200 | } |
201 | priv->num_leds = count; | ||
202 | } else { | 201 | } else { |
203 | ret = led_pwm_create_of(pdev, priv); | 202 | ret = led_pwm_create_of(&pdev->dev, priv); |
204 | if (ret) | 203 | } |
205 | return ret; | 204 | |
205 | if (ret) { | ||
206 | led_pwm_cleanup(priv); | ||
207 | return ret; | ||
206 | } | 208 | } |
207 | 209 | ||
208 | platform_set_drvdata(pdev, priv); | 210 | platform_set_drvdata(pdev, priv); |
209 | 211 | ||
210 | return 0; | 212 | return 0; |
211 | |||
212 | err: | ||
213 | priv->num_leds = i; | ||
214 | led_pwm_cleanup(priv); | ||
215 | |||
216 | return ret; | ||
217 | } | 213 | } |
218 | 214 | ||
219 | static int led_pwm_remove(struct platform_device *pdev) | 215 | static int led_pwm_remove(struct platform_device *pdev) |
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c index 28988b7b4fab..785eb53a87fc 100644 --- a/drivers/leds/leds-s3c24xx.c +++ b/drivers/leds/leds-s3c24xx.c | |||
@@ -76,10 +76,8 @@ static int s3c24xx_led_probe(struct platform_device *dev) | |||
76 | 76 | ||
77 | led = devm_kzalloc(&dev->dev, sizeof(struct s3c24xx_gpio_led), | 77 | led = devm_kzalloc(&dev->dev, sizeof(struct s3c24xx_gpio_led), |
78 | GFP_KERNEL); | 78 | GFP_KERNEL); |
79 | if (led == NULL) { | 79 | if (!led) |
80 | dev_err(&dev->dev, "No memory for device\n"); | ||
81 | return -ENOMEM; | 80 | return -ENOMEM; |
82 | } | ||
83 | 81 | ||
84 | platform_set_drvdata(dev, led); | 82 | platform_set_drvdata(dev, led); |
85 | 83 | ||
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c index 388632d23d44..0b8cc4a021a6 100644 --- a/drivers/leds/leds-sunfire.c +++ b/drivers/leds/leds-sunfire.c | |||
@@ -135,10 +135,8 @@ static int sunfire_led_generic_probe(struct platform_device *pdev, | |||
135 | } | 135 | } |
136 | 136 | ||
137 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | 137 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); |
138 | if (!p) { | 138 | if (!p) |
139 | dev_err(&pdev->dev, "Could not allocate struct sunfire_drvdata\n"); | ||
140 | return -ENOMEM; | 139 | return -ENOMEM; |
141 | } | ||
142 | 140 | ||
143 | for (i = 0; i < NUM_LEDS_PER_BOARD; i++) { | 141 | for (i = 0; i < NUM_LEDS_PER_BOARD; i++) { |
144 | struct led_classdev *lp = &p->leds[i].led_cdev; | 142 | struct led_classdev *lp = &p->leds[i].led_cdev; |
diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c index 1c3ee9fcaf34..aec0f02b6b3e 100644 --- a/drivers/leds/trigger/ledtrig-cpu.c +++ b/drivers/leds/trigger/ledtrig-cpu.c | |||
@@ -47,7 +47,7 @@ static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); | |||
47 | */ | 47 | */ |
48 | void ledtrig_cpu(enum cpu_led_event ledevt) | 48 | void ledtrig_cpu(enum cpu_led_event ledevt) |
49 | { | 49 | { |
50 | struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig); | 50 | struct led_trigger_cpu *trig = this_cpu_ptr(&cpu_trig); |
51 | 51 | ||
52 | /* Locate the correct CPU LED */ | 52 | /* Locate the correct CPU LED */ |
53 | switch (ledevt) { | 53 | switch (ledevt) { |