Skip to content

Commit 31379a5

Browse files
Ansuellag-linaro
authored andcommitted
leds: leds-lp55xx: Generalize update_program_memory function
LED Driver based on lp55xx all use the same logic to write memory in SMEM. The only difference is that legacy chip doesn't support pages and have the engine regs one after another. To handle this apply the same logic used for load_engine also for update_program_memory. Introduce a new config in device_config, base_prog. For LED chip that doesn't support pages, offset this values of 32 for each engine. Update all lp55xx based LED driver to use this new function and define all the required bits. Suggested-by: Lee Jones <[email protected]> Signed-off-by: Christian Marangi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Lee Jones <[email protected]>
1 parent 42a9eaa commit 31379a5

File tree

6 files changed

+79
-198
lines changed

6 files changed

+79
-198
lines changed

drivers/leds/leds-lp5521.c

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -146,55 +146,6 @@ static void lp5521_run_engine(struct lp55xx_chip *chip, bool start)
146146
lp5521_wait_enable_done();
147147
}
148148

149-
static int lp5521_update_program_memory(struct lp55xx_chip *chip,
150-
const u8 *data, size_t size)
151-
{
152-
enum lp55xx_engine_index idx = chip->engine_idx;
153-
u8 pattern[LP5521_PROGRAM_LENGTH] = {0};
154-
static const u8 addr[] = {
155-
[LP55XX_ENGINE_1] = LP5521_REG_R_PROG_MEM,
156-
[LP55XX_ENGINE_2] = LP5521_REG_G_PROG_MEM,
157-
[LP55XX_ENGINE_3] = LP5521_REG_B_PROG_MEM,
158-
};
159-
unsigned cmd;
160-
char c[3];
161-
int nrchars;
162-
int ret;
163-
int offset = 0;
164-
int i = 0;
165-
166-
while ((offset < size - 1) && (i < LP5521_PROGRAM_LENGTH)) {
167-
/* separate sscanfs because length is working only for %s */
168-
ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
169-
if (ret != 1)
170-
goto err;
171-
172-
ret = sscanf(c, "%2x", &cmd);
173-
if (ret != 1)
174-
goto err;
175-
176-
pattern[i] = (u8)cmd;
177-
offset += nrchars;
178-
i++;
179-
}
180-
181-
/* Each instruction is 16bit long. Check that length is even */
182-
if (i % 2)
183-
goto err;
184-
185-
for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) {
186-
ret = lp55xx_write(chip, addr[idx] + i, pattern[i]);
187-
if (ret)
188-
return -EINVAL;
189-
}
190-
191-
return size;
192-
193-
err:
194-
dev_err(&chip->cl->dev, "wrong pattern format\n");
195-
return -EINVAL;
196-
}
197-
198149
static void lp5521_firmware_loaded(struct lp55xx_chip *chip)
199150
{
200151
const struct firmware *fw = chip->fw;
@@ -212,7 +163,7 @@ static void lp5521_firmware_loaded(struct lp55xx_chip *chip)
212163
*/
213164

214165
lp55xx_load_engine(chip);
215-
lp5521_update_program_memory(chip, fw->data, fw->size);
166+
lp55xx_update_program_memory(chip, fw->data, fw->size);
216167
}
217168

218169
static int lp5521_post_init_device(struct lp55xx_chip *chip)
@@ -389,7 +340,7 @@ static ssize_t store_engine_load(struct device *dev,
389340

390341
chip->engine_idx = nr;
391342
lp55xx_load_engine(chip);
392-
ret = lp5521_update_program_memory(chip, buf, len);
343+
ret = lp55xx_update_program_memory(chip, buf, len);
393344

394345
mutex_unlock(&chip->lock);
395346

@@ -454,6 +405,9 @@ static struct lp55xx_device_config lp5521_cfg = {
454405
.addr = LP5521_REG_ENABLE,
455406
.val = LP5521_ENABLE_DEFAULT,
456407
},
408+
.prog_mem_base = {
409+
.addr = LP5521_REG_R_PROG_MEM,
410+
},
457411
.max_channel = LP5521_MAX_LEDS,
458412
.post_init_device = lp5521_post_init_device,
459413
.brightness_fn = lp5521_led_brightness,

drivers/leds/leds-lp5523.c

Lines changed: 5 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -254,49 +254,6 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
254254
return ret;
255255
}
256256

