diff options
author | Kim Kyuwon <chammoru@gmail.com> | 2009-06-10 15:48:50 -0400 |
---|---|---|
committer | Richard Purdie <rpurdie@linux.intel.com> | 2009-06-23 15:19:10 -0400 |
commit | 8792f7cf4368f9bc337eee65851d8e7abbbf946c (patch) | |
tree | 25c6c2974c77f7dcdcdf8943bbe62e254ff9623d | |
parent | 1b18cf413f63ff6de5ba3e5028e869c21322a4df (diff) |
leds: add the sysfs interface into the leds-bd2802 driver for changing wave pattern and led current.
Allow the user application to change the wave pattern and led current by
'wave_pattern' and 'rgb_current' sysfs files.
Signed-off-by: Kim Kyuwon <q1.kim@samsung.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
-rw-r--r-- | drivers/leds/leds-bd2802.c | 86 |
1 files changed, 73 insertions, 13 deletions
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 7a03efd54f69..779d7f262c04 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c | |||
@@ -97,6 +97,10 @@ struct bd2802_led { | |||
97 | enum led_ids led_id; | 97 | enum led_ids led_id; |
98 | enum led_colors color; | 98 | enum led_colors color; |
99 | enum led_bits state; | 99 | enum led_bits state; |
100 | |||
101 | /* General attributes of RGB LEDs */ | ||
102 | int wave_pattern; | ||
103 | int rgb_current; | ||
100 | }; | 104 | }; |
101 | 105 | ||
102 | 106 | ||
@@ -254,7 +258,7 @@ static void bd2802_set_on(struct bd2802_led *led, enum led_ids id, | |||
254 | bd2802_reset_cancel(led); | 258 | bd2802_reset_cancel(led); |
255 | 259 | ||
256 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); | 260 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); |
257 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); | 261 | bd2802_write_byte(led->client, reg, led->rgb_current); |
258 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); | 262 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); |
259 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); | 263 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); |
260 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); | 264 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); |
@@ -275,9 +279,9 @@ static void bd2802_set_blink(struct bd2802_led *led, enum led_ids id, | |||
275 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); | 279 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); |
276 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); | 280 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); |
277 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); | 281 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); |
278 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); | 282 | bd2802_write_byte(led->client, reg, led->rgb_current); |
279 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); | 283 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); |
280 | bd2802_write_byte(led->client, reg, BD2802_PATTERN_HALF); | 284 | bd2802_write_byte(led->client, reg, led->wave_pattern); |
281 | 285 | ||
282 | bd2802_enable(led, id); | 286 | bd2802_enable(led, id); |
283 | bd2802_update_state(led, id, color, BD2802_BLINK); | 287 | bd2802_update_state(led, id, color, BD2802_BLINK); |
@@ -406,7 +410,7 @@ static void bd2802_enable_adv_conf(struct bd2802_led *led) | |||
406 | ret = device_create_file(&led->client->dev, | 410 | ret = device_create_file(&led->client->dev, |
407 | bd2802_addr_attributes[i]); | 411 | bd2802_addr_attributes[i]); |
408 | if (ret) { | 412 | if (ret) { |
409 | dev_err(&led->client->dev, "failed to sysfs file %s\n", | 413 | dev_err(&led->client->dev, "failed: sysfs file %s\n", |
410 | bd2802_addr_attributes[i]->attr.name); | 414 | bd2802_addr_attributes[i]->attr.name); |
411 | goto failed_remove_files; | 415 | goto failed_remove_files; |
412 | } | 416 | } |
@@ -483,6 +487,52 @@ static struct device_attribute bd2802_adv_conf_attr = { | |||
483 | .store = bd2802_store_adv_conf, | 487 | .store = bd2802_store_adv_conf, |
484 | }; | 488 | }; |
485 | 489 | ||
490 | #define BD2802_CONTROL_ATTR(attr_name, name_str) \ | ||
491 | static ssize_t bd2802_show_##attr_name(struct device *dev, \ | ||
492 | struct device_attribute *attr, char *buf) \ | ||
493 | { \ | ||
494 | struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ | ||
495 | ssize_t ret; \ | ||
496 | down_read(&led->rwsem); \ | ||
497 | ret = sprintf(buf, "0x%02x\n", led->attr_name); \ | ||
498 | up_read(&led->rwsem); \ | ||
499 | return ret; \ | ||
500 | } \ | ||
501 | static ssize_t bd2802_store_##attr_name(struct device *dev, \ | ||
502 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
503 | { \ | ||
504 | struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ | ||
505 | unsigned long val; \ | ||
506 | int ret; \ | ||
507 | if (!count) \ | ||
508 | return -EINVAL; \ | ||
509 | ret = strict_strtoul(buf, 16, &val); \ | ||
510 | if (ret) \ | ||
511 | return ret; \ | ||
512 | down_write(&led->rwsem); \ | ||
513 | led->attr_name = val; \ | ||
514 | up_write(&led->rwsem); \ | ||
515 | return count; \ | ||
516 | } \ | ||
517 | static struct device_attribute bd2802_##attr_name##_attr = { \ | ||
518 | .attr = { \ | ||
519 | .name = name_str, \ | ||
520 | .mode = 0644, \ | ||
521 | .owner = THIS_MODULE \ | ||
522 | }, \ | ||
523 | .show = bd2802_show_##attr_name, \ | ||
524 | .store = bd2802_store_##attr_name, \ | ||
525 | }; | ||
526 | |||
527 | BD2802_CONTROL_ATTR(wave_pattern, "wave_pattern"); | ||
528 | BD2802_CONTROL_ATTR(rgb_current, "rgb_current"); | ||
529 | |||
530 | static struct device_attribute *bd2802_attributes[] = { | ||
531 | &bd2802_adv_conf_attr, | ||
532 | &bd2802_wave_pattern_attr, | ||
533 | &bd2802_rgb_current_attr, | ||
534 | }; | ||
535 | |||
486 | static void bd2802_led_work(struct work_struct *work) | 536 | static void bd2802_led_work(struct work_struct *work) |
487 | { | 537 | { |
488 | struct bd2802_led *led = container_of(work, struct bd2802_led, work); | 538 | struct bd2802_led *led = container_of(work, struct bd2802_led, work); |
@@ -635,7 +685,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
635 | { | 685 | { |
636 | struct bd2802_led *led; | 686 | struct bd2802_led *led; |
637 | struct bd2802_led_platform_data *pdata; | 687 | struct bd2802_led_platform_data *pdata; |
638 | int ret; | 688 | int ret, i; |
639 | 689 | ||
640 | led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); | 690 | led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); |
641 | if (!led) { | 691 | if (!led) { |
@@ -665,13 +715,20 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
665 | /* To save the power, reset BD2802 after detecting */ | 715 | /* To save the power, reset BD2802 after detecting */ |
666 | gpio_set_value(led->pdata->reset_gpio, 0); | 716 | gpio_set_value(led->pdata->reset_gpio, 0); |
667 | 717 | ||
718 | /* Default attributes */ | ||
719 | led->wave_pattern = BD2802_PATTERN_HALF; | ||
720 | led->rgb_current = BD2802_CURRENT_032; | ||
721 | |||
668 | init_rwsem(&led->rwsem); | 722 | init_rwsem(&led->rwsem); |
669 | 723 | ||
670 | ret = device_create_file(&client->dev, &bd2802_adv_conf_attr); | 724 | for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) { |
671 | if (ret) { | 725 | ret = device_create_file(&led->client->dev, |
672 | dev_err(&client->dev, "failed to create sysfs file %s\n", | 726 | bd2802_attributes[i]); |
673 | bd2802_adv_conf_attr.attr.name); | 727 | if (ret) { |
674 | goto failed_free; | 728 | dev_err(&led->client->dev, "failed: sysfs file %s\n", |
729 | bd2802_attributes[i]->attr.name); | ||
730 | goto failed_unregister_dev_file; | ||
731 | } | ||
675 | } | 732 | } |
676 | 733 | ||
677 | ret = bd2802_register_led_classdev(led); | 734 | ret = bd2802_register_led_classdev(led); |
@@ -681,7 +738,8 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
681 | return 0; | 738 | return 0; |
682 | 739 | ||
683 | failed_unregister_dev_file: | 740 | failed_unregister_dev_file: |
684 | device_remove_file(&client->dev, &bd2802_adv_conf_attr); | 741 | for (i--; i >= 0; i--) |
742 | device_remove_file(&led->client->dev, bd2802_attributes[i]); | ||
685 | failed_free: | 743 | failed_free: |
686 | i2c_set_clientdata(client, NULL); | 744 | i2c_set_clientdata(client, NULL); |
687 | kfree(led); | 745 | kfree(led); |
@@ -692,12 +750,14 @@ failed_free: | |||
692 | static int __exit bd2802_remove(struct i2c_client *client) | 750 | static int __exit bd2802_remove(struct i2c_client *client) |
693 | { | 751 | { |
694 | struct bd2802_led *led = i2c_get_clientdata(client); | 752 | struct bd2802_led *led = i2c_get_clientdata(client); |
753 | int i; | ||
695 | 754 | ||
696 | bd2802_unregister_led_classdev(led); | ||
697 | gpio_set_value(led->pdata->reset_gpio, 0); | 755 | gpio_set_value(led->pdata->reset_gpio, 0); |
756 | bd2802_unregister_led_classdev(led); | ||
698 | if (led->adf_on) | 757 | if (led->adf_on) |
699 | bd2802_disable_adv_conf(led); | 758 | bd2802_disable_adv_conf(led); |
700 | device_remove_file(&client->dev, &bd2802_adv_conf_attr); | 759 | for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) |
760 | device_remove_file(&led->client->dev, bd2802_attributes[i]); | ||
701 | i2c_set_clientdata(client, NULL); | 761 | i2c_set_clientdata(client, NULL); |
702 | kfree(led); | 762 | kfree(led); |
703 | 763 | ||