diff options
author | Álvaro Fernández Rojas <noltari@gmail.com> | 2015-12-16 15:13:48 -0500 |
---|---|---|
committer | Jacek Anaszewski <j.anaszewski@samsung.com> | 2016-01-04 03:57:40 -0500 |
commit | 1b85a5a5ef34a64c5c5edece1704bde62208f002 (patch) | |
tree | da22793cc5dd1124f737d07896b4b14f57cdb142 | |
parent | 6e636a0a28ffb0a504ccda5146411b219a74cc7f (diff) |
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>
-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, | |||
140 | spin_unlock_irqrestore(led->lock, flags); | 140 | spin_unlock_irqrestore(led->lock, flags); |
141 | } | 141 | } |
142 | 142 | ||
143 | static unsigned long bcm6328_blink_delay(unsigned long delay) | ||
144 | { | ||
145 | unsigned long bcm6328_delay; | ||
146 | |||
147 | bcm6328_delay = delay + BCM6328_LED_INTERVAL_MS / 2; | ||
148 | bcm6328_delay = bcm6328_delay / BCM6328_LED_INTERVAL_MS; | ||
149 | if (bcm6328_delay == 0) | ||
150 | bcm6328_delay = 1; | ||
151 | |||
152 | return bcm6328_delay; | ||
153 | } | ||
154 | |||
143 | static int bcm6328_blink_set(struct led_classdev *led_cdev, | 155 | static int bcm6328_blink_set(struct led_classdev *led_cdev, |
144 | unsigned long *delay_on, unsigned long *delay_off) | 156 | unsigned long *delay_on, unsigned long *delay_off) |
145 | { | 157 | { |
@@ -153,16 +165,14 @@ static int bcm6328_blink_set(struct led_classdev *led_cdev, | |||
153 | if (!*delay_off) | 165 | if (!*delay_off) |
154 | *delay_off = BCM6328_LED_DEF_DELAY; | 166 | *delay_off = BCM6328_LED_DEF_DELAY; |
155 | 167 | ||
156 | if (*delay_on != *delay_off) { | 168 | delay = bcm6328_blink_delay(*delay_on); |
169 | if (delay != bcm6328_blink_delay(*delay_off)) { | ||
157 | dev_dbg(led_cdev->dev, | 170 | dev_dbg(led_cdev->dev, |
158 | "fallback to soft blinking (delay_on != delay_off)\n"); | 171 | "fallback to soft blinking (delay_on != delay_off)\n"); |
159 | return -EINVAL; | 172 | return -EINVAL; |
160 | } | 173 | } |
161 | 174 | ||
162 | delay = *delay_on / BCM6328_LED_INTERVAL_MS; | 175 | if (delay > BCM6328_LED_INTV_MASK) { |
163 | if (delay == 0) { | ||
164 | delay = 1; | ||
165 | } else if (delay > BCM6328_LED_INTV_MASK) { | ||
166 | dev_dbg(led_cdev->dev, | 176 | dev_dbg(led_cdev->dev, |
167 | "fallback to soft blinking (delay > %ums)\n", | 177 | "fallback to soft blinking (delay > %ums)\n", |
168 | BCM6328_LED_INTV_MASK * BCM6328_LED_INTERVAL_MS); | 178 | BCM6328_LED_INTV_MASK * BCM6328_LED_INTERVAL_MS); |