drivers/leds/rgb/leds-group-multicolor.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
When the driver is loaded, it turned off all LEDs in the group. This
patch changes the driver to take over existing LED states and set
the brighness and intensity in the group accordingly.
Signed-off-by: Martijn de Gouw <martijn.de.gouw@prodrive-technologies.com>
---
Changes in v3:
- Use is_on boolean instead of storing the max_brightness twice
- Link to v2: https://lore.kernel.org/linux-leds/20251124210521.2064660-1-martijn.de.gouw@prodrive-technologies.com/
Changes in v2:
- Fix multiline comments
- Improve comments
- Link to v1: https://lore.kernel.org/linux-leds/20251111204556.2803878-1-martijn.de.gouw@prodrive-technologies.com/
---
drivers/leds/rgb/leds-group-multicolor.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/leds/rgb/leds-group-multicolor.c b/drivers/leds/rgb/leds-group-multicolor.c
index 548c7dd63ba1e..ab46537697d76 100644
--- a/drivers/leds/rgb/leds-group-multicolor.c
+++ b/drivers/leds/rgb/leds-group-multicolor.c
@@ -69,6 +69,7 @@ static int leds_gmc_probe(struct platform_device *pdev)
struct mc_subled *subled;
struct leds_multicolor *priv;
unsigned int max_brightness = 0;
+ bool is_on = false;
int i, ret, count = 0, common_flags = 0;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -96,6 +97,13 @@ static int leds_gmc_probe(struct platform_device *pdev)
max_brightness = max(max_brightness, led_cdev->max_brightness);
+ /*
+ * If any LED is on, set brightness to the max brightness.
+ * The actual brightness of the LED is set as intensity value.
+ */
+ if (led_cdev->brightness)
+ is_on = true;
+
count++;
}
@@ -109,14 +117,16 @@ static int leds_gmc_probe(struct platform_device *pdev)
subled[i].color_index = led_cdev->color;
- /* Configure the LED intensity to its maximum */
- subled[i].intensity = max_brightness;
+ /* Configure the LED intensity to its current brightness */
+ subled[i].intensity = DIV_ROUND_CLOSEST(led_cdev->brightness * max_brightness,
+ led_cdev->max_brightness);
}
/* Initialise the multicolor's LED class device */
cdev = &priv->mc_cdev.led_cdev;
cdev->brightness_set_blocking = leds_gmc_set;
cdev->max_brightness = max_brightness;
+ cdev->brightness = is_on ? max_brightness : 0;
cdev->color = LED_COLOR_ID_MULTI;
priv->mc_cdev.num_colors = count;
--
2.39.2
On Mon, 16 Mar 2026, Martijn de Gouw wrote: > When the driver is loaded, it turned off all LEDs in the group. This > patch changes the driver to take over existing LED states and set > the brighness and intensity in the group accordingly. > > Signed-off-by: Martijn de Gouw <martijn.de.gouw@prodrive-technologies.com> > --- > Changes in v3: > - Use is_on boolean instead of storing the max_brightness twice > - Link to v2: https://lore.kernel.org/linux-leds/20251124210521.2064660-1-martijn.de.gouw@prodrive-technologies.com/ > > Changes in v2: > - Fix multiline comments > - Improve comments > - Link to v1: https://lore.kernel.org/linux-leds/20251111204556.2803878-1-martijn.de.gouw@prodrive-technologies.com/ > > --- > drivers/leds/rgb/leds-group-multicolor.c | 14 ++++++++++++-- > 1 file changed, 12 insertions(+), 2 deletions(-) > > diff --git a/drivers/leds/rgb/leds-group-multicolor.c b/drivers/leds/rgb/leds-group-multicolor.c > index 548c7dd63ba1e..ab46537697d76 100644 > --- a/drivers/leds/rgb/leds-group-multicolor.c > +++ b/drivers/leds/rgb/leds-group-multicolor.c > @@ -69,6 +69,7 @@ static int leds_gmc_probe(struct platform_device *pdev) > struct mc_subled *subled; > struct leds_multicolor *priv; > unsigned int max_brightness = 0; > + bool is_on = false; > int i, ret, count = 0, common_flags = 0; > > priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > @@ -96,6 +97,13 @@ static int leds_gmc_probe(struct platform_device *pdev) > > max_brightness = max(max_brightness, led_cdev->max_brightness); > > + /* > + * If any LED is on, set brightness to the max brightness. > + * The actual brightness of the LED is set as intensity value. > + */ > + if (led_cdev->brightness) > + is_on = true; > + > count++; > } > > @@ -109,14 +117,16 @@ static int leds_gmc_probe(struct platform_device *pdev) > > subled[i].color_index = led_cdev->color; > > - /* Configure the LED intensity to its maximum */ > - subled[i].intensity = max_brightness; > + /* Configure the LED intensity to its current brightness */ > + subled[i].intensity = DIV_ROUND_CLOSEST(led_cdev->brightness * max_brightness, > + led_cdev->max_brightness); There are a couple of potential issues on this line. 'led_cdev->max_brightness' could theoretically be zero, which would cause a division-by-zero fault. While the core tries to prevent this, a defensive check might be worth while. The multiplication 'led_cdev->brightness * max_brightness' could overflow if both values are large. It would be safer to cast the multiplication to u64, like: (u64)led_cdev->brightness Finally, and this applies to the read in the first loop as well, the brightness field of a led_classdev is protected by 'led_sem'. To avoid a race condition with userspace (e.g., writing to the brightness via sysfs), we should acquire this lock before reading 'led_cdev->brightness'. > } > > /* Initialise the multicolor's LED class device */ > cdev = &priv->mc_cdev.led_cdev; > cdev->brightness_set_blocking = leds_gmc_set; > cdev->max_brightness = max_brightness; > + cdev->brightness = is_on ? max_brightness : 0; > cdev->color = LED_COLOR_ID_MULTI; > priv->mc_cdev.num_colors = count; > > -- > 2.39.2 > > -- Lee Jones [李琼斯]
© 2016 - 2026 Red Hat, Inc.