From patchwork Tue Aug 6 02:07:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 13754308 Received: from fhigh7-smtp.messagingengine.com (fhigh7-smtp.messagingengine.com [103.168.172.158]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 84D0BBA34; Tue, 6 Aug 2024 02:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.158 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910082; cv=none; b=A3+NNTE4ho209qp4to6iAgXZ9BmHRiED0tQrw9Q406IkFl8mEpufRayiSRl92kgVr5O+hAhSm1KGczFQnPR9nCm/UQuE4StZ+idb16hgb/JRf8IhWK7lYAd3DMGQ8+NvgBR+bIZBpgoHMgvhvPLsl03FMLXUyyq88gMbEnkdPD0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910082; c=relaxed/simple; bh=7GogOe5n9F2zHkC/WirTp89rqrdd3akHu64WR1KTE1Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nF6+wX+MqsjeRJ9ZZEP8sOZaSOPK2vrb7+IWa5hRbXw11Y0D9Y3xwaXuMRYjD9pqU0Z/xiEkgpjKeiBxeWgJU7JB+v0K4gktPERlFc/TAX0wuhq+NEvy+0A9zBg6C88jZ2xV4qPKhCeVb0CTakcXFGJH4YDAjyAccjjpTRX/ctU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev; spf=none smtp.mailfrom=ljones.dev; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b=FpcXUiVK; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=q3pCGfZi; arc=none smtp.client-ip=103.168.172.158 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=ljones.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b="FpcXUiVK"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="q3pCGfZi" Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfhigh.nyi.internal (Postfix) with ESMTP id A74ED1151A8A; Mon, 5 Aug 2024 22:07:59 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 05 Aug 2024 22:07:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ljones.dev; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1722910079; x= 1722996479; bh=gIvWdDLxWY22hhOBPE6JYFoqhl5WH6m9QN6kQjoDgMY=; b=F pcXUiVKTqyZ9SmvDc1uk2RqM9o8BH4dw9md3VBfFxIY4v5corV+kmXtKilN+HGgP FvyYx3faLKiofqaGrqy4Encn+H1r4Nhgz2lGCd+iSeKROuyNyfh5wQkXfO3M/7mp bdH5IRzrXm5ozgxAQ9d2NpLhFxGM2bJt5if6sqzwHSGCQi+2Dlc6I5JUt56KjWVS 08FrB2Diqvxl/F5nWojMzO6RCquU4p4AkbtDeaBvzBkUGoZdIWU9pcThaR+CFg/N Cr1MrLbJV7jhfrS2YXADN8x00aHmejYrovq8DvmZk/upfzic0awWWZugPfaQnOMl Vmsfo5TGR8sf0fffEP7Tw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1722910079; x= 1722996479; bh=gIvWdDLxWY22hhOBPE6JYFoqhl5WH6m9QN6kQjoDgMY=; b=q 3pCGfZiXipAuBzRPJnIvkV6tgXQ5wqTDrJ45IUPrIH7gSGfsei9Tlb6DaAJ5RLOD swRnrWTyD8L/Fc4gBUI/gYRVqRuPhblQn/id5FmRLgHSrocWpjiA2h1aSglrZ2Gh N60YKhgVPmc0UZPwVYPxwPbhkukhC57oY7moY/ura9oj3Llk32xHcgg4MAQBiLoi d5r7pv+YLnt83/jvADP7TmRvjcu7Iqn1RlhdWZSCFk6GE8yuvVirOAAVpe4CuQXE wMBv0LDozXK0vq6exXVXNYecSB6S5Ip63hL8JbFpNvdiVPCNAic/+95tFMI4S0x0 43iRfenv4p0yDBXPfHNAg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrkeejgdehiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvvefufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpefgteefudfgteduueehteejhfeugf fgleeltedvveethfeuueejfedvgeelveehgfenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghvpdhnsggprh gtphhtthhopedt X-ME-Proxy: Feedback-ID: i5ec1447f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 5 Aug 2024 22:07:56 -0400 (EDT) From: "Luke D. Jones" To: platform-driver-x86@vger.kernel.org Cc: linux-kernel@vger.kernel.org, ilpo.jarvinen@linux.intel.com, hdegoede@redhat.com, corentin.chary@gmail.com, "Luke D. Jones" Subject: [PATCH v2 1/6] platform/x86: asus-wmi: Add quirk for ROG Ally X Date: Tue, 6 Aug 2024 14:07:42 +1200 Message-ID: <20240806020747.365042-2-luke@ljones.dev> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240806020747.365042-1-luke@ljones.dev> References: <20240806020747.365042-1-luke@ljones.dev> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The new ROG Ally X functions the same as the previus model so we can use the same method to ensure the MCU USB devices wake and reconnect correctly. Given that two devices marks the start of a trend, this patch also adds a quirk table to make future additions easier if the MCU is the same. Signed-off-by: Luke D. Jones Reviewed-by: Ilpo Järvinen --- drivers/platform/x86/asus-wmi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index f15fcb45e1aa..0c80c6b0399b 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -152,6 +152,20 @@ static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL }; static int throttle_thermal_policy_write(struct asus_wmi *); +static const struct dmi_system_id asus_ally_mcu_quirk[] = { + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "RC71L"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "RC72L"), + }, + }, + { }, +}; + static bool ashs_present(void) { int i = 0; @@ -4751,7 +4765,7 @@ static int asus_wmi_add(struct platform_device *pdev) asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) - && dmi_match(DMI_BOARD_NAME, "RC71L"); + && dmi_check_system(asus_ally_mcu_quirk); if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE)) asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; From patchwork Tue Aug 6 02:07:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 13754309 Received: from fhigh7-smtp.messagingengine.com (fhigh7-smtp.messagingengine.com [103.168.172.158]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7DC029CE6; Tue, 6 Aug 2024 02:08:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.158 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910086; cv=none; b=bHw4QAGos6A3eMrYPjUOdIkt9K8lyPx+Q1v8H9Qqv/FG6DO+1HivjMUAo68dhRJi0ZCUhvs3PmCZL6QyZ8e5v5BgO0fxIrcF5zy/6TwE940zvvb1F8z+N1T6a61vKx8nefxGUL/rSdi3jwvFdAtlLmyPo8pVOIHKqWYf25Onk28= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910086; c=relaxed/simple; bh=BnwBpFbUMycLFEJTehUGTS4ilTkd7t9Q45A3jmiizV8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YAArfCkp+o3gjncat73sfmewjDWZqdciF4bud6khmeT039W9jXaHnv+BCH+k16khwfj2WotI+ucuKQ8Sbu4Zm21b1a2hvDzi2d9eFaIuu+rtm13ArppP7eXUr/e7X7VyGXh5Wb/BCHScRMVej7syXgsguoz1mWb423gW79jlz20= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev; spf=none smtp.mailfrom=ljones.dev; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b=bHoWMizC; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=AxUulaVa; arc=none smtp.client-ip=103.168.172.158 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=ljones.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b="bHoWMizC"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="AxUulaVa" Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 116441151A7B; Mon, 5 Aug 2024 22:08:03 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Mon, 05 Aug 2024 22:08:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ljones.dev; h=cc :cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm1; t=1722910083; x=1722996483; bh=HCYKHWQy0IxTckvxVzwpIordzEwWJDICax5XxaoRGik=; b= bHoWMizCCEO85V+TQN9U+LkRzdNt7CMOl1GMUFzSVbkvySdZHdDStqZLSTEl252S ltYlXeYlkWU/MJ+DBJ5SgTDX2gPJQsTzNOVF3KMlD/31UsvHXgCsBetkRBT+X/YJ bMY+wJjVN+V9VNDXQamsrd0EHwUSHMG7bXZ3crtUAzb8JG/6OKlJViBh/R+SjltU twz7nMc04oz85fv17tdH91Q9jNb2ADIOImkFUKv2D6TKEaI7eHcsuBahBgzzt65D 2HiqY+tg8KnpkPwPPA7O6PmMo9O/+ubE9aEInvb9F5Ffqw/2GfiQHhWGoBBo0z+B XaOXb+IdCI8ddeXrHlSOCQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1722910083; x= 1722996483; bh=HCYKHWQy0IxTckvxVzwpIordzEwWJDICax5XxaoRGik=; b=A xUulaVa5aWuE5LCsmfEh9l2H+04hjGJtaY/+IfAn8S3d1H8sdiARmp0Se3Q7/x9F iZOH+bq7nb3HI9jXt+prSwSampr+Q+5C8BsI+/L24yrKmtyrACOC5IX75RZf3Sjr jByleYMdmlevFoPt0HFlDcRB57NT1p1jwXeVRWU/E8QoSNGfwS1OokdT1aYWnx3k XdtoaF8CuH/QvUkTsJHovADhq0CZHOi9dAiyZ8brrKKb72popOIvuIGERx3m4+sC dVHwNte2pf7zlLS2VzWWB3hgkq+hdth7+7uz7BlLPa8meGIFedHgu1oJRj+ZVZYl 5OPP0aH6nroy8aQTZDC9g== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrkeejgdehiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvvefufffkofgjfhggtgfgsehtke ertdertdejnecuhfhrohhmpedfnfhukhgvucffrdculfhonhgvshdfuceolhhukhgvsehl jhhonhgvshdruggvvheqnecuggftrfgrthhtvghrnhepudduteduheeivddvveevlefhge ekfeffvdefteeugfevfefggfffieffiedtleeinecuvehluhhsthgvrhfuihiivgeptden ucfrrghrrghmpehmrghilhhfrhhomheplhhukhgvsehljhhonhgvshdruggvvhdpnhgspg hrtghpthhtoheptd X-ME-Proxy: Feedback-ID: i5ec1447f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 5 Aug 2024 22:07:59 -0400 (EDT) From: "Luke D. Jones" To: platform-driver-x86@vger.kernel.org Cc: linux-kernel@vger.kernel.org, ilpo.jarvinen@linux.intel.com, hdegoede@redhat.com, corentin.chary@gmail.com, "Luke D. Jones" Subject: [PATCH v2 2/6] platform/x86: asus-armoury: move existing tunings to asus-armoury module Date: Tue, 6 Aug 2024 14:07:43 +1200 Message-ID: <20240806020747.365042-3-luke@ljones.dev> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240806020747.365042-1-luke@ljones.dev> References: <20240806020747.365042-1-luke@ljones.dev> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The fw_attributes_class provides a much cleaner interface to all of the attributes introduced to asus-wmi. This patch moves all of these extra attributes over to fw_attributes_class, and shifts the bulk of these definitions to a new kernel module to reduce the clutter of asus-wmi with the intention of deprecating the asus-wmi attributes in future. The work applies only to WMI methods which don't have a clearly defined place within the sysfs and as a result ended up lumped together in /sys/devices/platform/asus-nb-wmi/ with no standard API. Where possible the fw attrs now implement defaults, min, max, scalar, choices, etc. As en example dgpu_disable becomes: /sys/class/firmware-attributes/asus-armoury/attributes/dgpu_disable/ ├── current_value ├── display_name ├── possible_values └── type as do other attributes. Signed-off-by: Luke D. Jones --- drivers/platform/x86/Kconfig | 14 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/asus-armoury.c | 706 +++++++++++++++++++++ drivers/platform/x86/asus-armoury.h | 195 ++++++ drivers/platform/x86/asus-wmi.c | 48 +- include/linux/platform_data/x86/asus-wmi.h | 11 + 6 files changed, 973 insertions(+), 2 deletions(-) create mode 100644 drivers/platform/x86/asus-armoury.c create mode 100644 drivers/platform/x86/asus-armoury.h diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 665fa9524986..8ecc73ef2670 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -265,6 +265,19 @@ config ASUS_WIRELESS If you choose to compile this driver as a module the module will be called asus-wireless. +config ASUS_ARMOURY + tristate "ASUS Armoury (firmware) Driver" + depends on ACPI_WMI + depends on ASUS_WMI + select FW_ATTR_CLASS + help + Say Y here if you have a WMI aware Asus laptop and would like to use the + firmware_attributes API to control various settings typically exposed in + the ASUS Armoury Crate application available on Windows. + + To compile this driver as a module, choose M here: the module will + be called asus-armoury. + config ASUS_WMI tristate "ASUS WMI Driver" depends on ACPI_WMI @@ -276,6 +289,7 @@ config ASUS_WMI depends on HOTPLUG_PCI depends on ACPI_VIDEO || ACPI_VIDEO = n depends on SERIO_I8042 || SERIO_I8042 = n + select ASUS_ARMOURY select INPUT_SPARSEKMAP select LEDS_CLASS select NEW_LEDS diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index e1b142947067..fe3e7e7dede8 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o # ASUS obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o obj-$(CONFIG_ASUS_WIRELESS) += asus-wireless.o +obj-$(CONFIG_ASUS_ARMOURY) += asus-armoury.o obj-$(CONFIG_ASUS_WMI) += asus-wmi.o obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o obj-$(CONFIG_ASUS_TF103C_DOCK) += asus-tf103c-dock.o diff --git a/drivers/platform/x86/asus-armoury.c b/drivers/platform/x86/asus-armoury.c new file mode 100644 index 000000000000..bb049ead00f9 --- /dev/null +++ b/drivers/platform/x86/asus-armoury.c @@ -0,0 +1,706 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Asus Armoury (WMI) attributes driver. This driver uses the fw_attributes + * class to expose the various WMI functions that many gaming and some + * non-gaming ASUS laptops have available. + * These typically don't fit anywhere else in the sysfs such as under LED class, + * hwmon or other, and are set in Windows using the ASUS Armoury Crate tool. + * + * Copyright(C) 2010 Intel Corporation. + * Copyright(C) 2024-2024 Luke Jones + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "asus-armoury.h" +#include "firmware_attributes_class.h" + +#define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C" + +#define ASUS_MINI_LED_MODE_MASK 0x03 +/* Standard modes for devices with only on/off */ +#define ASUS_MINI_LED_OFF 0x00 +#define ASUS_MINI_LED_ON 0x01 +/* New mode on some devices, define here to clarify remapping later */ +#define ASUS_MINI_LED_STRONG_MODE 0x02 +/* New modes for devices with 3 mini-led mode types */ +#define ASUS_MINI_LED_2024_WEAK 0x00 +#define ASUS_MINI_LED_2024_STRONG 0x01 +#define ASUS_MINI_LED_2024_OFF 0x02 + +/* Default limits for tunables available on ASUS ROG laptops */ +#define PPT_CPU_LIMIT_MIN 5 +#define PPT_CPU_LIMIT_MAX 150 +#define PPT_CPU_LIMIT_DEFAULT 80 +#define PPT_PLATFORM_MIN 5 +#define PPT_PLATFORM_MAX 100 +#define PPT_PLATFORM_DEFAULT 80 +#define NVIDIA_BOOST_MIN 5 +#define NVIDIA_BOOST_MAX 25 +#define NVIDIA_TEMP_MIN 75 +#define NVIDIA_TEMP_MAX 87 + +/* Tunables provided by ASUS for gaming laptops */ +struct rog_tunables { + u32 cpu_default; + u32 cpu_min; + u32 cpu_max; + + u32 platform_default; + u32 platform_min; + u32 platform_max; + + u32 ppt_pl1_spl; // cpu + u32 ppt_pl2_sppt; // cpu + u32 ppt_apu_sppt; // plat + u32 ppt_platform_sppt; // plat + u32 ppt_fppt; // cpu + + u32 nv_boost_default; + u32 nv_boost_min; + u32 nv_boost_max; + u32 nv_dynamic_boost; + + u32 nv_temp_default; + u32 nv_temp_min; + u32 nv_temp_max; + u32 nv_temp_target; +}; + +static const struct class *fw_attr_class; + +struct asus_armoury_priv { + struct device *fw_attr_dev; + struct kset *fw_attr_kset; + + struct rog_tunables *rog_tunables; + u32 mini_led_dev_id; + u32 gpu_mux_dev_id; + + struct mutex mutex; +}; + +static struct asus_armoury_priv asus_armoury = { .mutex = __MUTEX_INITIALIZER( + asus_armoury.mutex) }; + +struct fw_attrs_group { + u32 pending_reboot; +}; + +static struct fw_attrs_group fw_attrs = { + .pending_reboot = 0, +}; + +struct asus_attr_group { + const struct attribute_group *attr_group; + u32 wmi_devid; +}; + +/** + * asus_wmi_is_present() - determine if a WMI interface is available. + * @dev_id: The WMI function ID to use. + * + * Returns: Boolean state. Note that an error will also return false. + */ +static bool asus_wmi_is_present(u32 dev_id) +{ + u32 retval; + int status; + + status = asus_wmi_get_devstate_dsts(dev_id, &retval); + pr_debug("%s called (0x%08x), retval: 0x%08x\n", __func__, dev_id, retval); + + return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); +} + +static void asus_set_reboot_and_signal_event(void) +{ + fw_attrs.pending_reboot = 1; + kobject_uevent(&asus_armoury.fw_attr_dev->kobj, KOBJ_CHANGE); +} + +static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%u\n", fw_attrs.pending_reboot); +} + +static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); + +static bool asus_bios_requires_reboot(struct kobj_attribute *attr) +{ + return !strcmp(attr->attr.name, "gpu_mux_mode") || + !strcmp(attr->attr.name, "panel_hd_mode"); +} + +/** + * attr_int_store() - Generic store function for use with most WMI functions. + * @kobj: Pointer to the driver object. + * @kobj_attribute: Pointer the attribute calling this function. + * @buf: The buffer to read from, this is parsed to `int` type. + * @count: + * @min: Minimum accepted value. Below this returns -EINVAL. + * @max: Maximum accepted value. Above this returns -EINVAL. + * @store_value: Pointer to where the parsed value should be stored. + * @wmi_dev: The WMI function ID to use. + * + * The WMI functions available on most ASUS laptops return a 1 as "success", and + * a 0 as failed. However some functions can return n > 1 for additional errors. + * attr_int_store() currently treats all values which are not 1 as errors, ignoring + * the possible differences in WMI error returns. + * + * Returns: Either count, or an error. + */ +static ssize_t attr_int_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count, u32 min, u32 max, u32 *store_value, + u32 wmi_dev) +{ + u32 result, value; + int err; + + err = kstrtouint(buf, 10, &value); + if (err) + return err; + + if (value < min || value > max) + return -EINVAL; + + err = asus_wmi_set_devstate(wmi_dev, value, &result); + if (err) { + pr_err("Failed to set %s: %d\n", attr->attr.name, err); + return err; + } + + if (result != 1) { + pr_err("Failed to set %s (result): 0x%x\n", attr->attr.name, result); + return -EIO; + } + + if (store_value != NULL) + *store_value = value; + sysfs_notify(kobj, NULL, attr->attr.name); + + if (asus_bios_requires_reboot(attr)) + asus_set_reboot_and_signal_event(); + + return count; +} + +/* Mini-LED mode **************************************************************/ +static ssize_t mini_led_mode_current_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + u32 value; + int err; + + err = asus_wmi_get_devstate_dsts(asus_armoury.mini_led_dev_id, &value); + if (err) + return err; + + value = value & ASUS_MINI_LED_MODE_MASK; + + /* + * Remap the mode values to match previous generation mini-led. The last gen + * WMI 0 == off, while on this version WMI 2 ==off (flipped). + */ + if (asus_armoury.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) { + switch (value) { + case ASUS_MINI_LED_2024_WEAK: + value = ASUS_MINI_LED_ON; + break; + case ASUS_MINI_LED_2024_STRONG: + value = ASUS_MINI_LED_STRONG_MODE; + break; + case ASUS_MINI_LED_2024_OFF: + value = ASUS_MINI_LED_OFF; + break; + } + } + + return sysfs_emit(buf, "%u\n", value); +} + +static ssize_t mini_led_mode_current_value_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, + size_t count) +{ + int result, err; + u32 mode; + + err = kstrtou32(buf, 10, &mode); + if (err) + return err; + + if (asus_armoury.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE && + mode > ASUS_MINI_LED_ON) + return -EINVAL; + if (asus_armoury.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 && + mode > ASUS_MINI_LED_STRONG_MODE) + return -EINVAL; + + /* + * Remap the mode values so expected behaviour is the same as the last + * generation of mini-LED with 0 == off, 1 == on. + */ + if (asus_armoury.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) { + switch (mode) { + case ASUS_MINI_LED_OFF: + mode = ASUS_MINI_LED_2024_OFF; + break; + case ASUS_MINI_LED_ON: + mode = ASUS_MINI_LED_2024_WEAK; + break; + case ASUS_MINI_LED_STRONG_MODE: + mode = ASUS_MINI_LED_2024_STRONG; + break; + } + } + + err = asus_wmi_set_devstate(asus_armoury.mini_led_dev_id, mode, &result); + if (err) { + pr_warn("Failed to set mini-LED: %d\n", err); + return err; + } + + if (result != 1) { + pr_warn("Failed to set mini-LED mode (result): 0x%x\n", result); + return -EIO; + } + + sysfs_notify(kobj, NULL, attr->attr.name); + + return count; +} + +static ssize_t mini_led_mode_possible_values_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + switch (asus_armoury.mini_led_dev_id) { + case ASUS_WMI_DEVID_MINI_LED_MODE: + return sysfs_emit(buf, "0;1\n"); + case ASUS_WMI_DEVID_MINI_LED_MODE2: + return sysfs_emit(buf, "0;1;2\n"); + } + + return sysfs_emit(buf, "0\n"); +} + +ATTR_GROUP_ENUM_CUSTOM(mini_led_mode, "mini_led_mode", "Set the mini-LED backlight mode"); + +static ssize_t gpu_mux_mode_current_value_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, + size_t count) +{ + int result, err; + u32 optimus; + + err = kstrtou32(buf, 10, &optimus); + if (err) + return err; + + if (optimus > 1) + return -EINVAL; + + if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU)) { + err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_DGPU, &result); + if (err) + return err; + if (result && !optimus) { + err = -ENODEV; + pr_warn("Can not switch MUX to dGPU mode when dGPU is disabled: %d\n", + err); + return err; + } + } + + if (asus_wmi_is_present(ASUS_WMI_DEVID_EGPU)) { + err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_EGPU, &result); + if (err) + return err; + if (result && !optimus) { + err = -ENODEV; + pr_warn("Can not switch MUX to dGPU mode when eGPU is enabled: %d\n", + err); + return err; + } + } + + err = asus_wmi_set_devstate(asus_armoury.gpu_mux_dev_id, optimus, &result); + if (err) { + pr_err("Failed to set GPU MUX mode: %d\nn", err); + return err; + } + /* !1 is considered a fail by ASUS */ + if (result != 1) { + pr_warn("Failed to set GPU MUX mode (result): 0x%x\n", result); + return -EIO; + } + + sysfs_notify(kobj, NULL, attr->attr.name); + + return count; +} +WMI_SHOW_INT(gpu_mux_mode_current_value, "%d\n", asus_armoury.gpu_mux_dev_id); +ATTR_GROUP_BOOL_CUSTOM(gpu_mux_mode, "gpu_mux_mode", "Set the GPU display MUX mode"); + +/* + * A user may be required to store the value twice, typcial store first, then + * rescan PCI bus to activate power, then store a second time to save correctly. + * The reason for this is that an extra code path in the ACPI is enabled when + * the device and bus are powered. + */ +static ssize_t dgpu_disable_current_value_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, + size_t count) +{ + int result, err; + u32 disable; + + err = kstrtou32(buf, 10, &disable); + if (err) + return err; + + if (disable > 1) + return -EINVAL; + + if (asus_armoury.gpu_mux_dev_id) { + err = asus_wmi_get_devstate_dsts(asus_armoury.gpu_mux_dev_id, &result); + if (err) + return err; + if (!result && disable) { + err = -ENODEV; + pr_warn("Can not disable dGPU when the MUX is in dGPU mode: %d\n", err); + return err; + } + } + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, disable, &result); + if (err) { + pr_warn("Failed to set dgpu disable: %d\n", err); + return err; + } + + if (result != 1) { + pr_warn("Failed to set dgpu disable (result): 0x%x\n", result); + return -EIO; + } + + sysfs_notify(kobj, NULL, attr->attr.name); + + return count; +} +WMI_SHOW_INT(dgpu_disable_current_value, "%d\n", ASUS_WMI_DEVID_DGPU); +ATTR_GROUP_BOOL_CUSTOM(dgpu_disable, "dgpu_disable", "Disable the dGPU"); + +/* The ACPI call to enable the eGPU also disables the internal dGPU */ +static ssize_t egpu_enable_current_value_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, + size_t count) +{ + int result, err; + u32 enable; + + err = kstrtou32(buf, 10, &enable); + if (err) + return err; + + if (enable > 1) + return -EINVAL; + + err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_EGPU_CONNECTED, &result); + if (err) { + pr_warn("Failed to get egpu connection status: %d\n", err); + return err; + } + + if (asus_armoury.gpu_mux_dev_id) { + err = asus_wmi_get_devstate_dsts(asus_armoury.gpu_mux_dev_id, &result); + if (err) { + pr_warn("Failed to get gpu mux status: %d\n", result); + return result; + } + if (!result && enable) { + err = -ENODEV; + pr_warn("Can not enable eGPU when the MUX is in dGPU mode: %d\n", err); + return err; + } + } + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, enable, &result); + if (err) { + pr_warn("Failed to set egpu state: %d\n", err); + return err; + } + + if (result != 1) { + pr_warn("Failed to set egpu state (retval): 0x%x\n", result); + return -EIO; + } + + sysfs_notify(kobj, NULL, attr->attr.name); + + return count; +} +WMI_SHOW_INT(egpu_enable_current_value, "%d\n", ASUS_WMI_DEVID_EGPU); +ATTR_GROUP_BOOL_CUSTOM(egpu_enable, "egpu_enable", "Enable the eGPU (also disables dGPU)"); + +/* Simple attribute creation */ +ATTR_GROUP_ROG_TUNABLE(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL, cpu_default, + cpu_min, cpu_max, 1, "Set the CPU slow package limit"); +ATTR_GROUP_ROG_TUNABLE(ppt_pl2_sppt, "ppt_pl2_sppt", ASUS_WMI_DEVID_PPT_PL2_SPPT, cpu_default, + cpu_min, cpu_max, 1, "Set the CPU fast package limit"); +ATTR_GROUP_ROG_TUNABLE(ppt_apu_sppt, "ppt_apu_sppt", ASUS_WMI_DEVID_PPT_APU_SPPT, + platform_default, platform_min, platform_max, 1, + "Set the CPU slow package limit"); +ATTR_GROUP_ROG_TUNABLE(ppt_platform_sppt, "ppt_platform_sppt", ASUS_WMI_DEVID_PPT_PLAT_SPPT, + platform_default, platform_min, platform_max, 1, + "Set the CPU slow package limit"); +ATTR_GROUP_ROG_TUNABLE(ppt_fppt, "ppt_fppt", ASUS_WMI_DEVID_PPT_FPPT, cpu_default, cpu_min, + cpu_max, 1, "Set the CPU slow package limit"); + +ATTR_GROUP_ROG_TUNABLE(nv_dynamic_boost, "nv_dynamic_boost", ASUS_WMI_DEVID_NV_DYN_BOOST, + nv_boost_default, nv_boost_min, nv_boost_max, 1, + "Set the Nvidia dynamic boost limit"); +ATTR_GROUP_ROG_TUNABLE(nv_temp_target, "nv_temp_target", ASUS_WMI_DEVID_NV_THERM_TARGET, + nv_temp_default, nv_boost_min, nv_temp_max, 1, + "Set the Nvidia max thermal limit"); + +ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE, "0;1;2", + "Show the current mode of charging"); +ATTR_GROUP_BOOL_RW(boot_sound, "boot_sound", ASUS_WMI_DEVID_BOOT_SOUND, + "Set the boot POST sound"); +ATTR_GROUP_BOOL_RW(mcu_powersave, "mcu_powersave", ASUS_WMI_DEVID_MCU_POWERSAVE, + "Set MCU powersaving mode"); +ATTR_GROUP_BOOL_RW(panel_od, "panel_overdrive", ASUS_WMI_DEVID_PANEL_OD, + "Set the panel refresh overdrive"); +ATTR_GROUP_BOOL_RW(panel_hd_mode, "panel_hd_mode", ASUS_WMI_DEVID_PANEL_HD, + "Set the panel HD mode to UHD<0> or FHD<1>"); +ATTR_GROUP_BOOL_RO(egpu_connected, "egpu_connected", ASUS_WMI_DEVID_EGPU_CONNECTED, + "Show the eGPU connection status"); + +/* If an attribute does not require any special case handling add it here */ +static const struct asus_attr_group armoury_attr_groups[] = { + { &egpu_connected_attr_group, ASUS_WMI_DEVID_EGPU_CONNECTED }, + { &egpu_enable_attr_group, ASUS_WMI_DEVID_EGPU }, + { &dgpu_disable_attr_group, ASUS_WMI_DEVID_DGPU }, + + { &ppt_pl1_spl_attr_group, ASUS_WMI_DEVID_PPT_PL1_SPL }, + { &ppt_pl2_sppt_attr_group, ASUS_WMI_DEVID_PPT_PL2_SPPT }, + { &ppt_apu_sppt_attr_group, ASUS_WMI_DEVID_PPT_APU_SPPT }, + { &ppt_platform_sppt_attr_group, ASUS_WMI_DEVID_PPT_PLAT_SPPT }, + { &ppt_fppt_attr_group, ASUS_WMI_DEVID_PPT_FPPT }, + { &nv_dynamic_boost_attr_group, ASUS_WMI_DEVID_NV_DYN_BOOST }, + { &nv_temp_target_attr_group, ASUS_WMI_DEVID_NV_THERM_TARGET }, + + { &charge_mode_attr_group, ASUS_WMI_DEVID_CHARGE_MODE }, + { &boot_sound_attr_group, ASUS_WMI_DEVID_BOOT_SOUND }, + { &mcu_powersave_attr_group, ASUS_WMI_DEVID_MCU_POWERSAVE }, + { &panel_od_attr_group, ASUS_WMI_DEVID_PANEL_OD }, + { &panel_hd_mode_attr_group, ASUS_WMI_DEVID_PANEL_HD }, +}; + +static int asus_fw_attr_add(void) +{ + int err; + + err = fw_attributes_class_get(&fw_attr_class); + if (err) + goto fail_class_created; + + asus_armoury.fw_attr_dev = + device_create(fw_attr_class, NULL, MKDEV(0, 0), NULL, "%s", DRIVER_NAME); + + if (IS_ERR(asus_armoury.fw_attr_dev)) { + err = PTR_ERR(asus_armoury.fw_attr_dev); + goto fail_class_created; + } + + asus_armoury.fw_attr_kset = + kset_create_and_add("attributes", NULL, &asus_armoury.fw_attr_dev->kobj); + if (!asus_armoury.fw_attr_dev) { + err = -ENOMEM; + pr_debug("Failed to create and add attributes\n"); + goto err_destroy_classdev; + } + + err = sysfs_create_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr); + if (err) { + pr_warn("Failed to create sysfs level attributes\n"); + goto fail_class_created; + } + + err = 0; + asus_armoury.mini_led_dev_id = 0; + if (asus_wmi_is_present(ASUS_WMI_DEVID_MINI_LED_MODE)) { + asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; + err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, + &mini_led_mode_attr_group); + } else if (asus_wmi_is_present(ASUS_WMI_DEVID_MINI_LED_MODE2)) { + asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2; + err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, + &mini_led_mode_attr_group); + } + if (err) + pr_warn("Failed to create sysfs-group for mini_led\n"); + + err = 0; + asus_armoury.gpu_mux_dev_id = 0; + if (asus_wmi_is_present(ASUS_WMI_DEVID_GPU_MUX)) { + asus_armoury.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX; + err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, + &gpu_mux_mode_attr_group); + } else if (asus_wmi_is_present(ASUS_WMI_DEVID_GPU_MUX_VIVO)) { + asus_armoury.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX_VIVO; + err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, + &gpu_mux_mode_attr_group); + } + if (err) + pr_warn("Failed to create sysfs-group for gpu_mux\n"); + + for (int i = 0; i < ARRAY_SIZE(armoury_attr_groups); i++) { + if (!asus_wmi_is_present(armoury_attr_groups[i].wmi_devid)) + continue; + + err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, + armoury_attr_groups[i].attr_group); + if (err) + pr_warn("Failed to create sysfs-group for %s\n", + armoury_attr_groups[i].attr_group->name); + else + pr_debug("Created sysfs-group for %s\n", + armoury_attr_groups[i].attr_group->name); + } + + return 0; + +err_destroy_classdev: + device_destroy(fw_attr_class, MKDEV(0, 0)); + +fail_class_created: + fw_attributes_class_put(); + return err; +} + +/* Init / exit ****************************************************************/ + +/* Set up the min/max and defaults for ROG tunables */ +static void init_rog_tunables(struct rog_tunables *rog) +{ + const char *product; + u32 max_boost = NVIDIA_BOOST_MAX; + u32 cpu_default = PPT_CPU_LIMIT_DEFAULT; + u32 cpu_max = PPT_CPU_LIMIT_MAX; + u32 platform_default = PPT_PLATFORM_DEFAULT; + u32 platform_max = PPT_PLATFORM_MAX; + + /* + * ASUS product_name contains everything required, e.g, + * "ROG Flow X16 GV601VV_GV601VV_00185149B" + */ + product = dmi_get_system_info(DMI_PRODUCT_NAME); + + if (strstr(product, "GA402R")) { + cpu_default = 125; + } else if (strstr(product, "13QY")) { + cpu_max = 250; + } else if (strstr(product, "X13")) { + cpu_max = 75; + cpu_default = 50; + } else if (strstr(product, "RC71")) { + cpu_max = 50; + cpu_default = 30; + } else if (strstr(product, "G814") || strstr(product, "G614") || + strstr(product, "G834") || strstr(product, "G634")) { + cpu_max = 175; + } else if (strstr(product, "GA402X") || strstr(product, "GA403") || + strstr(product, "FA507N") || strstr(product, "FA507X") || + strstr(product, "FA707N") || strstr(product, "FA707X")) { + cpu_max = 90; + } + + if (strstr(product, "GZ301ZE")) + max_boost = 5; + else if (strstr(product, "FX507ZC4")) + max_boost = 15; + else if (strstr(product, "GU605")) + max_boost = 20; + + /* ensure defaults for tunables */ + rog->cpu_default = cpu_default; + rog->cpu_min = PPT_CPU_LIMIT_MIN; + rog->cpu_max = cpu_max; + + rog->platform_default = platform_default; + rog->platform_max = PPT_PLATFORM_MIN; + rog->platform_max = platform_max; + + rog->ppt_pl1_spl = cpu_default; + rog->ppt_pl2_sppt = cpu_default; + rog->ppt_apu_sppt = cpu_default; + + rog->ppt_platform_sppt = platform_default; + rog->ppt_fppt = platform_default; + + rog->nv_boost_default = NVIDIA_BOOST_MAX; + rog->nv_boost_max = NVIDIA_BOOST_MIN; + rog->nv_boost_max = max_boost; + rog->nv_dynamic_boost = NVIDIA_BOOST_MIN; + + rog->nv_temp_default = NVIDIA_TEMP_MAX; + rog->nv_temp_max = NVIDIA_TEMP_MIN; + rog->nv_temp_max = NVIDIA_TEMP_MAX; + rog->nv_temp_target = NVIDIA_TEMP_MIN; +} + +static int __init asus_fw_init(void) +{ + int err; + + fw_attrs.pending_reboot = 0; + + mutex_lock(&asus_armoury.mutex); + + asus_armoury.rog_tunables = kzalloc(sizeof(struct rog_tunables), GFP_KERNEL); + if (!asus_armoury.rog_tunables) { + mutex_unlock(&asus_armoury.mutex); + return -ENOMEM; + } + init_rog_tunables(asus_armoury.rog_tunables); + + err = asus_fw_attr_add(); + mutex_unlock(&asus_armoury.mutex); + if (err) + return err; + + return 0; +} + +static void __exit asus_fw_exit(void) +{ + mutex_lock(&asus_armoury.mutex); + + sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr); + kset_unregister(asus_armoury.fw_attr_kset); + device_destroy(fw_attr_class, MKDEV(0, 0)); + fw_attributes_class_put(); + + mutex_unlock(&asus_armoury.mutex); +} + +module_init(asus_fw_init); +module_exit(asus_fw_exit); + +MODULE_AUTHOR("Luke Jones "); +MODULE_DESCRIPTION("ASUS BIOS Configuration Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("wmi:" ASUS_NB_WMI_EVENT_GUID); diff --git a/drivers/platform/x86/asus-armoury.h b/drivers/platform/x86/asus-armoury.h new file mode 100644 index 000000000000..146170f91e69 --- /dev/null +++ b/drivers/platform/x86/asus-armoury.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Definitions for kernel modules using asus-armoury driver + * + * Copyright (c) 2024 Luke Jones + */ + +#ifndef _ASUS_BIOSCFG_H_ +#define _ASUS_BIOSCFG_H_ + +#include + +#define DRIVER_NAME "asus-armoury" + +static ssize_t attr_int_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count, u32 min, u32 max, u32 *store_value, + u32 wmi_dev); + +static ssize_t int_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "integer\n"); +} + +static ssize_t enum_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "enumeration\n"); +} + +#define __ASUS_ATTR_RO(_func, _name) \ + { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = _func##_##_name##_show, \ + } + +#define __ASUS_ATTR_RO_AS(_name, _show) \ + { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = _show, \ + } + +#define __ASUS_ATTR_RW(_func, _name) \ + __ATTR(_name, 0644, _func##_##_name##_show, _func##_##_name##_store) + +#define __WMI_STORE_INT(_attr, _min, _max, _wmi) \ + static ssize_t _attr##_store(struct kobject *kobj, struct kobj_attribute *attr, \ + const char *buf, size_t count) \ + { \ + return attr_int_store(kobj, attr, buf, count, _min, _max, NULL, _wmi); \ + } + +#define WMI_SHOW_INT(_attr, _fmt, _wmi) \ + static ssize_t _attr##_show(struct kobject *kobj, struct kobj_attribute *attr, \ + char *buf) \ + { \ + u32 result; \ + int err; \ + err = asus_wmi_get_devstate_dsts(_wmi, &result); \ + if (err) \ + return err; \ + return sysfs_emit(buf, _fmt, result & ~ASUS_WMI_DSTS_PRESENCE_BIT); \ + } + +/* Create functions and attributes for use in other macros or on their own */ + +#define __ATTR_CURRENT_INT_RO(_attr, _wmi) \ + WMI_SHOW_INT(_attr##_current_value, "%d\n", _wmi); \ + static struct kobj_attribute attr_##_attr##_current_value = \ + __ASUS_ATTR_RO(_attr, current_value) + +#define __ATTR_CURRENT_INT_RW(_attr, _minv, _maxv, _wmi) \ + __WMI_STORE_INT(_attr##_current_value, _minv, _maxv, _wmi); \ + WMI_SHOW_INT(_attr##_current_value, "%d\n", _wmi); \ + static struct kobj_attribute attr_##_attr##_current_value = \ + __ASUS_ATTR_RW(_attr, current_value) + +/* Shows a formatted static variable */ +#define __ATTR_SHOW_FMT(_prop, _attrname, _fmt, _val) \ + static ssize_t _attrname##_##_prop##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sysfs_emit(buf, _fmt, _val); \ + } \ + static struct kobj_attribute attr_##_attrname##_##_prop = \ + __ASUS_ATTR_RO(_attrname, _prop) + +/* Boolean style enumeration, base macro. Requires adding show/store */ +#define __ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname) \ + __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ + __ATTR_SHOW_FMT(possible_values, _attrname, "%s\n", _possible); \ + static struct kobj_attribute attr_##_attrname##_type = \ + __ASUS_ATTR_RO_AS(type, enum_type_show); \ + static struct attribute *_attrname##_attrs[] = { \ + &attr_##_attrname##_current_value.attr, &attr_##_attrname##_display_name.attr, \ + &attr_##_attrname##_possible_values.attr, &attr_##_attrname##_type.attr, NULL \ + }; \ + static const struct attribute_group _attrname##_attr_group = { \ + .name = _fsname, .attrs = _attrname##_attrs \ + } + +#define ATTR_GROUP_BOOL_RO(_attrname, _fsname, _wmi, _dispname) \ + __ATTR_CURRENT_INT_RO(_attrname, _wmi); \ + __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname) + +#define ATTR_GROUP_BOOL_RW(_attrname, _fsname, _wmi, _dispname) \ + __ATTR_CURRENT_INT_RW(_attrname, 0, 1, _wmi); \ + __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname) + +/* + * Requires _current_value_show(), _current_value_show() + */ +#define ATTR_GROUP_BOOL_CUSTOM(_attrname, _fsname, _dispname) \ + static struct kobj_attribute attr_##_attrname##_current_value = \ + __ASUS_ATTR_RW(_attrname, current_value); \ + __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname) + +#define ATTR_GROUP_ENUM_INT_RO(_attrname, _fsname, _wmi, _possible, _dispname) \ + __ATTR_CURRENT_INT_RO(_attrname, _wmi); \ + __ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname) + +/* + * Requires _current_value_show(), _current_value_show() + * and _possible_values_show() + */ +#define ATTR_GROUP_ENUM_CUSTOM(_attrname, _fsname, _dispname) \ + __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ + static struct kobj_attribute attr_##_attrname##_current_value = \ + __ASUS_ATTR_RW(_attrname, current_value); \ + static struct kobj_attribute attr_##_attrname##_possible_values = \ + __ASUS_ATTR_RO(_attrname, possible_values); \ + static struct kobj_attribute attr_##_attrname##_type = \ + __ASUS_ATTR_RO_AS(type, enum_type_show); \ + static struct attribute *_attrname##_attrs[] = { \ + &attr_##_attrname##_current_value.attr, &attr_##_attrname##_display_name.attr, \ + &attr_##_attrname##_possible_values.attr, &attr_##_attrname##_type.attr, NULL \ + }; \ + static const struct attribute_group _attrname##_attr_group = { \ + .name = _fsname, .attrs = _attrname##_attrs \ + } + +/* + * ROG PPT attributes need a little different in setup as they + * require rog_tunables members. + */ + +#define __ROG_TUNABLE_RW(_attr, _min, _max, _wmi) \ + static ssize_t _attr##_current_value_store(struct kobject *kobj, \ + struct kobj_attribute *attr, \ + const char *buf, size_t count) \ + { \ + return attr_int_store(kobj, attr, buf, count, asus_armoury.rog_tunables->_min, \ + asus_armoury.rog_tunables->_max, \ + &asus_armoury.rog_tunables->_attr, _wmi); \ + } \ + static ssize_t _attr##_current_value_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sysfs_emit(buf, "%u\n", asus_armoury.rog_tunables->_attr); \ + } \ + static struct kobj_attribute attr_##_attr##_current_value = \ + __ASUS_ATTR_RW(_attr, current_value) + +#define __ROG_TUNABLE_SHOW(_prop, _attrname, _val) \ + static ssize_t _attrname##_##_prop##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sysfs_emit(buf, "%d\n", asus_armoury.rog_tunables->_val); \ + } \ + static struct kobj_attribute attr_##_attrname##_##_prop = \ + __ASUS_ATTR_RO(_attrname, _prop) + +#define ATTR_GROUP_ROG_TUNABLE(_attrname, _fsname, _wmi, _default, _min, _max, _incstep, \ + _dispname) \ + __ROG_TUNABLE_SHOW(default_value, _attrname, _default); \ + __ROG_TUNABLE_RW(_attrname, _min, _max, _wmi); \ + __ROG_TUNABLE_SHOW(min_value, _attrname, _min); \ + __ROG_TUNABLE_SHOW(max_value, _attrname, _max); \ + __ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", _incstep); \ + __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ + static struct kobj_attribute attr_##_attrname##_type = \ + __ASUS_ATTR_RO_AS(type, int_type_show); \ + static struct attribute *_attrname##_attrs[] = { \ + &attr_##_attrname##_current_value.attr, \ + &attr_##_attrname##_default_value.attr, \ + &attr_##_attrname##_min_value.attr, \ + &attr_##_attrname##_max_value.attr, \ + &attr_##_attrname##_scalar_increment.attr, \ + &attr_##_attrname##_display_name.attr, \ + &attr_##_attrname##_type.attr, \ + NULL \ + }; \ + static const struct attribute_group _attrname##_attr_group = { \ + .name = _fsname, .attrs = _attrname##_attrs \ + } + +#endif /* _ASUS_BIOSCFG_H_ */ diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 0c80c6b0399b..165e7932c371 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -550,12 +550,56 @@ static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval) return 0; } -static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, - u32 *retval) +/** + * asus_wmi_get_devstate_dsts() - Get the WMI function state. + * @dev_id: The WMI function to call. + * @retval: A pointer to where to store the value returned from WMI. + * + * The returned WMI function state can also be used to determine if the WMI + * function is supported by checking if the asus_wmi_get_devstate_dsts() + * returns an error. + * + * On success the return value is 0, and the retval is a valid value returned + * by the successful WMI function call. An error value is returned only if the + * WMI function failed, or if it returns "unsupported" which is typically a 0 + * (no return, and no 'supported' bit set), or a 0xFFFFFFFE (~1) which if not + * caught here can result in unexpected behaviour later. + */ +int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval) +{ + int err; + + err = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, dev_id, 0, retval); + if (err) + return err; + /* Be explicit about retval */ + if (*retval == 0xFFFFFFFE || *retval == 0) + return -ENODEV; + + return 0; +} +EXPORT_SYMBOL_GPL(asus_wmi_get_devstate_dsts); + +/** + * asus_wmi_set_devstate() - Set the WMI function state. + * @dev_id: The WMI function to call. + * @ctrl_param: The argument to be used for this WMI function. + * @retval: A pointer to where to store the value returned from WMI. + * + * The returned WMI function state if not checked here for error as + * asus_wmi_set_devstate() is not called unless first paired with a call to + * asus_wmi_get_devstate_dsts() to check that the WMI function is supported. + * + * On success the return value is 0, and the retval is a valid value returned + * by the successful WMI function call. An error value is returned only if the + * WMI function failed. + */ +int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval) { return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id, ctrl_param, retval); } +EXPORT_SYMBOL_GPL(asus_wmi_set_devstate); /* Helper for special devices with magic return codes */ static int asus_wmi_get_devstate_bits(struct asus_wmi *asus, diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index b601b245a035..c164e656ae0b 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -72,6 +72,7 @@ #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO 0x00110019 /* Misc */ +#define ASUS_WMI_DEVID_PANEL_HD 0x0005001C #define ASUS_WMI_DEVID_PANEL_OD 0x00050019 #define ASUS_WMI_DEVID_CAMERA 0x00060013 #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 @@ -157,8 +158,18 @@ #define ASUS_WMI_DSTS_LIGHTBAR_MASK 0x0000000F #if IS_REACHABLE(CONFIG_ASUS_WMI) +int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval); +int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval); int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval); #else +static int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval) +{ + return -ENODEV; +} +static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval) +{ + return -ENODEV; +} static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval) { From patchwork Tue Aug 6 02:07:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 13754310 Received: from fout2-smtp.messagingengine.com (fout2-smtp.messagingengine.com [103.168.172.145]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 603A3DF71; Tue, 6 Aug 2024 02:08:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.145 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910089; cv=none; b=R6QN38yB29KQRxm6qqDmCzaRcntyXPVeAkFlN1ZzAdzL7rPUoS51ViYKJNlc+ay5WYT8tCniU5o/NgmokRID5VXEoM3El/Ss/kEKzk4OZC96WWUjgDVLpSHxVVgRar+1OXSSVMHoeqxrT71P8QHtkd4k9aXmz7rWLXtexlJ/fYg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910089; c=relaxed/simple; bh=uIB7/4OHAyBmfrbfmDDv3Vz80yUdMDj/O/p26M7mm3c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qr+VOclbPgHt74KeHNB5l5oSvRLpm7Kvl9V0nOHx5Ww/wXW5vFj9dC6+putAJ8mMO9zWGFPSKo0t1GuBDbV5UlFywkpUoGhqTwkWPXAZ7tYMz0HyIUMLGN30IuI8hVdL0GNO0E9zO4vbWdT8UCOgObG+SzXPuCe7URyyxNj6z8k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev; spf=none smtp.mailfrom=ljones.dev; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b=arwVxI6I; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=NgwEacaz; arc=none smtp.client-ip=103.168.172.145 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=ljones.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b="arwVxI6I"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="NgwEacaz" Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailfout.nyi.internal (Postfix) with ESMTP id 78A89138FC29; Mon, 5 Aug 2024 22:08:06 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Mon, 05 Aug 2024 22:08:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ljones.dev; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1722910086; x= 1722996486; bh=mGAnkWQ+s4jKoLerEH+XWqyzB+onfTH+kswNnPYw2NI=; b=a rwVxI6IAr5pGosyeZ0mtmpXd3PC+Xi7inR9DhEJN80LbpM+6EWXuTs6L89kxDuHc YTeF11rTH9f+4DWrzig9NhQ3hVAVSS+TtLRbNJSiI9h1Reanf2jtKDeowJ6ObuxL YW+sT8GtQCA3EccPq5eu5AZ16V58vlO47i68AtUirqaszghErWjgsVlO9P+V2otB 87d2KGkKqyDM69JHUX8f8/alU97pbOknmK62iHbXdDKxpr/Z0l+ZUn5ijErL/zcu 8gh9UKFJPB/1k0ubJ7IVKPRCNcq734xq886uF9TxYn3lHUGqnwAzupjPtTEZ8ms1 VZxf0oQoD5R0VPZ+kkxrw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1722910086; x= 1722996486; bh=mGAnkWQ+s4jKoLerEH+XWqyzB+onfTH+kswNnPYw2NI=; b=N gwEacazxcsomefO2b0McFUlpY3qKPN8WMILvDKLVjbz/pTYk5N07nD3C05pRZBC/ 5o8MGTDV4Sbo9fAJDCeHd3nEKPWj5KImnGBsJDlgRs6pKrMaioFh8duCqV8qr+7F wIcsai3DOwOI2nB90Nf5Y0ozuiPlzg7hftQUTjvmfmZBM9cpcJXZ4hXMNWRF9a3a SX+gxg7CHjOFk/1JdnolqnbKp00WR5il4zbBxV0KNh15QPQxpD2l1zppwHwzLyUb OqQYVZXMbgFWpuQGxEcJJCAtauJ5U4YbIFtXnGqu4OMSWifbJJdVIImiwKcuY/hU +R7J4mdgCYft4HGzCR9JA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrkeejgdehiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvvefufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpefgteefudfgteduueehteejhfeugf fgleeltedvveethfeuueejfedvgeelveehgfenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghvpdhnsggprh gtphhtthhopedt X-ME-Proxy: Feedback-ID: i5ec1447f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 5 Aug 2024 22:08:03 -0400 (EDT) From: "Luke D. Jones" To: platform-driver-x86@vger.kernel.org Cc: linux-kernel@vger.kernel.org, ilpo.jarvinen@linux.intel.com, hdegoede@redhat.com, corentin.chary@gmail.com, "Luke D. Jones" Subject: [PATCH v2 3/6] platform/x86: asus-armoury: add dgpu tgp control Date: Tue, 6 Aug 2024 14:07:44 +1200 Message-ID: <20240806020747.365042-4-luke@ljones.dev> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240806020747.365042-1-luke@ljones.dev> References: <20240806020747.365042-1-luke@ljones.dev> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Implement the dgpu TGP control under the asus-armoury module using the fw_attributes class. Signed-off-by: Luke D. Jones --- drivers/platform/x86/asus-armoury.c | 20 ++++++++++++++++++++ drivers/platform/x86/asus-armoury.h | 17 +++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 3 +++ 3 files changed, 40 insertions(+) diff --git a/drivers/platform/x86/asus-armoury.c b/drivers/platform/x86/asus-armoury.c index bb049ead00f9..31dbdacd8978 100644 --- a/drivers/platform/x86/asus-armoury.c +++ b/drivers/platform/x86/asus-armoury.c @@ -50,6 +50,9 @@ #define NVIDIA_BOOST_MAX 25 #define NVIDIA_TEMP_MIN 75 #define NVIDIA_TEMP_MAX 87 +#define NVIDIA_POWER_MIN 0 +#define NVIDIA_POWER_MAX 70 +#define NVIDIA_POWER_DEFAULT 70 /* Tunables provided by ASUS for gaming laptops */ struct rog_tunables { @@ -76,6 +79,11 @@ struct rog_tunables { u32 nv_temp_min; u32 nv_temp_max; u32 nv_temp_target; + + u32 dgpu_tgp_default; + u32 dgpu_tgp_min; + u32 dgpu_tgp_max; + u32 dgpu_tgp; }; static const struct class *fw_attr_class; @@ -474,6 +482,11 @@ ATTR_GROUP_ROG_TUNABLE(nv_dynamic_boost, "nv_dynamic_boost", ASUS_WMI_DEVID_NV_D ATTR_GROUP_ROG_TUNABLE(nv_temp_target, "nv_temp_target", ASUS_WMI_DEVID_NV_THERM_TARGET, nv_temp_default, nv_boost_min, nv_temp_max, 1, "Set the Nvidia max thermal limit"); +ATTR_GROUP_INT_VALUE_ONLY_RO(dgpu_base_tgp, "dgpu_base_tgp", ASUS_WMI_DEVID_DGPU_BASE_TGP, + "Read the base TGP value"); +ATTR_GROUP_ROG_TUNABLE(dgpu_tgp, "dgpu_tgp", ASUS_WMI_DEVID_DGPU_SET_TGP, dgpu_tgp_default, + dgpu_tgp_min, dgpu_tgp_max, 1, + "Set the additional TGP on top of the base TGP"); ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE, "0;1;2", "Show the current mode of charging"); @@ -501,6 +514,8 @@ static const struct asus_attr_group armoury_attr_groups[] = { { &ppt_fppt_attr_group, ASUS_WMI_DEVID_PPT_FPPT }, { &nv_dynamic_boost_attr_group, ASUS_WMI_DEVID_NV_DYN_BOOST }, { &nv_temp_target_attr_group, ASUS_WMI_DEVID_NV_THERM_TARGET }, + { &dgpu_base_tgp_attr_group, ASUS_WMI_DEVID_DGPU_BASE_TGP }, + { &dgpu_tgp_attr_group, ASUS_WMI_DEVID_DGPU_SET_TGP }, { &charge_mode_attr_group, ASUS_WMI_DEVID_CHARGE_MODE }, { &boot_sound_attr_group, ASUS_WMI_DEVID_BOOT_SOUND }, @@ -660,6 +675,11 @@ static void init_rog_tunables(struct rog_tunables *rog) rog->nv_temp_max = NVIDIA_TEMP_MIN; rog->nv_temp_max = NVIDIA_TEMP_MAX; rog->nv_temp_target = NVIDIA_TEMP_MIN; + + rog->dgpu_tgp_default = NVIDIA_POWER_DEFAULT; + rog->dgpu_tgp_min = NVIDIA_POWER_MIN; + rog->dgpu_tgp_max = NVIDIA_POWER_MAX; + rog->dgpu_tgp = NVIDIA_POWER_MAX; } static int __init asus_fw_init(void) diff --git a/drivers/platform/x86/asus-armoury.h b/drivers/platform/x86/asus-armoury.h index 146170f91e69..96d991383b8a 100644 --- a/drivers/platform/x86/asus-armoury.h +++ b/drivers/platform/x86/asus-armoury.h @@ -83,6 +83,19 @@ static ssize_t enum_type_show(struct kobject *kobj, struct kobj_attribute *attr, static struct kobj_attribute attr_##_attrname##_##_prop = \ __ASUS_ATTR_RO(_attrname, _prop) +/* Requires current_value show&|store */ +#define __ATTR_GROUP_INT_VALUE_ONLY(_attrname, _fsname, _dispname) \ + __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ + static struct kobj_attribute attr_##_attrname##_type = \ + __ASUS_ATTR_RO_AS(type, int_type_show); \ + static struct attribute *_attrname##_attrs[] = { \ + &attr_##_attrname##_current_value.attr, &attr_##_attrname##_display_name.attr, \ + &attr_##_attrname##_type.attr, NULL \ + }; \ + static const struct attribute_group _attrname##_attr_group = { \ + .name = _fsname, .attrs = _attrname##_attrs \ + } + /* Boolean style enumeration, base macro. Requires adding show/store */ #define __ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname) \ __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ @@ -97,6 +110,10 @@ static ssize_t enum_type_show(struct kobject *kobj, struct kobj_attribute *attr, .name = _fsname, .attrs = _attrname##_attrs \ } +#define ATTR_GROUP_INT_VALUE_ONLY_RO(_attrname, _fsname, _wmi, _dispname) \ + __ATTR_CURRENT_INT_RO(_attrname, _wmi); \ + __ATTR_GROUP_INT_VALUE_ONLY(_attrname, _fsname, _dispname) + #define ATTR_GROUP_BOOL_RO(_attrname, _fsname, _wmi, _dispname) \ __ATTR_CURRENT_INT_RO(_attrname, _wmi); \ __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname) diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index c164e656ae0b..3ce0c63be4c1 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -133,6 +133,9 @@ /* dgpu on/off */ #define ASUS_WMI_DEVID_DGPU 0x00090020 +#define ASUS_WMI_DEVID_DGPU_BASE_TGP 0x00120099 +#define ASUS_WMI_DEVID_DGPU_SET_TGP 0x00120098 + /* gpu mux switch, 0 = dGPU, 1 = Optimus */ #define ASUS_WMI_DEVID_GPU_MUX 0x00090016 #define ASUS_WMI_DEVID_GPU_MUX_VIVO 0x00090026 From patchwork Tue Aug 6 02:07:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 13754311 Received: from fout2-smtp.messagingengine.com (fout2-smtp.messagingengine.com [103.168.172.145]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5624F2E64A; Tue, 6 Aug 2024 02:08:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.145 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910093; cv=none; b=ezIDUHp6Ii4Kptn8GU+Kk+oGvVnkjVv7CAli6+UtQqWmkSAjUO8j6yqpKYAxaAUrTWpmL9/5lKCn46H4tuUQ4t6dv7gFzzbiNOcg3JwGWZlHNz67/RFsP3fOqoxh1HmHHiW+xgDylbil78AHUMAQkQtNdTqh/RLmKFM9w30mLfk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910093; c=relaxed/simple; bh=Yu7VkjGSRNITKTPdFuKK6Vgg5Y+JRTpvaRBfxtRtOb0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WzFM71L7fSyPFZphCMom4+ExDhHXnobxTDBmURtbRuk6C7LUkIMweYMl/R51vAp7D2WrW0CQRtCIz8Zo/H4TAawCtxFBOAgqmu2S70o9F/f7oiaECNiez3MnJy4UmiXxVJLApVahURENk0pEVeRW5MTntltWuexJxU11GSPFU/Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev; spf=none smtp.mailfrom=ljones.dev; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b=OkI1M9yv; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=he96+D3o; arc=none smtp.client-ip=103.168.172.145 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=ljones.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b="OkI1M9yv"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="he96+D3o" Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailfout.nyi.internal (Postfix) with ESMTP id 907C8138FC36; Mon, 5 Aug 2024 22:08:09 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 05 Aug 2024 22:08:09 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ljones.dev; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1722910089; x= 1722996489; bh=bBBcdwHVV+yQ+/NshzuL8M0iUusohPSYHkdYcEH7wUE=; b=O kI1M9yvJDFGAOE7v5+5U08CJL64ax4OzYbOi5NTDxuBDL/IqbpChdBTFpIS2g1ac tKeFyvr/K9hI3qh0ud6qO4dyp9/Ccscs0IABZ/M+20RIpocUsoitNYBF2MU7VFv5 G6FUkYpwtnVC688SYI749W+B3SdWazzVHuIyzymrwO4/i9NX0C/3Ce97RWnvl8+H n1+KkGPXwuuVdZaCCPVkXputXNbGhbyBuKgWwCSe6mMotqOnO55aBViuPBrMKD9F HRT0DCkSsD+HkNaE0xL+1OEx+bwdfZb/yi/SaMATlvE797aq3kThe7QdSIUyP5P5 9QuWFDMImvsEmq8EEpIIA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1722910089; x= 1722996489; bh=bBBcdwHVV+yQ+/NshzuL8M0iUusohPSYHkdYcEH7wUE=; b=h e96+D3o5+Svz+bb37jeE2jPgktk7OT9pXVHOBsVgRG056tBBqJlT7KwZSHxpH6mP Y4z15ZYRkVlOAMwHCCR3Mmom1ey9KUaf7e9hJlQAvR6mWTgoVxRgw1LiihOOmDDE 3b5Lk/HDpF06DuXml3zbR+zDeqfzvBpiQJP0aYISvvj8n9qSg2RBGIcPHWGbPo48 WtuwBC8X23fzaSEpaVwi4tlu6ivnmwMtqYMwunsv7PsT5m2g8F94SuhncmA4MhCG 1z6LtR6Von4V9ErvygEcNpWY/7c23sCrVwjqstQ2cvYG5y6a+6wevB2kyPFWPheo 55HUMyHyWzVdBsO7gEVaQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrkeejgdehiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvvefufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpefgteefudfgteduueehteejhfeugf fgleeltedvveethfeuueejfedvgeelveehgfenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghvpdhnsggprh gtphhtthhopedt X-ME-Proxy: Feedback-ID: i5ec1447f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 5 Aug 2024 22:08:06 -0400 (EDT) From: "Luke D. Jones" To: platform-driver-x86@vger.kernel.org Cc: linux-kernel@vger.kernel.org, ilpo.jarvinen@linux.intel.com, hdegoede@redhat.com, corentin.chary@gmail.com, "Luke D. Jones" Subject: [PATCH v2 4/6] platform/x86: asus-armoury: add apu-mem control support Date: Tue, 6 Aug 2024 14:07:45 +1200 Message-ID: <20240806020747.365042-5-luke@ljones.dev> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240806020747.365042-1-luke@ljones.dev> References: <20240806020747.365042-1-luke@ljones.dev> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Implement the APU memory size control under the asus-armoury module using the fw_attributes class. This allows the APU allocated memory size to be adjusted depending on the users priority. A reboot is required after change. Signed-off-by: Luke D. Jones --- drivers/platform/x86/asus-armoury.c | 115 +++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 1 + 2 files changed, 116 insertions(+) diff --git a/drivers/platform/x86/asus-armoury.c b/drivers/platform/x86/asus-armoury.c index 31dbdacd8978..412e75c652a4 100644 --- a/drivers/platform/x86/asus-armoury.c +++ b/drivers/platform/x86/asus-armoury.c @@ -462,6 +462,120 @@ static ssize_t egpu_enable_current_value_store(struct kobject *kobj, WMI_SHOW_INT(egpu_enable_current_value, "%d\n", ASUS_WMI_DEVID_EGPU); ATTR_GROUP_BOOL_CUSTOM(egpu_enable, "egpu_enable", "Enable the eGPU (also disables dGPU)"); +/* Device memory available to APU */ + +static ssize_t apu_mem_current_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int err; + u32 mem; + + err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_APU_MEM, &mem); + if (err) + return err; + + switch (mem) { + case 256: + mem = 0; + break; + case 258: + mem = 1; + break; + case 259: + mem = 2; + break; + case 260: + mem = 3; + break; + case 261: + mem = 4; + break; + case 262: + /* This is out of order and looks wrong but is correct */ + mem = 8; + break; + case 263: + mem = 5; + break; + case 264: + mem = 6; + break; + case 265: + mem = 7; + break; + default: + mem = 4; + break; + } + + return sysfs_emit(buf, "%d\n", mem); +} + +static ssize_t apu_mem_current_value_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int result, err; + u32 requested, mem; + + result = kstrtou32(buf, 10, &requested); + if (result) + return result; + + switch (requested) { + case 0: + mem = 0; + break; + case 1: + mem = 258; + break; + case 2: + mem = 259; + break; + case 3: + mem = 260; + break; + case 4: + mem = 261; + break; + case 5: + mem = 263; + break; + case 6: + mem = 264; + break; + case 7: + mem = 265; + break; + case 8: + /* This is outof order and looks wrong but is correct */ + mem = 262; + break; + default: + return -EIO; + } + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_APU_MEM, mem, &result); + if (err) { + pr_warn("Failed to set apu_mem: %d\n", err); + return err; + } + + pr_info("APU memory changed to %dGB, reboot required\n", requested); + sysfs_notify(kobj, NULL, attr->attr.name); + + asus_set_reboot_and_signal_event(); + + return count; +} + +static ssize_t apu_mem_possible_values_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "0;1;2;3;4;5;6;7;8\n"); +} +ATTR_GROUP_ENUM_CUSTOM(apu_mem, "apu_mem", "Set the available system memory for the APU to use"); + /* Simple attribute creation */ ATTR_GROUP_ROG_TUNABLE(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL, cpu_default, cpu_min, cpu_max, 1, "Set the CPU slow package limit"); @@ -516,6 +630,7 @@ static const struct asus_attr_group armoury_attr_groups[] = { { &nv_temp_target_attr_group, ASUS_WMI_DEVID_NV_THERM_TARGET }, { &dgpu_base_tgp_attr_group, ASUS_WMI_DEVID_DGPU_BASE_TGP }, { &dgpu_tgp_attr_group, ASUS_WMI_DEVID_DGPU_SET_TGP }, + { &apu_mem_attr_group, ASUS_WMI_DEVID_APU_MEM }, { &charge_mode_attr_group, ASUS_WMI_DEVID_CHARGE_MODE }, { &boot_sound_attr_group, ASUS_WMI_DEVID_BOOT_SOUND }, diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 3ce0c63be4c1..287206a03763 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -135,6 +135,7 @@ #define ASUS_WMI_DEVID_DGPU_BASE_TGP 0x00120099 #define ASUS_WMI_DEVID_DGPU_SET_TGP 0x00120098 +#define ASUS_WMI_DEVID_APU_MEM 0x000600C1 /* gpu mux switch, 0 = dGPU, 1 = Optimus */ #define ASUS_WMI_DEVID_GPU_MUX 0x00090016 From patchwork Tue Aug 6 02:07:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 13754312 Received: from fout2-smtp.messagingengine.com (fout2-smtp.messagingengine.com [103.168.172.145]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8897C38397; Tue, 6 Aug 2024 02:08:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.145 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910095; cv=none; b=MMygdhJw8QCEdHpn6bW4K++9+O83c+63ljwxQI86I6zkThs78qGW5fYhWV8TOUctUbZz/fq0IQ4fzXnSZN1MuUC0ttYTohgTmNwlJ+jm9HjAinK9WzyrvExs3mYEAj3bmvCTLGNR86aDvgHBiGA1GdivOkUiyNenpkHTDFLSGcA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910095; c=relaxed/simple; bh=kMqzAKEsG0EZcapDDZVghw91lFSIJx5D0VOn5BZ22O0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QamBwO+AOmt0ri1zJchG6giCOJXKMzKeGU6T4jXu1RSidZ5ROLMvtiCqclWWWWGMSirFlBrFuxW2YZgEOOzA8GLLjPEPEkdVHWgu+riowyi4Ysuaqw+VHXhQK2v4GZ5t4XcPS8frd8nq7T3FXvfPa45qT0NXrsDoslq2CxYYXKs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev; spf=none smtp.mailfrom=ljones.dev; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b=h1bVHYs2; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=luPL4pqc; arc=none smtp.client-ip=103.168.172.145 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=ljones.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b="h1bVHYs2"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="luPL4pqc" Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailfout.nyi.internal (Postfix) with ESMTP id DAEAF1385A02; Mon, 5 Aug 2024 22:08:12 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 05 Aug 2024 22:08:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ljones.dev; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1722910092; x= 1722996492; bh=nCg2zpOayykf84IC3wUZ76xe5f8FcKwty3iTfzp3zAc=; b=h 1bVHYs2q61q0lkq139G0dlTBF7AghtdGv+ZPiVDyIF7zt93f1V9wN3V+l55IzDDw d+7kkjAlKs7JL8K5A+tArhmb5JHwKzwyBebi6zKHaymEJIrYg1DAUl4pVOQh8L8r tUrM7Hcjo69UKh3yj38XABkLwUnfxuY7Ve+oqp9lp4v1SkTFqOjSDPAzFN1lYc3w 98OT1P586OCERujKuzvhG988HYhi57LObcyY7aEyqNhwgd8jNCu3vA7ux8yVQ23m NgbGbquQckpi7U1IuW2cNTPe7vRnqHD/eH+5uXmbnps2HRm1Gir0R1xZagto21k3 Uh4szTF3dPZpxtogEH4NA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1722910092; x= 1722996492; bh=nCg2zpOayykf84IC3wUZ76xe5f8FcKwty3iTfzp3zAc=; b=l uPL4pqcZPS9YWwRB+I4a7iMpkD5fL0Rjg8igwV+y6DMTpx6530Z+dkskAI4GG1+Z /sz+6jCO9Y/il1Jm2i3h+idz+O7mTxIQ1qf5v8WmcnEWwNMMW8STUYch2XkMQ1iZ LmvRlLU+IAyRHQOGUHdtFX2JYD/0b42Vo5Zb6dqlfu01slNe/7sYSZ4CPszc3HJ0 d2vovgaLRk2HbMk/Z5vS1SkXH3tC9tq5NokaoyRQdg63FMSEvdJKdEN64KU1cuRY x6iONivTSx+I9GUQV9uG7E5zK6ShB2I6m1NwVDZ117HqZMkddaYQKVkJYpqVRNwB IH3Xy7uwdHyz35YgdNhGQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrkeejgdehiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvvefufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpefgteefudfgteduueehteejhfeugf fgleeltedvveethfeuueejfedvgeelveehgfenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghvpdhnsggprh gtphhtthhopedt X-ME-Proxy: Feedback-ID: i5ec1447f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 5 Aug 2024 22:08:09 -0400 (EDT) From: "Luke D. Jones" To: platform-driver-x86@vger.kernel.org Cc: linux-kernel@vger.kernel.org, ilpo.jarvinen@linux.intel.com, hdegoede@redhat.com, corentin.chary@gmail.com, "Luke D. Jones" Subject: [PATCH v2 5/6] platform/x86: asus-armoury: add core count control Date: Tue, 6 Aug 2024 14:07:46 +1200 Message-ID: <20240806020747.365042-6-luke@ljones.dev> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240806020747.365042-1-luke@ljones.dev> References: <20240806020747.365042-1-luke@ljones.dev> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Implement Intel core enablement under the asus-armoury module using the fw_attributes class. This allows users to enable or disable preformance or efficiency cores depending on their requirements. After change a reboot is required. Signed-off-by: Luke D. Jones --- drivers/platform/x86/asus-armoury.c | 208 ++++++++++++++++++++- drivers/platform/x86/asus-armoury.h | 29 +++ include/linux/platform_data/x86/asus-wmi.h | 4 + 3 files changed, 240 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-armoury.c b/drivers/platform/x86/asus-armoury.c index 412e75c652a4..592ebea35ad5 100644 --- a/drivers/platform/x86/asus-armoury.c +++ b/drivers/platform/x86/asus-armoury.c @@ -39,6 +39,18 @@ #define ASUS_MINI_LED_2024_STRONG 0x01 #define ASUS_MINI_LED_2024_OFF 0x02 +enum cpu_core_type { + CPU_CORE_PERF = 0, + CPU_CORE_POWER, +}; + +enum cpu_core_value { + CPU_CORE_DEFAULT = 0, + CPU_CORE_MIN, + CPU_CORE_MAX, + CPU_CORE_CURRENT, +}; + /* Default limits for tunables available on ASUS ROG laptops */ #define PPT_CPU_LIMIT_MIN 5 #define PPT_CPU_LIMIT_MAX 150 @@ -84,6 +96,10 @@ struct rog_tunables { u32 dgpu_tgp_min; u32 dgpu_tgp_max; u32 dgpu_tgp; + + u32 min_perf_cores; + u32 max_perf_cores; + u32 max_power_cores; }; static const struct class *fw_attr_class; @@ -148,7 +164,9 @@ static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); static bool asus_bios_requires_reboot(struct kobj_attribute *attr) { return !strcmp(attr->attr.name, "gpu_mux_mode") || - !strcmp(attr->attr.name, "panel_hd_mode"); + !strcmp(attr->attr.name, "cores_performance") || + !strcmp(attr->attr.name, "cores_efficiency") || + !strcmp(attr->attr.name, "panel_hd_mode"); } /** @@ -576,6 +594,191 @@ static ssize_t apu_mem_possible_values_show(struct kobject *kobj, } ATTR_GROUP_ENUM_CUSTOM(apu_mem, "apu_mem", "Set the available system memory for the APU to use"); +static int init_max_cpu_cores(void) +{ + u32 cores; + int err; + + asus_armoury.rog_tunables->min_perf_cores = 4; + asus_armoury.rog_tunables->max_perf_cores = 4; + asus_armoury.rog_tunables->max_power_cores = 8; + + err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES_MAX, &cores); + if (err) + return err; + + cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT; + asus_armoury.rog_tunables->max_power_cores = (cores & 0xff00) >> 8; + asus_armoury.rog_tunables->max_perf_cores = cores & 0xff; + + return 0; +} + +static ssize_t cores_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf, + enum cpu_core_type core_type, + enum cpu_core_value core_value) +{ + u32 cores; + int err; + + switch (core_value) { + case CPU_CORE_DEFAULT: + case CPU_CORE_MAX: + if (core_type == CPU_CORE_PERF) + return sysfs_emit(buf, "%d\n", asus_armoury.rog_tunables->max_perf_cores); + else + return sysfs_emit(buf, "%d\n", asus_armoury.rog_tunables->max_power_cores); + case CPU_CORE_MIN: + if (core_type == CPU_CORE_PERF) + return sysfs_emit(buf, "%d\n", asus_armoury.rog_tunables->min_perf_cores); + else + return sysfs_emit(buf, "%d\n", 0); + default: + break; + } + + err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES, &cores); + if (err) + return err; + + cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT; + if (core_type == CPU_CORE_PERF) + cores &= 0xff; + else + cores = (cores & 0xff00) >> 8; + return sysfs_emit(buf, "%d\n", cores); +} + +static ssize_t cores_current_value_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, + enum cpu_core_type core_type) +{ + int result, err; + u32 cores, currentv, min, max; + + result = kstrtou32(buf, 10, &cores); + if (result) + return result; + + if (core_type == CPU_CORE_PERF) { + min = asus_armoury.rog_tunables->min_perf_cores; + max = asus_armoury.rog_tunables->max_perf_cores; + } else { + min = 0; + max = asus_armoury.rog_tunables->max_power_cores; + } + if (cores < min || cores > max) + return -EINVAL; + + err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES, ¤tv); + if (err) + return err; + + if (core_type == CPU_CORE_PERF) + cores |= (currentv & 0xff00); + else + cores |= currentv & 0xff; + + if (cores == currentv) + return 0; + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_CORES, cores, &result); + if (err) { + pr_warn("Failed to set CPU core count: %d\n", err); + return err; + } + + if (result > 1) { + pr_warn("Failed to set CPU core count (result): 0x%x\n", result); + return -EIO; + } + + pr_info("CPU core count changed, reboot required\n"); + sysfs_notify(kobj, NULL, attr->attr.name); + asus_set_reboot_and_signal_event(); + + return 0; +} + +static ssize_t cores_performance_min_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_MIN); +} + +static ssize_t cores_performance_max_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_MAX); +} + +static ssize_t cores_performance_default_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_DEFAULT); +} + +static ssize_t cores_performance_current_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_CURRENT); +} + +static ssize_t cores_performance_current_value_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int err; + + err = cores_current_value_store(kobj, attr, buf, CPU_CORE_PERF); + if (err) + return err; + + return count; +} +ATTR_GROUP_CORES_RW(cores_performance, "cores_performance", + "Set the max available performance cores"); + +static ssize_t cores_efficiency_min_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_MIN); +} + +static ssize_t cores_efficiency_max_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_MAX); +} + +static ssize_t cores_efficiency_default_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_DEFAULT); +} + +static ssize_t cores_efficiency_current_value_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_CURRENT); +} + +static ssize_t cores_efficiency_current_value_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int err; + + err = cores_current_value_store(kobj, attr, buf, CPU_CORE_POWER); + if (err) + return err; + + return count; +} +ATTR_GROUP_CORES_RW(cores_efficiency, "cores_efficiency", + "Set the max available efficiency cores"); + /* Simple attribute creation */ ATTR_GROUP_ROG_TUNABLE(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL, cpu_default, cpu_min, cpu_max, 1, "Set the CPU slow package limit"); @@ -631,6 +834,8 @@ static const struct asus_attr_group armoury_attr_groups[] = { { &dgpu_base_tgp_attr_group, ASUS_WMI_DEVID_DGPU_BASE_TGP }, { &dgpu_tgp_attr_group, ASUS_WMI_DEVID_DGPU_SET_TGP }, { &apu_mem_attr_group, ASUS_WMI_DEVID_APU_MEM }, + { &cores_efficiency_attr_group, ASUS_WMI_DEVID_CORES_MAX }, + { &cores_performance_attr_group, ASUS_WMI_DEVID_CORES_MAX }, { &charge_mode_attr_group, ASUS_WMI_DEVID_CHARGE_MODE }, { &boot_sound_attr_group, ASUS_WMI_DEVID_BOOT_SOUND }, @@ -811,6 +1016,7 @@ static int __init asus_fw_init(void) return -ENOMEM; } init_rog_tunables(asus_armoury.rog_tunables); + init_max_cpu_cores(); err = asus_fw_attr_add(); mutex_unlock(&asus_armoury.mutex); diff --git a/drivers/platform/x86/asus-armoury.h b/drivers/platform/x86/asus-armoury.h index 96d991383b8a..da585a180125 100644 --- a/drivers/platform/x86/asus-armoury.h +++ b/drivers/platform/x86/asus-armoury.h @@ -154,6 +154,35 @@ static ssize_t enum_type_show(struct kobject *kobj, struct kobj_attribute *attr, .name = _fsname, .attrs = _attrname##_attrs \ } +/* CPU core attributes need a little different in setup */ +#define ATTR_GROUP_CORES_RW(_attrname, _fsname, _dispname) \ +__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", 1); \ +__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ +static struct kobj_attribute attr_##_attrname##_current_value = \ + __ASUS_ATTR_RW(_attrname, current_value); \ +static struct kobj_attribute attr_##_attrname##_default_value = \ + __ASUS_ATTR_RO(_attrname, default_value); \ +static struct kobj_attribute attr_##_attrname##_min_value = \ + __ASUS_ATTR_RO(_attrname, min_value); \ +static struct kobj_attribute attr_##_attrname##_max_value = \ + __ASUS_ATTR_RO(_attrname, max_value); \ +static struct kobj_attribute attr_##_attrname##_type = \ + __ASUS_ATTR_RO_AS(type, int_type_show); \ +static struct attribute *_attrname##_attrs[] = { \ + &attr_##_attrname##_current_value.attr, \ + &attr_##_attrname##_default_value.attr, \ + &attr_##_attrname##_min_value.attr, \ + &attr_##_attrname##_max_value.attr, \ + &attr_##_attrname##_scalar_increment.attr, \ + &attr_##_attrname##_display_name.attr, \ + &attr_##_attrname##_type.attr, \ + NULL \ +}; \ +static const struct attribute_group _attrname##_attr_group = { \ + .name = _fsname, \ + .attrs = _attrname##_attrs \ +} + /* * ROG PPT attributes need a little different in setup as they * require rog_tunables members. diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 287206a03763..2e7509ab5be0 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -133,6 +133,10 @@ /* dgpu on/off */ #define ASUS_WMI_DEVID_DGPU 0x00090020 +/* Intel E-core and P-core configuration in a format 0x0[E]0[P] */ +#define ASUS_WMI_DEVID_CORES 0x001200D2 + /* Maximum Intel E-core and P-core availability */ +#define ASUS_WMI_DEVID_CORES_MAX 0x001200D3 #define ASUS_WMI_DEVID_DGPU_BASE_TGP 0x00120099 #define ASUS_WMI_DEVID_DGPU_SET_TGP 0x00120098 #define ASUS_WMI_DEVID_APU_MEM 0x000600C1 From patchwork Tue Aug 6 02:07:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 13754313 Received: from fout2-smtp.messagingengine.com (fout2-smtp.messagingengine.com [103.168.172.145]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 588A93C466; Tue, 6 Aug 2024 02:08:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.145 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910099; cv=none; b=KPlKIxV3WDMNv8UPBpKThxssE3Y5k0+6GZW0JsHLO5V613qPBe8eKwmIlqExeU4IIZdPhnpWuXBDxqiEZa/r32VMWzoAfhvUjsZpnlzHtSYbppNGr84ArB4tZfb0QKVNek3OE2QivKII/BBY5B7cz9EJBgPKKRYid1qusp03hRc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722910099; c=relaxed/simple; bh=927Y/8lx1xKRkyIL6RFt+6V+dxo/1qqK9xm26FW+gEM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=atspxwq0FDx9rsq+y+AoBvSd5eK2rl5C+fFPtSRzdEpCocoV53kFoE68myq1LZ5igxlFiANh2QFr0ZlCAzwc3hdKorBS0znXqMBbE6KvlFZYyfYlokvCBvsS/0HeMg/nGpDPj1//Wy8qUhKz5dzl6PfQ4JMNlDF8xJxfGSjwxus= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev; spf=none smtp.mailfrom=ljones.dev; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b=AU3Qd8Y0; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=rTM8LKfD; arc=none smtp.client-ip=103.168.172.145 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ljones.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=ljones.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ljones.dev header.i=@ljones.dev header.b="AU3Qd8Y0"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="rTM8LKfD" Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailfout.nyi.internal (Postfix) with ESMTP id 69DA4138FC3B; Mon, 5 Aug 2024 22:08:16 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Mon, 05 Aug 2024 22:08:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ljones.dev; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1722910096; x= 1722996496; bh=hepVkLOIOqBtH1VWXZfEsOU74Sztw04bD8peTe5i/40=; b=A U3Qd8Y0Iaxl48FWPvgJXp3XB4Unq/+1SmkxRo2/dsFXNjeAGVZoPIZ+w1+oD1kYR mk0M8TA4J6Ya5UtxONDX8nxuClooff+kxNxnFdP5N3D/HW+2EwvbPYpD3dAh5Mxw 9x/My7WJTylAWykBe/e2CfKL7wLCky7eaou7qpzl7gcdxnK68nCaCgtV8wzw21s3 bB5w1B589/wCdE4AjYTguQGmxu/vaGL8NXyWfoYJgZaeI53/s3nxZrgEXZ566F22 JlU4O3Oxl3hm1DAOQ0Ub+9tHx6RoHvJLCLbkFta5SqJhjUy7buV/XxA9fZtdxRe7 68yefJ/F7b/yz9rXh5LKA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1722910096; x= 1722996496; bh=hepVkLOIOqBtH1VWXZfEsOU74Sztw04bD8peTe5i/40=; b=r TM8LKfDEcn9rYO3p57onQ4I08m5t5UscOdmo9Ur9UIl6+CClEF5IvEXDzX9SfXyi GIv6LZbMHnS5FvQ9xKD7G/DWBjoqARM5Vf3UEV8ENR3z/+raAbvdlA2V+nDBKFuv Y/EGTofUggF4p7qzLnNK0UGB15grfOfGxZY/jh59yFBsiWodzYS1b2alTYH3aj5B IRAIM2d40/ZmFbwUTnX9s2txLmor8fLH7z9d9s2xjAeLn72JkKuMJO+XqktaJFlY QXQB79pVAI2Gq4PoMmb5ql9XL6Zi1nlXsNWH4wfEvrz6vzcpUdsqBICOZHOPPiNm 17qhFH0Teg548/Lcb5m0w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrkeejgdehiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvvefufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpefgteefudfgteduueehteejhfeugf fgleeltedvveethfeuueejfedvgeelveehgfenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghvpdhnsggprh gtphhtthhopedt X-ME-Proxy: Feedback-ID: i5ec1447f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 5 Aug 2024 22:08:13 -0400 (EDT) From: "Luke D. Jones" To: platform-driver-x86@vger.kernel.org Cc: linux-kernel@vger.kernel.org, ilpo.jarvinen@linux.intel.com, hdegoede@redhat.com, corentin.chary@gmail.com, "Luke D. Jones" Subject: [PATCH v2 6/6] asus-wmi: deprecate bios features Date: Tue, 6 Aug 2024 14:07:47 +1200 Message-ID: <20240806020747.365042-7-luke@ljones.dev> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240806020747.365042-1-luke@ljones.dev> References: <20240806020747.365042-1-luke@ljones.dev> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 With the existence of the asus-bioscfg module the attributes no-longer need to live under the /sys/devices/platform/asus-nb-wmi/ path. Deprecate all those that were implemented in asus-bioscfg with the goal of removing them fully in the next LTS cycle. Signed-off-by: Luke D. Jones --- .../ABI/testing/sysfs-platform-asus-wmi | 17 +++ drivers/platform/x86/Kconfig | 8 ++ drivers/platform/x86/asus-wmi.c | 125 ++++++++++++++---- 3 files changed, 124 insertions(+), 26 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi index 28144371a0f1..765d50b0d9df 100644 --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi @@ -63,6 +63,7 @@ Date: Aug 2022 KernelVersion: 6.1 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Switch the GPU hardware MUX mode. Laptops with this feature can can be toggled to boot with only the dGPU (discrete mode) or in standard Optimus/Hybrid mode. On switch a reboot is required: @@ -75,6 +76,7 @@ Date: Aug 2022 KernelVersion: 5.17 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Disable discrete GPU: * 0 - Enable dGPU, * 1 - Disable dGPU @@ -84,6 +86,7 @@ Date: Aug 2022 KernelVersion: 5.17 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Enable the external GPU paired with ROG X-Flow laptops. Toggling this setting will also trigger ACPI to disable the dGPU: @@ -95,6 +98,7 @@ Date: Aug 2022 KernelVersion: 5.17 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Enable an LCD response-time boost to reduce or remove ghosting: * 0 - Disable, * 1 - Enable @@ -104,6 +108,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Get the current charging mode being used: * 1 - Barrel connected charger, * 2 - USB-C charging @@ -114,6 +119,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Show if the egpu (XG Mobile) is correctly connected: * 0 - False, * 1 - True @@ -123,6 +129,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Change the mini-LED mode: * 0 - Single-zone, * 1 - Multi-zone @@ -133,6 +140,7 @@ Date: Apr 2024 KernelVersion: 6.10 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON List the available mini-led modes. What: /sys/devices/platform//ppt_pl1_spl @@ -140,6 +148,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set the Package Power Target total of CPU: PL1 on Intel, SPL on AMD. Shown on Intel+Nvidia or AMD+Nvidia based systems: @@ -150,6 +159,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set the Slow Package Power Tracking Limit of CPU: PL2 on Intel, SPPT, on AMD. Shown on Intel+Nvidia or AMD+Nvidia based systems: @@ -160,6 +170,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set the Fast Package Power Tracking Limit of CPU. AMD+Nvidia only: * min=5, max=250 @@ -168,6 +179,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set the APU SPPT limit. Shown on full AMD systems only: * min=5, max=130 @@ -176,6 +188,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set the platform SPPT limit. Shown on full AMD systems only: * min=5, max=130 @@ -184,6 +197,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set the dynamic boost limit of the Nvidia dGPU: * min=5, max=25 @@ -192,6 +206,7 @@ Date: Jun 2023 KernelVersion: 6.5 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set the target temperature limit of the Nvidia dGPU: * min=75, max=87 @@ -200,6 +215,7 @@ Date: Apr 2024 KernelVersion: 6.10 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set if the BIOS POST sound is played on boot. * 0 - False, * 1 - True @@ -209,6 +225,7 @@ Date: Apr 2024 KernelVersion: 6.10 Contact: "Luke Jones" Description: + DEPRECATED, WILL BE REMOVED SOON Set if the MCU can go in to low-power mode on system sleep * 0 - False, * 1 - True diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 8ecc73ef2670..bafe5883805b 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -301,6 +301,14 @@ config ASUS_WMI To compile this driver as a module, choose M here: the module will be called asus-wmi. +config ASUS_WMI_BIOS + bool "BIOS option support in WMI platform (DEPRECATED)" + depends on ASUS_WMI + help + Say Y to expose the configurable BIOS options through the asus-wmi + driver. This can be used with or without the new asus-bios driver as + the options are the same but the asus-bios driver has more features. + config ASUS_NB_WMI tristate "Asus Notebook WMI Driver" depends on ASUS_WMI diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 165e7932c371..5ecd47f23c83 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -290,11 +290,12 @@ struct asus_wmi { u8 fan_boost_mode_mask; u8 fan_boost_mode; + + /* Tunables provided by ASUS for gaming laptops */ + #if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) bool egpu_enable_available; bool dgpu_disable_available; u32 gpu_mux_dev; - - /* Tunables provided by ASUS for gaming laptops */ u32 ppt_pl2_sppt; u32 ppt_pl1_spl; u32 ppt_apu_sppt; @@ -302,6 +303,9 @@ struct asus_wmi { u32 ppt_fppt; u32 nv_dynamic_boost; u32 nv_temp_target; + bool panel_overdrive_available; + u32 mini_led_dev_id; + #endif u32 kbd_rgb_dev; bool kbd_rgb_state_available; @@ -320,9 +324,6 @@ struct asus_wmi { // The RSOC controls the maximum charging percentage. bool battery_rsoc_available; - bool panel_overdrive_available; - u32 mini_led_dev_id; - struct hotplug_slot hotplug_slot; struct mutex hotplug_lock; struct mutex wmi_lock; @@ -336,6 +337,15 @@ struct asus_wmi { struct asus_wmi_driver *driver; }; +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) +static void asus_wmi_show_deprecated(void) +{ + pr_notice_once("Accessing attributes through /sys/bus/platform/asus_wmi is " + + "deprecated and will be removed in a future release. Please switch " + + "over to /sys/class/firmware_attributes.\n"); +} +#endif + /* WMI ************************************************************************/ static int asus_wmi_evaluate_method3(u32 method_id, @@ -732,6 +742,7 @@ static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus) } /* Charging mode, 1=Barrel, 2=USB ******************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t charge_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -742,12 +753,16 @@ static ssize_t charge_mode_show(struct device *dev, if (result < 0) return result; + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", value & 0xff); } static DEVICE_ATTR_RO(charge_mode); +#endif /* dGPU ********************************************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t dgpu_disable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -758,6 +773,8 @@ static ssize_t dgpu_disable_show(struct device *dev, if (result < 0) return result; + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", result); } @@ -811,8 +828,10 @@ static ssize_t dgpu_disable_store(struct device *dev, return count; } static DEVICE_ATTR_RW(dgpu_disable); +#endif /* eGPU ********************************************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t egpu_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -823,6 +842,8 @@ static ssize_t egpu_enable_show(struct device *dev, if (result < 0) return result; + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", result); } @@ -879,8 +900,10 @@ static ssize_t egpu_enable_store(struct device *dev, return count; } static DEVICE_ATTR_RW(egpu_enable); +#endif /* Is eGPU connected? *********************************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t egpu_connected_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -891,12 +914,16 @@ static ssize_t egpu_connected_show(struct device *dev, if (result < 0) return result; + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", result); } static DEVICE_ATTR_RO(egpu_connected); +#endif /* gpu mux switch *************************************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t gpu_mux_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -907,6 +934,8 @@ static ssize_t gpu_mux_mode_show(struct device *dev, if (result < 0) return result; + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", result); } @@ -965,6 +994,7 @@ static ssize_t gpu_mux_mode_store(struct device *dev, return count; } static DEVICE_ATTR_RW(gpu_mux_mode); +#endif /* TUF Laptop Keyboard RGB Modes **********************************************/ static ssize_t kbd_rgb_mode_store(struct device *dev, @@ -1088,6 +1118,7 @@ static const struct attribute_group *kbd_rgb_mode_groups[] = { }; /* Tunable: PPT: Intel=PL1, AMD=SPPT *****************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t ppt_pl2_sppt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1126,6 +1157,8 @@ static ssize_t ppt_pl2_sppt_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%u\n", asus->ppt_pl2_sppt); } static DEVICE_ATTR_RW(ppt_pl2_sppt); @@ -1168,6 +1201,8 @@ static ssize_t ppt_pl1_spl_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%u\n", asus->ppt_pl1_spl); } static DEVICE_ATTR_RW(ppt_pl1_spl); @@ -1211,6 +1246,8 @@ static ssize_t ppt_fppt_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%u\n", asus->ppt_fppt); } static DEVICE_ATTR_RW(ppt_fppt); @@ -1254,6 +1291,8 @@ static ssize_t ppt_apu_sppt_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%u\n", asus->ppt_apu_sppt); } static DEVICE_ATTR_RW(ppt_apu_sppt); @@ -1297,6 +1336,8 @@ static ssize_t ppt_platform_sppt_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%u\n", asus->ppt_platform_sppt); } static DEVICE_ATTR_RW(ppt_platform_sppt); @@ -1340,6 +1381,8 @@ static ssize_t nv_dynamic_boost_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%u\n", asus->nv_dynamic_boost); } static DEVICE_ATTR_RW(nv_dynamic_boost); @@ -1383,11 +1426,15 @@ static ssize_t nv_temp_target_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%u\n", asus->nv_temp_target); } static DEVICE_ATTR_RW(nv_temp_target); +#endif /* Ally MCU Powersave ********************************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t mcu_powersave_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1398,6 +1445,8 @@ static ssize_t mcu_powersave_show(struct device *dev, if (result < 0) return result; + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", result); } @@ -1433,6 +1482,7 @@ static ssize_t mcu_powersave_store(struct device *dev, return count; } static DEVICE_ATTR_RW(mcu_powersave); +#endif /* Battery ********************************************************************/ @@ -2296,6 +2346,7 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus) } /* Panel Overdrive ************************************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t panel_od_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -2306,6 +2357,8 @@ static ssize_t panel_od_show(struct device *dev, if (result < 0) return result; + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", result); } @@ -2342,9 +2395,10 @@ static ssize_t panel_od_store(struct device *dev, return count; } static DEVICE_ATTR_RW(panel_od); +#endif /* Bootup sound ***************************************************************/ - +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t boot_sound_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -2355,6 +2409,8 @@ static ssize_t boot_sound_show(struct device *dev, if (result < 0) return result; + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", result); } @@ -2390,8 +2446,10 @@ static ssize_t boot_sound_store(struct device *dev, return count; } static DEVICE_ATTR_RW(boot_sound); +#endif /* Mini-LED mode **************************************************************/ +#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) static ssize_t mini_led_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -2422,6 +2480,8 @@ static ssize_t mini_led_mode_show(struct device *dev, } } + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "%d\n", value); } @@ -2492,10 +2552,13 @@ static ssize_t available_mini_led_mode_show(struct device *dev, return sysfs_emit(buf, "0 1 2\n"); } + asus_wmi_show_deprecated(); + return sysfs_emit(buf, "0\n"); } static DEVICE_ATTR_RO(available_mini_led_mode); +#endif /* Quirks *********************************************************************/ @@ -4477,27 +4540,29 @@ static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_touchpad.attr, - &dev_attr_charge_mode.attr, - &dev_attr_egpu_enable.attr, - &dev_attr_egpu_connected.attr, - &dev_attr_dgpu_disable.attr, - &dev_attr_gpu_mux_mode.attr, &dev_attr_lid_resume.attr, &dev_attr_als_enable.attr, &dev_attr_fan_boost_mode.attr, &dev_attr_throttle_thermal_policy.attr, - &dev_attr_ppt_pl2_sppt.attr, - &dev_attr_ppt_pl1_spl.attr, - &dev_attr_ppt_fppt.attr, - &dev_attr_ppt_apu_sppt.attr, - &dev_attr_ppt_platform_sppt.attr, - &dev_attr_nv_dynamic_boost.attr, - &dev_attr_nv_temp_target.attr, - &dev_attr_mcu_powersave.attr, - &dev_attr_boot_sound.attr, - &dev_attr_panel_od.attr, - &dev_attr_mini_led_mode.attr, - &dev_attr_available_mini_led_mode.attr, + #if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + &dev_attr_charge_mode.attr, + &dev_attr_egpu_enable.attr, + &dev_attr_egpu_connected.attr, + &dev_attr_dgpu_disable.attr, + &dev_attr_gpu_mux_mode.attr, + &dev_attr_ppt_pl2_sppt.attr, + &dev_attr_ppt_pl1_spl.attr, + &dev_attr_ppt_fppt.attr, + &dev_attr_ppt_apu_sppt.attr, + &dev_attr_ppt_platform_sppt.attr, + &dev_attr_nv_dynamic_boost.attr, + &dev_attr_nv_temp_target.attr, + &dev_attr_mcu_powersave.attr, + &dev_attr_boot_sound.attr, + &dev_attr_panel_od.attr, + &dev_attr_mini_led_mode.attr, + &dev_attr_available_mini_led_mode.attr, + #endif NULL }; @@ -4519,7 +4584,11 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, devid = ASUS_WMI_DEVID_LID_RESUME; else if (attr == &dev_attr_als_enable.attr) devid = ASUS_WMI_DEVID_ALS_ENABLE; - else if (attr == &dev_attr_charge_mode.attr) + else if (attr == &dev_attr_fan_boost_mode.attr) + ok = asus->fan_boost_mode_available; + + #if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + if (attr == &dev_attr_charge_mode.attr) devid = ASUS_WMI_DEVID_CHARGE_MODE; else if (attr == &dev_attr_egpu_enable.attr) ok = asus->egpu_enable_available; @@ -4557,6 +4626,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, ok = asus->mini_led_dev_id != 0; else if (attr == &dev_attr_available_mini_led_mode.attr) ok = asus->mini_led_dev_id != 0; + #endif /* CONFIG_ASUS_WMI_BIOS */ if (devid != -1) { ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); @@ -4797,6 +4867,7 @@ static int asus_wmi_add(struct platform_device *pdev) goto fail_platform; /* ensure defaults for tunables */ + #if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) asus->ppt_pl2_sppt = 5; asus->ppt_pl1_spl = 5; asus->ppt_apu_sppt = 5; @@ -4808,8 +4879,6 @@ static int asus_wmi_add(struct platform_device *pdev) asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); - asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) - && dmi_check_system(asus_ally_mcu_quirk); if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE)) asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; @@ -4820,6 +4889,10 @@ static int asus_wmi_add(struct platform_device *pdev) asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX; else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX_VIVO)) asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX_VIVO; + #endif + + asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) + && dmi_check_system(asus_ally_mcu_quirk); if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE)) asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE;