Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds: pca963x: workaround group blink scaling issue

PCA9632TK part seems to incorrectly blink at ~1.3x of the programmed
rate. This patchset add a nxp,period-scale devicetree property to
adjust for this misconfiguration.

Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>

authored by

Matt Ranostay and committed by
Jacek Anaszewski
35c7d301 ed25e9ca

+18 -3
+3
Documentation/devicetree/bindings/leds/pca963x.txt
··· 7 7 - nxp,totem-pole : use totem pole (push-pull) instead of open-drain (pca9632 defaults 8 8 to open-drain, newer chips to totem pole) 9 9 - nxp,hw-blink : use hardware blinking instead of software blinking 10 + - nxp,period-scale : In some configurations, the chip blinks faster than expected. 11 + This parameter provides a scaling ratio (fixed point, decimal divided 12 + by 1000) to compensate, e.g. 1300=1.3x and 750=0.75x. 10 13 11 14 Each led is represented as a sub-node of the nxp,pca963x device. 12 15
+15 -3
drivers/leds/leds-pca963x.c
··· 59 59 u8 grpfreq; 60 60 u8 ledout_base; 61 61 int n_leds; 62 + unsigned int scaling; 62 63 }; 63 64 64 65 static struct pca963x_chipdef pca963x_chipdefs[] = { ··· 190 189 return pca963x_brightness(pca963x, value); 191 190 } 192 191 192 + static unsigned int pca963x_period_scale(struct pca963x_led *pca963x, 193 + unsigned int val) 194 + { 195 + unsigned int scaling = pca963x->chip->chipdef->scaling; 196 + 197 + return scaling ? DIV_ROUND_CLOSEST(val * scaling, 1000) : val; 198 + } 199 + 193 200 static int pca963x_blink_set(struct led_classdev *led_cdev, 194 201 unsigned long *delay_on, unsigned long *delay_off) 195 202 { ··· 216 207 time_off = 500; 217 208 } 218 209 219 - period = time_on + time_off; 210 + period = pca963x_period_scale(pca963x, time_on + time_off); 220 211 221 212 /* If period not supported by hardware, default to someting sane. */ 222 213 if ((period < PCA963X_BLINK_PERIOD_MIN) || 223 214 (period > PCA963X_BLINK_PERIOD_MAX)) { 224 215 time_on = 500; 225 216 time_off = 500; 226 - period = time_on + time_off; 217 + period = pca963x_period_scale(pca963x, 1000); 227 218 } 228 219 229 220 /* ··· 231 222 * (time_on / period) = (GDC / 256) -> 232 223 * GDC = ((time_on * 256) / period) 233 224 */ 234 - gdc = (time_on * 256) / period; 225 + gdc = (pca963x_period_scale(pca963x, time_on) * 256) / period; 235 226 236 227 /* 237 228 * From manual: period = ((GFRQ + 1) / 24) in seconds. ··· 302 293 pdata->blink_type = PCA963X_HW_BLINK; 303 294 else 304 295 pdata->blink_type = PCA963X_SW_BLINK; 296 + 297 + if (of_property_read_u32(np, "nxp,period-scale", &chip->scaling)) 298 + chip->scaling = 1000; 305 299 306 300 return pdata; 307 301 }