257-
static int lp5523_update_program_memory(struct lp55xx_chip *chip,
258-
const u8 *data, size_t size)
259-
{
260-
u8 pattern[LP5523_PROGRAM_LENGTH] = {0};
261-
unsigned int cmd;
262-
char c[3];
263-
int nrchars;
264-
int ret;
265-
int offset = 0;
266-
int i = 0;
267-
268-
while ((offset < size - 1) && (i < LP5523_PROGRAM_LENGTH)) {
269-
/* separate sscanfs because length is working only for %s */
270-
ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
271-
if (ret != 1)
272-
goto err;
273-
274-
ret = sscanf(c, "%2x", &cmd);
275-
if (ret != 1)
276-
goto err;
277-
278-
pattern[i] = (u8)cmd;
279-
offset += nrchars;
280-
i++;
281-
}
282-
283-
/* Each instruction is 16bit long. Check that length is even */
284-
if (i % 2)
285-
goto err;
286-
287-
for (i = 0; i < LP5523_PROGRAM_LENGTH; i++) {
288-
ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + i, pattern[i]);
289-
if (ret)
290-
return -EINVAL;
291-
}
292-
293-
return size;
294-
295-
err:
296-
dev_err(&chip->cl->dev, "wrong pattern format\n");
297-
return -EINVAL;
298-
}
299-
300257
static void lp5523_firmware_loaded(struct lp55xx_chip *chip)
301258
{
302259
const struct firmware *fw = chip->fw;
@@ -314,7 +271,7 @@ static void lp5523_firmware_loaded(struct lp55xx_chip *chip)
314271
*/
315272

316273
lp55xx_load_engine(chip);
317-
lp5523_update_program_memory(chip, fw->data, fw->size);
274+
lp55xx_update_program_memory(chip, fw->data, fw->size);
318275
}
319276

