Skip to content

Commit

Permalink
leds: leds-lp55xx: Generalize sysfs engine_leds
Browse files Browse the repository at this point in the history
Generalize sysfs engine_leds since their implementation is the same across
some lp55xx based LED driver.

While at it simplify the implementation for show_engine_leds.

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 082a4d3 commit 8913c2c
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 129 deletions.
119 changes: 3 additions & 116 deletions drivers/leds/leds-lp5523.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,119 +225,6 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
return ret;
}

static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len)
{
u16 tmp_mux = 0;
int i;

len = min_t(int, len, LP5523_MAX_LEDS);

for (i = 0; i < len; i++) {
switch (buf[i]) {
case '1':
tmp_mux |= (1 << i);
break;
case '0':
break;
case '\n':
i = len;
break;
default:
return -1;
}
}
*mux = tmp_mux;

return 0;
}

static void lp5523_mux_to_array(u16 led_mux, char *array)
{
int i, pos = 0;

for (i = 0; i < LP5523_MAX_LEDS; i++)
pos += sprintf(array + pos, "%x", LED_ACTIVE(led_mux, i));

array[pos] = '\0';
}

static ssize_t show_engine_leds(struct device *dev,
struct device_attribute *attr,
char *buf, int nr)
{
struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
struct lp55xx_chip *chip = led->chip;
char mux[LP5523_MAX_LEDS + 1];

lp5523_mux_to_array(chip->engines[nr - 1].led_mux, mux);

return sprintf(buf, "%s\n", mux);
}
show_leds(1)
show_leds(2)
show_leds(3)

static int lp5523_load_mux(struct lp55xx_chip *chip, u16 mux, int nr)
{
struct lp55xx_engine *engine = &chip->engines[nr - 1];
int ret;
static const u8 mux_page[] = {
[LP55XX_ENGINE_1] = LP5523_PAGE_MUX1,
[LP55XX_ENGINE_2] = LP5523_PAGE_MUX2,
[LP55XX_ENGINE_3] = LP5523_PAGE_MUX3,
};

lp55xx_load_engine(chip);

ret = lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, mux_page[nr]);
if (ret)
return ret;

ret = lp55xx_write(chip, LP5523_REG_PROG_MEM, (u8)(mux >> 8));
if (ret)
return ret;

ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + 1, (u8)(mux));
if (ret)
return ret;

engine->led_mux = mux;
return 0;
}

static ssize_t store_engine_leds(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len, int nr)
{
struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
struct lp55xx_chip *chip = led->chip;
struct lp55xx_engine *engine = &chip->engines[nr - 1];
u16 mux = 0;
ssize_t ret;

if (lp5523_mux_parse(buf, &mux, len))
return -EINVAL;

mutex_lock(&chip->lock);

chip->engine_idx = nr;
ret = -EINVAL;

if (engine->mode != LP55XX_ENGINE_LOAD)
goto leave;

if (lp5523_load_mux(chip, mux, nr))
goto leave;

ret = len;
leave:
mutex_unlock(&chip->lock);
return ret;
}
store_leds(1)
store_leds(2)
store_leds(3)

