Skip to content

Commit

Permalink
leds: leds-lp55xx: Generalize update_program_memory function
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
Ansuel authored and lag-linaro committed Jun 26, 2024
1 parent 42a9eaa commit 31379a5
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 198 deletions.
56 changes: 5 additions & 51 deletions drivers/leds/leds-lp5521.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,55 +146,6 @@ static void lp5521_run_engine(struct lp55xx_chip *chip, bool start)
lp5521_wait_enable_done();
}

static int lp5521_update_program_memory(struct lp55xx_chip *chip,
const u8 *data, size_t size)
{
enum lp55xx_engine_index idx = chip->engine_idx;
u8 pattern[LP5521_PROGRAM_LENGTH] = {0};
static const u8 addr[] = {
[LP55XX_ENGINE_1] = LP5521_REG_R_PROG_MEM,
[LP55XX_ENGINE_2] = LP5521_REG_G_PROG_MEM,
[LP55XX_ENGINE_3] = LP5521_REG_B_PROG_MEM,
};
unsigned cmd;
char c[3];
int nrchars;
int ret;
int offset = 0;
int i = 0;

while ((offset < size - 1) && (i < LP5521_PROGRAM_LENGTH)) {
/* separate sscanfs because length is working only for %s */
ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
if (ret != 1)
goto err;

ret = sscanf(c, "%2x", &cmd);
if (ret != 1)
goto err;

pattern[i] = (u8)cmd;
offset += nrchars;
i++;
}

/* Each instruction is 16bit long. Check that length is even */
if (i % 2)
goto err;

for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) {
ret = lp55xx_write(chip, addr[idx] + i, pattern[i]);
if (ret)
return -EINVAL;
}

return size;

err:
dev_err(&chip->cl->dev, "wrong pattern format\n");
return -EINVAL;
}

static void lp5521_firmware_loaded(struct lp55xx_chip *chip)
{
const struct firmware *fw = chip->fw;
Expand All @@ -212,7 +163,7 @@ static void lp5521_firmware_loaded(struct lp55xx_chip *chip)
*/

lp55xx_load_engine(chip);
lp5521_update_program_memory(chip, fw->data, fw->size);
lp55xx_update_program_memory(chip, fw->data, fw->size);
}

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

chip->engine_idx = nr;
lp55xx_load_engine(chip);
ret = lp5521_update_program_memory(chip, buf, len);
ret = lp55xx_update_program_memory(chip, buf, len);

mutex_unlock(&chip->lock);

Expand Down Expand Up @@ -454,6 +405,9 @@ static struct lp55xx_device_config lp5521_cfg = {
.addr = LP5521_REG_ENABLE,
.val = LP5521_ENABLE_DEFAULT,
},
.prog_mem_base = {
.addr = LP5521_REG_R_PROG_MEM,
},
.max_channel = LP5521_MAX_LEDS,
.post_init_device = lp5521_post_init_device,
.brightness_fn = lp5521_led_brightness,
Expand Down
50 changes: 5 additions & 45 deletions drivers/leds/leds-lp5523.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,49 +254,6 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
return ret;
}

static int lp5523_update_program_memory(struct lp55xx_chip *chip,
const u8 *data, size_t size)
{
u8 pattern[LP5523_PROGRAM_LENGTH] = {0};
unsigned int cmd;
char c[3];
int nrchars;
int ret;
int offset = 0;
int i = 0;

while ((offset < size - 1) && (i < LP5523_PROGRAM_LENGTH)) {
/* separate sscanfs because length is working only for %s */
ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
if (ret != 1)
goto err;

ret = sscanf(c, "%2x", &cmd);
if (ret != 1)
goto err;

pattern[i] = (u8)cmd;
offset += nrchars;
i++;
}

/* Each instruction is 16bit long. Check that length is even */
if (i % 2)
goto err;

for (i = 0; i < LP5523_PROGRAM_LENGTH; i++) {
ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + i, pattern[i]);
if (ret)
return -EINVAL;
}

