summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJacek Anaszewski <j.anaszewski@samsung.com>2015-10-07 11:10:39 +0200
committerJacek Anaszewski <j.anaszewski@samsung.com>2016-01-04 09:57:30 +0100
commitf1e80c07416adacc9ba1d9c5a4635c27b571f0df (patch)
treee5179b1e484e98a26e4dbbe4e687cfb4b2b3e352 /drivers
parent2806e2ff489975eb40eb5b363a689716e78fd116 (diff)
leds: core: Add two new LED_BLINK_ flags
This patch adds LED_BLINK_BRIGHTNESS_CHANGE flag to indicate that blink brightness has changed, and LED_BLINK_DISABLE flag to indicate that blinking deactivation has been requested. In order to use the flags led_timer_function and set_brightness_delayed callbacks as well as led_set_brightness() function are being modified. The main goal of these modifications is to prepare set_brightness_work for extension of the scope of its responsibilities. Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com> Acked-by: Pavel Machek <pavel@ucw.cz> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/leds/led-core.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index ee9309e2ca82..7cf59243e0ef 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -44,18 +44,18 @@ static void led_timer_function(unsigned long data)
brightness = led_get_brightness(led_cdev);
if (!brightness) {
/* Time to switch the LED on. */
- if (led_cdev->delayed_set_value) {
- led_cdev->blink_brightness =
- led_cdev->delayed_set_value;
- led_cdev->delayed_set_value = 0;
- }
brightness = led_cdev->blink_brightness;
delay = led_cdev->blink_delay_on;
} else {
/* Store the current brightness value to be able
* to restore it when the delay_off period is over.
+ * Do it only if there is no pending blink brightness
+ * change, to avoid overwriting the new value.
*/
- led_cdev->blink_brightness = brightness;
+ if (!(led_cdev->flags & LED_BLINK_BRIGHTNESS_CHANGE))
+ led_cdev->blink_brightness = brightness;
+ else
+ led_cdev->flags &= ~LED_BLINK_BRIGHTNESS_CHANGE;
brightness = LED_OFF;
delay = led_cdev->blink_delay_off;
}
@@ -84,7 +84,11 @@ static void set_brightness_delayed(struct work_struct *ws)
struct led_classdev *led_cdev =
container_of(ws, struct led_classdev, set_brightness_work);
- led_stop_software_blink(led_cdev);
+ if (led_cdev->flags & LED_BLINK_DISABLE) {
+ led_cdev->delayed_set_value = LED_OFF;
+ led_stop_software_blink(led_cdev);
+ led_cdev->flags &= ~LED_BLINK_DISABLE;
+ }
led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
}
@@ -192,11 +196,23 @@ void led_set_brightness(struct led_classdev *led_cdev,
{
int ret = 0;
- /* delay brightness if soft-blink is active */
+ /*
+ * In case blinking is on delay brightness setting
+ * until the next timer tick.
+ */
if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
- led_cdev->delayed_set_value = brightness;
- if (brightness == LED_OFF)
+ /*
+ * If we need to disable soft blinking delegate this to the
+ * work queue task to avoid problems in case we are called
+ * from hard irq context.
+ */
+ if (brightness == LED_OFF) {
+ led_cdev->flags |= LED_BLINK_DISABLE;
schedule_work(&led_cdev->set_brightness_work);
+ } else {
+ led_cdev->flags |= LED_BLINK_BRIGHTNESS_CHANGE;
+ led_cdev->blink_brightness = brightness;
+ }
return;
}