blob: a6f4d910ca08de5407da089d78cabfb6530a3bec [file] [log] [blame]
Richard Purdiec72a1d62006-03-31 02:31:04 -08001/*
2 * LED Class Core
3 *
4 * Copyright 2005-2006 Openedhand Ltd.
5 *
6 * Author: Richard Purdie <rpurdie@openedhand.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/kernel.h>
15#include <linux/list.h>
16#include <linux/module.h>
Richard Purdie72f8da32007-12-31 23:09:44 +000017#include <linux/rwsem.h>
Richard Purdiec72a1d62006-03-31 02:31:04 -080018#include <linux/leds.h>
19#include "leds.h"
20
Richard Purdie72f8da32007-12-31 23:09:44 +000021DECLARE_RWSEM(leds_list_lock);
Richard Purdiec72a1d62006-03-31 02:31:04 -080022EXPORT_SYMBOL_GPL(leds_list_lock);
Németh Márton4d404fd2008-03-09 20:59:57 +000023
24LIST_HEAD(leds_list);
25EXPORT_SYMBOL_GPL(leds_list);
Bryan Wua403d932012-03-23 15:02:14 -070026
27static void led_stop_software_blink(struct led_classdev *led_cdev)
28{
29 /* deactivate previous settings */
Bryan Wua403d932012-03-23 15:02:14 -070030 led_cdev->blink_delay_on = 0;
31 led_cdev->blink_delay_off = 0;
32}
33
34static void led_set_software_blink(struct led_classdev *led_cdev,
35 unsigned long delay_on,
36 unsigned long delay_off)
37{
38 int current_brightness;
39
40 current_brightness = led_get_brightness(led_cdev);
41 if (current_brightness)
42 led_cdev->blink_brightness = current_brightness;
43 if (!led_cdev->blink_brightness)
44 led_cdev->blink_brightness = led_cdev->max_brightness;
45
Bryan Wua403d932012-03-23 15:02:14 -070046 led_cdev->blink_delay_on = delay_on;
47 led_cdev->blink_delay_off = delay_off;
48
49 /* never on - don't blink */
50 if (!delay_on)
51 return;
52
53 /* never off - just set to brightness */
54 if (!delay_off) {
55 led_set_brightness(led_cdev, led_cdev->blink_brightness);
56 return;
57 }
58
59 mod_timer(&led_cdev->blink_timer, jiffies + 1);
60}
61
62
Fabio Baltieri5bb629c2012-05-27 07:19:22 +080063void led_blink_setup(struct led_classdev *led_cdev,
64 unsigned long *delay_on,
65 unsigned long *delay_off)
Bryan Wua403d932012-03-23 15:02:14 -070066{
Fabio Baltieri5bb629c2012-05-27 07:19:22 +080067 if (!(led_cdev->flags & LED_BLINK_ONESHOT) &&
68 led_cdev->blink_set &&
Bryan Wua403d932012-03-23 15:02:14 -070069 !led_cdev->blink_set(led_cdev, delay_on, delay_off))
70 return;
71
72 /* blink with 1 Hz as default if nothing specified */
73 if (!*delay_on && !*delay_off)
74 *delay_on = *delay_off = 500;
75
76 led_set_software_blink(led_cdev, *delay_on, *delay_off);
77}
Fabio Baltieri5bb629c2012-05-27 07:19:22 +080078
79void led_blink_set(struct led_classdev *led_cdev,
80 unsigned long *delay_on,
81 unsigned long *delay_off)
82{
83 del_timer_sync(&led_cdev->blink_timer);
84
85 led_cdev->flags &= ~LED_BLINK_ONESHOT;
86 led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
87
88 led_blink_setup(led_cdev, delay_on, delay_off);
89}
Bryan Wua403d932012-03-23 15:02:14 -070090EXPORT_SYMBOL(led_blink_set);
91
Fabio Baltieri5bb629c2012-05-27 07:19:22 +080092void led_blink_set_oneshot(struct led_classdev *led_cdev,
93 unsigned long *delay_on,
94 unsigned long *delay_off,
95 int invert)
96{
97 if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
98 timer_pending(&led_cdev->blink_timer))
99 return;
100
101 led_cdev->flags |= LED_BLINK_ONESHOT;
102 led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
103
104 if (invert)
105 led_cdev->flags |= LED_BLINK_INVERT;
106 else
107 led_cdev->flags &= ~LED_BLINK_INVERT;
108
109 led_blink_setup(led_cdev, delay_on, delay_off);
110}
111EXPORT_SYMBOL(led_blink_set_oneshot);
112
Bryan Wua403d932012-03-23 15:02:14 -0700113void led_brightness_set(struct led_classdev *led_cdev,
114 enum led_brightness brightness)
115{
116 led_stop_software_blink(led_cdev);
117 led_cdev->brightness_set(led_cdev, brightness);
118}
119EXPORT_SYMBOL(led_brightness_set);