Commit 5a15b2ab authored by Christian Marangi's avatar Christian Marangi Committed by Lee Jones
Browse files

leds: leds-lp55xx: Generalize sysfs master_fader



Generalize sysfs master_fader since their implementation is the same across
some lp55xx based LED driver.

Suggested-by: default avatarLee Jones <lee@kernel.org>
Signed-off-by: default avatarChristian Marangi <ansuelsmth@gmail.com>
Link: https://lore.kernel.org/r/20240626160027.19703-18-ansuelsmth@gmail.com


Signed-off-by: default avatarLee Jones <lee@kernel.org>
parent 8913c2c1
Loading
Loading
Loading
Loading
+11 −139
Original line number Diff line number Diff line
@@ -315,137 +315,6 @@ static ssize_t lp5523_selftest(struct device *dev,
	return pos;
}

#define show_fader(nr)						\
static ssize_t show_master_fader##nr(struct device *dev,	\
			    struct device_attribute *attr,	\
			    char *buf)				\
{								\
	return show_master_fader(dev, attr, buf, nr);		\
}

#define store_fader(nr)						\
static ssize_t store_master_fader##nr(struct device *dev,	\
			     struct device_attribute *attr,	\
			     const char *buf, size_t len)	\
{								\
	return store_master_fader(dev, attr, buf, len, nr);	\
}

static ssize_t show_master_fader(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;
	int ret;
	u8 val;

	mutex_lock(&chip->lock);
	ret = lp55xx_read(chip, LP5523_REG_MASTER_FADER_BASE + nr - 1, &val);
	mutex_unlock(&chip->lock);

	if (ret == 0)
		ret = sprintf(buf, "%u\n", val);

	return ret;
}
show_fader(1)
show_fader(2)
show_fader(3)

static ssize_t store_master_fader(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;
	int ret;
	unsigned long val;

	if (kstrtoul(buf, 0, &val))
		return -EINVAL;

	if (val > 0xff)
		return -EINVAL;

	mutex_lock(&chip->lock);
	ret = lp55xx_write(chip, LP5523_REG_MASTER_FADER_BASE + nr - 1,
			   (u8)val);
	mutex_unlock(&chip->lock);

	if (ret == 0)
		ret = len;

	return ret;
}
store_fader(1)
store_fader(2)
store_fader(3)

static ssize_t show_master_fader_leds(struct device *dev,
				      struct device_attribute *attr,
				      char *buf)
{
	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
	struct lp55xx_chip *chip = led->chip;
	int i, ret, pos = 0;
	u8 val;

	mutex_lock(&chip->lock);

	for (i = 0; i < LP5523_MAX_LEDS; i++) {
		ret = lp55xx_read(chip, LP5523_REG_LED_CTRL_BASE + i, &val);
		if (ret)
			goto leave;

		val = (val & LP5523_FADER_MAPPING_MASK)
			>> LP5523_FADER_MAPPING_SHIFT;
		if (val > 3) {
			ret = -EINVAL;
			goto leave;
		}
		buf[pos++] = val + '0';
	}
	buf[pos++] = '\n';
	ret = pos;
leave:
	mutex_unlock(&chip->lock);
	return ret;
}

static ssize_t store_master_fader_leds(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t len)
{
	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
	struct lp55xx_chip *chip = led->chip;
	int i, n, ret;
	u8 val;

	n = min_t(int, len, LP5523_MAX_LEDS);

	mutex_lock(&chip->lock);

	for (i = 0; i < n; i++) {
		if (buf[i] >= '0' && buf[i] <= '3') {
			val = (buf[i] - '0') << LP5523_FADER_MAPPING_SHIFT;
			ret = lp55xx_update_bits(chip,
						 LP5523_REG_LED_CTRL_BASE + i,
						 LP5523_FADER_MAPPING_MASK,
						 val);
			if (ret)
				goto leave;
		} else {
			ret = -EINVAL;
			goto leave;
		}
	}
	ret = len;
leave:
	mutex_unlock(&chip->lock);
	return ret;
}

