From nobody Tue Dec 16 13:23:24 2025 Received: from mail.tuxedocomputers.com (mail.tuxedocomputers.com [157.90.84.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2169F23D7C4; Thu, 4 Dec 2025 13:51:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=157.90.84.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764856295; cv=none; b=dYwOIPC8Dmn+MK8o0eSyx34eWvnc7z79PTE5/X+fs0Wn/OjWUYFBq2gwHGSxsX9YVHlhqTEJMevhbOPBU6UZ+Gx4fabJwaaFJOwxnsc3A0v9xJ3/Yq6z+pWYpTqkRWzuW+QdLinZWKqFhaea6/Tp2P779MLeyGyFWDhknmZIUaY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764856295; c=relaxed/simple; bh=uaBlp18RghFHum3+2l5MqMj28EBp7N8P5n5Jj6zIAZ4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mEbSYEVLcoRoSrnkUDGAoO2FpKl2VrntZGaHPrwYKzIZZNzA/q6/vXIdQ5qmE77Pjx8f91JJfhxFoykPFc0FrzGllu2lHTMOzK0s61VpVoUE/2lrWpm6xfiO0bVf0SOxwbY5polkScVsLgH4gwB/UKHZZfGZ7xSsb50myk9Vy3M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=tuxedocomputers.com; spf=pass smtp.mailfrom=tuxedocomputers.com; dkim=pass (1024-bit key) header.d=tuxedocomputers.com header.i=@tuxedocomputers.com header.b=XO6OZW8d; arc=none smtp.client-ip=157.90.84.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=tuxedocomputers.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tuxedocomputers.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=tuxedocomputers.com header.i=@tuxedocomputers.com header.b="XO6OZW8d" Received: from wse-pc.fritz.box (pd9e597c7.dip0.t-ipconnect.de [217.229.151.199]) (Authenticated sender: wse@tuxedocomputers.com) by mail.tuxedocomputers.com (Postfix) with ESMTPA id 847452FC0095; Thu, 4 Dec 2025 14:51:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tuxedocomputers.com; s=default; t=1764856285; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lhsS7yX+gkI2gb3SOcFrx5jsA9mtPA0a7sOVkQ3AgAw=; b=XO6OZW8d6fX05Ho7RdLTwz1upNVp4cPwWjNbu0a8q1S9OGSD2WZW9VjuUOdhO1e8j91SKH 7sIg0rMfqn115TJIcVuVtT7Typ1vsXJcx/mM3wMna6t3ERGG01CXN1Mq3UF9P4Mb0Mv/hG Bze1lFjRq1WXwmdh1twkJondRqVRNYM= Authentication-Results: mail.tuxedocomputers.com; auth=pass smtp.auth=wse@tuxedocomputers.com smtp.mailfrom=wse@tuxedocomputers.com From: Werner Sembach To: W_Armin@gmx.de, hansg@kernel.org, ilpo.jarvinen@linux.intel.com Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, Werner Sembach Subject: [PATCH 1/2] platform/x86: uniwill-laptop: Introduce device descriptor system Date: Thu, 4 Dec 2025 14:50:03 +0100 Message-ID: <20251204135121.435905-2-wse@tuxedocomputers.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251204135121.435905-1-wse@tuxedocomputers.com> References: <20251204135121.435905-1-wse@tuxedocomputers.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Armin Wolf 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 Co-developed-by: Werner Sembach Signed-off-by: Werner Sembach Reviewed-by: Armin Wolf --- 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 b= atteries */ @@ -341,12 +342,21 @@ struct uniwill_battery_entry { struct power_supply *battery; }; =20 +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 devi= ces\n"); =20 -/* 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; =20 static const char * const uniwill_temp_labels[] =3D { "CPU", @@ -411,6 +421,13 @@ static const struct key_entry uniwill_keymap[] =3D { { KE_END } }; =20 +static inline bool uniwill_device_supports(struct uniwill_data *data, + unsigned int features_mask, + unsigned int features) +{ + return (data->features & features_mask) =3D=3D features; +} + static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned = int val) { union acpi_object params[2] =3D { @@ -799,24 +816,31 @@ static struct attribute *uniwill_attrs[] =3D { =20 static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attrib= ute *attr, int n) { + struct device *dev =3D kobj_to_dev(kobj); + struct uniwill_data *data =3D dev_get_drvdata(dev); + if (attr =3D=3D &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; } =20 if (attr =3D=3D &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; } =20 if (attr =3D=3D &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; } =20 if (attr =3D=3D &dev_attr_rainbow_animation.attr || attr =3D=3D &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; } =20 @@ -944,7 +968,8 @@ static int uniwill_hwmon_init(struct uniwill_data *data) { struct device *hdev; =20 - if (!(supported_features & UNIWILL_FEATURE_HWMON)) + if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON, + UNIWILL_FEATURE_HWMON)) return 0; =20 hdev =3D 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; =20 - if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR)) + if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR, + UNIWILL_FEATURE_LIGHTBAR)) return 0; =20 ret =3D devm_mutex_init(data->dev, &data->led_lock); @@ -1232,7 +1258,8 @@ static int uniwill_battery_init(struct uniwill_data *= data) { int ret; =20 - if (!(supported_features & UNIWILL_FEATURE_BATTERY)) + if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY, + UNIWILL_FEATURE_BATTERY)) return 0; =20 ret =3D devm_mutex_init(data->dev, &data->battery_lock); @@ -1361,6 +1388,19 @@ static int uniwill_probe(struct platform_device *pde= v) if (ret < 0) return ret; =20 + data->features =3D 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 =3D device_descriptor.probe(data); + if (ret < 0) + return ret; + } + ret =3D uniwill_battery_init(data); if (ret < 0) return ret; @@ -1385,7 +1425,8 @@ static void uniwill_shutdown(struct platform_device *= pdev) =20 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; =20 /* @@ -1397,7 +1438,8 @@ static int uniwill_suspend_keyboard(struct uniwill_da= ta *data) =20 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; =20 /* @@ -1432,7 +1474,8 @@ static int uniwill_resume_keyboard(struct uniwill_dat= a *data) unsigned int value; int ret; =20 - 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; =20 ret =3D regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value); @@ -1448,7 +1491,8 @@ static int uniwill_resume_keyboard(struct uniwill_dat= a *data) =20 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; =20 return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_= MASK, @@ -1496,6 +1540,25 @@ static struct platform_driver uniwill_driver =3D { .shutdown =3D uniwill_shutdown, }; =20 +static struct uniwill_device_descriptor lapac71h_descriptor __initdata =3D= { + .features =3D 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 =3D= { + .features =3D 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 =3D {}; + static const struct dmi_system_id uniwill_dmi_table[] __initconst =3D { { .ident =3D "XMG FUSION 15", @@ -1503,6 +1566,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "XMG FUSION 15", @@ -1510,6 +1574,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "Intel NUC x15", @@ -1517,11 +1582,7 @@ static const struct dmi_system_id uniwill_dmi_table[= ] __initconst =3D { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"), }, - .driver_data =3D (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE | - UNIWILL_FEATURE_SUPER_KEY_TOGGLE | - UNIWILL_FEATURE_TOUCHPAD_TOGGLE | - UNIWILL_FEATURE_BATTERY | - UNIWILL_FEATURE_HWMON), + .driver_data =3D &lapac71h_descriptor, }, { .ident =3D "Intel NUC x15", @@ -1529,12 +1590,7 @@ static const struct dmi_system_id uniwill_dmi_table[= ] __initconst =3D { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"), }, - .driver_data =3D (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 =3D &lapkc71f_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14 Gen6 Intel", @@ -1542,6 +1598,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTxX1"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14 Gen6 Intel", @@ -1549,6 +1606,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/16 Gen7 Intel", @@ -1556,6 +1614,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book P= ro Gen 7", @@ -1563,6 +1622,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Boo= k Pro Gen 8", @@ -1570,6 +1630,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book P= ro Gen 8", @@ -1577,6 +1638,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 16 Gen8 Intel", @@ -1584,6 +1646,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/15 Gen9 AMD", @@ -1591,6 +1654,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxHRXx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Boo= k 15 Gen9", @@ -1598,6 +1662,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxMRXx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/15 Gen10 AMD", @@ -1605,6 +1670,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxHP4NAx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/15 Gen10 AMD", @@ -1612,6 +1678,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 15 Gen10 Intel", @@ -1619,6 +1686,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxAR4NAx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Max 15 Gen10 AMD", @@ -1626,6 +1694,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Max 16 Gen10 AMD", @@ -1633,6 +1702,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6HP45xU"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Max 16 Gen10 AMD", @@ -1640,6 +1710,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6KK45xU_X6SP45xU"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Max 15 Gen10 Intel", @@ -1647,6 +1718,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5AR45xS"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO InfinityBook Max 16 Gen10 Intel", @@ -1654,6 +1726,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR55xU"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 15 Gen1 AMD", @@ -1661,6 +1734,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 15 Gen1 AMD", @@ -1668,6 +1742,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 17 Gen1 AMD", @@ -1675,6 +1750,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 17 Gen1 AMD", @@ -1682,6 +1758,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 15 Gen1 Intel", @@ -1689,6 +1766,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I1650TI"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 15 Gen1 Intel", @@ -1696,6 +1774,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I2060"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 17 Gen1 Intel", @@ -1703,6 +1782,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I1650TI"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 17 Gen1 Intel", @@ -1710,6 +1790,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I2060"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Trinity 15 Intel Gen1", @@ -1717,6 +1798,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1501I"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Trinity 17 Intel Gen1", @@ -1724,6 +1806,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1701I"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 15/17 Gen2 AMD", @@ -1731,6 +1814,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 15/17 Gen2 Intel", @@ -1738,6 +1822,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD", @@ -1745,6 +1830,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel", @@ -1752,6 +1838,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD", @@ -1759,6 +1846,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 15 Gen4 Intel", @@ -1766,6 +1854,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Polaris 15/17 Gen5 AMD", @@ -1773,6 +1862,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen5 AMD", @@ -1780,6 +1870,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5", @@ -1787,6 +1878,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris Slim 15 Gen6 AMD", @@ -1794,6 +1886,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "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 =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6", @@ -1808,6 +1902,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6", @@ -1815,6 +1910,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6", @@ -1822,6 +1918,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen7 AMD", @@ -1829,6 +1926,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen7 Intel", @@ -1836,6 +1934,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen7 Intel", @@ -1843,6 +1942,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Pulse 14 Gen1 AMD", @@ -1850,6 +1950,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1401"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Pulse 15 Gen1 AMD", @@ -1857,6 +1958,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1501"), }, + .driver_data =3D &empty_descriptor, }, { .ident =3D "TUXEDO Pulse 15 Gen2 AMD", @@ -1864,6 +1966,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5LUXG"), }, + .driver_data =3D &empty_descriptor, }, { } }; @@ -1871,6 +1974,7 @@ MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table); =20 static int __init uniwill_init(void) { + const struct uniwill_device_descriptor *descriptor; const struct dmi_system_id *id; int ret; =20 @@ -1880,10 +1984,22 @@ static int __init uniwill_init(void) return -ENODEV; =20 /* Assume that the device supports all features */ - supported_features =3D UINT_MAX; + device_descriptor.features =3D UINT_MAX; pr_warn("Loading on a potentially unsupported device\n"); } else { - supported_features =3D (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 =3D id->callback(id); + if (ret < 0) + return ret; + } + + descriptor =3D id->driver_data; + device_descriptor =3D *descriptor; } =20 ret =3D platform_driver_register(&uniwill_driver); --=20 2.43.0 From nobody Tue Dec 16 13:23:24 2025 Received: from mail.tuxedocomputers.com (mail.tuxedocomputers.com [157.90.84.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2F0D823183B; Thu, 4 Dec 2025 13:51:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=157.90.84.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764856296; cv=none; b=bLnYAylsYv2mNAhYHDIJnKC7wrKOehkJtL9p9u4ZRSz+ToommlvGcXjwRTC7z8lZIetkhfIwxg27InNAvOSnUL/rcyC5OjY7PAgIWz1z6rJiua3rctwri+O+2ML61IPJywtuid9qZ4pLtrmB1FK0xmgUXSvNWdkRrCkDO/kXvLI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764856296; c=relaxed/simple; bh=TPQdn1JhWT0b1oOwy+jrVD0yrGrCPFhFfkEy/GzEi+o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k2Jxx9ydOI37e5J5XXCTXDeDu5yGZG4FAieoc1Ho2f8XMnW1rSmZzFT3bDuoeNErmhAAiQKydgNqnkB3hl9WE4fMwn4csgopM2qfdwjbyuUzEyrlXQX1FYFBSz4V4BKx178RKyzpqFK2cZeAeiKfXGONTfgZK0ZuyT+BZ4r6MI4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=tuxedocomputers.com; spf=pass smtp.mailfrom=tuxedocomputers.com; dkim=pass (1024-bit key) header.d=tuxedocomputers.com header.i=@tuxedocomputers.com header.b=F0cIXAub; arc=none smtp.client-ip=157.90.84.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=tuxedocomputers.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tuxedocomputers.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=tuxedocomputers.com header.i=@tuxedocomputers.com header.b="F0cIXAub" Received: from wse-pc.fritz.box (pd9e597c7.dip0.t-ipconnect.de [217.229.151.199]) (Authenticated sender: wse@tuxedocomputers.com) by mail.tuxedocomputers.com (Postfix) with ESMTPA id 3A6152FC0094; Thu, 4 Dec 2025 14:51:26 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tuxedocomputers.com; s=default; t=1764856286; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hq6k8gATY4zLlojMf3WynQ4C5Iuygyovd2v0U+Wzcvc=; b=F0cIXAub6eq/yKntgtGIni0cVpjo4KuStCGcL8u9Z/lrX0PoHlC/n0shCX3s6AhS7G7KZc bpkJFmF/KN5Z3NzF/1aBik/OdxQjPYHtU8QirZ3nDOziOIhdr+XCoAnMZIri5lRAbugFBk D34D4gaV8pm99hNAT6H1CVVj0gfrXpM= Authentication-Results: mail.tuxedocomputers.com; auth=pass smtp.auth=wse@tuxedocomputers.com smtp.mailfrom=wse@tuxedocomputers.com From: Werner Sembach To: W_Armin@gmx.de, hansg@kernel.org, ilpo.jarvinen@linux.intel.com Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, Werner Sembach Subject: [PATCH 2/2] platform/x86/uniwill: Implement cTGP setting Date: Thu, 4 Dec 2025 14:50:04 +0100 Message-ID: <20251204135121.435905-3-wse@tuxedocomputers.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251204135121.435905-1-wse@tuxedocomputers.com> References: <20251204135121.435905-1-wse@tuxedocomputers.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Armin Wolf --- 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 @@ =20 #define EC_ADDR_GPU_TEMP 0x044F =20 +#define EC_ADDR_SYSTEM_ID 0x0456 +#define HAS_GPU BIT(7) + #define EC_ADDR_MAIN_FAN_RPM_1 0x0464 =20 #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) =20 -#define EC_ADDR_CTGP_OFFSET 0x0744 +#define EC_ADDR_CTGP_DB_CTGP_OFFSET 0x0744 =20 -#define EC_ADDR_TPP_OFFSET 0x0745 +#define EC_ADDR_CTGP_DB_TPP_OFFSET 0x0745 =20 -#define EC_ADDR_MAX_TGP 0x0746 +#define EC_ADDR_CTGP_DB_DB_OFFSET 0x0746 =20 #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) =20 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, u= nsigned 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 =20 static DEVICE_ATTR_RW(breathing_in_suspend); =20 +static ssize_t ctgp_offset_store(struct device *dev, struct device_attribu= te *attr, + const char *buf, size_t count) +{ + struct uniwill_data *data =3D dev_get_drvdata(dev); + unsigned int value; + int ret; + + ret =3D kstrtouint(buf, 0, &value); + if (ret < 0) + return ret; + + ret =3D 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_attribut= e *attr, + char *buf) +{ + struct uniwill_data *data =3D dev_get_drvdata(dev); + unsigned int value; + int ret; + + ret =3D 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 =3D regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, 0); + if (ret < 0) + return ret; + + ret =3D regmap_write(data->regmap, EC_ADDR_CTGP_DB_TPP_OFFSET, 255); + if (ret < 0) + return ret; + + ret =3D regmap_write(data->regmap, EC_ADDR_CTGP_DB_DB_OFFSET, 25); + if (ret < 0) + return ret; + + ret =3D 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[] =3D { /* Keyboard-related */ &dev_attr_fn_lock_toggle_enable.attr, @@ -811,6 +886,8 @@ static struct attribute *uniwill_attrs[] =3D { /* Lightbar-related */ &dev_attr_rainbow_animation.attr, &dev_attr_breathing_in_suspend.attr, + /* Power-management-related */ + &dev_attr_ctgp_offset.attr, NULL }; =20 @@ -844,6 +921,12 @@ static umode_t uniwill_attr_is_visible(struct kobject = *kobj, struct attribute *a return attr->mode; } =20 + if (attr =3D=3D &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; } =20 @@ -1413,6 +1496,10 @@ static int uniwill_probe(struct platform_device *pde= v) if (ret < 0) return ret; =20 + ret =3D uniwill_nvidia_ctgp_init(data); + if (ret < 0) + return ret; + return uniwill_input_init(data); } =20 @@ -1557,6 +1644,29 @@ static struct uniwill_device_descriptor lapkc71f_des= criptor __initdata =3D { UNIWILL_FEATURE_HWMON }; =20 +static int phxarx1_phxaqf1_probe(struct uniwill_data *data) +{ + unsigned int value; + int ret; + + ret =3D regmap_read(data->regmap, EC_ADDR_SYSTEM_ID, &value); + if (ret < 0) + return ret; + + if (value & HAS_GPU) + data->features |=3D UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL; + + return 0; +}; + +static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor __initd= ata =3D { + .probe =3D phxarx1_phxaqf1_probe +}; + +static struct uniwill_device_descriptor tux_featureset_1_descriptor __init= data =3D { + .features =3D UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL +}; + static struct uniwill_device_descriptor empty_descriptor __initdata =3D {}; =20 static const struct dmi_system_id uniwill_dmi_table[] __initconst =3D { @@ -1606,7 +1716,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/16 Gen7 Intel", @@ -1614,7 +1724,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &phxarx1_phxaqf1_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book P= ro Gen 7", @@ -1622,7 +1732,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Boo= k Pro Gen 8", @@ -1638,7 +1748,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 16 Gen8 Intel", @@ -1646,7 +1756,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO InfinityBook Pro 14/15 Gen9 AMD", @@ -1814,7 +1924,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Polaris 15/17 Gen2 Intel", @@ -1822,7 +1932,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD", @@ -1830,7 +1940,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel", @@ -1838,7 +1948,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD", @@ -1846,7 +1956,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 15 Gen4 Intel", @@ -1854,7 +1964,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Polaris 15/17 Gen5 AMD", @@ -1862,7 +1972,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen5 AMD", @@ -1870,7 +1980,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5", @@ -1878,7 +1988,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris Slim 15 Gen6 AMD", @@ -1886,7 +1996,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "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 =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6", @@ -1902,7 +2012,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6", @@ -1910,7 +2020,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6", @@ -1918,7 +2028,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen7 AMD", @@ -1926,7 +2036,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen7 Intel", @@ -1934,7 +2044,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Stellaris 16 Gen7 Intel", @@ -1942,7 +2052,7 @@ static const struct dmi_system_id uniwill_dmi_table[]= __initconst =3D { DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"), }, - .driver_data =3D &empty_descriptor, + .driver_data =3D &tux_featureset_1_descriptor, }, { .ident =3D "TUXEDO Pulse 14 Gen1 AMD", --=20 2.43.0