mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes
@ 2026-09-05 13:01 Armin Wolf
  2026-09-05 13:01 ` [PATCH 1/5] platform/x86: uniwill-laptop: Report correct lightbar brightness Armin Wolf
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Armin Wolf @ 2026-09-05 13:01 UTC (permalink / raw)
  To: hansg, ilpo.jarvinen; +Cc: wse, platform-driver-x86, linux-kernel

This patch series mainly deals with various issues inside the code
responsible for controlling the lightbar on supported devices.

The first patch utilizes the improved multicolor LED API to report
the correct brightness of the lightbar to userspace. The next two
patches fix issues discovered inside the code for controlling
animations, while the fourth patch fixes an issue with the naming
of the LEDs in general. The last patch also adds support for another
variant of the Intel NUC x15 laptop kit.

All patches have been tested on said Intel NUC x15 laptop and appear
to work.

Armin Wolf (5):
  platform/x86: uniwill-laptop: Report correct lightbar brightness
  platform/x86: uniwill-laptop: Implement rainbow animation as trigger
  platform/x86: uniwill-laptop: Fix breathing animation on Intel QC
  platform/x86: uniwill-laptop: Label multicolor LEDs correctly
  platform/x86: uniwill-laptop: Extend support for the Intel NUC x15

 .../ABI/removed/sysfs-driver-uniwill-laptop   |  10 +
 .../ABI/testing/sysfs-driver-uniwill-laptop   |  15 +-
 .../admin-guide/laptops/uniwill-laptop.rst    |   9 +-
 MAINTAINERS                                   |   1 +
 drivers/platform/x86/uniwill/Kconfig          |   1 +
 drivers/platform/x86/uniwill/uniwill-acpi.c   | 225 +++++++++++-------
 6 files changed, 161 insertions(+), 100 deletions(-)
 create mode 100644 Documentation/ABI/removed/sysfs-driver-uniwill-laptop

-- 
2.39.5


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/5] platform/x86: uniwill-laptop: Report correct lightbar brightness
  2026-09-05 13:01 [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
@ 2026-09-05 13:01 ` Armin Wolf
  2026-10-05 16:12   ` Ilpo Järvinen
  2026-09-05 13:01 ` [PATCH 2/5] platform/x86: uniwill-laptop: Implement rainbow animation as trigger Armin Wolf
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Armin Wolf @ 2026-09-05 13:01 UTC (permalink / raw)
  To: hansg, ilpo.jarvinen; +Cc: wse, platform-driver-x86, linux-kernel

The LED sysfs ABI now allows us to specify the maximum values for the
global brightness and the color intensity values independently. At the
same time the maximum brightness value reported for the lightbar (like
200) does not match the real value supported by the hardware (1),
potentially confusing users.

Report the correct maximum brightness value and only use the intensity
values for controlling the lightbar color.

Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
 drivers/platform/x86/uniwill/uniwill-acpi.c | 35 ++++++++++-----------
 1 file changed, 16 insertions(+), 19 deletions(-)

diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 7a2eeaec4c96..7420e1dd4716 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -398,7 +398,7 @@ struct uniwill_data {
 	struct mutex super_key_lock;	/* Protects the toggling of the super key lock state */
 	struct list_head batteries;
 	struct mutex led_lock;		/* Protects writes to the lightbar registers */
-	u8 lightbar_max_brightness;
+	u8 lightbar_max_intensity;
 	struct led_classdev_mc led_mc_cdev;
 	struct mc_subled led_mc_subled_info[LED_CHANNELS];
 	bool kbd_led_single_color;
@@ -429,7 +429,7 @@ struct uniwill_device_descriptor {
 	unsigned int features;
 	bool kbd_led_single_color;
 	u8 kbd_led_max_brightness;
-	u8 lightbar_max_brightness;
+	u8 lightbar_max_intensity;
 	/* Executed during driver probing */
 	int (*probe)(struct uniwill_data *data);
 };
@@ -1509,20 +1509,16 @@ static int uniwill_led_brightness_set(struct led_classdev *led_cdev, enum led_br
 	unsigned int value;
 	int ret;
 
-	ret = led_mc_calc_color_components(led_mc_cdev, brightness);
-	if (ret < 0)
-		return ret;
-
 	guard(mutex)(&data->led_lock);
 
 	for (int i = 0; i < LED_CHANNELS; i++) {
-		/* Prevent the brightness values from overflowing */
-		value = min(data->lightbar_max_brightness, data->led_mc_subled_info[i].brightness);
-		ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
+		ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i],
+				   data->led_mc_subled_info[i].intensity);
 		if (ret < 0)
 			return ret;
 
-		ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value);
+		ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i],
+				   data->led_mc_subled_info[i].intensity);
 		if (ret < 0)
 			return ret;
 	}
@@ -1586,14 +1582,14 @@ static int uniwill_led_init(struct uniwill_data *data)
 		return ret;
 
 	data->led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;
-	data->led_mc_cdev.led_cdev.max_brightness = data->lightbar_max_brightness;
+	data->led_mc_cdev.led_cdev.max_brightness = 1;
 	data->led_mc_cdev.led_cdev.flags = LED_REJECT_NAME_CONFLICT;
 	data->led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_led_brightness_set;
 
 	if (value & LIGHTBAR_S0_OFF)
 		data->led_mc_cdev.led_cdev.brightness = 0;
 	else
-		data->led_mc_cdev.led_cdev.brightness = data->lightbar_max_brightness;
+		data->led_mc_cdev.led_cdev.brightness = 1;
 
 	for (int i = 0; i < LED_CHANNELS; i++) {
 		data->led_mc_subled_info[i].color_index = color_indices[i];
@@ -1604,9 +1600,9 @@ static int uniwill_led_init(struct uniwill_data *data)
 
 		/*
 		 * Make sure that the initial intensity value is not greater than
-		 * the maximum brightness.
+		 * the maximum intensity.
 		 */
-		value = min(data->lightbar_max_brightness, value);
+		value = min(data->lightbar_max_intensity, value);
 		ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
 		if (ret < 0)
 			return ret;
@@ -1616,6 +1612,7 @@ static int uniwill_led_init(struct uniwill_data *data)
 			return ret;
 
 		data->led_mc_subled_info[i].intensity = value;
+		data->led_mc_subled_info[i].max_intensity = data->lightbar_max_intensity;
 		data->led_mc_subled_info[i].channel = i;
 	}
 