return size;

err:
dev_err(&chip->cl->dev, "wrong pattern format\n");
return -EINVAL;
}

static void lp5523_firmware_loaded(struct lp55xx_chip *chip)
{
const struct firmware *fw = chip->fw;
Expand All @@ -314,7 +271,7 @@ static void lp5523_firmware_loaded(struct lp55xx_chip *chip)
*/

lp55xx_load_engine(chip);
lp5523_update_program_memory(chip, fw->data, fw->size);
lp55xx_update_program_memory(chip, fw->data, fw->size);
}

static ssize_t show_engine_mode(struct device *dev,
Expand Down Expand Up @@ -496,7 +453,7 @@ static ssize_t store_engine_load(struct device *dev,

chip->engine_idx = nr;
lp55xx_load_engine(chip);
ret = lp5523_update_program_memory(chip, buf, len);
ret = lp55xx_update_program_memory(chip, buf, len);

mutex_unlock(&chip->lock);

Expand Down Expand Up @@ -819,6 +776,9 @@ static struct lp55xx_device_config lp5523_cfg = {
.addr = LP5523_REG_ENABLE,
.val = LP5523_ENABLE,
},
.prog_mem_base = {
.addr = LP5523_REG_PROG_MEM,
},
.pages_per_engine = LP5523_PAGES_PER_ENGINE,
.max_channel = LP5523_MAX_LEDS,
.post_init_device = lp5523_post_init_device,
Expand Down
58 changes: 4 additions & 54 deletions drivers/leds/leds-lp5562.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,59 +144,6 @@ static void lp5562_run_engine(struct lp55xx_chip *chip, bool start)
lp5562_wait_enable_done();
}

static int lp5562_update_firmware(struct lp55xx_chip *chip,
const u8 *data, size_t size)
{
enum lp55xx_engine_index idx = chip->engine_idx;
u8 pattern[LP5562_PROGRAM_LENGTH] = {0};
static const u8 addr[] = {
[LP55XX_ENGINE_1] = LP5562_REG_PROG_MEM_ENG1,
[LP55XX_ENGINE_2] = LP5562_REG_PROG_MEM_ENG2,
[LP55XX_ENGINE_3] = LP5562_REG_PROG_MEM_ENG3,
};
unsigned cmd;
char c[3];
int program_size;
int nrchars;
int offset = 0;
int ret;
int i;

/* clear program memory before updating */
for (i = 0; i < LP5562_PROGRAM_LENGTH; i++)
lp55xx_write(chip, addr[idx] + i, 0);

i = 0;
while ((offset < size - 1) && (i < LP5562_PROGRAM_LENGTH)) {
/* separate sscanfs because length is working only for %s */
ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
if (ret != 1)
goto err;

ret = sscanf(c, "%2x", &cmd);
if (ret != 1)
goto err;

pattern[i] = (u8)cmd;
offset += nrchars;
i++;
}

/* Each instruction is 16bit long. Check that length is even */
if (i % 2)
goto err;

program_size = i;
for (i = 0; i < program_size; i++)
lp55xx_write(chip, addr[idx] + i, pattern[i]);

return 0;

err:
dev_err(&chip->cl->dev, "wrong pattern format\n");
return -EINVAL;
}

static void lp5562_firmware_loaded(struct lp55xx_chip *chip)
{
const struct firmware *fw = chip->fw;
Expand All @@ -218,7 +165,7 @@ static void lp5562_firmware_loaded(struct lp55xx_chip *chip)
*/

lp55xx_load_engine(chip);
lp5562_update_firmware(chip, fw->data, fw->size);
lp55xx_update_program_memory(chip, fw->data, fw->size);
}

static int lp5562_post_init_device(struct lp55xx_chip *chip)
Expand Down Expand Up @@ -450,6 +397,9 @@ static struct lp55xx_device_config lp5562_cfg = {
.addr = LP5562_REG_ENABLE,
.val = LP5562_ENABLE_DEFAULT,
},
.prog_mem_base = {
.addr = LP5562_REG_PROG_MEM_ENG1,
},
.post_init_device = lp5562_post_init_device,
.set_led_current = lp5562_set_led_current,
.brightness_fn = lp5562_led_brightness,
Expand Down
57 changes: 57 additions & 0 deletions drivers/leds/leds-lp55xx-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
/* OP MODE require at least 153 us to clear regs */
#define LP55XX_CMD_SLEEP 200

#define LP55xx_PROGRAM_LENGTH 32

/*
* Program Memory Operations
* Same Mask for each engine for both mode and exec
Expand Down Expand Up @@ -160,6 +162,61 @@ int lp55xx_run_engine_common(struct lp55xx_chip *chip)
}
EXPORT_SYMBOL_GPL(lp55xx_run_engine_common);

int lp55xx_update_program_memory(struct lp55xx_chip *chip,
const u8 *data, size_t size)
{
enum lp55xx_engine_index idx = chip->engine_idx;
const struct lp55xx_device_config *cfg = chip->cfg;
u8 pattern[LP55xx_PROGRAM_LENGTH] = { };
u8 start_addr = cfg->prog_mem_base.addr;
int i = 0, offset = 0;
int ret;

while ((offset < size - 1) && (i < LP55xx_PROGRAM_LENGTH)) {
unsigned int cmd;
int nrchars;
char c[3];

/* separate sscanfs because length is working only for %s */
ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
if (ret != 1)
goto err;

ret = sscanf(c, "%2x", &cmd);
if (ret != 1)
goto err;

pattern[i] = (u8)cmd;
offset += nrchars;
i++;
}

