aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-15 21:28:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-15 21:28:25 -0500
commit2dbfca5a181973558277b28b1f4c36362291f5e0 (patch)
treee9d217adf53e3532939e7a3c3bcec94afd671306 /drivers/leds
parentdab363f938a53ddaee60bfecc1aebdbb3d3af5f0 (diff)
parent2969bb18f8895eb4e0fbbc98efe706f15a3acff5 (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds
Pull LED subsystem update from Bryan Wu: "We got some cleanup and driver for LP8860 as well as some patches for LED Flash Class" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds: leds: lp8860: Fix module dependency leds: lp8860: Introduce TI lp8860 4 channel LED driver leds: Add support for setting brightness in a synchronous way leds: implement sysfs interface locking mechanism leds: syscon: handle multiple syscon instances leds: delete copy/paste mistake leds: regulator: Convert to devm_regulator_get_exclusive
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/Kconfig11
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/led-class.c29
-rw-r--r--drivers/leds/led-core.c36
-rw-r--r--drivers/leds/led-triggers.c16
-rw-r--r--drivers/leds/leds-lp8860.c491
-rw-r--r--drivers/leds/leds-regulator.c18
-rw-r--r--drivers/leds/leds-syscon.c71
-rw-r--r--drivers/leds/leds.h20
-rw-r--r--drivers/leds/trigger/ledtrig-backlight.c8
-rw-r--r--drivers/leds/trigger/ledtrig-default-on.c2
-rw-r--r--drivers/leds/trigger/ledtrig-gpio.c6
-rw-r--r--drivers/leds/trigger/ledtrig-heartbeat.c2
-rw-r--r--drivers/leds/trigger/ledtrig-oneshot.c4
-rw-r--r--drivers/leds/trigger/ledtrig-transient.c10
15 files changed, 645 insertions, 80 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a210338cfeb1..a6c3d2f153f3 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -250,6 +250,17 @@ config LEDS_LP8788
250 help 250 help
251 This option enables support for the Keyboard LEDs on the LP8788 PMIC. 251 This option enables support for the Keyboard LEDs on the LP8788 PMIC.
252 252
253config LEDS_LP8860
254 tristate "LED support for the TI LP8860 4 channel LED driver"
255 depends on LEDS_CLASS && I2C
256 select REGMAP_I2C
257 help
258 If you say yes here you get support for the TI LP8860 4 channel
259 LED driver.
260 This option enables support for the display cluster LEDs
261 on the LP8860 4 channel LED driver using the I2C communication
262 bus.
263
253config LEDS_CLEVO_MAIL 264config LEDS_CLEVO_MAIL
254 tristate "Mail LED on Clevo notebook" 265 tristate "Mail LED on Clevo notebook"
255 depends on LEDS_CLASS 266 depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index a2b164741465..1c65a191d907 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
28obj-$(CONFIG_LEDS_LP5562) += leds-lp5562.o 28obj-$(CONFIG_LEDS_LP5562) += leds-lp5562.o
29obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o 29obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o
30obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o 30obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o
31obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o
31obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o 32obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
32obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 33obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
33obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o 34obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 7440c58b8e6f..dbeebac38d31 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -40,17 +40,27 @@ static ssize_t brightness_store(struct device *dev,
40{ 40{
41 struct led_classdev *led_cdev = dev_get_drvdata(dev); 41 struct led_classdev *led_cdev = dev_get_drvdata(dev);
42 unsigned long state; 42 unsigned long state;
43 ssize_t ret = -EINVAL; 43 ssize_t ret;
44
45 mutex_lock(&led_cdev->led_access);
46
47 if (led_sysfs_is_disabled(led_cdev)) {
48 ret = -EBUSY;
49 goto unlock;
50 }
44 51
45 ret = kstrtoul(buf, 10, &state); 52 ret = kstrtoul(buf, 10, &state);
46 if (ret) 53 if (ret)
47 return ret; 54 goto unlock;
48 55
49 if (state == LED_OFF) 56 if (state == LED_OFF)
50 led_trigger_remove(led_cdev); 57 led_trigger_remove(led_cdev);
51 __led_set_brightness(led_cdev, state); 58 led_set_brightness(led_cdev, state);
52 59
53 return size; 60 ret = size;
61unlock:
62 mutex_unlock(&led_cdev->led_access);
63 return ret;
54} 64}
55static DEVICE_ATTR_RW(brightness); 65static DEVICE_ATTR_RW(brightness);
56 66
@@ -99,7 +109,7 @@ static void led_timer_function(unsigned long data)
99 unsigned long delay; 109 unsigned long delay;
100 110
101 if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) { 111 if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
102 __led_set_brightness(led_cdev, LED_OFF); 112 led_set_brightness_async(led_cdev, LED_OFF);
103 return; 113 return;
104 } 114 }
105 115
@@ -122,7 +132,7 @@ static void led_timer_function(unsigned long data)
122 delay = led_cdev->blink_delay_off; 132 delay = led_cdev->blink_delay_off;
123 } 133 }
124 134
125 __led_set_brightness(led_cdev, brightness); 135 led_set_brightness_async(led_cdev, brightness);
126 136
127 /* Return in next iteration if led is in one-shot mode and we are in 137 /* Return in next iteration if led is in one-shot mode and we are in
128 * the final blink state so that the led is toggled each delay_on + 138 * the final blink state so that the led is toggled each delay_on +
@@ -148,7 +158,7 @@ static void set_brightness_delayed(struct work_struct *ws)
148 158
149 led_stop_software_blink(led_cdev); 159 led_stop_software_blink(led_cdev);
150 160
151 __led_set_brightness(led_cdev, led_cdev->delayed_set_value); 161 led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
152} 162}
153 163
154/** 164/**
@@ -214,6 +224,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
214#ifdef CONFIG_LEDS_TRIGGERS 224#ifdef CONFIG_LEDS_TRIGGERS
215 init_rwsem(&led_cdev->trigger_lock); 225 init_rwsem(&led_cdev->trigger_lock);
216#endif 226#endif
227 mutex_init(&led_cdev->led_access);
217 /* add to the list of leds */ 228 /* add to the list of leds */
218 down_write(&leds_list_lock); 229 down_write(&leds_list_lock);
219 list_add_tail(&led_cdev->node, &leds_list); 230 list_add_tail(&led_cdev->node, &leds_list);
@@ -222,6 +233,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
222 if (!led_cdev->max_brightness) 233 if (!led_cdev->max_brightness)
223 led_cdev->max_brightness = LED_FULL; 234 led_cdev->max_brightness = LED_FULL;
224 235
236 led_cdev->flags |= SET_BRIGHTNESS_ASYNC;
237
225 led_update_brightness(led_cdev); 238 led_update_brightness(led_cdev);
226 239
227 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); 240 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
@@ -267,6 +280,8 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
267 down_write(&leds_list_lock); 280 down_write(&leds_list_lock);
268 list_del(&led_cdev->node); 281 list_del(&led_cdev->node);
269 up_write(&leds_list_lock); 282 up_write(&leds_list_lock);
283
284 mutex_destroy(&led_cdev->led_access);
270} 285}
271EXPORT_SYMBOL_GPL(led_classdev_unregister); 286EXPORT_SYMBOL_GPL(led_classdev_unregister);
272 287
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index aaa8eba9099f..9886dace5ad2 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -42,13 +42,13 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
42 42
43 /* never on - just set to off */ 43 /* never on - just set to off */
44 if (!delay_on) { 44 if (!delay_on) {
45 __led_set_brightness(led_cdev, LED_OFF); 45 led_set_brightness_async(led_cdev, LED_OFF);
46 return; 46 return;
47 } 47 }
48 48
49 /* never off - just set to brightness */ 49 /* never off - just set to brightness */
50 if (!delay_off) { 50 if (!delay_off) {
51 __led_set_brightness(led_cdev, led_cdev->blink_brightness); 51 led_set_brightness_async(led_cdev, led_cdev->blink_brightness);
52 return; 52 return;
53 } 53 }
54 54
@@ -117,6 +117,8 @@ EXPORT_SYMBOL_GPL(led_stop_software_blink);
117void led_set_brightness(struct led_classdev *led_cdev, 117void led_set_brightness(struct led_classdev *led_cdev,
118 enum led_brightness brightness) 118 enum led_brightness brightness)
119{ 119{
120 int ret = 0;
121
120 /* delay brightness setting if need to stop soft-blink timer */ 122 /* delay brightness setting if need to stop soft-blink timer */
121 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) { 123 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
122 led_cdev->delayed_set_value = brightness; 124 led_cdev->delayed_set_value = brightness;
@@ -124,7 +126,17 @@ void led_set_brightness(struct led_classdev *led_cdev,
124 return; 126 return;
125 } 127 }
126 128
127 __led_set_brightness(led_cdev, brightness); 129 if (led_cdev->flags & SET_BRIGHTNESS_ASYNC) {
130 led_set_brightness_async(led_cdev, brightness);
131 return;
132 } else if (led_cdev->flags & SET_BRIGHTNESS_SYNC)
133 ret = led_set_brightness_sync(led_cdev, brightness);
134 else
135 ret = -EINVAL;
136
137 if (ret < 0)
138 dev_dbg(led_cdev->dev, "Setting LED brightness failed (%d)\n",
139 ret);
128} 140}
129EXPORT_SYMBOL(led_set_brightness); 141EXPORT_SYMBOL(led_set_brightness);
130 142
@@ -143,3 +155,21 @@ int led_update_brightness(struct led_classdev *led_cdev)
143 return ret; 155 return ret;
144} 156}
145EXPORT_SYMBOL(led_update_brightness); 157EXPORT_SYMBOL(led_update_brightness);
158
159/* Caller must ensure led_cdev->led_access held */
160void led_sysfs_disable(struct led_classdev *led_cdev)
161{
162 lockdep_assert_held(&led_cdev->led_access);
163
164 led_cdev->flags |= LED_SYSFS_DISABLE;
165}
166EXPORT_SYMBOL_GPL(led_sysfs_disable);
167
168/* Caller must ensure led_cdev->led_access held */
169void led_sysfs_enable(struct led_classdev *led_cdev)
170{
171 lockdep_assert_held(&led_cdev->led_access);
172
173 led_cdev->flags &= ~LED_SYSFS_DISABLE;
174}
175EXPORT_SYMBOL_GPL(led_sysfs_enable);
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index c3734f10fdd5..e8b1120f486d 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -37,6 +37,14 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
37 char trigger_name[TRIG_NAME_MAX]; 37 char trigger_name[TRIG_NAME_MAX];
38 struct led_trigger *trig; 38 struct led_trigger *trig;
39 size_t len; 39 size_t len;
40 int ret = count;
41
42 mutex_lock(&led_cdev->led_access);
43
44 if (led_sysfs_is_disabled(led_cdev)) {
45 ret = -EBUSY;
46 goto unlock;
47 }
40 48
41 trigger_name[sizeof(trigger_name) - 1] = '\0'; 49 trigger_name[sizeof(trigger_name) - 1] = '\0';
42 strncpy(trigger_name, buf, sizeof(trigger_name) - 1); 50 strncpy(trigger_name, buf, sizeof(trigger_name) - 1);
@@ -47,7 +55,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
47 55
48 if (!strcmp(trigger_name, "none")) { 56 if (!strcmp(trigger_name, "none")) {
49 led_trigger_remove(led_cdev); 57 led_trigger_remove(led_cdev);
50 return count; 58 goto unlock;
51 } 59 }
52 60
53 down_read(&triggers_list_lock); 61 down_read(&triggers_list_lock);
@@ -58,12 +66,14 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
58 up_write(&led_cdev->trigger_lock); 66 up_write(&led_cdev->trigger_lock);
59 67
60 up_read(&triggers_list_lock); 68 up_read(&triggers_list_lock);
61 return count; 69 goto unlock;
62 } 70 }
63 } 71 }
64 up_read(&triggers_list_lock); 72 up_read(&triggers_list_lock);
65 73
66 return -EINVAL; 74unlock:
75 mutex_unlock(&led_cdev->led_access);
76 return ret;
67} 77}
68EXPORT_SYMBOL_GPL(led_trigger_store); 78EXPORT_SYMBOL_GPL(led_trigger_store);
69 79
diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c
new file mode 100644
index 000000000000..840e93f3ab3e
--- /dev/null
+++ b/drivers/leds/leds-lp8860.c
@@ -0,0 +1,491 @@
1/*
2 * TI LP8860 4-Channel LED Driver
3 *
4 * Copyright (C) 2014 Texas Instruments
5 *
6 * Author: Dan Murphy <dmurphy@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/i2c.h>
15#include <linux/init.h>
16#include <linux/leds.h>
17#include <linux/regmap.h>
18#include <linux/regulator/consumer.h>
19#include <linux/module.h>
20#include <linux/mutex.h>
21#include <linux/of.h>
22#include <linux/of_gpio.h>
23#include <linux/gpio/consumer.h>
24#include <linux/slab.h>
25
26#define LP8860_DISP_CL1_BRT_MSB 0x00
27#define LP8860_DISP_CL1_BRT_LSB 0x01
28#define LP8860_DISP_CL1_CURR_MSB 0x02
29#define LP8860_DISP_CL1_CURR_LSB 0x03
30#define LP8860_CL2_BRT_MSB 0x04
31#define LP8860_CL2_BRT_LSB 0x05
32#define LP8860_CL2_CURRENT 0x06
33#define LP8860_CL3_BRT_MSB 0x07
34#define LP8860_CL3_BRT_LSB 0x08
35#define LP8860_CL3_CURRENT 0x09
36#define LP8860_CL4_BRT_MSB 0x0a
37#define LP8860_CL4_BRT_LSB 0x0b
38#define LP8860_CL4_CURRENT 0x0c
39#define LP8860_CONFIG 0x0d
40#define LP8860_STATUS 0x0e
41#define LP8860_FAULT 0x0f
42#define LP8860_LED_FAULT 0x10
43#define LP8860_FAULT_CLEAR 0x11
44#define LP8860_ID 0x12
45#define LP8860_TEMP_MSB 0x13
46#define LP8860_TEMP_LSB 0x14
47#define LP8860_DISP_LED_CURR_MSB 0x15
48#define LP8860_DISP_LED_CURR_LSB 0x16
49#define LP8860_DISP_LED_PWM_MSB 0x17
50#define LP8860_DISP_LED_PWM_LSB 0x18
51#define LP8860_EEPROM_CNTRL 0x19
52#define LP8860_EEPROM_UNLOCK 0x1a
53
54#define LP8860_EEPROM_REG_0 0x60
55#define LP8860_EEPROM_REG_1 0x61
56#define LP8860_EEPROM_REG_2 0x62
57#define LP8860_EEPROM_REG_3 0x63
58#define LP8860_EEPROM_REG_4 0x64
59#define LP8860_EEPROM_REG_5 0x65
60#define LP8860_EEPROM_REG_6 0x66
61#define LP8860_EEPROM_REG_7 0x67
62#define LP8860_EEPROM_REG_8 0x68
63#define LP8860_EEPROM_REG_9 0x69
64#define LP8860_EEPROM_REG_10 0x6a
65#define LP8860_EEPROM_REG_11 0x6b
66#define LP8860_EEPROM_REG_12 0x6c
67#define LP8860_EEPROM_REG_13 0x6d
68#define LP8860_EEPROM_REG_14 0x6e
69#define LP8860_EEPROM_REG_15 0x6f
70#define LP8860_EEPROM_REG_16 0x70
71#define LP8860_EEPROM_REG_17 0x71
72#define LP8860_EEPROM_REG_18 0x72
73#define LP8860_EEPROM_REG_19 0x73
74#define LP8860_EEPROM_REG_20 0x74
75#define LP8860_EEPROM_REG_21 0x75
76#define LP8860_EEPROM_REG_22 0x76
77#define LP8860_EEPROM_REG_23 0x77
78#define LP8860_EEPROM_REG_24 0x78
79
80#define LP8860_LOCK_EEPROM 0x00
81#define LP8860_UNLOCK_EEPROM 0x01
82#define LP8860_PROGRAM_EEPROM 0x02
83#define LP8860_EEPROM_CODE_1 0x08
84#define LP8860_EEPROM_CODE_2 0xba
85#define LP8860_EEPROM_CODE_3 0xef
86
87#define LP8860_CLEAR_FAULTS 0x01
88
89#define LP8860_DISP_LED_NAME "display_cluster"
90
91/**
92 * struct lp8860_led -
93 * @lock - Lock for reading/writing the device
94 * @work - Work item used to off load the brightness register writes
95 * @client - Pointer to the I2C client
96 * @led_dev - led class device pointer
97 * @regmap - Devices register map
98 * @eeprom_regmap - EEPROM register map
99 * @enable_gpio - VDDIO/EN gpio to enable communication interface
100 * @regulator - LED supply regulator pointer
101 * @brightness - Current brightness value requested
102 * @label - LED label
103**/
104struct lp8860_led {
105 struct mutex lock;
106 struct work_struct work;
107 struct i2c_client *client;
108 struct led_classdev led_dev;
109 struct regmap *regmap;
110 struct regmap *eeprom_regmap;
111 struct gpio_desc *enable_gpio;
112 struct regulator *regulator;
113 enum led_brightness brightness;
114 const char *label;
115};
116
117struct lp8860_eeprom_reg {
118 uint8_t reg;
119 uint8_t value;
120};
121
122static struct lp8860_eeprom_reg lp8860_eeprom_disp_regs[] = {
123 { LP8860_EEPROM_REG_0, 0xed },
124 { LP8860_EEPROM_REG_1, 0xdf },
125 { LP8860_EEPROM_REG_2, 0xdc },
126 { LP8860_EEPROM_REG_3, 0xf0 },
127 { LP8860_EEPROM_REG_4, 0xdf },
128 { LP8860_EEPROM_REG_5, 0xe5 },
129 { LP8860_EEPROM_REG_6, 0xf2 },
130 { LP8860_EEPROM_REG_7, 0x77 },
131 { LP8860_EEPROM_REG_8, 0x77 },
132 { LP8860_EEPROM_REG_9, 0x71 },
133 { LP8860_EEPROM_REG_10, 0x3f },
134 { LP8860_EEPROM_REG_11, 0xb7 },
135 { LP8860_EEPROM_REG_12, 0x17 },
136 { LP8860_EEPROM_REG_13, 0xef },
137 { LP8860_EEPROM_REG_14, 0xb0 },
138 { LP8860_EEPROM_REG_15, 0x87 },
139 { LP8860_EEPROM_REG_16, 0xce },
140 { LP8860_EEPROM_REG_17, 0x72 },
141 { LP8860_EEPROM_REG_18, 0xe5 },
142 { LP8860_EEPROM_REG_19, 0xdf },
143 { LP8860_EEPROM_REG_20, 0x35 },
144 { LP8860_EEPROM_REG_21, 0x06 },
145 { LP8860_EEPROM_REG_22, 0xdc },
146 { LP8860_EEPROM_REG_23, 0x88 },
147 { LP8860_EEPROM_REG_24, 0x3E },
148};
149
150static int lp8860_unlock_eeprom(struct lp8860_led *led, int lock)
151{
152 int ret;
153
154 mutex_lock(&led->lock);
155
156 if (lock == LP8860_UNLOCK_EEPROM) {
157 ret = regmap_write(led->regmap,
158 LP8860_EEPROM_UNLOCK,
159 LP8860_EEPROM_CODE_1);
160 if (ret) {
161 dev_err(&led->client->dev, "EEPROM Unlock failed\n");
162 goto out;
163 }
164
165 ret = regmap_write(led->regmap,
166 LP8860_EEPROM_UNLOCK,
167 LP8860_EEPROM_CODE_2);
168 if (ret) {
169 dev_err(&led->client->dev, "EEPROM Unlock failed\n");
170 goto out;
171 }
172 ret = regmap_write(led->regmap,
173 LP8860_EEPROM_UNLOCK,
174 LP8860_EEPROM_CODE_3);
175 if (ret) {
176 dev_err(&led->client->dev, "EEPROM Unlock failed\n");
177 goto out;
178 }
179 } else {
180 ret = regmap_write(led->regmap,
181 LP8860_EEPROM_UNLOCK,
182 LP8860_LOCK_EEPROM);
183 }
184
185out:
186 mutex_unlock(&led->lock);
187 return ret;
188}
189
190static int lp8860_fault_check(struct lp8860_led *led)
191{
192 int ret, fault;
193 unsigned int read_buf;
194
195 ret = regmap_read(led->regmap, LP8860_LED_FAULT, &read_buf);
196 if (ret)
197 goto out;
198
199 fault = read_buf;
200
201 ret = regmap_read(led->regmap, LP8860_FAULT, &read_buf);
202 if (ret)
203 goto out;
204
205 fault |= read_buf;
206
207 /* Attempt to clear any faults */
208 if (fault)
209 ret = regmap_write(led->regmap, LP8860_FAULT_CLEAR,
210 LP8860_CLEAR_FAULTS);
211out:
212 return ret;
213}
214
215static void lp8860_led_brightness_work(struct work_struct *work)
216{
217 struct lp8860_led *led = container_of(work, struct lp8860_led, work);
218 int ret;
219 int disp_brightness = led->brightness * 255;
220
221 mutex_lock(&led->lock);
222
223 ret = lp8860_fault_check(led);
224 if (ret) {
225 dev_err(&led->client->dev, "Cannot read/clear faults\n");
226 goto out;
227 }
228
229 ret = regmap_write(led->regmap, LP8860_DISP_CL1_BRT_MSB,
230 (disp_brightness & 0xff00) >> 8);
231 if (ret) {
232 dev_err(&led->client->dev, "Cannot write CL1 MSB\n");
233 goto out;
234 }
235
236 ret = regmap_write(led->regmap, LP8860_DISP_CL1_BRT_LSB,
237 disp_brightness & 0xff);
238 if (ret) {
239 dev_err(&led->client->dev, "Cannot write CL1 LSB\n");
240 goto out;
241 }
242out:
243 mutex_unlock(&led->lock);
244}
245
246static void lp8860_brightness_set(struct led_classdev *led_cdev,
247 enum led_brightness brt_val)
248{
249 struct lp8860_led *led =
250 container_of(led_cdev, struct lp8860_led, led_dev);
251
252 led->brightness = brt_val;
253 schedule_work(&led->work);
254}
255
256static int lp8860_init(struct lp8860_led *led)
257{
258 unsigned int read_buf;
259 int ret, i, reg_count;
260
261 if (led->enable_gpio)
262 gpiod_direction_output(led->enable_gpio, 1);
263
264 ret = lp8860_fault_check(led);
265 if (ret)
266 goto out;
267
268 ret = regmap_read(led->regmap, LP8860_STATUS, &read_buf);
269 if (ret)
270 goto out;
271
272 ret = lp8860_unlock_eeprom(led, LP8860_UNLOCK_EEPROM);
273 if (ret) {
274 dev_err(&led->client->dev, "Failed unlocking EEPROM\n");
275 goto out;
276 }
277
278 reg_count = ARRAY_SIZE(lp8860_eeprom_disp_regs) / sizeof(lp8860_eeprom_disp_regs[0]);
279 for (i = 0; i < reg_count; i++) {
280 ret = regmap_write(led->eeprom_regmap,
281 lp8860_eeprom_disp_regs[i].reg,
282 lp8860_eeprom_disp_regs[i].value);
283 if (ret) {
284 dev_err(&led->client->dev, "Failed writing EEPROM\n");
285 goto out;
286 }
287 }
288
289 ret = lp8860_unlock_eeprom(led, LP8860_LOCK_EEPROM);
290 if (ret)
291 goto out;
292
293 ret = regmap_write(led->regmap,
294 LP8860_EEPROM_CNTRL,
295 LP8860_PROGRAM_EEPROM);
296 if (ret)
297 dev_err(&led->client->dev, "Failed programming EEPROM\n");
298out:
299 if (ret)
300 if (led->enable_gpio)
301 gpiod_direction_output(led->enable_gpio, 0);
302 return ret;
303}
304
305static struct reg_default lp8860_reg_defs[] = {
306 { LP8860_DISP_CL1_BRT_MSB, 0x00},
307 { LP8860_DISP_CL1_BRT_LSB, 0x00},
308 { LP8860_DISP_CL1_CURR_MSB, 0x00},
309 { LP8860_DISP_CL1_CURR_LSB, 0x00},
310 { LP8860_CL2_BRT_MSB, 0x00},
311 { LP8860_CL2_BRT_LSB, 0x00},
312 { LP8860_CL2_CURRENT, 0x00},
313 { LP8860_CL3_BRT_MSB, 0x00},
314 { LP8860_CL3_BRT_LSB, 0x00},
315 { LP8860_CL3_CURRENT, 0x00},
316 { LP8860_CL4_BRT_MSB, 0x00},
317 { LP8860_CL4_BRT_LSB, 0x00},
318 { LP8860_CL4_CURRENT, 0x00},
319 { LP8860_CONFIG, 0x00},
320 { LP8860_FAULT_CLEAR, 0x00},
321 { LP8860_EEPROM_CNTRL, 0x80},
322 { LP8860_EEPROM_UNLOCK, 0x00},
323};
324
325static const struct regmap_config lp8860_regmap_config = {
326 .reg_bits = 8,
327 .val_bits = 8,
328
329 .max_register = LP8860_EEPROM_UNLOCK,
330 .reg_defaults = lp8860_reg_defs,
331 .num_reg_defaults = ARRAY_SIZE(lp8860_reg_defs),
332 .cache_type = REGCACHE_NONE,
333};
334
335static struct reg_default lp8860_eeprom_defs[] = {
336 { LP8860_EEPROM_REG_0, 0x00 },
337 { LP8860_EEPROM_REG_1, 0x00 },
338 { LP8860_EEPROM_REG_2, 0x00 },
339 { LP8860_EEPROM_REG_3, 0x00 },
340 { LP8860_EEPROM_REG_4, 0x00 },
341 { LP8860_EEPROM_REG_5, 0x00 },
342 { LP8860_EEPROM_REG_6, 0x00 },
343 { LP8860_EEPROM_REG_7, 0x00 },
344 { LP8860_EEPROM_REG_8, 0x00 },
345 { LP8860_EEPROM_REG_9, 0x00 },
346 { LP8860_EEPROM_REG_10, 0x00 },
347 { LP8860_EEPROM_REG_11, 0x00 },
348 { LP8860_EEPROM_REG_12, 0x00 },
349 { LP8860_EEPROM_REG_13, 0x00 },
350 { LP8860_EEPROM_REG_14, 0x00 },
351 { LP8860_EEPROM_REG_15, 0x00 },
352 { LP8860_EEPROM_REG_16, 0x00 },
353 { LP8860_EEPROM_REG_17, 0x00 },
354 { LP8860_EEPROM_REG_18, 0x00 },
355 { LP8860_EEPROM_REG_19, 0x00 },
356 { LP8860_EEPROM_REG_20, 0x00 },
357 { LP8860_EEPROM_REG_21, 0x00 },
358 { LP8860_EEPROM_REG_22, 0x00 },
359 { LP8860_EEPROM_REG_23, 0x00 },
360 { LP8860_EEPROM_REG_24, 0x00 },
361};
362
363static const struct regmap_config lp8860_eeprom_regmap_config = {
364 .reg_bits = 8,
365 .val_bits = 8,
366
367 .max_register = LP8860_EEPROM_REG_24,
368 .reg_defaults = lp8860_eeprom_defs,
369 .num_reg_defaults = ARRAY_SIZE(lp8860_eeprom_defs),
370 .cache_type = REGCACHE_NONE,
371};
372
373static int lp8860_probe(struct i2c_client *client,
374 const struct i2c_device_id *id)
375{
376 int ret;
377 struct lp8860_led *led;
378 struct device_node *np = client->dev.of_node;
379
380 led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
381 if (!led)
382 return -ENOMEM;
383
384 led->label = LP8860_DISP_LED_NAME;
385
386 if (client->dev.of_node) {
387 ret = of_property_read_string(np, "label", &led->label);
388 if (ret) {
389 dev_err(&client->dev, "Missing label in dt\n");
390 return -EINVAL;
391 }
392 }
393
394 led->enable_gpio = devm_gpiod_get(&client->dev, "enable");
395 if (IS_ERR(led->enable_gpio))
396 led->enable_gpio = NULL;
397 else
398 gpiod_direction_output(led->enable_gpio, 0);
399
400 led->regulator = devm_regulator_get(&client->dev, "vled");
401 if (IS_ERR(led->regulator))
402 led->regulator = NULL;
403
404 led->client = client;
405 led->led_dev.name = led->label;
406 led->led_dev.max_brightness = LED_FULL;
407 led->led_dev.brightness_set = lp8860_brightness_set;
408
409 mutex_init(&led->lock);
410 INIT_WORK(&led->work, lp8860_led_brightness_work);
411
412 i2c_set_clientdata(client, led);
413
414 led->regmap = devm_regmap_init_i2c(client, &lp8860_regmap_config);
415 if (IS_ERR(led->regmap)) {
416 ret = PTR_ERR(led->regmap);
417 dev_err(&client->dev, "Failed to allocate register map: %d\n",
418 ret);
419 return ret;
420 }
421
422 led->eeprom_regmap = devm_regmap_init_i2c(client, &lp8860_eeprom_regmap_config);
423 if (IS_ERR(led->eeprom_regmap)) {
424 ret = PTR_ERR(led->eeprom_regmap);
425 dev_err(&client->dev, "Failed to allocate register map: %d\n",
426 ret);
427 return ret;
428 }
429
430 ret = lp8860_init(led);
431 if (ret)
432 return ret;
433
434 ret = led_classdev_register(&client->dev, &led->led_dev);
435 if (ret) {
436 dev_err(&client->dev, "led register err: %d\n", ret);
437 return ret;
438 }
439
440 return 0;
441}
442
443static int lp8860_remove(struct i2c_client *client)
444{
445 struct lp8860_led *led = i2c_get_clientdata(client);
446 int ret;
447
448 led_classdev_unregister(&led->led_dev);
449 cancel_work_sync(&led->work);
450
451 if (led->enable_gpio)
452 gpiod_direction_output(led->enable_gpio, 0);
453
454 if (led->regulator) {
455 ret = regulator_disable(led->regulator);
456 if (ret)
457 dev_err(&led->client->dev,
458 "Failed to disable regulator\n");
459 }
460
461 return 0;
462}
463
464static const struct i2c_device_id lp8860_id[] = {
465 { "lp8860", 0 },
466 { }
467};
468MODULE_DEVICE_TABLE(i2c, lp8860_id);
469
470#ifdef CONFIG_OF
471static const struct of_device_id of_lp8860_leds_match[] = {
472 { .compatible = "ti,lp8860", },
473 {},
474};
475MODULE_DEVICE_TABLE(of, of_lp8860_leds_match);
476#endif
477
478static struct i2c_driver lp8860_driver = {
479 .driver = {
480 .name = "lp8860",
481 .of_match_table = of_match_ptr(of_lp8860_leds_match),
482 },
483 .probe = lp8860_probe,
484 .remove = lp8860_remove,
485 .id_table = lp8860_id,
486};
487module_i2c_driver(lp8860_driver);
488
489MODULE_DESCRIPTION("Texas Instruments LP8860 LED drvier");
490MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
491MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index fa1126f12063..ffc21397a675 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -153,24 +153,21 @@ static int regulator_led_probe(struct platform_device *pdev)
153 return -ENODEV; 153 return -ENODEV;
154 } 154 }
155 155
156 vcc = regulator_get_exclusive(&pdev->dev, "vled"); 156 vcc = devm_regulator_get_exclusive(&pdev->dev, "vled");
157 if (IS_ERR(vcc)) { 157 if (IS_ERR(vcc)) {
158 dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name); 158 dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
159 return PTR_ERR(vcc); 159 return PTR_ERR(vcc);
160 } 160 }
161 161
162 led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL); 162 led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
163 if (led == NULL) { 163 if (led == NULL)
164 ret = -ENOMEM; 164 return -ENOMEM;
165 goto err_vcc;
166 }
167 165
168 led->cdev.max_brightness = led_regulator_get_max_brightness(vcc); 166 led->cdev.max_brightness = led_regulator_get_max_brightness(vcc);
169 if (pdata->brightness > led->cdev.max_brightness) { 167 if (pdata->brightness > led->cdev.max_brightness) {
170 dev_err(&pdev->dev, "Invalid default brightness %d\n", 168 dev_err(&pdev->dev, "Invalid default brightness %d\n",
171 pdata->brightness); 169 pdata->brightness);
172 ret = -EINVAL; 170 return -EINVAL;
173 goto err_vcc;
174 } 171 }
175 led->value = pdata->brightness; 172 led->value = pdata->brightness;
176 173
@@ -191,7 +188,7 @@ static int regulator_led_probe(struct platform_device *pdev)
191 ret = led_classdev_register(&pdev->dev, &led->cdev); 188 ret = led_classdev_register(&pdev->dev, &led->cdev);
192 if (ret < 0) { 189 if (ret < 0) {
193 cancel_work_sync(&led->work); 190 cancel_work_sync(&led->work);
194 goto err_vcc; 191 return ret;
195 } 192 }
196 193
197 /* to expose the default value to userspace */ 194 /* to expose the default value to userspace */
@@ -201,10 +198,6 @@ static int regulator_led_probe(struct platform_device *pdev)
201 regulator_led_set_value(led); 198 regulator_led_set_value(led);
202 199
203 return 0; 200 return 0;
204
205err_vcc:
206 regulator_put(vcc);
207 return ret;
208} 201}
209 202
210static int regulator_led_remove(struct platform_device *pdev) 203static int regulator_led_remove(struct platform_device *pdev)
@@ -214,7 +207,6 @@ static int regulator_led_remove(struct platform_device *pdev)
214 led_classdev_unregister(&led->cdev); 207 led_classdev_unregister(&led->cdev);
215 cancel_work_sync(&led->work); 208 cancel_work_sync(&led->work);
216 regulator_led_disable(led); 209 regulator_led_disable(led);
217 regulator_put(led->vcc);
218 return 0; 210 return 0;
219} 211}
220 212
diff --git a/drivers/leds/leds-syscon.c b/drivers/leds/leds-syscon.c
index 3afec79c43f4..6896e2d9ba58 100644
--- a/drivers/leds/leds-syscon.c
+++ b/drivers/leds/leds-syscon.c
@@ -18,10 +18,6 @@
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA 20 * MA 02111-1307 USA
21 *
22 * This driver provides system reboot functionality for APM X-Gene SoC.
23 * For system shutdown, this is board specify. If a board designer
24 * implements GPIO shutdown, use the gpio-poweroff.c driver.
25 */ 21 */
26#include <linux/io.h> 22#include <linux/io.h>
27#include <linux/of_device.h> 23#include <linux/of_device.h>
@@ -70,39 +66,13 @@ static void syscon_led_set(struct led_classdev *led_cdev,
70 dev_err(sled->cdev.dev, "error updating LED status\n"); 66 dev_err(sled->cdev.dev, "error updating LED status\n");
71} 67}
72 68
73static const struct of_device_id syscon_match[] = { 69static int __init syscon_leds_spawn(struct device_node *np,
74 { .compatible = "syscon", }, 70 struct device *dev,
75 {}, 71 struct regmap *map)
76};
77
78static int __init syscon_leds_init(void)
79{ 72{
80 const struct of_device_id *devid;
81 struct device_node *np;
82 struct device_node *child; 73 struct device_node *child;
83 struct regmap *map;
84 struct platform_device *pdev;
85 struct device *dev;
86 int ret; 74 int ret;
87 75
88 np = of_find_matching_node_and_match(NULL, syscon_match,
89 &devid);
90 if (!np)
91 return -ENODEV;
92
93 map = syscon_node_to_regmap(np);
94 if (IS_ERR(map))
95 return PTR_ERR(map);
96
97 /*
98 * If the map is there, the device should be there, we allocate
99 * memory on the syscon device's behalf here.
100 */
101 pdev = of_find_device_by_node(np);
102 if (!pdev)
103 return -ENODEV;
104 dev = &pdev->dev;
105
106 for_each_available_child_of_node(np, child) { 76 for_each_available_child_of_node(np, child) {
107 struct syscon_led *sled; 77 struct syscon_led *sled;
108 const char *state; 78 const char *state;
@@ -150,7 +120,6 @@ static int __init syscon_leds_init(void)
150 if (ret < 0) 120 if (ret < 0)
151 return ret; 121 return ret;
152 } 122 }
153
154 } 123 }
155 sled->cdev.brightness_set = syscon_led_set; 124 sled->cdev.brightness_set = syscon_led_set;
156 125
@@ -160,7 +129,39 @@ static int __init syscon_leds_init(void)
160 129
161 dev_info(dev, "registered LED %s\n", sled->cdev.name); 130 dev_info(dev, "registered LED %s\n", sled->cdev.name);
162 } 131 }
132 return 0;
133}
134
135static int __init syscon_leds_init(void)
136{
137 struct device_node *np;
138
139 for_each_of_allnodes(np) {
140 struct platform_device *pdev;
141 struct regmap *map;
142 int ret;
143
144 if (!of_device_is_compatible(np, "syscon"))
145 continue;
146
147 map = syscon_node_to_regmap(np);
148 if (IS_ERR(map)) {
149 pr_err("error getting regmap for syscon LEDs\n");
150 continue;
151 }
152
153 /*
154 * If the map is there, the device should be there, we allocate
155 * memory on the syscon device's behalf here.
156 */
157 pdev = of_find_device_by_node(np);
158 if (!pdev)
159 return -ENODEV;
160 ret = syscon_leds_spawn(np, &pdev->dev, map);
161 if (ret)
162 dev_err(&pdev->dev, "could not spawn syscon LEDs\n");
163 }
163 164
164 return 0; 165 return 0;
165} 166}
166device_initcall(syscon_leds_init); 167device_initcall(syscon_leds_init);
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index 4c50365344a9..2348dbda5269 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -17,16 +17,28 @@
17#include <linux/rwsem.h> 17#include <linux/rwsem.h>
18#include <linux/leds.h> 18#include <linux/leds.h>
19 19
20static inline void __led_set_brightness(struct led_classdev *led_cdev, 20static inline void led_set_brightness_async(struct led_classdev *led_cdev,
21 enum led_brightness value) 21 enum led_brightness value)
22{ 22{
23 if (value > led_cdev->max_brightness) 23 led_cdev->brightness = min(value, led_cdev->max_brightness);
24 value = led_cdev->max_brightness; 24
25 led_cdev->brightness = value;
26 if (!(led_cdev->flags & LED_SUSPENDED)) 25 if (!(led_cdev->flags & LED_SUSPENDED))
27 led_cdev->brightness_set(led_cdev, value); 26 led_cdev->brightness_set(led_cdev, value);
28} 27}
29 28
29static inline int led_set_brightness_sync(struct led_classdev *led_cdev,
30 enum led_brightness value)
31{
32 int ret = 0;
33
34 led_cdev->brightness = min(value, led_cdev->max_brightness);
35
36 if (!(led_cdev->flags & LED_SUSPENDED))
37 ret = led_cdev->brightness_set_sync(led_cdev,
38 led_cdev->brightness);
39 return ret;
40}
41
30static inline int led_get_brightness(struct led_classdev *led_cdev) 42static inline int led_get_brightness(struct led_classdev *led_cdev)
31{ 43{
32 return led_cdev->brightness; 44 return led_cdev->brightness;
diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c
index 47e55aa9eefa..59eca17d9661 100644
--- a/drivers/leds/trigger/ledtrig-backlight.c
+++ b/drivers/leds/trigger/ledtrig-backlight.c
@@ -51,9 +51,9 @@ static int fb_notifier_callback(struct notifier_block *p,
51 51
52 if ((n->old_status == UNBLANK) ^ n->invert) { 52 if ((n->old_status == UNBLANK) ^ n->invert) {
53 n->brightness = led->brightness; 53 n->brightness = led->brightness;
54 __led_set_brightness(led, LED_OFF); 54 led_set_brightness_async(led, LED_OFF);
55 } else { 55 } else {
56 __led_set_brightness(led, n->brightness); 56 led_set_brightness_async(led, n->brightness);
57 } 57 }
58 58
59 n->old_status = new_status; 59 n->old_status = new_status;
@@ -89,9 +89,9 @@ static ssize_t bl_trig_invert_store(struct device *dev,
89 89
90 /* After inverting, we need to update the LED. */ 90 /* After inverting, we need to update the LED. */
91 if ((n->old_status == BLANK) ^ n->invert) 91 if ((n->old_status == BLANK) ^ n->invert)
92 __led_set_brightness(led, LED_OFF); 92 led_set_brightness_async(led, LED_OFF);
93 else 93 else
94 __led_set_brightness(led, n->brightness); 94 led_set_brightness_async(led, n->brightness);
95 95
96 return num; 96 return num;
97} 97}
diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c
index 81a91be8e18d..6f38f883aaf1 100644
--- a/drivers/leds/trigger/ledtrig-default-on.c
+++ b/drivers/leds/trigger/ledtrig-default-on.c
@@ -19,7 +19,7 @@
19 19
20static void defon_trig_activate(struct led_classdev *led_cdev) 20static void defon_trig_activate(struct led_classdev *led_cdev)
21{ 21{
22 __led_set_brightness(led_cdev, led_cdev->max_brightness); 22 led_set_brightness_async(led_cdev, led_cdev->max_brightness);
23} 23}
24 24
25static struct led_trigger defon_led_trigger = { 25static struct led_trigger defon_led_trigger = {
diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c
index c86c41826476..4cc7040746c6 100644
--- a/drivers/leds/trigger/ledtrig-gpio.c
+++ b/drivers/leds/trigger/ledtrig-gpio.c
@@ -54,12 +54,12 @@ static void gpio_trig_work(struct work_struct *work)
54 54
55 if (tmp) { 55 if (tmp) {
56 if (gpio_data->desired_brightness) 56 if (gpio_data->desired_brightness)
57 __led_set_brightness(gpio_data->led, 57 led_set_brightness_async(gpio_data->led,
58 gpio_data->desired_brightness); 58 gpio_data->desired_brightness);
59 else 59 else
60 __led_set_brightness(gpio_data->led, LED_FULL); 60 led_set_brightness_async(gpio_data->led, LED_FULL);
61 } else { 61 } else {
62 __led_set_brightness(gpio_data->led, LED_OFF); 62 led_set_brightness_async(gpio_data->led, LED_OFF);
63 } 63 }
64} 64}
65 65
diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c
index 5c8464a33172..fea6871d2609 100644
--- a/drivers/leds/trigger/ledtrig-heartbeat.c
+++ b/drivers/leds/trigger/ledtrig-heartbeat.c
@@ -74,7 +74,7 @@ static void led_heartbeat_function(unsigned long data)
74 break; 74 break;
75 } 75 }
76 76
77 __led_set_brightness(led_cdev, brightness); 77 led_set_brightness_async(led_cdev, brightness);
78 mod_timer(&heartbeat_data->timer, jiffies + delay); 78 mod_timer(&heartbeat_data->timer, jiffies + delay);
79} 79}
80 80
diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c
index cb4c7466692a..fbd02cdc3ad7 100644
--- a/drivers/leds/trigger/ledtrig-oneshot.c
+++ b/drivers/leds/trigger/ledtrig-oneshot.c
@@ -63,9 +63,9 @@ static ssize_t led_invert_store(struct device *dev,
63 oneshot_data->invert = !!state; 63 oneshot_data->invert = !!state;
64 64
65 if (oneshot_data->invert) 65 if (oneshot_data->invert)
66 __led_set_brightness(led_cdev, LED_FULL); 66 led_set_brightness_async(led_cdev, LED_FULL);
67 else 67 else
68 __led_set_brightness(led_cdev, LED_OFF); 68 led_set_brightness_async(led_cdev, LED_OFF);
69 69
70 return size; 70 return size;
71} 71}
diff --git a/drivers/leds/trigger/ledtrig-transient.c b/drivers/leds/trigger/ledtrig-transient.c
index e5abc00bb00c..3c34de404d18 100644
--- a/drivers/leds/trigger/ledtrig-transient.c
+++ b/drivers/leds/trigger/ledtrig-transient.c
@@ -41,7 +41,7 @@ static void transient_timer_function(unsigned long data)
41 struct transient_trig_data *transient_data = led_cdev->trigger_data; 41 struct transient_trig_data *transient_data = led_cdev->trigger_data;
42 42
43 transient_data->activate = 0; 43 transient_data->activate = 0;
44 __led_set_brightness(led_cdev, transient_data->restore_state); 44 led_set_brightness_async(led_cdev, transient_data->restore_state);
45} 45}
46 46
47static ssize_t transient_activate_show(struct device *dev, 47static ssize_t transient_activate_show(struct device *dev,
@@ -72,7 +72,8 @@ static ssize_t transient_activate_store(struct device *dev,
72 if (state == 0 && transient_data->activate == 1) { 72 if (state == 0 && transient_data->activate == 1) {
73 del_timer(&transient_data->timer); 73 del_timer(&transient_data->timer);
74 transient_data->activate = state; 74 transient_data->activate = state;
75 __led_set_brightness(led_cdev, transient_data->restore_state); 75 led_set_brightness_async(led_cdev,
76 transient_data->restore_state);
76 return size; 77 return size;
77 } 78 }
78 79
@@ -80,7 +81,7 @@ static ssize_t transient_activate_store(struct device *dev,
80 if (state == 1 && transient_data->activate == 0 && 81 if (state == 1 && transient_data->activate == 0 &&
81 transient_data->duration != 0) { 82 transient_data->duration != 0) {
82 transient_data->activate = state; 83 transient_data->activate = state;
83 __led_set_brightness(led_cdev, transient_data->state); 84 led_set_brightness_async(led_cdev, transient_data->state);
84 transient_data->restore_state = 85 transient_data->restore_state =
85 (transient_data->state == LED_FULL) ? LED_OFF : LED_FULL; 86 (transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
86 mod_timer(&transient_data->timer, 87 mod_timer(&transient_data->timer,
@@ -203,7 +204,8 @@ static void transient_trig_deactivate(struct led_classdev *led_cdev)
203 204
204 if (led_cdev->activated) { 205 if (led_cdev->activated) {
205 del_timer_sync(&transient_data->timer); 206 del_timer_sync(&transient_data->timer);
206 __led_set_brightness(led_cdev, transient_data->restore_state); 207 led_set_brightness_async(led_cdev,
208 transient_data->restore_state);
207 device_remove_file(led_cdev->dev, &dev_attr_activate); 209 device_remove_file(led_cdev->dev, &dev_attr_activate);
208 device_remove_file(led_cdev->dev, &dev_attr_duration); 210 device_remove_file(led_cdev->dev, &dev_attr_duration);
209 device_remove_file(led_cdev->dev, &dev_attr_state); 211 device_remove_file(led_cdev->dev, &dev_attr_state);