diff options
author | Jacek Anaszewski <j.anaszewski@samsung.com> | 2015-10-07 11:10:39 +0200 |
---|---|---|
committer | Jacek Anaszewski <j.anaszewski@samsung.com> | 2016-01-04 09:57:30 +0100 |
commit | f1e80c07416adacc9ba1d9c5a4635c27b571f0df (patch) | |
tree | e5179b1e484e98a26e4dbbe4e687cfb4b2b3e352 /drivers | |
parent | 2806e2ff489975eb40eb5b363a689716e78fd116 (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.c | 36 |
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; } |