1c72a1d60SRichard Purdie /* 2c72a1d60SRichard Purdie * LED Class Core 3c72a1d60SRichard Purdie * 4c72a1d60SRichard Purdie * Copyright 2005-2006 Openedhand Ltd. 5c72a1d60SRichard Purdie * 6c72a1d60SRichard Purdie * Author: Richard Purdie <rpurdie@openedhand.com> 7c72a1d60SRichard Purdie * 8c72a1d60SRichard Purdie * This program is free software; you can redistribute it and/or modify 9c72a1d60SRichard Purdie * it under the terms of the GNU General Public License version 2 as 10c72a1d60SRichard Purdie * published by the Free Software Foundation. 11c72a1d60SRichard Purdie * 12c72a1d60SRichard Purdie */ 13c72a1d60SRichard Purdie 14c72a1d60SRichard Purdie #include <linux/kernel.h> 15*04713306SJacek Anaszewski #include <linux/leds.h> 16c72a1d60SRichard Purdie #include <linux/list.h> 17c72a1d60SRichard Purdie #include <linux/module.h> 18*04713306SJacek Anaszewski #include <linux/mutex.h> 1972f8da32SRichard Purdie #include <linux/rwsem.h> 20c72a1d60SRichard Purdie #include "leds.h" 21c72a1d60SRichard Purdie 2272f8da32SRichard Purdie DECLARE_RWSEM(leds_list_lock); 23c72a1d60SRichard Purdie EXPORT_SYMBOL_GPL(leds_list_lock); 244d404fd5SNémeth Márton 254d404fd5SNémeth Márton LIST_HEAD(leds_list); 264d404fd5SNémeth Márton EXPORT_SYMBOL_GPL(leds_list); 27a403d930SBryan Wu 28a403d930SBryan Wu static void led_set_software_blink(struct led_classdev *led_cdev, 29a403d930SBryan Wu unsigned long delay_on, 30a403d930SBryan Wu unsigned long delay_off) 31a403d930SBryan Wu { 32a403d930SBryan Wu int current_brightness; 33a403d930SBryan Wu 34a403d930SBryan Wu current_brightness = led_get_brightness(led_cdev); 35a403d930SBryan Wu if (current_brightness) 36a403d930SBryan Wu led_cdev->blink_brightness = current_brightness; 37a403d930SBryan Wu if (!led_cdev->blink_brightness) 38a403d930SBryan Wu led_cdev->blink_brightness = led_cdev->max_brightness; 39a403d930SBryan Wu 40a403d930SBryan Wu led_cdev->blink_delay_on = delay_on; 41a403d930SBryan Wu led_cdev->blink_delay_off = delay_off; 42a403d930SBryan Wu 438d82fef8SStefan Sørensen /* never on - just set to off */ 448d82fef8SStefan Sørensen if (!delay_on) { 458d82fef8SStefan Sørensen __led_set_brightness(led_cdev, LED_OFF); 46a403d930SBryan Wu return; 478d82fef8SStefan Sørensen } 48a403d930SBryan Wu 49a403d930SBryan Wu /* never off - just set to brightness */ 50a403d930SBryan Wu if (!delay_off) { 510da3e65bSShuah Khan __led_set_brightness(led_cdev, led_cdev->blink_brightness); 52a403d930SBryan Wu return; 53a403d930SBryan Wu } 54a403d930SBryan Wu 559067359fSJiri Kosina mod_timer(&led_cdev->blink_timer, jiffies + 1); 56a403d930SBryan Wu } 57a403d930SBryan Wu 58a403d930SBryan Wu 5920c0e6b8SBryan Wu static void led_blink_setup(struct led_classdev *led_cdev, 60a403d930SBryan Wu unsigned long *delay_on, 61a403d930SBryan Wu unsigned long *delay_off) 62a403d930SBryan Wu { 635bb629c5SFabio Baltieri if (!(led_cdev->flags & LED_BLINK_ONESHOT) && 645bb629c5SFabio Baltieri led_cdev->blink_set && 65a403d930SBryan Wu !led_cdev->blink_set(led_cdev, delay_on, delay_off)) 66a403d930SBryan Wu return; 67a403d930SBryan Wu 68a403d930SBryan Wu /* blink with 1 Hz as default if nothing specified */ 69a403d930SBryan Wu if (!*delay_on && !*delay_off) 70a403d930SBryan Wu *delay_on = *delay_off = 500; 71a403d930SBryan Wu 72a403d930SBryan Wu led_set_software_blink(led_cdev, *delay_on, *delay_off); 73a403d930SBryan Wu } 745bb629c5SFabio Baltieri 755bb629c5SFabio Baltieri void led_blink_set(struct led_classdev *led_cdev, 765bb629c5SFabio Baltieri unsigned long *delay_on, 775bb629c5SFabio Baltieri unsigned long *delay_off) 785bb629c5SFabio Baltieri { 799067359fSJiri Kosina del_timer_sync(&led_cdev->blink_timer); 805bb629c5SFabio Baltieri 815bb629c5SFabio Baltieri led_cdev->flags &= ~LED_BLINK_ONESHOT; 825bb629c5SFabio Baltieri led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; 835bb629c5SFabio Baltieri 845bb629c5SFabio Baltieri led_blink_setup(led_cdev, delay_on, delay_off); 855bb629c5SFabio Baltieri } 86a403d930SBryan Wu EXPORT_SYMBOL(led_blink_set); 87a403d930SBryan Wu 885bb629c5SFabio Baltieri void led_blink_set_oneshot(struct led_classdev *led_cdev, 895bb629c5SFabio Baltieri unsigned long *delay_on, 905bb629c5SFabio Baltieri unsigned long *delay_off, 915bb629c5SFabio Baltieri int invert) 925bb629c5SFabio Baltieri { 935bb629c5SFabio Baltieri if ((led_cdev->flags & LED_BLINK_ONESHOT) && 949067359fSJiri Kosina timer_pending(&led_cdev->blink_timer)) 955bb629c5SFabio Baltieri return; 965bb629c5SFabio Baltieri 975bb629c5SFabio Baltieri led_cdev->flags |= LED_BLINK_ONESHOT; 985bb629c5SFabio Baltieri led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; 995bb629c5SFabio Baltieri 1005bb629c5SFabio Baltieri if (invert) 1015bb629c5SFabio Baltieri led_cdev->flags |= LED_BLINK_INVERT; 1025bb629c5SFabio Baltieri else 1035bb629c5SFabio Baltieri led_cdev->flags &= ~LED_BLINK_INVERT; 1045bb629c5SFabio Baltieri 1055bb629c5SFabio Baltieri led_blink_setup(led_cdev, delay_on, delay_off); 1065bb629c5SFabio Baltieri } 1075bb629c5SFabio Baltieri EXPORT_SYMBOL(led_blink_set_oneshot); 1085bb629c5SFabio Baltieri 109d23a22a7SFabio Baltieri void led_stop_software_blink(struct led_classdev *led_cdev) 110a403d930SBryan Wu { 1119067359fSJiri Kosina del_timer_sync(&led_cdev->blink_timer); 11243786482SFabio Baltieri led_cdev->blink_delay_on = 0; 11343786482SFabio Baltieri led_cdev->blink_delay_off = 0; 114d23a22a7SFabio Baltieri } 115d23a22a7SFabio Baltieri EXPORT_SYMBOL_GPL(led_stop_software_blink); 116d23a22a7SFabio Baltieri 117d23a22a7SFabio Baltieri void led_set_brightness(struct led_classdev *led_cdev, 118d23a22a7SFabio Baltieri enum led_brightness brightness) 119d23a22a7SFabio Baltieri { 1209067359fSJiri Kosina /* delay brightness setting if need to stop soft-blink timer */ 121d23a22a7SFabio Baltieri if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) { 122d23a22a7SFabio Baltieri led_cdev->delayed_set_value = brightness; 123d23a22a7SFabio Baltieri schedule_work(&led_cdev->set_brightness_work); 124d23a22a7SFabio Baltieri return; 125d23a22a7SFabio Baltieri } 12643786482SFabio Baltieri 1270da3e65bSShuah Khan __led_set_brightness(led_cdev, brightness); 128a403d930SBryan Wu } 12919cd67e2SShuah Khan EXPORT_SYMBOL(led_set_brightness); 130