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> 15c72a1d60SRichard Purdie #include <linux/list.h> 16c72a1d60SRichard Purdie #include <linux/module.h> 1772f8da32SRichard Purdie #include <linux/rwsem.h> 18c72a1d60SRichard Purdie #include <linux/leds.h> 19c72a1d60SRichard Purdie #include "leds.h" 20c72a1d60SRichard Purdie 2172f8da32SRichard Purdie DECLARE_RWSEM(leds_list_lock); 22c72a1d60SRichard Purdie EXPORT_SYMBOL_GPL(leds_list_lock); 234d404fd5SNémeth Márton 244d404fd5SNémeth Márton LIST_HEAD(leds_list); 254d404fd5SNémeth Márton EXPORT_SYMBOL_GPL(leds_list); 26a403d930SBryan Wu 27a403d930SBryan Wu static void led_set_software_blink(struct led_classdev *led_cdev, 28a403d930SBryan Wu unsigned long delay_on, 29a403d930SBryan Wu unsigned long delay_off) 30a403d930SBryan Wu { 31a403d930SBryan Wu int current_brightness; 32a403d930SBryan Wu 33a403d930SBryan Wu current_brightness = led_get_brightness(led_cdev); 34a403d930SBryan Wu if (current_brightness) 35a403d930SBryan Wu led_cdev->blink_brightness = current_brightness; 36a403d930SBryan Wu if (!led_cdev->blink_brightness) 37a403d930SBryan Wu led_cdev->blink_brightness = led_cdev->max_brightness; 38a403d930SBryan Wu 39a403d930SBryan Wu led_cdev->blink_delay_on = delay_on; 40a403d930SBryan Wu led_cdev->blink_delay_off = delay_off; 41a403d930SBryan Wu 428d82fef8SStefan Sørensen /* never on - just set to off */ 438d82fef8SStefan Sørensen if (!delay_on) { 448d82fef8SStefan Sørensen __led_set_brightness(led_cdev, LED_OFF); 45a403d930SBryan Wu return; 468d82fef8SStefan Sørensen } 47a403d930SBryan Wu 48a403d930SBryan Wu /* never off - just set to brightness */ 49a403d930SBryan Wu if (!delay_off) { 500da3e65bSShuah Khan __led_set_brightness(led_cdev, led_cdev->blink_brightness); 51a403d930SBryan Wu return; 52a403d930SBryan Wu } 53a403d930SBryan Wu 54*9067359fSJiri Kosina mod_timer(&led_cdev->blink_timer, jiffies + 1); 55a403d930SBryan Wu } 56a403d930SBryan Wu 57a403d930SBryan Wu 5820c0e6b8SBryan Wu static void led_blink_setup(struct led_classdev *led_cdev, 59a403d930SBryan Wu unsigned long *delay_on, 60a403d930SBryan Wu unsigned long *delay_off) 61a403d930SBryan Wu { 625bb629c5SFabio Baltieri if (!(led_cdev->flags & LED_BLINK_ONESHOT) && 635bb629c5SFabio Baltieri led_cdev->blink_set && 64a403d930SBryan Wu !led_cdev->blink_set(led_cdev, delay_on, delay_off)) 65a403d930SBryan Wu return; 66a403d930SBryan Wu 67a403d930SBryan Wu /* blink with 1 Hz as default if nothing specified */ 68a403d930SBryan Wu if (!*delay_on && !*delay_off) 69a403d930SBryan Wu *delay_on = *delay_off = 500; 70a403d930SBryan Wu 71a403d930SBryan Wu led_set_software_blink(led_cdev, *delay_on, *delay_off); 72a403d930SBryan Wu } 735bb629c5SFabio Baltieri 745bb629c5SFabio Baltieri void led_blink_set(struct led_classdev *led_cdev, 755bb629c5SFabio Baltieri unsigned long *delay_on, 765bb629c5SFabio Baltieri unsigned long *delay_off) 775bb629c5SFabio Baltieri { 78*9067359fSJiri Kosina del_timer_sync(&led_cdev->blink_timer); 795bb629c5SFabio Baltieri 805bb629c5SFabio Baltieri led_cdev->flags &= ~LED_BLINK_ONESHOT; 815bb629c5SFabio Baltieri led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; 825bb629c5SFabio Baltieri 835bb629c5SFabio Baltieri led_blink_setup(led_cdev, delay_on, delay_off); 845bb629c5SFabio Baltieri } 85a403d930SBryan Wu EXPORT_SYMBOL(led_blink_set); 86a403d930SBryan Wu 875bb629c5SFabio Baltieri void led_blink_set_oneshot(struct led_classdev *led_cdev, 885bb629c5SFabio Baltieri unsigned long *delay_on, 895bb629c5SFabio Baltieri unsigned long *delay_off, 905bb629c5SFabio Baltieri int invert) 915bb629c5SFabio Baltieri { 925bb629c5SFabio Baltieri if ((led_cdev->flags & LED_BLINK_ONESHOT) && 93*9067359fSJiri Kosina timer_pending(&led_cdev->blink_timer)) 945bb629c5SFabio Baltieri return; 955bb629c5SFabio Baltieri 965bb629c5SFabio Baltieri led_cdev->flags |= LED_BLINK_ONESHOT; 975bb629c5SFabio Baltieri led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; 985bb629c5SFabio Baltieri 995bb629c5SFabio Baltieri if (invert) 1005bb629c5SFabio Baltieri led_cdev->flags |= LED_BLINK_INVERT; 1015bb629c5SFabio Baltieri else 1025bb629c5SFabio Baltieri led_cdev->flags &= ~LED_BLINK_INVERT; 1035bb629c5SFabio Baltieri 1045bb629c5SFabio Baltieri led_blink_setup(led_cdev, delay_on, delay_off); 1055bb629c5SFabio Baltieri } 1065bb629c5SFabio Baltieri EXPORT_SYMBOL(led_blink_set_oneshot); 1075bb629c5SFabio Baltieri 108d23a22a7SFabio Baltieri void led_stop_software_blink(struct led_classdev *led_cdev) 109a403d930SBryan Wu { 110*9067359fSJiri Kosina del_timer_sync(&led_cdev->blink_timer); 11143786482SFabio Baltieri led_cdev->blink_delay_on = 0; 11243786482SFabio Baltieri led_cdev->blink_delay_off = 0; 113d23a22a7SFabio Baltieri } 114d23a22a7SFabio Baltieri EXPORT_SYMBOL_GPL(led_stop_software_blink); 115d23a22a7SFabio Baltieri 116d23a22a7SFabio Baltieri void led_set_brightness(struct led_classdev *led_cdev, 117d23a22a7SFabio Baltieri enum led_brightness brightness) 118d23a22a7SFabio Baltieri { 119*9067359fSJiri Kosina /* delay brightness setting if need to stop soft-blink timer */ 120d23a22a7SFabio Baltieri if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) { 121d23a22a7SFabio Baltieri led_cdev->delayed_set_value = brightness; 122d23a22a7SFabio Baltieri schedule_work(&led_cdev->set_brightness_work); 123d23a22a7SFabio Baltieri return; 124d23a22a7SFabio Baltieri } 12543786482SFabio Baltieri 1260da3e65bSShuah Khan __led_set_brightness(led_cdev, brightness); 127a403d930SBryan Wu } 12819cd67e2SShuah Khan EXPORT_SYMBOL(led_set_brightness); 129