* [PATCH 0/2] platform/x86: uniwill-laptop: Introduce device descriptor system
@ 2025-12-04 13:50 Werner Sembach
2025-12-04 13:50 ` [PATCH 1/2] " Werner Sembach
2025-12-04 13:50 ` [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting Werner Sembach
0 siblings, 2 replies; 19+ messages in thread
From: Werner Sembach @ 2025-12-04 13:50 UTC (permalink / raw)
To: W_Armin, hansg, ilpo.jarvinen
Cc: platform-driver-x86, linux-kernel, Werner Sembach
The first patch is based on a PoC by Armin and extended the be able to
modify feature bits based on readouts from the EC Memory.
The 2nd patch is a new feature that requires such a modification.
Changes since RFC: - more flexible uniwill_device_supports
- minor cleanups
- initialization of cTGP before activation
Sorry for the spam, accidentially still had the --rfc in the command line of
send-email.
Armin Wolf (1):
platform/x86: uniwill-laptop: Introduce device descriptor system
Werner Sembach (1):
platform/x86/uniwill: Implement cTGP setting
drivers/platform/x86/uniwill/uniwill-acpi.c | 284 ++++++++++++++++++--
1 file changed, 255 insertions(+), 29 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2025-12-04 13:50 [PATCH 0/2] platform/x86: uniwill-laptop: Introduce device descriptor system Werner Sembach
@ 2025-12-04 13:50 ` Werner Sembach
2025-12-04 16:03 ` Armin Wolf
2025-12-16 13:40 ` Ilpo Järvinen
2025-12-04 13:50 ` [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting Werner Sembach
1 sibling, 2 replies; 19+ messages in thread
From: Werner Sembach @ 2025-12-04 13:50 UTC (permalink / raw)
To: W_Armin, hansg, ilpo.jarvinen
Cc: platform-driver-x86, linux-kernel, Werner Sembach
From: Armin Wolf <W_Armin@gmx.de>
Future additions to the driver will depend on device-specific
initialization steps. Extend the DMI-based feature detection system
to include device descriptors. Each descriptor contains a bitmap of
supported features and a set of callback for performing
device-specific initialization.
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
---
drivers/platform/x86/uniwill/uniwill-acpi.c | 168 +++++++++++++++++---
1 file changed, 142 insertions(+), 26 deletions(-)
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index bd7e63dd51810..01192c32608e5 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -322,6 +322,7 @@ struct uniwill_data {
struct device *dev;
acpi_handle handle;
struct regmap *regmap;
+ unsigned int features;
struct acpi_battery_hook hook;
unsigned int last_charge_ctrl;
struct mutex battery_lock; /* Protects the list of currently registered batteries */
@@ -341,12 +342,21 @@ struct uniwill_battery_entry {
struct power_supply *battery;
};
+struct uniwill_device_descriptor {
+ unsigned int features;
+ /* Executed during driver probing */
+ int (*probe)(struct uniwill_data *data);
+};
+
static bool force;
module_param_unsafe(force, bool, 0);
MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
-/* Feature bitmask since the associated registers are not reliable */
-static unsigned int supported_features;
+/*
+ * Contains device specific data like the feature bitmap since
+ * the associated registers are not always reliable.
+ */
+static struct uniwill_device_descriptor device_descriptor __ro_after_init;
static const char * const uniwill_temp_labels[] = {
"CPU",
@@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] = {
{ KE_END }
};
+static inline bool uniwill_device_supports(struct uniwill_data *data,
+ unsigned int features_mask,
+ unsigned int features)
+{
+ return (data->features & features_mask) == features;
+}
+
static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
{
union acpi_object params[2] = {
@@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] = {
static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
{
+ struct device *dev = kobj_to_dev(kobj);
+ struct uniwill_data *data = dev_get_drvdata(dev);
+
if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
- if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK_TOGGLE,
+ UNIWILL_FEATURE_FN_LOCK_TOGGLE))
return attr->mode;
}
if (attr == &dev_attr_super_key_toggle_enable.attr) {
- if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
+ UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
return attr->mode;
}
if (attr == &dev_attr_touchpad_toggle_enable.attr) {
- if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE,
+ UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
return attr->mode;
}
if (attr == &dev_attr_rainbow_animation.attr ||
attr == &dev_attr_breathing_in_suspend.attr) {
- if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
+ UNIWILL_FEATURE_LIGHTBAR))
return attr->mode;
}
@@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
{
struct device *hdev;
- if (!(supported_features & UNIWILL_FEATURE_HWMON))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON,
+ UNIWILL_FEATURE_HWMON))
return 0;
hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
@@ -1019,7 +1044,8 @@ static int uniwill_led_init(struct uniwill_data *data)
unsigned int value;
int ret;
- if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
+ UNIWILL_FEATURE_LIGHTBAR))
return 0;
ret = devm_mutex_init(data->dev, &data->led_lock);
@@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct uniwill_data *data)
{
int ret;
- if (!(supported_features & UNIWILL_FEATURE_BATTERY))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
+ UNIWILL_FEATURE_BATTERY))
return 0;
ret = devm_mutex_init(data->dev, &data->battery_lock);
@@ -1361,6 +1388,19 @@ static int uniwill_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
+ data->features = device_descriptor.features;
+
+ /*
+ * Some devices might need to perform some device-specific initialization steps
+ * before the supported features are initialized. Because of this we have to call
+ * this callback just after the EC itself was initialized.
+ */
+ if (device_descriptor.probe) {
+ ret = device_descriptor.probe(data);
+ if (ret < 0)
+ return ret;
+ }
+
ret = uniwill_battery_init(data);
if (ret < 0)
return ret;
@@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct platform_device *pdev)
static int uniwill_suspend_keyboard(struct uniwill_data *data)
{
- if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
+ UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
return 0;
/*
@@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct uniwill_data *data)
static int uniwill_suspend_battery(struct uniwill_data *data)
{
- if (!(supported_features & UNIWILL_FEATURE_BATTERY))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
+ UNIWILL_FEATURE_BATTERY))
return 0;
/*
@@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
unsigned int value;
int ret;
- if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
+ UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
return 0;
ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
@@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
static int uniwill_resume_battery(struct uniwill_data *data)
{
- if (!(supported_features & UNIWILL_FEATURE_BATTERY))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
+ UNIWILL_FEATURE_BATTERY))
return 0;
return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
@@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver = {
.shutdown = uniwill_shutdown,
};
+static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
+ UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
+ UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
+ UNIWILL_FEATURE_BATTERY |
+ UNIWILL_FEATURE_HWMON
+};
+
+static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
+ UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
+ UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
+ UNIWILL_FEATURE_LIGHTBAR |
+ UNIWILL_FEATURE_BATTERY |
+ UNIWILL_FEATURE_HWMON
+};
+
+static struct uniwill_device_descriptor empty_descriptor __initdata = {};
+
static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
{
.ident = "XMG FUSION 15",
@@ -1503,6 +1566,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
},
+ .driver_data = &empty_descriptor,
},
{
.ident = "XMG FUSION 15",
@@ -1510,6 +1574,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
},
+ .driver_data = &empty_descriptor,
},
{
.ident = "Intel NUC x15",
@@ -1517,11 +1582,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
},
- .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
- UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
- UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
- UNIWILL_FEATURE_BATTERY |
- UNIWILL_FEATURE_HWMON),
+ .driver_data = &lapac71h_descriptor,
},
{
.ident = "Intel NUC x15",
@@ -1529,12 +1590,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
},
- .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
- UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
- UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
- UNIWILL_FEATURE_LIGHTBAR |
- UNIWILL_FEATURE_BATTERY |
- UNIWILL_FEATURE_HWMON),
+ .driver_data = &lapkc71f_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
@@ -1542,6 +1598,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
@@ -1549,6 +1606,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 = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
@@ -1556,6 +1614,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
},
+ .driver_data = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
@@ -1563,6 +1622,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 = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1570,6 +1630,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1577,6 +1638,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 = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
@@ -1584,6 +1646,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 = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
@@ -1591,6 +1654,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
@@ -1598,6 +1662,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
@@ -1605,6 +1670,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
@@ -1612,6 +1678,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,
},
{
.ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
@@ -1619,6 +1686,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,
},
{
.ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
@@ -1626,6 +1694,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,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
@@ -1633,6 +1702,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,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
@@ -1640,6 +1710,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,
},
{
.ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
@@ -1647,6 +1718,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,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
@@ -1654,6 +1726,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,
},
{
.ident = "TUXEDO Polaris 15 Gen1 AMD",
@@ -1661,6 +1734,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,
},
{
.ident = "TUXEDO Polaris 15 Gen1 AMD",
@@ -1668,6 +1742,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,
},
{
.ident = "TUXEDO Polaris 17 Gen1 AMD",
@@ -1675,6 +1750,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,
},
{
.ident = "TUXEDO Polaris 17 Gen1 AMD",
@@ -1682,6 +1758,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,
},
{
.ident = "TUXEDO Polaris 15 Gen1 Intel",
@@ -1689,6 +1766,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,
},
{
.ident = "TUXEDO Polaris 15 Gen1 Intel",
@@ -1696,6 +1774,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,
},
{
.ident = "TUXEDO Polaris 17 Gen1 Intel",
@@ -1703,6 +1782,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,
},
{
.ident = "TUXEDO Polaris 17 Gen1 Intel",
@@ -1710,6 +1790,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,
},
{
.ident = "TUXEDO Trinity 15 Intel Gen1",
@@ -1717,6 +1798,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,
},
{
.ident = "TUXEDO Trinity 17 Intel Gen1",
@@ -1724,6 +1806,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,
},
{
.ident = "TUXEDO Polaris 15/17 Gen2 AMD",
@@ -1731,6 +1814,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen2 Intel",
@@ -1738,6 +1822,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
@@ -1745,6 +1830,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
@@ -1752,6 +1838,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
@@ -1759,6 +1846,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 15 Gen4 Intel",
@@ -1766,6 +1854,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen5 AMD",
@@ -1773,6 +1862,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen5 AMD",
@@ -1780,6 +1870,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
@@ -1787,6 +1878,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
@@ -1794,6 +1886,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
@@ -1801,6 +1894,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -1808,6 +1902,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -1815,6 +1910,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
@@ -1822,6 +1918,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 AMD",
@@ -1829,6 +1926,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -1836,6 +1934,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -1843,6 +1942,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Pulse 14 Gen1 AMD",
@@ -1850,6 +1950,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,
},
{
.ident = "TUXEDO Pulse 15 Gen1 AMD",
@@ -1857,6 +1958,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,
},
{
.ident = "TUXEDO Pulse 15 Gen2 AMD",
@@ -1864,6 +1966,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,
},
{ }
};
@@ -1871,6 +1974,7 @@ MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
static int __init uniwill_init(void)
{
+ const struct uniwill_device_descriptor *descriptor;
const struct dmi_system_id *id;
int ret;
@@ -1880,10 +1984,22 @@ static int __init uniwill_init(void)
return -ENODEV;
/* Assume that the device supports all features */
- supported_features = UINT_MAX;
+ device_descriptor.features = UINT_MAX;
pr_warn("Loading on a potentially unsupported device\n");
} else {
- supported_features = (uintptr_t)id->driver_data;
+ /*
+ * Some devices might support additional features depending on
+ * the BIOS version/date, so we call this callback to let them
+ * modify their device descriptor accordingly.
+ */
+ if (id->callback) {
+ ret = id->callback(id);
+ if (ret < 0)
+ return ret;
+ }
+
+ descriptor = id->driver_data;
+ device_descriptor = *descriptor;
}
ret = platform_driver_register(&uniwill_driver);
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting
2025-12-04 13:50 [PATCH 0/2] platform/x86: uniwill-laptop: Introduce device descriptor system Werner Sembach
2025-12-04 13:50 ` [PATCH 1/2] " Werner Sembach
@ 2025-12-04 13:50 ` Werner Sembach
2025-12-04 16:11 ` Armin Wolf
1 sibling, 1 reply; 19+ messages in thread
From: Werner Sembach @ 2025-12-04 13:50 UTC (permalink / raw)
To: W_Armin, hansg, ilpo.jarvinen
Cc: platform-driver-x86, linux-kernel, Werner Sembach
Uniwill offers user setable cTGP for their EC on devices using NVIDIA 3000
Series and newer GPUs. This patch implements this setting as a sysfs
attribute.
For one device, the TUXEDO InfinityBook Gen7, the variant with and without
NVIDIA GPU can't be differentiated using only the DMI strings, so the new
probe callback needs to be used to test a bit from the EC memory.
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
---
drivers/platform/x86/uniwill/uniwill-acpi.c | 160 +++++++++++++++++---
1 file changed, 135 insertions(+), 25 deletions(-)
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 01192c32608e5..f87f6e9d08234 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -88,6 +88,9 @@
#define EC_ADDR_GPU_TEMP 0x044F
+#define EC_ADDR_SYSTEM_ID 0x0456
+#define HAS_GPU BIT(7)
+
#define EC_ADDR_MAIN_FAN_RPM_1 0x0464
#define EC_ADDR_MAIN_FAN_RPM_2 0x0465
@@ -122,11 +125,11 @@
#define CTGP_DB_DB_ENABLE BIT(1)
#define CTGP_DB_CTGP_ENABLE BIT(2)
-#define EC_ADDR_CTGP_OFFSET 0x0744
+#define EC_ADDR_CTGP_DB_CTGP_OFFSET 0x0744
-#define EC_ADDR_TPP_OFFSET 0x0745
+#define EC_ADDR_CTGP_DB_TPP_OFFSET 0x0745
-#define EC_ADDR_MAX_TGP 0x0746
+#define EC_ADDR_CTGP_DB_DB_OFFSET 0x0746
#define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748
#define LIGHTBAR_APP_EXISTS BIT(0)
@@ -317,6 +320,7 @@
#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)
struct uniwill_data {
struct device *dev;
@@ -515,6 +519,10 @@ static bool uniwill_writeable_reg(struct device *dev, unsigned int reg)
case EC_ADDR_LIGHTBAR_BAT_RED:
case EC_ADDR_LIGHTBAR_BAT_GREEN:
case EC_ADDR_LIGHTBAR_BAT_BLUE:
+ case EC_ADDR_CTGP_DB_CTRL:
+ case EC_ADDR_CTGP_DB_CTGP_OFFSET:
+ case EC_ADDR_CTGP_DB_TPP_OFFSET:
+ case EC_ADDR_CTGP_DB_DB_OFFSET:
return true;
default:
return false;
@@ -548,6 +556,10 @@ static bool uniwill_readable_reg(struct device *dev, unsigned int reg)
case EC_ADDR_LIGHTBAR_BAT_RED:
case EC_ADDR_LIGHTBAR_BAT_GREEN:
case EC_ADDR_LIGHTBAR_BAT_BLUE:
+ case EC_ADDR_CTGP_DB_CTRL:
+ case EC_ADDR_CTGP_DB_CTGP_OFFSET:
+ case EC_ADDR_CTGP_DB_TPP_OFFSET:
+ case EC_ADDR_CTGP_DB_DB_OFFSET:
return true;
default:
return false;
@@ -803,6 +815,69 @@ static ssize_t breathing_in_suspend_show(struct device *dev, struct device_attri
static DEVICE_ATTR_RW(breathing_in_suspend);
+static ssize_t ctgp_offset_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 = kstrtouint(buf, 0, &value);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, value);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static ssize_t ctgp_offset_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct uniwill_data *data = dev_get_drvdata(dev);
+ unsigned int value;
+ int ret;
+
+ ret = regmap_read(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, &value);
+ if (ret < 0)
+ return ret;
+
+ return sysfs_emit(buf, "%u\n", value);
+}
+
+static DEVICE_ATTR_RW(ctgp_offset);
+
+static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
+{
+ int ret;
+
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
+ UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
+ return 0;
+
+ ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_TPP_OFFSET, 255);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_DB_OFFSET, 25);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
+ CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE,
+ CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static struct attribute *uniwill_attrs[] = {
/* Keyboard-related */
&dev_attr_fn_lock_toggle_enable.attr,
@@ -811,6 +886,8 @@ static struct attribute *uniwill_attrs[] = {
/* Lightbar-related */
&dev_attr_rainbow_animation.attr,
&dev_attr_breathing_in_suspend.attr,
+ /* Power-management-related */
+ &dev_attr_ctgp_offset.attr,
NULL
};
@@ -844,6 +921,12 @@ static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *a
return attr->mode;
}
+ if (attr == &dev_attr_ctgp_offset.attr) {
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
+ UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
+ return attr->mode;
+ }
+
return 0;
}
@@ -1413,6 +1496,10 @@ static int uniwill_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
+ ret = uniwill_nvidia_ctgp_init(data);
+ if (ret < 0)
+ return ret;
+
return uniwill_input_init(data);
}
@@ -1557,6 +1644,29 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
UNIWILL_FEATURE_HWMON
};
+static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
+{
+ unsigned int value;
+ int ret;
+
+ ret = regmap_read(data->regmap, EC_ADDR_SYSTEM_ID, &value);
+ if (ret < 0)
+ return ret;
+
+ if (value & HAS_GPU)
+ data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
+
+ return 0;
+};
+
+static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor __initdata = {
+ .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 empty_descriptor __initdata = {};
static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
@@ -1606,7 +1716,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
@@ -1614,7 +1724,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &phxarx1_phxaqf1_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
@@ -1622,7 +1732,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1638,7 +1748,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
@@ -1646,7 +1756,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
@@ -1814,7 +1924,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen2 Intel",
@@ -1822,7 +1932,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
@@ -1830,7 +1940,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
@@ -1838,7 +1948,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
@@ -1846,7 +1956,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 15 Gen4 Intel",
@@ -1854,7 +1964,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen5 AMD",
@@ -1862,7 +1972,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen5 AMD",
@@ -1870,7 +1980,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
@@ -1878,7 +1988,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
@@ -1886,7 +1996,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
@@ -1894,7 +2004,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -1902,7 +2012,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -1910,7 +2020,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
@@ -1918,7 +2028,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 AMD",
@@ -1926,7 +2036,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -1934,7 +2044,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -1942,7 +2052,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 = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Pulse 14 Gen1 AMD",
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2025-12-04 13:50 ` [PATCH 1/2] " Werner Sembach
@ 2025-12-04 16:03 ` Armin Wolf
2025-12-04 21:03 ` Werner Sembach
2025-12-16 13:40 ` Ilpo Järvinen
1 sibling, 1 reply; 19+ messages in thread
From: Armin Wolf @ 2025-12-04 16:03 UTC (permalink / raw)
To: Werner Sembach, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, linux-kernel
Am 04.12.25 um 14:50 schrieb Werner Sembach:
> From: Armin Wolf <W_Armin@gmx.de>
>
> Future additions to the driver will depend on device-specific
> initialization steps. Extend the DMI-based feature detection system
> to include device descriptors. Each descriptor contains a bitmap of
> supported features and a set of callback for performing
> device-specific initialization.
>
> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
> Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
> drivers/platform/x86/uniwill/uniwill-acpi.c | 168 +++++++++++++++++---
> 1 file changed, 142 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index bd7e63dd51810..01192c32608e5 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -322,6 +322,7 @@ struct uniwill_data {
> struct device *dev;
> acpi_handle handle;
> struct regmap *regmap;
> + unsigned int features;
> struct acpi_battery_hook hook;
> unsigned int last_charge_ctrl;
> struct mutex battery_lock; /* Protects the list of currently registered batteries */
> @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
> struct power_supply *battery;
> };
>
> +struct uniwill_device_descriptor {
> + unsigned int features;
> + /* Executed during driver probing */
> + int (*probe)(struct uniwill_data *data);
> +};
> +
> static bool force;
> module_param_unsafe(force, bool, 0);
> MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
>
> -/* Feature bitmask since the associated registers are not reliable */
> -static unsigned int supported_features;
> +/*
> + * Contains device specific data like the feature bitmap since
> + * the associated registers are not always reliable.
> + */
> +static struct uniwill_device_descriptor device_descriptor __ro_after_init;
>
> static const char * const uniwill_temp_labels[] = {
> "CPU",
> @@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] = {
> { KE_END }
> };
>
> +static inline bool uniwill_device_supports(struct uniwill_data *data,
> + unsigned int features_mask,
> + unsigned int features)
> +{
> + return (data->features & features_mask) == features;
Hi,
i am not sure if having a separate feature parameter is really useful, as there
are currently no real users for it. Please replace features with feature_mask and
remove the associated parameter.
With that being addressed:
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
> +}
> +
> static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
> {
> union acpi_object params[2] = {
> @@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] = {
>
> static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
> {
> + struct device *dev = kobj_to_dev(kobj);
> + struct uniwill_data *data = dev_get_drvdata(dev);
> +
> if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK_TOGGLE,
> + UNIWILL_FEATURE_FN_LOCK_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_super_key_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_touchpad_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE,
> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_rainbow_animation.attr ||
> attr == &dev_attr_breathing_in_suspend.attr) {
> - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
> + UNIWILL_FEATURE_LIGHTBAR))
> return attr->mode;
> }
>
> @@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
> {
> struct device *hdev;
>
> - if (!(supported_features & UNIWILL_FEATURE_HWMON))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON,
> + UNIWILL_FEATURE_HWMON))
> return 0;
>
> hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
> @@ -1019,7 +1044,8 @@ static int uniwill_led_init(struct uniwill_data *data)
> unsigned int value;
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
> + UNIWILL_FEATURE_LIGHTBAR))
> return 0;
>
> ret = devm_mutex_init(data->dev, &data->led_lock);
> @@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct uniwill_data *data)
> {
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> + UNIWILL_FEATURE_BATTERY))
> return 0;
>
> ret = devm_mutex_init(data->dev, &data->battery_lock);
> @@ -1361,6 +1388,19 @@ static int uniwill_probe(struct platform_device *pdev)
> if (ret < 0)
> return ret;
>
> + data->features = device_descriptor.features;
> +
> + /*
> + * Some devices might need to perform some device-specific initialization steps
> + * before the supported features are initialized. Because of this we have to call
> + * this callback just after the EC itself was initialized.
> + */
> + if (device_descriptor.probe) {
> + ret = device_descriptor.probe(data);
> + if (ret < 0)
> + return ret;
> + }
> +
> ret = uniwill_battery_init(data);
> if (ret < 0)
> return ret;
> @@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct platform_device *pdev)
>
> static int uniwill_suspend_keyboard(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return 0;
>
> /*
> @@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct uniwill_data *data)
>
> static int uniwill_suspend_battery(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> + UNIWILL_FEATURE_BATTERY))
> return 0;
>
> /*
> @@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
> unsigned int value;
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return 0;
>
> ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
> @@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
>
> static int uniwill_resume_battery(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> + UNIWILL_FEATURE_BATTERY))
> return 0;
>
> return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
> @@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver = {
> .shutdown = uniwill_shutdown,
> };
>
> +static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> + UNIWILL_FEATURE_BATTERY |
> + UNIWILL_FEATURE_HWMON
> +};
> +
> +static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> + UNIWILL_FEATURE_LIGHTBAR |
> + UNIWILL_FEATURE_BATTERY |
> + UNIWILL_FEATURE_HWMON
> +};
> +
> +static struct uniwill_device_descriptor empty_descriptor __initdata = {};
> +
> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> {
> .ident = "XMG FUSION 15",
> @@ -1503,6 +1566,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
> },
> + .driver_data = &empty_descriptor,
> },
> {
> .ident = "XMG FUSION 15",
> @@ -1510,6 +1574,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
> },
> + .driver_data = &empty_descriptor,
> },
> {
> .ident = "Intel NUC x15",
> @@ -1517,11 +1582,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
> },
> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> - UNIWILL_FEATURE_BATTERY |
> - UNIWILL_FEATURE_HWMON),
> + .driver_data = &lapac71h_descriptor,
> },
> {
> .ident = "Intel NUC x15",
> @@ -1529,12 +1590,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
> },
> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> - UNIWILL_FEATURE_LIGHTBAR |
> - UNIWILL_FEATURE_BATTERY |
> - UNIWILL_FEATURE_HWMON),
> + .driver_data = &lapkc71f_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
> @@ -1542,6 +1598,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
> @@ -1549,6 +1606,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
> @@ -1556,6 +1614,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
> },
> + .driver_data = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
> @@ -1563,6 +1622,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
> @@ -1570,6 +1630,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
> @@ -1577,6 +1638,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
> @@ -1584,6 +1646,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
> @@ -1591,6 +1654,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
> @@ -1598,6 +1662,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
> @@ -1605,6 +1670,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
> @@ -1612,6 +1678,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
> @@ -1619,6 +1686,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
> @@ -1626,6 +1694,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
> @@ -1633,6 +1702,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
> @@ -1640,6 +1710,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
> @@ -1647,6 +1718,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
> @@ -1654,6 +1726,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,
> },
> {
> .ident = "TUXEDO Polaris 15 Gen1 AMD",
> @@ -1661,6 +1734,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,
> },
> {
> .ident = "TUXEDO Polaris 15 Gen1 AMD",
> @@ -1668,6 +1742,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,
> },
> {
> .ident = "TUXEDO Polaris 17 Gen1 AMD",
> @@ -1675,6 +1750,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,
> },
> {
> .ident = "TUXEDO Polaris 17 Gen1 AMD",
> @@ -1682,6 +1758,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,
> },
> {
> .ident = "TUXEDO Polaris 15 Gen1 Intel",
> @@ -1689,6 +1766,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,
> },
> {
> .ident = "TUXEDO Polaris 15 Gen1 Intel",
> @@ -1696,6 +1774,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,
> },
> {
> .ident = "TUXEDO Polaris 17 Gen1 Intel",
> @@ -1703,6 +1782,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,
> },
> {
> .ident = "TUXEDO Polaris 17 Gen1 Intel",
> @@ -1710,6 +1790,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,
> },
> {
> .ident = "TUXEDO Trinity 15 Intel Gen1",
> @@ -1717,6 +1798,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,
> },
> {
> .ident = "TUXEDO Trinity 17 Intel Gen1",
> @@ -1724,6 +1806,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,
> },
> {
> .ident = "TUXEDO Polaris 15/17 Gen2 AMD",
> @@ -1731,6 +1814,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
> @@ -1738,6 +1822,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
> @@ -1745,6 +1830,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
> @@ -1752,6 +1838,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
> @@ -1759,6 +1846,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
> @@ -1766,6 +1854,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
> @@ -1773,6 +1862,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
> @@ -1780,6 +1870,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
> @@ -1787,6 +1878,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
> @@ -1794,6 +1886,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
> @@ -1801,6 +1894,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
> @@ -1808,6 +1902,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
> @@ -1815,6 +1910,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
> @@ -1822,6 +1918,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
> @@ -1829,6 +1926,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
> @@ -1836,6 +1934,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
> @@ -1843,6 +1942,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Pulse 14 Gen1 AMD",
> @@ -1850,6 +1950,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,
> },
> {
> .ident = "TUXEDO Pulse 15 Gen1 AMD",
> @@ -1857,6 +1958,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,
> },
> {
> .ident = "TUXEDO Pulse 15 Gen2 AMD",
> @@ -1864,6 +1966,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,
> },
> { }
> };
> @@ -1871,6 +1974,7 @@ MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
>
> static int __init uniwill_init(void)
> {
> + const struct uniwill_device_descriptor *descriptor;
> const struct dmi_system_id *id;
> int ret;
>
> @@ -1880,10 +1984,22 @@ static int __init uniwill_init(void)
> return -ENODEV;
>
> /* Assume that the device supports all features */
> - supported_features = UINT_MAX;
> + device_descriptor.features = UINT_MAX;
> pr_warn("Loading on a potentially unsupported device\n");
> } else {
> - supported_features = (uintptr_t)id->driver_data;
> + /*
> + * Some devices might support additional features depending on
> + * the BIOS version/date, so we call this callback to let them
> + * modify their device descriptor accordingly.
> + */
> + if (id->callback) {
> + ret = id->callback(id);
> + if (ret < 0)
> + return ret;
> + }
> +
> + descriptor = id->driver_data;
> + device_descriptor = *descriptor;
> }
>
> ret = platform_driver_register(&uniwill_driver);
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting
2025-12-04 13:50 ` [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting Werner Sembach
@ 2025-12-04 16:11 ` Armin Wolf
2025-12-04 16:58 ` Armin Wolf
2025-12-04 21:05 ` Werner Sembach
0 siblings, 2 replies; 19+ messages in thread
From: Armin Wolf @ 2025-12-04 16:11 UTC (permalink / raw)
To: Werner Sembach, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, linux-kernel
Am 04.12.25 um 14:50 schrieb Werner Sembach:
> Uniwill offers user setable cTGP for their EC on devices using NVIDIA 3000
> Series and newer GPUs. This patch implements this setting as a sysfs
> attribute.
>
> For one device, the TUXEDO InfinityBook Gen7, the variant with and without
> NVIDIA GPU can't be differentiated using only the DMI strings, so the new
> probe callback needs to be used to test a bit from the EC memory.
>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
> drivers/platform/x86/uniwill/uniwill-acpi.c | 160 +++++++++++++++++---
> 1 file changed, 135 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index 01192c32608e5..f87f6e9d08234 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -88,6 +88,9 @@
>
> #define EC_ADDR_GPU_TEMP 0x044F
>
> +#define EC_ADDR_SYSTEM_ID 0x0456
> +#define HAS_GPU BIT(7)
I think you need to tell regmap that this new register is readable
by modifying uniwill_readable_reg(), otherwise phxarx1_phxaqf1_probe()
will always fail.
With that being fixed:
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
> +
> #define EC_ADDR_MAIN_FAN_RPM_1 0x0464
>
> #define EC_ADDR_MAIN_FAN_RPM_2 0x0465
> @@ -122,11 +125,11 @@
> #define CTGP_DB_DB_ENABLE BIT(1)
> #define CTGP_DB_CTGP_ENABLE BIT(2)
>
> -#define EC_ADDR_CTGP_OFFSET 0x0744
> +#define EC_ADDR_CTGP_DB_CTGP_OFFSET 0x0744
>
> -#define EC_ADDR_TPP_OFFSET 0x0745
> +#define EC_ADDR_CTGP_DB_TPP_OFFSET 0x0745
>
> -#define EC_ADDR_MAX_TGP 0x0746
> +#define EC_ADDR_CTGP_DB_DB_OFFSET 0x0746
>
> #define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748
> #define LIGHTBAR_APP_EXISTS BIT(0)
> @@ -317,6 +320,7 @@
> #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)
>
> struct uniwill_data {
> struct device *dev;
> @@ -515,6 +519,10 @@ static bool uniwill_writeable_reg(struct device *dev, unsigned int reg)
> case EC_ADDR_LIGHTBAR_BAT_RED:
> case EC_ADDR_LIGHTBAR_BAT_GREEN:
> case EC_ADDR_LIGHTBAR_BAT_BLUE:
> + case EC_ADDR_CTGP_DB_CTRL:
> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
> + case EC_ADDR_CTGP_DB_DB_OFFSET:
> return true;
> default:
> return false;
> @@ -548,6 +556,10 @@ static bool uniwill_readable_reg(struct device *dev, unsigned int reg)
> case EC_ADDR_LIGHTBAR_BAT_RED:
> case EC_ADDR_LIGHTBAR_BAT_GREEN:
> case EC_ADDR_LIGHTBAR_BAT_BLUE:
> + case EC_ADDR_CTGP_DB_CTRL:
> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
> + case EC_ADDR_CTGP_DB_DB_OFFSET:
> return true;
> default:
> return false;
> @@ -803,6 +815,69 @@ static ssize_t breathing_in_suspend_show(struct device *dev, struct device_attri
>
> static DEVICE_ATTR_RW(breathing_in_suspend);
>
> +static ssize_t ctgp_offset_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 = kstrtouint(buf, 0, &value);
> + if (ret < 0)
> + return ret;
> +
> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, value);
> + if (ret < 0)
> + return ret;
> +
> + return count;
> +}
> +
> +static ssize_t ctgp_offset_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct uniwill_data *data = dev_get_drvdata(dev);
> + unsigned int value;
> + int ret;
> +
> + ret = regmap_read(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, &value);
> + if (ret < 0)
> + return ret;
> +
> + return sysfs_emit(buf, "%u\n", value);
> +}
> +
> +static DEVICE_ATTR_RW(ctgp_offset);
> +
> +static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
> +{
> + int ret;
> +
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
> + return 0;
> +
> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, 0);
> + if (ret < 0)
> + return ret;
> +
> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_TPP_OFFSET, 255);
> + if (ret < 0)
> + return ret;
> +
> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_DB_OFFSET, 25);
> + if (ret < 0)
> + return ret;
> +
> + ret = regmap_update_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE,
> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> static struct attribute *uniwill_attrs[] = {
> /* Keyboard-related */
> &dev_attr_fn_lock_toggle_enable.attr,
> @@ -811,6 +886,8 @@ static struct attribute *uniwill_attrs[] = {
> /* Lightbar-related */
> &dev_attr_rainbow_animation.attr,
> &dev_attr_breathing_in_suspend.attr,
> + /* Power-management-related */
> + &dev_attr_ctgp_offset.attr,
> NULL
> };
>
> @@ -844,6 +921,12 @@ static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *a
> return attr->mode;
> }
>
> + if (attr == &dev_attr_ctgp_offset.attr) {
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
> + return attr->mode;
> + }
> +
> return 0;
> }
>
> @@ -1413,6 +1496,10 @@ static int uniwill_probe(struct platform_device *pdev)
> if (ret < 0)
> return ret;
>
> + ret = uniwill_nvidia_ctgp_init(data);
> + if (ret < 0)
> + return ret;
> +
> return uniwill_input_init(data);
> }
>
> @@ -1557,6 +1644,29 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
> UNIWILL_FEATURE_HWMON
> };
>
> +static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
> +{
> + unsigned int value;
> + int ret;
> +
> + ret = regmap_read(data->regmap, EC_ADDR_SYSTEM_ID, &value);
> + if (ret < 0)
> + return ret;
> +
> + if (value & HAS_GPU)
> + data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
> +
> + return 0;
> +};
> +
> +static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor __initdata = {
> + .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 empty_descriptor __initdata = {};
>
> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> @@ -1606,7 +1716,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
> @@ -1614,7 +1724,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
> },
> - .driver_data = &empty_descriptor,
> + .driver_data = &phxarx1_phxaqf1_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
> @@ -1622,7 +1732,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
> @@ -1638,7 +1748,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
> @@ -1646,7 +1756,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
> @@ -1814,7 +1924,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
> @@ -1822,7 +1932,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
> @@ -1830,7 +1940,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
> @@ -1838,7 +1948,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
> @@ -1846,7 +1956,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
> @@ -1854,7 +1964,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
> @@ -1862,7 +1972,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
> @@ -1870,7 +1980,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
> @@ -1878,7 +1988,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
> @@ -1886,7 +1996,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
> @@ -1894,7 +2004,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
> @@ -1902,7 +2012,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
> @@ -1910,7 +2020,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
> @@ -1918,7 +2028,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
> @@ -1926,7 +2036,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
> @@ -1934,7 +2044,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
> @@ -1942,7 +2052,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 = &empty_descriptor,
> + .driver_data = &tux_featureset_1_descriptor,
> },
> {
> .ident = "TUXEDO Pulse 14 Gen1 AMD",
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting
2025-12-04 16:11 ` Armin Wolf
@ 2025-12-04 16:58 ` Armin Wolf
2025-12-04 19:38 ` Armin Wolf
2025-12-04 21:06 ` Werner Sembach
2025-12-04 21:05 ` Werner Sembach
1 sibling, 2 replies; 19+ messages in thread
From: Armin Wolf @ 2025-12-04 16:58 UTC (permalink / raw)
To: Werner Sembach, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, linux-kernel
Am 04.12.25 um 17:11 schrieb Armin Wolf:
> Am 04.12.25 um 14:50 schrieb Werner Sembach:
>
>> Uniwill offers user setable cTGP for their EC on devices using NVIDIA
>> 3000
>> Series and newer GPUs. This patch implements this setting as a sysfs
>> attribute.
>>
>> For one device, the TUXEDO InfinityBook Gen7, the variant with and
>> without
>> NVIDIA GPU can't be differentiated using only the DMI strings, so the
>> new
>> probe callback needs to be used to test a bit from the EC memory.
>>
>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>> ---
>> drivers/platform/x86/uniwill/uniwill-acpi.c | 160 +++++++++++++++++---
>> 1 file changed, 135 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> index 01192c32608e5..f87f6e9d08234 100644
>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> @@ -88,6 +88,9 @@
>> #define EC_ADDR_GPU_TEMP 0x044F
>> +#define EC_ADDR_SYSTEM_ID 0x0456
>> +#define HAS_GPU BIT(7)
>
> I think you need to tell regmap that this new register is readable
> by modifying uniwill_readable_reg(), otherwise phxarx1_phxaqf1_probe()
> will always fail.
>
> With that being fixed:
> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
>
>> +
>> #define EC_ADDR_MAIN_FAN_RPM_1 0x0464
>> #define EC_ADDR_MAIN_FAN_RPM_2 0x0465
>> @@ -122,11 +125,11 @@
>> #define CTGP_DB_DB_ENABLE BIT(1)
>> #define CTGP_DB_CTGP_ENABLE BIT(2)
>> -#define EC_ADDR_CTGP_OFFSET 0x0744
>> +#define EC_ADDR_CTGP_DB_CTGP_OFFSET 0x0744
>> -#define EC_ADDR_TPP_OFFSET 0x0745
>> +#define EC_ADDR_CTGP_DB_TPP_OFFSET 0x0745
>> -#define EC_ADDR_MAX_TGP 0x0746
>> +#define EC_ADDR_CTGP_DB_DB_OFFSET 0x0746
>> #define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748
>> #define LIGHTBAR_APP_EXISTS BIT(0)
>> @@ -317,6 +320,7 @@
>> #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)
>> struct uniwill_data {
>> struct device *dev;
>> @@ -515,6 +519,10 @@ static bool uniwill_writeable_reg(struct device
>> *dev, unsigned int reg)
>> case EC_ADDR_LIGHTBAR_BAT_RED:
>> case EC_ADDR_LIGHTBAR_BAT_GREEN:
>> case EC_ADDR_LIGHTBAR_BAT_BLUE:
>> + case EC_ADDR_CTGP_DB_CTRL:
>> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
>> + case EC_ADDR_CTGP_DB_DB_OFFSET:
>> return true;
>> default:
>> return false;
>> @@ -548,6 +556,10 @@ static bool uniwill_readable_reg(struct device
>> *dev, unsigned int reg)
>> case EC_ADDR_LIGHTBAR_BAT_RED:
>> case EC_ADDR_LIGHTBAR_BAT_GREEN:
>> case EC_ADDR_LIGHTBAR_BAT_BLUE:
>> + case EC_ADDR_CTGP_DB_CTRL:
>> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
>> + case EC_ADDR_CTGP_DB_DB_OFFSET:
>> return true;
>> default:
>> return false;
>> @@ -803,6 +815,69 @@ static ssize_t breathing_in_suspend_show(struct
>> device *dev, struct device_attri
>> static DEVICE_ATTR_RW(breathing_in_suspend);
>> +static ssize_t ctgp_offset_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 = kstrtouint(buf, 0, &value);
>> + if (ret < 0)
>> + return ret;
I forget to mention that you still need to verify that value is smaller than U8_MAX.
Thanks,
Armin Wolf
>> +
>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET,
>> value);
>> + if (ret < 0)
>> + return ret;
>> +
>> + return count;
>> +}
>> +
>> +static ssize_t ctgp_offset_show(struct device *dev, struct
>> device_attribute *attr,
>> + char *buf)
>> +{
>> + struct uniwill_data *data = dev_get_drvdata(dev);
>> + unsigned int value;
>> + int ret;
>> +
>> + ret = regmap_read(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET,
>> &value);
>> + if (ret < 0)
>> + return ret;
>> +
>> + return sysfs_emit(buf, "%u\n", value);
>> +}
>> +
>> +static DEVICE_ATTR_RW(ctgp_offset);
>> +
>> +static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
>> +{
>> + int ret;
>> +
>> + if (!uniwill_device_supports(data,
>> UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
>> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
>> + return 0;
>> +
>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, 0);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_TPP_OFFSET, 255);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_DB_OFFSET, 25);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = regmap_update_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
>> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE |
>> CTGP_DB_CTGP_ENABLE,
>> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE |
>> CTGP_DB_CTGP_ENABLE);
>> + if (ret < 0)
>> + return ret;
>> +
>> + return 0;
>> +}
>> +
>> static struct attribute *uniwill_attrs[] = {
>> /* Keyboard-related */
>> &dev_attr_fn_lock_toggle_enable.attr,
>> @@ -811,6 +886,8 @@ static struct attribute *uniwill_attrs[] = {
>> /* Lightbar-related */
>> &dev_attr_rainbow_animation.attr,
>> &dev_attr_breathing_in_suspend.attr,
>> + /* Power-management-related */
>> + &dev_attr_ctgp_offset.attr,
>> NULL
>> };
>> @@ -844,6 +921,12 @@ static umode_t uniwill_attr_is_visible(struct
>> kobject *kobj, struct attribute *a
>> return attr->mode;
>> }
>> + if (attr == &dev_attr_ctgp_offset.attr) {
>> + if (uniwill_device_supports(data,
>> UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
>> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
>> + return attr->mode;
>> + }
>> +
>> return 0;
>> }
>> @@ -1413,6 +1496,10 @@ static int uniwill_probe(struct
>> platform_device *pdev)
>> if (ret < 0)
>> return ret;
>> + ret = uniwill_nvidia_ctgp_init(data);
>> + if (ret < 0)
>> + return ret;
>> +
>> return uniwill_input_init(data);
>> }
>> @@ -1557,6 +1644,29 @@ static struct uniwill_device_descriptor
>> lapkc71f_descriptor __initdata = {
>> UNIWILL_FEATURE_HWMON
>> };
>> +static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
>> +{
>> + unsigned int value;
>> + int ret;
>> +
>> + ret = regmap_read(data->regmap, EC_ADDR_SYSTEM_ID, &value);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if (value & HAS_GPU)
>> + data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
>> +
>> + return 0;
>> +};
>> +
>> +static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor
>> __initdata = {
>> + .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 empty_descriptor __initdata
>> = {};
>> static const struct dmi_system_id uniwill_dmi_table[] __initconst
>> = {
>> @@ -1606,7 +1716,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
>> @@ -1614,7 +1724,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
>> },
>> - .driver_data = &empty_descriptor,
>> + .driver_data = &phxarx1_phxaqf1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore
>> Omnia-Book Pro Gen 7",
>> @@ -1622,7 +1732,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8
>> Intel/Commodore Omnia-Book Pro Gen 8",
>> @@ -1638,7 +1748,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
>> @@ -1646,7 +1756,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
>> @@ -1814,7 +1924,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
>> @@ -1822,7 +1932,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
>> @@ -1830,7 +1940,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
>> @@ -1838,7 +1948,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
>> @@ -1846,7 +1956,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
>> @@ -1854,7 +1964,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
>> @@ -1862,7 +1972,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
>> @@ -1870,7 +1980,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION
>> Gen 5",
>> @@ -1878,7 +1988,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
>> @@ -1886,7 +1996,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore
>> ORION Slim 15 Gen6",
>> @@ -1894,7 +2004,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16
>> Gen6",
>> @@ -1902,7 +2012,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16
>> Gen6",
>> @@ -1910,7 +2020,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17
>> Gen6",
>> @@ -1918,7 +2028,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
>> @@ -1926,7 +2036,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>> @@ -1934,7 +2044,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>> @@ -1942,7 +2052,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Pulse 14 Gen1 AMD",
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting
2025-12-04 16:58 ` Armin Wolf
@ 2025-12-04 19:38 ` Armin Wolf
2025-12-04 21:06 ` Werner Sembach
1 sibling, 0 replies; 19+ messages in thread
From: Armin Wolf @ 2025-12-04 19:38 UTC (permalink / raw)
To: Werner Sembach, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 20468 bytes --]
Am 04.12.25 um 17:58 schrieb Armin Wolf:
> Am 04.12.25 um 17:11 schrieb Armin Wolf:
>
>> Am 04.12.25 um 14:50 schrieb Werner Sembach:
>>
>>> Uniwill offers user setable cTGP for their EC on devices using
>>> NVIDIA 3000
>>> Series and newer GPUs. This patch implements this setting as a sysfs
>>> attribute.
>>>
>>> For one device, the TUXEDO InfinityBook Gen7, the variant with and
>>> without
>>> NVIDIA GPU can't be differentiated using only the DMI strings, so
>>> the new
>>> probe callback needs to be used to test a bit from the EC memory.
>>>
>>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>>> ---
>>> drivers/platform/x86/uniwill/uniwill-acpi.c | 160
>>> +++++++++++++++++---
>>> 1 file changed, 135 insertions(+), 25 deletions(-)
>>>
>>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> index 01192c32608e5..f87f6e9d08234 100644
>>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> @@ -88,6 +88,9 @@
>>> #define EC_ADDR_GPU_TEMP 0x044F
>>> +#define EC_ADDR_SYSTEM_ID 0x0456
>>> +#define HAS_GPU BIT(7)
>>
>> I think you need to tell regmap that this new register is readable
>> by modifying uniwill_readable_reg(), otherwise phxarx1_phxaqf1_probe()
>> will always fail.
>>
>> With that being fixed:
>> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
>>
>>> +
>>> #define EC_ADDR_MAIN_FAN_RPM_1 0x0464
>>> #define EC_ADDR_MAIN_FAN_RPM_2 0x0465
>>> @@ -122,11 +125,11 @@
>>> #define CTGP_DB_DB_ENABLE BIT(1)
>>> #define CTGP_DB_CTGP_ENABLE BIT(2)
>>> -#define EC_ADDR_CTGP_OFFSET 0x0744
>>> +#define EC_ADDR_CTGP_DB_CTGP_OFFSET 0x0744
>>> -#define EC_ADDR_TPP_OFFSET 0x0745
>>> +#define EC_ADDR_CTGP_DB_TPP_OFFSET 0x0745
>>> -#define EC_ADDR_MAX_TGP 0x0746
>>> +#define EC_ADDR_CTGP_DB_DB_OFFSET 0x0746
>>> #define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748
>>> #define LIGHTBAR_APP_EXISTS BIT(0)
>>> @@ -317,6 +320,7 @@
>>> #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)
>>> struct uniwill_data {
>>> struct device *dev;
>>> @@ -515,6 +519,10 @@ static bool uniwill_writeable_reg(struct device
>>> *dev, unsigned int reg)
>>> case EC_ADDR_LIGHTBAR_BAT_RED:
>>> case EC_ADDR_LIGHTBAR_BAT_GREEN:
>>> case EC_ADDR_LIGHTBAR_BAT_BLUE:
>>> + case EC_ADDR_CTGP_DB_CTRL:
>>> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>>> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
>>> + case EC_ADDR_CTGP_DB_DB_OFFSET:
>>> return true;
>>> default:
>>> return false;
>>> @@ -548,6 +556,10 @@ static bool uniwill_readable_reg(struct device
>>> *dev, unsigned int reg)
>>> case EC_ADDR_LIGHTBAR_BAT_RED:
>>> case EC_ADDR_LIGHTBAR_BAT_GREEN:
>>> case EC_ADDR_LIGHTBAR_BAT_BLUE:
>>> + case EC_ADDR_CTGP_DB_CTRL:
>>> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>>> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
>>> + case EC_ADDR_CTGP_DB_DB_OFFSET:
>>> return true;
>>> default:
>>> return false;
>>> @@ -803,6 +815,69 @@ static ssize_t breathing_in_suspend_show(struct
>>> device *dev, struct device_attri
>>> static DEVICE_ATTR_RW(breathing_in_suspend);
>>> +static ssize_t ctgp_offset_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 = kstrtouint(buf, 0, &value);
>>> + if (ret < 0)
>>> + return ret;
>
> I forget to mention that you still need to verify that value is
> smaller than U8_MAX.
>
> Thanks,
> Armin Wolf
>
While using this patch series to add cTGP support for the LAPKC71F, i just noticed that
you also did not disable cTGP and dynamic boost during suspend. I attached an experimental patch
for that, you can use that if you wish. I do not think that you have to clear CTGP_DB_GENERAL_ENABLE
during suspend, as the driver itself still controls the cTGP and dynamic boost settings.
Thanks,
Armin Wolf
>>> +
>>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET,
>>> value);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + return count;
>>> +}
>>> +
>>> +static ssize_t ctgp_offset_show(struct device *dev, struct
>>> device_attribute *attr,
>>> + char *buf)
>>> +{
>>> + struct uniwill_data *data = dev_get_drvdata(dev);
>>> + unsigned int value;
>>> + int ret;
>>> +
>>> + ret = regmap_read(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET,
>>> &value);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + return sysfs_emit(buf, "%u\n", value);
>>> +}
>>> +
>>> +static DEVICE_ATTR_RW(ctgp_offset);
>>> +
>>> +static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
>>> +{
>>> + int ret;
>>> +
>>> + if (!uniwill_device_supports(data,
>>> UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
>>> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
>>> + return 0;
>>> +
>>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, 0);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_TPP_OFFSET, 255);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_DB_OFFSET, 25);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + ret = regmap_update_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
>>> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE |
>>> CTGP_DB_CTGP_ENABLE,
>>> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE |
>>> CTGP_DB_CTGP_ENABLE);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static struct attribute *uniwill_attrs[] = {
>>> /* Keyboard-related */
>>> &dev_attr_fn_lock_toggle_enable.attr,
>>> @@ -811,6 +886,8 @@ static struct attribute *uniwill_attrs[] = {
>>> /* Lightbar-related */
>>> &dev_attr_rainbow_animation.attr,
>>> &dev_attr_breathing_in_suspend.attr,
>>> + /* Power-management-related */
>>> + &dev_attr_ctgp_offset.attr,
>>> NULL
>>> };
>>> @@ -844,6 +921,12 @@ static umode_t uniwill_attr_is_visible(struct
>>> kobject *kobj, struct attribute *a
>>> return attr->mode;
>>> }
>>> + if (attr == &dev_attr_ctgp_offset.attr) {
>>> + if (uniwill_device_supports(data,
>>> UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
>>> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
>>> + return attr->mode;
>>> + }
>>> +
>>> return 0;
>>> }
>>> @@ -1413,6 +1496,10 @@ static int uniwill_probe(struct
>>> platform_device *pdev)
>>> if (ret < 0)
>>> return ret;
>>> + ret = uniwill_nvidia_ctgp_init(data);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> return uniwill_input_init(data);
>>> }
>>> @@ -1557,6 +1644,29 @@ static struct uniwill_device_descriptor
>>> lapkc71f_descriptor __initdata = {
>>> UNIWILL_FEATURE_HWMON
>>> };
>>> +static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
>>> +{
>>> + unsigned int value;
>>> + int ret;
>>> +
>>> + ret = regmap_read(data->regmap, EC_ADDR_SYSTEM_ID, &value);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + if (value & HAS_GPU)
>>> + data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
>>> +
>>> + return 0;
>>> +};
>>> +
>>> +static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor
>>> __initdata = {
>>> + .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 empty_descriptor
>>> __initdata = {};
>>> static const struct dmi_system_id uniwill_dmi_table[]
>>> __initconst = {
>>> @@ -1606,7 +1716,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
>>> @@ -1614,7 +1724,7 @@ static const struct dmi_system_id
>>> uniwill_dmi_table[] __initconst = {
>>> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
>>> },
>>> - .driver_data = &empty_descriptor,
>>> + .driver_data = &phxarx1_phxaqf1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore
>>> Omnia-Book Pro Gen 7",
>>> @@ -1622,7 +1732,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8
>>> Intel/Commodore Omnia-Book Pro Gen 8",
>>> @@ -1638,7 +1748,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
>>> @@ -1646,7 +1756,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
>>> @@ -1814,7 +1924,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
>>> @@ -1822,7 +1932,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
>>> @@ -1830,7 +1940,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
>>> @@ -1838,7 +1948,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
>>> @@ -1846,7 +1956,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
>>> @@ -1854,7 +1964,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
>>> @@ -1862,7 +1972,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
>>> @@ -1870,7 +1980,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore
>>> ORION Gen 5",
>>> @@ -1878,7 +1988,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
>>> @@ -1886,7 +1996,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore
>>> ORION Slim 15 Gen6",
>>> @@ -1894,7 +2004,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION
>>> 16 Gen6",
>>> @@ -1902,7 +2012,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION
>>> 16 Gen6",
>>> @@ -1910,7 +2020,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION
>>> 17 Gen6",
>>> @@ -1918,7 +2028,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
>>> @@ -1926,7 +2036,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>>> @@ -1934,7 +2044,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>>> @@ -1942,7 +2052,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Pulse 14 Gen1 AMD",
>>
[-- Attachment #2: 0001-platform-x86-uniwill-laptop-Disable-cTGP-and-dynamic.patch --]
[-- Type: text/x-patch, Size: 2812 bytes --]
From 707597b019a608625f64fef0c787fdf6c75f32b8 Mon Sep 17 00:00:00 2001
From: Armin Wolf <W_Armin@gmx.de>
Date: Thu, 4 Dec 2025 20:21:38 +0100
Subject: [PATCH] platform/x86: uniwill-laptop: Disable cTGP and dynamic boost
during suspend
TODO
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
drivers/platform/x86/uniwill/uniwill-acpi.c | 33 ++++++++++++++++++---
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 6ce0b9c99d3d..c7e9db3c9a4d 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -897,9 +897,8 @@ static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
if (ret < 0)
return ret;
- ret = regmap_update_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
- CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE,
- CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
+ ret = regmap_set_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
+ CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
if (ret < 0)
return ret;
@@ -1570,6 +1569,15 @@ static int uniwill_suspend_battery(struct uniwill_data *data)
return regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &data->last_charge_ctrl);
}
+static int uniwill_suspend_nvidia_ctgp(struct uniwill_data *data)
+{
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
+ return 0;
+
+ return regmap_clear_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
+ CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
+}
+
static int uniwill_suspend(struct device *dev)
{
struct uniwill_data *data = dev_get_drvdata(dev);
@@ -1583,6 +1591,10 @@ static int uniwill_suspend(struct device *dev)
if (ret < 0)
return ret;
+ ret = uniwill_suspend_nvidia_ctgp(data);
+ if (ret < 0)
+ return ret;
+
regcache_cache_only(data->regmap, true);
regcache_mark_dirty(data->regmap);
@@ -1619,6 +1631,15 @@ static int uniwill_resume_battery(struct uniwill_data *data)
data->last_charge_ctrl);
}
+static int uniwill_resume_nvidia_ctgp(struct uniwill_data *data)
+{
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
+ return 0;
+
+ return regmap_set_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
+ CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
+}
+
static int uniwill_resume(struct device *dev)
{
struct uniwill_data *data = dev_get_drvdata(dev);
@@ -1634,7 +1655,11 @@ static int uniwill_resume(struct device *dev)
if (ret < 0)
return ret;
- return uniwill_resume_battery(data);
+ ret = uniwill_resume_battery(data);
+ if (ret < 0)
+ return ret;
+
+ return uniwill_resume_nvidia_ctgp(data);
}
static DEFINE_SIMPLE_DEV_PM_OPS(uniwill_pm_ops, uniwill_suspend, uniwill_resume);
--
2.39.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2025-12-04 16:03 ` Armin Wolf
@ 2025-12-04 21:03 ` Werner Sembach
2025-12-04 21:22 ` Armin Wolf
0 siblings, 1 reply; 19+ messages in thread
From: Werner Sembach @ 2025-12-04 21:03 UTC (permalink / raw)
To: Armin Wolf, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, linux-kernel
Am 04.12.25 um 17:03 schrieb Armin Wolf:
> Am 04.12.25 um 14:50 schrieb Werner Sembach:
>
>> From: Armin Wolf <W_Armin@gmx.de>
>>
>> Future additions to the driver will depend on device-specific
>> initialization steps. Extend the DMI-based feature detection system
>> to include device descriptors. Each descriptor contains a bitmap of
>> supported features and a set of callback for performing
>> device-specific initialization.
>>
>> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
>> Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>> ---
>> drivers/platform/x86/uniwill/uniwill-acpi.c | 168 +++++++++++++++++---
>> 1 file changed, 142 insertions(+), 26 deletions(-)
>>
>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> index bd7e63dd51810..01192c32608e5 100644
>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> @@ -322,6 +322,7 @@ struct uniwill_data {
>> struct device *dev;
>> acpi_handle handle;
>> struct regmap *regmap;
>> + unsigned int features;
>> struct acpi_battery_hook hook;
>> unsigned int last_charge_ctrl;
>> struct mutex battery_lock; /* Protects the list of currently
>> registered batteries */
>> @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
>> struct power_supply *battery;
>> };
>> +struct uniwill_device_descriptor {
>> + unsigned int features;
>> + /* Executed during driver probing */
>> + int (*probe)(struct uniwill_data *data);
>> +};
>> +
>> static bool force;
>> module_param_unsafe(force, bool, 0);
>> MODULE_PARM_DESC(force, "Force loading without checking for
>> supported devices\n");
>> -/* Feature bitmask since the associated registers are not reliable */
>> -static unsigned int supported_features;
>> +/*
>> + * Contains device specific data like the feature bitmap since
>> + * the associated registers are not always reliable.
>> + */
>> +static struct uniwill_device_descriptor device_descriptor
>> __ro_after_init;
>> static const char * const uniwill_temp_labels[] = {
>> "CPU",
>> @@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] = {
>> { KE_END }
>> };
>> +static inline bool uniwill_device_supports(struct uniwill_data *data,
>> + unsigned int features_mask,
>> + unsigned int features)
>> +{
>> + return (data->features & features_mask) == features;
>
> Hi,
>
> i am not sure if having a separate feature parameter is really useful,
> as there
> are currently no real users for it. Please replace features with
> feature_mask and
> remove the associated parameter.
There might be mutually exclusive features that can be represented with
more then 1 bit to save some bit space, e.g. 3 different kind of
keyboard backlight controls that could be represented by 2 bits: 00 ->
None, 01 -> Type 1, 10 -> Type 2, 11 -> Type 3 instead of having one bit
for each type.
>
> With that being addressed:
> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
>
>> +}
>> +
>> static int uniwill_ec_reg_write(void *context, unsigned int reg,
>> unsigned int val)
>> {
>> union acpi_object params[2] = {
>> @@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] = {
>> static umode_t uniwill_attr_is_visible(struct kobject *kobj,
>> struct attribute *attr, int n)
>> {
>> + struct device *dev = kobj_to_dev(kobj);
>> + struct uniwill_data *data = dev_get_drvdata(dev);
>> +
>> if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
>> + if (uniwill_device_supports(data,
>> UNIWILL_FEATURE_FN_LOCK_TOGGLE,
>> + UNIWILL_FEATURE_FN_LOCK_TOGGLE))
>> return attr->mode;
>> }
>> if (attr == &dev_attr_super_key_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
>> + if (uniwill_device_supports(data,
>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return attr->mode;
>> }
>> if (attr == &dev_attr_touchpad_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
>> + if (uniwill_device_supports(data,
>> UNIWILL_FEATURE_TOUCHPAD_TOGGLE,
>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
>> return attr->mode;
>> }
>> if (attr == &dev_attr_rainbow_animation.attr ||
>> attr == &dev_attr_breathing_in_suspend.attr) {
>> - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
>> + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
>> + UNIWILL_FEATURE_LIGHTBAR))
>> return attr->mode;
>> }
>> @@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct
>> uniwill_data *data)
>> {
>> struct device *hdev;
>> - if (!(supported_features & UNIWILL_FEATURE_HWMON))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON,
>> + UNIWILL_FEATURE_HWMON))
>> return 0;
>> hdev = devm_hwmon_device_register_with_info(data->dev,
>> "uniwill", data,
>> @@ -1019,7 +1044,8 @@ static int uniwill_led_init(struct uniwill_data
>> *data)
>> unsigned int value;
>> int ret;
>> - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
>> + UNIWILL_FEATURE_LIGHTBAR))
>> return 0;
>> ret = devm_mutex_init(data->dev, &data->led_lock);
>> @@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct
>> uniwill_data *data)
>> {
>> int ret;
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>> + UNIWILL_FEATURE_BATTERY))
>> return 0;
>> ret = devm_mutex_init(data->dev, &data->battery_lock);
>> @@ -1361,6 +1388,19 @@ static int uniwill_probe(struct
>> platform_device *pdev)
>> if (ret < 0)
>> return ret;
>> + data->features = device_descriptor.features;
>> +
>> + /*
>> + * Some devices might need to perform some device-specific
>> initialization steps
>> + * before the supported features are initialized. Because of
>> this we have to call
>> + * this callback just after the EC itself was initialized.
>> + */
>> + if (device_descriptor.probe) {
>> + ret = device_descriptor.probe(data);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> ret = uniwill_battery_init(data);
>> if (ret < 0)
>> return ret;
>> @@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct
>> platform_device *pdev)
>> static int uniwill_suspend_keyboard(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> + if (!uniwill_device_supports(data,
>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return 0;
>> /*
>> @@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct
>> uniwill_data *data)
>> static int uniwill_suspend_battery(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>> + UNIWILL_FEATURE_BATTERY))
>> return 0;
>> /*
>> @@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct
>> uniwill_data *data)
>> unsigned int value;
>> int ret;
>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> + if (!uniwill_device_supports(data,
>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return 0;
>> ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
>> @@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct
>> uniwill_data *data)
>> static int uniwill_resume_battery(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>> + UNIWILL_FEATURE_BATTERY))
>> return 0;
>> return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL,
>> CHARGE_CTRL_MASK,
>> @@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver = {
>> .shutdown = uniwill_shutdown,
>> };
>> +static struct uniwill_device_descriptor lapac71h_descriptor
>> __initdata = {
>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> + UNIWILL_FEATURE_BATTERY |
>> + UNIWILL_FEATURE_HWMON
>> +};
>> +
>> +static struct uniwill_device_descriptor lapkc71f_descriptor
>> __initdata = {
>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> + UNIWILL_FEATURE_LIGHTBAR |
>> + UNIWILL_FEATURE_BATTERY |
>> + UNIWILL_FEATURE_HWMON
>> +};
>> +
>> +static struct uniwill_device_descriptor empty_descriptor __initdata
>> = {};
>> +
>> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>> {
>> .ident = "XMG FUSION 15",
>> @@ -1503,6 +1566,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
>> },
>> + .driver_data = &empty_descriptor,
>> },
>> {
>> .ident = "XMG FUSION 15",
>> @@ -1510,6 +1574,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
>> },
>> + .driver_data = &empty_descriptor,
>> },
>> {
>> .ident = "Intel NUC x15",
>> @@ -1517,11 +1582,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client
>> Systems"),
>> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
>> },
>> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> - UNIWILL_FEATURE_BATTERY |
>> - UNIWILL_FEATURE_HWMON),
>> + .driver_data = &lapac71h_descriptor,
>> },
>> {
>> .ident = "Intel NUC x15",
>> @@ -1529,12 +1590,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client
>> Systems"),
>> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
>> },
>> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> - UNIWILL_FEATURE_LIGHTBAR |
>> - UNIWILL_FEATURE_BATTERY |
>> - UNIWILL_FEATURE_HWMON),
>> + .driver_data = &lapkc71f_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
>> @@ -1542,6 +1598,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
>> @@ -1549,6 +1606,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
>> @@ -1556,6 +1614,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
>> },
>> + .driver_data = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore
>> Omnia-Book Pro Gen 7",
>> @@ -1563,6 +1622,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8
>> Intel/Commodore Omnia-Book Pro Gen 8",
>> @@ -1570,6 +1630,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore
>> Omnia-Book Pro Gen 8",
>> @@ -1577,6 +1638,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
>> @@ -1584,6 +1646,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
>> @@ -1591,6 +1654,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9
>> Intel/Commodore Omnia-Book 15 Gen9",
>> @@ -1598,6 +1662,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
>> @@ -1605,6 +1670,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
>> @@ -1612,6 +1678,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
>> @@ -1619,6 +1686,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
>> @@ -1626,6 +1694,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
>> @@ -1633,6 +1702,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
>> @@ -1640,6 +1710,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
>> @@ -1647,6 +1718,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
>> @@ -1654,6 +1726,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15 Gen1 AMD",
>> @@ -1661,6 +1734,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15 Gen1 AMD",
>> @@ -1668,6 +1742,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 17 Gen1 AMD",
>> @@ -1675,6 +1750,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 17 Gen1 AMD",
>> @@ -1682,6 +1758,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15 Gen1 Intel",
>> @@ -1689,6 +1766,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15 Gen1 Intel",
>> @@ -1696,6 +1774,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 17 Gen1 Intel",
>> @@ -1703,6 +1782,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 17 Gen1 Intel",
>> @@ -1710,6 +1790,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,
>> },
>> {
>> .ident = "TUXEDO Trinity 15 Intel Gen1",
>> @@ -1717,6 +1798,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,
>> },
>> {
>> .ident = "TUXEDO Trinity 17 Intel Gen1",
>> @@ -1724,6 +1806,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen2 AMD",
>> @@ -1731,6 +1814,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
>> @@ -1738,6 +1822,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
>> @@ -1745,6 +1830,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
>> @@ -1752,6 +1838,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
>> @@ -1759,6 +1846,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
>> @@ -1766,6 +1854,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
>> @@ -1773,6 +1862,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
>> @@ -1780,6 +1870,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION
>> Gen 5",
>> @@ -1787,6 +1878,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
>> @@ -1794,6 +1886,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore
>> ORION Slim 15 Gen6",
>> @@ -1801,6 +1894,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16
>> Gen6",
>> @@ -1808,6 +1902,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16
>> Gen6",
>> @@ -1815,6 +1910,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17
>> Gen6",
>> @@ -1822,6 +1918,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
>> @@ -1829,6 +1926,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>> @@ -1836,6 +1934,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>> @@ -1843,6 +1942,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Pulse 14 Gen1 AMD",
>> @@ -1850,6 +1950,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,
>> },
>> {
>> .ident = "TUXEDO Pulse 15 Gen1 AMD",
>> @@ -1857,6 +1958,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,
>> },
>> {
>> .ident = "TUXEDO Pulse 15 Gen2 AMD",
>> @@ -1864,6 +1966,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,
>> },
>> { }
>> };
>> @@ -1871,6 +1974,7 @@ MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
>> static int __init uniwill_init(void)
>> {
>> + const struct uniwill_device_descriptor *descriptor;
>> const struct dmi_system_id *id;
>> int ret;
>> @@ -1880,10 +1984,22 @@ static int __init uniwill_init(void)
>> return -ENODEV;
>> /* Assume that the device supports all features */
>> - supported_features = UINT_MAX;
>> + device_descriptor.features = UINT_MAX;
>> pr_warn("Loading on a potentially unsupported device\n");
>> } else {
>> - supported_features = (uintptr_t)id->driver_data;
>> + /*
>> + * Some devices might support additional features depending on
>> + * the BIOS version/date, so we call this callback to let them
>> + * modify their device descriptor accordingly.
>> + */
>> + if (id->callback) {
>> + ret = id->callback(id);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> + descriptor = id->driver_data;
>> + device_descriptor = *descriptor;
>> }
>> ret = platform_driver_register(&uniwill_driver);
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting
2025-12-04 16:11 ` Armin Wolf
2025-12-04 16:58 ` Armin Wolf
@ 2025-12-04 21:05 ` Werner Sembach
1 sibling, 0 replies; 19+ messages in thread
From: Werner Sembach @ 2025-12-04 21:05 UTC (permalink / raw)
To: Armin Wolf, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, linux-kernel
Am 04.12.25 um 17:11 schrieb Armin Wolf:
> Am 04.12.25 um 14:50 schrieb Werner Sembach:
>
>> Uniwill offers user setable cTGP for their EC on devices using NVIDIA
>> 3000
>> Series and newer GPUs. This patch implements this setting as a sysfs
>> attribute.
>>
>> For one device, the TUXEDO InfinityBook Gen7, the variant with and
>> without
>> NVIDIA GPU can't be differentiated using only the DMI strings, so the
>> new
>> probe callback needs to be used to test a bit from the EC memory.
>>
>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>> ---
>> drivers/platform/x86/uniwill/uniwill-acpi.c | 160 +++++++++++++++++---
>> 1 file changed, 135 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> index 01192c32608e5..f87f6e9d08234 100644
>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> @@ -88,6 +88,9 @@
>> #define EC_ADDR_GPU_TEMP 0x044F
>> +#define EC_ADDR_SYSTEM_ID 0x0456
>> +#define HAS_GPU BIT(7)
>
> I think you need to tell regmap that this new register is readable
> by modifying uniwill_readable_reg(), otherwise phxarx1_phxaqf1_probe()
> will always fail.
ack will double check
>
> With that being fixed:
> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
>
>> +
>> #define EC_ADDR_MAIN_FAN_RPM_1 0x0464
>> #define EC_ADDR_MAIN_FAN_RPM_2 0x0465
>> @@ -122,11 +125,11 @@
>> #define CTGP_DB_DB_ENABLE BIT(1)
>> #define CTGP_DB_CTGP_ENABLE BIT(2)
>> -#define EC_ADDR_CTGP_OFFSET 0x0744
>> +#define EC_ADDR_CTGP_DB_CTGP_OFFSET 0x0744
>> -#define EC_ADDR_TPP_OFFSET 0x0745
>> +#define EC_ADDR_CTGP_DB_TPP_OFFSET 0x0745
>> -#define EC_ADDR_MAX_TGP 0x0746
>> +#define EC_ADDR_CTGP_DB_DB_OFFSET 0x0746
>> #define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748
>> #define LIGHTBAR_APP_EXISTS BIT(0)
>> @@ -317,6 +320,7 @@
>> #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)
>> struct uniwill_data {
>> struct device *dev;
>> @@ -515,6 +519,10 @@ static bool uniwill_writeable_reg(struct device
>> *dev, unsigned int reg)
>> case EC_ADDR_LIGHTBAR_BAT_RED:
>> case EC_ADDR_LIGHTBAR_BAT_GREEN:
>> case EC_ADDR_LIGHTBAR_BAT_BLUE:
>> + case EC_ADDR_CTGP_DB_CTRL:
>> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
>> + case EC_ADDR_CTGP_DB_DB_OFFSET:
>> return true;
>> default:
>> return false;
>> @@ -548,6 +556,10 @@ static bool uniwill_readable_reg(struct device
>> *dev, unsigned int reg)
>> case EC_ADDR_LIGHTBAR_BAT_RED:
>> case EC_ADDR_LIGHTBAR_BAT_GREEN:
>> case EC_ADDR_LIGHTBAR_BAT_BLUE:
>> + case EC_ADDR_CTGP_DB_CTRL:
>> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
>> + case EC_ADDR_CTGP_DB_DB_OFFSET:
>> return true;
>> default:
>> return false;
>> @@ -803,6 +815,69 @@ static ssize_t breathing_in_suspend_show(struct
>> device *dev, struct device_attri
>> static DEVICE_ATTR_RW(breathing_in_suspend);
>> +static ssize_t ctgp_offset_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 = kstrtouint(buf, 0, &value);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET,
>> value);
>> + if (ret < 0)
>> + return ret;
>> +
>> + return count;
>> +}
>> +
>> +static ssize_t ctgp_offset_show(struct device *dev, struct
>> device_attribute *attr,
>> + char *buf)
>> +{
>> + struct uniwill_data *data = dev_get_drvdata(dev);
>> + unsigned int value;
>> + int ret;
>> +
>> + ret = regmap_read(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET,
>> &value);
>> + if (ret < 0)
>> + return ret;
>> +
>> + return sysfs_emit(buf, "%u\n", value);
>> +}
>> +
>> +static DEVICE_ATTR_RW(ctgp_offset);
>> +
>> +static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
>> +{
>> + int ret;
>> +
>> + if (!uniwill_device_supports(data,
>> UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
>> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
>> + return 0;
>> +
>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, 0);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_TPP_OFFSET, 255);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_DB_OFFSET, 25);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = regmap_update_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
>> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE |
>> CTGP_DB_CTGP_ENABLE,
>> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE |
>> CTGP_DB_CTGP_ENABLE);
>> + if (ret < 0)
>> + return ret;
>> +
>> + return 0;
>> +}
>> +
>> static struct attribute *uniwill_attrs[] = {
>> /* Keyboard-related */
>> &dev_attr_fn_lock_toggle_enable.attr,
>> @@ -811,6 +886,8 @@ static struct attribute *uniwill_attrs[] = {
>> /* Lightbar-related */
>> &dev_attr_rainbow_animation.attr,
>> &dev_attr_breathing_in_suspend.attr,
>> + /* Power-management-related */
>> + &dev_attr_ctgp_offset.attr,
>> NULL
>> };
>> @@ -844,6 +921,12 @@ static umode_t uniwill_attr_is_visible(struct
>> kobject *kobj, struct attribute *a
>> return attr->mode;
>> }
>> + if (attr == &dev_attr_ctgp_offset.attr) {
>> + if (uniwill_device_supports(data,
>> UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
>> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
>> + return attr->mode;
>> + }
>> +
>> return 0;
>> }
>> @@ -1413,6 +1496,10 @@ static int uniwill_probe(struct
>> platform_device *pdev)
>> if (ret < 0)
>> return ret;
>> + ret = uniwill_nvidia_ctgp_init(data);
>> + if (ret < 0)
>> + return ret;
>> +
>> return uniwill_input_init(data);
>> }
>> @@ -1557,6 +1644,29 @@ static struct uniwill_device_descriptor
>> lapkc71f_descriptor __initdata = {
>> UNIWILL_FEATURE_HWMON
>> };
>> +static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
>> +{
>> + unsigned int value;
>> + int ret;
>> +
>> + ret = regmap_read(data->regmap, EC_ADDR_SYSTEM_ID, &value);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if (value & HAS_GPU)
>> + data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
>> +
>> + return 0;
>> +};
>> +
>> +static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor
>> __initdata = {
>> + .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 empty_descriptor __initdata
>> = {};
>> static const struct dmi_system_id uniwill_dmi_table[] __initconst
>> = {
>> @@ -1606,7 +1716,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
>> @@ -1614,7 +1724,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
>> },
>> - .driver_data = &empty_descriptor,
>> + .driver_data = &phxarx1_phxaqf1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore
>> Omnia-Book Pro Gen 7",
>> @@ -1622,7 +1732,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8
>> Intel/Commodore Omnia-Book Pro Gen 8",
>> @@ -1638,7 +1748,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
>> @@ -1646,7 +1756,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
>> @@ -1814,7 +1924,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
>> @@ -1822,7 +1932,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
>> @@ -1830,7 +1940,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
>> @@ -1838,7 +1948,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
>> @@ -1846,7 +1956,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
>> @@ -1854,7 +1964,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
>> @@ -1862,7 +1972,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
>> @@ -1870,7 +1980,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION
>> Gen 5",
>> @@ -1878,7 +1988,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
>> @@ -1886,7 +1996,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore
>> ORION Slim 15 Gen6",
>> @@ -1894,7 +2004,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16
>> Gen6",
>> @@ -1902,7 +2012,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16
>> Gen6",
>> @@ -1910,7 +2020,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17
>> Gen6",
>> @@ -1918,7 +2028,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
>> @@ -1926,7 +2036,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>> @@ -1934,7 +2044,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>> @@ -1942,7 +2052,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 = &empty_descriptor,
>> + .driver_data = &tux_featureset_1_descriptor,
>> },
>> {
>> .ident = "TUXEDO Pulse 14 Gen1 AMD",
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting
2025-12-04 16:58 ` Armin Wolf
2025-12-04 19:38 ` Armin Wolf
@ 2025-12-04 21:06 ` Werner Sembach
1 sibling, 0 replies; 19+ messages in thread
From: Werner Sembach @ 2025-12-04 21:06 UTC (permalink / raw)
To: Armin Wolf, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, linux-kernel
Am 04.12.25 um 17:58 schrieb Armin Wolf:
> Am 04.12.25 um 17:11 schrieb Armin Wolf:
>
>> Am 04.12.25 um 14:50 schrieb Werner Sembach:
>>
>>> Uniwill offers user setable cTGP for their EC on devices using
>>> NVIDIA 3000
>>> Series and newer GPUs. This patch implements this setting as a sysfs
>>> attribute.
>>>
>>> For one device, the TUXEDO InfinityBook Gen7, the variant with and
>>> without
>>> NVIDIA GPU can't be differentiated using only the DMI strings, so
>>> the new
>>> probe callback needs to be used to test a bit from the EC memory.
>>>
>>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>>> ---
>>> drivers/platform/x86/uniwill/uniwill-acpi.c | 160
>>> +++++++++++++++++---
>>> 1 file changed, 135 insertions(+), 25 deletions(-)
>>>
>>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> index 01192c32608e5..f87f6e9d08234 100644
>>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> @@ -88,6 +88,9 @@
>>> #define EC_ADDR_GPU_TEMP 0x044F
>>> +#define EC_ADDR_SYSTEM_ID 0x0456
>>> +#define HAS_GPU BIT(7)
>>
>> I think you need to tell regmap that this new register is readable
>> by modifying uniwill_readable_reg(), otherwise phxarx1_phxaqf1_probe()
>> will always fail.
>>
>> With that being fixed:
>> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
>>
>>> +
>>> #define EC_ADDR_MAIN_FAN_RPM_1 0x0464
>>> #define EC_ADDR_MAIN_FAN_RPM_2 0x0465
>>> @@ -122,11 +125,11 @@
>>> #define CTGP_DB_DB_ENABLE BIT(1)
>>> #define CTGP_DB_CTGP_ENABLE BIT(2)
>>> -#define EC_ADDR_CTGP_OFFSET 0x0744
>>> +#define EC_ADDR_CTGP_DB_CTGP_OFFSET 0x0744
>>> -#define EC_ADDR_TPP_OFFSET 0x0745
>>> +#define EC_ADDR_CTGP_DB_TPP_OFFSET 0x0745
>>> -#define EC_ADDR_MAX_TGP 0x0746
>>> +#define EC_ADDR_CTGP_DB_DB_OFFSET 0x0746
>>> #define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748
>>> #define LIGHTBAR_APP_EXISTS BIT(0)
>>> @@ -317,6 +320,7 @@
>>> #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)
>>> struct uniwill_data {
>>> struct device *dev;
>>> @@ -515,6 +519,10 @@ static bool uniwill_writeable_reg(struct device
>>> *dev, unsigned int reg)
>>> case EC_ADDR_LIGHTBAR_BAT_RED:
>>> case EC_ADDR_LIGHTBAR_BAT_GREEN:
>>> case EC_ADDR_LIGHTBAR_BAT_BLUE:
>>> + case EC_ADDR_CTGP_DB_CTRL:
>>> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>>> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
>>> + case EC_ADDR_CTGP_DB_DB_OFFSET:
>>> return true;
>>> default:
>>> return false;
>>> @@ -548,6 +556,10 @@ static bool uniwill_readable_reg(struct device
>>> *dev, unsigned int reg)
>>> case EC_ADDR_LIGHTBAR_BAT_RED:
>>> case EC_ADDR_LIGHTBAR_BAT_GREEN:
>>> case EC_ADDR_LIGHTBAR_BAT_BLUE:
>>> + case EC_ADDR_CTGP_DB_CTRL:
>>> + case EC_ADDR_CTGP_DB_CTGP_OFFSET:
>>> + case EC_ADDR_CTGP_DB_TPP_OFFSET:
>>> + case EC_ADDR_CTGP_DB_DB_OFFSET:
>>> return true;
>>> default:
>>> return false;
>>> @@ -803,6 +815,69 @@ static ssize_t breathing_in_suspend_show(struct
>>> device *dev, struct device_attri
>>> static DEVICE_ATTR_RW(breathing_in_suspend);
>>> +static ssize_t ctgp_offset_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 = kstrtouint(buf, 0, &value);
>>> + if (ret < 0)
>>> + return ret;
>
> I forget to mention that you still need to verify that value is
> smaller than U8_MAX.
ack
>
> Thanks,
> Armin Wolf
>
>>> +
>>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET,
>>> value);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + return count;
>>> +}
>>> +
>>> +static ssize_t ctgp_offset_show(struct device *dev, struct
>>> device_attribute *attr,
>>> + char *buf)
>>> +{
>>> + struct uniwill_data *data = dev_get_drvdata(dev);
>>> + unsigned int value;
>>> + int ret;
>>> +
>>> + ret = regmap_read(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET,
>>> &value);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + return sysfs_emit(buf, "%u\n", value);
>>> +}
>>> +
>>> +static DEVICE_ATTR_RW(ctgp_offset);
>>> +
>>> +static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
>>> +{
>>> + int ret;
>>> +
>>> + if (!uniwill_device_supports(data,
>>> UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
>>> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
>>> + return 0;
>>> +
>>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, 0);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_TPP_OFFSET, 255);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_DB_OFFSET, 25);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + ret = regmap_update_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
>>> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE |
>>> CTGP_DB_CTGP_ENABLE,
>>> + CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE |
>>> CTGP_DB_CTGP_ENABLE);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static struct attribute *uniwill_attrs[] = {
>>> /* Keyboard-related */
>>> &dev_attr_fn_lock_toggle_enable.attr,
>>> @@ -811,6 +886,8 @@ static struct attribute *uniwill_attrs[] = {
>>> /* Lightbar-related */
>>> &dev_attr_rainbow_animation.attr,
>>> &dev_attr_breathing_in_suspend.attr,
>>> + /* Power-management-related */
>>> + &dev_attr_ctgp_offset.attr,
>>> NULL
>>> };
>>> @@ -844,6 +921,12 @@ static umode_t uniwill_attr_is_visible(struct
>>> kobject *kobj, struct attribute *a
>>> return attr->mode;
>>> }
>>> + if (attr == &dev_attr_ctgp_offset.attr) {
>>> + if (uniwill_device_supports(data,
>>> UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
>>> + UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
>>> + return attr->mode;
>>> + }
>>> +
>>> return 0;
>>> }
>>> @@ -1413,6 +1496,10 @@ static int uniwill_probe(struct
>>> platform_device *pdev)
>>> if (ret < 0)
>>> return ret;
>>> + ret = uniwill_nvidia_ctgp_init(data);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> return uniwill_input_init(data);
>>> }
>>> @@ -1557,6 +1644,29 @@ static struct uniwill_device_descriptor
>>> lapkc71f_descriptor __initdata = {
>>> UNIWILL_FEATURE_HWMON
>>> };
>>> +static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
>>> +{
>>> + unsigned int value;
>>> + int ret;
>>> +
>>> + ret = regmap_read(data->regmap, EC_ADDR_SYSTEM_ID, &value);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + if (value & HAS_GPU)
>>> + data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
>>> +
>>> + return 0;
>>> +};
>>> +
>>> +static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor
>>> __initdata = {
>>> + .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 empty_descriptor
>>> __initdata = {};
>>> static const struct dmi_system_id uniwill_dmi_table[]
>>> __initconst = {
>>> @@ -1606,7 +1716,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
>>> @@ -1614,7 +1724,7 @@ static const struct dmi_system_id
>>> uniwill_dmi_table[] __initconst = {
>>> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
>>> },
>>> - .driver_data = &empty_descriptor,
>>> + .driver_data = &phxarx1_phxaqf1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore
>>> Omnia-Book Pro Gen 7",
>>> @@ -1622,7 +1732,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8
>>> Intel/Commodore Omnia-Book Pro Gen 8",
>>> @@ -1638,7 +1748,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
>>> @@ -1646,7 +1756,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
>>> @@ -1814,7 +1924,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
>>> @@ -1822,7 +1932,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
>>> @@ -1830,7 +1940,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
>>> @@ -1838,7 +1948,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
>>> @@ -1846,7 +1956,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
>>> @@ -1854,7 +1964,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
>>> @@ -1862,7 +1972,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
>>> @@ -1870,7 +1980,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore
>>> ORION Gen 5",
>>> @@ -1878,7 +1988,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
>>> @@ -1886,7 +1996,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore
>>> ORION Slim 15 Gen6",
>>> @@ -1894,7 +2004,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION
>>> 16 Gen6",
>>> @@ -1902,7 +2012,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION
>>> 16 Gen6",
>>> @@ -1910,7 +2020,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION
>>> 17 Gen6",
>>> @@ -1918,7 +2028,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
>>> @@ -1926,7 +2036,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>>> @@ -1934,7 +2044,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>>> @@ -1942,7 +2052,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 = &empty_descriptor,
>>> + .driver_data = &tux_featureset_1_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Pulse 14 Gen1 AMD",
>>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2025-12-04 21:03 ` Werner Sembach
@ 2025-12-04 21:22 ` Armin Wolf
0 siblings, 0 replies; 19+ messages in thread
From: Armin Wolf @ 2025-12-04 21:22 UTC (permalink / raw)
To: Werner Sembach, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, linux-kernel
Am 04.12.25 um 22:03 schrieb Werner Sembach:
>
> Am 04.12.25 um 17:03 schrieb Armin Wolf:
>> Am 04.12.25 um 14:50 schrieb Werner Sembach:
>>
>>> From: Armin Wolf <W_Armin@gmx.de>
>>>
>>> Future additions to the driver will depend on device-specific
>>> initialization steps. Extend the DMI-based feature detection system
>>> to include device descriptors. Each descriptor contains a bitmap of
>>> supported features and a set of callback for performing
>>> device-specific initialization.
>>>
>>> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
>>> Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
>>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>>> ---
>>> drivers/platform/x86/uniwill/uniwill-acpi.c | 168
>>> +++++++++++++++++---
>>> 1 file changed, 142 insertions(+), 26 deletions(-)
>>>
>>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> index bd7e63dd51810..01192c32608e5 100644
>>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>> @@ -322,6 +322,7 @@ struct uniwill_data {
>>> struct device *dev;
>>> acpi_handle handle;
>>> struct regmap *regmap;
>>> + unsigned int features;
>>> struct acpi_battery_hook hook;
>>> unsigned int last_charge_ctrl;
>>> struct mutex battery_lock; /* Protects the list of
>>> currently registered batteries */
>>> @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
>>> struct power_supply *battery;
>>> };
>>> +struct uniwill_device_descriptor {
>>> + unsigned int features;
>>> + /* Executed during driver probing */
>>> + int (*probe)(struct uniwill_data *data);
>>> +};
>>> +
>>> static bool force;
>>> module_param_unsafe(force, bool, 0);
>>> MODULE_PARM_DESC(force, "Force loading without checking for
>>> supported devices\n");
>>> -/* Feature bitmask since the associated registers are not
>>> reliable */
>>> -static unsigned int supported_features;
>>> +/*
>>> + * Contains device specific data like the feature bitmap since
>>> + * the associated registers are not always reliable.
>>> + */
>>> +static struct uniwill_device_descriptor device_descriptor
>>> __ro_after_init;
>>> static const char * const uniwill_temp_labels[] = {
>>> "CPU",
>>> @@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] = {
>>> { KE_END }
>>> };
>>> +static inline bool uniwill_device_supports(struct uniwill_data
>>> *data,
>>> + unsigned int features_mask,
>>> + unsigned int features)
>>> +{
>>> + return (data->features & features_mask) == features;
>>
>> Hi,
>>
>> i am not sure if having a separate feature parameter is really
>> useful, as there
>> are currently no real users for it. Please replace features with
>> feature_mask and
>> remove the associated parameter.
> There might be mutually exclusive features that can be represented
> with more then 1 bit to save some bit space, e.g. 3 different kind of
> keyboard backlight controls that could be represented by 2 bits: 00 ->
> None, 01 -> Type 1, 10 -> Type 2, 11 -> Type 3 instead of having one
> bit for each type.
Unlikely that we will ever have something like this, such scenarios would likely have a single feature bit
and a separate enum field inside uniwill_data. Additionally, the additional third parameter clutters the source code,
so i would like to get rid of it.
Thanks,
Armin Wolf
>>
>> With that being addressed:
>> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
>>
>>> +}
>>> +
>>> static int uniwill_ec_reg_write(void *context, unsigned int reg,
>>> unsigned int val)
>>> {
>>> union acpi_object params[2] = {
>>> @@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] = {
>>> static umode_t uniwill_attr_is_visible(struct kobject *kobj,
>>> struct attribute *attr, int n)
>>> {
>>> + struct device *dev = kobj_to_dev(kobj);
>>> + struct uniwill_data *data = dev_get_drvdata(dev);
>>> +
>>> if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
>>> - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
>>> + if (uniwill_device_supports(data,
>>> UNIWILL_FEATURE_FN_LOCK_TOGGLE,
>>> + UNIWILL_FEATURE_FN_LOCK_TOGGLE))
>>> return attr->mode;
>>> }
>>> if (attr == &dev_attr_super_key_toggle_enable.attr) {
>>> - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
>>> + if (uniwill_device_supports(data,
>>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>> return attr->mode;
>>> }
>>> if (attr == &dev_attr_touchpad_toggle_enable.attr) {
>>> - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
>>> + if (uniwill_device_supports(data,
>>> UNIWILL_FEATURE_TOUCHPAD_TOGGLE,
>>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
>>> return attr->mode;
>>> }
>>> if (attr == &dev_attr_rainbow_animation.attr ||
>>> attr == &dev_attr_breathing_in_suspend.attr) {
>>> - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
>>> + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
>>> + UNIWILL_FEATURE_LIGHTBAR))
>>> return attr->mode;
>>> }
>>> @@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct
>>> uniwill_data *data)
>>> {
>>> struct device *hdev;
>>> - if (!(supported_features & UNIWILL_FEATURE_HWMON))
>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON,
>>> + UNIWILL_FEATURE_HWMON))
>>> return 0;
>>> hdev = devm_hwmon_device_register_with_info(data->dev,
>>> "uniwill", data,
>>> @@ -1019,7 +1044,8 @@ static int uniwill_led_init(struct
>>> uniwill_data *data)
>>> unsigned int value;
>>> int ret;
>>> - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
>>> + UNIWILL_FEATURE_LIGHTBAR))
>>> return 0;
>>> ret = devm_mutex_init(data->dev, &data->led_lock);
>>> @@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct
>>> uniwill_data *data)
>>> {
>>> int ret;
>>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>>> + UNIWILL_FEATURE_BATTERY))
>>> return 0;
>>> ret = devm_mutex_init(data->dev, &data->battery_lock);
>>> @@ -1361,6 +1388,19 @@ static int uniwill_probe(struct
>>> platform_device *pdev)
>>> if (ret < 0)
>>> return ret;
>>> + data->features = device_descriptor.features;
>>> +
>>> + /*
>>> + * Some devices might need to perform some device-specific
>>> initialization steps
>>> + * before the supported features are initialized. Because of
>>> this we have to call
>>> + * this callback just after the EC itself was initialized.
>>> + */
>>> + if (device_descriptor.probe) {
>>> + ret = device_descriptor.probe(data);
>>> + if (ret < 0)
>>> + return ret;
>>> + }
>>> +
>>> ret = uniwill_battery_init(data);
>>> if (ret < 0)
>>> return ret;
>>> @@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct
>>> platform_device *pdev)
>>> static int uniwill_suspend_keyboard(struct uniwill_data *data)
>>> {
>>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>> + if (!uniwill_device_supports(data,
>>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>> return 0;
>>> /*
>>> @@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct
>>> uniwill_data *data)
>>> static int uniwill_suspend_battery(struct uniwill_data *data)
>>> {
>>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>>> + UNIWILL_FEATURE_BATTERY))
>>> return 0;
>>> /*
>>> @@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct
>>> uniwill_data *data)
>>> unsigned int value;
>>> int ret;
>>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>> + if (!uniwill_device_supports(data,
>>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>> return 0;
>>> ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
>>> @@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct
>>> uniwill_data *data)
>>> static int uniwill_resume_battery(struct uniwill_data *data)
>>> {
>>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>>> + UNIWILL_FEATURE_BATTERY))
>>> return 0;
>>> return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL,
>>> CHARGE_CTRL_MASK,
>>> @@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver = {
>>> .shutdown = uniwill_shutdown,
>>> };
>>> +static struct uniwill_device_descriptor lapac71h_descriptor
>>> __initdata = {
>>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>> + UNIWILL_FEATURE_BATTERY |
>>> + UNIWILL_FEATURE_HWMON
>>> +};
>>> +
>>> +static struct uniwill_device_descriptor lapkc71f_descriptor
>>> __initdata = {
>>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>> + UNIWILL_FEATURE_LIGHTBAR |
>>> + UNIWILL_FEATURE_BATTERY |
>>> + UNIWILL_FEATURE_HWMON
>>> +};
>>> +
>>> +static struct uniwill_device_descriptor empty_descriptor __initdata
>>> = {};
>>> +
>>> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>>> {
>>> .ident = "XMG FUSION 15",
>>> @@ -1503,6 +1566,7 @@ static const struct dmi_system_id
>>> uniwill_dmi_table[] __initconst = {
>>> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
>>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
>>> },
>>> + .driver_data = &empty_descriptor,
>>> },
>>> {
>>> .ident = "XMG FUSION 15",
>>> @@ -1510,6 +1574,7 @@ static const struct dmi_system_id
>>> uniwill_dmi_table[] __initconst = {
>>> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
>>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
>>> },
>>> + .driver_data = &empty_descriptor,
>>> },
>>> {
>>> .ident = "Intel NUC x15",
>>> @@ -1517,11 +1582,7 @@ static const struct dmi_system_id
>>> uniwill_dmi_table[] __initconst = {
>>> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client
>>> Systems"),
>>> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
>>> },
>>> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>>> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>>> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>> - UNIWILL_FEATURE_BATTERY |
>>> - UNIWILL_FEATURE_HWMON),
>>> + .driver_data = &lapac71h_descriptor,
>>> },
>>> {
>>> .ident = "Intel NUC x15",
>>> @@ -1529,12 +1590,7 @@ static const struct dmi_system_id
>>> uniwill_dmi_table[] __initconst = {
>>> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client
>>> Systems"),
>>> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
>>> },
>>> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>>> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>>> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>> - UNIWILL_FEATURE_LIGHTBAR |
>>> - UNIWILL_FEATURE_BATTERY |
>>> - UNIWILL_FEATURE_HWMON),
>>> + .driver_data = &lapkc71f_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
>>> @@ -1542,6 +1598,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
>>> @@ -1549,6 +1606,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
>>> @@ -1556,6 +1614,7 @@ static const struct dmi_system_id
>>> uniwill_dmi_table[] __initconst = {
>>> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
>>> },
>>> + .driver_data = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore
>>> Omnia-Book Pro Gen 7",
>>> @@ -1563,6 +1622,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8
>>> Intel/Commodore Omnia-Book Pro Gen 8",
>>> @@ -1570,6 +1630,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore
>>> Omnia-Book Pro Gen 8",
>>> @@ -1577,6 +1638,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
>>> @@ -1584,6 +1646,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
>>> @@ -1591,6 +1654,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9
>>> Intel/Commodore Omnia-Book 15 Gen9",
>>> @@ -1598,6 +1662,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
>>> @@ -1605,6 +1670,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
>>> @@ -1612,6 +1678,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
>>> @@ -1619,6 +1686,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
>>> @@ -1626,6 +1694,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
>>> @@ -1633,6 +1702,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
>>> @@ -1640,6 +1710,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
>>> @@ -1647,6 +1718,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,
>>> },
>>> {
>>> .ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
>>> @@ -1654,6 +1726,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15 Gen1 AMD",
>>> @@ -1661,6 +1734,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15 Gen1 AMD",
>>> @@ -1668,6 +1742,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 17 Gen1 AMD",
>>> @@ -1675,6 +1750,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 17 Gen1 AMD",
>>> @@ -1682,6 +1758,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15 Gen1 Intel",
>>> @@ -1689,6 +1766,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15 Gen1 Intel",
>>> @@ -1696,6 +1774,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 17 Gen1 Intel",
>>> @@ -1703,6 +1782,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 17 Gen1 Intel",
>>> @@ -1710,6 +1790,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,
>>> },
>>> {
>>> .ident = "TUXEDO Trinity 15 Intel Gen1",
>>> @@ -1717,6 +1798,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,
>>> },
>>> {
>>> .ident = "TUXEDO Trinity 17 Intel Gen1",
>>> @@ -1724,6 +1806,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,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15/17 Gen2 AMD",
>>> @@ -1731,6 +1814,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
>>> @@ -1738,6 +1822,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
>>> @@ -1745,6 +1830,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
>>> @@ -1752,6 +1838,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
>>> @@ -1759,6 +1846,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
>>> @@ -1766,6 +1854,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
>>> @@ -1773,6 +1862,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
>>> @@ -1780,6 +1870,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore
>>> ORION Gen 5",
>>> @@ -1787,6 +1878,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
>>> @@ -1794,6 +1886,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore
>>> ORION Slim 15 Gen6",
>>> @@ -1801,6 +1894,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION
>>> 16 Gen6",
>>> @@ -1808,6 +1902,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION
>>> 16 Gen6",
>>> @@ -1815,6 +1910,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION
>>> 17 Gen6",
>>> @@ -1822,6 +1918,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
>>> @@ -1829,6 +1926,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>>> @@ -1836,6 +1934,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>>> @@ -1843,6 +1942,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 = &empty_descriptor,
>>> },
>>> {
>>> .ident = "TUXEDO Pulse 14 Gen1 AMD",
>>> @@ -1850,6 +1950,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,
>>> },
>>> {
>>> .ident = "TUXEDO Pulse 15 Gen1 AMD",
>>> @@ -1857,6 +1958,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,
>>> },
>>> {
>>> .ident = "TUXEDO Pulse 15 Gen2 AMD",
>>> @@ -1864,6 +1966,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,
>>> },
>>> { }
>>> };
>>> @@ -1871,6 +1974,7 @@ MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
>>> static int __init uniwill_init(void)
>>> {
>>> + const struct uniwill_device_descriptor *descriptor;
>>> const struct dmi_system_id *id;
>>> int ret;
>>> @@ -1880,10 +1984,22 @@ static int __init uniwill_init(void)
>>> return -ENODEV;
>>> /* Assume that the device supports all features */
>>> - supported_features = UINT_MAX;
>>> + device_descriptor.features = UINT_MAX;
>>> pr_warn("Loading on a potentially unsupported device\n");
>>> } else {
>>> - supported_features = (uintptr_t)id->driver_data;
>>> + /*
>>> + * Some devices might support additional features depending on
>>> + * the BIOS version/date, so we call this callback to let them
>>> + * modify their device descriptor accordingly.
>>> + */
>>> + if (id->callback) {
>>> + ret = id->callback(id);
>>> + if (ret < 0)
>>> + return ret;
>>> + }
>>> +
>>> + descriptor = id->driver_data;
>>> + device_descriptor = *descriptor;
>>> }
>>> ret = platform_driver_register(&uniwill_driver);
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2025-12-04 13:50 ` [PATCH 1/2] " Werner Sembach
2025-12-04 16:03 ` Armin Wolf
@ 2025-12-16 13:40 ` Ilpo Järvinen
2025-12-16 15:14 ` Werner Sembach
1 sibling, 1 reply; 19+ messages in thread
From: Ilpo Järvinen @ 2025-12-16 13:40 UTC (permalink / raw)
To: Werner Sembach; +Cc: W_Armin, Hans de Goede, platform-driver-x86, LKML
On Thu, 4 Dec 2025, Werner Sembach wrote:
> From: Armin Wolf <W_Armin@gmx.de>
>
> Future additions to the driver will depend on device-specific
> initialization steps. Extend the DMI-based feature detection system
> to include device descriptors. Each descriptor contains a bitmap of
> supported features and a set of callback for performing
> device-specific initialization.
>
> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
> Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
> drivers/platform/x86/uniwill/uniwill-acpi.c | 168 +++++++++++++++++---
> 1 file changed, 142 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index bd7e63dd51810..01192c32608e5 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -322,6 +322,7 @@ struct uniwill_data {
> struct device *dev;
> acpi_handle handle;
> struct regmap *regmap;
> + unsigned int features;
> struct acpi_battery_hook hook;
> unsigned int last_charge_ctrl;
> struct mutex battery_lock; /* Protects the list of currently registered batteries */
> @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
> struct power_supply *battery;
> };
>
> +struct uniwill_device_descriptor {
> + unsigned int features;
> + /* Executed during driver probing */
> + int (*probe)(struct uniwill_data *data);
> +};
> +
> static bool force;
> module_param_unsafe(force, bool, 0);
> MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
>
> -/* Feature bitmask since the associated registers are not reliable */
> -static unsigned int supported_features;
> +/*
> + * Contains device specific data like the feature bitmap since
> + * the associated registers are not always reliable.
> + */
> +static struct uniwill_device_descriptor device_descriptor __ro_after_init;
>
> static const char * const uniwill_temp_labels[] = {
> "CPU",
> @@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] = {
> { KE_END }
> };
>
> +static inline bool uniwill_device_supports(struct uniwill_data *data,
> + unsigned int features_mask,
> + unsigned int features)
> +{
> + return (data->features & features_mask) == features;
> +}
> +
> static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
> {
> union acpi_object params[2] = {
> @@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] = {
>
> static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
> {
> + struct device *dev = kobj_to_dev(kobj);
> + struct uniwill_data *data = dev_get_drvdata(dev);
> +
> if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK_TOGGLE,
> + UNIWILL_FEATURE_FN_LOCK_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_super_key_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_touchpad_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE,
> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_rainbow_animation.attr ||
> attr == &dev_attr_breathing_in_suspend.attr) {
> - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
> + UNIWILL_FEATURE_LIGHTBAR))
> return attr->mode;
> }
>
> @@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
> {
> struct device *hdev;
>
> - if (!(supported_features & UNIWILL_FEATURE_HWMON))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON,
> + UNIWILL_FEATURE_HWMON))
> return 0;
>
> hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
> @@ -1019,7 +1044,8 @@ static int uniwill_led_init(struct uniwill_data *data)
> unsigned int value;
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
> + UNIWILL_FEATURE_LIGHTBAR))
> return 0;
>
> ret = devm_mutex_init(data->dev, &data->led_lock);
> @@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct uniwill_data *data)
> {
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> + UNIWILL_FEATURE_BATTERY))
> return 0;
>
> ret = devm_mutex_init(data->dev, &data->battery_lock);
> @@ -1361,6 +1388,19 @@ static int uniwill_probe(struct platform_device *pdev)
> if (ret < 0)
> return ret;
>
> + data->features = device_descriptor.features;
> +
> + /*
> + * Some devices might need to perform some device-specific initialization steps
> + * before the supported features are initialized. Because of this we have to call
> + * this callback just after the EC itself was initialized.
> + */
> + if (device_descriptor.probe) {
> + ret = device_descriptor.probe(data);
> + if (ret < 0)
> + return ret;
> + }
> +
> ret = uniwill_battery_init(data);
> if (ret < 0)
> return ret;
> @@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct platform_device *pdev)
>
> static int uniwill_suspend_keyboard(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return 0;
>
> /*
> @@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct uniwill_data *data)
>
> static int uniwill_suspend_battery(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> + UNIWILL_FEATURE_BATTERY))
> return 0;
>
> /*
> @@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
> unsigned int value;
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return 0;
>
> ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
> @@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
>
> static int uniwill_resume_battery(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> + UNIWILL_FEATURE_BATTERY))
> return 0;
>
> return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
> @@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver = {
> .shutdown = uniwill_shutdown,
> };
>
> +static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> + UNIWILL_FEATURE_BATTERY |
> + UNIWILL_FEATURE_HWMON
> +};
> +
> +static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> + UNIWILL_FEATURE_LIGHTBAR |
> + UNIWILL_FEATURE_BATTERY |
> + UNIWILL_FEATURE_HWMON
> +};
> +
> +static struct uniwill_device_descriptor empty_descriptor __initdata = {};
> +
> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> {
> .ident = "XMG FUSION 15",
> @@ -1503,6 +1566,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
> },
> + .driver_data = &empty_descriptor,
Hi,
Is there some advantage of having an "empty descriptor" over just NULL
checking its presence in the code?
> static int __init uniwill_init(void)
> {
> + const struct uniwill_device_descriptor *descriptor;
> const struct dmi_system_id *id;
> int ret;
>
> @@ -1880,10 +1984,22 @@ static int __init uniwill_init(void)
> return -ENODEV;
>
> /* Assume that the device supports all features */
> - supported_features = UINT_MAX;
> + device_descriptor.features = UINT_MAX;
> pr_warn("Loading on a potentially unsupported device\n");
> } else {
> - supported_features = (uintptr_t)id->driver_data;
> + /*
> + * Some devices might support additional features depending on
> + * the BIOS version/date, so we call this callback to let them
> + * modify their device descriptor accordingly.
> + */
> + if (id->callback) {
> + ret = id->callback(id);
> + if (ret < 0)
> + return ret;
> + }
> +
> + descriptor = id->driver_data;
> + device_descriptor = *descriptor;
> }
>
> ret = platform_driver_register(&uniwill_driver);
>
--
i.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2025-12-16 13:40 ` Ilpo Järvinen
@ 2025-12-16 15:14 ` Werner Sembach
2025-12-16 15:20 ` Ilpo Järvinen
0 siblings, 1 reply; 19+ messages in thread
From: Werner Sembach @ 2025-12-16 15:14 UTC (permalink / raw)
To: Ilpo Järvinen; +Cc: W_Armin, Hans de Goede, platform-driver-x86, LKML
Am 16.12.25 um 14:40 schrieb Ilpo Järvinen:
> On Thu, 4 Dec 2025, Werner Sembach wrote:
>
>> From: Armin Wolf <W_Armin@gmx.de>
>>
>> Future additions to the driver will depend on device-specific
>> initialization steps. Extend the DMI-based feature detection system
>> to include device descriptors. Each descriptor contains a bitmap of
>> supported features and a set of callback for performing
>> device-specific initialization.
>>
>> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
>> Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>> ---
>> drivers/platform/x86/uniwill/uniwill-acpi.c | 168 +++++++++++++++++---
>> 1 file changed, 142 insertions(+), 26 deletions(-)
>>
>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> index bd7e63dd51810..01192c32608e5 100644
>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> @@ -322,6 +322,7 @@ struct uniwill_data {
>> struct device *dev;
>> acpi_handle handle;
>> struct regmap *regmap;
>> + unsigned int features;
>> struct acpi_battery_hook hook;
>> unsigned int last_charge_ctrl;
>> struct mutex battery_lock; /* Protects the list of currently registered batteries */
>> @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
>> struct power_supply *battery;
>> };
>>
>> +struct uniwill_device_descriptor {
>> + unsigned int features;
>> + /* Executed during driver probing */
>> + int (*probe)(struct uniwill_data *data);
>> +};
>> +
>> static bool force;
>> module_param_unsafe(force, bool, 0);
>> MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
>>
>> -/* Feature bitmask since the associated registers are not reliable */
>> -static unsigned int supported_features;
>> +/*
>> + * Contains device specific data like the feature bitmap since
>> + * the associated registers are not always reliable.
>> + */
>> +static struct uniwill_device_descriptor device_descriptor __ro_after_init;
>>
>> static const char * const uniwill_temp_labels[] = {
>> "CPU",
>> @@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] = {
>> { KE_END }
>> };
>>
>> +static inline bool uniwill_device_supports(struct uniwill_data *data,
>> + unsigned int features_mask,
>> + unsigned int features)
>> +{
>> + return (data->features & features_mask) == features;
>> +}
>> +
>> static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
>> {
>> union acpi_object params[2] = {
>> @@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] = {
>>
>> static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
>> {
>> + struct device *dev = kobj_to_dev(kobj);
>> + struct uniwill_data *data = dev_get_drvdata(dev);
>> +
>> if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
>> + if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK_TOGGLE,
>> + UNIWILL_FEATURE_FN_LOCK_TOGGLE))
>> return attr->mode;
>> }
>>
>> if (attr == &dev_attr_super_key_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
>> + if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return attr->mode;
>> }
>>
>> if (attr == &dev_attr_touchpad_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
>> + if (uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE,
>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
>> return attr->mode;
>> }
>>
>> if (attr == &dev_attr_rainbow_animation.attr ||
>> attr == &dev_attr_breathing_in_suspend.attr) {
>> - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
>> + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
>> + UNIWILL_FEATURE_LIGHTBAR))
>> return attr->mode;
>> }
>>
>> @@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
>> {
>> struct device *hdev;
>>
>> - if (!(supported_features & UNIWILL_FEATURE_HWMON))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON,
>> + UNIWILL_FEATURE_HWMON))
>> return 0;
>>
>> hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
>> @@ -1019,7 +1044,8 @@ static int uniwill_led_init(struct uniwill_data *data)
>> unsigned int value;
>> int ret;
>>
>> - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
>> + UNIWILL_FEATURE_LIGHTBAR))
>> return 0;
>>
>> ret = devm_mutex_init(data->dev, &data->led_lock);
>> @@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct uniwill_data *data)
>> {
>> int ret;
>>
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>> + UNIWILL_FEATURE_BATTERY))
>> return 0;
>>
>> ret = devm_mutex_init(data->dev, &data->battery_lock);
>> @@ -1361,6 +1388,19 @@ static int uniwill_probe(struct platform_device *pdev)
>> if (ret < 0)
>> return ret;
>>
>> + data->features = device_descriptor.features;
>> +
>> + /*
>> + * Some devices might need to perform some device-specific initialization steps
>> + * before the supported features are initialized. Because of this we have to call
>> + * this callback just after the EC itself was initialized.
>> + */
>> + if (device_descriptor.probe) {
>> + ret = device_descriptor.probe(data);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> ret = uniwill_battery_init(data);
>> if (ret < 0)
>> return ret;
>> @@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct platform_device *pdev)
>>
>> static int uniwill_suspend_keyboard(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return 0;
>>
>> /*
>> @@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct uniwill_data *data)
>>
>> static int uniwill_suspend_battery(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>> + UNIWILL_FEATURE_BATTERY))
>> return 0;
>>
>> /*
>> @@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
>> unsigned int value;
>> int ret;
>>
>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return 0;
>>
>> ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
>> @@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
>>
>> static int uniwill_resume_battery(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>> + UNIWILL_FEATURE_BATTERY))
>> return 0;
>>
>> return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
>> @@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver = {
>> .shutdown = uniwill_shutdown,
>> };
>>
>> +static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> + UNIWILL_FEATURE_BATTERY |
>> + UNIWILL_FEATURE_HWMON
>> +};
>> +
>> +static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> + UNIWILL_FEATURE_LIGHTBAR |
>> + UNIWILL_FEATURE_BATTERY |
>> + UNIWILL_FEATURE_HWMON
>> +};
>> +
>> +static struct uniwill_device_descriptor empty_descriptor __initdata = {};
>> +
>> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>> {
>> .ident = "XMG FUSION 15",
>> @@ -1503,6 +1566,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
>> },
>> + .driver_data = &empty_descriptor,
> Hi,
>
> Is there some advantage of having an "empty descriptor" over just NULL
> checking its presence in the code?
One less "if"
In the long run (with more features implemented and tested) there probably wont
be any device using the empty descriptor, then it can be removed again.
>
>> static int __init uniwill_init(void)
>> {
>> + const struct uniwill_device_descriptor *descriptor;
>> const struct dmi_system_id *id;
>> int ret;
>>
>> @@ -1880,10 +1984,22 @@ static int __init uniwill_init(void)
>> return -ENODEV;
>>
>> /* Assume that the device supports all features */
>> - supported_features = UINT_MAX;
>> + device_descriptor.features = UINT_MAX;
>> pr_warn("Loading on a potentially unsupported device\n");
>> } else {
>> - supported_features = (uintptr_t)id->driver_data;
>> + /*
>> + * Some devices might support additional features depending on
>> + * the BIOS version/date, so we call this callback to let them
>> + * modify their device descriptor accordingly.
>> + */
>> + if (id->callback) {
>> + ret = id->callback(id);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> + descriptor = id->driver_data;
>> + device_descriptor = *descriptor;
>> }
>>
>> ret = platform_driver_register(&uniwill_driver);
>>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2025-12-16 15:14 ` Werner Sembach
@ 2025-12-16 15:20 ` Ilpo Järvinen
2025-12-16 15:28 ` Werner Sembach
0 siblings, 1 reply; 19+ messages in thread
From: Ilpo Järvinen @ 2025-12-16 15:20 UTC (permalink / raw)
To: Werner Sembach; +Cc: W_Armin, Hans de Goede, platform-driver-x86, LKML
[-- Attachment #1: Type: text/plain, Size: 10038 bytes --]
On Tue, 16 Dec 2025, Werner Sembach wrote:
>
> Am 16.12.25 um 14:40 schrieb Ilpo Järvinen:
> > On Thu, 4 Dec 2025, Werner Sembach wrote:
> >
> > > From: Armin Wolf <W_Armin@gmx.de>
> > >
> > > Future additions to the driver will depend on device-specific
> > > initialization steps. Extend the DMI-based feature detection system
> > > to include device descriptors. Each descriptor contains a bitmap of
> > > supported features and a set of callback for performing
> > > device-specific initialization.
> > >
> > > Signed-off-by: Armin Wolf <W_Armin@gmx.de>
> > > Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
> > > Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> > > ---
> > > drivers/platform/x86/uniwill/uniwill-acpi.c | 168 +++++++++++++++++---
> > > 1 file changed, 142 insertions(+), 26 deletions(-)
> > >
> > > diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
> > > b/drivers/platform/x86/uniwill/uniwill-acpi.c
> > > index bd7e63dd51810..01192c32608e5 100644
> > > --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> > > +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> > > @@ -322,6 +322,7 @@ struct uniwill_data {
> > > struct device *dev;
> > > acpi_handle handle;
> > > struct regmap *regmap;
> > > + unsigned int features;
> > > struct acpi_battery_hook hook;
> > > unsigned int last_charge_ctrl;
> > > struct mutex battery_lock; /* Protects the list of currently
> > > registered batteries */
> > > @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
> > > struct power_supply *battery;
> > > };
> > > +struct uniwill_device_descriptor {
> > > + unsigned int features;
> > > + /* Executed during driver probing */
> > > + int (*probe)(struct uniwill_data *data);
> > > +};
> > > +
> > > static bool force;
> > > module_param_unsafe(force, bool, 0);
> > > MODULE_PARM_DESC(force, "Force loading without checking for supported
> > > devices\n");
> > > -/* Feature bitmask since the associated registers are not reliable */
> > > -static unsigned int supported_features;
> > > +/*
> > > + * Contains device specific data like the feature bitmap since
> > > + * the associated registers are not always reliable.
> > > + */
> > > +static struct uniwill_device_descriptor device_descriptor
> > > __ro_after_init;
> > > static const char * const uniwill_temp_labels[] = {
> > > "CPU",
> > > @@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] = {
> > > { KE_END }
> > > };
> > > +static inline bool uniwill_device_supports(struct uniwill_data *data,
> > > + unsigned int features_mask,
> > > + unsigned int features)
> > > +{
> > > + return (data->features & features_mask) == features;
> > > +}
> > > +
> > > static int uniwill_ec_reg_write(void *context, unsigned int reg,
> > > unsigned int val)
> > > {
> > > union acpi_object params[2] = {
> > > @@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] = {
> > > static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct
> > > attribute *attr, int n)
> > > {
> > > + struct device *dev = kobj_to_dev(kobj);
> > > + struct uniwill_data *data = dev_get_drvdata(dev);
> > > +
> > > if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
> > > - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
> > > + if (uniwill_device_supports(data,
> > > UNIWILL_FEATURE_FN_LOCK_TOGGLE,
> > > + UNIWILL_FEATURE_FN_LOCK_TOGGLE))
> > > return attr->mode;
> > > }
> > > if (attr == &dev_attr_super_key_toggle_enable.attr) {
> > > - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
> > > + if (uniwill_device_supports(data,
> > > UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> > > + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> > > return attr->mode;
> > > }
> > > if (attr == &dev_attr_touchpad_toggle_enable.attr) {
> > > - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
> > > + if (uniwill_device_supports(data,
> > > UNIWILL_FEATURE_TOUCHPAD_TOGGLE,
> > > + UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
> > > return attr->mode;
> > > }
> > > if (attr == &dev_attr_rainbow_animation.attr ||
> > > attr == &dev_attr_breathing_in_suspend.attr) {
> > > - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
> > > + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
> > > + UNIWILL_FEATURE_LIGHTBAR))
> > > return attr->mode;
> > > }
> > > @@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct uniwill_data
> > > *data)
> > > {
> > > struct device *hdev;
> > > - if (!(supported_features & UNIWILL_FEATURE_HWMON))
> > > + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON,
> > > + UNIWILL_FEATURE_HWMON))
> > > return 0;
> > > hdev = devm_hwmon_device_register_with_info(data->dev,
> > > "uniwill", data,
> > > @@ -1019,7 +1044,8 @@ static int uniwill_led_init(struct uniwill_data
> > > *data)
> > > unsigned int value;
> > > int ret;
> > > - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
> > > + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
> > > + UNIWILL_FEATURE_LIGHTBAR))
> > > return 0;
> > > ret = devm_mutex_init(data->dev, &data->led_lock);
> > > @@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct uniwill_data
> > > *data)
> > > {
> > > int ret;
> > > - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> > > + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> > > + UNIWILL_FEATURE_BATTERY))
> > > return 0;
> > > ret = devm_mutex_init(data->dev, &data->battery_lock);
> > > @@ -1361,6 +1388,19 @@ static int uniwill_probe(struct platform_device
> > > *pdev)
> > > if (ret < 0)
> > > return ret;
> > > + data->features = device_descriptor.features;
> > > +
> > > + /*
> > > + * Some devices might need to perform some device-specific
> > > initialization steps
> > > + * before the supported features are initialized. Because of this we
> > > have to call
> > > + * this callback just after the EC itself was initialized.
> > > + */
> > > + if (device_descriptor.probe) {
> > > + ret = device_descriptor.probe(data);
> > > + if (ret < 0)
> > > + return ret;
> > > + }
> > > +
> > > ret = uniwill_battery_init(data);
> > > if (ret < 0)
> > > return ret;
> > > @@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct platform_device
> > > *pdev)
> > > static int uniwill_suspend_keyboard(struct uniwill_data *data)
> > > {
> > > - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> > > + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> > > + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> > > return 0;
> > > /*
> > > @@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct
> > > uniwill_data *data)
> > > static int uniwill_suspend_battery(struct uniwill_data *data)
> > > {
> > > - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> > > + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> > > + UNIWILL_FEATURE_BATTERY))
> > > return 0;
> > > /*
> > > @@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct
> > > uniwill_data *data)
> > > unsigned int value;
> > > int ret;
> > > - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> > > + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
> > > + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> > > return 0;
> > > ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS,
> > > &value);
> > > @@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct
> > > uniwill_data *data)
> > > static int uniwill_resume_battery(struct uniwill_data *data)
> > > {
> > > - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> > > + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
> > > + UNIWILL_FEATURE_BATTERY))
> > > return 0;
> > > return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL,
> > > CHARGE_CTRL_MASK,
> > > @@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver = {
> > > .shutdown = uniwill_shutdown,
> > > };
> > > +static struct uniwill_device_descriptor lapac71h_descriptor __initdata
> > > = {
> > > + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> > > + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> > > + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> > > + UNIWILL_FEATURE_BATTERY |
> > > + UNIWILL_FEATURE_HWMON
> > > +};
> > > +
> > > +static struct uniwill_device_descriptor lapkc71f_descriptor __initdata =
> > > {
> > > + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> > > + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> > > + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> > > + UNIWILL_FEATURE_LIGHTBAR |
> > > + UNIWILL_FEATURE_BATTERY |
> > > + UNIWILL_FEATURE_HWMON
> > > +};
> > > +
> > > +static struct uniwill_device_descriptor empty_descriptor __initdata = {};
> > > +
> > > static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> > > {
> > > .ident = "XMG FUSION 15",
> > > @@ -1503,6 +1566,7 @@ static const struct dmi_system_id
> > > uniwill_dmi_table[] __initconst = {
> > > DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
> > > DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
> > > },
> > > + .driver_data = &empty_descriptor,
> > Hi,
> >
> > Is there some advantage of having an "empty descriptor" over just NULL
> > checking its presence in the code?
>
> One less "if"
That pays no respect to devs who have read those dummy driver_data
lines. ;-)
> In the long run (with more features implemented and tested) there probably
> wont be any device using the empty descriptor, then it can be removed again.
Fair (so I'm fine with keeping empty_descriptor for now).
--
i.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2025-12-16 15:20 ` Ilpo Järvinen
@ 2025-12-16 15:28 ` Werner Sembach
0 siblings, 0 replies; 19+ messages in thread
From: Werner Sembach @ 2025-12-16 15:28 UTC (permalink / raw)
To: Ilpo Järvinen; +Cc: W_Armin, Hans de Goede, platform-driver-x86, LKML
Am 16.12.25 um 16:20 schrieb Ilpo Järvinen:
> On Tue, 16 Dec 2025, Werner Sembach wrote:
>
>> Am 16.12.25 um 14:40 schrieb Ilpo Järvinen:
>>> On Thu, 4 Dec 2025, Werner Sembach wrote:
>>>
>>>> From: Armin Wolf <W_Armin@gmx.de>
>>>>
>>>> Future additions to the driver will depend on device-specific
>>>> initialization steps. Extend the DMI-based feature detection system
>>>> to include device descriptors. Each descriptor contains a bitmap of
>>>> supported features and a set of callback for performing
>>>> device-specific initialization.
>>>>
>>>> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
>>>> Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
>>>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>>>> ---
>>>> drivers/platform/x86/uniwill/uniwill-acpi.c | 168 +++++++++++++++++---
>>>> 1 file changed, 142 insertions(+), 26 deletions(-)
>>>>
>>>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>>> index bd7e63dd51810..01192c32608e5 100644
>>>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>>> @@ -322,6 +322,7 @@ struct uniwill_data {
>>>> struct device *dev;
>>>> acpi_handle handle;
>>>> struct regmap *regmap;
>>>> + unsigned int features;
>>>> struct acpi_battery_hook hook;
>>>> unsigned int last_charge_ctrl;
>>>> struct mutex battery_lock; /* Protects the list of currently
>>>> registered batteries */
>>>> @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
>>>> struct power_supply *battery;
>>>> };
>>>> +struct uniwill_device_descriptor {
>>>> + unsigned int features;
>>>> + /* Executed during driver probing */
>>>> + int (*probe)(struct uniwill_data *data);
>>>> +};
>>>> +
>>>> static bool force;
>>>> module_param_unsafe(force, bool, 0);
>>>> MODULE_PARM_DESC(force, "Force loading without checking for supported
>>>> devices\n");
>>>> -/* Feature bitmask since the associated registers are not reliable */
>>>> -static unsigned int supported_features;
>>>> +/*
>>>> + * Contains device specific data like the feature bitmap since
>>>> + * the associated registers are not always reliable.
>>>> + */
>>>> +static struct uniwill_device_descriptor device_descriptor
>>>> __ro_after_init;
>>>> static const char * const uniwill_temp_labels[] = {
>>>> "CPU",
>>>> @@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] = {
>>>> { KE_END }
>>>> };
>>>> +static inline bool uniwill_device_supports(struct uniwill_data *data,
>>>> + unsigned int features_mask,
>>>> + unsigned int features)
>>>> +{
>>>> + return (data->features & features_mask) == features;
>>>> +}
>>>> +
>>>> static int uniwill_ec_reg_write(void *context, unsigned int reg,
>>>> unsigned int val)
>>>> {
>>>> union acpi_object params[2] = {
>>>> @@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] = {
>>>> static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct
>>>> attribute *attr, int n)
>>>> {
>>>> + struct device *dev = kobj_to_dev(kobj);
>>>> + struct uniwill_data *data = dev_get_drvdata(dev);
>>>> +
>>>> if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
>>>> - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
>>>> + if (uniwill_device_supports(data,
>>>> UNIWILL_FEATURE_FN_LOCK_TOGGLE,
>>>> + UNIWILL_FEATURE_FN_LOCK_TOGGLE))
>>>> return attr->mode;
>>>> }
>>>> if (attr == &dev_attr_super_key_toggle_enable.attr) {
>>>> - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
>>>> + if (uniwill_device_supports(data,
>>>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>>> return attr->mode;
>>>> }
>>>> if (attr == &dev_attr_touchpad_toggle_enable.attr) {
>>>> - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
>>>> + if (uniwill_device_supports(data,
>>>> UNIWILL_FEATURE_TOUCHPAD_TOGGLE,
>>>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
>>>> return attr->mode;
>>>> }
>>>> if (attr == &dev_attr_rainbow_animation.attr ||
>>>> attr == &dev_attr_breathing_in_suspend.attr) {
>>>> - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
>>>> + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
>>>> + UNIWILL_FEATURE_LIGHTBAR))
>>>> return attr->mode;
>>>> }
>>>> @@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct uniwill_data
>>>> *data)
>>>> {
>>>> struct device *hdev;
>>>> - if (!(supported_features & UNIWILL_FEATURE_HWMON))
>>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON,
>>>> + UNIWILL_FEATURE_HWMON))
>>>> return 0;
>>>> hdev = devm_hwmon_device_register_with_info(data->dev,
>>>> "uniwill", data,
>>>> @@ -1019,7 +1044,8 @@ static int uniwill_led_init(struct uniwill_data
>>>> *data)
>>>> unsigned int value;
>>>> int ret;
>>>> - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
>>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR,
>>>> + UNIWILL_FEATURE_LIGHTBAR))
>>>> return 0;
>>>> ret = devm_mutex_init(data->dev, &data->led_lock);
>>>> @@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct uniwill_data
>>>> *data)
>>>> {
>>>> int ret;
>>>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>>>> + UNIWILL_FEATURE_BATTERY))
>>>> return 0;
>>>> ret = devm_mutex_init(data->dev, &data->battery_lock);
>>>> @@ -1361,6 +1388,19 @@ static int uniwill_probe(struct platform_device
>>>> *pdev)
>>>> if (ret < 0)
>>>> return ret;
>>>> + data->features = device_descriptor.features;
>>>> +
>>>> + /*
>>>> + * Some devices might need to perform some device-specific
>>>> initialization steps
>>>> + * before the supported features are initialized. Because of this we
>>>> have to call
>>>> + * this callback just after the EC itself was initialized.
>>>> + */
>>>> + if (device_descriptor.probe) {
>>>> + ret = device_descriptor.probe(data);
>>>> + if (ret < 0)
>>>> + return ret;
>>>> + }
>>>> +
>>>> ret = uniwill_battery_init(data);
>>>> if (ret < 0)
>>>> return ret;
>>>> @@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct platform_device
>>>> *pdev)
>>>> static int uniwill_suspend_keyboard(struct uniwill_data *data)
>>>> {
>>>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>>> return 0;
>>>> /*
>>>> @@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct
>>>> uniwill_data *data)
>>>> static int uniwill_suspend_battery(struct uniwill_data *data)
>>>> {
>>>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>>>> + UNIWILL_FEATURE_BATTERY))
>>>> return 0;
>>>> /*
>>>> @@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct
>>>> uniwill_data *data)
>>>> unsigned int value;
>>>> int ret;
>>>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE,
>>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>>>> return 0;
>>>> ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS,
>>>> &value);
>>>> @@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct
>>>> uniwill_data *data)
>>>> static int uniwill_resume_battery(struct uniwill_data *data)
>>>> {
>>>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>>>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY,
>>>> + UNIWILL_FEATURE_BATTERY))
>>>> return 0;
>>>> return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL,
>>>> CHARGE_CTRL_MASK,
>>>> @@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver = {
>>>> .shutdown = uniwill_shutdown,
>>>> };
>>>> +static struct uniwill_device_descriptor lapac71h_descriptor __initdata
>>>> = {
>>>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>>>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>>> + UNIWILL_FEATURE_BATTERY |
>>>> + UNIWILL_FEATURE_HWMON
>>>> +};
>>>> +
>>>> +static struct uniwill_device_descriptor lapkc71f_descriptor __initdata =
>>>> {
>>>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>>>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>>>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>>> + UNIWILL_FEATURE_LIGHTBAR |
>>>> + UNIWILL_FEATURE_BATTERY |
>>>> + UNIWILL_FEATURE_HWMON
>>>> +};
>>>> +
>>>> +static struct uniwill_device_descriptor empty_descriptor __initdata = {};
>>>> +
>>>> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>>>> {
>>>> .ident = "XMG FUSION 15",
>>>> @@ -1503,6 +1566,7 @@ static const struct dmi_system_id
>>>> uniwill_dmi_table[] __initconst = {
>>>> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
>>>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
>>>> },
>>>> + .driver_data = &empty_descriptor,
>>> Hi,
>>>
>>> Is there some advantage of having an "empty descriptor" over just NULL
>>> checking its presence in the code?
>> One less "if"
> That pays no respect to devs who have read those dummy driver_data
> lines. ;-)
Thanks for doing it anyway ^^
v2 of this patch set is already finished, but i'm still waiting for the special
case ibp gen7 being tested before sending it.
>
>> In the long run (with more features implemented and tested) there probably
>> wont be any device using the empty descriptor, then it can be removed again.
> Fair (so I'm fine with keeping empty_descriptor for now).
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
@ 2026-01-15 15:42 Werner Sembach
2026-01-15 20:41 ` Armin Wolf
2026-01-26 14:30 ` Ilpo Järvinen
0 siblings, 2 replies; 19+ messages in thread
From: Werner Sembach @ 2026-01-15 15:42 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>
Future additions to the driver will depend on device-specific
initialization steps. Extend the DMI-based feature detection system
to include device descriptors. Each descriptor contains a bitmap of
supported features and a set of callback for performing
device-specific initialization.
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
---
drivers/platform/x86/uniwill/uniwill-acpi.c | 157 ++++++++++++++++----
1 file changed, 131 insertions(+), 26 deletions(-)
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 0f935532f2504..3d8c136e36219 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -322,6 +322,7 @@ struct uniwill_data {
struct device *dev;
acpi_handle handle;
struct regmap *regmap;
+ unsigned int features;
struct acpi_battery_hook hook;
unsigned int last_charge_ctrl;
struct mutex battery_lock; /* Protects the list of currently registered batteries */
@@ -341,12 +342,21 @@ struct uniwill_battery_entry {
struct power_supply *battery;
};
+struct uniwill_device_descriptor {
+ unsigned int features;
+ /* Executed during driver probing */
+ int (*probe)(struct uniwill_data *data);
+};
+
static bool force;
module_param_unsafe(force, bool, 0);
MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
-/* Feature bitmask since the associated registers are not reliable */
-static unsigned int supported_features;
+/*
+ * Contains device specific data like the feature bitmap since
+ * the associated registers are not always reliable.
+ */
+static struct uniwill_device_descriptor device_descriptor __ro_after_init;
static const char * const uniwill_temp_labels[] = {
"CPU",
@@ -411,6 +421,12 @@ static const struct key_entry uniwill_keymap[] = {
{ KE_END }
};
+static inline bool uniwill_device_supports(struct uniwill_data *data,
+ unsigned int features)
+{
+ return (data->features & features) == features;
+}
+
static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
{
union acpi_object params[2] = {
@@ -799,24 +815,27 @@ static struct attribute *uniwill_attrs[] = {
static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
{
+ struct device *dev = kobj_to_dev(kobj);
+ struct uniwill_data *data = dev_get_drvdata(dev);
+
if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
- if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK_TOGGLE))
return attr->mode;
}
if (attr == &dev_attr_super_key_toggle_enable.attr) {
- if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
return attr->mode;
}
if (attr == &dev_attr_touchpad_toggle_enable.attr) {
- if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
return attr->mode;
}
if (attr == &dev_attr_rainbow_animation.attr ||
attr == &dev_attr_breathing_in_suspend.attr) {
- if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
return attr->mode;
}
@@ -944,7 +963,7 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
{
struct device *hdev;
- if (!(supported_features & UNIWILL_FEATURE_HWMON))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON))
return 0;
hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
@@ -1019,7 +1038,7 @@ static int uniwill_led_init(struct uniwill_data *data)
unsigned int value;
int ret;
- if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
return 0;
ret = devm_mutex_init(data->dev, &data->led_lock);
@@ -1232,7 +1251,7 @@ static int uniwill_battery_init(struct uniwill_data *data)
{
int ret;
- if (!(supported_features & UNIWILL_FEATURE_BATTERY))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
return 0;
ret = devm_mutex_init(data->dev, &data->battery_lock);
@@ -1361,6 +1380,19 @@ static int uniwill_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
+ data->features = device_descriptor.features;
+
+ /*
+ * Some devices might need to perform some device-specific initialization steps
+ * before the supported features are initialized. Because of this we have to call
+ * this callback just after the EC itself was initialized.
+ */
+ if (device_descriptor.probe) {
+ ret = device_descriptor.probe(data);
+ if (ret < 0)
+ return ret;
+ }
+
ret = uniwill_battery_init(data);
if (ret < 0)
return ret;
@@ -1385,7 +1417,7 @@ static void uniwill_shutdown(struct platform_device *pdev)
static int uniwill_suspend_keyboard(struct uniwill_data *data)
{
- if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
return 0;
/*
@@ -1397,7 +1429,7 @@ static int uniwill_suspend_keyboard(struct uniwill_data *data)
static int uniwill_suspend_battery(struct uniwill_data *data)
{
- if (!(supported_features & UNIWILL_FEATURE_BATTERY))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
return 0;
/*
@@ -1432,7 +1464,7 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
unsigned int value;
int ret;
- if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
return 0;
ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
@@ -1448,7 +1480,7 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
static int uniwill_resume_battery(struct uniwill_data *data)
{
- if (!(supported_features & UNIWILL_FEATURE_BATTERY))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
return 0;
return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
@@ -1496,6 +1528,25 @@ static struct platform_driver uniwill_driver = {
.shutdown = uniwill_shutdown,
};
+static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
+ UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
+ UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
+ UNIWILL_FEATURE_BATTERY |
+ UNIWILL_FEATURE_HWMON
+};
+
+static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
+ UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
+ UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
+ UNIWILL_FEATURE_LIGHTBAR |
+ UNIWILL_FEATURE_BATTERY |
+ UNIWILL_FEATURE_HWMON
+};
+
+static struct uniwill_device_descriptor empty_descriptor __initdata = {};
+
static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
{
.ident = "XMG FUSION 15",
@@ -1503,6 +1554,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
},
+ .driver_data = &empty_descriptor,
},
{
.ident = "XMG FUSION 15",
@@ -1510,6 +1562,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
},
+ .driver_data = &empty_descriptor,
},
{
.ident = "Intel NUC x15",
@@ -1517,11 +1570,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
},
- .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
- UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
- UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
- UNIWILL_FEATURE_BATTERY |
- UNIWILL_FEATURE_HWMON),
+ .driver_data = &lapac71h_descriptor,
},
{
.ident = "Intel NUC x15",
@@ -1529,12 +1578,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
},
- .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
- UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
- UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
- UNIWILL_FEATURE_LIGHTBAR |
- UNIWILL_FEATURE_BATTERY |
- UNIWILL_FEATURE_HWMON),
+ .driver_data = &lapkc71f_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
@@ -1542,6 +1586,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
@@ -1549,6 +1594,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 = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
@@ -1556,6 +1602,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
},
+ .driver_data = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
@@ -1563,6 +1610,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 = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1570,6 +1618,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1577,6 +1626,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 = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
@@ -1584,6 +1634,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 = &empty_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
@@ -1591,6 +1642,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
@@ -1598,6 +1650,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
@@ -1605,6 +1658,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,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
@@ -1612,6 +1666,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,
},
{
.ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
@@ -1619,6 +1674,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,
},
{
.ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
@@ -1626,6 +1682,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,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
@@ -1633,6 +1690,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,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
@@ -1640,6 +1698,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,
},
{
.ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
@@ -1647,6 +1706,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,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
@@ -1654,6 +1714,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,
},
{
.ident = "TUXEDO Polaris 15 Gen1 AMD",
@@ -1661,6 +1722,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,
},
{
.ident = "TUXEDO Polaris 15 Gen1 AMD",
@@ -1668,6 +1730,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,
},
{
.ident = "TUXEDO Polaris 17 Gen1 AMD",
@@ -1675,6 +1738,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,
},
{
.ident = "TUXEDO Polaris 17 Gen1 AMD",
@@ -1682,6 +1746,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,
},
{
.ident = "TUXEDO Polaris 15 Gen1 Intel",
@@ -1689,6 +1754,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,
},
{
.ident = "TUXEDO Polaris 15 Gen1 Intel",
@@ -1696,6 +1762,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,
},
{
.ident = "TUXEDO Polaris 17 Gen1 Intel",
@@ -1703,6 +1770,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,
},
{
.ident = "TUXEDO Polaris 17 Gen1 Intel",
@@ -1710,6 +1778,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,
},
{
.ident = "TUXEDO Trinity 15 Intel Gen1",
@@ -1717,6 +1786,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,
},
{
.ident = "TUXEDO Trinity 17 Intel Gen1",
@@ -1724,6 +1794,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,
},
{
.ident = "TUXEDO Polaris 15/17 Gen2 AMD",
@@ -1731,6 +1802,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen2 Intel",
@@ -1738,6 +1810,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
@@ -1745,6 +1818,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
@@ -1752,6 +1826,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
@@ -1759,6 +1834,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 15 Gen4 Intel",
@@ -1766,6 +1842,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen5 AMD",
@@ -1773,6 +1850,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen5 AMD",
@@ -1780,6 +1858,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
@@ -1787,6 +1866,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
@@ -1794,6 +1874,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
@@ -1801,6 +1882,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -1808,6 +1890,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -1815,6 +1898,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
@@ -1822,6 +1906,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 AMD",
@@ -1829,6 +1914,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -1836,6 +1922,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -1843,6 +1930,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 = &empty_descriptor,
},
{
.ident = "TUXEDO Book BA15 Gen10 AMD",
@@ -1850,6 +1938,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,
},
{
.ident = "TUXEDO Pulse 14 Gen1 AMD",
@@ -1857,6 +1946,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,
},
{
.ident = "TUXEDO Pulse 15 Gen1 AMD",
@@ -1864,6 +1954,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,
},
{
.ident = "TUXEDO Pulse 15 Gen2 AMD",
@@ -1871,6 +1962,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,
},
{ }
};
@@ -1878,6 +1970,7 @@ MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
static int __init uniwill_init(void)
{
+ const struct uniwill_device_descriptor *descriptor;
const struct dmi_system_id *id;
int ret;
@@ -1887,10 +1980,22 @@ static int __init uniwill_init(void)
return -ENODEV;
/* Assume that the device supports all features */
- supported_features = UINT_MAX;
+ device_descriptor.features = UINT_MAX;
pr_warn("Loading on a potentially unsupported device\n");
} else {
- supported_features = (uintptr_t)id->driver_data;
+ /*
+ * Some devices might support additional features depending on
+ * the BIOS version/date, so we call this callback to let them
+ * modify their device descriptor accordingly.
+ */
+ if (id->callback) {
+ ret = id->callback(id);
+ if (ret < 0)
+ return ret;
+ }
+
+ descriptor = id->driver_data;
+ device_descriptor = *descriptor;
}
ret = platform_driver_register(&uniwill_driver);
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2026-01-15 15:42 [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system Werner Sembach
@ 2026-01-15 20:41 ` Armin Wolf
2026-01-26 10:53 ` Armin Wolf
2026-01-26 14:30 ` Ilpo Järvinen
1 sibling, 1 reply; 19+ messages in thread
From: Armin Wolf @ 2026-01-15 20:41 UTC (permalink / raw)
To: Werner Sembach, Hans de Goede, Ilpo Järvinen
Cc: platform-driver-x86, linux-kernel
Am 15.01.26 um 16:42 schrieb Werner Sembach:
> From: Armin Wolf <W_Armin@gmx.de>
>
> Future additions to the driver will depend on device-specific
> initialization steps. Extend the DMI-based feature detection system
> to include device descriptors. Each descriptor contains a bitmap of
> supported features and a set of callback for performing
> device-specific initialization.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
> Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
> drivers/platform/x86/uniwill/uniwill-acpi.c | 157 ++++++++++++++++----
> 1 file changed, 131 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
> index 0f935532f2504..3d8c136e36219 100644
> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
> @@ -322,6 +322,7 @@ struct uniwill_data {
> struct device *dev;
> acpi_handle handle;
> struct regmap *regmap;
> + unsigned int features;
> struct acpi_battery_hook hook;
> unsigned int last_charge_ctrl;
> struct mutex battery_lock; /* Protects the list of currently registered batteries */
> @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
> struct power_supply *battery;
> };
>
> +struct uniwill_device_descriptor {
> + unsigned int features;
> + /* Executed during driver probing */
> + int (*probe)(struct uniwill_data *data);
> +};
> +
> static bool force;
> module_param_unsafe(force, bool, 0);
> MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
>
> -/* Feature bitmask since the associated registers are not reliable */
> -static unsigned int supported_features;
> +/*
> + * Contains device specific data like the feature bitmap since
> + * the associated registers are not always reliable.
> + */
> +static struct uniwill_device_descriptor device_descriptor __ro_after_init;
>
> static const char * const uniwill_temp_labels[] = {
> "CPU",
> @@ -411,6 +421,12 @@ static const struct key_entry uniwill_keymap[] = {
> { KE_END }
> };
>
> +static inline bool uniwill_device_supports(struct uniwill_data *data,
> + unsigned int features)
> +{
> + return (data->features & features) == features;
> +}
> +
> static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
> {
> union acpi_object params[2] = {
> @@ -799,24 +815,27 @@ static struct attribute *uniwill_attrs[] = {
>
> static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
> {
> + struct device *dev = kobj_to_dev(kobj);
> + struct uniwill_data *data = dev_get_drvdata(dev);
> +
> if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_super_key_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_touchpad_toggle_enable.attr) {
> - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
> return attr->mode;
> }
>
> if (attr == &dev_attr_rainbow_animation.attr ||
> attr == &dev_attr_breathing_in_suspend.attr) {
> - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
> + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
> return attr->mode;
> }
>
> @@ -944,7 +963,7 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
> {
> struct device *hdev;
>
> - if (!(supported_features & UNIWILL_FEATURE_HWMON))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON))
> return 0;
>
> hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
> @@ -1019,7 +1038,7 @@ static int uniwill_led_init(struct uniwill_data *data)
> unsigned int value;
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
> return 0;
>
> ret = devm_mutex_init(data->dev, &data->led_lock);
> @@ -1232,7 +1251,7 @@ static int uniwill_battery_init(struct uniwill_data *data)
> {
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
> return 0;
>
> ret = devm_mutex_init(data->dev, &data->battery_lock);
> @@ -1361,6 +1380,19 @@ static int uniwill_probe(struct platform_device *pdev)
> if (ret < 0)
> return ret;
>
> + data->features = device_descriptor.features;
> +
> + /*
> + * Some devices might need to perform some device-specific initialization steps
> + * before the supported features are initialized. Because of this we have to call
> + * this callback just after the EC itself was initialized.
> + */
> + if (device_descriptor.probe) {
> + ret = device_descriptor.probe(data);
> + if (ret < 0)
> + return ret;
> + }
> +
> ret = uniwill_battery_init(data);
> if (ret < 0)
> return ret;
> @@ -1385,7 +1417,7 @@ static void uniwill_shutdown(struct platform_device *pdev)
>
> static int uniwill_suspend_keyboard(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return 0;
>
> /*
> @@ -1397,7 +1429,7 @@ static int uniwill_suspend_keyboard(struct uniwill_data *data)
>
> static int uniwill_suspend_battery(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
> return 0;
>
> /*
> @@ -1432,7 +1464,7 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
> unsigned int value;
> int ret;
>
> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
> return 0;
>
> ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
> @@ -1448,7 +1480,7 @@ static int uniwill_resume_keyboard(struct uniwill_data *data)
>
> static int uniwill_resume_battery(struct uniwill_data *data)
> {
> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
> return 0;
>
> return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
> @@ -1496,6 +1528,25 @@ static struct platform_driver uniwill_driver = {
> .shutdown = uniwill_shutdown,
> };
>
> +static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> + UNIWILL_FEATURE_BATTERY |
> + UNIWILL_FEATURE_HWMON
> +};
> +
> +static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> + UNIWILL_FEATURE_LIGHTBAR |
> + UNIWILL_FEATURE_BATTERY |
> + UNIWILL_FEATURE_HWMON
> +};
> +
> +static struct uniwill_device_descriptor empty_descriptor __initdata = {};
> +
> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> {
> .ident = "XMG FUSION 15",
> @@ -1503,6 +1554,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
> },
> + .driver_data = &empty_descriptor,
> },
> {
> .ident = "XMG FUSION 15",
> @@ -1510,6 +1562,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
> },
> + .driver_data = &empty_descriptor,
> },
> {
> .ident = "Intel NUC x15",
> @@ -1517,11 +1570,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
> },
> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> - UNIWILL_FEATURE_BATTERY |
> - UNIWILL_FEATURE_HWMON),
> + .driver_data = &lapac71h_descriptor,
> },
> {
> .ident = "Intel NUC x15",
> @@ -1529,12 +1578,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
> },
> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
> - UNIWILL_FEATURE_LIGHTBAR |
> - UNIWILL_FEATURE_BATTERY |
> - UNIWILL_FEATURE_HWMON),
> + .driver_data = &lapkc71f_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
> @@ -1542,6 +1586,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
> @@ -1549,6 +1594,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
> @@ -1556,6 +1602,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
> },
> + .driver_data = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
> @@ -1563,6 +1610,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
> @@ -1570,6 +1618,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
> @@ -1577,6 +1626,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
> @@ -1584,6 +1634,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
> @@ -1591,6 +1642,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
> @@ -1598,6 +1650,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
> @@ -1605,6 +1658,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
> @@ -1612,6 +1666,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,
> },
> {
> .ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
> @@ -1619,6 +1674,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
> @@ -1626,6 +1682,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
> @@ -1633,6 +1690,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
> @@ -1640,6 +1698,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
> @@ -1647,6 +1706,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,
> },
> {
> .ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
> @@ -1654,6 +1714,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,
> },
> {
> .ident = "TUXEDO Polaris 15 Gen1 AMD",
> @@ -1661,6 +1722,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,
> },
> {
> .ident = "TUXEDO Polaris 15 Gen1 AMD",
> @@ -1668,6 +1730,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,
> },
> {
> .ident = "TUXEDO Polaris 17 Gen1 AMD",
> @@ -1675,6 +1738,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,
> },
> {
> .ident = "TUXEDO Polaris 17 Gen1 AMD",
> @@ -1682,6 +1746,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,
> },
> {
> .ident = "TUXEDO Polaris 15 Gen1 Intel",
> @@ -1689,6 +1754,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,
> },
> {
> .ident = "TUXEDO Polaris 15 Gen1 Intel",
> @@ -1696,6 +1762,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,
> },
> {
> .ident = "TUXEDO Polaris 17 Gen1 Intel",
> @@ -1703,6 +1770,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,
> },
> {
> .ident = "TUXEDO Polaris 17 Gen1 Intel",
> @@ -1710,6 +1778,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,
> },
> {
> .ident = "TUXEDO Trinity 15 Intel Gen1",
> @@ -1717,6 +1786,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,
> },
> {
> .ident = "TUXEDO Trinity 17 Intel Gen1",
> @@ -1724,6 +1794,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,
> },
> {
> .ident = "TUXEDO Polaris 15/17 Gen2 AMD",
> @@ -1731,6 +1802,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
> @@ -1738,6 +1810,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
> @@ -1745,6 +1818,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
> @@ -1752,6 +1826,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
> @@ -1759,6 +1834,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
> @@ -1766,6 +1842,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
> @@ -1773,6 +1850,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
> @@ -1780,6 +1858,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
> @@ -1787,6 +1866,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
> @@ -1794,6 +1874,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
> @@ -1801,6 +1882,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
> @@ -1808,6 +1890,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
> @@ -1815,6 +1898,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
> @@ -1822,6 +1906,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
> @@ -1829,6 +1914,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
> @@ -1836,6 +1922,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
> @@ -1843,6 +1930,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 = &empty_descriptor,
> },
> {
> .ident = "TUXEDO Book BA15 Gen10 AMD",
> @@ -1850,6 +1938,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,
> },
> {
> .ident = "TUXEDO Pulse 14 Gen1 AMD",
> @@ -1857,6 +1946,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,
> },
> {
> .ident = "TUXEDO Pulse 15 Gen1 AMD",
> @@ -1864,6 +1954,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,
> },
> {
> .ident = "TUXEDO Pulse 15 Gen2 AMD",
> @@ -1871,6 +1962,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,
> },
> { }
> };
> @@ -1878,6 +1970,7 @@ MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
>
> static int __init uniwill_init(void)
> {
> + const struct uniwill_device_descriptor *descriptor;
> const struct dmi_system_id *id;
> int ret;
>
> @@ -1887,10 +1980,22 @@ static int __init uniwill_init(void)
> return -ENODEV;
>
> /* Assume that the device supports all features */
> - supported_features = UINT_MAX;
> + device_descriptor.features = UINT_MAX;
> pr_warn("Loading on a potentially unsupported device\n");
> } else {
> - supported_features = (uintptr_t)id->driver_data;
> + /*
> + * Some devices might support additional features depending on
> + * the BIOS version/date, so we call this callback to let them
> + * modify their device descriptor accordingly.
> + */
> + if (id->callback) {
> + ret = id->callback(id);
> + if (ret < 0)
> + return ret;
> + }
> +
> + descriptor = id->driver_data;
> + device_descriptor = *descriptor;
> }
>
> ret = platform_driver_register(&uniwill_driver);
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2026-01-15 20:41 ` Armin Wolf
@ 2026-01-26 10:53 ` Armin Wolf
0 siblings, 0 replies; 19+ messages in thread
From: Armin Wolf @ 2026-01-26 10:53 UTC (permalink / raw)
To: Werner Sembach, Hans de Goede, Ilpo Järvinen
Cc: platform-driver-x86, linux-kernel
Am 15.01.26 um 21:41 schrieb Armin Wolf:
> Am 15.01.26 um 16:42 schrieb Werner Sembach:
>
>> From: Armin Wolf <W_Armin@gmx.de>
>>
>> Future additions to the driver will depend on device-specific
>> initialization steps. Extend the DMI-based feature detection system
>> to include device descriptors. Each descriptor contains a bitmap of
>> supported features and a set of callback for performing
>> device-specific initialization.
>
> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
>
What is the status of this series?
Thanks,
Armin Wolf
>> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
>> Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>> ---
>> drivers/platform/x86/uniwill/uniwill-acpi.c | 157 ++++++++++++++++----
>> 1 file changed, 131 insertions(+), 26 deletions(-)
>>
>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> index 0f935532f2504..3d8c136e36219 100644
>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>> @@ -322,6 +322,7 @@ struct uniwill_data {
>> struct device *dev;
>> acpi_handle handle;
>> struct regmap *regmap;
>> + unsigned int features;
>> struct acpi_battery_hook hook;
>> unsigned int last_charge_ctrl;
>> struct mutex battery_lock; /* Protects the list of currently
>> registered batteries */
>> @@ -341,12 +342,21 @@ struct uniwill_battery_entry {
>> struct power_supply *battery;
>> };
>> +struct uniwill_device_descriptor {
>> + unsigned int features;
>> + /* Executed during driver probing */
>> + int (*probe)(struct uniwill_data *data);
>> +};
>> +
>> static bool force;
>> module_param_unsafe(force, bool, 0);
>> MODULE_PARM_DESC(force, "Force loading without checking for
>> supported devices\n");
>> -/* Feature bitmask since the associated registers are not reliable */
>> -static unsigned int supported_features;
>> +/*
>> + * Contains device specific data like the feature bitmap since
>> + * the associated registers are not always reliable.
>> + */
>> +static struct uniwill_device_descriptor device_descriptor
>> __ro_after_init;
>> static const char * const uniwill_temp_labels[] = {
>> "CPU",
>> @@ -411,6 +421,12 @@ static const struct key_entry uniwill_keymap[] = {
>> { KE_END }
>> };
>> +static inline bool uniwill_device_supports(struct uniwill_data *data,
>> + unsigned int features)
>> +{
>> + return (data->features & features) == features;
>> +}
>> +
>> static int uniwill_ec_reg_write(void *context, unsigned int reg,
>> unsigned int val)
>> {
>> union acpi_object params[2] = {
>> @@ -799,24 +815,27 @@ static struct attribute *uniwill_attrs[] = {
>> static umode_t uniwill_attr_is_visible(struct kobject *kobj,
>> struct attribute *attr, int n)
>> {
>> + struct device *dev = kobj_to_dev(kobj);
>> + struct uniwill_data *data = dev_get_drvdata(dev);
>> +
>> if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
>> + if (uniwill_device_supports(data,
>> UNIWILL_FEATURE_FN_LOCK_TOGGLE))
>> return attr->mode;
>> }
>> if (attr == &dev_attr_super_key_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
>> + if (uniwill_device_supports(data,
>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return attr->mode;
>> }
>> if (attr == &dev_attr_touchpad_toggle_enable.attr) {
>> - if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
>> + if (uniwill_device_supports(data,
>> UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
>> return attr->mode;
>> }
>> if (attr == &dev_attr_rainbow_animation.attr ||
>> attr == &dev_attr_breathing_in_suspend.attr) {
>> - if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
>> + if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
>> return attr->mode;
>> }
>> @@ -944,7 +963,7 @@ static int uniwill_hwmon_init(struct
>> uniwill_data *data)
>> {
>> struct device *hdev;
>> - if (!(supported_features & UNIWILL_FEATURE_HWMON))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON))
>> return 0;
>> hdev = devm_hwmon_device_register_with_info(data->dev,
>> "uniwill", data,
>> @@ -1019,7 +1038,7 @@ static int uniwill_led_init(struct uniwill_data
>> *data)
>> unsigned int value;
>> int ret;
>> - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
>> return 0;
>> ret = devm_mutex_init(data->dev, &data->led_lock);
>> @@ -1232,7 +1251,7 @@ static int uniwill_battery_init(struct
>> uniwill_data *data)
>> {
>> int ret;
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
>> return 0;
>> ret = devm_mutex_init(data->dev, &data->battery_lock);
>> @@ -1361,6 +1380,19 @@ static int uniwill_probe(struct
>> platform_device *pdev)
>> if (ret < 0)
>> return ret;
>> + data->features = device_descriptor.features;
>> +
>> + /*
>> + * Some devices might need to perform some device-specific
>> initialization steps
>> + * before the supported features are initialized. Because of
>> this we have to call
>> + * this callback just after the EC itself was initialized.
>> + */
>> + if (device_descriptor.probe) {
>> + ret = device_descriptor.probe(data);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> ret = uniwill_battery_init(data);
>> if (ret < 0)
>> return ret;
>> @@ -1385,7 +1417,7 @@ static void uniwill_shutdown(struct
>> platform_device *pdev)
>> static int uniwill_suspend_keyboard(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> + if (!uniwill_device_supports(data,
>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return 0;
>> /*
>> @@ -1397,7 +1429,7 @@ static int uniwill_suspend_keyboard(struct
>> uniwill_data *data)
>> static int uniwill_suspend_battery(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
>> return 0;
>> /*
>> @@ -1432,7 +1464,7 @@ static int uniwill_resume_keyboard(struct
>> uniwill_data *data)
>> unsigned int value;
>> int ret;
>> - if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> + if (!uniwill_device_supports(data,
>> UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
>> return 0;
>> ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
>> @@ -1448,7 +1480,7 @@ static int uniwill_resume_keyboard(struct
>> uniwill_data *data)
>> static int uniwill_resume_battery(struct uniwill_data *data)
>> {
>> - if (!(supported_features & UNIWILL_FEATURE_BATTERY))
>> + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
>> return 0;
>> return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL,
>> CHARGE_CTRL_MASK,
>> @@ -1496,6 +1528,25 @@ static struct platform_driver uniwill_driver = {
>> .shutdown = uniwill_shutdown,
>> };
>> +static struct uniwill_device_descriptor lapac71h_descriptor
>> __initdata = {
>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> + UNIWILL_FEATURE_BATTERY |
>> + UNIWILL_FEATURE_HWMON
>> +};
>> +
>> +static struct uniwill_device_descriptor lapkc71f_descriptor
>> __initdata = {
>> + .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> + UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> + UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> + UNIWILL_FEATURE_LIGHTBAR |
>> + UNIWILL_FEATURE_BATTERY |
>> + UNIWILL_FEATURE_HWMON
>> +};
>> +
>> +static struct uniwill_device_descriptor empty_descriptor __initdata
>> = {};
>> +
>> static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
>> {
>> .ident = "XMG FUSION 15",
>> @@ -1503,6 +1554,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
>> },
>> + .driver_data = &empty_descriptor,
>> },
>> {
>> .ident = "XMG FUSION 15",
>> @@ -1510,6 +1562,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
>> },
>> + .driver_data = &empty_descriptor,
>> },
>> {
>> .ident = "Intel NUC x15",
>> @@ -1517,11 +1570,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client
>> Systems"),
>> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
>> },
>> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> - UNIWILL_FEATURE_BATTERY |
>> - UNIWILL_FEATURE_HWMON),
>> + .driver_data = &lapac71h_descriptor,
>> },
>> {
>> .ident = "Intel NUC x15",
>> @@ -1529,12 +1578,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client
>> Systems"),
>> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
>> },
>> - .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
>> - UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
>> - UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>> - UNIWILL_FEATURE_LIGHTBAR |
>> - UNIWILL_FEATURE_BATTERY |
>> - UNIWILL_FEATURE_HWMON),
>> + .driver_data = &lapkc71f_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
>> @@ -1542,6 +1586,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
>> @@ -1549,6 +1594,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
>> @@ -1556,6 +1602,7 @@ static const struct dmi_system_id
>> uniwill_dmi_table[] __initconst = {
>> DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
>> DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
>> },
>> + .driver_data = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore
>> Omnia-Book Pro Gen 7",
>> @@ -1563,6 +1610,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/16 Gen8
>> Intel/Commodore Omnia-Book Pro Gen 8",
>> @@ -1570,6 +1618,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore
>> Omnia-Book Pro Gen 8",
>> @@ -1577,6 +1626,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
>> @@ -1584,6 +1634,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
>> @@ -1591,6 +1642,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen9
>> Intel/Commodore Omnia-Book 15 Gen9",
>> @@ -1598,6 +1650,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
>> @@ -1605,6 +1658,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
>> @@ -1612,6 +1666,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
>> @@ -1619,6 +1674,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
>> @@ -1626,6 +1682,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
>> @@ -1633,6 +1690,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
>> @@ -1640,6 +1698,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
>> @@ -1647,6 +1706,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,
>> },
>> {
>> .ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
>> @@ -1654,6 +1714,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15 Gen1 AMD",
>> @@ -1661,6 +1722,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15 Gen1 AMD",
>> @@ -1668,6 +1730,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 17 Gen1 AMD",
>> @@ -1675,6 +1738,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 17 Gen1 AMD",
>> @@ -1682,6 +1746,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15 Gen1 Intel",
>> @@ -1689,6 +1754,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15 Gen1 Intel",
>> @@ -1696,6 +1762,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 17 Gen1 Intel",
>> @@ -1703,6 +1770,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 17 Gen1 Intel",
>> @@ -1710,6 +1778,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,
>> },
>> {
>> .ident = "TUXEDO Trinity 15 Intel Gen1",
>> @@ -1717,6 +1786,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,
>> },
>> {
>> .ident = "TUXEDO Trinity 17 Intel Gen1",
>> @@ -1724,6 +1794,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,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen2 AMD",
>> @@ -1731,6 +1802,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
>> @@ -1738,6 +1810,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
>> @@ -1745,6 +1818,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
>> @@ -1752,6 +1826,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
>> @@ -1759,6 +1834,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 15 Gen4 Intel",
>> @@ -1766,6 +1842,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
>> @@ -1773,6 +1850,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen5 AMD",
>> @@ -1780,6 +1858,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION
>> Gen 5",
>> @@ -1787,6 +1866,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
>> @@ -1794,6 +1874,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore
>> ORION Slim 15 Gen6",
>> @@ -1801,6 +1882,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16
>> Gen6",
>> @@ -1808,6 +1890,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16
>> Gen6",
>> @@ -1815,6 +1898,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17
>> Gen6",
>> @@ -1822,6 +1906,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 AMD",
>> @@ -1829,6 +1914,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>> @@ -1836,6 +1922,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Stellaris 16 Gen7 Intel",
>> @@ -1843,6 +1930,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 = &empty_descriptor,
>> },
>> {
>> .ident = "TUXEDO Book BA15 Gen10 AMD",
>> @@ -1850,6 +1938,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,
>> },
>> {
>> .ident = "TUXEDO Pulse 14 Gen1 AMD",
>> @@ -1857,6 +1946,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,
>> },
>> {
>> .ident = "TUXEDO Pulse 15 Gen1 AMD",
>> @@ -1864,6 +1954,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,
>> },
>> {
>> .ident = "TUXEDO Pulse 15 Gen2 AMD",
>> @@ -1871,6 +1962,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,
>> },
>> { }
>> };
>> @@ -1878,6 +1970,7 @@ MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
>> static int __init uniwill_init(void)
>> {
>> + const struct uniwill_device_descriptor *descriptor;
>> const struct dmi_system_id *id;
>> int ret;
>> @@ -1887,10 +1980,22 @@ static int __init uniwill_init(void)
>> return -ENODEV;
>> /* Assume that the device supports all features */
>> - supported_features = UINT_MAX;
>> + device_descriptor.features = UINT_MAX;
>> pr_warn("Loading on a potentially unsupported device\n");
>> } else {
>> - supported_features = (uintptr_t)id->driver_data;
>> + /*
>> + * Some devices might support additional features depending on
>> + * the BIOS version/date, so we call this callback to let them
>> + * modify their device descriptor accordingly.
>> + */
>> + if (id->callback) {
>> + ret = id->callback(id);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> + descriptor = id->driver_data;
>> + device_descriptor = *descriptor;
>> }
>> ret = platform_driver_register(&uniwill_driver);
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
2026-01-15 15:42 [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system Werner Sembach
2026-01-15 20:41 ` Armin Wolf
@ 2026-01-26 14:30 ` Ilpo Järvinen
1 sibling, 0 replies; 19+ messages in thread
From: Ilpo Järvinen @ 2026-01-26 14:30 UTC (permalink / raw)
To: Armin Wolf, Hans de Goede, Werner Sembach
Cc: platform-driver-x86, linux-kernel
On Thu, 15 Jan 2026 16:42:01 +0100, Werner Sembach wrote:
> Future additions to the driver will depend on device-specific
> initialization steps. Extend the DMI-based feature detection system
> to include device descriptors. Each descriptor contains a bitmap of
> supported features and a set of callback for performing
> device-specific initialization.
>
>
> [...]
Thank you for your contribution, it has been applied to my local
review-ilpo-next branch. Note it will show up in the public
platform-drivers-x86/review-ilpo-next branch only once I've pushed my
local branch there, which might take a while.
The list of commits applied:
[1/2] platform/x86: uniwill-laptop: Introduce device descriptor system
commit: d8c560f76dcac7ff4c630d5d84958183adbf19d2
[2/2] platform/x86/uniwill: Implement cTGP setting
commit: 7c9aa38a59f611c619d026c2d082d0e8c9b9069f
--
i.
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-01-26 14:30 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-04 13:50 [PATCH 0/2] platform/x86: uniwill-laptop: Introduce device descriptor system Werner Sembach
2025-12-04 13:50 ` [PATCH 1/2] " Werner Sembach
2025-12-04 16:03 ` Armin Wolf
2025-12-04 21:03 ` Werner Sembach
2025-12-04 21:22 ` Armin Wolf
2025-12-16 13:40 ` Ilpo Järvinen
2025-12-16 15:14 ` Werner Sembach
2025-12-16 15:20 ` Ilpo Järvinen
2025-12-16 15:28 ` Werner Sembach
2025-12-04 13:50 ` [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting Werner Sembach
2025-12-04 16:11 ` Armin Wolf
2025-12-04 16:58 ` Armin Wolf
2025-12-04 19:38 ` Armin Wolf
2025-12-04 21:06 ` Werner Sembach
2025-12-04 21:05 ` Werner Sembach
-- strict thread matches above, loose matches on Subject: below --
2026-01-15 15:42 [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system Werner Sembach
2026-01-15 20:41 ` Armin Wolf
2026-01-26 10:53 ` Armin Wolf
2026-01-26 14:30 ` Ilpo Järvinen
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.