diff options
author | Álvaro Fernández Rojas <noltari@gmail.com> | 2015-12-16 23:13:48 +0300 |
---|---|---|
committer | Jacek Anaszewski <j.anaszewski@samsung.com> | 2016-01-04 11:57:40 +0300 |
commit | 1b85a5a5ef34a64c5c5edece1704bde62208f002 (patch) | |
tree | da22793cc5dd1124f737d07896b4b14f57cdb142 /drivers | |
parent | 6e636a0a28ffb0a504ccda5146411b219a74cc7f (diff) | |
download | linux-1b85a5a5ef34a64c5c5edece1704bde62208f002.tar.xz |
leds: bcm6328: improve blink support
BCM6328 controller has a margin of 20ms per blink step, which means that
we can only set it to 20, 40, 60 ... 1260 ms (0x3f * 20ms).
However, when checking if delay_on == delay_off, we were not considering
the case when the user had set delay_on=20 and delay_off=21, since this
will cause the driver to fallback to software blinking.
This update fixes this issue and improves blink steps by rounding them
in a more sensible way. Now 30-49ms is rounded to 40 ms, and previous
behaviour implied 40-59ms being rounded to 40 ms.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/leds/leds-bcm6328.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c index 47f7c9f310be..1548259297c1 100644 --- a/drivers/leds/leds-bcm6328.c +++ b/drivers/leds/leds-bcm6328.c @@ -140,6 +140,18 @@ static void bcm6328_led_set(struct led_classdev *led_cdev, spin_unlock_irqrestore(led->lock, flags); } +static unsigned long bcm6328_blink_delay(unsigned long delay) +{ + unsigned long bcm6328_delay; + + bcm6328_delay = delay + BCM6328_LED_INTERVAL_MS / 2; + bcm6328_delay = bcm6328_delay / BCM6328_LED_INTERVAL_MS; + if (bcm6328_delay == 0) + bcm6328_delay = 1; + + return bcm6328_delay; +} + static int bcm6328_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { @@ -153,16 +165,14 @@ static int bcm6328_blink_set(struct led_classdev *led_cdev, if (!*delay_off) *delay_off = BCM6328_LED_DEF_DELAY; - if (*delay_on != *delay_off) { + delay = bcm6328_blink_delay(*delay_on); + if (delay != bcm6328_blink_delay(*delay_off)) { dev_dbg(led_cdev->dev, "fallback to soft blinking (delay_on != delay_off)\n"); return -EINVAL; } - delay = *delay_on / BCM6328_LED_INTERVAL_MS; - if (delay == 0) { - delay = 1; - } else if (delay > BCM6328_LED_INTV_MASK) { + if (delay > BCM6328_LED_INTV_MASK) { dev_dbg(led_cdev->dev, "fallback to soft blinking (delay > %ums)\n", BCM6328_LED_INTV_MASK * BCM6328_LED_INTERVAL_MS); |