[PATCH v5 16/20] leds: leds-lp55xx: generalize sysfs engine_leds

From: Christian Marangi
Date: Sat Jun 15 2024 - 19:16:43 EST


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.

Signed-off-by: Christian Marangi <ansuelsmth@xxxxxxxxx>
---
drivers/leds/leds-lp5523.c | 119 +-----------------------------
drivers/leds/leds-lp55xx-common.c | 108 +++++++++++++++++++++++++++
drivers/leds/leds-lp55xx-common.h | 15 +++-
3 files changed, 124 insertions(+), 118 deletions(-)

diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 19b119a2b256..9d91c2c5a3eb 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -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)
@@ -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);
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 1a23352c9850..687693bed868 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -61,6 +61,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

@@ -691,6 +693,112 @@ 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;
+ int i, pos = 0;
+
+ for (i = 0; i < cfg->max_channel; i++)
+ pos += sysfs_emit_at(buf, pos, "%x",
+ LED_ACTIVE(chip->engines[nr - 1].led_mux,
+ i));
+
+ 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,
diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h
index 00d16a86b750..212bdb216c9a 100644
--- a/drivers/leds/leds-lp55xx-common.h
+++ b/drivers/leds/leds-lp55xx-common.h
@@ -61,7 +61,7 @@ static ssize_t show_engine##nr##_leds(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
- return show_engine_leds(dev, attr, buf, nr); \
+ return lp55xx_show_engine_leds(dev, attr, buf, nr); \
}

#define store_leds(nr) \
@@ -69,9 +69,14 @@ 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_store_engine_leds(dev, attr, buf, len, nr); \
}

+#define LP55XX_DEV_ATTR_ENGINE_LEDS(nr) \
+ show_leds(nr) \
+ store_leds(nr) \
+ static LP55XX_DEV_ATTR_RW(engine##nr##_leds, show_engine##nr##_leds, store_engine##nr##_leds)
+
#define store_load(nr) \
static ssize_t store_engine##nr##_load(struct device *dev, \
struct device_attribute *attr, \
@@ -246,5 +251,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 */
--
2.43.0