LP55XX_DEV_ATTR_ENGINE_MODE(1);
LP55XX_DEV_ATTR_ENGINE_MODE(2);
LP55XX_DEV_ATTR_ENGINE_MODE(3);
@@ -456,14 +325,11 @@ LP55XX_DEV_ATTR_ENGINE_LOAD(1);
LP55XX_DEV_ATTR_ENGINE_LOAD(2);
LP55XX_DEV_ATTR_ENGINE_LOAD(3);
static LP55XX_DEV_ATTR_RO(selftest, lp5523_selftest);
static LP55XX_DEV_ATTR_RW(master_fader1, show_master_fader1,
			  store_master_fader1);
static LP55XX_DEV_ATTR_RW(master_fader2, show_master_fader2,
			  store_master_fader2);
static LP55XX_DEV_ATTR_RW(master_fader3, show_master_fader3,
			  store_master_fader3);
static LP55XX_DEV_ATTR_RW(master_fader_leds, show_master_fader_leds,
			  store_master_fader_leds);
LP55XX_DEV_ATTR_MASTER_FADER(1);
LP55XX_DEV_ATTR_MASTER_FADER(2);
LP55XX_DEV_ATTR_MASTER_FADER(3);
static LP55XX_DEV_ATTR_RW(master_fader_leds, lp55xx_show_master_fader_leds,
			  lp55xx_store_master_fader_leds);