/* Each instruction is 16bit long. Check that length is even */
if (i % 2)
goto err;

/*
* For legacy LED chip with no page support, engine base address are
* one after another at offset of 32.
* For LED chip that support page, PAGE is already set in load_engine.
*/
if (!cfg->pages_per_engine)
start_addr += LP55xx_PROGRAM_LENGTH * idx;

for (i = 0; i < LP55xx_PROGRAM_LENGTH; i++) {
ret = lp55xx_write(chip, start_addr + i, pattern[i]);
if (ret)
return -EINVAL;
}

return size;

err:
dev_err(&chip->cl->dev, "wrong pattern format\n");
return -EINVAL;
}
EXPORT_SYMBOL_GPL(lp55xx_update_program_memory);

static void lp55xx_reset_device(struct lp55xx_chip *chip)
{
const struct lp55xx_device_config *cfg = chip->cfg;
Expand Down
4 changes: 4 additions & 0 deletions drivers/leds/leds-lp55xx-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct lp55xx_reg {
* (if not supported 153 us sleep)
* @reset : Chip specific reset command
* @enable : Chip specific enable command
* @prog_mem_base : Chip specific base reg address for chip SMEM programming
* @pages_per_engine : Assigned pages for each engine
* (if not set chip doesn't support pages)
* @max_channel : Maximum number of channels
Expand All @@ -116,6 +117,7 @@ struct lp55xx_device_config {
const struct lp55xx_reg engine_busy; /* addr, mask */
const struct lp55xx_reg reset;
const struct lp55xx_reg enable;
const struct lp55xx_reg prog_mem_base;
const int pages_per_engine;
const int max_channel;

Expand Down Expand Up @@ -208,6 +210,8 @@ extern bool lp55xx_is_extclk_used(struct lp55xx_chip *chip);
extern void lp55xx_stop_all_engine(struct lp55xx_chip *chip);
extern void lp55xx_load_engine(struct lp55xx_chip *chip);
extern int lp55xx_run_engine_common(struct lp55xx_chip *chip);
extern int lp55xx_update_program_memory(struct lp55xx_chip *chip,
const u8 *data, size_t size);

/* common probe/remove function */
extern int lp55xx_probe(struct i2c_client *client);
Expand Down
Loading

0 comments on commit 31379a5

Please sign in to comment.