aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-01-10 18:09:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 19:30:49 -0500
commita6d511e5155406cd214d3af3ff9cffc69548b006 (patch)
tree2151e16ad65c9646a47d9591b264e9016efedc33
parentb96a573f4c27529d379922670e8cf5530120d5ca (diff)
leds: add driver for TCA6507 LED controller
TI's TCA6507 is the LED driver in the GTA04 Openmoko motherboard. The driver provides full support for brightness levels and hardware blinking. This driver can drive each of 7 outputs as an LED or a GPIO output, and provides hardware-assist blinking. [akpm@linux-foundation.org: fix __mod_i2c_device_table alias] [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: NeilBrown <neilb@suse.de> Cc: Richard Purdie <rpurdie@rpsys.net> Cc: Randy Dunlap <rdunlap@xenotime.net> Cc: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/leds/Kconfig8
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-tca6507.c779
-rw-r--r--include/linux/leds-tca6507.h34
4 files changed, 822 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 1b75a56ebd08..897a77dfa9d7 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -388,6 +388,14 @@ config LEDS_RENESAS_TPU
388 pin function. The latter to support brightness control. 388 pin function. The latter to support brightness control.
389 Brightness control is supported but hardware blinking is not. 389 Brightness control is supported but hardware blinking is not.
390 390
391config LEDS_TCA6507
392 tristate "LED Support for TCA6507 I2C chip"
393 depends on LEDS_CLASS && I2C
394 help
395 This option enables support for LEDs connected to TC6507
396 LED driver chips accessed via the I2C bus.
397 Driver support brightness control and hardware-assisted blinking.
398
391config LEDS_TRIGGERS 399config LEDS_TRIGGERS
392 bool "LED Trigger support" 400 bool "LED Trigger support"
393 depends on LEDS_CLASS 401 depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e4f6bf568880..5c9dc4b000d5 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -25,6 +25,7 @@ obj-$(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 26obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
27obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o 27obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
28obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
28obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 29obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
29obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 30obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
30obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 31obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
new file mode 100644
index 000000000000..133f89fb7071
--- /dev/null
+++ b/drivers/leds/leds-tca6507.c
@@ -0,0 +1,779 @@
1/*
2 * leds-tca6507
3 *
4 * The TCA6507 is a programmable LED controller that can drive 7
5 * separate lines either by holding them low, or by pulsing them
6 * with modulated width.
7 * The modulation can be varied in a simple pattern to produce a blink or
8 * double-blink.
9 *
10 * This driver can configure each line either as a 'GPIO' which is out-only
11 * (no pull-up) or as an LED with variable brightness and hardware-assisted
12 * blinking.
13 *
14 * Apart from OFF and ON there are three programmable brightness levels which
15 * can be programmed from 0 to 15 and indicate how many 500usec intervals in
16 * each 8msec that the led is 'on'. The levels are named MASTER, BANK0 and
17 * BANK1.
18 *
19 * There are two different blink rates that can be programmed, each with
20 * separate time for rise, on, fall, off and second-off. Thus if 3 or more
21 * different non-trivial rates are required, software must be used for the extra
22 * rates. The two different blink rates must align with the two levels BANK0 and
23 * BANK1.
24 * This driver does not support double-blink so 'second-off' always matches
25 * 'off'.
26 *
27 * Only 16 different times can be programmed in a roughly logarithmic scale from
28 * 64ms to 16320ms. To be precise the possible times are:
29 * 0, 64, 128, 192, 256, 384, 512, 768,
30 * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
31 *
32 * Times that cannot be closely matched with these must be
33 * handled in software. This driver allows 12.5% error in matching.
34 *
35 * This driver does not allow rise/fall rates to be set explicitly. When trying
36 * to match a given 'on' or 'off' period, an appropriate pair of 'change' and
37 * 'hold' times are chosen to get a close match. If the target delay is even,
38 * the 'change' number will be the smaller; if odd, the 'hold' number will be
39 * the smaller.
40
41 * Choosing pairs of delays with 12.5% errors allows us to match delays in the
42 * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720.
43 * 26% of the achievable sums can be matched by multiple pairings. For example
44 * 1536 == 1536+0, 1024+512, or 768+768. This driver will always choose the
45 * pairing with the least maximum - 768+768 in this case. Other pairings are
46 * not available.
47 *
48 * Access to the 3 levels and 2 blinks are on a first-come, first-served basis.
49 * Access can be shared by multiple leds if they have the same level and
50 * either same blink rates, or some don't blink.
51 * When a led changes, it relinquishes access and tries again, so it might
52 * lose access to hardware blink.
53 * If a blink engine cannot be allocated, software blink is used.
54 * If the desired brightness cannot be allocated, the closest available non-zero
55 * brightness is used. As 'full' is always available, the worst case would be
56 * to have two different blink rates at '1', with Max at '2', then other leds
57 * will have to choose between '2' and '16'. Hopefully this is not likely.
58 *
59 * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness
60 * and LEDs using the blink. It can only be reprogrammed when the appropriate
61 * counter is zero. The MASTER level has a single usage count.
62 *
63 * Each Led has programmable 'on' and 'off' time as milliseconds. With each
64 * there is a flag saying if it was explicitly requested or defaulted.
65 * Similarly the banks know if each time was explicit or a default. Defaults
66 * are permitted to be changed freely - they are not recognised when matching.
67 *
68 *
69 * An led-tca6507 device must be provided with platform data. This data
70 * lists for each output: the name, default trigger, and whether the signal
71 * is being used as a GPiO rather than an led. 'struct led_plaform_data'
72 * is used for this. If 'name' is NULL, the output isn't used. If 'flags'
73 * is TCA6507_MAKE_CPIO, the output is a GPO.
74 * The "struct led_platform_data" can be embedded in a
75 * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs,
76 * and a 'setup' callback which is called once the GPiOs are available.
77 *
78 */
79
80#include <linux/module.h>
81#include <linux/slab.h>
82#include <linux/leds.h>
83#include <linux/err.h>
84#include <linux/i2c.h>
85#include <linux/gpio.h>
86#include <linux/workqueue.h>
87#include <linux/leds-tca6507.h>
88
89/* LED select registers determine the source that drives LED outputs */
90#define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */
91#define TCA6507_LS_LED_OFF1 0x1 /* Output HI-Z (off) - not used */
92#define TCA6507_LS_LED_PWM0 0x2 /* Output LOW with Bank0 rate */
93#define TCA6507_LS_LED_PWM1 0x3 /* Output LOW with Bank1 rate */
94#define TCA6507_LS_LED_ON 0x4 /* Output LOW (on) */
95#define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */
96#define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */
97#define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */
98
99enum {
100 BANK0,
101 BANK1,
102 MASTER,
103};
104static int bank_source[3] = {
105 TCA6507_LS_LED_PWM0,
106 TCA6507_LS_LED_PWM1,
107 TCA6507_LS_LED_MIR,
108};
109static int blink_source[2] = {
110 TCA6507_LS_BLINK0,
111 TCA6507_LS_BLINK1,
112};
113
114/* PWM registers */
115#define TCA6507_REG_CNT 11
116
117/*
118 * 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output
119 * owns one bit in each register
120 */
121#define TCA6507_FADE_ON 0x03
122#define TCA6507_FULL_ON 0x04
123#define TCA6507_FADE_OFF 0x05
124#define TCA6507_FIRST_OFF 0x06
125#define TCA6507_SECOND_OFF 0x07
126#define TCA6507_MAX_INTENSITY 0x08
127#define TCA6507_MASTER_INTENSITY 0x09
128#define TCA6507_INITIALIZE 0x0A
129
130#define INIT_CODE 0x8
131
132#define TIMECODES 16
133static int time_codes[TIMECODES] = {
134 0, 64, 128, 192, 256, 384, 512, 768,
135 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
136};
137
138/* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */
139static inline int TO_LEVEL(int brightness)
140{
141 return brightness >> 4;
142}
143
144/* ...and convert back */
145static inline int TO_BRIGHT(int level)
146{
147 if (level)
148 return (level << 4) | 0xf;
149 return 0;
150}
151
152#define NUM_LEDS 7
153struct tca6507_chip {
154 int reg_set; /* One bit per register where
155 * a '1' means the register
156 * should be written */
157 u8 reg_file[TCA6507_REG_CNT];
158 /* Bank 2 is Master Intensity and doesn't use times */
159 struct bank {
160 int level;
161 int ontime, offtime;
162 int on_dflt, off_dflt;
163 int time_use, level_use;
164 } bank[3];
165 struct i2c_client *client;
166 struct work_struct work;
167 spinlock_t lock;
168
169 struct tca6507_led {
170 struct tca6507_chip *chip;
171 struct led_classdev led_cdev;
172 int num;
173 int ontime, offtime;
174 int on_dflt, off_dflt;
175 int bank; /* Bank used, or -1 */
176 int blink; /* Set if hardware-blinking */
177 } leds[NUM_LEDS];
178#ifdef CONFIG_GPIOLIB
179 struct gpio_chip gpio;
180 const char *gpio_name[NUM_LEDS];
181 int gpio_map[NUM_LEDS];
182#endif
183};
184
185static const struct i2c_device_id tca6507_id[] = {
186 { "tca6507" },
187 { }
188};
189MODULE_DEVICE_TABLE(i2c, tca6507_id);
190
191static int choose_times(int msec, int *c1p, int *c2p)
192{
193 /*
194 * Choose two timecodes which add to 'msec' as near as possible.
195 * The first returned is the 'on' or 'off' time. The second is to be
196 * used as a 'fade-on' or 'fade-off' time. If 'msec' is even,
197 * the first will not be smaller than the second. If 'msec' is odd,
198 * the first will not be larger than the second.
199 * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL,
200 * otherwise return the sum that was achieved, plus 1 if the first is
201 * smaller.
202 * If two possibilities are equally good (e.g. 512+0, 256+256), choose
203 * the first pair so there is more change-time visible (i.e. it is
204 * softer).
205 */
206 int c1, c2;
207 int tmax = msec * 9 / 8;
208 int tmin = msec * 7 / 8;
209 int diff = 65536;
210
211 /* We start at '1' to ensure we never even think of choosing a
212 * total time of '0'.
213 */
214 for (c1 = 1; c1 < TIMECODES; c1++) {
215 int t = time_codes[c1];
216 if (t*2 < tmin)
217 continue;
218 if (t > tmax)
219 break;
220 for (c2 = 0; c2 <= c1; c2++) {
221 int tt = t + time_codes[c2];
222 int d;
223 if (tt < tmin)
224 continue;
225 if (tt > tmax)
226 break;
227 /* This works! */
228 d = abs(msec - tt);
229 if (d >= diff)
230 continue;
231 /* Best yet */
232 *c1p = c1;
233 *c2p = c2;
234 diff = d;
235 if (d == 0)
236 return msec;
237 }
238 }
239 if (diff < 65536) {
240 int actual;
241 if (msec & 1) {
242 c1 = *c2p;
243 *c2p = *c1p;
244 *c1p = c1;
245 }
246 actual = time_codes[*c1p] + time_codes[*c2p];
247 if (*c1p < *c2p)
248 return actual + 1;
249 else
250 return actual;
251 }
252 /* No close match */
253 return -EINVAL;
254}
255
256/*
257 * Update the register file with the appropriate 3-bit state for
258 * the given led.
259 */
260static void set_select(struct tca6507_chip *tca, int led, int val)
261{
262 int mask = (1 << led);
263 int bit;
264
265 for (bit = 0; bit < 3; bit++) {
266 int n = tca->reg_file[bit] & ~mask;
267 if (val & (1 << bit))
268 n |= mask;
269 if (tca->reg_file[bit] != n) {
270 tca->reg_file[bit] = n;
271 tca->reg_set |= (1 << bit);
272 }
273 }
274}
275
276/* Update the register file with the appropriate 4-bit code for
277 * one bank or other. This can be used for timers, for levels, or
278 * for initialisation.
279 */
280static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
281{
282 int mask = 0xF;
283 int n;
284 if (bank) {
285 mask <<= 4;
286 new <<= 4;
287 }
288 n = tca->reg_file[reg] & ~mask;
289 n |= new;
290 if (tca->reg_file[reg] != n) {
291 tca->reg_file[reg] = n;
292 tca->reg_set |= 1 << reg;
293 }
294}
295
296/* Update brightness level. */
297static void set_level(struct tca6507_chip *tca, int bank, int level)
298{
299 switch (bank) {
300 case BANK0:
301 case BANK1:
302 set_code(tca, TCA6507_MAX_INTENSITY, bank, level);
303 break;
304 case MASTER:
305 set_code(tca, TCA6507_MASTER_INTENSITY, 0, level);
306 break;
307 }
308 tca->bank[bank].level = level;
309}
310
311/* Record all relevant time code for a given bank */
312static void set_times(struct tca6507_chip *tca, int bank)
313{
314 int c1, c2;
315 int result;
316
317 result = choose_times(tca->bank[bank].ontime, &c1, &c2);
318 dev_dbg(&tca->client->dev,
319 "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
320 c2, time_codes[c2], tca->bank[bank].ontime);
321 set_code(tca, TCA6507_FADE_ON, bank, c2);
322 set_code(tca, TCA6507_FULL_ON, bank, c1);
323 tca->bank[bank].ontime = result;
324
325 result = choose_times(tca->bank[bank].offtime, &c1, &c2);
326 dev_dbg(&tca->client->dev,
327 "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
328 c2, time_codes[c2], tca->bank[bank].offtime);
329 set_code(tca, TCA6507_FADE_OFF, bank, c2);
330 set_code(tca, TCA6507_FIRST_OFF, bank, c1);
331 set_code(tca, TCA6507_SECOND_OFF, bank, c1);
332 tca->bank[bank].offtime = result;
333
334 set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE);
335}
336
337/* Write all needed register of tca6507 */
338
339static void tca6507_work(struct work_struct *work)
340{
341 struct tca6507_chip *tca = container_of(work, struct tca6507_chip,
342 work);
343 struct i2c_client *cl = tca->client;
344 int set;
345 u8 file[TCA6507_REG_CNT];
346 int r;
347
348 spin_lock_irq(&tca->lock);
349 set = tca->reg_set;
350 memcpy(file, tca->reg_file, TCA6507_REG_CNT);
351 tca->reg_set = 0;
352 spin_unlock_irq(&tca->lock);
353
354 for (r = 0; r < TCA6507_REG_CNT; r++)
355 if (set & (1<<r))
356 i2c_smbus_write_byte_data(cl, r, file[r]);
357}
358
359static void led_release(struct tca6507_led *led)
360{
361 /* If led owns any resource, release it. */
362 struct tca6507_chip *tca = led->chip;
363 if (led->bank >= 0) {
364 struct bank *b = tca->bank + led->bank;
365 if (led->blink)
366 b->time_use--;
367 b->level_use--;
368 }
369 led->blink = 0;
370 led->bank = -1;
371}
372
373static int led_prepare(struct tca6507_led *led)
374{
375 /* Assign this led to a bank, configuring that bank if necessary. */
376 int level = TO_LEVEL(led->led_cdev.brightness);
377 struct tca6507_chip *tca = led->chip;
378 int c1, c2;
379 int i;
380 struct bank *b;
381 int need_init = 0;
382
383 led->led_cdev.brightness = TO_BRIGHT(level);
384 if (level == 0) {
385 set_select(tca, led->num, TCA6507_LS_LED_OFF);
386 return 0;
387 }
388
389 if (led->ontime == 0 || led->offtime == 0) {
390 /*
391 * Just set the brightness, choosing first usable bank.
392 * If none perfect, choose best.
393 * Count backwards so we check MASTER bank first
394 * to avoid wasting a timer.
395 */
396 int best = -1;/* full-on */
397 int diff = 15-level;
398
399 if (level == 15) {
400 set_select(tca, led->num, TCA6507_LS_LED_ON);
401 return 0;
402 }
403
404 for (i = MASTER; i >= BANK0; i--) {
405 int d;
406 if (tca->bank[i].level == level ||
407 tca->bank[i].level_use == 0) {
408 best = i;
409 break;
410 }
411 d = abs(level - tca->bank[i].level);
412 if (d < diff) {
413 diff = d;
414 best = i;
415 }
416 }
417 if (best == -1) {
418 /* Best brightness is full-on */
419 set_select(tca, led->num, TCA6507_LS_LED_ON);
420 led->led_cdev.brightness = LED_FULL;
421 return 0;
422 }
423
424 if (!tca->bank[best].level_use)
425 set_level(tca, best, level);
426
427 tca->bank[best].level_use++;
428 led->bank = best;
429 set_select(tca, led->num, bank_source[best]);
430 led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level);
431 return 0;
432 }
433
434 /*
435 * We have on/off time so we need to try to allocate a timing bank.
436 * First check if times are compatible with hardware and give up if
437 * not.
438 */
439 if (choose_times(led->ontime, &c1, &c2) < 0)
440 return -EINVAL;
441 if (choose_times(led->offtime, &c1, &c2) < 0)
442 return -EINVAL;
443
444 for (i = BANK0; i <= BANK1; i++) {
445 if (tca->bank[i].level_use == 0)
446 /* not in use - it is ours! */
447 break;
448 if (tca->bank[i].level != level)
449 /* Incompatible level - skip */
450 /* FIX: if timer matches we maybe should consider
451 * this anyway...
452 */
453 continue;
454
455 if (tca->bank[i].time_use == 0)
456 /* Timer not in use, and level matches - use it */
457 break;
458
459 if (!(tca->bank[i].on_dflt ||
460 led->on_dflt ||
461 tca->bank[i].ontime == led->ontime))
462 /* on time is incompatible */
463 continue;
464
465 if (!(tca->bank[i].off_dflt ||
466 led->off_dflt ||
467 tca->bank[i].offtime == led->offtime))
468 /* off time is incompatible */
469 continue;
470
471 /* looks like a suitable match */
472 break;
473 }
474
475 if (i > BANK1)
476 /* Nothing matches - how sad */
477 return -EINVAL;
478
479 b = &tca->bank[i];
480 if (b->level_use == 0)
481 set_level(tca, i, level);
482 b->level_use++;
483 led->bank = i;
484
485 if (b->on_dflt ||
486 !led->on_dflt ||
487 b->time_use == 0) {
488 b->ontime = led->ontime;
489 b->on_dflt = led->on_dflt;
490 need_init = 1;
491 }
492
493 if (b->off_dflt ||
494 !led->off_dflt ||
495 b->time_use == 0) {
496 b->offtime = led->offtime;
497 b->off_dflt = led->off_dflt;
498 need_init = 1;
499 }
500
501 if (need_init)
502 set_times(tca, i);
503
504 led->ontime = b->ontime;
505 led->offtime = b->offtime;
506
507 b->time_use++;
508 led->blink = 1;
509 led->led_cdev.brightness = TO_BRIGHT(b->level);
510 set_select(tca, led->num, blink_source[i]);
511 return 0;
512}
513
514static int led_assign(struct tca6507_led *led)
515{
516 struct tca6507_chip *tca = led->chip;
517 int err;
518 unsigned long flags;
519
520 spin_lock_irqsave(&tca->lock, flags);
521 led_release(led);
522 err = led_prepare(led);
523 if (err) {
524 /*
525 * Can only fail on timer setup. In that case we need to
526 * re-establish as steady level.
527 */
528 led->ontime = 0;
529 led->offtime = 0;
530 led_prepare(led);
531 }
532 spin_unlock_irqrestore(&tca->lock, flags);
533
534 if (tca->reg_set)
535 schedule_work(&tca->work);
536 return err;
537}
538
539static void tca6507_brightness_set(struct led_classdev *led_cdev,
540 enum led_brightness brightness)
541{
542 struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
543 led_cdev);
544 led->led_cdev.brightness = brightness;
545 led->ontime = 0;
546 led->offtime = 0;
547 led_assign(led);
548}
549
550static int tca6507_blink_set(struct led_classdev *led_cdev,
551 unsigned long *delay_on,
552 unsigned long *delay_off)
553{
554 struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
555 led_cdev);
556
557 if (*delay_on == 0)
558 led->on_dflt = 1;
559 else if (delay_on != &led_cdev->blink_delay_on)
560 led->on_dflt = 0;
561 led->ontime = *delay_on;
562
563 if (*delay_off == 0)
564 led->off_dflt = 1;
565 else if (delay_off != &led_cdev->blink_delay_off)
566 led->off_dflt = 0;
567 led->offtime = *delay_off;
568
569 if (led->ontime == 0)
570 led->ontime = 512;
571 if (led->offtime == 0)
572 led->offtime = 512;
573
574 if (led->led_cdev.brightness == LED_OFF)
575 led->led_cdev.brightness = LED_FULL;
576 if (led_assign(led) < 0) {
577 led->ontime = 0;
578 led->offtime = 0;
579 led->led_cdev.brightness = LED_OFF;
580 return -EINVAL;
581 }
582 *delay_on = led->ontime;
583 *delay_off = led->offtime;
584 return 0;
585}
586
587#ifdef CONFIG_GPIOLIB
588static void tca6507_gpio_set_value(struct gpio_chip *gc,
589 unsigned offset, int val)
590{
591 struct tca6507_chip *tca = container_of(gc, struct tca6507_chip, gpio);
592 unsigned long flags;
593
594 spin_lock_irqsave(&tca->lock, flags);
595 /*
596 * 'OFF' is floating high, and 'ON' is pulled down, so it has the
597 * inverse sense of 'val'.
598 */
599 set_select(tca, tca->gpio_map[offset],
600 val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
601 spin_unlock_irqrestore(&tca->lock, flags);
602 if (tca->reg_set)
603 schedule_work(&tca->work);
604}
605
606static int tca6507_gpio_direction_output(struct gpio_chip *gc,
607 unsigned offset, int val)
608{
609 tca6507_gpio_set_value(gc, offset, val);
610 return 0;
611}
612
613static int tca6507_probe_gpios(struct i2c_client *client,
614 struct tca6507_chip *tca,
615 struct tca6507_platform_data *pdata)
616{
617 int err;
618 int i = 0;
619 int gpios = 0;
620
621 for (i = 0; i < NUM_LEDS; i++)
622 if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) {
623 /* Configure as a gpio */
624 tca->gpio_name[gpios] = pdata->leds.leds[i].name;
625 tca->gpio_map[gpios] = i;
626 gpios++;
627 }
628
629 if (!gpios)
630 return 0;
631
632 tca->gpio.label = "gpio-tca6507";
633 tca->gpio.names = tca->gpio_name;
634 tca->gpio.ngpio = gpios;
635 tca->gpio.base = pdata->gpio_base;
636 tca->gpio.owner = THIS_MODULE;
637 tca->gpio.direction_output = tca6507_gpio_direction_output;
638 tca->gpio.set = tca6507_gpio_set_value;
639 tca->gpio.dev = &client->dev;
640 err = gpiochip_add(&tca->gpio);
641 if (err) {
642 tca->gpio.ngpio = 0;
643 return err;
644 }
645 if (pdata->setup)
646 pdata->setup(tca->gpio.base, tca->gpio.ngpio);
647 return 0;
648}
649
650static void tca6507_remove_gpio(struct tca6507_chip *tca)
651{
652 if (tca->gpio.ngpio) {
653 int err = gpiochip_remove(&tca->gpio);
654 dev_err(&tca->client->dev, "%s failed, %d\n",
655 "gpiochip_remove()", err);
656 }
657}
658#else /* CONFIG_GPIOLIB */
659static int tca6507_probe_gpios(struct i2c_client *client,
660 struct tca6507_chip *tca,
661 struct tca6507_platform_data *pdata)
662{
663 return 0;
664}
665static void tca6507_remove_gpio(struct tca6507_chip *tca)
666{
667}
668#endif /* CONFIG_GPIOLIB */
669
670static int __devinit tca6507_probe(struct i2c_client *client,
671 const struct i2c_device_id *id)
672{
673 struct tca6507_chip *tca;
674 struct i2c_adapter *adapter;
675 struct tca6507_platform_data *pdata;
676 int err;
677 int i = 0;
678
679 adapter = to_i2c_adapter(client->dev.parent);
680 pdata = client->dev.platform_data;
681
682 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
683 return -EIO;
684
685 if (!pdata || pdata->leds.num_leds != NUM_LEDS) {
686 dev_err(&client->dev, "Need %d entries in platform-data list\n",
687 NUM_LEDS);
688 return -ENODEV;
689 }
690 err = -ENOMEM;
691 tca = kzalloc(sizeof(*tca), GFP_KERNEL);
692 if (!tca)
693 goto exit;
694
695 tca->client = client;
696 INIT_WORK(&tca->work, tca6507_work);
697 spin_lock_init(&tca->lock);
698 i2c_set_clientdata(client, tca);
699
700 for (i = 0; i < NUM_LEDS; i++) {
701 struct tca6507_led *l = tca->leds + i;
702
703 l->chip = tca;
704 l->num = i;
705 if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) {
706 l->led_cdev.name = pdata->leds.leds[i].name;
707 l->led_cdev.default_trigger
708 = pdata->leds.leds[i].default_trigger;
709 l->led_cdev.brightness_set = tca6507_brightness_set;
710 l->led_cdev.blink_set = tca6507_blink_set;
711 l->bank = -1;
712 err = led_classdev_register(&client->dev,
713 &l->led_cdev);
714 if (err < 0)
715 goto exit;
716 }
717 }
718 err = tca6507_probe_gpios(client, tca, pdata);
719 if (err)
720 goto exit;
721 /* set all registers to known state - zero */
722 tca->reg_set = 0x7f;
723 schedule_work(&tca->work);
724
725 return 0;
726exit:
727 while (i--)
728 if (tca->leds[i].led_cdev.name)
729 led_classdev_unregister(&tca->leds[i].led_cdev);
730 cancel_work_sync(&tca->work);
731 i2c_set_clientdata(client, NULL);
732 kfree(tca);
733 return err;
734}
735
736static int __devexit tca6507_remove(struct i2c_client *client)
737{
738 int i;
739 struct tca6507_chip *tca = i2c_get_clientdata(client);
740 struct tca6507_led *tca_leds = tca->leds;
741
742 for (i = 0; i < NUM_LEDS; i++) {
743 if (tca_leds[i].led_cdev.name)
744 led_classdev_unregister(&tca_leds[i].led_cdev);
745 }
746 tca6507_remove_gpio(tca);
747 cancel_work_sync(&tca->work);
748 i2c_set_clientdata(client, NULL);
749 kfree(tca);
750
751 return 0;
752}
753
754static struct i2c_driver tca6507_driver = {
755 .driver = {
756 .name = "leds-tca6507",
757 .owner = THIS_MODULE,
758 },
759 .probe = tca6507_probe,
760 .remove = __devexit_p(tca6507_remove),
761 .id_table = tca6507_id,
762};
763
764static int __init tca6507_leds_init(void)
765{
766 return i2c_add_driver(&tca6507_driver);
767}
768
769static void __exit tca6507_leds_exit(void)
770{
771 i2c_del_driver(&tca6507_driver);
772}
773
774module_init(tca6507_leds_init);
775module_exit(tca6507_leds_exit);
776
777MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
778MODULE_DESCRIPTION("TCA6507 LED/GPO driver");
779MODULE_LICENSE("GPL v2");
diff --git a/include/linux/leds-tca6507.h b/include/linux/leds-tca6507.h
new file mode 100644
index 000000000000..dcabf4fa2aef
--- /dev/null
+++ b/include/linux/leds-tca6507.h
@@ -0,0 +1,34 @@
1/*
2 * TCA6507 LED chip driver.
3 *
4 * Copyright (C) 2011 Neil Brown <neil@brown.name>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 */
20
21#ifndef __LINUX_TCA6507_H
22#define __LINUX_TCA6507_H
23#include <linux/leds.h>
24
25struct tca6507_platform_data {
26 struct led_platform_data leds;
27#ifdef CONFIG_GPIOLIB
28 int gpio_base;
29 void (*setup)(unsigned gpio_base, unsigned ngpio);
30#endif
31};
32
33#define TCA6507_MAKE_GPIO 1
34#endif /* __LINUX_TCA6507_H*/