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

leds: lp5521/5523: Fix multiple engine usage bug

Whenever the engine is loaded by the user-application, the operation mode is
reset first. But it has a problem in case of multiple engine used because
previous engine settings are cleared.
The driver should update not whole 8bits but each engine bit by masking.

On the other hands, whole engines should be reset when the driver is unloaded
and on initializing the LP5523 driver.
So, new functions are used for this handling - lp5521/5523_stop_all_engines().

Cc: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Milo Kim <milo.kim@ti.com>
Signed-off-by: Bryan Wu <cooloney@gmail.com>

authored by

Milo Kim and committed by
Bryan Wu
28c9266b 1f431afd

+33 -5
+16 -2
drivers/leds/leds-lp5521.c
··· 152 152 lp5521_wait_opmode_done(); 153 153 } 154 154 155 - static void lp5521_stop_engine(struct lp55xx_chip *chip) 155 + static void lp5521_stop_all_engines(struct lp55xx_chip *chip) 156 156 { 157 157 lp55xx_write(chip, LP5521_REG_OP_MODE, 0); 158 + lp5521_wait_opmode_done(); 159 + } 160 + 161 + static void lp5521_stop_engine(struct lp55xx_chip *chip) 162 + { 163 + enum lp55xx_engine_index idx = chip->engine_idx; 164 + u8 mask[] = { 165 + [LP55XX_ENGINE_1] = LP5521_MODE_R_M, 166 + [LP55XX_ENGINE_2] = LP5521_MODE_G_M, 167 + [LP55XX_ENGINE_3] = LP5521_MODE_B_M, 168 + }; 169 + 170 + lp55xx_update_bits(chip, LP5521_REG_OP_MODE, mask[idx], 0); 171 + 158 172 lp5521_wait_opmode_done(); 159 173 } 160 174 ··· 582 568 struct lp55xx_led *led = i2c_get_clientdata(client); 583 569 struct lp55xx_chip *chip = led->chip; 584 570 585 - lp5521_stop_engine(chip); 571 + lp5521_stop_all_engines(chip); 586 572 lp55xx_unregister_sysfs(chip); 587 573 lp55xx_unregister_leds(led, chip); 588 574 lp55xx_deinit_device(chip);
+17 -3
drivers/leds/leds-lp5523.c
··· 187 187 lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, page_sel[idx]); 188 188 } 189 189 190 - static void lp5523_stop_engine(struct lp55xx_chip *chip) 190 + static void lp5523_stop_all_engines(struct lp55xx_chip *chip) 191 191 { 192 192 lp55xx_write(chip, LP5523_REG_OP_MODE, 0); 193 + lp5523_wait_opmode_done(); 194 + } 195 + 196 + static void lp5523_stop_engine(struct lp55xx_chip *chip) 197 + { 198 + enum lp55xx_engine_index idx = chip->engine_idx; 199 + u8 mask[] = { 200 + [LP55XX_ENGINE_1] = LP5523_MODE_ENG1_M, 201 + [LP55XX_ENGINE_2] = LP5523_MODE_ENG2_M, 202 + [LP55XX_ENGINE_3] = LP5523_MODE_ENG3_M, 203 + }; 204 + 205 + lp55xx_update_bits(chip, LP5523_REG_OP_MODE, mask[idx], 0); 206 + 193 207 lp5523_wait_opmode_done(); 194 208 } 195 209 ··· 317 303 } 318 304 319 305 out: 320 - lp5523_stop_engine(chip); 306 + lp5523_stop_all_engines(chip); 321 307 return ret; 322 308 } 323 309 ··· 792 778 struct lp55xx_led *led = i2c_get_clientdata(client); 793 779 struct lp55xx_chip *chip = led->chip; 794 780 795 - lp5523_stop_engine(chip); 781 + lp5523_stop_all_engines(chip); 796 782 lp55xx_unregister_sysfs(chip); 797 783 lp55xx_unregister_leds(led, chip); 798 784 lp55xx_deinit_device(chip);