@@ -2338,7 +2335,7 @@ static int uniwill_probe(struct platform_device *pdev)
 	data->features = device_descriptor.features;
 	data->kbd_led_single_color = device_descriptor.kbd_led_single_color;
 	data->kbd_led_max_brightness = device_descriptor.kbd_led_max_brightness;
-	data->lightbar_max_brightness = device_descriptor.lightbar_max_brightness;
+	data->lightbar_max_intensity = device_descriptor.lightbar_max_intensity;
 
 	/*
 	 * Some devices might need to perform some device-specific initialization steps
@@ -2685,7 +2682,7 @@ static struct uniwill_device_descriptor lapqc71a_lapqc71b_descriptor __initdata
 		    UNIWILL_FEATURE_GPU_TEMP |
 		    UNIWILL_FEATURE_PRIMARY_FAN |
 		    UNIWILL_FEATURE_SECONDARY_FAN,
-	.lightbar_max_brightness = 36,
+	.lightbar_max_intensity = 36,
 };
 
 static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
@@ -2709,7 +2706,7 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
 		    UNIWILL_FEATURE_GPU_TEMP |
 		    UNIWILL_FEATURE_PRIMARY_FAN |
 		    UNIWILL_FEATURE_SECONDARY_FAN,
-	.lightbar_max_brightness = 200,
+	.lightbar_max_intensity = 200,
 };
 
 /*
@@ -3355,8 +3352,8 @@ static int __init uniwill_init(void)
 		device_descriptor.kbd_led_single_color = false;
 		/* Some models only support 3 brightness levels */
 		device_descriptor.kbd_led_max_brightness = 4;
-		/* Some models only support 36 brightness levels per color component */
-		device_descriptor.lightbar_max_brightness = 200;
+		/* Some models only support 36 intensity levels per color component */
+		device_descriptor.lightbar_max_intensity = 200;
 		pr_warn("Enabling potentially unsupported features\n");
 	}
 
