diff options
Diffstat (limited to 'drivers/leds/leds-lp5521.c')
-rw-r--r-- | drivers/leds/leds-lp5521.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 3782f31f06d2..33facd0c45d1 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c | |||
@@ -125,11 +125,22 @@ struct lp5521_chip { | |||
125 | u8 num_leds; | 125 | u8 num_leds; |
126 | }; | 126 | }; |
127 | 127 | ||
128 | #define cdev_to_led(c) container_of(c, struct lp5521_led, cdev) | 128 | static inline struct lp5521_led *cdev_to_led(struct led_classdev *cdev) |
129 | #define engine_to_lp5521(eng) container_of((eng), struct lp5521_chip, \ | 129 | { |
130 | engines[(eng)->id - 1]) | 130 | return container_of(cdev, struct lp5521_led, cdev); |
131 | #define led_to_lp5521(led) container_of((led), struct lp5521_chip, \ | 131 | } |
132 | leds[(led)->id]) | 132 | |
133 | static inline struct lp5521_chip *engine_to_lp5521(struct lp5521_engine *engine) | ||
134 | { | ||
135 | return container_of(engine, struct lp5521_chip, | ||
136 | engines[engine->id - 1]); | ||
137 | } | ||
138 | |||
139 | static inline struct lp5521_chip *led_to_lp5521(struct lp5521_led *led) | ||
140 | { | ||
141 | return container_of(led, struct lp5521_chip, | ||
142 | leds[led->id]); | ||
143 | } | ||
133 | 144 | ||
134 | static void lp5521_led_brightness_work(struct work_struct *work); | 145 | static void lp5521_led_brightness_work(struct work_struct *work); |
135 | 146 | ||
@@ -185,14 +196,17 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern) | |||
185 | 196 | ||
186 | /* move current engine to direct mode and remember the state */ | 197 | /* move current engine to direct mode and remember the state */ |
187 | ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT); | 198 | ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT); |
188 | usleep_range(1000, 10000); | 199 | /* Mode change requires min 500 us delay. 1 - 2 ms with margin */ |
200 | usleep_range(1000, 2000); | ||
189 | ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode); | 201 | ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode); |
190 | 202 | ||
191 | /* For loading, all the engines to load mode */ | 203 | /* For loading, all the engines to load mode */ |
192 | lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT); | 204 | lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT); |
193 | usleep_range(1000, 10000); | 205 | /* Mode change requires min 500 us delay. 1 - 2 ms with margin */ |
206 | usleep_range(1000, 2000); | ||
194 | lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_LOAD); | 207 | lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_LOAD); |
195 | usleep_range(1000, 10000); | 208 | /* Mode change requires min 500 us delay. 1 - 2 ms with margin */ |
209 | usleep_range(1000, 2000); | ||
196 | 210 | ||
197 | addr = LP5521_PROG_MEM_BASE + eng->prog_page * LP5521_PROG_MEM_SIZE; | 211 | addr = LP5521_PROG_MEM_BASE + eng->prog_page * LP5521_PROG_MEM_SIZE; |
198 | i2c_smbus_write_i2c_block_data(client, | 212 | i2c_smbus_write_i2c_block_data(client, |
@@ -231,10 +245,6 @@ static int lp5521_configure(struct i2c_client *client, | |||
231 | 245 | ||
232 | lp5521_init_engine(chip, attr_group); | 246 | lp5521_init_engine(chip, attr_group); |
233 | 247 | ||
234 | lp5521_write(client, LP5521_REG_RESET, 0xff); | ||
235 | |||
236 | usleep_range(10000, 20000); | ||
237 | |||
238 | /* Set all PWMs to direct control mode */ | 248 | /* Set all PWMs to direct control mode */ |
239 | ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F); | 249 | ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F); |
240 | 250 | ||
@@ -251,8 +261,8 @@ static int lp5521_configure(struct i2c_client *client, | |||
251 | ret |= lp5521_write(client, LP5521_REG_ENABLE, | 261 | ret |= lp5521_write(client, LP5521_REG_ENABLE, |
252 | LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM | | 262 | LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM | |
253 | LP5521_EXEC_RUN); | 263 | LP5521_EXEC_RUN); |
254 | /* enable takes 500us */ | 264 | /* enable takes 500us. 1 - 2 ms leaves some margin */ |
255 | usleep_range(500, 20000); | 265 | usleep_range(1000, 2000); |
256 | 266 | ||
257 | return ret; | 267 | return ret; |
258 | } | 268 | } |
@@ -305,7 +315,8 @@ static int lp5521_detect(struct i2c_client *client) | |||
305 | LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM); | 315 | LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM); |
306 | if (ret) | 316 | if (ret) |
307 | return ret; | 317 | return ret; |
308 | usleep_range(1000, 10000); | 318 | /* enable takes 500us. 1 - 2 ms leaves some margin */ |
319 | usleep_range(1000, 2000); | ||
309 | ret = lp5521_read(client, LP5521_REG_ENABLE, &buf); | 320 | ret = lp5521_read(client, LP5521_REG_ENABLE, &buf); |
310 | if (ret) | 321 | if (ret) |
311 | return ret; | 322 | return ret; |
@@ -693,11 +704,16 @@ static int lp5521_probe(struct i2c_client *client, | |||
693 | 704 | ||
694 | if (pdata->enable) { | 705 | if (pdata->enable) { |
695 | pdata->enable(0); | 706 | pdata->enable(0); |
696 | usleep_range(1000, 10000); | 707 | usleep_range(1000, 2000); /* Keep enable down at least 1ms */ |
697 | pdata->enable(1); | 708 | pdata->enable(1); |
698 | usleep_range(1000, 10000); /* Spec says min 500us */ | 709 | usleep_range(1000, 2000); /* 500us abs min. */ |
699 | } | 710 | } |
700 | 711 | ||
712 | lp5521_write(client, LP5521_REG_RESET, 0xff); | ||
713 | usleep_range(10000, 20000); /* | ||
714 | * Exact value is not available. 10 - 20ms | ||
715 | * appears to be enough for reset. | ||
716 | */ | ||
701 | ret = lp5521_detect(client); | 717 | ret = lp5521_detect(client); |
702 | 718 | ||
703 | if (ret) { | 719 | if (ret) { |