mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 1/4] platform/x86/uniwill: uniwill-laptop: Rework hwmon feature defines
       [not found] <20260226205302.123782-1-wse@tuxedocomputers.com>
@ 2026-02-26 20:50 ` Werner Sembach
  2026-02-27  9:28   ` Armin Wolf
  2026-02-26 20:50 ` [PATCH v2 2/4] platform/x86/uniwill: Implement USB-C power priority setting Werner Sembach
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Werner Sembach @ 2026-02-26 20:50 UTC (permalink / raw)
  To: Armin Wolf, Hans de Goede, Ilpo Järvinen
  Cc: Werner Sembach, platform-driver-x86, linux-kernel

From: Armin Wolf <W_Armin@gmx.de>

Split hwmon feature define in smaller parts to accommodate for diverse
hardware. You can now specify the presence of a cpu and/or a gpu temp
sensor separately and if one or 2 fans exists.

Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
---
 drivers/platform/x86/uniwill/uniwill-acpi.c | 68 ++++++++++++++++++---
 1 file changed, 61 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 6341dca20b76a..7ab82cf16f388 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -319,8 +319,11 @@
 #define UNIWILL_FEATURE_TOUCHPAD_TOGGLE		BIT(2)
 #define UNIWILL_FEATURE_LIGHTBAR		BIT(3)
 #define UNIWILL_FEATURE_BATTERY			BIT(4)
-#define UNIWILL_FEATURE_HWMON			BIT(5)
-#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL	BIT(6)
+#define UNIWILL_FEATURE_CPU_TEMP		BIT(5)
+#define UNIWILL_FEATURE_GPU_TEMP		BIT(6)
+#define UNIWILL_FEATURE_PRIMARY_FAN		BIT(7)
+#define UNIWILL_FEATURE_SECONDARY_FAN		BIT(8)
+#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL	BIT(9)
 
 struct uniwill_data {
 	struct device *dev;
@@ -427,7 +430,7 @@ static const struct key_entry uniwill_keymap[] = {
 	{ KE_END }
 };
 
-static inline bool uniwill_device_supports(struct uniwill_data *data,
+static inline bool uniwill_device_supports(const struct uniwill_data *data,
 					   unsigned int features)
 {
 	return (data->features & features) == features;
@@ -937,6 +940,48 @@ static const struct attribute_group *uniwill_groups[] = {
 	NULL
 };
 
+static umode_t uniwill_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,
+				  int channel)
+{
+	const struct uniwill_data *data = drvdata;
+	unsigned int feature;
+
+	switch (type) {
+	case hwmon_temp:
+		switch (channel) {
+		case 0:
+			feature = UNIWILL_FEATURE_CPU_TEMP;
+			break;
+		case 1:
+			feature = UNIWILL_FEATURE_GPU_TEMP;
+			break;
+		default:
+			return 0;
+		}
+		break;
+	case hwmon_fan:
+	case hwmon_pwm:
+		switch (channel) {
+		case 0:
+			feature = UNIWILL_FEATURE_PRIMARY_FAN;
+			break;
+		case 1:
+			feature = UNIWILL_FEATURE_SECONDARY_FAN;
+			break;
+		default:
+			return 0;
+		}
+		break;
+	default:
+		return 0;
+	}
+
+	if (uniwill_device_supports(data, feature))
+		return 0440;
+
+	return 0;
+}
+
 static int uniwill_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
 			long *val)
 {
@@ -1020,7 +1065,7 @@ static int uniwill_read_string(struct device *dev, enum hwmon_sensor_types type,
 }
 
 static const struct hwmon_ops uniwill_ops = {
-	.visible = 0444,
+	.is_visible = uniwill_is_visible,
 	.read = uniwill_read,
 	.read_string = uniwill_read_string,
 };
@@ -1048,7 +1093,10 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
 {
 	struct device *hdev;
 
-	if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON))
+	if (!uniwill_device_supports(data, UNIWILL_FEATURE_CPU_TEMP) &&
+	    !uniwill_device_supports(data, UNIWILL_FEATURE_GPU_TEMP) &&
+	    !uniwill_device_supports(data, UNIWILL_FEATURE_PRIMARY_FAN) &&
+	    !uniwill_device_supports(data, UNIWILL_FEATURE_SECONDARY_FAN))
 		return 0;
 
 	hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
@@ -1687,7 +1735,10 @@ static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
 		    UNIWILL_FEATURE_SUPER_KEY |
 		    UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
 		    UNIWILL_FEATURE_BATTERY |
-		    UNIWILL_FEATURE_HWMON,
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_GPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN,
 };
 
 static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
@@ -1696,7 +1747,10 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
 		    UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
 		    UNIWILL_FEATURE_LIGHTBAR |
 		    UNIWILL_FEATURE_BATTERY |
-		    UNIWILL_FEATURE_HWMON,
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_GPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN,
 };
 
 static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
-- 
2.43.0


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

* [PATCH v2 2/4] platform/x86/uniwill: Implement USB-C power priority setting
       [not found] <20260226205302.123782-1-wse@tuxedocomputers.com>
  2026-02-26 20:50 ` [PATCH v2 1/4] platform/x86/uniwill: uniwill-laptop: Rework hwmon feature defines Werner Sembach
@ 2026-02-26 20:50 ` Werner Sembach
  2026-02-27  9:31   ` Armin Wolf
  2026-02-26 20:50 ` [PATCH v2 3/4] platform/x86/uniwill: Apply features across all TUXEDO devices Werner Sembach
  2026-02-26 20:50 ` [PATCH v2 4/4] Documentation: laptops: Update documentation for uniwill laptops Werner Sembach
  3 siblings, 1 reply; 10+ messages in thread
From: Werner Sembach @ 2026-02-26 20:50 UTC (permalink / raw)
  To: Armin Wolf, Hans de Goede, Ilpo Järvinen
  Cc: Werner Sembach, platform-driver-x86, linux-kernel

On some devices Uniwill offers the option to set the USB-C port to
prioritise charging or performance. This patch exposes this setting to the
userspace via sysfs for all TUXEDO devices supporting it.

Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
---
 drivers/platform/x86/uniwill/uniwill-acpi.c | 103 ++++++++++++++++++--
 1 file changed, 97 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 7ab82cf16f388..a34b1eed74eb2 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -266,8 +266,8 @@
 #define BATTERY_CHARGE_FULL_OVER_24H	BIT(3)
 #define BATTERY_ERM_STATUS_REACHED	BIT(4)
 
-#define EC_ADDR_CHARGE_PRIO		0x07CC
-#define CHARGING_PERFORMANCE		BIT(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 */
 #define EC_ADDR_LIGHTBAR_BAT_CTRL	0x07E2
@@ -324,6 +324,7 @@
 #define UNIWILL_FEATURE_PRIMARY_FAN		BIT(7)
 #define UNIWILL_FEATURE_SECONDARY_FAN		BIT(8)
 #define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL	BIT(9)
