2 * lp5521.c - LP5521 LED Driver
4 * Copyright (C) 2007 Nokia Corporation
6 * Written by Mathias Nyman <mathias.nyman@nokia.com>
7 * Updated by Felipe Balbi <felipe.balbi@nokia.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/i2c.h>
27 #include <linux/leds.h>
28 #include <linux/mutex.h>
29 #include <linux/workqueue.h>
30 #include <linux/i2c/lp5521.h>
32 #define LP5521_DRIVER_NAME "lp5521"
34 #define LP5521_REG_R_PWM 0x02
35 #define LP5521_REG_B_PWM 0x04
36 #define LP5521_REG_ENABLE 0x00
37 #define LP5521_REG_OP_MODE 0x01
38 #define LP5521_REG_G_PWM 0x03
39 #define LP5521_REG_R_CNTRL 0x05
40 #define LP5521_REG_G_CNTRL 0x06
41 #define LP5521_REG_B_CNTRL 0x07
42 #define LP5521_REG_MISC 0x08
43 #define LP5521_REG_R_CHANNEL_PC 0x09
44 #define LP5521_REG_G_CHANNEL_PC 0x0a
45 #define LP5521_REG_B_CHANNEL_PC 0x0b
46 #define LP5521_REG_STATUS 0x0c
47 #define LP5521_REG_RESET 0x0d
48 #define LP5521_REG_GPO 0x0e
49 #define LP5521_REG_R_PROG_MEM 0x10
50 #define LP5521_REG_G_PROG_MEM 0x30
51 #define LP5521_REG_B_PROG_MEM 0x50
53 #define LP5521_CURRENT_1m5 0x0f
54 #define LP5521_CURRENT_3m1 0x1f
55 #define LP5521_CURRENT_4m7 0x2f
56 #define LP5521_CURRENT_6m3 0x3f
57 #define LP5521_CURRENT_7m9 0x4f
58 #define LP5521_CURRENT_9m5 0x5f
59 #define LP5521_CURRENT_11m1 0x6f
60 #define LP5521_CURRENT_12m7 0x7f
61 #define LP5521_CURRENT_14m3 0x8f
62 #define LP5521_CURRENT_15m9 0x9f
63 #define LP5521_CURRENT_17m5 0xaf
64 #define LP5521_CURRENT_19m1 0xbf
65 #define LP5521_CURRENT_20m7 0xcf
66 #define LP5521_CURRENT_22m3 0xdf
67 #define LP5521_CURRENT_23m9 0xef
68 #define LP5521_CURRENT_25m5 0xff
70 #define LP5521_PROGRAM_LENGTH 32 /* in bytes */
75 struct i2c_client *client;
77 struct work_struct red_work;
78 struct work_struct green_work;
79 struct work_struct blue_work;
81 struct led_classdev ledr;
82 struct led_classdev ledg;
83 struct led_classdev ledb;
85 enum lp5521_mode mode;
92 static int lp5521_set_mode(struct lp5521_chip *chip, enum lp5521_mode mode);
94 static inline int lp5521_write(struct i2c_client *client, u8 reg, u8 value)
96 return i2c_smbus_write_byte_data(client, reg, value);
99 static inline int lp5521_read(struct i2c_client *client, u8 reg)
101 return i2c_smbus_read_byte_data(client, reg);
104 static int lp5521_configure(struct i2c_client *client)
108 /* Enable chip and set light to logarithmic mode*/
109 ret |= lp5521_write(client, LP5521_REG_ENABLE, 0xc0);
111 /* setting all color pwms to direct control mode */
112 ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x3f);
114 /* setting current to 4.7 mA for all channels */
115 ret |= lp5521_write(client, LP5521_REG_R_CNTRL, LP5521_CURRENT_4m7);
116 ret |= lp5521_write(client, LP5521_REG_G_CNTRL, LP5521_CURRENT_4m7);
117 ret |= lp5521_write(client, LP5521_REG_B_CNTRL, LP5521_CURRENT_4m7);
119 /* Enable auto-powersave, set charge pump to auto, red to battery */
120 ret |= lp5521_write(client, LP5521_REG_MISC, 0x3c);
122 /* initialize all channels pwm to zero */
123 ret |= lp5521_write(client, LP5521_REG_R_PWM, 0);
124 ret |= lp5521_write(client, LP5521_REG_G_PWM, 0);
125 ret |= lp5521_write(client, LP5521_REG_B_PWM, 0);
127 /* Not much can be done about errors at this point */
131 static int lp5521_load_program(struct lp5521_chip *chip, u8 *pattern)
133 struct i2c_client *client = chip->client;
136 /* Enter load program mode for all led channels */
137 ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x15); /* 0001 0101 */
142 ret |= i2c_smbus_write_i2c_block_data(client,
143 LP5521_REG_R_PROG_MEM,
144 LP5521_PROGRAM_LENGTH,
147 ret |= i2c_smbus_write_i2c_block_data(client,
148 LP5521_REG_G_PROG_MEM,
149 LP5521_PROGRAM_LENGTH,
152 ret |= i2c_smbus_write_i2c_block_data(client,
153 LP5521_REG_B_PROG_MEM,
154 LP5521_PROGRAM_LENGTH,
160 static int lp5521_run_program(struct lp5521_chip *chip)
162 struct i2c_client *client = chip->client;
167 reg = lp5521_read(client, LP5521_REG_ENABLE);
173 /* set all active channels exec state to countinous run*/
174 exec_state |= (chip->red << 5);
175 exec_state |= (chip->green << 3);
176 exec_state |= (chip->blue << 1);
180 if (lp5521_write(client, LP5521_REG_ENABLE, reg))
181 dev_dbg(&client->dev, "failed writing to register %02x\n",
184 /* set op-mode to run for active channels, disabled for others */
185 if (lp5521_write(client, LP5521_REG_OP_MODE, exec_state))
186 dev_dbg(&client->dev, "failed writing to register %02x\n",
192 /*--------------------------------------------------------------*/
193 /* Sysfs interface */
194 /*--------------------------------------------------------------*/
196 static ssize_t show_active_channels(struct device *dev,
197 struct device_attribute *attr,
200 struct lp5521_chip *chip = dev_get_drvdata(dev);
205 pos += sprintf(channels + pos, "r");
207 pos += sprintf(channels + pos, "g");
209 pos += sprintf(channels + pos, "b");
211 channels[pos] = '\0';
213 return sprintf(buf, "%s\n", channels);
216 static ssize_t store_active_channels(struct device *dev,
217 struct device_attribute *attr,
218 const char *buf, size_t len)
220 struct lp5521_chip *chip = dev_get_drvdata(dev);
226 if (strchr(buf, 'r') != NULL)
228 if (strchr(buf, 'b') != NULL)
230 if (strchr(buf, 'g') != NULL)
236 static ssize_t show_color(struct device *dev,
237 struct device_attribute *attr,
240 struct i2c_client *client = to_i2c_client(dev);
243 r = lp5521_read(client, LP5521_REG_R_PWM);
244 g = lp5521_read(client, LP5521_REG_G_PWM);
245 b = lp5521_read(client, LP5521_REG_B_PWM);
247 if (r < 0 || g < 0 || b < 0)
250 return sprintf(buf, "%.2x:%.2x:%.2x\n", r, g, b);
253 static ssize_t store_color(struct device *dev,
254 struct device_attribute *attr,
255 const char *buf, size_t len)
257 struct i2c_client *client = to_i2c_client(dev);
258 struct lp5521_chip *chip = i2c_get_clientdata(client);
263 ret = sscanf(buf, "%2x:%2x:%2x", &r, &g, &b);
267 mutex_lock(&chip->lock);
269 ret = lp5521_write(client, LP5521_REG_R_PWM, (u8)r);
270 ret = lp5521_write(client, LP5521_REG_G_PWM, (u8)g);
271 ret = lp5521_write(client, LP5521_REG_B_PWM, (u8)b);
273 mutex_unlock(&chip->lock);
278 static ssize_t store_load(struct device *dev,
279 struct device_attribute *attr,
280 const char *buf, size_t len)
282 struct lp5521_chip *chip = dev_get_drvdata(dev);
283 int ret, nrchars, offset = 0, i = 0;
286 u8 pattern[LP5521_PROGRAM_LENGTH] = {0};
288 while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) {
290 /* separate sscanfs because length is working only for %s */
291 ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
292 ret = sscanf(c, "%2x", &cmd);
295 pattern[i] = (u8)cmd;
301 /* pattern commands are always two bytes long */
305 mutex_lock(&chip->lock);
307 ret = lp5521_load_program(chip, pattern);
308 mutex_unlock(&chip->lock);
311 dev_err(dev, "lp5521 failed loading pattern\n");
317 dev_err(dev, "lp5521 wrong pattern format\n");
321 static ssize_t show_mode(struct device *dev,
322 struct device_attribute *attr,
325 struct lp5521_chip *chip = dev_get_drvdata(dev);
328 mutex_lock(&chip->lock);
329 switch (chip->mode) {
330 case LP5521_MODE_RUN:
333 case LP5521_MODE_LOAD:
336 case LP5521_MODE_DIRECT_CONTROL:
342 mutex_unlock(&chip->lock);
344 return sprintf(buf, "%s\n", mode);
347 static ssize_t store_mode(struct device *dev,
348 struct device_attribute *attr,
349 const char *buf, size_t len)
351 struct lp5521_chip *chip = dev_get_drvdata(dev);
353 mutex_lock(&chip->lock);
355 if (!strncmp(buf, "run", 3))
356 lp5521_set_mode(chip, LP5521_MODE_RUN);
357 else if (!strncmp(buf, "load", 4))
358 lp5521_set_mode(chip, LP5521_MODE_LOAD);
359 else if (!strncmp(buf, "direct", 6))
360 lp5521_set_mode(chip, LP5521_MODE_DIRECT_CONTROL);
362 mutex_unlock(&chip->lock);
367 static ssize_t show_current(struct device *dev,
368 struct device_attribute *attr,
371 struct i2c_client *client = to_i2c_client(dev);
374 r = lp5521_read(client, LP5521_REG_R_CNTRL);
375 g = lp5521_read(client, LP5521_REG_G_CNTRL);
376 b = lp5521_read(client, LP5521_REG_B_CNTRL);
378 if (r < 0 || g < 0 || b < 0)
385 return sprintf(buf, "%x %x %x\n", r, g, b);
388 static ssize_t store_current(struct device *dev,
389 struct device_attribute *attr,
390 const char *buf, size_t len)
392 struct lp5521_chip *chip = dev_get_drvdata(dev);
393 struct i2c_client *client = chip->client;
397 ret = sscanf(buf, "%1x", &curr);
401 /* current level is determined by the 4 upper bits, rest is ones */
402 curr = (curr << 4) | 0x0f;
404 mutex_lock(&chip->lock);
406 ret |= lp5521_write(client, LP5521_REG_R_CNTRL, (u8)curr);
407 ret |= lp5521_write(client, LP5521_REG_G_CNTRL, (u8)curr);
408 ret |= lp5521_write(client, LP5521_REG_B_CNTRL, (u8)curr);
410 mutex_unlock(&chip->lock);
415 static DEVICE_ATTR(color, S_IRUGO | S_IWUGO, show_color, store_color);
416 static DEVICE_ATTR(load, S_IWUGO, NULL, store_load);
417 static DEVICE_ATTR(mode, S_IRUGO | S_IWUGO, show_mode, store_mode);
418 static DEVICE_ATTR(active_channels, S_IRUGO | S_IWUGO,
419 show_active_channels, store_active_channels);
420 static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
422 static int lp5521_register_sysfs(struct i2c_client *client)
424 struct device *dev = &client->dev;
427 ret = device_create_file(dev, &dev_attr_color);
430 ret = device_create_file(dev, &dev_attr_load);
433 ret = device_create_file(dev, &dev_attr_active_channels);
436 ret = device_create_file(dev, &dev_attr_mode);
439 ret = device_create_file(dev, &dev_attr_led_current);
446 device_remove_file(dev, &dev_attr_mode);
448 device_remove_file(dev, &dev_attr_active_channels);
450 device_remove_file(dev, &dev_attr_load);
452 device_remove_file(dev, &dev_attr_color);
457 static void lp5521_unregister_sysfs(struct i2c_client *client)
459 struct device *dev = &client->dev;
461 device_remove_file(dev, &dev_attr_led_current);
462 device_remove_file(dev, &dev_attr_mode);
463 device_remove_file(dev, &dev_attr_active_channels);
464 device_remove_file(dev, &dev_attr_color);
465 device_remove_file(dev, &dev_attr_load);
468 /*--------------------------------------------------------------*/
469 /* Set chip operating mode */
470 /*--------------------------------------------------------------*/
472 static int lp5521_set_mode(struct lp5521_chip *chip, enum lp5521_mode mode)
474 struct i2c_client *client = chip->client ;
477 /* if in that mode already do nothing, except for run */
478 if (chip->mode == mode && mode != LP5521_MODE_RUN)
482 case LP5521_MODE_RUN:
483 ret = lp5521_run_program(chip);
485 case LP5521_MODE_LOAD:
486 ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x15);
488 case LP5521_MODE_DIRECT_CONTROL:
489 ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x3F);
492 dev_dbg(&client->dev, "unsupported mode %d\n", mode);
500 static void lp5521_red_work(struct work_struct *work)
502 struct lp5521_chip *chip = container_of(work, struct lp5521_chip, red_work);
505 ret = lp5521_configure(chip->client);
507 dev_dbg(&chip->client->dev, "could not configure lp5521, %d\n",
512 ret = lp5521_write(chip->client, LP5521_REG_R_PWM, chip->red);
514 dev_dbg(&chip->client->dev, "could not set brightness, %d\n",
518 static void lp5521_red_set(struct led_classdev *led,
519 enum led_brightness value)
521 struct lp5521_chip *chip = container_of(led, struct lp5521_chip, ledr);
524 schedule_work(&chip->red_work);
527 static void lp5521_green_work(struct work_struct *work)
529 struct lp5521_chip *chip = container_of(work, struct lp5521_chip, green_work);
532 ret = lp5521_configure(chip->client);
534 dev_dbg(&chip->client->dev, "could not configure lp5521, %d\n",
539 ret = lp5521_write(chip->client, LP5521_REG_G_PWM, chip->green);
541 dev_dbg(&chip->client->dev, "could not set brightness, %d\n",
545 static void lp5521_green_set(struct led_classdev *led,
546 enum led_brightness value)
548 struct lp5521_chip *chip = container_of(led, struct lp5521_chip, ledg);
551 schedule_work(&chip->green_work);
554 static void lp5521_blue_work(struct work_struct *work)
556 struct lp5521_chip *chip = container_of(work, struct lp5521_chip, blue_work);
559 ret = lp5521_configure(chip->client);
561 dev_dbg(&chip->client->dev, "could not configure lp5521, %d\n",
566 ret = lp5521_write(chip->client, LP5521_REG_B_PWM, chip->blue);
568 dev_dbg(&chip->client->dev, "could not set brightness, %d\n",
572 static void lp5521_blue_set(struct led_classdev *led,
573 enum led_brightness value)
575 struct lp5521_chip *chip = container_of(led, struct lp5521_chip, ledb);
578 schedule_work(&chip->blue_work);
581 /*--------------------------------------------------------------*/
582 /* Probe, Attach, Remove */
583 /*--------------------------------------------------------------*/
585 static int __init lp5521_probe(struct i2c_client *client,
586 const struct i2c_device_id *id)
588 struct lp5521_platform_data *pdata = client->dev.platform_data;
589 struct lp5521_chip *chip;
594 dev_err(&client->dev, "platform_data is missing\n");
598 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
602 chip->client = client;
603 strncpy(client->name, LP5521_DRIVER_NAME, I2C_NAME_SIZE);
604 i2c_set_clientdata(client, chip);
606 mutex_init(&chip->lock);
608 INIT_WORK(&chip->red_work, lp5521_red_work);
609 INIT_WORK(&chip->green_work, lp5521_green_work);
610 INIT_WORK(&chip->blue_work, lp5521_blue_work);
612 ret = lp5521_configure(client);
614 dev_err(&client->dev, "lp5521 error configuring chip \n");
618 /* Set default values */
619 chip->mode = pdata->mode;
620 chip->red = pdata->red_present;
621 chip->green = pdata->green_present;
622 chip->blue = pdata->blue_present;
624 chip->ledr.brightness_set = lp5521_red_set;
625 chip->ledr.default_trigger = NULL;
626 snprintf(name, sizeof(name), "%s::red", pdata->label);
627 chip->ledr.name = name;
628 ret = led_classdev_register(&client->dev, &chip->ledr);
630 dev_dbg(&client->dev, "failed to register led %s, %d\n",
631 chip->ledb.name, ret);
635 chip->ledg.brightness_set = lp5521_green_set;
636 chip->ledg.default_trigger = NULL;
637 snprintf(name, sizeof(name), "%s::green", pdata->label);
638 chip->ledg.name = name;
639 ret = led_classdev_register(&client->dev, &chip->ledg);
641 dev_dbg(&client->dev, "failed to register led %s, %d\n",
642 chip->ledb.name, ret);
646 chip->ledb.brightness_set = lp5521_blue_set;
647 chip->ledb.default_trigger = NULL;
648 snprintf(name, sizeof(name), "%s::blue", pdata->label);
649 chip->ledb.name = name;
650 ret = led_classdev_register(&client->dev, &chip->ledb);
652 dev_dbg(&client->dev, "failed to register led %s, %d\n", chip->ledb.name, ret);
656 ret = lp5521_register_sysfs(client);
658 dev_err(&client->dev, "lp5521 registering sysfs failed \n");
665 led_classdev_unregister(&chip->ledb);
667 led_classdev_unregister(&chip->ledg);
669 led_classdev_unregister(&chip->ledr);
671 i2c_set_clientdata(client, NULL);
677 static int __exit lp5521_remove(struct i2c_client *client)
679 struct lp5521_chip *chip = i2c_get_clientdata(client);
681 lp5521_unregister_sysfs(client);
682 i2c_set_clientdata(client, NULL);
684 led_classdev_unregister(&chip->ledb);
685 led_classdev_unregister(&chip->ledg);
686 led_classdev_unregister(&chip->ledr);
693 static const struct i2c_device_id lp5521_id[] = {
694 { LP5521_DRIVER_NAME, 0},
697 MODULE_DEVICE_TABLE(i2c, lp5521_id);
699 static struct i2c_driver lp5521_driver = {
701 .name = LP5521_DRIVER_NAME,
703 .probe = lp5521_probe,
704 .remove = __exit_p(lp5521_remove),
705 .id_table = lp5521_id,
708 static int __init lp5521_init(void)
710 return i2c_add_driver(&lp5521_driver);
712 module_init(lp5521_init);
714 static void __exit lp5521_exit(void)
716 i2c_del_driver(&lp5521_driver);
718 module_exit(lp5521_exit);
720 MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>");
721 MODULE_DESCRIPTION("lp5521 LED driver");
722 MODULE_LICENSE("GPL");