]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
leds: leds-lp55xx: Generalize sysfs engine_leds
authorChristian Marangi <ansuelsmth@gmail.com>
Wed, 26 Jun 2024 16:00:21 +0000 (18:00 +0200)
committerLee Jones <lee@kernel.org>
Wed, 26 Jun 2024 16:08:31 +0000 (17:08 +0100)
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 <lee@kernel.org>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Link: https://lore.kernel.org/r/20240626160027.19703-17-ansuelsmth@gmail.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/leds/leds-lp5523.c
drivers/leds/leds-lp55xx-common.c
drivers/leds/leds-lp55xx-common.h

index 19b119a2b256e35ecb0ffc444e146e5783ddea26..9d91c2c5a3eb139d9e68531042992867e92219bd 100644 (file)
@@ -225,119 +225,6 @@ out:
        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 @@ leave:
 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);
index 0974488780c0d13d0cbc2fc41ced41e51b1aacd7..f0b673c613960fcd4ae04ddeb3b18603dd4e5264 100644 (file)
@@ -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
 
@@ -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,
index 5b3e9473cadc37a03c502b39e7cc08b3ed82c1ce..5f2394a6de159ee88d7c3444c058c84950cd143b 100644 (file)
@@ -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,             \
@@ -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 */