-- 
2.39.5


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/5] platform/x86: uniwill-laptop: Implement rainbow animation as trigger
  2026-09-05 13:01 [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
  2026-09-05 13:01 ` [PATCH 1/5] platform/x86: uniwill-laptop: Report correct lightbar brightness Armin Wolf
@ 2026-09-05 13:01 ` Armin Wolf
  2026-09-05 13:01 ` [PATCH 3/5] platform/x86: uniwill-laptop: Fix breathing animation on Intel QC Armin Wolf
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Armin Wolf @ 2026-09-05 13:01 UTC (permalink / raw)
  To: hansg, ilpo.jarvinen; +Cc: wse, platform-driver-x86, linux-kernel

It turns out that some models require the lightbar to be activated
in order to display the rainbow animation, so users have to access
both the "rainbow_animation" sysfs attribute and the LED sysfs
interface when enabling the rainbow animation. This can cause short
glitches when the lightbar was previously disabled.

Fix this by replacing the sysfs attribute with a custom LED trigger
called "uniwill-rainbow". Selecting this trigger will atomically
activate the lightbar and enable the rainbow animation mode. This
can potentially break userspace applications using the old sysfs
attribute, but so far no such application is known to exist (yet).

Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
 .../ABI/removed/sysfs-driver-uniwill-laptop   |  10 ++
 .../ABI/testing/sysfs-driver-uniwill-laptop   |  11 --
 .../admin-guide/laptops/uniwill-laptop.rst    |   5 +-
 MAINTAINERS                                   |   1 +
 drivers/platform/x86/uniwill/Kconfig          |   1 +
 drivers/platform/x86/uniwill/uniwill-acpi.c   | 133 +++++++++++-------
 6 files changed, 95 insertions(+), 66 deletions(-)
 create mode 100644 Documentation/ABI/removed/sysfs-driver-uniwill-laptop

diff --git a/Documentation/ABI/removed/sysfs-driver-uniwill-laptop b/Documentation/ABI/removed/sysfs-driver-uniwill-laptop
new file mode 100644
index 000000000000..c226efc23b59
--- /dev/null
+++ b/Documentation/ABI/removed/sysfs-driver-uniwill-laptop
@@ -0,0 +1,10 @@
+What:		/sys/bus/platform/devices/INOU0000:XX/rainbow_animation
+Date:		November 2025
+KernelVersion:	6.19
+Contact:	Armin Wolf <W_Armin@gmx.de>
+Description:
+		Forces the integrated lightbar to display a rainbow animation when the machine
+		is not suspended. Writing "1"/"0" into this file enables/disables this
+		functionality.
+
+		Reading this file returns the current status of the rainbow animation functionality.
diff --git a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
index 943f92c6b561..b9b9feebe2ed 100644
--- a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
+++ b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
@@ -29,17 +29,6 @@ Description:
 		Reading this file returns the current enable status of the touchpad toggle
 		functionality.
 
-What:		/sys/bus/platform/devices/INOU0000:XX/rainbow_animation
-Date:		November 2025
-KernelVersion:	6.19
-Contact:	Armin Wolf <W_Armin@gmx.de>
-Description:
-		Forces the integrated lightbar to display a rainbow animation when the machine
-		is not suspended. Writing "1"/"0" into this file enables/disables this
-		functionality.
-
-		Reading this file returns the current status of the rainbow animation functionality.
-
 What:		/sys/bus/platform/devices/INOU0000:XX/breathing_in_suspend
 Date:		November 2025
 KernelVersion:	6.19
diff --git a/Documentation/admin-guide/laptops/uniwill-laptop.rst b/Documentation/admin-guide/laptops/uniwill-laptop.rst
index be50b45b82ef..aaf50e3074c1 100644
--- a/Documentation/admin-guide/laptops/uniwill-laptop.rst
+++ b/Documentation/admin-guide/laptops/uniwill-laptop.rst
@@ -74,8 +74,9 @@ Lightbar
 The ``uniwill-laptop`` driver exposes the lightbar found on some models as a standard multicolor
 LED class device. The default name of this LED class device is ``uniwill:multicolor:status``.
 
-See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details on how to control the various
-animation modes of the lightbar.
+The lightbar supports a separate rainbow animation mode that can be enabled by selecting the
+`uniwill-rainbow` LED trigger. To enable a breathing animation during suspend, see
+Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details.
 
 Keyboard Backlight
 ------------------
diff --git a/MAINTAINERS b/MAINTAINERS
index 3a19da74d00c..a3e25d111203 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28107,6 +28107,7 @@ UNIWILL LAPTOP DRIVER
 M:	Armin Wolf <W_Armin@gmx.de>
 L:	platform-driver-x86@vger.kernel.org
 S:	Maintained
+F:	Documentation/ABI/removed/sysfs-driver-uniwill-laptop
 F:	Documentation/ABI/testing/sysfs-driver-uniwill-laptop
 F:	Documentation/admin-guide/laptops/uniwill-laptop.rst
 F:	Documentation/wmi/devices/uniwill-laptop.rst
diff --git a/drivers/platform/x86/uniwill/Kconfig b/drivers/platform/x86/uniwill/Kconfig
index d07cc8440188..f80794bdfaef 100644
--- a/drivers/platform/x86/uniwill/Kconfig
+++ b/drivers/platform/x86/uniwill/Kconfig
@@ -28,6 +28,7 @@ config UNIWILL_LAPTOP
 	depends on DMI
 	select REGMAP
 	select INPUT_SPARSEKMAP
+	select LEDS_TRIGGERS
 	help
 	  This driver adds support for various extra features found on Uniwill laptops,
 	  like the lightbar, hwmon sensors and hotkeys. It also supports many OEM laptops
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 7420e1dd4716..6366171c6981 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -898,51 +898,6 @@ static ssize_t touchpad_toggle_enable_show(struct device *dev, struct device_att
 
 static DEVICE_ATTR_RW(touchpad_toggle_enable);
 
-static ssize_t rainbow_animation_store(struct device *dev, struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct uniwill_data *data = dev_get_drvdata(dev);
-	unsigned int value;
-	bool enable;
-	int ret;
-
-	ret = kstrtobool(buf, &enable);
-	if (ret < 0)
-		return ret;
-
-	if (enable)
-		value = LIGHTBAR_WELCOME;
-	else
-		value = 0;
-
-	guard(mutex)(&data->led_lock);
-
-	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_WELCOME, value);
-	if (ret < 0)
-		return ret;
-
-	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_WELCOME, value);
-	if (ret < 0)
-		return ret;
-
-	return count;
-}
-
-static ssize_t rainbow_animation_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct uniwill_data *data = dev_get_drvdata(dev);
-	unsigned int value;
-	int ret;
-
-	ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
-	if (ret < 0)
-		return ret;
-
-	return sysfs_emit(buf, "%d\n", !!(value & LIGHTBAR_WELCOME));
-}
-
-static DEVICE_ATTR_RW(rainbow_animation);
-
 static ssize_t breathing_in_suspend_store(struct device *dev, struct device_attribute *attr,
 					  const char *buf, size_t count)
 {
@@ -1256,7 +1211,6 @@ static struct attribute *uniwill_attrs[] = {
 	&dev_attr_super_key_enable.attr,
 	&dev_attr_touchpad_toggle_enable.attr,
 	/* Lightbar-related */
-	&dev_attr_rainbow_animation.attr,
 	&dev_attr_breathing_in_suspend.attr,
 	/* Power-management-related */
 	&dev_attr_ctgp_offset.attr,
@@ -1286,8 +1240,7 @@ static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *a
 			return attr->mode;
 	}
 
-	if (attr == &dev_attr_rainbow_animation.attr ||
-	    attr == &dev_attr_breathing_in_suspend.attr) {
+	if (attr == &dev_attr_breathing_in_suspend.attr) {
 		if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
 			return attr->mode;
 	}
@@ -1535,6 +1488,59 @@ static int uniwill_led_brightness_set(struct led_classdev *led_cdev, enum led_br
 	return regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_S0_OFF, value);
 }
 
+static int uniwill_led_hw_control_set(struct led_classdev *led_cdev, unsigned long flags)
+{
+	struct led_classdev_mc *led_mc_cdev = lcdev_to_mccdev(led_cdev);
+	struct uniwill_data *data = container_of(led_mc_cdev, struct uniwill_data, led_mc_cdev);
+	unsigned int value;
+	int ret;
+
+	guard(mutex)(&data->led_lock);
+
+	if (flags)
+		value = LIGHTBAR_WELCOME;
+	else
+		value = LIGHTBAR_S0_OFF;
+
+	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL,
+				 LIGHTBAR_S0_OFF | LIGHTBAR_WELCOME, value);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL,
+				 LIGHTBAR_S0_OFF | LIGHTBAR_WELCOME, value);
+	if (ret < 0)
+		return ret;
+
+	/* The LED is always on during hw control */
+	led_cdev->brightness = flags;
+
+	return 0;
+}
+
+static int uniwill_lightbar_trigger_activate(struct led_classdev *led_cdev)
+{
+	return led_cdev->hw_control_set(led_cdev, 1);
+}
+
+static void uniwill_lightbar_trigger_deactivate(struct led_classdev *led_cdev)
+{
+	int ret;
+
+	ret = led_cdev->hw_control_set(led_cdev, 0);
+	if (ret < 0)
+		dev_err(led_cdev->dev, "Failed to stop rainbow animation: %d\n", ret);
+}
+
+static struct led_hw_trigger_type uniwill_lightbar_trigger_type;
+
+static struct led_trigger uniwill_lightbar_trigger = {
+	.name = "uniwill-rainbow",
+	.activate = uniwill_lightbar_trigger_activate,
+	.deactivate = uniwill_lightbar_trigger_deactivate,
+	.trigger_type = &uniwill_lightbar_trigger_type,
+};
+
 #define LIGHTBAR_MASK	(LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | LIGHTBAR_WELCOME)
 
 static int uniwill_led_init(struct uniwill_data *data)
@@ -1585,12 +1591,18 @@ static int uniwill_led_init(struct uniwill_data *data)
 	data->led_mc_cdev.led_cdev.max_brightness = 1;
 	data->led_mc_cdev.led_cdev.flags = LED_REJECT_NAME_CONFLICT;
 	data->led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_led_brightness_set;
+	data->led_mc_cdev.led_cdev.trigger_type = &uniwill_lightbar_trigger_type;
+	data->led_mc_cdev.led_cdev.hw_control_trigger = uniwill_lightbar_trigger.name;
+	data->led_mc_cdev.led_cdev.hw_control_set = uniwill_led_hw_control_set;
 
 	if (value & LIGHTBAR_S0_OFF)
 		data->led_mc_cdev.led_cdev.brightness = 0;
 	else
 		data->led_mc_cdev.led_cdev.brightness = 1;
 
+	if (value & LIGHTBAR_WELCOME)
+		data->led_mc_cdev.led_cdev.default_trigger = uniwill_lightbar_trigger.name;
+
 	for (int i = 0; i < LED_CHANNELS; i++) {
 		data->led_mc_subled_info[i].color_index = color_indices[i];
 
@@ -3357,17 +3369,31 @@ static int __init uniwill_init(void)
 		pr_warn("Enabling potentially unsupported features\n");
 	}
 
-	ret = platform_driver_register(&uniwill_driver);
+	/*
+	 * We cannot register the trigger inside the .probe callback of the
+	 * platform driver, because each trigger needs a unique name.
+	 */
+	ret = led_trigger_register(&uniwill_lightbar_trigger);
 	if (ret < 0)
 		return ret;
 
+	ret = platform_driver_register(&uniwill_driver);
+	if (ret < 0)
+		goto err_platform;
+
 	ret = uniwill_wmi_register_driver();
-	if (ret < 0) {
-		platform_driver_unregister(&uniwill_driver);
-		return ret;
-	}
+	if (ret < 0)
+		goto err_wmi;
 
 	return 0;
+
+err_wmi:
+	platform_driver_unregister(&uniwill_driver);
+
+err_platform:
+	led_trigger_unregister(&uniwill_lightbar_trigger);
+
+	return ret;
 }
 module_init(uniwill_init);
 
@@ -3375,6 +3401,7 @@ static void __exit uniwill_exit(void)
 {
 	uniwill_wmi_unregister_driver();
 	platform_driver_unregister(&uniwill_driver);
+	led_trigger_unregister(&uniwill_lightbar_trigger);
 }
 module_exit(uniwill_exit);
 
-- 
2.39.5


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/5] platform/x86: uniwill-laptop: Fix breathing animation on Intel QC
  2026-09-05 13:01 [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
  2026-09-05 13:01 ` [PATCH 1/5] platform/x86: uniwill-laptop: Report correct lightbar brightness Armin Wolf
  2026-09-05 13:01 ` [PATCH 2/5] platform/x86: uniwill-laptop: Implement rainbow animation as trigger Armin Wolf
@ 2026-09-05 13:01 ` Armin Wolf
  2026-10-05 16:13   ` Ilpo Järvinen
  2026-09-05 13:01 ` [PATCH 4/5] platform/x86: uniwill-laptop: Label multicolor LEDs correctly Armin Wolf
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Armin Wolf @ 2026-09-05 13:01 UTC (permalink / raw)
  To: hansg, ilpo.jarvinen; +Cc: wse, platform-driver-x86, linux-kernel

Intel NUC 9 Extreme (Queens County) devices have a separate bit
inside the EC_ADDR_LIGHTBAR_AC:CTRL register for enabling the
breathing animation in s2idle mode.

Add support for this additional setting.

Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
 .../ABI/testing/sysfs-driver-uniwill-laptop   |  4 +--
 drivers/platform/x86/uniwill/uniwill-acpi.c   | 27 ++++++++++++++-----
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
index b9b9feebe2ed..f3060aaf8a76 100644
--- a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
+++ b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
@@ -35,8 +35,8 @@ KernelVersion:	6.19
 Contact:	Armin Wolf <W_Armin@gmx.de>
 Description:
 		Causes the integrated lightbar to display a breathing animation when the machine
-		has been suspended and is running on AC power. Writing "1"/"0" into this file
-		enables/disables this functionality.
+		has been suspended, is running on AC power and the lightbar brightness not zero.
+		Writing "1"/"0" into this file enables/disables this functionality.
 
 		Reading this file returns the current status of the breathing animation
 		functionality.
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 6366171c6981..e527ed7461c3 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -165,9 +165,10 @@
 #define EC_ADDR_LIGHTBAR_AC_CTRL	0x0748
 #define LIGHTBAR_APP_EXISTS		BIT(0)
 #define LIGHTBAR_POWER_SAVE		BIT(1)
-#define LIGHTBAR_S0_OFF			BIT(2)
-#define LIGHTBAR_S3_OFF			BIT(3)	// Breathing animation when suspended
-#define LIGHTBAR_WELCOME		BIT(7)	// Rainbow animation
+#define LIGHTBAR_S0_OFF			BIT(2)	/* Also disables animations */
+#define LIGHTBAR_S3_OFF			BIT(3)	/* No breathing animation when in s2ram */
+#define LIGHTBAR_MODERN_STANDBY_ON	BIT(6)	/* Breathing animation when in s2idle */
+#define LIGHTBAR_WELCOME		BIT(7)	/* Rainbow animation */
 
 #define EC_ADDR_LIGHTBAR_AC_RED		0x0749
 
@@ -306,7 +307,7 @@
 #define EC_ADDR_USB_C_POWER_PRIORITY	0x07CC
 #define USB_C_POWER_PRIORITY		BIT(7)
 
-/* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF */
+/* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF and LIGHTBAR_MODERN_STANDBY_ON */
 #define EC_ADDR_LIGHTBAR_BAT_CTRL	0x07E2
 
 #define EC_ADDR_LIGHTBAR_BAT_RED	0x07E3
@@ -911,12 +912,13 @@ static ssize_t breathing_in_suspend_store(struct device *dev, struct device_attr
 		return ret;
 
 	if (enable)
-		value = 0;
+		value = LIGHTBAR_MODERN_STANDBY_ON;
 	else
 		value = LIGHTBAR_S3_OFF;
 
 	/* We only access a single register here, so we do not need to use data->led_lock */
-	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S3_OFF, value);
+	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL,
+				 LIGHTBAR_S3_OFF | LIGHTBAR_MODERN_STANDBY_ON, value);
 	if (ret < 0)
 		return ret;
 
