aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds/leds-lp5521.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds/leds-lp5521.c')
-rw-r--r--drivers/leds/leds-lp5521.c102
1 files changed, 101 insertions, 1 deletions
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 9682ece16011..007c7c921e7e 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -88,6 +88,9 @@
88/* default R channel current register value */ 88/* default R channel current register value */
89#define LP5521_REG_R_CURR_DEFAULT 0xAF 89#define LP5521_REG_R_CURR_DEFAULT 0xAF
90 90
91/* Pattern Mode */
92#define PATTERN_OFF 0
93
91struct lp5521_engine { 94struct lp5521_engine {
92 int id; 95 int id;
93 u8 mode; 96 u8 mode;
@@ -493,7 +496,7 @@ static ssize_t store_current(struct device *dev,
493 ssize_t ret; 496 ssize_t ret;
494 unsigned long curr; 497 unsigned long curr;
495 498
496 if (strict_strtoul(buf, 0, &curr)) 499 if (kstrtoul(buf, 0, &curr))
497 return -EINVAL; 500 return -EINVAL;
498 501
499 if (curr > led->max_current) 502 if (curr > led->max_current)
@@ -525,6 +528,100 @@ static ssize_t lp5521_selftest(struct device *dev,
525 return sprintf(buf, "%s\n", ret ? "FAIL" : "OK"); 528 return sprintf(buf, "%s\n", ret ? "FAIL" : "OK");
526} 529}
527 530
531static void lp5521_clear_program_memory(struct i2c_client *cl)
532{
533 int i;
534 u8 rgb_mem[] = {
535 LP5521_REG_R_PROG_MEM,
536 LP5521_REG_G_PROG_MEM,
537 LP5521_REG_B_PROG_MEM,
538 };
539
540 for (i = 0; i < ARRAY_SIZE(rgb_mem); i++) {
541 lp5521_write(cl, rgb_mem[i], 0);
542 lp5521_write(cl, rgb_mem[i] + 1, 0);
543 }
544}
545
546static void lp5521_write_program_memory(struct i2c_client *cl,
547 u8 base, u8 *rgb, int size)
548{
549 int i;
550
551 if (!rgb || size <= 0)
552 return;
553
554 for (i = 0; i < size; i++)
555 lp5521_write(cl, base + i, *(rgb + i));
556
557 lp5521_write(cl, base + i, 0);
558 lp5521_write(cl, base + i + 1, 0);
559}
560
561static inline struct lp5521_led_pattern *lp5521_get_pattern
562 (struct lp5521_chip *chip, u8 offset)
563{
564 struct lp5521_led_pattern *ptn;
565 ptn = chip->pdata->patterns + (offset - 1);
566 return ptn;
567}
568
569static void lp5521_run_led_pattern(int mode, struct lp5521_chip *chip)
570{
571 struct lp5521_led_pattern *ptn;
572 struct i2c_client *cl = chip->client;
573 int num_patterns = chip->pdata->num_patterns;
574
575 if (mode > num_patterns || !(chip->pdata->patterns))
576 return;
577
578 if (mode == PATTERN_OFF) {
579 lp5521_write(cl, LP5521_REG_ENABLE,
580 LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM);
581 usleep_range(1000, 2000);
582 lp5521_write(cl, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
583 } else {
584 ptn = lp5521_get_pattern(chip, mode);
585 if (!ptn)
586 return;
587
588 lp5521_write(cl, LP5521_REG_OP_MODE, LP5521_CMD_LOAD);
589 usleep_range(1000, 2000);
590
591 lp5521_clear_program_memory(cl);
592
593 lp5521_write_program_memory(cl, LP5521_REG_R_PROG_MEM,
594 ptn->r, ptn->size_r);
595 lp5521_write_program_memory(cl, LP5521_REG_G_PROG_MEM,
596 ptn->g, ptn->size_g);
597 lp5521_write_program_memory(cl, LP5521_REG_B_PROG_MEM,
598 ptn->b, ptn->size_b);
599
600 lp5521_write(cl, LP5521_REG_OP_MODE, LP5521_CMD_RUN);
601 usleep_range(1000, 2000);
602 lp5521_write(cl, LP5521_REG_ENABLE,
603 LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM |
604 LP5521_EXEC_RUN);
605 }
606}
607
608static ssize_t store_led_pattern(struct device *dev,
609 struct device_attribute *attr,
610 const char *buf, size_t len)
611{
612 struct lp5521_chip *chip = i2c_get_clientdata(to_i2c_client(dev));
613 unsigned long val;
614 int ret;
615
616 ret = strict_strtoul(buf, 16, &val);
617 if (ret)
618 return ret;
619
620 lp5521_run_led_pattern(val, chip);
621
622 return len;
623}
624
528/* led class device attributes */ 625/* led class device attributes */
529static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current); 626static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
530static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); 627static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
@@ -550,6 +647,7 @@ static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
550static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load); 647static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
551static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load); 648static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
552static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL); 649static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL);
650static DEVICE_ATTR(led_pattern, S_IWUSR, NULL, store_led_pattern);
553 651
554static struct attribute *lp5521_attributes[] = { 652static struct attribute *lp5521_attributes[] = {
555 &dev_attr_engine1_mode.attr, 653 &dev_attr_engine1_mode.attr,
@@ -559,6 +657,7 @@ static struct attribute *lp5521_attributes[] = {
559 &dev_attr_engine1_load.attr, 657 &dev_attr_engine1_load.attr,
560 &dev_attr_engine2_load.attr, 658 &dev_attr_engine2_load.attr,
561 &dev_attr_engine3_load.attr, 659 &dev_attr_engine3_load.attr,
660 &dev_attr_led_pattern.attr,
562 NULL 661 NULL
563}; 662};
564 663
@@ -761,6 +860,7 @@ static int __devexit lp5521_remove(struct i2c_client *client)
761 struct lp5521_chip *chip = i2c_get_clientdata(client); 860 struct lp5521_chip *chip = i2c_get_clientdata(client);
762 int i; 861 int i;
763 862
863 lp5521_run_led_pattern(PATTERN_OFF, chip);
764 lp5521_unregister_sysfs(client); 864 lp5521_unregister_sysfs(client);
765 865
766 for (i = 0; i < chip->num_leds; i++) { 866 for (i = 0; i < chip->num_leds; i++) {