aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorÁlvaro Fernández Rojas <noltari@gmail.com>2015-12-16 15:13:48 -0500
committerJacek Anaszewski <j.anaszewski@samsung.com>2016-01-04 03:57:40 -0500
commit1b85a5a5ef34a64c5c5edece1704bde62208f002 (patch)
treeda22793cc5dd1124f737d07896b4b14f57cdb142
parent6e636a0a28ffb0a504ccda5146411b219a74cc7f (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.c20
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
143static 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
143static int bcm6328_blink_set(struct led_classdev *led_cdev, 155static 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);