@@ -934,6 +936,10 @@ static ssize_t breathing_in_suspend_show(struct device *dev, struct device_attri
 	if (ret < 0)
 		return ret;
 
+	/*
+	 * We only test LIGHTBAR_S3_OFF here, because LIGHTBAR_MODERN_STANDBY_ON
+	 * should have the exact opposite value.
+	 */
 	return sysfs_emit(buf, "%d\n", !(value & LIGHTBAR_S3_OFF));
 }
 
@@ -1541,7 +1547,8 @@ static struct led_trigger uniwill_lightbar_trigger = {
 	.trigger_type = &uniwill_lightbar_trigger_type,
 };
 
-#define LIGHTBAR_MASK	(LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | LIGHTBAR_WELCOME)
+#define LIGHTBAR_MASK	(LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | \
+			 LIGHTBAR_MODERN_STANDBY_ON | LIGHTBAR_WELCOME)
 
 static int uniwill_led_init(struct uniwill_data *data)
 {
@@ -1574,6 +1581,11 @@ static int uniwill_led_init(struct uniwill_data *data)
 		return ret;
 
 	value |= LIGHTBAR_APP_EXISTS;
+	if (value & LIGHTBAR_S3_OFF)
+		value &= ~LIGHTBAR_MODERN_STANDBY_ON;
+	else
+		value |= LIGHTBAR_MODERN_STANDBY_ON;
+
 	ret = regmap_write(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, value);
 	if (ret < 0)
 		return ret;
@@ -1583,6 +1595,7 @@ static int uniwill_led_init(struct uniwill_data *data)
 	 * running on battery power.
 	 */
 	value |= LIGHTBAR_S3_OFF;
+	value &= ~LIGHTBAR_MODERN_STANDBY_ON;
 	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_MASK, value);
 	if (ret < 0)
 		return ret;
-- 
2.39.5


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4/5] platform/x86: uniwill-laptop: Label multicolor LEDs correctly
  2026-09-05 13:01 [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
                   ` (2 preceding siblings ...)
  2026-09-05 13:01 ` [PATCH 3/5] platform/x86: uniwill-laptop: Fix breathing animation on Intel QC Armin Wolf
@ 2026-09-05 13:01 ` Armin Wolf
  2026-09-05 13:01 ` [PATCH 5/5] platform/x86: uniwill-laptop: Extend support for the Intel NUC x15 Armin Wolf
  2026-09-22 20:45 ` [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
  5 siblings, 0 replies; 9+ messages in thread
From: Armin Wolf @ 2026-09-05 13:01 UTC (permalink / raw)
  To: hansg, ilpo.jarvinen; +Cc: wse, platform-driver-x86, linux-kernel

The LED subsystem specifies that LEDs capable of producing arbitrary
colors (like RGB) should label themselfs as "rgb" instead of
"multicolor".

Use the "rgb" label instead of the "multicolor" label to fix
detection by userspace applications.

Reported-by: Werner Sembach <wse@tuxedocomputers.com>
Closes: https://github.com/Wer-Wolf/uniwill-laptop/issues/18
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
 Documentation/admin-guide/laptops/uniwill-laptop.rst | 4 ++--
 drivers/platform/x86/uniwill/uniwill-acpi.c          | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Documentation/admin-guide/laptops/uniwill-laptop.rst b/Documentation/admin-guide/laptops/uniwill-laptop.rst
index aaf50e3074c1..d8ce30f10d7c 100644
--- a/Documentation/admin-guide/laptops/uniwill-laptop.rst
+++ b/Documentation/admin-guide/laptops/uniwill-laptop.rst
@@ -72,7 +72,7 @@ Lightbar
 --------
 
 The ``uniwill-laptop`` driver exposes the lightbar found on some models as a standard multicolor
-LED class device. The default name of this LED class device is ``uniwill:multicolor:status``.
+LED class device. The default name of this LED class device is ``uniwill:rgb:status``.
 
 The lightbar supports a separate rainbow animation mode that can be enabled by selecting the
 `uniwill-rainbow` LED trigger. To enable a breathing animation during suspend, see
@@ -83,7 +83,7 @@ Keyboard Backlight
 
 The ``uniwill-laptop`` driver supports controlling the keyboard backlight using the standard
 LED class interface. The default name of this LED class device is ``uniwill:white:kbd_backlight``
-when the keyboard backlight supports only a single color, or ``uniwill:multicolor:kbd_backlight``
+when the keyboard backlight supports only a single color, or ``uniwill:rgb:kbd_backlight``
 when the keyboard backlight supports RGB colors. The maximum intensity for each color channel
 in RGB mode is 50.
 
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index e527ed7461c3..27d5e54f0e1c 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -1554,7 +1554,7 @@ static int uniwill_led_init(struct uniwill_data *data)
 {
 	struct led_init_data init_data = {
 		.devicename = DRIVER_NAME,
-		.default_label = "multicolor:" LED_FUNCTION_STATUS,
+		.default_label = "rgb:" LED_FUNCTION_STATUS,
 		.devname_mandatory = true,
 	};
 	unsigned int color_indices[3] = {
@@ -1600,7 +1600,7 @@ static int uniwill_led_init(struct uniwill_data *data)
 	if (ret < 0)
 		return ret;
 
-	data->led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;
+	data->led_mc_cdev.led_cdev.color = LED_COLOR_ID_RGB;
 	data->led_mc_cdev.led_cdev.max_brightness = 1;
 	data->led_mc_cdev.led_cdev.flags = LED_REJECT_NAME_CONFLICT;
 	data->led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_led_brightness_set;
@@ -1782,7 +1782,7 @@ static int uniwill_rgb_kbd_led_init(struct uniwill_data *data)
 		LED_COLOR_ID_BLUE,
 	};
 	struct led_init_data init_data = {
-		.default_label = "multicolor:" LED_FUNCTION_KBD_BACKLIGHT,
+		.default_label = "rgb:" LED_FUNCTION_KBD_BACKLIGHT,
 		.devicename = DRIVER_NAME,
 		.devname_mandatory = true,
 	};
@@ -1843,7 +1843,7 @@ static int uniwill_rgb_kbd_led_init(struct uniwill_data *data)
 		return ret;
 
 	data->kbd_led_mc_cdev.led_cdev.max_brightness = data->kbd_led_max_brightness;
-	data->kbd_led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;
+	data->kbd_led_mc_cdev.led_cdev.color = LED_COLOR_ID_RGB;
 	data->kbd_led_mc_cdev.led_cdev.flags = LED_BRIGHT_HW_CHANGED | LED_REJECT_NAME_CONFLICT;
 	data->kbd_led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_kbd_led_mc_brightness_set;
 	data->kbd_led_mc_cdev.led_cdev.brightness_get = uniwill_kbd_led_mc_brightness_get;
-- 
2.39.5


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 5/5] platform/x86: uniwill-laptop: Extend support for the Intel NUC x15
  2026-09-05 13:01 [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
                   ` (3 preceding siblings ...)
  2026-09-05 13:01 ` [PATCH 4/5] platform/x86: uniwill-laptop: Label multicolor LEDs correctly Armin Wolf
@ 2026-09-05 13:01 ` Armin Wolf
  2026-09-22 20:45 ` [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
  5 siblings, 0 replies; 9+ messages in thread
From: Armin Wolf @ 2026-09-05 13:01 UTC (permalink / raw)
  To: hansg, ilpo.jarvinen; +Cc: wse, platform-driver-x86, linux-kernel

A user has reported that the LAPKC71E variant of the Intel NUC x15
also works with the uniwill-laptop driver. The difference between the
LAPKC71E and the LAPKC71F seems to be the dedicated NVidia GPU module.

Add support for this device as well. It is suspected that the LAPKC71F
also supports the new UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL feature, but
this would need to be verified on real hardware.

Link: https://github.com/Wer-Wolf/uniwill-laptop/issues/17
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
 drivers/platform/x86/uniwill/uniwill-acpi.c | 22 +++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 27d5e54f0e1c..433a7a0eeba6 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -2721,6 +2721,20 @@ static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
 		    UNIWILL_FEATURE_SECONDARY_FAN,
 };
 
+static struct uniwill_device_descriptor lapkc71e_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
+		    UNIWILL_FEATURE_LIGHTBAR |
+		    UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_GPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN |
+		    UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
+	.lightbar_max_intensity = 200,
+};
+
 static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
 	.features = UNIWILL_FEATURE_FN_LOCK |
 		    UNIWILL_FEATURE_SUPER_KEY |
@@ -2946,6 +2960,14 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 		},
 		.driver_data = &lapac71h_descriptor,
 	},
+	{
+		.ident = "Intel NUC x15",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71E"),
+		},
+		.driver_data = &lapkc71e_descriptor,
+	},
 	{
 		.ident = "Intel NUC x15",
 		.matches = {
-- 
2.39.5


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes
  2026-09-05 13:01 [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
                   ` (4 preceding siblings ...)
  2026-09-05 13:01 ` [PATCH 5/5] platform/x86: uniwill-laptop: Extend support for the Intel NUC x15 Armin Wolf
@ 2026-09-22 20:45 ` Armin Wolf
  5 siblings, 0 replies; 9+ messages in thread
From: Armin Wolf @ 2026-09-22 20:45 UTC (permalink / raw)
  To: hansg, ilpo.jarvinen; +Cc: wse, platform-driver-x86, linux-kernel

Am 05.09.26 um 15:01 schrieb Armin Wolf:

> This patch series mainly deals with various issues inside the code
> responsible for controlling the lightbar on supported devices.
>
> The first patch utilizes the improved multicolor LED API to report
> the correct brightness of the lightbar to userspace. The next two
> patches fix issues discovered inside the code for controlling
> animations, while the fourth patch fixes an issue with the naming
> of the LEDs in general. The last patch also adds support for another
> variant of the Intel NUC x15 laptop kit.
>
> All patches have been tested on said Intel NUC x15 laptop and appear
> to work.

Any thoughts on this series?

Thanks,
Armin Wolf

>
> Armin Wolf (5):
>    platform/x86: uniwill-laptop: Report correct lightbar brightness
>    platform/x86: uniwill-laptop: Implement rainbow animation as trigger
>    platform/x86: uniwill-laptop: Fix breathing animation on Intel QC
>    platform/x86: uniwill-laptop: Label multicolor LEDs correctly
>    platform/x86: uniwill-laptop: Extend support for the Intel NUC x15
>
>   .../ABI/removed/sysfs-driver-uniwill-laptop   |  10 +
>   .../ABI/testing/sysfs-driver-uniwill-laptop   |  15 +-
>   .../admin-guide/laptops/uniwill-laptop.rst    |   9 +-
>   MAINTAINERS                                   |   1 +
>   drivers/platform/x86/uniwill/Kconfig          |   1 +
>   drivers/platform/x86/uniwill/uniwill-acpi.c   | 225 +++++++++++-------
>   6 files changed, 161 insertions(+), 100 deletions(-)
>   create mode 100644 Documentation/ABI/removed/sysfs-driver-uniwill-laptop
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/5] platform/x86: uniwill-laptop: Report correct lightbar brightness
  2026-09-05 13:01 ` [PATCH 1/5] platform/x86: uniwill-laptop: Report correct lightbar brightness Armin Wolf
@ 2026-10-05 16:12   ` Ilpo Järvinen
  0 siblings, 0 replies; 9+ messages in thread
From: Ilpo Järvinen @ 2026-10-05 16:12 UTC (permalink / raw)
  To: Armin Wolf; +Cc: Hans de Goede, wse, platform-driver-x86, LKML

On Sat, 5 Sep 2026, Armin Wolf wrote:

> The LED sysfs ABI now allows us to specify the maximum values for the
> global brightness and the color intensity values independently. At the
> same time the maximum brightness value reported for the lightbar (like
> 200) does not match the real value supported by the hardware (1),
> potentially confusing users.
> 
> Report the correct maximum brightness value and only use the intensity
> values for controlling the lightbar color.
> 
> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
> ---
>  drivers/platform/x86/uniwill/uniwill-acpi.c | 35 ++++++++++-----------
>  1 file changed, 16 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index 7a2eeaec4c96..7420e1dd4716 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -398,7 +398,7 @@ struct uniwill_data {
>  	struct mutex super_key_lock;	/* Protects the toggling of the super key lock state */
>  	struct list_head batteries;
>  	struct mutex led_lock;		/* Protects writes to the lightbar registers */
> -	u8 lightbar_max_brightness;
> +	u8 lightbar_max_intensity;
>  	struct led_classdev_mc led_mc_cdev;
>  	struct mc_subled led_mc_subled_info[LED_CHANNELS];
>  	bool kbd_led_single_color;
> @@ -429,7 +429,7 @@ struct uniwill_device_descriptor {
>  	unsigned int features;
>  	bool kbd_led_single_color;
>  	u8 kbd_led_max_brightness;
> -	u8 lightbar_max_brightness;
> +	u8 lightbar_max_intensity;
>  	/* Executed during driver probing */
>  	int (*probe)(struct uniwill_data *data);
>  };
> @@ -1509,20 +1509,16 @@ static int uniwill_led_brightness_set(struct led_classdev *led_cdev, enum led_br
>  	unsigned int value;
>  	int ret;
>  
> -	ret = led_mc_calc_color_components(led_mc_cdev, brightness);
> -	if (ret < 0)
> -		return ret;
> -
>  	guard(mutex)(&data->led_lock);
>  
>  	for (int i = 0; i < LED_CHANNELS; i++) {
> -		/* Prevent the brightness values from overflowing */
> -		value = min(data->lightbar_max_brightness, data->led_mc_subled_info[i].brightness);
> -		ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
> +		ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i],
> +				   data->led_mc_subled_info[i].intensity);
>  		if (ret < 0)
>  			return ret;
>  
> -		ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value);
> +		ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i],
> +				   data->led_mc_subled_info[i].intensity);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -1586,14 +1582,14 @@ static int uniwill_led_init(struct uniwill_data *data)
>  		return ret;
>  
>  	data->led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;
> -	data->led_mc_cdev.led_cdev.max_brightness = data->lightbar_max_brightness;
> +	data->led_mc_cdev.led_cdev.max_brightness = 1;
>  	data->led_mc_cdev.led_cdev.flags = LED_REJECT_NAME_CONFLICT;
>  	data->led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_led_brightness_set;
>  
>  	if (value & LIGHTBAR_S0_OFF)
>  		data->led_mc_cdev.led_cdev.brightness = 0;
>  	else
> -		data->led_mc_cdev.led_cdev.brightness = data->lightbar_max_brightness;
> +		data->led_mc_cdev.led_cdev.brightness = 1;
>  
>  	for (int i = 0; i < LED_CHANNELS; i++) {
>  		data->led_mc_subled_info[i].color_index = color_indices[i];
> @@ -1604,9 +1600,9 @@ static int uniwill_led_init(struct uniwill_data *data)
>  
>  		/*
>  		 * Make sure that the initial intensity value is not greater than
> -		 * the maximum brightness.
> +		 * the maximum intensity.
>  		 */
> -		value = min(data->lightbar_max_brightness, value);
> +		value = min(data->lightbar_max_intensity, value);
>  		ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
>  		if (ret < 0)
>  			return ret;
> @@ -1616,6 +1612,7 @@ static int uniwill_led_init(struct uniwill_data *data)
>  			return ret;
>  
>  		data->led_mc_subled_info[i].intensity = value;
> +		data->led_mc_subled_info[i].max_intensity = data->lightbar_max_intensity;
>  		data->led_mc_subled_info[i].channel = i;
>  	}
>  
> @@ -2338,7 +2335,7 @@ static int uniwill_probe(struct platform_device *pdev)
>  	data->features = device_descriptor.features;
>  	data->kbd_led_single_color = device_descriptor.kbd_led_single_color;
>  	data->kbd_led_max_brightness = device_descriptor.kbd_led_max_brightness;
> -	data->lightbar_max_brightness = device_descriptor.lightbar_max_brightness;
> +	data->lightbar_max_intensity = device_descriptor.lightbar_max_intensity;
>  
>  	/*
>  	 * Some devices might need to perform some device-specific initialization steps
> @@ -2685,7 +2682,7 @@ static struct uniwill_device_descriptor lapqc71a_lapqc71b_descriptor __initdata
>  		    UNIWILL_FEATURE_GPU_TEMP |
>  		    UNIWILL_FEATURE_PRIMARY_FAN |
>  		    UNIWILL_FEATURE_SECONDARY_FAN,
> -	.lightbar_max_brightness = 36,
> +	.lightbar_max_intensity = 36,
>  };
>  
>  static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
> @@ -2709,7 +2706,7 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
>  		    UNIWILL_FEATURE_GPU_TEMP |
>  		    UNIWILL_FEATURE_PRIMARY_FAN |
>  		    UNIWILL_FEATURE_SECONDARY_FAN,
> -	.lightbar_max_brightness = 200,
> +	.lightbar_max_intensity = 200,
>  };

Can you respin this on top of what's in the review-ilpo-next I think there 
are now more entries to touch after Werner's descriptor splits.

>  /*
> @@ -3355,8 +3352,8 @@ static int __init uniwill_init(void)
>  		device_descriptor.kbd_led_single_color = false;
>  		/* Some models only support 3 brightness levels */
>  		device_descriptor.kbd_led_max_brightness = 4;
> -		/* Some models only support 36 brightness levels per color component */
> -		device_descriptor.lightbar_max_brightness = 200;
> +		/* Some models only support 36 intensity levels per color component */
> +		device_descriptor.lightbar_max_intensity = 200;
>  		pr_warn("Enabling potentially unsupported features\n");
>  	}
>  
> 

-- 
 i.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/5] platform/x86: uniwill-laptop: Fix breathing animation on Intel QC
  2026-09-05 13:01 ` [PATCH 3/5] platform/x86: uniwill-laptop: Fix breathing animation on Intel QC Armin Wolf
@ 2026-10-05 16:13   ` Ilpo Järvinen
  0 siblings, 0 replies; 9+ messages in thread
From: Ilpo Järvinen @ 2026-10-05 16:13 UTC (permalink / raw)
  To: Armin Wolf; +Cc: hansg, ilpo.jarvinen, wse, platform-driver-x86, linux-kernel

On Sat, 5 Sep 2026, Armin Wolf wrote:

> Intel NUC 9 Extreme (Queens County) devices have a separate bit
> inside the EC_ADDR_LIGHTBAR_AC:CTRL register for enabling the

Should be _

-- 
 i.


> breathing animation in s2idle mode.
> 
> Add support for this additional setting.
> 
> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
> ---
>  .../ABI/testing/sysfs-driver-uniwill-laptop   |  4 +--
>  drivers/platform/x86/uniwill/uniwill-acpi.c   | 27 ++++++++++++++-----
>  2 files changed, 22 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> index b9b9feebe2ed..f3060aaf8a76 100644
> --- a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> +++ b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> @@ -35,8 +35,8 @@ KernelVersion:	6.19
>  Contact:	Armin Wolf <W_Armin@gmx.de>
>  Description:
>  		Causes the integrated lightbar to display a breathing animation when the machine
> -		has been suspended and is running on AC power. Writing "1"/"0" into this file
> -		enables/disables this functionality.
> +		has been suspended, is running on AC power and the lightbar brightness not zero.
> +		Writing "1"/"0" into this file enables/disables this functionality.
>  
>  		Reading this file returns the current status of the breathing animation
>  		functionality.
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index 6366171c6981..e527ed7461c3 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -165,9 +165,10 @@
>  #define EC_ADDR_LIGHTBAR_AC_CTRL	0x0748
>  #define LIGHTBAR_APP_EXISTS		BIT(0)
>  #define LIGHTBAR_POWER_SAVE		BIT(1)
> -#define LIGHTBAR_S0_OFF			BIT(2)
> -#define LIGHTBAR_S3_OFF			BIT(3)	// Breathing animation when suspended
> -#define LIGHTBAR_WELCOME		BIT(7)	// Rainbow animation
> +#define LIGHTBAR_S0_OFF			BIT(2)	/* Also disables animations */
> +#define LIGHTBAR_S3_OFF			BIT(3)	/* No breathing animation when in s2ram */
> +#define LIGHTBAR_MODERN_STANDBY_ON	BIT(6)	/* Breathing animation when in s2idle */
> +#define LIGHTBAR_WELCOME		BIT(7)	/* Rainbow animation */
>  
>  #define EC_ADDR_LIGHTBAR_AC_RED		0x0749
>  
> @@ -306,7 +307,7 @@
>  #define EC_ADDR_USB_C_POWER_PRIORITY	0x07CC
>  #define USB_C_POWER_PRIORITY		BIT(7)
>  
> -/* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF */
> +/* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF and LIGHTBAR_MODERN_STANDBY_ON */
>  #define EC_ADDR_LIGHTBAR_BAT_CTRL	0x07E2
>  
>  #define EC_ADDR_LIGHTBAR_BAT_RED	0x07E3
> @@ -911,12 +912,13 @@ static ssize_t breathing_in_suspend_store(struct device *dev, struct device_attr
>  		return ret;
>  
>  	if (enable)
> -		value = 0;
> +		value = LIGHTBAR_MODERN_STANDBY_ON;
>  	else
>  		value = LIGHTBAR_S3_OFF;
>  
>  	/* We only access a single register here, so we do not need to use data->led_lock */
> -	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S3_OFF, value);
> +	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL,
> +				 LIGHTBAR_S3_OFF | LIGHTBAR_MODERN_STANDBY_ON, value);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -934,6 +936,10 @@ static ssize_t breathing_in_suspend_show(struct device *dev, struct device_attri
>  	if (ret < 0)
>  		return ret;
>  
> +	/*
> +	 * We only test LIGHTBAR_S3_OFF here, because LIGHTBAR_MODERN_STANDBY_ON
> +	 * should have the exact opposite value.
> +	 */
>  	return sysfs_emit(buf, "%d\n", !(value & LIGHTBAR_S3_OFF));
>  }
>  
> @@ -1541,7 +1547,8 @@ static struct led_trigger uniwill_lightbar_trigger = {
>  	.trigger_type = &uniwill_lightbar_trigger_type,
>  };
>  
> -#define LIGHTBAR_MASK	(LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | LIGHTBAR_WELCOME)
> +#define LIGHTBAR_MASK	(LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | \
> +			 LIGHTBAR_MODERN_STANDBY_ON | LIGHTBAR_WELCOME)
>  
>  static int uniwill_led_init(struct uniwill_data *data)
>  {
> @@ -1574,6 +1581,11 @@ static int uniwill_led_init(struct uniwill_data *data)
>  		return ret;
>  
>  	value |= LIGHTBAR_APP_EXISTS;
> +	if (value & LIGHTBAR_S3_OFF)
> +		value &= ~LIGHTBAR_MODERN_STANDBY_ON;
> +	else
> +		value |= LIGHTBAR_MODERN_STANDBY_ON;
> +
>  	ret = regmap_write(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, value);
>  	if (ret < 0)
>  		return ret;
> @@ -1583,6 +1595,7 @@ static int uniwill_led_init(struct uniwill_data *data)
>  	 * running on battery power.
>  	 */
>  	value |= LIGHTBAR_S3_OFF;
> +	value &= ~LIGHTBAR_MODERN_STANDBY_ON;
>  	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_MASK, value);
>  	if (ret < 0)
>  		return ret;
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-05 16:13 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-05 13:01 [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf
2026-09-05 13:01 ` [PATCH 1/5] platform/x86: uniwill-laptop: Report correct lightbar brightness Armin Wolf
2026-10-05 16:12   ` Ilpo Järvinen
2026-09-05 13:01 ` [PATCH 2/5] platform/x86: uniwill-laptop: Implement rainbow animation as trigger Armin Wolf
2026-09-05 13:01 ` [PATCH 3/5] platform/x86: uniwill-laptop: Fix breathing animation on Intel QC Armin Wolf
2026-10-05 16:13   ` Ilpo Järvinen
2026-09-05 13:01 ` [PATCH 4/5] platform/x86: uniwill-laptop: Label multicolor LEDs correctly Armin Wolf
2026-09-05 13:01 ` [PATCH 5/5] platform/x86: uniwill-laptop: Extend support for the Intel NUC x15 Armin Wolf
2026-09-22 20:45 ` [PATCH 0/5] platform/x86: uniwill-laptop: Lightbar fixes Armin Wolf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®