320277
static ssize_t show_engine_mode(struct device *dev,
@@ -496,7 +453,7 @@ static ssize_t store_engine_load(struct device *dev,
496453

497454
chip->engine_idx = nr;
498455
lp55xx_load_engine(chip);
499-
ret = lp5523_update_program_memory(chip, buf, len);
456+
ret = lp55xx_update_program_memory(chip, buf, len);
500457

501458
mutex_unlock(&chip->lock);
502459

@@ -819,6 +776,9 @@ static struct lp55xx_device_config lp5523_cfg = {
819776
.addr = LP5523_REG_ENABLE,
820777
.val = LP5523_ENABLE,
821778
},
779+
.prog_mem_base = {
780+
.addr = LP5523_REG_PROG_MEM,
781+
},
822782
.pages_per_engine = LP5523_PAGES_PER_ENGINE,
823783
.max_channel = LP5523_MAX_LEDS,
824784
.post_init_device = lp5523_post_init_device,

drivers/leds/leds-lp5562.c

Lines changed: 4 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -144,59 +144,6 @@ static void lp5562_run_engine(struct lp55xx_chip *chip, bool start)
144144
lp5562_wait_enable_done();
145145
}
146146

147-
static int lp5562_update_firmware(struct lp55xx_chip *chip,
148-
const u8 *data, size_t size)
149-
{
150-
enum lp55xx_engine_index idx = chip->engine_idx;
151-
u8 pattern[LP5562_PROGRAM_LENGTH] = {0};
152-
static const u8 addr[] = {
153-
[LP55XX_ENGINE_1] = LP5562_REG_PROG_MEM_ENG1,
154-
[LP55XX_ENGINE_2] = LP5562_REG_PROG_MEM_ENG2,
155-
[LP55XX_ENGINE_3] = LP5562_REG_PROG_MEM_ENG3,
156-
};
157-
unsigned cmd;
158-
char c[3];
159-
int program_size;
160-
int nrchars;
161-
int offset = 0;
162-
int ret;
163-
int i;
164-
165-
/* clear program memory before updating */
166-
for (i = 0; i < LP5562_PROGRAM_LENGTH; i++)
167-
lp55xx_write(chip, addr[idx] + i, 0);
168-
169-
i = 0;
170-
while ((offset < size - 1) && (i < LP5562_PROGRAM_LENGTH)) {
171-
/* separate sscanfs because length is working only for %s */
172-
ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
173-
if (ret != 1)
174-
goto err;
175-
176-
ret = sscanf(c, "%2x", &cmd);
177-
if (ret != 1)
178-
goto err;
179-
180-
pattern[i] = (u8)cmd;
181-
offset += nrchars;
182-
i++;
183-
}
184-
185-
/* Each instruction is 16bit long. Check that length is even */
186-
if (i % 2)
187-
goto err;
188-
189-
program_size = i;
190-
for (i = 0; i < program_size; i++)
191-
lp55xx_write(chip, addr[idx] + i, pattern[i]);
192-
193-
return 0;
194-
195-
err:
196-
dev_err(&chip->cl->dev, "wrong pattern format\n");
197-
return -EINVAL;
198-
}
199-
200147
static void lp5562_firmware_loaded(struct lp55xx_chip *chip)
201148
{
202149
const struct firmware *fw = chip->fw;
@@ -218,7 +165,7 @@ static void lp5562_firmware_loaded(struct lp55xx_chip *chip)
218165
*/
219166

220167
lp55xx_load_engine(chip);
221-
lp5562_update_firmware(chip, fw->data, fw->size);
168+
lp55xx_update_program_memory(chip, fw->data, fw->size);
222169
}
223170

224171
static int lp5562_post_init_device(struct lp55xx_chip *chip)
@@ -450,6 +397,9 @@ static struct lp55xx_device_config lp5562_cfg = {
450397
.addr = LP5562_REG_ENABLE,
451398
.val = LP5562_ENABLE_DEFAULT,
452399
},
400+
.prog_mem_base = {
401+
.addr = LP5562_REG_PROG_MEM_ENG1,
402+
},
453403
.post_init_device = lp5562_post_init_device,
454404
.set_led_current = lp5562_set_led_current,
455405
.brightness_fn = lp5562_led_brightness,

drivers/leds/leds-lp55xx-common.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
/* OP MODE require at least 153 us to clear regs */
2828
#define LP55XX_CMD_SLEEP 200
2929

30+
#define LP55xx_PROGRAM_LENGTH 32
31+
3032
/*
3133
* Program Memory Operations
3234
* Same Mask for each engine for both mode and exec
@@ -160,6 +162,61 @@ int lp55xx_run_engine_common(struct lp55xx_chip *chip)
160162
}
161163
EXPORT_SYMBOL_GPL(lp55xx_run_engine_common);
162164

165+
int lp55xx_update_program_memory(struct lp55xx_chip *chip,
166+
const u8 *data, size_t size)
167+
{
168+
enum lp55xx_engine_index idx = chip->engine_idx;
169+
const struct lp55xx_device_config *cfg = chip->cfg;
170+
u8 pattern[LP55xx_PROGRAM_LENGTH] = { };
171+
u8 start_addr = cfg->prog_mem_base.addr;
172+
int i = 0, offset = 0;
173+
int ret;
174+
175+
while ((offset < size - 1) && (i < LP55xx_PROGRAM_LENGTH)) {
176+
unsigned int cmd;
177+
int nrchars;
178+
char c[3];
179+
180+
/* separate sscanfs because length is working only for %s */
181+
ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
182+
if (ret != 1)
183+
goto err;
184+
185+
ret = sscanf(c, "%2x", &cmd);
186+
if (ret != 1)
187+
goto err;
188+
189+
pattern[i] = (u8)cmd;
190+
offset += nrchars;
191+
i++;
192+
}
193+
194+
/* Each instruction is 16bit long. Check that length is even */
195+
if (i % 2)
196+
goto err;
197+
198+
/*
199+
* For legacy LED chip with no page support, engine base address are
200+
* one after another at offset of 32.
201+
* For LED chip that support page, PAGE is already set in load_engine.
202+
*/
203+
if (!cfg->pages_per_engine)
204+
start_addr += LP55xx_PROGRAM_LENGTH * idx;
205+
206+
for (i = 0; i < LP55xx_PROGRAM_LENGTH; i++) {
207+
ret = lp55xx_write(chip, start_addr + i, pattern[i]);
208+
if (ret)
209+
return -EINVAL;
210+
}
211+
212+
return size;
213+
214+
err:
215+
dev_err(&chip->cl->dev, "wrong pattern format\n");
216+
return -EINVAL;
217+
}
218+
EXPORT_SYMBOL_GPL(lp55xx_update_program_memory);
219+
163220
static void lp55xx_reset_device(struct lp55xx_chip *chip)
164221
{
165222
const struct lp55xx_device_config *cfg = chip->cfg;

drivers/leds/leds-lp55xx-common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct lp55xx_reg {
9999
* (if not supported 153 us sleep)
100100
* @reset : Chip specific reset command
101101
* @enable : Chip specific enable command
102+
* @prog_mem_base : Chip specific base reg address for chip SMEM programming
102103
* @pages_per_engine : Assigned pages for each engine
103104
* (if not set chip doesn't support pages)
104105
* @max_channel : Maximum number of channels
@@ -116,6 +117,7 @@ struct lp55xx_device_config {
116117
const struct lp55xx_reg engine_busy; /* addr, mask */
117118
const struct lp55xx_reg reset;
118119
const struct lp55xx_reg enable;
120+
const struct lp55xx_reg prog_mem_base;
119121
const int pages_per_engine;
120122
const int max_channel;
121123

@@ -208,6 +210,8 @@ extern bool lp55xx_is_extclk_used(struct lp55xx_chip *chip);
208210
extern void lp55xx_stop_all_engine(struct lp55xx_chip *chip);
209211
extern void lp55xx_load_engine(struct lp55xx_chip *chip);
210212
extern int lp55xx_run_engine_common(struct lp55xx_chip *chip);
213+
extern int lp55xx_update_program_memory(struct lp55xx_chip *chip,
214+
const u8 *data, size_t size);
211215

212216
/* common probe/remove function */
213217
extern int lp55xx_probe(struct i2c_client *client);

0 commit comments

Comments
 (0)