static struct attribute *lp5523_attributes[] = {
	&dev_attr_engine1_mode.attr,
@@ -516,6 +382,12 @@ static struct lp55xx_device_config lp5523_cfg = {
	.reg_led_current_base = {
		.addr = LP5523_REG_LED_CURRENT_BASE,
	},
	.reg_master_fader_base = {
		.addr = LP5523_REG_MASTER_FADER_BASE,
	},
	.reg_led_ctrl_base = {
		.addr = LP5523_REG_LED_CTRL_BASE,
	},
	.pages_per_engine   = LP5523_PAGES_PER_ENGINE,
	.max_channel  = LP5523_MAX_LEDS,
	.post_init_device   = lp5523_post_init_device,
+113 −0
Original line number Diff line number Diff line
@@ -64,6 +64,9 @@

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

/* MASTER FADER common property */
#define LP55xx_FADER_MAPPING_MASK	GENMASK(7, 6)

/* External clock rate */
#define LP55XX_CLK_32K			32768

@@ -800,6 +803,116 @@ ssize_t lp55xx_store_engine_leds(struct device *dev,
}
EXPORT_SYMBOL_GPL(lp55xx_store_engine_leds);

ssize_t lp55xx_show_master_fader(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 ret;
	u8 val;

	mutex_lock(&chip->lock);
	ret = lp55xx_read(chip, cfg->reg_master_fader_base.addr + nr - 1, &val);
	mutex_unlock(&chip->lock);

	return ret ? ret : sysfs_emit(buf, "%u\n", val);
}
EXPORT_SYMBOL_GPL(lp55xx_show_master_fader);

ssize_t lp55xx_store_master_fader(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;
	const struct lp55xx_device_config *cfg = chip->cfg;
	int ret;
	unsigned long val;

	if (kstrtoul(buf, 0, &val))
		return -EINVAL;

	if (val > 0xff)
		return -EINVAL;

	mutex_lock(&chip->lock);
	ret = lp55xx_write(chip, cfg->reg_master_fader_base.addr + nr - 1,
			   (u8)val);
	mutex_unlock(&chip->lock);

	return ret ? ret : len;
}
EXPORT_SYMBOL_GPL(lp55xx_store_master_fader);

ssize_t lp55xx_show_master_fader_leds(struct device *dev,
				      struct device_attribute *attr,
				      char *buf)
{
	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, ret, pos = 0;
	u8 val;

	mutex_lock(&chip->lock);

	for (i = 0; i < cfg->max_channel; i++) {
		ret = lp55xx_read(chip, cfg->reg_led_ctrl_base.addr + i, &val);
		if (ret)
			goto leave;

		val = FIELD_GET(LP55xx_FADER_MAPPING_MASK, val);
		if (val > FIELD_MAX(LP55xx_FADER_MAPPING_MASK)) {
			ret = -EINVAL;
			goto leave;
		}
		buf[pos++] = val + '0';
	}
	buf[pos++] = '\n';
	ret = pos;
leave:
	mutex_unlock(&chip->lock);
	return ret;
}
EXPORT_SYMBOL_GPL(lp55xx_show_master_fader_leds);

ssize_t lp55xx_store_master_fader_leds(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t len)
{
	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, n, ret;
	u8 val;

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

	mutex_lock(&chip->lock);

	for (i = 0; i < n; i++) {
		if (buf[i] >= '0' && buf[i] <= '3') {
			val = (buf[i] - '0') << __bf_shf(LP55xx_FADER_MAPPING_MASK);
			ret = lp55xx_update_bits(chip,
						 cfg->reg_led_ctrl_base.addr + i,
						 LP55xx_FADER_MAPPING_MASK,
						 val);
			if (ret)
				goto leave;
		} else {
			ret = -EINVAL;
			goto leave;
		}
	}
	ret = len;
leave:
	mutex_unlock(&chip->lock);
	return ret;
}
EXPORT_SYMBOL_GPL(lp55xx_store_master_fader_leds);

static struct attribute *lp55xx_engine_attributes[] = {
	&dev_attr_select_engine.attr,
	&dev_attr_run_engine.attr,
+32 −0
Original line number Diff line number Diff line
@@ -76,6 +76,22 @@ static ssize_t store_engine##nr##_load(struct device *dev, \
}									\
static LP55XX_DEV_ATTR_WO(engine##nr##_load, store_engine##nr##_load)

#define LP55XX_DEV_ATTR_MASTER_FADER(nr)				\
static ssize_t show_master_fader##nr(struct device *dev,		\
				     struct device_attribute *attr,	\
				     char *buf)				\
{									\
	return lp55xx_show_master_fader(dev, attr, buf, nr);		\
}									\
static ssize_t store_master_fader##nr(struct device *dev,		\
				      struct device_attribute *attr,	\
				      const char *buf, size_t len)	\
{									\
	return lp55xx_store_master_fader(dev, attr, buf, len, nr);	\
}									\
static LP55XX_DEV_ATTR_RW(master_fader##nr, show_master_fader##nr,	\
			  store_master_fader##nr)

struct lp55xx_led;
struct lp55xx_chip;

@@ -103,6 +119,8 @@ struct lp55xx_reg {
 * @prog_mem_base      : Chip specific base reg address for chip SMEM programming
 * @reg_led_pwm_base   : Chip specific base reg address for LED PWM conf
 * @reg_led_current_base : Chip specific base reg address for LED current conf
 * @reg_master_fader_base : Chip specific base reg address for master fader base
 * @reg_led_ctrl_base  : Chip specific base reg address for LED ctrl base
 * @pages_per_engine   : Assigned pages for each engine
 *                       (if not set chip doesn't support pages)
 * @max_channel        : Maximum number of channels
@@ -123,6 +141,8 @@ struct lp55xx_device_config {
	const struct lp55xx_reg prog_mem_base;
	const struct lp55xx_reg reg_led_pwm_base;
	const struct lp55xx_reg reg_led_current_base;
	const struct lp55xx_reg reg_master_fader_base;
	const struct lp55xx_reg reg_led_ctrl_base;
	const int pages_per_engine;
	const int max_channel;

@@ -244,5 +264,17 @@ extern ssize_t lp55xx_show_engine_leds(struct device *dev,
extern ssize_t lp55xx_store_engine_leds(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t len, int nr);
extern ssize_t lp55xx_show_master_fader(struct device *dev,
					struct device_attribute *attr,
					char *buf, int nr);
extern ssize_t lp55xx_store_master_fader(struct device *dev,
					 struct device_attribute *attr,
					 const char *buf, size_t len, int nr);
extern ssize_t lp55xx_show_master_fader_leds(struct device *dev,
					     struct device_attribute *attr,
					     char *buf);
extern ssize_t lp55xx_store_master_fader_leds(struct device *dev,
					      struct device_attribute *attr,
					      const char *buf, size_t len);

#endif /* _LEDS_LP55XX_COMMON_H */