2006-03-31 02:31:04 -08:00
/*
* LED Class Core
*
* Copyright 2005 - 2006 Openedhand Ltd .
*
* Author : Richard Purdie < rpurdie @ openedhand . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
*/
# include <linux/kernel.h>
# include <linux/list.h>
# include <linux/module.h>
2007-12-31 23:09:44 +00:00
# include <linux/rwsem.h>
2006-03-31 02:31:04 -08:00
# include <linux/leds.h>
# include "leds.h"
2007-12-31 23:09:44 +00:00
DECLARE_RWSEM ( leds_list_lock ) ;
2008-03-09 20:59:57 +00:00
EXPORT_SYMBOL_GPL ( leds_list_lock ) ;
2006-03-31 02:31:04 -08:00
2008-03-09 20:59:57 +00:00
LIST_HEAD ( leds_list ) ;
2006-03-31 02:31:04 -08:00
EXPORT_SYMBOL_GPL ( leds_list ) ;
2012-03-23 15:02:14 -07:00
static void led_set_software_blink ( struct led_classdev * led_cdev ,
unsigned long delay_on ,
unsigned long delay_off )
{
int current_brightness ;
current_brightness = led_get_brightness ( led_cdev ) ;
if ( current_brightness )
led_cdev - > blink_brightness = current_brightness ;
if ( ! led_cdev - > blink_brightness )
led_cdev - > blink_brightness = led_cdev - > max_brightness ;
led_cdev - > blink_delay_on = delay_on ;
led_cdev - > blink_delay_off = delay_off ;
/* never on - don't blink */
if ( ! delay_on )
return ;
/* never off - just set to brightness */
if ( ! delay_off ) {
2012-06-13 10:01:37 +08:00
__led_set_brightness ( led_cdev , led_cdev - > blink_brightness ) ;
2012-03-23 15:02:14 -07:00
return ;
}
mod_timer ( & led_cdev - > blink_timer , jiffies + 1 ) ;
}
2012-06-15 22:15:27 +08:00
static void led_blink_setup ( struct led_classdev * led_cdev ,
2012-05-27 07:19:22 +08:00
unsigned long * delay_on ,
unsigned long * delay_off )
2012-03-23 15:02:14 -07:00
{
2012-05-27 07:19:22 +08:00
if ( ! ( led_cdev - > flags & LED_BLINK_ONESHOT ) & &
led_cdev - > blink_set & &
2012-03-23 15:02:14 -07:00
! led_cdev - > blink_set ( led_cdev , delay_on , delay_off ) )
return ;
/* blink with 1 Hz as default if nothing specified */
if ( ! * delay_on & & ! * delay_off )
* delay_on = * delay_off = 500 ;
led_set_software_blink ( led_cdev , * delay_on , * delay_off ) ;
}
2012-05-27 07:19:22 +08:00
void led_blink_set ( struct led_classdev * led_cdev ,
unsigned long * delay_on ,
unsigned long * delay_off )
{
del_timer_sync ( & led_cdev - > blink_timer ) ;
led_cdev - > flags & = ~ LED_BLINK_ONESHOT ;
led_cdev - > flags & = ~ LED_BLINK_ONESHOT_STOP ;
led_blink_setup ( led_cdev , delay_on , delay_off ) ;
}
2012-03-23 15:02:14 -07:00
EXPORT_SYMBOL ( led_blink_set ) ;
2012-05-27 07:19:22 +08:00
void led_blink_set_oneshot ( struct led_classdev * led_cdev ,
unsigned long * delay_on ,
unsigned long * delay_off ,
int invert )
{
if ( ( led_cdev - > flags & LED_BLINK_ONESHOT ) & &
timer_pending ( & led_cdev - > blink_timer ) )
return ;
led_cdev - > flags | = LED_BLINK_ONESHOT ;
led_cdev - > flags & = ~ LED_BLINK_ONESHOT_STOP ;
if ( invert )
led_cdev - > flags | = LED_BLINK_INVERT ;
else
led_cdev - > flags & = ~ LED_BLINK_INVERT ;
led_blink_setup ( led_cdev , delay_on , delay_off ) ;
}
EXPORT_SYMBOL ( led_blink_set_oneshot ) ;
2012-08-15 21:44:34 +08:00
void led_stop_software_blink ( struct led_classdev * led_cdev )
2012-03-23 15:02:14 -07:00
{
2012-06-07 03:12:34 +08:00
del_timer_sync ( & led_cdev - > blink_timer ) ;
led_cdev - > blink_delay_on = 0 ;
led_cdev - > blink_delay_off = 0 ;
2012-08-15 21:44:34 +08:00
}
EXPORT_SYMBOL_GPL ( led_stop_software_blink ) ;
void led_set_brightness ( struct led_classdev * led_cdev ,
enum led_brightness brightness )
{
/* delay brightness setting if need to stop soft-blink timer */
if ( led_cdev - > blink_delay_on | | led_cdev - > blink_delay_off ) {
led_cdev - > delayed_set_value = brightness ;
schedule_work ( & led_cdev - > set_brightness_work ) ;
return ;
}
2012-06-07 03:12:34 +08:00
2012-06-13 10:01:37 +08:00
__led_set_brightness ( led_cdev , brightness ) ;
2012-03-23 15:02:14 -07:00
}
2012-06-14 04:34:30 +08:00
EXPORT_SYMBOL ( led_set_brightness ) ;