diff options
Diffstat (limited to 'drivers/leds/leds-lp5523.c')
-rw-r--r-- | drivers/leds/leds-lp5523.c | 75 |
1 files changed, 46 insertions, 29 deletions
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index fbc12acada95..97994ffdc014 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c | |||
@@ -104,6 +104,11 @@ | |||
104 | #define LED_ACTIVE(mux, led) (!!(mux & (0x0001 << led))) | 104 | #define LED_ACTIVE(mux, led) (!!(mux & (0x0001 << led))) |
105 | #define SHIFT_MASK(id) (((id) - 1) * 2) | 105 | #define SHIFT_MASK(id) (((id) - 1) * 2) |
106 | 106 | ||
107 | enum lp5523_chip_id { | ||
108 | LP5523, | ||
109 | LP55231, | ||
110 | }; | ||
111 | |||
107 | struct lp5523_engine { | 112 | struct lp5523_engine { |
108 | int id; | 113 | int id; |
109 | u8 mode; | 114 | u8 mode; |
@@ -150,7 +155,7 @@ static inline struct lp5523_chip *led_to_lp5523(struct lp5523_led *led) | |||
150 | leds[led->id]); | 155 | leds[led->id]); |
151 | } | 156 | } |
152 | 157 | ||
153 | static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode); | 158 | static void lp5523_set_mode(struct lp5523_engine *engine, u8 mode); |
154 | static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode); | 159 | static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode); |
155 | static int lp5523_load_program(struct lp5523_engine *engine, const u8 *pattern); | 160 | static int lp5523_load_program(struct lp5523_engine *engine, const u8 *pattern); |
156 | 161 | ||
@@ -177,7 +182,7 @@ static int lp5523_detect(struct i2c_client *client) | |||
177 | int ret; | 182 | int ret; |
178 | u8 buf; | 183 | u8 buf; |
179 | 184 | ||
180 | ret = lp5523_write(client, LP5523_REG_ENABLE, 0x40); | 185 | ret = lp5523_write(client, LP5523_REG_ENABLE, LP5523_ENABLE); |
181 | if (ret) | 186 | if (ret) |
182 | return ret; | 187 | return ret; |
183 | ret = lp5523_read(client, LP5523_REG_ENABLE, &buf); | 188 | ret = lp5523_read(client, LP5523_REG_ENABLE, &buf); |
@@ -338,7 +343,8 @@ static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len) | |||
338 | { | 343 | { |
339 | int i; | 344 | int i; |
340 | u16 tmp_mux = 0; | 345 | u16 tmp_mux = 0; |
341 | len = len < LP5523_LEDS ? len : LP5523_LEDS; | 346 | |
347 | len = min_t(int, len, LP5523_LEDS); | ||
342 | for (i = 0; i < len; i++) { | 348 | for (i = 0; i < len; i++) { |
343 | switch (buf[i]) { | 349 | switch (buf[i]) { |
344 | case '1': | 350 | case '1': |
@@ -546,6 +552,9 @@ static int lp5523_do_store_load(struct lp5523_engine *engine, | |||
546 | unsigned cmd; | 552 | unsigned cmd; |
547 | u8 pattern[LP5523_PROGRAM_LENGTH] = {0}; | 553 | u8 pattern[LP5523_PROGRAM_LENGTH] = {0}; |
548 | 554 | ||
555 | if (engine->mode != LP5523_CMD_LOAD) | ||
556 | return -EINVAL; | ||
557 | |||
549 | while ((offset < len - 1) && (i < LP5523_PROGRAM_LENGTH)) { | 558 | while ((offset < len - 1) && (i < LP5523_PROGRAM_LENGTH)) { |
550 | /* separate sscanfs because length is working only for %s */ | 559 | /* separate sscanfs because length is working only for %s */ |
551 | ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); | 560 | ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); |
@@ -563,12 +572,7 @@ static int lp5523_do_store_load(struct lp5523_engine *engine, | |||
563 | goto fail; | 572 | goto fail; |
564 | 573 | ||
565 | mutex_lock(&chip->lock); | 574 | mutex_lock(&chip->lock); |
566 | 575 | ret = lp5523_load_program(engine, pattern); | |
567 | if (engine->mode == LP5523_CMD_LOAD) | ||
568 | ret = lp5523_load_program(engine, pattern); | ||
569 | else | ||
570 | ret = -EINVAL; | ||
571 | |||
572 | mutex_unlock(&chip->lock); | 576 | mutex_unlock(&chip->lock); |
573 | 577 | ||
574 | if (ret) { | 578 | if (ret) { |
@@ -755,6 +759,7 @@ static struct attribute *lp5523_attributes[] = { | |||
755 | &dev_attr_engine2_leds.attr, | 759 | &dev_attr_engine2_leds.attr, |
756 | &dev_attr_engine3_load.attr, | 760 | &dev_attr_engine3_load.attr, |
757 | &dev_attr_engine3_leds.attr, | 761 | &dev_attr_engine3_leds.attr, |
762 | NULL, | ||
758 | }; | 763 | }; |
759 | 764 | ||
760 | static const struct attribute_group lp5523_group = { | 765 | static const struct attribute_group lp5523_group = { |
@@ -789,26 +794,28 @@ static void lp5523_unregister_sysfs(struct i2c_client *client) | |||
789 | /*--------------------------------------------------------------*/ | 794 | /*--------------------------------------------------------------*/ |
790 | /* Set chip operating mode */ | 795 | /* Set chip operating mode */ |
791 | /*--------------------------------------------------------------*/ | 796 | /*--------------------------------------------------------------*/ |
792 | static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode) | 797 | static void lp5523_set_mode(struct lp5523_engine *engine, u8 mode) |
793 | { | 798 | { |
794 | int ret = 0; | ||
795 | |||
796 | /* if in that mode already do nothing, except for run */ | 799 | /* if in that mode already do nothing, except for run */ |
797 | if (mode == engine->mode && mode != LP5523_CMD_RUN) | 800 | if (mode == engine->mode && mode != LP5523_CMD_RUN) |
798 | return 0; | 801 | return; |
799 | 802 | ||
800 | if (mode == LP5523_CMD_RUN) { | 803 | switch (mode) { |
801 | ret = lp5523_run_program(engine); | 804 | case LP5523_CMD_RUN: |
802 | } else if (mode == LP5523_CMD_LOAD) { | 805 | lp5523_run_program(engine); |
806 | break; | ||
807 | case LP5523_CMD_LOAD: | ||
803 | lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); | 808 | lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); |
804 | lp5523_set_engine_mode(engine, LP5523_CMD_LOAD); | 809 | lp5523_set_engine_mode(engine, LP5523_CMD_LOAD); |
805 | } else if (mode == LP5523_CMD_DISABLED) { | 810 | break; |
811 | case LP5523_CMD_DISABLED: | ||
806 | lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); | 812 | lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); |
813 | break; | ||
814 | default: | ||
815 | return; | ||
807 | } | 816 | } |
808 | 817 | ||
809 | engine->mode = mode; | 818 | engine->mode = mode; |
810 | |||
811 | return ret; | ||
812 | } | 819 | } |
813 | 820 | ||
814 | /*--------------------------------------------------------------*/ | 821 | /*--------------------------------------------------------------*/ |
@@ -827,7 +834,8 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id) | |||
827 | } | 834 | } |
828 | 835 | ||
829 | static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev, | 836 | static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev, |
830 | int chan, struct lp5523_platform_data *pdata) | 837 | int chan, struct lp5523_platform_data *pdata, |
838 | const char *chip_name) | ||
831 | { | 839 | { |
832 | char name[32]; | 840 | char name[32]; |
833 | int res; | 841 | int res; |
@@ -846,10 +854,14 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev, | |||
846 | return -EINVAL; | 854 | return -EINVAL; |
847 | } | 855 | } |
848 | 856 | ||
849 | snprintf(name, sizeof(name), "%s:channel%d", | 857 | if (pdata->led_config[chan].name) { |
850 | pdata->label ?: "lp5523", chan); | 858 | led->cdev.name = pdata->led_config[chan].name; |
859 | } else { | ||
860 | snprintf(name, sizeof(name), "%s:channel%d", | ||
861 | pdata->label ? : chip_name, chan); | ||
862 | led->cdev.name = name; | ||
863 | } | ||
851 | 864 | ||
852 | led->cdev.name = name; | ||
853 | led->cdev.brightness_set = lp5523_set_brightness; | 865 | led->cdev.brightness_set = lp5523_set_brightness; |
854 | res = led_classdev_register(dev, &led->cdev); | 866 | res = led_classdev_register(dev, &led->cdev); |
855 | if (res < 0) { | 867 | if (res < 0) { |
@@ -917,7 +929,7 @@ static int __devinit lp5523_probe(struct i2c_client *client, | |||
917 | if (ret) | 929 | if (ret) |
918 | goto fail1; | 930 | goto fail1; |
919 | 931 | ||
920 | dev_info(&client->dev, "LP5523 Programmable led chip found\n"); | 932 | dev_info(&client->dev, "%s Programmable led chip found\n", id->name); |
921 | 933 | ||
922 | /* Initialize engines */ | 934 | /* Initialize engines */ |
923 | for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { | 935 | for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { |
@@ -945,7 +957,8 @@ static int __devinit lp5523_probe(struct i2c_client *client, | |||
945 | INIT_WORK(&chip->leds[led].brightness_work, | 957 | INIT_WORK(&chip->leds[led].brightness_work, |
946 | lp5523_led_brightness_work); | 958 | lp5523_led_brightness_work); |
947 | 959 | ||
948 | ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata); | 960 | ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata, |
961 | id->name); | ||
949 | if (ret) { | 962 | if (ret) { |
950 | dev_err(&client->dev, "error initializing leds\n"); | 963 | dev_err(&client->dev, "error initializing leds\n"); |
951 | goto fail2; | 964 | goto fail2; |
@@ -970,7 +983,7 @@ static int __devinit lp5523_probe(struct i2c_client *client, | |||
970 | fail2: | 983 | fail2: |
971 | for (i = 0; i < chip->num_leds; i++) { | 984 | for (i = 0; i < chip->num_leds; i++) { |
972 | led_classdev_unregister(&chip->leds[i].cdev); | 985 | led_classdev_unregister(&chip->leds[i].cdev); |
973 | cancel_work_sync(&chip->leds[i].brightness_work); | 986 | flush_work(&chip->leds[i].brightness_work); |
974 | } | 987 | } |
975 | fail1: | 988 | fail1: |
976 | if (pdata->enable) | 989 | if (pdata->enable) |
@@ -985,11 +998,14 @@ static int lp5523_remove(struct i2c_client *client) | |||
985 | struct lp5523_chip *chip = i2c_get_clientdata(client); | 998 | struct lp5523_chip *chip = i2c_get_clientdata(client); |
986 | int i; | 999 | int i; |
987 | 1000 | ||
1001 | /* Disable engine mode */ | ||
1002 | lp5523_write(client, LP5523_REG_OP_MODE, LP5523_CMD_DISABLED); | ||
1003 | |||
988 | lp5523_unregister_sysfs(client); | 1004 | lp5523_unregister_sysfs(client); |
989 | 1005 | ||
990 | for (i = 0; i < chip->num_leds; i++) { | 1006 | for (i = 0; i < chip->num_leds; i++) { |
991 | led_classdev_unregister(&chip->leds[i].cdev); | 1007 | led_classdev_unregister(&chip->leds[i].cdev); |
992 | cancel_work_sync(&chip->leds[i].brightness_work); | 1008 | flush_work(&chip->leds[i].brightness_work); |
993 | } | 1009 | } |
994 | 1010 | ||
995 | if (chip->pdata->enable) | 1011 | if (chip->pdata->enable) |
@@ -1000,7 +1016,8 @@ static int lp5523_remove(struct i2c_client *client) | |||
1000 | } | 1016 | } |
1001 | 1017 | ||
1002 | static const struct i2c_device_id lp5523_id[] = { | 1018 | static const struct i2c_device_id lp5523_id[] = { |
1003 | { "lp5523", 0 }, | 1019 | { "lp5523", LP5523 }, |
1020 | { "lp55231", LP55231 }, | ||
1004 | { } | 1021 | { } |
1005 | }; | 1022 | }; |
1006 | 1023 | ||
@@ -1008,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, lp5523_id); | |||
1008 | 1025 | ||
1009 | static struct i2c_driver lp5523_driver = { | 1026 | static struct i2c_driver lp5523_driver = { |
1010 | .driver = { | 1027 | .driver = { |
1011 | .name = "lp5523", | 1028 | .name = "lp5523x", |
1012 | }, | 1029 | }, |
1013 | .probe = lp5523_probe, | 1030 | .probe = lp5523_probe, |
1014 | .remove = lp5523_remove, | 1031 | .remove = lp5523_remove, |