summary refs log tree commit diff
path: root/drivers/leds/led-core.c
diff options
context:
space:
mode:
authorFabio Baltieri <fabio.baltieri@gmail.com>2012-05-27 07:19:22 +0800
committerBryan Wu <bryan.wu@canonical.com>2012-07-24 07:52:34 +0800
commit5bb629c504394f4d42c53a25d75ccb02a393f92f (patch)
treec504fb776de83b95045d3274cd7bc82cee0bc983 /drivers/leds/led-core.c
parenteb202621f8c0fb264a35e1b35fc00bdb3114a897 (diff)
downloadlinux-5bb629c504394f4d42c53a25d75ccb02a393f92f.tar.gz
leds: add oneshot blink functions
Add two new functions, led_blink_set_oneshot and
led_trigger_blink_oneshot, to be used by triggers for one-shot blink of
led devices.

This is implemented extending the existing software-blink code, and uses
the same timer and handler function.

The behavior of the code is to do a blink-on, blink-off sequence when
the function is called, ignoring other calls until the sequence is
completed so that the leds keep blinking at constant rate if the
functions are called repeatedly.

This is meant to be used by drivers which needs to trigger on sporadic
event, but doesn't have clear busy/idle trigger points.

After the blink sequence the led remains off. This behavior can be
inverted setting the "invert" argument, which blink the led off, than on
and leave the led on after the sequence.

(bryan.wu@canonical.com: rebase to commit 'leds: don't disable blinking
when writing the same value to delay_on or delay_off')

Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com>
Acked-by: Shuah Khan <shuahkhan@gmail.com>
Signed-off-by: Bryan Wu <bryan.wu@canonical.com>
Diffstat (limited to 'drivers/leds/led-core.c')
-rw-r--r--drivers/leds/led-core.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index d65353d8d3fc..a6f4d910ca08 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -27,7 +27,6 @@ EXPORT_SYMBOL_GPL(leds_list);
 static void led_stop_software_blink(struct led_classdev *led_cdev)
 {
 	/* deactivate previous settings */
-	del_timer_sync(&led_cdev->blink_timer);
 	led_cdev->blink_delay_on = 0;
 	led_cdev->blink_delay_off = 0;
 }
@@ -61,13 +60,12 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
 }
 
 
-void led_blink_set(struct led_classdev *led_cdev,
-		   unsigned long *delay_on,
-		   unsigned long *delay_off)
+void led_blink_setup(struct led_classdev *led_cdev,
+		     unsigned long *delay_on,
+		     unsigned long *delay_off)
 {
-	del_timer_sync(&led_cdev->blink_timer);
-
-	if (led_cdev->blink_set &&
+	if (!(led_cdev->flags & LED_BLINK_ONESHOT) &&
+	    led_cdev->blink_set &&
 	    !led_cdev->blink_set(led_cdev, delay_on, delay_off))
 		return;
 
@@ -77,8 +75,41 @@ void led_blink_set(struct led_classdev *led_cdev,
 
 	led_set_software_blink(led_cdev, *delay_on, *delay_off);
 }
+
+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);
+}
 EXPORT_SYMBOL(led_blink_set);
 
+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);
+
 void led_brightness_set(struct led_classdev *led_cdev,
 			enum led_brightness brightness)
 {