+#define UNIWILL_FEATURE_USB_C_POWER_PRIORITY	BIT(10)
 
 struct uniwill_data {
 	struct device *dev;
@@ -343,6 +344,8 @@ struct uniwill_data {
 	struct mutex input_lock;	/* Protects input sequence during notify */
 	struct input_dev *input_device;
 	struct notifier_block nb;
+	struct mutex usb_c_power_priority_lock; /* Protects dependent bit write and state safe */
+	unsigned int last_usb_c_power_priority;
 };
 
 struct uniwill_battery_entry {
@@ -527,6 +530,7 @@ static bool uniwill_writeable_reg(struct device *dev, unsigned int reg)
 	case EC_ADDR_CTGP_DB_CTGP_OFFSET:
 	case EC_ADDR_CTGP_DB_TPP_OFFSET:
 	case EC_ADDR_CTGP_DB_DB_OFFSET:
+	case EC_ADDR_USB_C_POWER_PRIORITY:
 		return true;
 	default:
 		return false;
@@ -565,6 +569,7 @@ static bool uniwill_readable_reg(struct device *dev, unsigned int reg)
 	case EC_ADDR_CTGP_DB_CTGP_OFFSET:
 	case EC_ADDR_CTGP_DB_TPP_OFFSET:
 	case EC_ADDR_CTGP_DB_DB_OFFSET:
+	case EC_ADDR_USB_C_POWER_PRIORITY:
 		return true;
 	default:
 		return false;
@@ -587,6 +592,7 @@ static bool uniwill_volatile_reg(struct device *dev, unsigned int reg)
 	case EC_ADDR_TRIGGER:
 	case EC_ADDR_SWITCH_STATUS:
 	case EC_ADDR_CHARGE_CTRL:
+	case EC_ADDR_USB_C_POWER_PRIORITY:
 		return true;
 	default:
 		return false;
@@ -883,6 +889,78 @@ static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
 	return 0;
 }
 
+enum usb_c_power_priority_options {
+	USB_C_POWER_PRIORITY_OPTIONS_CHARGING = 0,
+	USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE,
+};
+
+static const char * const USB_C_POWER_PRIORITY_OPTIONS_TEXT[] = {
+	[USB_C_POWER_PRIORITY_OPTIONS_CHARGING]		= "charging",
+	[USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE]	= "performance",
+};
+
+static const u8 USB_C_POWER_PRIORITY_OPTIONS_VALUE[] = {
+	[USB_C_POWER_PRIORITY_OPTIONS_CHARGING]		= 0,
+	[USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE]	= USB_C_POWER_PRIORITY,
+};
+
+static ssize_t usb_c_power_priority_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;
+	int ret;
+
+	ret = sysfs_match_string(USB_C_POWER_PRIORITY_OPTIONS_TEXT, buf);
+	if (ret < 0)
+		return ret;
+
+	value = USB_C_POWER_PRIORITY_OPTIONS_VALUE[ret];
+
+	guard(mutex)(&data->usb_c_power_priority_lock);
+
+	ret = regmap_update_bits(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY,
+				 USB_C_POWER_PRIORITY, value);
+	if (ret < 0)
+		return ret;
+
+	data->last_usb_c_power_priority = value;
+
+	return count;
+}
+
+static ssize_t usb_c_power_priority_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct uniwill_data *data = dev_get_drvdata(dev);
+	unsigned int value;
+	ssize_t count = 0;
+	int ret;
+
+	ret = regmap_read(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY, &value);
+	if (ret < 0)
+		return ret;
+
+	value &= USB_C_POWER_PRIORITY;
+
+	for (int i = 0; i < ARRAY_SIZE(USB_C_POWER_PRIORITY_OPTIONS_VALUE); ++i) {
+		if (USB_C_POWER_PRIORITY_OPTIONS_VALUE[i] == value)
+			count += sysfs_emit_at(buf, count, "[%s] ",
+					       USB_C_POWER_PRIORITY_OPTIONS_TEXT[i]);
+		else
+			count += sysfs_emit_at(buf, count, "%s ",
+					       USB_C_POWER_PRIORITY_OPTIONS_TEXT[i]);
+	}
+	if (count)
+		buf[count - 1] = '\n';
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(usb_c_power_priority);
+
 static struct attribute *uniwill_attrs[] = {
 	/* Keyboard-related */
 	&dev_attr_fn_lock.attr,
@@ -893,6 +971,7 @@ static struct attribute *uniwill_attrs[] = {
 	&dev_attr_breathing_in_suspend.attr,
 	/* Power-management-related */
 	&dev_attr_ctgp_offset.attr,
+	&dev_attr_usb_c_power_priority.attr,
 	NULL
 };
 
@@ -927,6 +1006,11 @@ static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *a
 			return attr->mode;
 	}
 
+	if (attr == &dev_attr_usb_c_power_priority.attr) {
+		if (uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
+			return attr->mode;
+	}
+
 	return 0;
 }
 
@@ -1417,11 +1501,13 @@ static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action
 
 		return NOTIFY_OK;
 	case UNIWILL_OSD_DC_ADAPTER_CHANGED:
-		/* noop for the time being, will change once charging priority
-		 * gets implemented.
-		 */
+		if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
+			return NOTIFY_DONE;
 
-		return NOTIFY_OK;
+		return notifier_from_errno(regmap_update_bits(data->regmap,
+							      EC_ADDR_OEM_4,
+							      USB_C_POWER_PRIORITY,
+							      data->last_usb_c_power_priority));
 	case UNIWILL_OSD_FN_LOCK:
 		if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
 			return NOTIFY_DONE;
@@ -1515,10 +1601,15 @@ static int uniwill_probe(struct platform_device *pdev)
 		return PTR_ERR(regmap);
 
 	data->regmap = regmap;
+
 	ret = devm_mutex_init(&pdev->dev, &data->super_key_lock);
 	if (ret < 0)
 		return ret;
 
+	ret = devm_mutex_init(&pdev->dev, &data->usb_c_power_priority_lock);
+	if (ret < 0)
+		return ret;
+
 	ret = uniwill_ec_init(data);
 	if (ret < 0)
 		return ret;
-- 
2.43.0


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

* [PATCH v2 3/4] platform/x86/uniwill: Apply features across all TUXEDO devices
       [not found] <20260226205302.123782-1-wse@tuxedocomputers.com>
  2026-02-26 20:50 ` [PATCH v2 1/4] platform/x86/uniwill: uniwill-laptop: Rework hwmon feature defines Werner Sembach
  2026-02-26 20:50 ` [PATCH v2 2/4] platform/x86/uniwill: Implement USB-C power priority setting Werner Sembach
@ 2026-02-26 20:50 ` Werner Sembach
  2026-02-27  9:35   ` Armin Wolf
  2026-02-26 20:50 ` [PATCH v2 4/4] Documentation: laptops: Update documentation for uniwill laptops Werner Sembach
  3 siblings, 1 reply; 10+ messages in thread
From: Werner Sembach @ 2026-02-26 20:50 UTC (permalink / raw)
  To: Armin Wolf, Hans de Goede, Ilpo Järvinen
  Cc: Werner Sembach, platform-driver-x86, linux-kernel

Uses the more fine granular and/or new feature defines to enable more
features across the TUXEDO device lineup.

Also adds features defines that where already present, but not tested until
now.

Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
---
 drivers/platform/x86/uniwill/uniwill-acpi.c | 214 ++++++++++++++------
 1 file changed, 156 insertions(+), 58 deletions(-)

diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index a34b1eed74eb2..f54b27ae832d2 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -110,6 +110,8 @@
 #define EC_ADDR_BAT_CYCLE_COUNT_2	0x04A7
 
 #define EC_ADDR_PROJECT_ID		0x0740
+#define PROJECT_ID_PH4TRX1		0x12
+#define PROJECT_ID_PH6TRX1		0x15
 
 #define EC_ADDR_AP_OEM			0x0741
 #define	ENABLE_MANUAL_CTRL		BIT(0)
@@ -1821,6 +1823,15 @@ static struct platform_driver uniwill_driver = {
 	.shutdown = uniwill_shutdown,
 };
 
+static struct uniwill_device_descriptor lapqc71a_lapqc71b_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_BATTERY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_GPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN,
+};
+
 static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
 	.features = UNIWILL_FEATURE_FN_LOCK |
 		    UNIWILL_FEATURE_SUPER_KEY |
@@ -1844,6 +1855,85 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
 		    UNIWILL_FEATURE_SECONDARY_FAN,
 };
 
+/*
+ * The featuresets below reflect somewhat chronological changes:
+ * 1 -> 2: UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL is added to the EC firmware.
+ * 2 -> 3: UNIWILL_FEATURE_USB_C_POWER_PRIORITY is removed from the EC firmware.
+ * Some devices might divert from this timeline.
+ */
+
+static struct uniwill_device_descriptor tux_featureset_1_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN |
+		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
+};
+
+static struct uniwill_device_descriptor tux_featureset_1_nvidia_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_GPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN |
+		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
+};
+
+static struct uniwill_device_descriptor tux_featureset_2_nvidia_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_GPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN |
+		    UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL |
+		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
+};
+
+static struct uniwill_device_descriptor tux_featureset_3_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN,
+};
+
+static struct uniwill_device_descriptor tux_featureset_3_nvidia_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_GPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN |
+		    UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
+};
+
+static int phxtxx1_probe(struct uniwill_data *data)
+{
+	unsigned int value;
+	int ret;
+
+	ret = regmap_read(data->regmap, EC_ADDR_PROJECT_ID, &value);
+	if (ret < 0)
+		return ret;
+
+	if (value == PROJECT_ID_PH4TRX1 || value == PROJECT_ID_PH6TRX1)
+		data->features |= UNIWILL_FEATURE_SECONDARY_FAN;
+
+	return 0;
+};
+
+static struct uniwill_device_descriptor phxtxx1_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
+	.probe = phxtxx1_probe,
+};
+
 static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
 {
 	unsigned int value;
@@ -1854,37 +1944,45 @@ static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
 		return ret;
 
 	if (value & HAS_GPU)
-		data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
+		data->features |= UNIWILL_FEATURE_GPU_TEMP |
+				  UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
 
 	return 0;
 };
 
 static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN |
+		    UNIWILL_FEATURE_SECONDARY_FAN |
+		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
 	.probe = phxarx1_phxaqf1_probe,
 };
 
-static struct uniwill_device_descriptor tux_featureset_1_descriptor __initdata = {
-	.features = UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
+static struct uniwill_device_descriptor pf5pu1g_descriptor __initdata = {
+	.features = UNIWILL_FEATURE_FN_LOCK |
+		    UNIWILL_FEATURE_SUPER_KEY |
+		    UNIWILL_FEATURE_CPU_TEMP |
+		    UNIWILL_FEATURE_PRIMARY_FAN,
 };
 
-static struct uniwill_device_descriptor empty_descriptor __initdata = {};
-
 static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 	{
-		.ident = "XMG FUSION 15",
+		.ident = "XMG FUSION 15 (L19)",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
+			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &lapqc71a_lapqc71b_descriptor,
 	},
 	{
-		.ident = "XMG FUSION 15",
+		.ident = "XMG FUSION 15 (L19)",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
+			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &lapqc71a_lapqc71b_descriptor,
 	},
 	{
 		.ident = "Intel NUC x15",
@@ -1908,7 +2006,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTxX1"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &phxtxx1_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
@@ -1916,7 +2014,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
@@ -1932,7 +2030,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1940,7 +2038,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1948,7 +2046,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
@@ -1956,7 +2054,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
@@ -1964,7 +2062,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxHRXx"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
@@ -1972,7 +2070,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxMRXx"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
@@ -1980,7 +2078,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxHP4NAx"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
@@ -1988,7 +2086,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
@@ -1996,7 +2094,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxAR4NAx"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
@@ -2004,7 +2102,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
@@ -2012,7 +2110,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6HP45xU"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
@@ -2020,7 +2118,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6KK45xU_X6SP45xU"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
@@ -2028,7 +2126,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5AR45xS"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
@@ -2036,7 +2134,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR55xU"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 15 Gen1 AMD",
@@ -2044,7 +2142,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 15 Gen1 AMD",
@@ -2052,7 +2150,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 17 Gen1 AMD",
@@ -2060,7 +2158,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 17 Gen1 AMD",
@@ -2068,7 +2166,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 15 Gen1 Intel",
@@ -2076,7 +2174,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I1650TI"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 15 Gen1 Intel",
@@ -2084,7 +2182,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I2060"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 17 Gen1 Intel",
@@ -2092,7 +2190,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I1650TI"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 17 Gen1 Intel",
@@ -2100,7 +2198,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I2060"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Trinity 15 Intel Gen1",
@@ -2108,7 +2206,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1501I"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Trinity 17 Intel Gen1",
@@ -2116,7 +2214,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1701I"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 15/17 Gen2 AMD",
@@ -2124,7 +2222,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 15/17 Gen2 Intel",
@@ -2132,7 +2230,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
@@ -2140,7 +2238,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
@@ -2148,7 +2246,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
@@ -2156,7 +2254,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 15 Gen4 Intel",
@@ -2164,7 +2262,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Polaris 15/17 Gen5 AMD",
@@ -2172,7 +2270,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_2_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 16 Gen5 AMD",
@@ -2180,7 +2278,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
@@ -2188,7 +2286,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
@@ -2196,7 +2294,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
@@ -2204,7 +2302,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -2212,7 +2310,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -2220,7 +2318,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
@@ -2228,7 +2326,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 16 Gen7 AMD",
@@ -2236,7 +2334,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -2244,7 +2342,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -2252,7 +2350,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"),
 		},
-		.driver_data = &tux_featureset_1_descriptor,
+		.driver_data = &tux_featureset_3_nvidia_descriptor,
 	},
 	{
 		.ident = "TUXEDO Book BA15 Gen10 AMD",
@@ -2260,7 +2358,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &pf5pu1g_descriptor,
 	},
 	{
 		.ident = "TUXEDO Pulse 14 Gen1 AMD",
@@ -2268,7 +2366,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1401"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_descriptor,
 	},
 	{
 		.ident = "TUXEDO Pulse 15 Gen1 AMD",
@@ -2276,7 +2374,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1501"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_descriptor,
 	},
 	{
 		.ident = "TUXEDO Pulse 15 Gen2 AMD",
@@ -2284,7 +2382,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
 		},
-		.driver_data = &empty_descriptor,
+		.driver_data = &tux_featureset_1_descriptor,
 	},
 	{ }
 };
-- 
2.43.0


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

* [PATCH v2 4/4] Documentation: laptops: Update documentation for uniwill laptops
       [not found] <20260226205302.123782-1-wse@tuxedocomputers.com>
                   ` (2 preceding siblings ...)
  2026-02-26 20:50 ` [PATCH v2 3/4] platform/x86/uniwill: Apply features across all TUXEDO devices Werner Sembach
@ 2026-02-26 20:50 ` Werner Sembach
  2026-02-27  9:36   ` Armin Wolf
  3 siblings, 1 reply; 10+ messages in thread
From: Werner Sembach @ 2026-02-26 20:50 UTC (permalink / raw)
  To: Armin Wolf, Jonathan Corbet, Shuah Khan
  Cc: Werner Sembach, platform-driver-x86, linux-kernel, linux-doc

Adds short description for two new sysfs entries, ctgp_offset and
usb_c_power_priority, to the documentation of uniwill laptops.

Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
---
 .../ABI/testing/sysfs-driver-uniwill-laptop   | 25 +++++++++++++++++++
 .../admin-guide/laptops/uniwill-laptop.rst    | 12 +++++++++
 2 files changed, 37 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
index 2df70792968f3..55943252f2ab9 100644
--- a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
+++ b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
@@ -51,3 +51,28 @@ Description:
 
 		Reading this file returns the current status of the breathing animation
 		functionality.
+
+What:		/sys/bus/platform/devices/INOU0000:XX/ctgp_offset
+Date:		January 2026
+KernelVersion:	7.0
+Contact:	Werner Sembach <wse@tuxedocomputers.com>
+Description:
+		Allows userspace applications to set the configurable TGP offset on top of the base
+		TGP. Base TGP and max TGP and therefore the max cTGP offset are device specific.
+		Note that setting the maximal cTGP leaves no window open for Dynamic Boost,
+		effectifly disabling that feature for the GPU to always be prioritized.
+
+		Reading this file returns the current configurable TGP offset.
+
+What:		/sys/bus/platform/devices/INOU0000:XX/usb_c_power_priority
+Date:		February 2026
+KernelVersion:	7.1
+Contact:	Werner Sembach <wse@tuxedocomputers.com>
+Description:
+		Allows userspace applications to set USB-C power distribution profile between one
+		that offers a bigger share of the power to the battery and one that offers more of
+		it to the CPU. Writing "charging"/"performance" into this file selects the
+		respective profile.
+
+		Reading this file returns the profile names with the currently active one in
+		brackets.
diff --git a/Documentation/admin-guide/laptops/uniwill-laptop.rst b/Documentation/admin-guide/laptops/uniwill-laptop.rst
index aff5f57a6bd47..c89b8b3756f84 100644
--- a/Documentation/admin-guide/laptops/uniwill-laptop.rst
+++ b/Documentation/admin-guide/laptops/uniwill-laptop.rst
@@ -50,6 +50,10 @@ between 1 and 100 percent are supported.
 Additionally the driver signals the presence of battery charging issues through the standard
 ``health`` power supply sysfs attribute.
 
+It also let you set whether an USB-C power source should prioritise charging the battery or
+delivering immediate power to the cpu. See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for
+details.
+
 Lightbar
 --------
 
@@ -58,3 +62,11 @@ LED class device. The default name of this LED class device is ``uniwill:multico
 
 See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details on how to control the various
 animation modes of the lightbar.
+
+Configurable TGP
+--------
+
+The ``uniwill-laptop`` driver allows to set the configurable TGP for devices with NVIDIA GPUs that
+allow it.
+
+See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details.
-- 
2.43.0


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

* Re: [PATCH v2 1/4] platform/x86/uniwill: uniwill-laptop: Rework hwmon feature defines
  2026-02-26 20:50 ` [PATCH v2 1/4] platform/x86/uniwill: uniwill-laptop: Rework hwmon feature defines Werner Sembach
@ 2026-02-27  9:28   ` Armin Wolf
  2026-02-27 18:45     ` Werner Sembach
  0 siblings, 1 reply; 10+ messages in thread
From: Armin Wolf @ 2026-02-27  9:28 UTC (permalink / raw)
  To: Werner Sembach, Hans de Goede, Ilpo Järvinen
  Cc: platform-driver-x86, linux-kernel

Am 26.02.26 um 21:50 schrieb Werner Sembach:

> From: Armin Wolf <W_Armin@gmx.de>
>
> Split hwmon feature define in smaller parts to accommodate for diverse
> hardware. You can now specify the presence of a cpu and/or a gpu temp
> sensor separately and if one or 2 fans exists.
>
> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
>   drivers/platform/x86/uniwill/uniwill-acpi.c | 68 ++++++++++++++++++---
>   1 file changed, 61 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index 6341dca20b76a..7ab82cf16f388 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -319,8 +319,11 @@
>   #define UNIWILL_FEATURE_TOUCHPAD_TOGGLE		BIT(2)
>   #define UNIWILL_FEATURE_LIGHTBAR		BIT(3)
>   #define UNIWILL_FEATURE_BATTERY			BIT(4)
> -#define UNIWILL_FEATURE_HWMON			BIT(5)
> -#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL	BIT(6)
> +#define UNIWILL_FEATURE_CPU_TEMP		BIT(5)
> +#define UNIWILL_FEATURE_GPU_TEMP		BIT(6)
> +#define UNIWILL_FEATURE_PRIMARY_FAN		BIT(7)
> +#define UNIWILL_FEATURE_SECONDARY_FAN		BIT(8)
> +#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL	BIT(9)
>   
>   struct uniwill_data {
>   	struct device *dev;
> @@ -427,7 +430,7 @@ static const struct key_entry uniwill_keymap[] = {
>   	{ KE_END }
>   };
>   
> -static inline bool uniwill_device_supports(struct uniwill_data *data,
> +static inline bool uniwill_device_supports(const struct uniwill_data *data,
>   					   unsigned int features)
>   {
>   	return (data->features & features) == features;
> @@ -937,6 +940,48 @@ static const struct attribute_group *uniwill_groups[] = {
>   	NULL
>   };
>   
> +static umode_t uniwill_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,
> +				  int channel)
> +{
> +	const struct uniwill_data *data = drvdata;
> +	unsigned int feature;
> +
> +	switch (type) {
> +	case hwmon_temp:
> +		switch (channel) {
> +		case 0:
> +			feature = UNIWILL_FEATURE_CPU_TEMP;
> +			break;
> +		case 1:
> +			feature = UNIWILL_FEATURE_GPU_TEMP;
> +			break;
> +		default:
> +			return 0;
> +		}
> +		break;
> +	case hwmon_fan:
> +	case hwmon_pwm:
> +		switch (channel) {
> +		case 0:
> +			feature = UNIWILL_FEATURE_PRIMARY_FAN;
> +			break;
> +		case 1:
> +			feature = UNIWILL_FEATURE_SECONDARY_FAN;
> +			break;
> +		default:
> +			return 0;
> +		}
> +		break;
> +	default:
> +		return 0;
> +	}
> +
> +	if (uniwill_device_supports(data, feature))
> +		return 0440;

I think you forgot this one.

> +
> +	return 0;
> +}
> +
>   static int uniwill_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
>   			long *val)
>   {
> @@ -1020,7 +1065,7 @@ static int uniwill_read_string(struct device *dev, enum hwmon_sensor_types type,
>   }
>   
>   static const struct hwmon_ops uniwill_ops = {
> -	.visible = 0444,
> +	.is_visible = uniwill_is_visible,
>   	.read = uniwill_read,
>   	.read_string = uniwill_read_string,
>   };
> @@ -1048,7 +1093,10 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
>   {
>   	struct device *hdev;
>   
> -	if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON))
> +	if (!uniwill_device_supports(data, UNIWILL_FEATURE_CPU_TEMP) &&
> +	    !uniwill_device_supports(data, UNIWILL_FEATURE_GPU_TEMP) &&
> +	    !uniwill_device_supports(data, UNIWILL_FEATURE_PRIMARY_FAN) &&
> +	    !uniwill_device_supports(data, UNIWILL_FEATURE_SECONDARY_FAN))
>   		return 0;
>   
>   	hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
> @@ -1687,7 +1735,10 @@ static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
>   		    UNIWILL_FEATURE_SUPER_KEY |
>   		    UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>   		    UNIWILL_FEATURE_BATTERY |
> -		    UNIWILL_FEATURE_HWMON,
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_GPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN,
>   };
>   
>   static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
> @@ -1696,7 +1747,10 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
>   		    UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>   		    UNIWILL_FEATURE_LIGHTBAR |
>   		    UNIWILL_FEATURE_BATTERY |
> -		    UNIWILL_FEATURE_HWMON,
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_GPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN,
>   };
>   
>   static int phxarx1_phxaqf1_probe(struct uniwill_data *data)

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

* Re: [PATCH v2 2/4] platform/x86/uniwill: Implement USB-C power priority setting
  2026-02-26 20:50 ` [PATCH v2 2/4] platform/x86/uniwill: Implement USB-C power priority setting Werner Sembach
@ 2026-02-27  9:31   ` Armin Wolf
  2026-02-27 18:48     ` Werner Sembach
  0 siblings, 1 reply; 10+ messages in thread
From: Armin Wolf @ 2026-02-27  9:31 UTC (permalink / raw)
  To: Werner Sembach, Hans de Goede, Ilpo Järvinen
  Cc: platform-driver-x86, linux-kernel

Am 26.02.26 um 21:50 schrieb Werner Sembach:

> On some devices Uniwill offers the option to set the USB-C port to
> prioritise charging or performance. This patch exposes this setting to the
> userspace via sysfs for all TUXEDO devices supporting it.
>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
>   drivers/platform/x86/uniwill/uniwill-acpi.c | 103 ++++++++++++++++++--
>   1 file changed, 97 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index 7ab82cf16f388..a34b1eed74eb2 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -266,8 +266,8 @@
>   #define BATTERY_CHARGE_FULL_OVER_24H	BIT(3)
>   #define BATTERY_ERM_STATUS_REACHED	BIT(4)
>   
> -#define EC_ADDR_CHARGE_PRIO		0x07CC
> -#define CHARGING_PERFORMANCE		BIT(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 */
>   #define EC_ADDR_LIGHTBAR_BAT_CTRL	0x07E2
> @@ -324,6 +324,7 @@
>   #define UNIWILL_FEATURE_PRIMARY_FAN		BIT(7)
>   #define UNIWILL_FEATURE_SECONDARY_FAN		BIT(8)
>   #define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL	BIT(9)
> +#define UNIWILL_FEATURE_USB_C_POWER_PRIORITY	BIT(10)
>   
>   struct uniwill_data {
>   	struct device *dev;
> @@ -343,6 +344,8 @@ struct uniwill_data {
>   	struct mutex input_lock;	/* Protects input sequence during notify */
>   	struct input_dev *input_device;
>   	struct notifier_block nb;
> +	struct mutex usb_c_power_priority_lock; /* Protects dependent bit write and state safe */
> +	unsigned int last_usb_c_power_priority;
>   };
>   
>   struct uniwill_battery_entry {
> @@ -527,6 +530,7 @@ static bool uniwill_writeable_reg(struct device *dev, unsigned int reg)
>   	case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>   	case EC_ADDR_CTGP_DB_TPP_OFFSET:
>   	case EC_ADDR_CTGP_DB_DB_OFFSET:
> +	case EC_ADDR_USB_C_POWER_PRIORITY:
>   		return true;
>   	default:
>   		return false;
> @@ -565,6 +569,7 @@ static bool uniwill_readable_reg(struct device *dev, unsigned int reg)
>   	case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>   	case EC_ADDR_CTGP_DB_TPP_OFFSET:
>   	case EC_ADDR_CTGP_DB_DB_OFFSET:
> +	case EC_ADDR_USB_C_POWER_PRIORITY:
>   		return true;
>   	default:
>   		return false;
> @@ -587,6 +592,7 @@ static bool uniwill_volatile_reg(struct device *dev, unsigned int reg)
>   	case EC_ADDR_TRIGGER:
>   	case EC_ADDR_SWITCH_STATUS:
>   	case EC_ADDR_CHARGE_CTRL:
> +	case EC_ADDR_USB_C_POWER_PRIORITY:
>   		return true;
>   	default:
>   		return false;
> @@ -883,6 +889,78 @@ static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
>   	return 0;
>   }
>   
> +enum usb_c_power_priority_options {
> +	USB_C_POWER_PRIORITY_OPTIONS_CHARGING = 0,
> +	USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE,
> +};
> +
> +static const char * const USB_C_POWER_PRIORITY_OPTIONS_TEXT[] = {
> +	[USB_C_POWER_PRIORITY_OPTIONS_CHARGING]		= "charging",
> +	[USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE]	= "performance",
> +};
> +
> +static const u8 USB_C_POWER_PRIORITY_OPTIONS_VALUE[] = {
> +	[USB_C_POWER_PRIORITY_OPTIONS_CHARGING]		= 0,
> +	[USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE]	= USB_C_POWER_PRIORITY,
> +};
> +
> +static ssize_t usb_c_power_priority_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;
> +	int ret;
> +
> +	ret = sysfs_match_string(USB_C_POWER_PRIORITY_OPTIONS_TEXT, buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	value = USB_C_POWER_PRIORITY_OPTIONS_VALUE[ret];
> +
> +	guard(mutex)(&data->usb_c_power_priority_lock);
> +
> +	ret = regmap_update_bits(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY,
> +				 USB_C_POWER_PRIORITY, value);
> +	if (ret < 0)
> +		return ret;
> +
> +	data->last_usb_c_power_priority = value;
> +
> +	return count;
> +}
> +
> +static ssize_t usb_c_power_priority_show(struct device *dev,
> +					 struct device_attribute *attr,
> +					 char *buf)
> +{
> +	struct uniwill_data *data = dev_get_drvdata(dev);
> +	unsigned int value;
> +	ssize_t count = 0;
> +	int ret;
> +
> +	ret = regmap_read(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY, &value);
> +	if (ret < 0)
> +		return ret;
> +
> +	value &= USB_C_POWER_PRIORITY;
> +
> +	for (int i = 0; i < ARRAY_SIZE(USB_C_POWER_PRIORITY_OPTIONS_VALUE); ++i) {
> +		if (USB_C_POWER_PRIORITY_OPTIONS_VALUE[i] == value)
> +			count += sysfs_emit_at(buf, count, "[%s] ",
> +					       USB_C_POWER_PRIORITY_OPTIONS_TEXT[i]);
> +		else
> +			count += sysfs_emit_at(buf, count, "%s ",
> +					       USB_C_POWER_PRIORITY_OPTIONS_TEXT[i]);
> +	}
> +	if (count)
> +		buf[count - 1] = '\n';
> +
> +	return count;
> +}
> +
> +static DEVICE_ATTR_RW(usb_c_power_priority);
> +
>   static struct attribute *uniwill_attrs[] = {
>   	/* Keyboard-related */
>   	&dev_attr_fn_lock.attr,
> @@ -893,6 +971,7 @@ static struct attribute *uniwill_attrs[] = {
>   	&dev_attr_breathing_in_suspend.attr,
>   	/* Power-management-related */
>   	&dev_attr_ctgp_offset.attr,
> +	&dev_attr_usb_c_power_priority.attr,
>   	NULL
>   };
>   
> @@ -927,6 +1006,11 @@ static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *a
>   			return attr->mode;
>   	}
>   
> +	if (attr == &dev_attr_usb_c_power_priority.attr) {
> +		if (uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
> +			return attr->mode;
> +	}
> +
>   	return 0;
>   }
>   
> @@ -1417,11 +1501,13 @@ static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action
>   
>   		return NOTIFY_OK;
>   	case UNIWILL_OSD_DC_ADAPTER_CHANGED:
> -		/* noop for the time being, will change once charging priority
> -		 * gets implemented.
> -		 */
> +		if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
> +			return NOTIFY_DONE;
>   
> -		return NOTIFY_OK;
> +		return notifier_from_errno(regmap_update_bits(data->regmap,
> +							      EC_ADDR_OEM_4,
> +							      USB_C_POWER_PRIORITY,
> +							      data->last_usb_c_power_priority));

You need to lock the associated mutex here before accessing last_usb_c_power_priority. Since this
is not possible inside a switch statement when using guard(), i suggest that you move this code
(feature check + register access) into a small helper function.

>   	case UNIWILL_OSD_FN_LOCK:
>   		if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
>   			return NOTIFY_DONE;
> @@ -1515,10 +1601,15 @@ static int uniwill_probe(struct platform_device *pdev)
>   		return PTR_ERR(regmap);
>   
>   	data->regmap = regmap;
> +
>   	ret = devm_mutex_init(&pdev->dev, &data->super_key_lock);
>   	if (ret < 0)
>   		return ret;
>   
> +	ret = devm_mutex_init(&pdev->dev, &data->usb_c_power_priority_lock);
> +	if (ret < 0)
> +		return ret;

last_usb_c_power_priority still needs to be initialized with the value of USB_C_POWER_PRIORITY here.
I suggest that you move all of this (feature check + mutex + init) into a small helper function.

Thanks,
Armin Wolf

> +
>   	ret = uniwill_ec_init(data);
>   	if (ret < 0)
>   		return ret;

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

* Re: [PATCH v2 3/4] platform/x86/uniwill: Apply features across all TUXEDO devices
  2026-02-26 20:50 ` [PATCH v2 3/4] platform/x86/uniwill: Apply features across all TUXEDO devices Werner Sembach
@ 2026-02-27  9:35   ` Armin Wolf
  0 siblings, 0 replies; 10+ messages in thread
From: Armin Wolf @ 2026-02-27  9:35 UTC (permalink / raw)
  To: Werner Sembach, Hans de Goede, Ilpo Järvinen
  Cc: platform-driver-x86, linux-kernel

Am 26.02.26 um 21:50 schrieb Werner Sembach:

> Uses the more fine granular and/or new feature defines to enable more
> features across the TUXEDO device lineup.
>
> Also adds features defines that where already present, but not tested until
> now.
>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
>   drivers/platform/x86/uniwill/uniwill-acpi.c | 214 ++++++++++++++------
>   1 file changed, 156 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index a34b1eed74eb2..f54b27ae832d2 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -110,6 +110,8 @@
>   #define EC_ADDR_BAT_CYCLE_COUNT_2	0x04A7
>   
>   #define EC_ADDR_PROJECT_ID		0x0740
> +#define PROJECT_ID_PH4TRX1		0x12
> +#define PROJECT_ID_PH6TRX1		0x15
>   
>   #define EC_ADDR_AP_OEM			0x0741
>   #define	ENABLE_MANUAL_CTRL		BIT(0)
> @@ -1821,6 +1823,15 @@ static struct platform_driver uniwill_driver = {
>   	.shutdown = uniwill_shutdown,
>   };
>   
> +static struct uniwill_device_descriptor lapqc71a_lapqc71b_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_BATTERY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_GPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN,
> +};
> +
>   static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
>   	.features = UNIWILL_FEATURE_FN_LOCK |
>   		    UNIWILL_FEATURE_SUPER_KEY |
> @@ -1844,6 +1855,85 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
>   		    UNIWILL_FEATURE_SECONDARY_FAN,
>   };
>   
> +/*
> + * The featuresets below reflect somewhat chronological changes:
> + * 1 -> 2: UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL is added to the EC firmware.
> + * 2 -> 3: UNIWILL_FEATURE_USB_C_POWER_PRIORITY is removed from the EC firmware.
> + * Some devices might divert from this timeline.
> + */
> +
> +static struct uniwill_device_descriptor tux_featureset_1_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_FN_LOCK |
> +		    UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN |
> +		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
> +};
> +
> +static struct uniwill_device_descriptor tux_featureset_1_nvidia_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_FN_LOCK |
> +		    UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_GPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN |
> +		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
> +};
> +
> +static struct uniwill_device_descriptor tux_featureset_2_nvidia_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_FN_LOCK |
> +		    UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_GPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN |
> +		    UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL |
> +		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
> +};
> +
> +static struct uniwill_device_descriptor tux_featureset_3_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_FN_LOCK |
> +		    UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN,
> +};
> +
> +static struct uniwill_device_descriptor tux_featureset_3_nvidia_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_FN_LOCK |
> +		    UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_GPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN |
> +		    UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
> +};
> +
> +static int phxtxx1_probe(struct uniwill_data *data)
> +{
> +	unsigned int value;
> +	int ret;
> +
> +	ret = regmap_read(data->regmap, EC_ADDR_PROJECT_ID, &value);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (value == PROJECT_ID_PH4TRX1 || value == PROJECT_ID_PH6TRX1)
> +		data->features |= UNIWILL_FEATURE_SECONDARY_FAN;
> +
> +	return 0;
> +};
> +
> +static struct uniwill_device_descriptor phxtxx1_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_FN_LOCK |
> +		    UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
> +	.probe = phxtxx1_probe,
> +};
> +
>   static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
>   {
>   	unsigned int value;
> @@ -1854,37 +1944,45 @@ static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
>   		return ret;
>   
>   	if (value & HAS_GPU)
> -		data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
> +		data->features |= UNIWILL_FEATURE_GPU_TEMP |
> +				  UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
>   
>   	return 0;
>   };
>   
>   static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_FN_LOCK |
> +		    UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN |
> +		    UNIWILL_FEATURE_SECONDARY_FAN |
> +		    UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
>   	.probe = phxarx1_phxaqf1_probe,
>   };
>   
> -static struct uniwill_device_descriptor tux_featureset_1_descriptor __initdata = {
> -	.features = UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
> +static struct uniwill_device_descriptor pf5pu1g_descriptor __initdata = {
> +	.features = UNIWILL_FEATURE_FN_LOCK |
> +		    UNIWILL_FEATURE_SUPER_KEY |
> +		    UNIWILL_FEATURE_CPU_TEMP |
> +		    UNIWILL_FEATURE_PRIMARY_FAN,
>   };
>   
> -static struct uniwill_device_descriptor empty_descriptor __initdata = {};
> -
>   static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   	{
> -		.ident = "XMG FUSION 15",
> +		.ident = "XMG FUSION 15 (L19)",
>   		.matches = {
> -			DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
> +			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &lapqc71a_lapqc71b_descriptor,
>   	},
>   	{
> -		.ident = "XMG FUSION 15",
> +		.ident = "XMG FUSION 15 (L19)",
>   		.matches = {
> -			DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
> +			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),

I am missing a changelog for the series, and i am a bit confused. Was this change a mistake or not?

Thanks,
Armin Wolf

>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &lapqc71a_lapqc71b_descriptor,
>   	},
>   	{
>   		.ident = "Intel NUC x15",
> @@ -1908,7 +2006,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTxX1"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &phxtxx1_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
> @@ -1916,7 +2014,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
> @@ -1932,7 +2030,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
> @@ -1940,7 +2038,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
> @@ -1948,7 +2046,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
> @@ -1956,7 +2054,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
> @@ -1964,7 +2062,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxHRXx"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
> @@ -1972,7 +2070,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxMRXx"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
> @@ -1980,7 +2078,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxHP4NAx"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
> @@ -1988,7 +2086,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
> @@ -1996,7 +2094,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxAR4NAx"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
> @@ -2004,7 +2102,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
> @@ -2012,7 +2110,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6HP45xU"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
> @@ -2020,7 +2118,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6KK45xU_X6SP45xU"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
> @@ -2028,7 +2126,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5AR45xS"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
> @@ -2036,7 +2134,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR55xU"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 15 Gen1 AMD",
> @@ -2044,7 +2142,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 15 Gen1 AMD",
> @@ -2052,7 +2150,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 17 Gen1 AMD",
> @@ -2060,7 +2158,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 17 Gen1 AMD",
> @@ -2068,7 +2166,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 15 Gen1 Intel",
> @@ -2076,7 +2174,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I1650TI"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 15 Gen1 Intel",
> @@ -2084,7 +2182,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I2060"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 17 Gen1 Intel",
> @@ -2092,7 +2190,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I1650TI"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 17 Gen1 Intel",
> @@ -2100,7 +2198,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I2060"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Trinity 15 Intel Gen1",
> @@ -2108,7 +2206,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1501I"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Trinity 17 Intel Gen1",
> @@ -2116,7 +2214,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1701I"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 15/17 Gen2 AMD",
> @@ -2124,7 +2222,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 15/17 Gen2 Intel",
> @@ -2132,7 +2230,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
> @@ -2140,7 +2238,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
> @@ -2148,7 +2246,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
> @@ -2156,7 +2254,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 15 Gen4 Intel",
> @@ -2164,7 +2262,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Polaris 15/17 Gen5 AMD",
> @@ -2172,7 +2270,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_2_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 16 Gen5 AMD",
> @@ -2180,7 +2278,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
> @@ -2188,7 +2286,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
> @@ -2196,7 +2294,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
> @@ -2204,7 +2302,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
> @@ -2212,7 +2310,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
> @@ -2220,7 +2318,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
> @@ -2228,7 +2326,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 16 Gen7 AMD",
> @@ -2236,7 +2334,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 16 Gen7 Intel",
> @@ -2244,7 +2342,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Stellaris 16 Gen7 Intel",
> @@ -2252,7 +2350,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"),
>   		},
> -		.driver_data = &tux_featureset_1_descriptor,
> +		.driver_data = &tux_featureset_3_nvidia_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Book BA15 Gen10 AMD",
> @@ -2260,7 +2358,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &pf5pu1g_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Pulse 14 Gen1 AMD",
> @@ -2268,7 +2366,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1401"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Pulse 15 Gen1 AMD",
> @@ -2276,7 +2374,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1501"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_descriptor,
>   	},
>   	{
>   		.ident = "TUXEDO Pulse 15 Gen2 AMD",
> @@ -2284,7 +2382,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>   			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>   			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
>   		},
> -		.driver_data = &empty_descriptor,
> +		.driver_data = &tux_featureset_1_descriptor,
>   	},
>   	{ }
>   };

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

* Re: [PATCH v2 4/4] Documentation: laptops: Update documentation for uniwill laptops
  2026-02-26 20:50 ` [PATCH v2 4/4] Documentation: laptops: Update documentation for uniwill laptops Werner Sembach
@ 2026-02-27  9:36   ` Armin Wolf
  0 siblings, 0 replies; 10+ messages in thread
From: Armin Wolf @ 2026-02-27  9:36 UTC (permalink / raw)
  To: Werner Sembach, Jonathan Corbet, Shuah Khan
  Cc: platform-driver-x86, linux-kernel, linux-doc

Am 26.02.26 um 21:50 schrieb Werner Sembach:

> Adds short description for two new sysfs entries, ctgp_offset and
> usb_c_power_priority, to the documentation of uniwill laptops.
>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
>   .../ABI/testing/sysfs-driver-uniwill-laptop   | 25 +++++++++++++++++++
>   .../admin-guide/laptops/uniwill-laptop.rst    | 12 +++++++++
>   2 files changed, 37 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> index 2df70792968f3..55943252f2ab9 100644
> --- a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> +++ b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> @@ -51,3 +51,28 @@ Description:
>   
>   		Reading this file returns the current status of the breathing animation
>   		functionality.
> +
> +What:		/sys/bus/platform/devices/INOU0000:XX/ctgp_offset
> +Date:		January 2026
> +KernelVersion:	7.0
> +Contact:	Werner Sembach <wse@tuxedocomputers.com>
> +Description:
> +		Allows userspace applications to set the configurable TGP offset on top of the base
> +		TGP. Base TGP and max TGP and therefore the max cTGP offset are device specific.
> +		Note that setting the maximal cTGP leaves no window open for Dynamic Boost,
> +		effectifly disabling that feature for the GPU to always be prioritized.
> +
> +		Reading this file returns the current configurable TGP offset.
> +
> +What:		/sys/bus/platform/devices/INOU0000:XX/usb_c_power_priority
> +Date:		February 2026
> +KernelVersion:	7.1
> +Contact:	Werner Sembach <wse@tuxedocomputers.com>
> +Description:
> +		Allows userspace applications to set USB-C power distribution profile between one

set -> choose the

Thanks,
Armin Wolf

> +		that offers a bigger share of the power to the battery and one that offers more of
> +		it to the CPU. Writing "charging"/"performance" into this file selects the
> +		respective profile.
> +
> +		Reading this file returns the profile names with the currently active one in
> +		brackets.
> diff --git a/Documentation/admin-guide/laptops/uniwill-laptop.rst b/Documentation/admin-guide/laptops/uniwill-laptop.rst
> index aff5f57a6bd47..c89b8b3756f84 100644
> --- a/Documentation/admin-guide/laptops/uniwill-laptop.rst
> +++ b/Documentation/admin-guide/laptops/uniwill-laptop.rst
> @@ -50,6 +50,10 @@ between 1 and 100 percent are supported.
>   Additionally the driver signals the presence of battery charging issues through the standard
>   ``health`` power supply sysfs attribute.
>   
> +It also let you set whether an USB-C power source should prioritise charging the battery or
> +delivering immediate power to the cpu. See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for
> +details.
> +
>   Lightbar
>   --------
>   
> @@ -58,3 +62,11 @@ LED class device. The default name of this LED class device is ``uniwill:multico
>   
>   See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details on how to control the various
>   animation modes of the lightbar.
> +
> +Configurable TGP
> +--------
> +
> +The ``uniwill-laptop`` driver allows to set the configurable TGP for devices with NVIDIA GPUs that
> +allow it.
> +
> +See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details.

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

* Re: [PATCH v2 1/4] platform/x86/uniwill: uniwill-laptop: Rework hwmon feature defines
  2026-02-27  9:28   ` Armin Wolf
@ 2026-02-27 18:45     ` Werner Sembach
  0 siblings, 0 replies; 10+ messages in thread
From: Werner Sembach @ 2026-02-27 18:45 UTC (permalink / raw)
  To: Armin Wolf, Hans de Goede, Ilpo Järvinen
  Cc: platform-driver-x86, linux-kernel


Am 27.02.26 um 10:28 schrieb Armin Wolf:
> Am 26.02.26 um 21:50 schrieb Werner Sembach:
>
>> From: Armin Wolf <W_Armin@gmx.de>
>>
>> Split hwmon feature define in smaller parts to accommodate for diverse
>> hardware. You can now specify the presence of a cpu and/or a gpu temp
>> sensor separately and if one or 2 fans exists.
>>
>> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>> ---
>>   drivers/platform/x86/uniwill/uniwill-acpi.c | 68 ++++++++++++++++++---
>>   1 file changed, 61 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c 
>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> index 6341dca20b76a..7ab82cf16f388 100644
>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> @@ -319,8 +319,11 @@
>>   #define UNIWILL_FEATURE_TOUCHPAD_TOGGLE        BIT(2)
>>   #define UNIWILL_FEATURE_LIGHTBAR        BIT(3)
>>   #define UNIWILL_FEATURE_BATTERY            BIT(4)
>> -#define UNIWILL_FEATURE_HWMON            BIT(5)
>> -#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL    BIT(6)
>> +#define UNIWILL_FEATURE_CPU_TEMP        BIT(5)
>> +#define UNIWILL_FEATURE_GPU_TEMP        BIT(6)
>> +#define UNIWILL_FEATURE_PRIMARY_FAN        BIT(7)
>> +#define UNIWILL_FEATURE_SECONDARY_FAN        BIT(8)
>> +#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL    BIT(9)
>>     struct uniwill_data {
>>       struct device *dev;
>> @@ -427,7 +430,7 @@ static const struct key_entry uniwill_keymap[] = {
>>       { KE_END }
>>   };
>>   -static inline bool uniwill_device_supports(struct uniwill_data *data,
>> +static inline bool uniwill_device_supports(const struct uniwill_data *data,
>>                          unsigned int features)
>>   {
>>       return (data->features & features) == features;
>> @@ -937,6 +940,48 @@ static const struct attribute_group *uniwill_groups[] = {
>>       NULL
>>   };
>>   +static umode_t uniwill_is_visible(const void *drvdata, enum 
>> hwmon_sensor_types type, u32 attr,
>> +                  int channel)
>> +{
>> +    const struct uniwill_data *data = drvdata;
>> +    unsigned int feature;
>> +
>> +    switch (type) {
>> +    case hwmon_temp:
>> +        switch (channel) {
>> +        case 0:
>> +            feature = UNIWILL_FEATURE_CPU_TEMP;
>> +            break;
>> +        case 1:
>> +            feature = UNIWILL_FEATURE_GPU_TEMP;
>> +            break;
>> +        default:
>> +            return 0;
>> +        }
>> +        break;
>> +    case hwmon_fan:
>> +    case hwmon_pwm:
>> +        switch (channel) {
>> +        case 0:
>> +            feature = UNIWILL_FEATURE_PRIMARY_FAN;
>> +            break;
>> +        case 1:
>> +            feature = UNIWILL_FEATURE_SECONDARY_FAN;
>> +            break;
>> +        default:
>> +            return 0;
>> +        }
>> +        break;
>> +    default:
>> +        return 0;
>> +    }
>> +
>> +    if (uniwill_device_supports(data, feature))
>> +        return 0440;
>
> I think you forgot this one.
yes missed it
>
>> +
>> +    return 0;
>> +}
>> +
>>   static int uniwill_read(struct device *dev, enum hwmon_sensor_types type, 
>> u32 attr, int channel,
>>               long *val)
>>   {
>> @@ -1020,7 +1065,7 @@ static int uniwill_read_string(struct device *dev, enum 
>> hwmon_sensor_types type,
>>   }
>>     static const struct hwmon_ops uniwill_ops = {
>> -    .visible = 0444,
>> +    .is_visible = uniwill_is_visible,
>>       .read = uniwill_read,
>>       .read_string = uniwill_read_string,
>>   };
>> @@ -1048,7 +1093,10 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
>>   {
>>       struct device *hdev;
>>   -    if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON))
>> +    if (!uniwill_device_supports(data, UNIWILL_FEATURE_CPU_TEMP) &&
>> +        !uniwill_device_supports(data, UNIWILL_FEATURE_GPU_TEMP) &&
>> +        !uniwill_device_supports(data, UNIWILL_FEATURE_PRIMARY_FAN) &&
>> +        !uniwill_device_supports(data, UNIWILL_FEATURE_SECONDARY_FAN))
>>           return 0;
>>         hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
>> @@ -1687,7 +1735,10 @@ static struct uniwill_device_descriptor 
>> lapac71h_descriptor __initdata = {
>>               UNIWILL_FEATURE_SUPER_KEY |
>>               UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>               UNIWILL_FEATURE_BATTERY |
>> -            UNIWILL_FEATURE_HWMON,
>> +            UNIWILL_FEATURE_CPU_TEMP |
>> +            UNIWILL_FEATURE_GPU_TEMP |
>> +            UNIWILL_FEATURE_PRIMARY_FAN |
>> +            UNIWILL_FEATURE_SECONDARY_FAN,
>>   };
>>     static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
>> @@ -1696,7 +1747,10 @@ static struct uniwill_device_descriptor 
>> lapkc71f_descriptor __initdata = {
>>               UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>               UNIWILL_FEATURE_LIGHTBAR |
>>               UNIWILL_FEATURE_BATTERY |
>> -            UNIWILL_FEATURE_HWMON,
>> +            UNIWILL_FEATURE_CPU_TEMP |
>> +            UNIWILL_FEATURE_GPU_TEMP |
>> +            UNIWILL_FEATURE_PRIMARY_FAN |
>> +            UNIWILL_FEATURE_SECONDARY_FAN,
>>   };
>>     static int phxarx1_phxaqf1_probe(struct uniwill_data *data)

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

* Re: [PATCH v2 2/4] platform/x86/uniwill: Implement USB-C power priority setting
  2026-02-27  9:31   ` Armin Wolf