static ssize_t lp5523_selftest(struct device *dev,
struct device_attribute *attr,
char *buf)
Expand Down Expand Up @@ -562,9 +449,9 @@ static ssize_t store_master_fader_leds(struct device *dev,
LP55XX_DEV_ATTR_ENGINE_MODE(1);
LP55XX_DEV_ATTR_ENGINE_MODE(2);
LP55XX_DEV_ATTR_ENGINE_MODE(3);
static LP55XX_DEV_ATTR_RW(engine1_leds, show_engine1_leds, store_engine1_leds);
static LP55XX_DEV_ATTR_RW(engine2_leds, show_engine2_leds, store_engine2_leds);
static LP55XX_DEV_ATTR_RW(engine3_leds, show_engine3_leds, store_engine3_leds);
LP55XX_DEV_ATTR_ENGINE_LEDS(1);
LP55XX_DEV_ATTR_ENGINE_LEDS(2);
LP55XX_DEV_ATTR_ENGINE_LEDS(3);
LP55XX_DEV_ATTR_ENGINE_LOAD(1);
LP55XX_DEV_ATTR_ENGINE_LOAD(2);
LP55XX_DEV_ATTR_ENGINE_LOAD(3);
Expand Down
109 changes: 109 additions & 0 deletions drivers/leds/leds-lp55xx-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
/* If supported, each ENGINE have an equal amount of pages offset from page 0 */
#define LP55xx_PAGE_OFFSET(n, pages) (((n) - 1) * (pages))

#define LED_ACTIVE(mux, led) (!!((mux) & (0x0001 << (led))))

/* External clock rate */
#define LP55XX_CLK_32K 32768

Expand Down Expand Up @@ -691,6 +693,113 @@ ssize_t lp55xx_store_engine_load(struct device *dev,
}
EXPORT_SYMBOL_GPL(lp55xx_store_engine_load);

static int lp55xx_mux_parse(struct lp55xx_chip *chip, const char *buf,
u16 *mux, size_t len)
{
const struct lp55xx_device_config *cfg = chip->cfg;
u16 tmp_mux = 0;
int i;

len = min_t(int, len, cfg->max_channel);

for (i = 0; i < len; i++) {
switch (buf[i]) {
case '1':
tmp_mux |= (1 << i);
break;
case '0':
break;
case '\n':
i = len;
break;
default:
return -1;
}
}
*mux = tmp_mux;

return 0;
}

ssize_t lp55xx_show_engine_leds(struct device *dev,
struct device_attribute *attr,
char *buf, int nr)
{
struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
struct lp55xx_chip *chip = led->chip;
const struct lp55xx_device_config *cfg = chip->cfg;
unsigned int led_active;
int i, pos = 0;

for (i = 0; i < cfg->max_channel; i++) {
led_active = LED_ACTIVE(chip->engines[nr - 1].led_mux, i);
pos += sysfs_emit_at(buf, pos, "%x", led_active);
}

pos += sysfs_emit_at(buf, pos, "\n");

return pos;
}
EXPORT_SYMBOL_GPL(lp55xx_show_engine_leds);

static int lp55xx_load_mux(struct lp55xx_chip *chip, u16 mux, int nr)
{
struct lp55xx_engine *engine = &chip->engines[nr - 1];
const struct lp55xx_device_config *cfg = chip->cfg;
u8 mux_page;
int ret;

lp55xx_load_engine(chip);

/* Derive the MUX page offset by starting at the end of the ENGINE pages */
mux_page = cfg->pages_per_engine * LP55XX_ENGINE_MAX + (nr - 1);
ret = lp55xx_write(chip, LP55xx_REG_PROG_PAGE_SEL, mux_page);
if (ret)
return ret;

ret = lp55xx_write(chip, cfg->prog_mem_base.addr, (u8)(mux >> 8));
if (ret)
return ret;

ret = lp55xx_write(chip, cfg->prog_mem_base.addr + 1, (u8)(mux));
if (ret)
return ret;

engine->led_mux = mux;
return 0;
}

ssize_t lp55xx_store_engine_leds(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len, int nr)
{
struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
struct lp55xx_chip *chip = led->chip;
struct lp55xx_engine *engine = &chip->engines[nr - 1];
u16 mux = 0;
ssize_t ret;

if (lp55xx_mux_parse(chip, buf, &mux, len))
return -EINVAL;

mutex_lock(&chip->lock);

chip->engine_idx = nr;
ret = -EINVAL;

if (engine->mode != LP55XX_ENGINE_LOAD)
goto leave;

if (lp55xx_load_mux(chip, mux, nr))
goto leave;

ret = len;
leave:
mutex_unlock(&chip->lock);
return ret;
}
EXPORT_SYMBOL_GPL(lp55xx_store_engine_leds);

static struct attribute *lp55xx_engine_attributes[] = {
&dev_attr_select_engine.attr,
&dev_attr_run_engine.attr,
Expand Down
32 changes: 19 additions & 13 deletions drivers/leds/leds-lp55xx-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,21 @@ static ssize_t store_engine##nr##_mode(struct device *dev, \
static LP55XX_DEV_ATTR_RW(engine##nr##_mode, show_engine##nr##_mode, \
store_engine##nr##_mode)

#define show_leds(nr) \
#define LP55XX_DEV_ATTR_ENGINE_LEDS(nr) \
static ssize_t show_engine##nr##_leds(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
struct device_attribute *attr, \
char *buf) \
{ \
return show_engine_leds(dev, attr, buf, nr); \
}

#define store_leds(nr) \
static ssize_t store_engine##nr##_leds(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t len) \
{ \
return store_engine_leds(dev, attr, buf, len, nr); \
}
return lp55xx_show_engine_leds(dev, attr, buf, nr); \
} \
static ssize_t store_engine##nr##_leds(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t len) \
{ \
return lp55xx_store_engine_leds(dev, attr, buf, len, nr); \
} \
static LP55XX_DEV_ATTR_RW(engine##nr##_leds, show_engine##nr##_leds, \
store_engine##nr##_leds)

#define LP55XX_DEV_ATTR_ENGINE_LOAD(nr) \
static ssize_t store_engine##nr##_load(struct device *dev, \
Expand Down Expand Up @@ -238,5 +238,11 @@ extern ssize_t lp55xx_store_engine_mode(struct device *dev,
extern ssize_t lp55xx_store_engine_load(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len, int nr);
extern ssize_t lp55xx_show_engine_leds(struct device *dev,
struct device_attribute *attr,
char *buf, int nr);
extern ssize_t lp55xx_store_engine_leds(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len, int nr);

#endif /* _LEDS_LP55XX_COMMON_H */

0 comments on commit 8913c2c

Please sign in to comment.