aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/Kconfig20
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/led-class.c105
-rw-r--r--drivers/leds/led-triggers.c2
-rw-r--r--drivers/leds/leds-gpio.c2
-rw-r--r--drivers/leds/leds-lp5521.c821
-rw-r--r--drivers/leds/leds-lp5523.c1065
-rw-r--r--drivers/leds/ledtrig-timer.c124
8 files changed, 2023 insertions, 118 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index cc2a88d5192f..77b8fd20cd90 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -10,7 +10,7 @@ menuconfig NEW_LEDS
10if NEW_LEDS 10if NEW_LEDS
11 11
12config LEDS_CLASS 12config LEDS_CLASS
13 tristate "LED Class Support" 13 bool "LED Class Support"
14 help 14 help
15 This option enables the led sysfs class in /sys/class/leds. You'll 15 This option enables the led sysfs class in /sys/class/leds. You'll
16 need this to do anything useful with LEDs. If unsure, say N. 16 need this to do anything useful with LEDs. If unsure, say N.
@@ -176,6 +176,24 @@ config LEDS_LP3944
176 To compile this driver as a module, choose M here: the 176 To compile this driver as a module, choose M here: the
177 module will be called leds-lp3944. 177 module will be called leds-lp3944.
178 178
179config LEDS_LP5521
180 tristate "LED Support for N.S. LP5521 LED driver chip"
181 depends on LEDS_CLASS && I2C
182 help
183 If you say yes here you get support for the National Semiconductor
184 LP5521 LED driver. It is 3 channel chip with programmable engines.
185 Driver provides direct control via LED class and interface for
186 programming the engines.
187
188config LEDS_LP5523
189 tristate "LED Support for N.S. LP5523 LED driver chip"
190 depends on LEDS_CLASS && I2C
191 help
192 If you say yes here you get support for the National Semiconductor
193 LP5523 LED driver. It is 9 channel chip with programmable engines.
194 Driver provides direct control via LED class and interface for
195 programming the engines.
196
179config LEDS_CLEVO_MAIL 197config LEDS_CLEVO_MAIL
180 tristate "Mail LED on Clevo notebook" 198 tristate "Mail LED on Clevo notebook"
181 depends on X86 && SERIO_I8042 && DMI 199 depends on X86 && SERIO_I8042 && DMI
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 9c96db40ef6d..aae6989ff6b6 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -23,6 +23,8 @@ obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
23obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o 23obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
24obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o 24obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
25obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o 25obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
26obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
27obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
26obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 28obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
27obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 29obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
28obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 30obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 260660076507..211e21f34bd5 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -81,6 +81,79 @@ static struct device_attribute led_class_attrs[] = {
81 __ATTR_NULL, 81 __ATTR_NULL,
82}; 82};
83 83
84static void led_timer_function(unsigned long data)
85{
86 struct led_classdev *led_cdev = (void *)data;
87 unsigned long brightness;
88 unsigned long delay;
89
90 if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
91 led_set_brightness(led_cdev, LED_OFF);
92 return;
93 }
94
95 brightness = led_get_brightness(led_cdev);
96 if (!brightness) {
97 /* Time to switch the LED on. */
98 brightness = led_cdev->blink_brightness;
99 delay = led_cdev->blink_delay_on;
100 } else {
101 /* Store the current brightness value to be able
102 * to restore it when the delay_off period is over.
103 */
104 led_cdev->blink_brightness = brightness;
105 brightness = LED_OFF;
106 delay = led_cdev->blink_delay_off;
107 }
108
109 led_set_brightness(led_cdev, brightness);
110
111 mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
112}
113
114static void led_stop_software_blink(struct led_classdev *led_cdev)
115{
116 /* deactivate previous settings */
117 del_timer_sync(&led_cdev->blink_timer);
118 led_cdev->blink_delay_on = 0;
119 led_cdev->blink_delay_off = 0;
120}
121
122static void led_set_software_blink(struct led_classdev *led_cdev,
123 unsigned long delay_on,
124 unsigned long delay_off)
125{
126 int current_brightness;
127
128 current_brightness = led_get_brightness(led_cdev);
129 if (current_brightness)
130 led_cdev->blink_brightness = current_brightness;
131 if (!led_cdev->blink_brightness)
132 led_cdev->blink_brightness = led_cdev->max_brightness;
133
134 if (delay_on == led_cdev->blink_delay_on &&
135 delay_off == led_cdev->blink_delay_off)
136 return;
137
138 led_stop_software_blink(led_cdev);
139
140 led_cdev->blink_delay_on = delay_on;
141 led_cdev->blink_delay_off = delay_off;
142
143 /* never on - don't blink */
144 if (!delay_on)
145 return;
146
147 /* never off - just set to brightness */
148 if (!delay_off) {
149 led_set_brightness(led_cdev, led_cdev->blink_brightness);
150 return;
151 }
152
153 mod_timer(&led_cdev->blink_timer, jiffies + 1);
154}
155
156
84/** 157/**
85 * led_classdev_suspend - suspend an led_classdev. 158 * led_classdev_suspend - suspend an led_classdev.
86 * @led_cdev: the led_classdev to suspend. 159 * @led_cdev: the led_classdev to suspend.
@@ -148,6 +221,10 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
148 221
149 led_update_brightness(led_cdev); 222 led_update_brightness(led_cdev);
150 223
224 init_timer(&led_cdev->blink_timer);
225 led_cdev->blink_timer.function = led_timer_function;
226 led_cdev->blink_timer.data = (unsigned long)led_cdev;
227
151#ifdef CONFIG_LEDS_TRIGGERS 228#ifdef CONFIG_LEDS_TRIGGERS
152 led_trigger_set_default(led_cdev); 229 led_trigger_set_default(led_cdev);
153#endif 230#endif
@@ -157,7 +234,6 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
157 234
158 return 0; 235 return 0;
159} 236}
160
161EXPORT_SYMBOL_GPL(led_classdev_register); 237EXPORT_SYMBOL_GPL(led_classdev_register);
162 238
163/** 239/**
@@ -175,6 +251,9 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
175 up_write(&led_cdev->trigger_lock); 251 up_write(&led_cdev->trigger_lock);
176#endif 252#endif
177 253
254 /* Stop blinking */
255 led_brightness_set(led_cdev, LED_OFF);
256
178 device_unregister(led_cdev->dev); 257 device_unregister(led_cdev->dev);
179 258
180 down_write(&leds_list_lock); 259 down_write(&leds_list_lock);
@@ -183,6 +262,30 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
183} 262}
184EXPORT_SYMBOL_GPL(led_classdev_unregister); 263EXPORT_SYMBOL_GPL(led_classdev_unregister);
185 264
265void led_blink_set(struct led_classdev *led_cdev,
266 unsigned long *delay_on,
267 unsigned long *delay_off)
268{
269 if (led_cdev->blink_set &&
270 led_cdev->blink_set(led_cdev, delay_on, delay_off))
271 return;
272
273 /* blink with 1 Hz as default if nothing specified */
274 if (!*delay_on && !*delay_off)
275 *delay_on = *delay_off = 500;
276
277 led_set_software_blink(led_cdev, *delay_on, *delay_off);
278}
279EXPORT_SYMBOL(led_blink_set);
280
281void led_brightness_set(struct led_classdev *led_cdev,
282 enum led_brightness brightness)
283{
284 led_stop_software_blink(led_cdev);
285 led_cdev->brightness_set(led_cdev, brightness);
286}
287EXPORT_SYMBOL(led_brightness_set);
288
186static int __init leds_init(void) 289static int __init leds_init(void)
187{ 290{
188 leds_class = class_create(THIS_MODULE, "leds"); 291 leds_class = class_create(THIS_MODULE, "leds");
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index f1c00db88b5e..c41eb6180c9c 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -113,7 +113,7 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
113 if (led_cdev->trigger->deactivate) 113 if (led_cdev->trigger->deactivate)
114 led_cdev->trigger->deactivate(led_cdev); 114 led_cdev->trigger->deactivate(led_cdev);
115 led_cdev->trigger = NULL; 115 led_cdev->trigger = NULL;
116 led_set_brightness(led_cdev, LED_OFF); 116 led_brightness_set(led_cdev, LED_OFF);
117 } 117 }
118 if (trigger) { 118 if (trigger) {
119 write_lock_irqsave(&trigger->leddev_list_lock, flags); 119 write_lock_irqsave(&trigger->leddev_list_lock, flags);
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index ea57e05d08f3..4d9fa38d9ff6 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -316,7 +316,7 @@ static struct of_platform_driver of_gpio_leds_driver = {
316 316
317static int __init gpio_led_init(void) 317static int __init gpio_led_init(void)
318{ 318{
319 int ret; 319 int ret = 0;
320 320
321#ifdef CONFIG_LEDS_GPIO_PLATFORM 321#ifdef CONFIG_LEDS_GPIO_PLATFORM
322 ret = platform_driver_register(&gpio_led_driver); 322 ret = platform_driver_register(&gpio_led_driver);
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
new file mode 100644
index 000000000000..3782f31f06d2
--- /dev/null
+++ b/drivers/leds/leds-lp5521.c
@@ -0,0 +1,821 @@
1/*
2 * LP5521 LED chip driver.
3 *
4 * Copyright (C) 2010 Nokia Corporation
5 *
6 * Contact: Samu Onkalo <samu.p.onkalo@nokia.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 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/i2c.h>
26#include <linux/mutex.h>
27#include <linux/gpio.h>
28#include <linux/interrupt.h>
29#include <linux/delay.h>
30#include <linux/ctype.h>
31#include <linux/spinlock.h>
32#include <linux/wait.h>
33#include <linux/leds.h>
34#include <linux/leds-lp5521.h>
35#include <linux/workqueue.h>
36#include <linux/slab.h>
37
38#define LP5521_PROGRAM_LENGTH 32 /* in bytes */
39
40#define LP5521_MAX_LEDS 3 /* Maximum number of LEDs */
41#define LP5521_MAX_ENGINES 3 /* Maximum number of engines */
42
43#define LP5521_ENG_MASK_BASE 0x30 /* 00110000 */
44#define LP5521_ENG_STATUS_MASK 0x07 /* 00000111 */
45
46#define LP5521_CMD_LOAD 0x15 /* 00010101 */
47#define LP5521_CMD_RUN 0x2a /* 00101010 */
48#define LP5521_CMD_DIRECT 0x3f /* 00111111 */
49#define LP5521_CMD_DISABLED 0x00 /* 00000000 */
50
51/* Registers */
52#define LP5521_REG_ENABLE 0x00
53#define LP5521_REG_OP_MODE 0x01
54#define LP5521_REG_R_PWM 0x02
55#define LP5521_REG_G_PWM 0x03
56#define LP5521_REG_B_PWM 0x04
57#define LP5521_REG_R_CURRENT 0x05
58#define LP5521_REG_G_CURRENT 0x06
59#define LP5521_REG_B_CURRENT 0x07
60#define LP5521_REG_CONFIG 0x08
61#define LP5521_REG_R_CHANNEL_PC 0x09
62#define LP5521_REG_G_CHANNEL_PC 0x0A
63#define LP5521_REG_B_CHANNEL_PC 0x0B
64#define LP5521_REG_STATUS 0x0C
65#define LP5521_REG_RESET 0x0D
66#define LP5521_REG_GPO 0x0E
67#define LP5521_REG_R_PROG_MEM 0x10
68#define LP5521_REG_G_PROG_MEM 0x30
69#define LP5521_REG_B_PROG_MEM 0x50
70
71#define LP5521_PROG_MEM_BASE LP5521_REG_R_PROG_MEM
72#define LP5521_PROG_MEM_SIZE 0x20
73
74/* Base register to set LED current */
75#define LP5521_REG_LED_CURRENT_BASE LP5521_REG_R_CURRENT
76
77/* Base register to set the brightness */
78#define LP5521_REG_LED_PWM_BASE LP5521_REG_R_PWM
79
80/* Bits in ENABLE register */
81#define LP5521_MASTER_ENABLE 0x40 /* Chip master enable */
82#define LP5521_LOGARITHMIC_PWM 0x80 /* Logarithmic PWM adjustment */
83#define LP5521_EXEC_RUN 0x2A
84
85/* Bits in CONFIG register */
86#define LP5521_PWM_HF 0x40 /* PWM: 0 = 256Hz, 1 = 558Hz */
87#define LP5521_PWRSAVE_EN 0x20 /* 1 = Power save mode */
88#define LP5521_CP_MODE_OFF 0 /* Charge pump (CP) off */
89#define LP5521_CP_MODE_BYPASS 8 /* CP forced to bypass mode */
90#define LP5521_CP_MODE_1X5 0x10 /* CP forced to 1.5x mode */
91#define LP5521_CP_MODE_AUTO 0x18 /* Automatic mode selection */
92#define LP5521_R_TO_BATT 4 /* R out: 0 = CP, 1 = Vbat */
93#define LP5521_CLK_SRC_EXT 0 /* Ext-clk source (CLK_32K) */
94#define LP5521_CLK_INT 1 /* Internal clock */
95#define LP5521_CLK_AUTO 2 /* Automatic clock selection */
96
97/* Status */
98#define LP5521_EXT_CLK_USED 0x08
99
100struct lp5521_engine {
101 const struct attribute_group *attributes;
102 int id;
103 u8 mode;
104 u8 prog_page;
105 u8 engine_mask;
106};
107
108struct lp5521_led {
109 int id;
110 u8 chan_nr;
111 u8 led_current;
112 u8 max_current;
113 struct led_classdev cdev;
114 struct work_struct brightness_work;
115 u8 brightness;
116};
117
118struct lp5521_chip {
119 struct lp5521_platform_data *pdata;
120 struct mutex lock; /* Serialize control */
121 struct i2c_client *client;
122 struct lp5521_engine engines[LP5521_MAX_ENGINES];
123 struct lp5521_led leds[LP5521_MAX_LEDS];
124 u8 num_channels;
125 u8 num_leds;
126};
127
128#define cdev_to_led(c) container_of(c, struct lp5521_led, cdev)
129#define engine_to_lp5521(eng) container_of((eng), struct lp5521_chip, \
130 engines[(eng)->id - 1])
131#define led_to_lp5521(led) container_of((led), struct lp5521_chip, \
132 leds[(led)->id])
133
134static void lp5521_led_brightness_work(struct work_struct *work);
135
136static inline int lp5521_write(struct i2c_client *client, u8 reg, u8 value)
137{
138 return i2c_smbus_write_byte_data(client, reg, value);
139}
140
141static int lp5521_read(struct i2c_client *client, u8 reg, u8 *buf)
142{
143 s32 ret;
144
145 ret = i2c_smbus_read_byte_data(client, reg);
146 if (ret < 0)
147 return -EIO;
148
149 *buf = ret;
150 return 0;
151}
152
153static int lp5521_set_engine_mode(struct lp5521_engine *engine, u8 mode)
154{
155 struct lp5521_chip *chip = engine_to_lp5521(engine);
156 struct i2c_client *client = chip->client;
157 int ret;
158 u8 engine_state;
159
160 /* Only transition between RUN and DIRECT mode are handled here */
161 if (mode == LP5521_CMD_LOAD)
162 return 0;
163
164 if (mode == LP5521_CMD_DISABLED)
165 mode = LP5521_CMD_DIRECT;
166
167 ret = lp5521_read(client, LP5521_REG_OP_MODE, &engine_state);
168
169 /* set mode only for this engine */
170 engine_state &= ~(engine->engine_mask);
171 mode &= engine->engine_mask;
172 engine_state |= mode;
173 ret |= lp5521_write(client, LP5521_REG_OP_MODE, engine_state);
174
175 return ret;
176}
177
178static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
179{
180 struct lp5521_chip *chip = engine_to_lp5521(eng);
181 struct i2c_client *client = chip->client;
182 int ret;
183 int addr;
184 u8 mode;
185
186 /* move current engine to direct mode and remember the state */
187 ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT);
188 usleep_range(1000, 10000);
189 ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode);
190
191 /* For loading, all the engines to load mode */
192 lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
193 usleep_range(1000, 10000);
194 lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_LOAD);
195 usleep_range(1000, 10000);
196
197 addr = LP5521_PROG_MEM_BASE + eng->prog_page * LP5521_PROG_MEM_SIZE;
198 i2c_smbus_write_i2c_block_data(client,
199 addr,
200 LP5521_PROG_MEM_SIZE,
201 pattern);
202
203 ret |= lp5521_write(client, LP5521_REG_OP_MODE, mode);
204 return ret;
205}
206
207static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr)
208{
209 return lp5521_write(chip->client,
210 LP5521_REG_LED_CURRENT_BASE + chip->leds[led].chan_nr,
211 curr);
212}
213
214static void lp5521_init_engine(struct lp5521_chip *chip,
215 const struct attribute_group *attr_group)
216{
217 int i;
218 for (i = 0; i < ARRAY_SIZE(chip->engines); i++) {
219 chip->engines[i].id = i + 1;
220 chip->engines[i].engine_mask = LP5521_ENG_MASK_BASE >> (i * 2);
221 chip->engines[i].prog_page = i;
222 chip->engines[i].attributes = &attr_group[i];
223 }
224}
225
226static int lp5521_configure(struct i2c_client *client,
227 const struct attribute_group *attr_group)
228{
229 struct lp5521_chip *chip = i2c_get_clientdata(client);
230 int ret;
231
232 lp5521_init_engine(chip, attr_group);
233
234 lp5521_write(client, LP5521_REG_RESET, 0xff);
235
236 usleep_range(10000, 20000);
237
238 /* Set all PWMs to direct control mode */
239 ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F);
240
241 /* Enable auto-powersave, set charge pump to auto, red to battery */
242 ret |= lp5521_write(client, LP5521_REG_CONFIG,
243 LP5521_PWRSAVE_EN | LP5521_CP_MODE_AUTO | LP5521_R_TO_BATT);
244
245 /* Initialize all channels PWM to zero -> leds off */
246 ret |= lp5521_write(client, LP5521_REG_R_PWM, 0);
247 ret |= lp5521_write(client, LP5521_REG_G_PWM, 0);
248 ret |= lp5521_write(client, LP5521_REG_B_PWM, 0);
249
250 /* Set engines are set to run state when OP_MODE enables engines */
251 ret |= lp5521_write(client, LP5521_REG_ENABLE,
252 LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM |
253 LP5521_EXEC_RUN);
254 /* enable takes 500us */
255 usleep_range(500, 20000);
256
257 return ret;
258}
259
260static int lp5521_run_selftest(struct lp5521_chip *chip, char *buf)
261{
262 int ret;
263 u8 status;
264
265 ret = lp5521_read(chip->client, LP5521_REG_STATUS, &status);
266 if (ret < 0)
267 return ret;
268
269 /* Check that ext clock is really in use if requested */
270 if (chip->pdata && chip->pdata->clock_mode == LP5521_CLOCK_EXT)
271 if ((status & LP5521_EXT_CLK_USED) == 0)
272 return -EIO;
273 return 0;
274}
275
276static void lp5521_set_brightness(struct led_classdev *cdev,
277 enum led_brightness brightness)
278{
279 struct lp5521_led *led = cdev_to_led(cdev);
280 led->brightness = (u8)brightness;
281 schedule_work(&led->brightness_work);
282}
283
284static void lp5521_led_brightness_work(struct work_struct *work)
285{
286 struct lp5521_led *led = container_of(work,
287 struct lp5521_led,
288 brightness_work);
289 struct lp5521_chip *chip = led_to_lp5521(led);
290 struct i2c_client *client = chip->client;
291
292 mutex_lock(&chip->lock);
293 lp5521_write(client, LP5521_REG_LED_PWM_BASE + led->chan_nr,
294 led->brightness);
295 mutex_unlock(&chip->lock);
296}
297
298/* Detect the chip by setting its ENABLE register and reading it back. */
299static int lp5521_detect(struct i2c_client *client)
300{
301 int ret;
302 u8 buf;
303
304 ret = lp5521_write(client, LP5521_REG_ENABLE,
305 LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM);
306 if (ret)
307 return ret;
308 usleep_range(1000, 10000);
309 ret = lp5521_read(client, LP5521_REG_ENABLE, &buf);
310 if (ret)
311 return ret;
312 if (buf != (LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM))
313 return -ENODEV;
314
315 return 0;
316}
317
318/* Set engine mode and create appropriate sysfs attributes, if required. */
319static int lp5521_set_mode(struct lp5521_engine *engine, u8 mode)
320{
321 struct lp5521_chip *chip = engine_to_lp5521(engine);
322 struct i2c_client *client = chip->client;
323 struct device *dev = &client->dev;
324 int ret = 0;
325
326 /* if in that mode already do nothing, except for run */
327 if (mode == engine->mode && mode != LP5521_CMD_RUN)
328 return 0;
329
330 if (mode == LP5521_CMD_RUN) {
331 ret = lp5521_set_engine_mode(engine, LP5521_CMD_RUN);
332 } else if (mode == LP5521_CMD_LOAD) {
333 lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED);
334 lp5521_set_engine_mode(engine, LP5521_CMD_LOAD);
335
336 ret = sysfs_create_group(&dev->kobj, engine->attributes);
337 if (ret)
338 return ret;
339 } else if (mode == LP5521_CMD_DISABLED) {
340 lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED);
341 }
342
343 /* remove load attribute from sysfs if not in load mode */
344 if (engine->mode == LP5521_CMD_LOAD && mode != LP5521_CMD_LOAD)
345 sysfs_remove_group(&dev->kobj, engine->attributes);
346
347 engine->mode = mode;
348
349 return ret;
350}
351
352static int lp5521_do_store_load(struct lp5521_engine *engine,
353 const char *buf, size_t len)
354{
355 struct lp5521_chip *chip = engine_to_lp5521(engine);
356 struct i2c_client *client = chip->client;
357 int ret, nrchars, offset = 0, i = 0;
358 char c[3];
359 unsigned cmd;
360 u8 pattern[LP5521_PROGRAM_LENGTH] = {0};
361
362 while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) {
363 /* separate sscanfs because length is working only for %s */
364 ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
365 ret = sscanf(c, "%2x", &cmd);
366 if (ret != 1)
367 goto fail;
368 pattern[i] = (u8)cmd;
369
370 offset += nrchars;
371 i++;
372 }
373
374 /* Each instruction is 16bit long. Check that length is even */
375 if (i % 2)
376 goto fail;
377
378 mutex_lock(&chip->lock);
379 ret = lp5521_load_program(engine, pattern);
380 mutex_unlock(&chip->lock);
381
382 if (ret) {
383 dev_err(&client->dev, "failed loading pattern\n");
384 return ret;
385 }
386
387 return len;
388fail:
389 dev_err(&client->dev, "wrong pattern format\n");
390 return -EINVAL;
391}
392
393static ssize_t store_engine_load(struct device *dev,
394 struct device_attribute *attr,
395 const char *buf, size_t len, int nr)
396{
397 struct i2c_client *client = to_i2c_client(dev);
398 struct lp5521_chip *chip = i2c_get_clientdata(client);
399 return lp5521_do_store_load(&chip->engines[nr - 1], buf, len);
400}
401
402#define store_load(nr) \
403static ssize_t store_engine##nr##_load(struct device *dev, \
404 struct device_attribute *attr, \
405 const char *buf, size_t len) \
406{ \
407 return store_engine_load(dev, attr, buf, len, nr); \
408}
409store_load(1)
410store_load(2)
411store_load(3)
412
413static ssize_t show_engine_mode(struct device *dev,
414 struct device_attribute *attr,
415 char *buf, int nr)
416{
417 struct i2c_client *client = to_i2c_client(dev);
418 struct lp5521_chip *chip = i2c_get_clientdata(client);
419 switch (chip->engines[nr - 1].mode) {
420 case LP5521_CMD_RUN:
421 return sprintf(buf, "run\n");
422 case LP5521_CMD_LOAD:
423 return sprintf(buf, "load\n");
424 case LP5521_CMD_DISABLED:
425 return sprintf(buf, "disabled\n");
426 default:
427 return sprintf(buf, "disabled\n");
428 }
429}
430
431#define show_mode(nr) \
432static ssize_t show_engine##nr##_mode(struct device *dev, \
433 struct device_attribute *attr, \
434 char *buf) \
435{ \
436 return show_engine_mode(dev, attr, buf, nr); \
437}
438show_mode(1)
439show_mode(2)
440show_mode(3)
441
442static ssize_t store_engine_mode(struct device *dev,
443 struct device_attribute *attr,
444 const char *buf, size_t len, int nr)
445{
446 struct i2c_client *client = to_i2c_client(dev);
447 struct lp5521_chip *chip = i2c_get_clientdata(client);
448 struct lp5521_engine *engine = &chip->engines[nr - 1];
449 mutex_lock(&chip->lock);
450
451 if (!strncmp(buf, "run", 3))
452 lp5521_set_mode(engine, LP5521_CMD_RUN);
453 else if (!strncmp(buf, "load", 4))
454 lp5521_set_mode(engine, LP5521_CMD_LOAD);
455 else if (!strncmp(buf, "disabled", 8))
456 lp5521_set_mode(engine, LP5521_CMD_DISABLED);
457
458 mutex_unlock(&chip->lock);
459 return len;
460}
461
462#define store_mode(nr) \
463static ssize_t store_engine##nr##_mode(struct device *dev, \
464 struct device_attribute *attr, \
465 const char *buf, size_t len) \
466{ \
467 return store_engine_mode(dev, attr, buf, len, nr); \
468}
469store_mode(1)
470store_mode(2)
471store_mode(3)
472
473static ssize_t show_max_current(struct device *dev,
474 struct device_attribute *attr,
475 char *buf)
476{
477 struct led_classdev *led_cdev = dev_get_drvdata(dev);
478 struct lp5521_led *led = cdev_to_led(led_cdev);
479
480 return sprintf(buf, "%d\n", led->max_current);
481}
482
483static ssize_t show_current(struct device *dev,
484 struct device_attribute *attr,
485 char *buf)
486{
487 struct led_classdev *led_cdev = dev_get_drvdata(dev);
488 struct lp5521_led *led = cdev_to_led(led_cdev);
489
490 return sprintf(buf, "%d\n", led->led_current);
491}
492
493static ssize_t store_current(struct device *dev,
494 struct device_attribute *attr,
495 const char *buf, size_t len)
496{
497 struct led_classdev *led_cdev = dev_get_drvdata(dev);
498 struct lp5521_led *led = cdev_to_led(led_cdev);
499 struct lp5521_chip *chip = led_to_lp5521(led);
500 ssize_t ret;
501 unsigned long curr;
502
503 if (strict_strtoul(buf, 0, &curr))
504 return -EINVAL;
505
506 if (curr > led->max_current)
507 return -EINVAL;
508
509 mutex_lock(&chip->lock);
510 ret = lp5521_set_led_current(chip, led->id, curr);
511 mutex_unlock(&chip->lock);
512
513 if (ret < 0)
514 return ret;
515
516 led->led_current = (u8)curr;
517
518 return len;
519}
520
521static ssize_t lp5521_selftest(struct device *dev,
522 struct device_attribute *attr,
523 char *buf)
524{
525 struct i2c_client *client = to_i2c_client(dev);
526 struct lp5521_chip *chip = i2c_get_clientdata(client);
527 int ret;
528
529 mutex_lock(&chip->lock);
530 ret = lp5521_run_selftest(chip, buf);
531 mutex_unlock(&chip->lock);
532 return sprintf(buf, "%s\n", ret ? "FAIL" : "OK");
533}
534
535/* led class device attributes */
536static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
537static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
538
539static struct attribute *lp5521_led_attributes[] = {
540 &dev_attr_led_current.attr,
541 &dev_attr_max_current.attr,
542 NULL,
543};
544
545static struct attribute_group lp5521_led_attribute_group = {
546 .attrs = lp5521_led_attributes
547};
548
549/* device attributes */
550static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
551 show_engine1_mode, store_engine1_mode);
552static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
553 show_engine2_mode, store_engine2_mode);
554static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
555 show_engine3_mode, store_engine3_mode);
556static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
557static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
558static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
559static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL);
560
561static struct attribute *lp5521_attributes[] = {
562 &dev_attr_engine1_mode.attr,
563 &dev_attr_engine2_mode.attr,
564 &dev_attr_engine3_mode.attr,
565 &dev_attr_selftest.attr,
566 NULL
567};
568
569static struct attribute *lp5521_engine1_attributes[] = {
570 &dev_attr_engine1_load.attr,
571 NULL
572};
573
574static struct attribute *lp5521_engine2_attributes[] = {
575 &dev_attr_engine2_load.attr,
576 NULL
577};
578
579static struct attribute *lp5521_engine3_attributes[] = {
580 &dev_attr_engine3_load.attr,
581 NULL
582};
583
584static const struct attribute_group lp5521_group = {
585 .attrs = lp5521_attributes,
586};
587
588static const struct attribute_group lp5521_engine_group[] = {
589 {.attrs = lp5521_engine1_attributes },
590 {.attrs = lp5521_engine2_attributes },
591 {.attrs = lp5521_engine3_attributes },
592};
593
594static int lp5521_register_sysfs(struct i2c_client *client)
595{
596 struct device *dev = &client->dev;
597 return sysfs_create_group(&dev->kobj, &lp5521_group);
598}
599
600static void lp5521_unregister_sysfs(struct i2c_client *client)
601{
602 struct lp5521_chip *chip = i2c_get_clientdata(client);
603 struct device *dev = &client->dev;
604 int i;
605
606 sysfs_remove_group(&dev->kobj, &lp5521_group);
607
608 for (i = 0; i < ARRAY_SIZE(chip->engines); i++) {
609 if (chip->engines[i].mode == LP5521_CMD_LOAD)
610 sysfs_remove_group(&dev->kobj,
611 chip->engines[i].attributes);
612 }
613
614 for (i = 0; i < chip->num_leds; i++)
615 sysfs_remove_group(&chip->leds[i].cdev.dev->kobj,
616 &lp5521_led_attribute_group);
617}
618
619static int __init lp5521_init_led(struct lp5521_led *led,
620 struct i2c_client *client,
621 int chan, struct lp5521_platform_data *pdata)
622{
623 struct device *dev = &client->dev;
624 char name[32];
625 int res;
626
627 if (chan >= LP5521_MAX_LEDS)
628 return -EINVAL;
629
630 if (pdata->led_config[chan].led_current == 0)
631 return 0;
632
633 led->led_current = pdata->led_config[chan].led_current;
634 led->max_current = pdata->led_config[chan].max_current;
635 led->chan_nr = pdata->led_config[chan].chan_nr;
636
637 if (led->chan_nr >= LP5521_MAX_LEDS) {
638 dev_err(dev, "Use channel numbers between 0 and %d\n",
639 LP5521_MAX_LEDS - 1);
640 return -EINVAL;
641 }
642
643 snprintf(name, sizeof(name), "%s:channel%d", client->name, chan);
644 led->cdev.brightness_set = lp5521_set_brightness;
645 led->cdev.name = name;
646 res = led_classdev_register(dev, &led->cdev);
647 if (res < 0) {
648 dev_err(dev, "couldn't register led on channel %d\n", chan);
649 return res;
650 }
651
652 res = sysfs_create_group(&led->cdev.dev->kobj,
653 &lp5521_led_attribute_group);
654 if (res < 0) {
655 dev_err(dev, "couldn't register current attribute\n");
656 led_classdev_unregister(&led->cdev);
657 return res;
658 }
659 return 0;
660}
661
662static int lp5521_probe(struct i2c_client *client,
663 const struct i2c_device_id *id)
664{
665 struct lp5521_chip *chip;
666 struct lp5521_platform_data *pdata;
667 int ret, i, led;
668
669 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
670 if (!chip)
671 return -ENOMEM;
672
673 i2c_set_clientdata(client, chip);
674 chip->client = client;
675
676 pdata = client->dev.platform_data;
677
678 if (!pdata) {
679 dev_err(&client->dev, "no platform data\n");
680 ret = -EINVAL;
681 goto fail1;
682 }
683
684 mutex_init(&chip->lock);
685
686 chip->pdata = pdata;
687
688 if (pdata->setup_resources) {
689 ret = pdata->setup_resources();
690 if (ret < 0)
691 goto fail1;
692 }
693
694 if (pdata->enable) {
695 pdata->enable(0);
696 usleep_range(1000, 10000);
697 pdata->enable(1);
698 usleep_range(1000, 10000); /* Spec says min 500us */
699 }
700
701 ret = lp5521_detect(client);
702
703 if (ret) {
704 dev_err(&client->dev, "Chip not found\n");
705 goto fail2;
706 }
707
708 dev_info(&client->dev, "%s programmable led chip found\n", id->name);
709
710 ret = lp5521_configure(client, lp5521_engine_group);
711 if (ret < 0) {
712 dev_err(&client->dev, "error configuring chip\n");
713 goto fail2;
714 }
715
716 /* Initialize leds */
717 chip->num_channels = pdata->num_channels;
718 chip->num_leds = 0;
719 led = 0;
720 for (i = 0; i < pdata->num_channels; i++) {
721 /* Do not initialize channels that are not connected */
722 if (pdata->led_config[i].led_current == 0)
723 continue;
724
725 ret = lp5521_init_led(&chip->leds[led], client, i, pdata);
726 if (ret) {
727 dev_err(&client->dev, "error initializing leds\n");
728 goto fail3;
729 }
730 chip->num_leds++;
731
732 chip->leds[led].id = led;
733 /* Set initial LED current */
734 lp5521_set_led_current(chip, led,
735 chip->leds[led].led_current);
736
737 INIT_WORK(&(chip->leds[led].brightness_work),
738 lp5521_led_brightness_work);
739
740 led++;
741 }
742
743 ret = lp5521_register_sysfs(client);
744 if (ret) {
745 dev_err(&client->dev, "registering sysfs failed\n");
746 goto fail3;
747 }
748 return ret;
749fail3:
750 for (i = 0; i < chip->num_leds; i++) {
751 led_classdev_unregister(&chip->leds[i].cdev);
752 cancel_work_sync(&chip->leds[i].brightness_work);
753 }
754fail2:
755 if (pdata->enable)
756 pdata->enable(0);
757 if (pdata->release_resources)
758 pdata->release_resources();
759fail1:
760 kfree(chip);
761 return ret;
762}
763
764static int lp5521_remove(struct i2c_client *client)
765{
766 struct lp5521_chip *chip = i2c_get_clientdata(client);
767 int i;
768
769 lp5521_unregister_sysfs(client);
770
771 for (i = 0; i < chip->num_leds; i++) {
772 led_classdev_unregister(&chip->leds[i].cdev);
773 cancel_work_sync(&chip->leds[i].brightness_work);
774 }
775
776 if (chip->pdata->enable)
777 chip->pdata->enable(0);
778 if (chip->pdata->release_resources)
779 chip->pdata->release_resources();
780 kfree(chip);
781 return 0;
782}
783
784static const struct i2c_device_id lp5521_id[] = {
785 { "lp5521", 0 }, /* Three channel chip */
786 { }
787};
788MODULE_DEVICE_TABLE(i2c, lp5521_id);
789
790static struct i2c_driver lp5521_driver = {
791 .driver = {
792 .name = "lp5521",
793 },
794 .probe = lp5521_probe,
795 .remove = lp5521_remove,
796 .id_table = lp5521_id,
797};
798
799static int __init lp5521_init(void)
800{
801 int ret;
802
803 ret = i2c_add_driver(&lp5521_driver);
804
805 if (ret < 0)
806 printk(KERN_ALERT "Adding lp5521 driver failed\n");
807
808 return ret;
809}
810
811static void __exit lp5521_exit(void)
812{
813 i2c_del_driver(&lp5521_driver);
814}
815
816module_init(lp5521_init);
817module_exit(lp5521_exit);
818
819MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo");
820MODULE_DESCRIPTION("LP5521 LED engine");
821MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
new file mode 100644
index 000000000000..1e11fcc08b28
--- /dev/null
+++ b/drivers/leds/leds-lp5523.c
@@ -0,0 +1,1065 @@
1/*
2 * lp5523.c - LP5523 LED Driver
3 *
4 * Copyright (C) 2010 Nokia Corporation
5 *
6 * Contact: Samu Onkalo <samu.p.onkalo@nokia.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 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/i2c.h>
26#include <linux/mutex.h>
27#include <linux/gpio.h>
28#include <linux/interrupt.h>
29#include <linux/delay.h>
30#include <linux/ctype.h>
31#include <linux/spinlock.h>
32#include <linux/wait.h>
33#include <linux/leds.h>
34#include <linux/leds-lp5523.h>
35#include <linux/workqueue.h>
36#include <linux/slab.h>
37
38#define LP5523_REG_ENABLE 0x00
39#define LP5523_REG_OP_MODE 0x01
40#define LP5523_REG_RATIOMETRIC_MSB 0x02
41#define LP5523_REG_RATIOMETRIC_LSB 0x03
42#define LP5523_REG_ENABLE_LEDS_MSB 0x04
43#define LP5523_REG_ENABLE_LEDS_LSB 0x05
44#define LP5523_REG_LED_CNTRL_BASE 0x06
45#define LP5523_REG_LED_PWM_BASE 0x16
46#define LP5523_REG_LED_CURRENT_BASE 0x26
47#define LP5523_REG_CONFIG 0x36
48#define LP5523_REG_CHANNEL1_PC 0x37
49#define LP5523_REG_CHANNEL2_PC 0x38
50#define LP5523_REG_CHANNEL3_PC 0x39
51#define LP5523_REG_STATUS 0x3a
52#define LP5523_REG_GPO 0x3b
53#define LP5523_REG_VARIABLE 0x3c
54#define LP5523_REG_RESET 0x3d
55#define LP5523_REG_TEMP_CTRL 0x3e
56#define LP5523_REG_TEMP_READ 0x3f
57#define LP5523_REG_TEMP_WRITE 0x40
58#define LP5523_REG_LED_TEST_CTRL 0x41
59#define LP5523_REG_LED_TEST_ADC 0x42
60#define LP5523_REG_ENG1_VARIABLE 0x45
61#define LP5523_REG_ENG2_VARIABLE 0x46
62#define LP5523_REG_ENG3_VARIABLE 0x47
63#define LP5523_REG_MASTER_FADER1 0x48
64#define LP5523_REG_MASTER_FADER2 0x49
65#define LP5523_REG_MASTER_FADER3 0x4a
66#define LP5523_REG_CH1_PROG_START 0x4c
67#define LP5523_REG_CH2_PROG_START 0x4d
68#define LP5523_REG_CH3_PROG_START 0x4e
69#define LP5523_REG_PROG_PAGE_SEL 0x4f
70#define LP5523_REG_PROG_MEM 0x50
71
72#define LP5523_CMD_LOAD 0x15 /* 00010101 */
73#define LP5523_CMD_RUN 0x2a /* 00101010 */
74#define LP5523_CMD_DISABLED 0x00 /* 00000000 */
75
76#define LP5523_ENABLE 0x40
77#define LP5523_AUTO_INC 0x40
78#define LP5523_PWR_SAVE 0x20
79#define LP5523_PWM_PWR_SAVE 0x04
80#define LP5523_CP_1 0x08
81#define LP5523_CP_1_5 0x10
82#define LP5523_CP_AUTO 0x18
83#define LP5523_INT_CLK 0x01
84#define LP5523_AUTO_CLK 0x02
85#define LP5523_EN_LEDTEST 0x80
86#define LP5523_LEDTEST_DONE 0x80
87
88#define LP5523_DEFAULT_CURRENT 50 /* microAmps */
89#define LP5523_PROGRAM_LENGTH 32 /* in bytes */
90#define LP5523_PROGRAM_PAGES 6
91#define LP5523_ADC_SHORTCIRC_LIM 80
92
93#define LP5523_LEDS 9
94#define LP5523_ENGINES 3
95
96#define LP5523_ENG_MASK_BASE 0x30 /* 00110000 */
97
98#define LP5523_ENG_STATUS_MASK 0x07 /* 00000111 */
99
100#define LP5523_IRQ_FLAGS IRQF_TRIGGER_FALLING
101
102#define LP5523_EXT_CLK_USED 0x08
103
104#define LED_ACTIVE(mux, led) (!!(mux & (0x0001 << led)))
105#define SHIFT_MASK(id) (((id) - 1) * 2)
106
107struct lp5523_engine {
108 const struct attribute_group *attributes;
109 int id;
110 u8 mode;
111 u8 prog_page;
112 u8 mux_page;
113 u16 led_mux;
114 u8 engine_mask;
115};
116
117struct lp5523_led {
118 int id;
119 u8 chan_nr;
120 u8 led_current;
121 u8 max_current;
122 struct led_classdev cdev;
123 struct work_struct brightness_work;
124 u8 brightness;
125};
126
127struct lp5523_chip {
128 struct mutex lock; /* Serialize control */
129 struct i2c_client *client;
130 struct lp5523_engine engines[LP5523_ENGINES];
131 struct lp5523_led leds[LP5523_LEDS];
132 struct lp5523_platform_data *pdata;
133 u8 num_channels;
134 u8 num_leds;
135};
136
137#define cdev_to_led(c) container_of(c, struct lp5523_led, cdev)
138
139static struct lp5523_chip *engine_to_lp5523(struct lp5523_engine *engine)
140{
141 return container_of(engine, struct lp5523_chip,
142 engines[engine->id - 1]);
143}
144
145static struct lp5523_chip *led_to_lp5523(struct lp5523_led *led)
146{
147 return container_of(led, struct lp5523_chip,
148 leds[led->id]);
149}
150
151static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode);
152static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode);
153static int lp5523_load_program(struct lp5523_engine *engine, u8 *pattern);
154
155static void lp5523_led_brightness_work(struct work_struct *work);
156
157static int lp5523_write(struct i2c_client *client, u8 reg, u8 value)
158{
159 return i2c_smbus_write_byte_data(client, reg, value);
160}
161
162static int lp5523_read(struct i2c_client *client, u8 reg, u8 *buf)
163{
164 s32 ret = i2c_smbus_read_byte_data(client, reg);
165
166 if (ret < 0)
167 return -EIO;
168
169 *buf = ret;
170 return 0;
171}
172
173static int lp5523_detect(struct i2c_client *client)
174{
175 int ret;
176 u8 buf;
177
178 ret = lp5523_write(client, LP5523_REG_ENABLE, 0x40);
179 if (ret)
180 return ret;
181 ret = lp5523_read(client, LP5523_REG_ENABLE, &buf);
182 if (ret)
183 return ret;
184 if (buf == 0x40)
185 return 0;
186 else
187 return -ENODEV;
188}
189
190static int lp5523_configure(struct i2c_client *client)
191{
192 struct lp5523_chip *chip = i2c_get_clientdata(client);
193 int ret = 0;
194 u8 status;
195
196 /* one pattern per engine setting led mux start and stop addresses */
197 u8 pattern[][LP5523_PROGRAM_LENGTH] = {
198 { 0x9c, 0x30, 0x9c, 0xb0, 0x9d, 0x80, 0xd8, 0x00, 0},
199 { 0x9c, 0x40, 0x9c, 0xc0, 0x9d, 0x80, 0xd8, 0x00, 0},
200 { 0x9c, 0x50, 0x9c, 0xd0, 0x9d, 0x80, 0xd8, 0x00, 0},
201 };
202
203 lp5523_write(client, LP5523_REG_RESET, 0xff);
204
205 usleep_range(10000, 100000);
206
207 ret |= lp5523_write(client, LP5523_REG_ENABLE, LP5523_ENABLE);
208 /* Chip startup time after reset is 500 us */
209 usleep_range(1000, 10000);
210
211 ret |= lp5523_write(client, LP5523_REG_CONFIG,
212 LP5523_AUTO_INC | LP5523_PWR_SAVE |
213 LP5523_CP_AUTO | LP5523_AUTO_CLK |
214 LP5523_PWM_PWR_SAVE);
215
216 /* turn on all leds */
217 ret |= lp5523_write(client, LP5523_REG_ENABLE_LEDS_MSB, 0x01);
218 ret |= lp5523_write(client, LP5523_REG_ENABLE_LEDS_LSB, 0xff);
219
220 /* hardcode 32 bytes of memory for each engine from program memory */
221 ret |= lp5523_write(client, LP5523_REG_CH1_PROG_START, 0x00);
222 ret |= lp5523_write(client, LP5523_REG_CH2_PROG_START, 0x10);
223 ret |= lp5523_write(client, LP5523_REG_CH3_PROG_START, 0x20);
224
225 /* write led mux address space for each channel */
226 ret |= lp5523_load_program(&chip->engines[0], pattern[0]);
227 ret |= lp5523_load_program(&chip->engines[1], pattern[1]);
228 ret |= lp5523_load_program(&chip->engines[2], pattern[2]);
229
230 if (ret) {
231 dev_err(&client->dev, "could not load mux programs\n");
232 return -1;
233 }
234
235 /* set all engines exec state and mode to run 00101010 */
236 ret |= lp5523_write(client, LP5523_REG_ENABLE,
237 (LP5523_CMD_RUN | LP5523_ENABLE));
238
239 ret |= lp5523_write(client, LP5523_REG_OP_MODE, LP5523_CMD_RUN);
240
241 if (ret) {
242 dev_err(&client->dev, "could not start mux programs\n");
243 return -1;
244 }
245
246 /* Wait 3ms and check the engine status */
247 usleep_range(3000, 20000);
248 lp5523_read(client, LP5523_REG_STATUS, &status);
249 status &= LP5523_ENG_STATUS_MASK;
250
251 if (status == LP5523_ENG_STATUS_MASK) {
252 dev_dbg(&client->dev, "all engines configured\n");
253 } else {
254 dev_info(&client->dev, "status == %x\n", status);
255 dev_err(&client->dev, "cound not configure LED engine\n");
256 return -1;
257 }
258
259 dev_info(&client->dev, "disabling engines\n");
260
261 ret |= lp5523_write(client, LP5523_REG_OP_MODE, LP5523_CMD_DISABLED);
262
263 return ret;
264}
265
266static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode)
267{
268 struct lp5523_chip *chip = engine_to_lp5523(engine);
269 struct i2c_client *client = chip->client;
270 int ret;
271 u8 engine_state;
272
273 ret = lp5523_read(client, LP5523_REG_OP_MODE, &engine_state);
274 if (ret)
275 goto fail;
276
277 engine_state &= ~(engine->engine_mask);
278
279 /* set mode only for this engine */
280 mode &= engine->engine_mask;
281
282 engine_state |= mode;
283
284 ret |= lp5523_write(client, LP5523_REG_OP_MODE, engine_state);
285fail:
286 return ret;
287}
288
289static int lp5523_load_mux(struct lp5523_engine *engine, u16 mux)
290{
291 struct lp5523_chip *chip = engine_to_lp5523(engine);
292 struct i2c_client *client = chip->client;
293 int ret = 0;
294
295 ret |= lp5523_set_engine_mode(engine, LP5523_CMD_LOAD);
296
297 ret |= lp5523_write(client, LP5523_REG_PROG_PAGE_SEL, engine->mux_page);
298 ret |= lp5523_write(client, LP5523_REG_PROG_MEM,
299 (u8)(mux >> 8));
300 ret |= lp5523_write(client, LP5523_REG_PROG_MEM + 1, (u8)(mux));
301 engine->led_mux = mux;
302
303 return ret;
304}
305
306static int lp5523_load_program(struct lp5523_engine *engine, u8 *pattern)
307{
308 struct lp5523_chip *chip = engine_to_lp5523(engine);
309 struct i2c_client *client = chip->client;
310
311 int ret = 0;
312
313 ret |= lp5523_set_engine_mode(engine, LP5523_CMD_LOAD);
314
315 ret |= lp5523_write(client, LP5523_REG_PROG_PAGE_SEL,
316 engine->prog_page);
317 ret |= i2c_smbus_write_i2c_block_data(client, LP5523_REG_PROG_MEM,
318 LP5523_PROGRAM_LENGTH, pattern);
319
320 return ret;
321}
322
323static int lp5523_run_program(struct lp5523_engine *engine)
324{
325 struct lp5523_chip *chip = engine_to_lp5523(engine);
326 struct i2c_client *client = chip->client;
327 int ret;
328
329 ret = lp5523_write(client, LP5523_REG_ENABLE,
330 LP5523_CMD_RUN | LP5523_ENABLE);
331 if (ret)
332 goto fail;
333
334 ret = lp5523_set_engine_mode(engine, LP5523_CMD_RUN);
335fail:
336 return ret;
337}
338
339static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len)
340{
341 int i;
342 u16 tmp_mux = 0;
343 len = len < LP5523_LEDS ? len : LP5523_LEDS;
344 for (i = 0; i < len; i++) {
345 switch (buf[i]) {
346 case '1':
347 tmp_mux |= (1 << i);
348 break;
349 case '0':
350 break;
351 case '\n':
352 i = len;
353 break;
354 default:
355 return -1;
356 }
357 }
358 *mux = tmp_mux;
359
360 return 0;
361}
362
363static void lp5523_mux_to_array(u16 led_mux, char *array)
364{
365 int i, pos = 0;
366 for (i = 0; i < LP5523_LEDS; i++)
367 pos += sprintf(array + pos, "%x", LED_ACTIVE(led_mux, i));
368
369 array[pos] = '\0';
370}
371
372/*--------------------------------------------------------------*/
373/* Sysfs interface */
374/*--------------------------------------------------------------*/
375
376static ssize_t show_engine_leds(struct device *dev,
377 struct device_attribute *attr,
378 char *buf, int nr)
379{
380 struct i2c_client *client = to_i2c_client(dev);
381 struct lp5523_chip *chip = i2c_get_clientdata(client);
382 char mux[LP5523_LEDS + 1];
383
384 lp5523_mux_to_array(chip->engines[nr - 1].led_mux, mux);
385
386 return sprintf(buf, "%s\n", mux);
387}
388
389#define show_leds(nr) \
390static ssize_t show_engine##nr##_leds(struct device *dev, \
391 struct device_attribute *attr, \
392 char *buf) \
393{ \
394 return show_engine_leds(dev, attr, buf, nr); \
395}
396show_leds(1)
397show_leds(2)
398show_leds(3)
399
400static ssize_t store_engine_leds(struct device *dev,
401 struct device_attribute *attr,
402 const char *buf, size_t len, int nr)
403{
404 struct i2c_client *client = to_i2c_client(dev);
405 struct lp5523_chip *chip = i2c_get_clientdata(client);
406 u16 mux = 0;
407
408 if (lp5523_mux_parse(buf, &mux, len))
409 return -EINVAL;
410
411 if (lp5523_load_mux(&chip->engines[nr - 1], mux))
412 return -EINVAL;
413
414 return len;
415}
416
417#define store_leds(nr) \
418static ssize_t store_engine##nr##_leds(struct device *dev, \
419 struct device_attribute *attr, \
420 const char *buf, size_t len) \
421{ \
422 return store_engine_leds(dev, attr, buf, len, nr); \
423}
424store_leds(1)
425store_leds(2)
426store_leds(3)
427
428static ssize_t lp5523_selftest(struct device *dev,
429 struct device_attribute *attr,
430 char *buf)
431{
432 struct i2c_client *client = to_i2c_client(dev);
433 struct lp5523_chip *chip = i2c_get_clientdata(client);
434 int i, ret, pos = 0;
435 int led = 0;
436 u8 status, adc, vdd;
437
438 mutex_lock(&chip->lock);
439
440 ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
441 if (ret < 0)
442 goto fail;
443
444 /* Check that ext clock is really in use if requested */
445 if ((chip->pdata) && (chip->pdata->clock_mode == LP5523_CLOCK_EXT))
446 if ((status & LP5523_EXT_CLK_USED) == 0)
447 goto fail;
448
449 /* Measure VDD (i.e. VBAT) first (channel 16 corresponds to VDD) */
450 lp5523_write(chip->client, LP5523_REG_LED_TEST_CTRL,
451 LP5523_EN_LEDTEST | 16);
452 usleep_range(3000, 10000);
453 ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
454 if (!(status & LP5523_LEDTEST_DONE))
455 usleep_range(3000, 10000);
456
457 ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &vdd);
458 vdd--; /* There may be some fluctuation in measurement */
459
460 for (i = 0; i < LP5523_LEDS; i++) {
461 /* Skip non-existing channels */
462 if (chip->pdata->led_config[i].led_current == 0)
463 continue;
464
465 /* Set default current */
466 lp5523_write(chip->client,
467 LP5523_REG_LED_CURRENT_BASE + i,
468 chip->pdata->led_config[i].led_current);
469
470 lp5523_write(chip->client, LP5523_REG_LED_PWM_BASE + i, 0xff);
471 /* let current stabilize 2ms before measurements start */
472 usleep_range(2000, 10000);
473 lp5523_write(chip->client,
474 LP5523_REG_LED_TEST_CTRL,
475 LP5523_EN_LEDTEST | i);
476 /* ledtest takes 2.7ms */
477 usleep_range(3000, 10000);
478 ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
479 if (!(status & LP5523_LEDTEST_DONE))
480 usleep_range(3000, 10000);
481 ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &adc);
482
483 if (adc >= vdd || adc < LP5523_ADC_SHORTCIRC_LIM)
484 pos += sprintf(buf + pos, "LED %d FAIL\n", i);
485
486 lp5523_write(chip->client, LP5523_REG_LED_PWM_BASE + i, 0x00);
487
488 /* Restore current */
489 lp5523_write(chip->client,
490 LP5523_REG_LED_CURRENT_BASE + i,
491 chip->leds[led].led_current);
492 led++;
493 }
494 if (pos == 0)
495 pos = sprintf(buf, "OK\n");
496 goto release_lock;
497fail:
498 pos = sprintf(buf, "FAIL\n");
499
500release_lock:
501 mutex_unlock(&chip->lock);
502
503 return pos;
504}
505
506static void lp5523_set_brightness(struct led_classdev *cdev,
507 enum led_brightness brightness)
508{
509 struct lp5523_led *led = cdev_to_led(cdev);
510
511 led->brightness = (u8)brightness;
512
513 schedule_work(&led->brightness_work);
514}
515
516static void lp5523_led_brightness_work(struct work_struct *work)
517{
518 struct lp5523_led *led = container_of(work,
519 struct lp5523_led,
520 brightness_work);
521 struct lp5523_chip *chip = led_to_lp5523(led);
522 struct i2c_client *client = chip->client;
523
524 mutex_lock(&chip->lock);
525
526 lp5523_write(client, LP5523_REG_LED_PWM_BASE + led->chan_nr,
527 led->brightness);
528
529 mutex_unlock(&chip->lock);
530}
531
532static int lp5523_do_store_load(struct lp5523_engine *engine,
533 const char *buf, size_t len)
534{
535 struct lp5523_chip *chip = engine_to_lp5523(engine);
536 struct i2c_client *client = chip->client;
537 int ret, nrchars, offset = 0, i = 0;
538 char c[3];
539 unsigned cmd;
540 u8 pattern[LP5523_PROGRAM_LENGTH] = {0};
541
542 while ((offset < len - 1) && (i < LP5523_PROGRAM_LENGTH)) {
543 /* separate sscanfs because length is working only for %s */
544 ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
545 ret = sscanf(c, "%2x", &cmd);
546 if (ret != 1)
547 goto fail;
548 pattern[i] = (u8)cmd;
549
550 offset += nrchars;
551 i++;
552 }
553
554 /* Each instruction is 16bit long. Check that length is even */
555 if (i % 2)
556 goto fail;
557
558 mutex_lock(&chip->lock);
559
560 ret = lp5523_load_program(engine, pattern);
561 mutex_unlock(&chip->lock);
562
563 if (ret) {
564 dev_err(&client->dev, "failed loading pattern\n");
565 return ret;
566 }
567
568 return len;
569fail:
570 dev_err(&client->dev, "wrong pattern format\n");
571 return -EINVAL;
572}
573
574static ssize_t store_engine_load(struct device *dev,
575 struct device_attribute *attr,
576 const char *buf, size_t len, int nr)
577{
578 struct i2c_client *client = to_i2c_client(dev);
579 struct lp5523_chip *chip = i2c_get_clientdata(client);
580 return lp5523_do_store_load(&chip->engines[nr - 1], buf, len);
581}
582
583#define store_load(nr) \
584static ssize_t store_engine##nr##_load(struct device *dev, \
585 struct device_attribute *attr, \
586 const char *buf, size_t len) \
587{ \
588 return store_engine_load(dev, attr, buf, len, nr); \
589}
590store_load(1)
591store_load(2)
592store_load(3)
593
594static ssize_t show_engine_mode(struct device *dev,
595 struct device_attribute *attr,
596 char *buf, int nr)
597{
598 struct i2c_client *client = to_i2c_client(dev);
599 struct lp5523_chip *chip = i2c_get_clientdata(client);
600 switch (chip->engines[nr - 1].mode) {
601 case LP5523_CMD_RUN:
602 return sprintf(buf, "run\n");
603 case LP5523_CMD_LOAD:
604 return sprintf(buf, "load\n");
605 case LP5523_CMD_DISABLED:
606 return sprintf(buf, "disabled\n");
607 default:
608 return sprintf(buf, "disabled\n");
609 }
610}
611
612#define show_mode(nr) \
613static ssize_t show_engine##nr##_mode(struct device *dev, \
614 struct device_attribute *attr, \
615 char *buf) \
616{ \
617 return show_engine_mode(dev, attr, buf, nr); \
618}
619show_mode(1)
620show_mode(2)
621show_mode(3)
622
623static ssize_t store_engine_mode(struct device *dev,
624 struct device_attribute *attr,
625 const char *buf, size_t len, int nr)
626{
627 struct i2c_client *client = to_i2c_client(dev);
628 struct lp5523_chip *chip = i2c_get_clientdata(client);
629 struct lp5523_engine *engine = &chip->engines[nr - 1];
630 mutex_lock(&chip->lock);
631
632 if (!strncmp(buf, "run", 3))
633 lp5523_set_mode(engine, LP5523_CMD_RUN);
634 else if (!strncmp(buf, "load", 4))
635 lp5523_set_mode(engine, LP5523_CMD_LOAD);
636 else if (!strncmp(buf, "disabled", 8))
637 lp5523_set_mode(engine, LP5523_CMD_DISABLED);
638
639 mutex_unlock(&chip->lock);
640 return len;
641}
642
643#define store_mode(nr) \
644static ssize_t store_engine##nr##_mode(struct device *dev, \
645 struct device_attribute *attr, \
646 const char *buf, size_t len) \
647{ \
648 return store_engine_mode(dev, attr, buf, len, nr); \
649}
650store_mode(1)
651store_mode(2)
652store_mode(3)
653
654static ssize_t show_max_current(struct device *dev,
655 struct device_attribute *attr,
656 char *buf)
657{
658 struct led_classdev *led_cdev = dev_get_drvdata(dev);
659 struct lp5523_led *led = cdev_to_led(led_cdev);
660
661 return sprintf(buf, "%d\n", led->max_current);
662}
663
664static ssize_t show_current(struct device *dev,
665 struct device_attribute *attr,
666 char *buf)
667{
668 struct led_classdev *led_cdev = dev_get_drvdata(dev);
669 struct lp5523_led *led = cdev_to_led(led_cdev);
670
671 return sprintf(buf, "%d\n", led->led_current);
672}
673
674static ssize_t store_current(struct device *dev,
675 struct device_attribute *attr,
676 const char *buf, size_t len)
677{
678 struct led_classdev *led_cdev = dev_get_drvdata(dev);
679 struct lp5523_led *led = cdev_to_led(led_cdev);
680 struct lp5523_chip *chip = led_to_lp5523(led);
681 ssize_t ret;
682 unsigned long curr;
683
684 if (strict_strtoul(buf, 0, &curr))
685 return -EINVAL;
686
687 if (curr > led->max_current)
688 return -EINVAL;
689
690 mutex_lock(&chip->lock);
691 ret = lp5523_write(chip->client,
692 LP5523_REG_LED_CURRENT_BASE + led->chan_nr,
693 (u8)curr);
694 mutex_unlock(&chip->lock);
695
696 if (ret < 0)
697 return ret;
698
699 led->led_current = (u8)curr;
700
701 return len;
702}
703
704/* led class device attributes */
705static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
706static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
707
708static struct attribute *lp5523_led_attributes[] = {
709 &dev_attr_led_current.attr,
710 &dev_attr_max_current.attr,
711 NULL,
712};
713
714static struct attribute_group lp5523_led_attribute_group = {
715 .attrs = lp5523_led_attributes
716};
717
718/* device attributes */
719static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
720 show_engine1_mode, store_engine1_mode);
721static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
722 show_engine2_mode, store_engine2_mode);
723static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
724 show_engine3_mode, store_engine3_mode);
725static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUGO,
726 show_engine1_leds, store_engine1_leds);
727static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUGO,
728 show_engine2_leds, store_engine2_leds);
729static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUGO,
730 show_engine3_leds, store_engine3_leds);
731static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
732static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
733static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
734static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL);
735
736static struct attribute *lp5523_attributes[] = {
737 &dev_attr_engine1_mode.attr,
738 &dev_attr_engine2_mode.attr,
739 &dev_attr_engine3_mode.attr,
740 &dev_attr_selftest.attr,
741 NULL
742};
743
744static struct attribute *lp5523_engine1_attributes[] = {
745 &dev_attr_engine1_load.attr,
746 &dev_attr_engine1_leds.attr,
747 NULL
748};
749
750static struct attribute *lp5523_engine2_attributes[] = {
751 &dev_attr_engine2_load.attr,
752 &dev_attr_engine2_leds.attr,
753 NULL
754};
755
756static struct attribute *lp5523_engine3_attributes[] = {
757 &dev_attr_engine3_load.attr,
758 &dev_attr_engine3_leds.attr,
759 NULL
760};
761
762static const struct attribute_group lp5523_group = {
763 .attrs = lp5523_attributes,
764};
765
766static const struct attribute_group lp5523_engine_group[] = {
767 {.attrs = lp5523_engine1_attributes },
768 {.attrs = lp5523_engine2_attributes },
769 {.attrs = lp5523_engine3_attributes },
770};
771
772static int lp5523_register_sysfs(struct i2c_client *client)
773{
774 struct device *dev = &client->dev;
775 int ret;
776
777 ret = sysfs_create_group(&dev->kobj, &lp5523_group);
778 if (ret < 0)
779 return ret;
780
781 return 0;
782}
783
784static void lp5523_unregister_sysfs(struct i2c_client *client)
785{
786 struct lp5523_chip *chip = i2c_get_clientdata(client);
787 struct device *dev = &client->dev;
788 int i;
789
790 sysfs_remove_group(&dev->kobj, &lp5523_group);
791
792 for (i = 0; i < ARRAY_SIZE(chip->engines); i++)
793 if (chip->engines[i].mode == LP5523_CMD_LOAD)
794 sysfs_remove_group(&dev->kobj, &lp5523_engine_group[i]);
795
796 for (i = 0; i < chip->num_leds; i++)
797 sysfs_remove_group(&chip->leds[i].cdev.dev->kobj,
798 &lp5523_led_attribute_group);
799}
800
801/*--------------------------------------------------------------*/
802/* Set chip operating mode */
803/*--------------------------------------------------------------*/
804static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode)
805{
806 /* engine to chip */
807 struct lp5523_chip *chip = engine_to_lp5523(engine);
808 struct i2c_client *client = chip->client;
809 struct device *dev = &client->dev;
810 int ret = 0;
811
812 /* if in that mode already do nothing, except for run */
813 if (mode == engine->mode && mode != LP5523_CMD_RUN)
814 return 0;
815
816 if (mode == LP5523_CMD_RUN) {
817 ret = lp5523_run_program(engine);
818 } else if (mode == LP5523_CMD_LOAD) {
819 lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
820 lp5523_set_engine_mode(engine, LP5523_CMD_LOAD);
821
822 ret = sysfs_create_group(&dev->kobj, engine->attributes);
823 if (ret)
824 return ret;
825 } else if (mode == LP5523_CMD_DISABLED) {
826 lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
827 }
828
829 /* remove load attribute from sysfs if not in load mode */
830 if (engine->mode == LP5523_CMD_LOAD && mode != LP5523_CMD_LOAD)
831 sysfs_remove_group(&dev->kobj, engine->attributes);
832
833 engine->mode = mode;
834
835 return ret;
836}
837
838/*--------------------------------------------------------------*/
839/* Probe, Attach, Remove */
840/*--------------------------------------------------------------*/
841static int __init lp5523_init_engine(struct lp5523_engine *engine, int id)
842{
843 if (id < 1 || id > LP5523_ENGINES)
844 return -1;
845 engine->id = id;
846 engine->engine_mask = LP5523_ENG_MASK_BASE >> SHIFT_MASK(id);
847 engine->prog_page = id - 1;
848 engine->mux_page = id + 2;
849 engine->attributes = &lp5523_engine_group[id - 1];
850
851 return 0;
852}
853
854static int __init lp5523_init_led(struct lp5523_led *led, struct device *dev,
855 int chan, struct lp5523_platform_data *pdata)
856{
857 char name[32];
858 int res;
859
860 if (chan >= LP5523_LEDS)
861 return -EINVAL;
862
863 if (pdata->led_config[chan].led_current) {
864 led->led_current = pdata->led_config[chan].led_current;
865 led->max_current = pdata->led_config[chan].max_current;
866 led->chan_nr = pdata->led_config[chan].chan_nr;
867
868 if (led->chan_nr >= LP5523_LEDS) {
869 dev_err(dev, "Use channel numbers between 0 and %d\n",
870 LP5523_LEDS - 1);
871 return -EINVAL;
872 }
873
874 snprintf(name, 32, "lp5523:channel%d", chan);
875
876 led->cdev.name = name;
877 led->cdev.brightness_set = lp5523_set_brightness;
878 res = led_classdev_register(dev, &led->cdev);
879 if (res < 0) {
880 dev_err(dev, "couldn't register led on channel %d\n",
881 chan);
882 return res;
883 }
884 res = sysfs_create_group(&led->cdev.dev->kobj,
885 &lp5523_led_attribute_group);
886 if (res < 0) {
887 dev_err(dev, "couldn't register current attribute\n");
888 led_classdev_unregister(&led->cdev);
889 return res;
890 }
891 } else {
892 led->led_current = 0;
893 }
894 return 0;
895}
896
897static struct i2c_driver lp5523_driver;
898
899static int lp5523_probe(struct i2c_client *client,
900 const struct i2c_device_id *id)
901{
902 struct lp5523_chip *chip;
903 struct lp5523_platform_data *pdata;
904 int ret, i, led;
905
906 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
907 if (!chip)
908 return -ENOMEM;
909
910 i2c_set_clientdata(client, chip);
911 chip->client = client;
912
913 pdata = client->dev.platform_data;
914
915 if (!pdata) {
916 dev_err(&client->dev, "no platform data\n");
917 ret = -EINVAL;
918 goto fail1;
919 }
920
921 mutex_init(&chip->lock);
922
923 chip->pdata = pdata;
924
925 if (pdata->setup_resources) {
926 ret = pdata->setup_resources();
927 if (ret < 0)
928 goto fail1;
929 }
930
931 if (pdata->enable) {
932 pdata->enable(0);
933 usleep_range(1000, 10000);
934 pdata->enable(1);
935 usleep_range(1000, 10000); /* Spec says min 500us */
936 }
937
938 ret = lp5523_detect(client);
939 if (ret)
940 goto fail2;
941
942 dev_info(&client->dev, "LP5523 Programmable led chip found\n");
943
944 /* Initialize engines */
945 for (i = 0; i < ARRAY_SIZE(chip->engines); i++) {
946 ret = lp5523_init_engine(&chip->engines[i], i + 1);
947 if (ret) {
948 dev_err(&client->dev, "error initializing engine\n");
949 goto fail2;
950 }
951 }
952 ret = lp5523_configure(client);
953 if (ret < 0) {
954 dev_err(&client->dev, "error configuring chip\n");
955 goto fail2;
956 }
957
958 /* Initialize leds */
959 chip->num_channels = pdata->num_channels;
960 chip->num_leds = 0;
961 led = 0;
962 for (i = 0; i < pdata->num_channels; i++) {
963 /* Do not initialize channels that are not connected */
964 if (pdata->led_config[i].led_current == 0)
965 continue;
966
967 ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata);
968 if (ret) {
969 dev_err(&client->dev, "error initializing leds\n");
970 goto fail3;
971 }
972 chip->num_leds++;
973
974 chip->leds[led].id = led;
975 /* Set LED current */
976 lp5523_write(client,
977 LP5523_REG_LED_CURRENT_BASE + chip->leds[led].chan_nr,
978 chip->leds[led].led_current);
979
980 INIT_WORK(&(chip->leds[led].brightness_work),
981 lp5523_led_brightness_work);
982
983 led++;
984 }
985
986 ret = lp5523_register_sysfs(client);
987 if (ret) {
988 dev_err(&client->dev, "registering sysfs failed\n");
989 goto fail3;
990 }
991 return ret;
992fail3:
993 for (i = 0; i < chip->num_leds; i++) {
994 led_classdev_unregister(&chip->leds[i].cdev);
995 cancel_work_sync(&chip->leds[i].brightness_work);
996 }
997fail2:
998 if (pdata->enable)
999 pdata->enable(0);
1000 if (pdata->release_resources)
1001 pdata->release_resources();
1002fail1:
1003 kfree(chip);
1004 return ret;
1005}
1006
1007static int lp5523_remove(struct i2c_client *client)
1008{
1009 struct lp5523_chip *chip = i2c_get_clientdata(client);
1010 int i;
1011
1012 lp5523_unregister_sysfs(client);
1013
1014 for (i = 0; i < chip->num_leds; i++) {
1015 led_classdev_unregister(&chip->leds[i].cdev);
1016 cancel_work_sync(&chip->leds[i].brightness_work);
1017 }
1018
1019 if (chip->pdata->enable)
1020 chip->pdata->enable(0);
1021 if (chip->pdata->release_resources)
1022 chip->pdata->release_resources();
1023 kfree(chip);
1024 return 0;
1025}
1026
1027static const struct i2c_device_id lp5523_id[] = {
1028 { "lp5523", 0 },
1029 { }
1030};
1031
1032MODULE_DEVICE_TABLE(i2c, lp5523_id);
1033
1034static struct i2c_driver lp5523_driver = {
1035 .driver = {
1036 .name = "lp5523",
1037 },
1038 .probe = lp5523_probe,
1039 .remove = lp5523_remove,
1040 .id_table = lp5523_id,
1041};
1042
1043static int __init lp5523_init(void)
1044{
1045 int ret;
1046
1047 ret = i2c_add_driver(&lp5523_driver);
1048
1049 if (ret < 0)
1050 printk(KERN_ALERT "Adding lp5523 driver failed\n");
1051
1052 return ret;
1053}
1054
1055static void __exit lp5523_exit(void)
1056{
1057 i2c_del_driver(&lp5523_driver);
1058}
1059
1060module_init(lp5523_init);
1061module_exit(lp5523_exit);
1062
1063MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>");
1064MODULE_DESCRIPTION("LP5523 LED engine");
1065MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
index 82b77bd482ff..b09bcbeade9c 100644
--- a/drivers/leds/ledtrig-timer.c
+++ b/drivers/leds/ledtrig-timer.c
@@ -12,73 +12,25 @@
12 */ 12 */
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/jiffies.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/list.h>
19#include <linux/spinlock.h>
20#include <linux/device.h> 17#include <linux/device.h>
21#include <linux/sysdev.h>
22#include <linux/timer.h>
23#include <linux/ctype.h> 18#include <linux/ctype.h>
24#include <linux/leds.h> 19#include <linux/leds.h>
25#include <linux/slab.h>
26#include "leds.h" 20#include "leds.h"
27 21
28struct timer_trig_data {
29 int brightness_on; /* LED brightness during "on" period.
30 * (LED_OFF < brightness_on <= LED_FULL)
31 */
32 unsigned long delay_on; /* milliseconds on */
33 unsigned long delay_off; /* milliseconds off */
34 struct timer_list timer;
35};
36
37static void led_timer_function(unsigned long data)
38{
39 struct led_classdev *led_cdev = (struct led_classdev *) data;
40 struct timer_trig_data *timer_data = led_cdev->trigger_data;
41 unsigned long brightness;
42 unsigned long delay;
43
44 if (!timer_data->delay_on || !timer_data->delay_off) {
45 led_set_brightness(led_cdev, LED_OFF);
46 return;
47 }
48
49 brightness = led_get_brightness(led_cdev);
50 if (!brightness) {
51 /* Time to switch the LED on. */
52 brightness = timer_data->brightness_on;
53 delay = timer_data->delay_on;
54 } else {
55 /* Store the current brightness value to be able
56 * to restore it when the delay_off period is over.
57 */
58 timer_data->brightness_on = brightness;
59 brightness = LED_OFF;
60 delay = timer_data->delay_off;
61 }
62
63 led_set_brightness(led_cdev, brightness);
64
65 mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
66}
67
68static ssize_t led_delay_on_show(struct device *dev, 22static ssize_t led_delay_on_show(struct device *dev,
69 struct device_attribute *attr, char *buf) 23 struct device_attribute *attr, char *buf)
70{ 24{
71 struct led_classdev *led_cdev = dev_get_drvdata(dev); 25 struct led_classdev *led_cdev = dev_get_drvdata(dev);
72 struct timer_trig_data *timer_data = led_cdev->trigger_data;
73 26
74 return sprintf(buf, "%lu\n", timer_data->delay_on); 27 return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
75} 28}
76 29
77static ssize_t led_delay_on_store(struct device *dev, 30static ssize_t led_delay_on_store(struct device *dev,
78 struct device_attribute *attr, const char *buf, size_t size) 31 struct device_attribute *attr, const char *buf, size_t size)
79{ 32{
80 struct led_classdev *led_cdev = dev_get_drvdata(dev); 33 struct led_classdev *led_cdev = dev_get_drvdata(dev);
81 struct timer_trig_data *timer_data = led_cdev->trigger_data;
82 int ret = -EINVAL; 34 int ret = -EINVAL;
83 char *after; 35 char *after;
84 unsigned long state = simple_strtoul(buf, &after, 10); 36 unsigned long state = simple_strtoul(buf, &after, 10);
@@ -88,21 +40,7 @@ static ssize_t led_delay_on_store(struct device *dev,
88 count++; 40 count++;
89 41
90 if (count == size) { 42 if (count == size) {
91 if (timer_data->delay_on != state) { 43 led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
92 /* the new value differs from the previous */
93 timer_data->delay_on = state;
94
95 /* deactivate previous settings */
96 del_timer_sync(&timer_data->timer);
97
98 /* try to activate hardware acceleration, if any */
99 if (!led_cdev->blink_set ||
100 led_cdev->blink_set(led_cdev,
101 &timer_data->delay_on, &timer_data->delay_off)) {
102 /* no hardware acceleration, blink via timer */
103 mod_timer(&timer_data->timer, jiffies + 1);
104 }
105 }
106 ret = count; 44 ret = count;
107 } 45 }
108 46
@@ -113,16 +51,14 @@ static ssize_t led_delay_off_show(struct device *dev,
113 struct device_attribute *attr, char *buf) 51 struct device_attribute *attr, char *buf)
114{ 52{
115 struct led_classdev *led_cdev = dev_get_drvdata(dev); 53 struct led_classdev *led_cdev = dev_get_drvdata(dev);
116 struct timer_trig_data *timer_data = led_cdev->trigger_data;
117 54
118 return sprintf(buf, "%lu\n", timer_data->delay_off); 55 return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
119} 56}
120 57
121static ssize_t led_delay_off_store(struct device *dev, 58static ssize_t led_delay_off_store(struct device *dev,
122 struct device_attribute *attr, const char *buf, size_t size) 59 struct device_attribute *attr, const char *buf, size_t size)
123{ 60{
124 struct led_classdev *led_cdev = dev_get_drvdata(dev); 61 struct led_classdev *led_cdev = dev_get_drvdata(dev);
125 struct timer_trig_data *timer_data = led_cdev->trigger_data;
126 int ret = -EINVAL; 62 int ret = -EINVAL;
127 char *after; 63 char *after;
128 unsigned long state = simple_strtoul(buf, &after, 10); 64 unsigned long state = simple_strtoul(buf, &after, 10);
@@ -132,21 +68,7 @@ static ssize_t led_delay_off_store(struct device *dev,
132 count++; 68 count++;
133 69
134 if (count == size) { 70 if (count == size) {
135 if (timer_data->delay_off != state) { 71 led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
136 /* the new value differs from the previous */
137 timer_data->delay_off = state;
138
139 /* deactivate previous settings */
140 del_timer_sync(&timer_data->timer);
141
142 /* try to activate hardware acceleration, if any */
143 if (!led_cdev->blink_set ||
144 led_cdev->blink_set(led_cdev,
145 &timer_data->delay_on, &timer_data->delay_off)) {
146 /* no hardware acceleration, blink via timer */
147 mod_timer(&timer_data->timer, jiffies + 1);
148 }
149 }
150 ret = count; 72 ret = count;
151 } 73 }
152 74
@@ -158,60 +80,34 @@ static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
158 80
159static void timer_trig_activate(struct led_classdev *led_cdev) 81static void timer_trig_activate(struct led_classdev *led_cdev)
160{ 82{
161 struct timer_trig_data *timer_data;
162 int rc; 83 int rc;
163 84
164 timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL); 85 led_cdev->trigger_data = NULL;
165 if (!timer_data)
166 return;
167
168 timer_data->brightness_on = led_get_brightness(led_cdev);
169 if (timer_data->brightness_on == LED_OFF)
170 timer_data->brightness_on = led_cdev->max_brightness;
171 led_cdev->trigger_data = timer_data;
172
173 init_timer(&timer_data->timer);
174 timer_data->timer.function = led_timer_function;
175 timer_data->timer.data = (unsigned long) led_cdev;
176 86
177 rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); 87 rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
178 if (rc) 88 if (rc)
179 goto err_out; 89 return;
180 rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); 90 rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
181 if (rc) 91 if (rc)
182 goto err_out_delayon; 92 goto err_out_delayon;
183 93
184 /* If there is hardware support for blinking, start one 94 led_cdev->trigger_data = (void *)1;
185 * user friendly blink rate chosen by the driver.
186 */
187 if (led_cdev->blink_set)
188 led_cdev->blink_set(led_cdev,
189 &timer_data->delay_on, &timer_data->delay_off);
190 95
191 return; 96 return;
192 97
193err_out_delayon: 98err_out_delayon:
194 device_remove_file(led_cdev->dev, &dev_attr_delay_on); 99 device_remove_file(led_cdev->dev, &dev_attr_delay_on);
195err_out:
196 led_cdev->trigger_data = NULL;
197 kfree(timer_data);
198} 100}
199 101
200static void timer_trig_deactivate(struct led_classdev *led_cdev) 102static void timer_trig_deactivate(struct led_classdev *led_cdev)
201{ 103{
202 struct timer_trig_data *timer_data = led_cdev->trigger_data; 104 if (led_cdev->trigger_data) {
203 unsigned long on = 0, off = 0;
204
205 if (timer_data) {
206 device_remove_file(led_cdev->dev, &dev_attr_delay_on); 105 device_remove_file(led_cdev->dev, &dev_attr_delay_on);
207 device_remove_file(led_cdev->dev, &dev_attr_delay_off); 106 device_remove_file(led_cdev->dev, &dev_attr_delay_off);
208 del_timer_sync(&timer_data->timer);
209 kfree(timer_data);
210 } 107 }
211 108
212 /* If there is hardware support for blinking, stop it */ 109 /* Stop blinking */
213 if (led_cdev->blink_set) 110 led_brightness_set(led_cdev, LED_OFF);
214 led_cdev->blink_set(led_cdev, &on, &off);
215} 111}
216 112
217static struct led_trigger timer_led_trigger = { 113static struct led_trigger timer_led_trigger = {