@ 2026-02-27 18:48     ` Werner Sembach
  0 siblings, 0 replies; 10+ messages in thread
From: Werner Sembach @ 2026-02-27 18:48 UTC (permalink / raw)
  To: Armin Wolf, Hans de Goede, Ilpo Järvinen
  Cc: platform-driver-x86, linux-kernel


Am 27.02.26 um 10:31 schrieb Armin Wolf:
> Am 26.02.26 um 21:50 schrieb Werner Sembach:
>
>> On some devices Uniwill offers the option to set the USB-C port to
>> prioritise charging or performance. This patch exposes this setting to the
>> userspace via sysfs for all TUXEDO devices supporting it.
>>
>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>> ---
>>   drivers/platform/x86/uniwill/uniwill-acpi.c | 103 ++++++++++++++++++--
>>   1 file changed, 97 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c 
>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> index 7ab82cf16f388..a34b1eed74eb2 100644
>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> @@ -266,8 +266,8 @@
>>   #define BATTERY_CHARGE_FULL_OVER_24H    BIT(3)
>>   #define BATTERY_ERM_STATUS_REACHED    BIT(4)
>>   -#define EC_ADDR_CHARGE_PRIO        0x07CC
>> -#define CHARGING_PERFORMANCE        BIT(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 */
>>   #define EC_ADDR_LIGHTBAR_BAT_CTRL    0x07E2
>> @@ -324,6 +324,7 @@
>>   #define UNIWILL_FEATURE_PRIMARY_FAN        BIT(7)
>>   #define UNIWILL_FEATURE_SECONDARY_FAN        BIT(8)
>>   #define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL    BIT(9)
>> +#define UNIWILL_FEATURE_USB_C_POWER_PRIORITY    BIT(10)
>>     struct uniwill_data {
>>       struct device *dev;
>> @@ -343,6 +344,8 @@ struct uniwill_data {
>>       struct mutex input_lock;    /* Protects input sequence during notify */
>>       struct input_dev *input_device;
>>       struct notifier_block nb;
>> +    struct mutex usb_c_power_priority_lock; /* Protects dependent bit write 
>> and state safe */
>> +    unsigned int last_usb_c_power_priority;
>>   };
>>     struct uniwill_battery_entry {
>> @@ -527,6 +530,7 @@ static bool uniwill_writeable_reg(struct device *dev, 
>> unsigned int reg)
>>       case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>>       case EC_ADDR_CTGP_DB_TPP_OFFSET:
>>       case EC_ADDR_CTGP_DB_DB_OFFSET:
>> +    case EC_ADDR_USB_C_POWER_PRIORITY:
>>           return true;
>>       default:
>>           return false;
>> @@ -565,6 +569,7 @@ static bool uniwill_readable_reg(struct device *dev, 
>> unsigned int reg)
>>       case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>>       case EC_ADDR_CTGP_DB_TPP_OFFSET:
>>       case EC_ADDR_CTGP_DB_DB_OFFSET:
>> +    case EC_ADDR_USB_C_POWER_PRIORITY:
>>           return true;
>>       default:
>>           return false;
>> @@ -587,6 +592,7 @@ static bool uniwill_volatile_reg(struct device *dev, 
>> unsigned int reg)
>>       case EC_ADDR_TRIGGER:
>>       case EC_ADDR_SWITCH_STATUS:
>>       case EC_ADDR_CHARGE_CTRL:
>> +    case EC_ADDR_USB_C_POWER_PRIORITY:
>>           return true;
>>       default:
>>           return false;
>> @@ -883,6 +889,78 @@ static int uniwill_nvidia_ctgp_init(struct uniwill_data 
>> *data)
>>       return 0;
>>   }
>>   +enum usb_c_power_priority_options {
>> +    USB_C_POWER_PRIORITY_OPTIONS_CHARGING = 0,
>> +    USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE,
>> +};
>> +
>> +static const char * const USB_C_POWER_PRIORITY_OPTIONS_TEXT[] = {
>> +    [USB_C_POWER_PRIORITY_OPTIONS_CHARGING]        = "charging",
>> +    [USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE]    = "performance",
>> +};
>> +
>> +static const u8 USB_C_POWER_PRIORITY_OPTIONS_VALUE[] = {
>> +    [USB_C_POWER_PRIORITY_OPTIONS_CHARGING]        = 0,
>> +    [USB_C_POWER_PRIORITY_OPTIONS_PERFORMANCE]    = USB_C_POWER_PRIORITY,
>> +};
>> +
>> +static ssize_t usb_c_power_priority_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;
>> +    int ret;
>> +
>> +    ret = sysfs_match_string(USB_C_POWER_PRIORITY_OPTIONS_TEXT, buf);
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    value = USB_C_POWER_PRIORITY_OPTIONS_VALUE[ret];
>> +
>> +    guard(mutex)(&data->usb_c_power_priority_lock);
>> +
>> +    ret = regmap_update_bits(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY,
>> +                 USB_C_POWER_PRIORITY, value);
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    data->last_usb_c_power_priority = value;
>> +
>> +    return count;
>> +}
>> +
>> +static ssize_t usb_c_power_priority_show(struct device *dev,
>> +                     struct device_attribute *attr,
>> +                     char *buf)
>> +{
>> +    struct uniwill_data *data = dev_get_drvdata(dev);
>> +    unsigned int value;
>> +    ssize_t count = 0;
>> +    int ret;
>> +
>> +    ret = regmap_read(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY, &value);
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    value &= USB_C_POWER_PRIORITY;
>> +
>> +    for (int i = 0; i < ARRAY_SIZE(USB_C_POWER_PRIORITY_OPTIONS_VALUE); ++i) {
>> +        if (USB_C_POWER_PRIORITY_OPTIONS_VALUE[i] == value)
>> +            count += sysfs_emit_at(buf, count, "[%s] ",
>> + USB_C_POWER_PRIORITY_OPTIONS_TEXT[i]);
>> +        else
>> +            count += sysfs_emit_at(buf, count, "%s ",
>> + USB_C_POWER_PRIORITY_OPTIONS_TEXT[i]);
>> +    }
>> +    if (count)
>> +        buf[count - 1] = '\n';
>> +
>> +    return count;
>> +}
>> +
>> +static DEVICE_ATTR_RW(usb_c_power_priority);
>> +
>>   static struct attribute *uniwill_attrs[] = {
>>       /* Keyboard-related */
>>       &dev_attr_fn_lock.attr,
>> @@ -893,6 +971,7 @@ static struct attribute *uniwill_attrs[] = {
>>       &dev_attr_breathing_in_suspend.attr,
>>       /* Power-management-related */
>>       &dev_attr_ctgp_offset.attr,
>> +    &dev_attr_usb_c_power_priority.attr,
>>       NULL
>>   };
>>   @@ -927,6 +1006,11 @@ static umode_t uniwill_attr_is_visible(struct kobject 
>> *kobj, struct attribute *a
>>               return attr->mode;
>>       }
>>   +    if (attr == &dev_attr_usb_c_power_priority.attr) {
>> +        if (uniwill_device_supports(data, 
>> UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
>> +            return attr->mode;
>> +    }
>> +
>>       return 0;
>>   }
>>   @@ -1417,11 +1501,13 @@ static int uniwill_notifier_call(struct 
>> notifier_block *nb, unsigned long action
>>             return NOTIFY_OK;
>>       case UNIWILL_OSD_DC_ADAPTER_CHANGED:
>> -        /* noop for the time being, will change once charging priority
>> -         * gets implemented.
>> -         */
>> +        if (!uniwill_device_supports(data, 
>> UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
>> +            return NOTIFY_DONE;
>>   -        return NOTIFY_OK;
>> +        return notifier_from_errno(regmap_update_bits(data->regmap,
>> +                                  EC_ADDR_OEM_4,
>> +                                  USB_C_POWER_PRIORITY,
>> + data->last_usb_c_power_priority));
>
> You need to lock the associated mutex here before accessing 
> last_usb_c_power_priority. Since this
> is not possible inside a switch statement when using guard(), i suggest that 
> you move this code
> (feature check + register access) into a small helper function.
>
>>       case UNIWILL_OSD_FN_LOCK:
>>           if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
>>               return NOTIFY_DONE;
>> @@ -1515,10 +1601,15 @@ static int uniwill_probe(struct platform_device *pdev)
>>           return PTR_ERR(regmap);
>>         data->regmap = regmap;
>> +
>>       ret = devm_mutex_init(&pdev->dev, &data->super_key_lock);
>>       if (ret < 0)
>>           return ret;
>>   +    ret = devm_mutex_init(&pdev->dev, &data->usb_c_power_priority_lock);
>> +    if (ret < 0)
>> +        return ret;
>
> last_usb_c_power_priority still needs to be initialized with the value of 
> USB_C_POWER_PRIORITY here.
> I suggest that you move all of this (feature check + mutex + init) into a 
> small helper function.
ack
>
> Thanks,
> Armin Wolf
>
>> +
>>       ret = uniwill_ec_init(data);
>>       if (ret < 0)
>>           return ret;

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

end of thread, other threads:[~2026-02-27 18:48 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20260226205302.123782-1-wse@tuxedocomputers.com>
2026-02-26 20:50 ` [PATCH v2 1/4] platform/x86/uniwill: uniwill-laptop: Rework hwmon feature defines Werner Sembach
2026-02-27  9:28   ` Armin Wolf
2026-02-27 18:45     ` Werner Sembach
2026-02-26 20:50 ` [PATCH v2 2/4] platform/x86/uniwill: Implement USB-C power priority setting Werner Sembach
2026-02-27  9:31   ` Armin Wolf
2026-02-27 18:48     ` Werner Sembach
2026-02-26 20:50 ` [PATCH v2 3/4] platform/x86/uniwill: Apply features across all TUXEDO devices Werner Sembach
2026-02-27  9:35   ` Armin Wolf
2026-02-26 20:50 ` [PATCH v2 4/4] Documentation: laptops: Update documentation for uniwill laptops Werner Sembach
2026-02-27  9:36   ` 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®