From: "Derek J. Clark" <derekjohn.clark@gmail.com>
To: "Hans de Goede" <hdegoede@redhat.com>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
Cc: Armin Wolf <W_Armin@gmx.de>, Jonathan Corbet <corbet@lwn.net>,
Mario Limonciello <superm1@kernel.org>,
Luke Jones <luke@ljones.dev>, Xino Ni <nijs1@lenovo.com>,
Zhixin Zhang <zhangzx36@lenovo.com>,
Mia Shao <shaohz1@lenovo.com>,
Mark Pearson <mpearson-lenovo@squebb.ca>,
"Pierre-Loup A . Griffais" <pgriffais@valvesoftware.com>,
"Cody T . -H . Chiu" <codyit@gmail.com>,
John Martens <johnfanv2@gmail.com>,
"Derek J . Clark" <derekjohn.clark@gmail.com>,
platform-driver-x86@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v3 2/4] platform/x86: Add Lenovo Gamezone WMI Driver
Date: Tue, 25 Feb 2025 13:59:53 -0800 [thread overview]
Message-ID: <20250225220037.16073-3-derekjohn.clark@gmail.com> (raw)
In-Reply-To: <20250225220037.16073-1-derekjohn.clark@gmail.com>
Adds lenovo-wmi-gamezone.c which provides a driver for the Lenovo
Gamezone WMI interface that comes on Lenovo "Gaming Series" hardware.
Provides ACPI platform profiles over WMI.
Adds lenovo-wmi.h and lenovo-wmi.c which provide helper functions for
wmidev_evaluate_method as well as prototypes for exported functions.
v3:
- Use notifier chain to report platform profile changes to any
subscribed drivers.
- Adds THERMAL_MODE_EVENT GUID and .notify function to trigger notifier
chain.
- Adds support for Extreme Mode profile on supported hardware, as well
as a DMI quirk table for some devices that report extreme mode version
support but so not have it fully implemented.
- Update to include recent changes to platform-profile.
v2:
- Use devm_kmalloc to ensure driver can be instanced, remove global
reference.
- Ensure reverse Christmas tree for all variable declarations.
- Remove extra whitespace.
- Use guard(mutex) in all mutex instances, global mutex.
- Use pr_fmt instead of adding the driver name to each pr_err.
- Remove noisy pr_info usage.
- Rename gamezone_wmi to lenovo_wmi_gz_priv and gz_wmi to priv.
- Remove GZ_WMI symbol exporting.
Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
---
MAINTAINERS | 3 +
drivers/platform/x86/Kconfig | 16 +
drivers/platform/x86/Makefile | 2 +
drivers/platform/x86/lenovo-wmi-gamezone.c | 374 +++++++++++++++++++++
drivers/platform/x86/lenovo-wmi.c | 77 +++++
drivers/platform/x86/lenovo-wmi.h | 62 ++++
6 files changed, 534 insertions(+)
create mode 100644 drivers/platform/x86/lenovo-wmi-gamezone.c
create mode 100644 drivers/platform/x86/lenovo-wmi.c
create mode 100644 drivers/platform/x86/lenovo-wmi.h
diff --git a/MAINTAINERS b/MAINTAINERS
index e20c32b3c480..cf7f4fce1a25 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13157,6 +13157,9 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/wmi/devices/lenovo-wmi-gamezone.rst
F: Documentation/wmi/devices/lenovo-wmi-other.rst
+F: drivers/platform/x86/lenovo-wmi-gamezone.c
+F: drivers/platform/x86/lenovo-wmi.c
+F: drivers/platform/x86/lenovo-wmi.h
LETSKETCH HID TABLET DRIVER
M: Hans de Goede <hdegoede@redhat.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 7e20a58861eb..875822e6bd65 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -459,6 +459,22 @@ config IBM_RTL
state = 0 (BIOS SMIs on)
state = 1 (BIOS SMIs off)
+config LENOVO_WMI
+ tristate
+ depends on ACPI_WMI
+
+config LENOVO_WMI_GAMEZONE
+ tristate "Lenovo GameZone WMI Driver"
+ depends on ACPI_WMI
+ select ACPI_PLATFORM_PROFILE
+ select LENOVO_WMI
+ help
+ Say Y here if you have a WMI aware Lenovo Legion device and would like to use the
+ platform-profile firmware interface to manage power usage.
+
+ To compile this driver as a module, choose M here: the module will
+ be called lenovo-wmi-gamezone.
+
config IDEAPAD_LAPTOP
tristate "Lenovo IdeaPad Laptop Extras"
depends on ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 5f6307246e69..4a7b2d14eb82 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -67,7 +67,9 @@ obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o
obj-$(CONFIG_YOGABOOK) += lenovo-yogabook.o
obj-$(CONFIG_YT2_1380) += lenovo-yoga-tab2-pro-1380-fastcharger.o
+obj-$(CONFIG_LENOVO_WMI) += lenovo-wmi.o
obj-$(CONFIG_LENOVO_WMI_CAMERA) += lenovo-wmi-camera.o
+obj-$(CONFIG_LENOVO_WMI_GAMEZONE) += lenovo-wmi-gamezone.o
# Intel
obj-y += intel/
diff --git a/drivers/platform/x86/lenovo-wmi-gamezone.c b/drivers/platform/x86/lenovo-wmi-gamezone.c
new file mode 100644
index 000000000000..d5329fecba47
--- /dev/null
+++ b/drivers/platform/x86/lenovo-wmi-gamezone.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Lenovo GameZone WMI interface driver. The GameZone WMI interface provides
+ * platform profile and fan curve settings for devices that fall under the
+ * "Gaming Series" of Lenovo Legion devices.
+ *
+ * Copyright(C) 2024 Derek J. Clark <derekjohn.clark@gmail.com>
+ */
+
+#include "linux/container_of.h"
+#include "linux/printk.h"
+#include <linux/cleanup.h>
+#include <linux/dev_printk.h>
+#include <linux/dmi.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/platform_profile.h>
+#include <linux/types.h>
+#include <linux/wmi.h>
+#include "lenovo-wmi.h"
+
+/* Interface GUIDs */
+#define LENOVO_GAMEZONE_GUID "887B54E3-DDDC-4B2C-8B88-68A26A8835D0"
+#define THERMAL_MODE_EVENT_GUID "D320289E-8FEA-41E0-86F9-911D83151B5F"
+
+/* Method IDs */
+#define WMI_METHOD_ID_SMARTFAN_SUPP 43 /* IsSupportSmartFan */
+#define WMI_METHOD_ID_SMARTFAN_SET 44 /* SetSmartFanMode */
+#define WMI_METHOD_ID_SMARTFAN_GET 45 /* GetSmartFanMode */
+
+enum lenovo_wmi_gz_type {
+ GAMEZONE_FULL = 1,
+ THERMAL_MODE,
+};
+
+#define GAMEZONE_WMI_DEVICE(guid, type) \
+ .guid_string = (guid), .context = &(enum lenovo_wmi_gz_type) \
+ { \
+ type \
+ }
+
+static BLOCKING_NOTIFIER_HEAD(gz_chain_head);
+static DEFINE_MUTEX(gz_chain_mutex);
+
+struct lenovo_wmi_gz_priv {
+ enum platform_profile_option current_profile;
+ struct wmi_device *wdev;
+ bool extreme_supported;
+ struct device *ppdev; /*platform profile device */
+ enum lenovo_wmi_gz_type type;
+ struct blocking_notifier_head nhead;
+};
+
+struct quirk_entry {
+ bool extreme_supported;
+};
+
+static struct quirk_entry quirk_no_extreme_bug = {
+ .extreme_supported = false,
+};
+
+/* Platform Profile Methods & Setup */
+static int
+lenovo_wmi_gz_platform_profile_supported(struct lenovo_wmi_gz_priv *priv,
+ int *supported)
+{
+ return lenovo_wmidev_evaluate_method_1(priv->wdev, 0x0,
+ WMI_METHOD_ID_SMARTFAN_SUPP, 0, supported);
+}
+
+static int lenovo_wmi_gz_profile_get(struct device *dev,
+ enum platform_profile_option *profile)
+{
+ struct lenovo_wmi_gz_priv *priv = dev_get_drvdata(dev);
+ int sel_prof;
+ int ret;
+
+ ret = lenovo_wmidev_evaluate_method_1(priv->wdev, 0x0,
+ WMI_METHOD_ID_SMARTFAN_GET, 0, &sel_prof);
+ if (ret)
+ return ret;
+
+ switch (sel_prof) {
+ case SMARTFAN_MODE_QUIET:
+ *profile = PLATFORM_PROFILE_LOW_POWER;
+ break;
+ case SMARTFAN_MODE_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case SMARTFAN_MODE_PERFORMANCE:
+ if (priv->extreme_supported) {
+ *profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;
+ break;
+ }
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case SMARTFAN_MODE_EXTREME:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case SMARTFAN_MODE_CUSTOM:
+ *profile = PLATFORM_PROFILE_CUSTOM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ priv->current_profile = *profile;
+
+ ret = blocking_notifier_call_chain(&gz_chain_head, THERMAL_MODE_EVENT,
+ &sel_prof);
+ if (ret == NOTIFY_BAD)
+ pr_err("Failed to send notification to call chain for WMI event %u\n",
+ priv->type);
+ return 0;
+}
+
+static int lenovo_wmi_gz_profile_set(struct device *dev,
+ enum platform_profile_option profile)
+{
+ struct lenovo_wmi_gz_priv *priv = dev_get_drvdata(dev);
+ int sel_prof;
+ int ret;
+
+ switch (profile) {
+ case PLATFORM_PROFILE_LOW_POWER:
+ sel_prof = SMARTFAN_MODE_QUIET;
+ break;
+ case PLATFORM_PROFILE_BALANCED:
+ sel_prof = SMARTFAN_MODE_BALANCED;
+ break;
+ case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
+ sel_prof = SMARTFAN_MODE_PERFORMANCE;
+ break;
+ case PLATFORM_PROFILE_PERFORMANCE:
+ if (priv->extreme_supported) {
+ sel_prof = SMARTFAN_MODE_EXTREME;
+ break;
+ }
+ sel_prof = SMARTFAN_MODE_PERFORMANCE;
+ break;
+ case PLATFORM_PROFILE_CUSTOM:
+ sel_prof = SMARTFAN_MODE_CUSTOM;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ ret = lenovo_wmidev_evaluate_method_1(priv->wdev, 0x0,
+ WMI_METHOD_ID_SMARTFAN_SET, sel_prof, NULL);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct dmi_system_id fwbug_list[] = {
+ {
+ .ident = "Legion Go 8APU1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Legion Go 8APU1"),
+ },
+ .driver_data = &quirk_no_extreme_bug,
+ },
+ {
+ .ident = "Legion Go S 8ARP1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Legion Go S 8ARP1"),
+ },
+ .driver_data = &quirk_no_extreme_bug,
+ },
+ {
+ .ident = "Legion Go S 8APU1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Legion Go S 8APU1"),
+ },
+ .driver_data = &quirk_no_extreme_bug,
+ },
+ {},
+
+};
+
+static bool extreme_supported(int profile_support_ver)
+{
+ const struct dmi_system_id *dmi_id;
+ struct quirk_entry *quirks;
+
+ if (profile_support_ver < 6)
+ return false;
+
+ dmi_id = dmi_first_match(fwbug_list);
+ if (!dmi_id)
+ return true;
+
+ quirks = dmi_id->driver_data;
+ return quirks->extreme_supported;
+}
+
+static int lenovo_wmi_platform_profile_probe(void *drvdata,
+ unsigned long *choices)
+{
+ struct lenovo_wmi_gz_priv *priv = drvdata;
+ enum platform_profile_option profile;
+ int profile_support_ver;
+ int ret;
+
+ ret = lenovo_wmi_gz_platform_profile_supported(priv,
+ &profile_support_ver);
+ if (ret)
+ return ret;
+
+ if (profile_support_ver < 1)
+ return -ENODEV;
+
+ priv->extreme_supported = extreme_supported(profile_support_ver);
+
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+ set_bit(PLATFORM_PROFILE_CUSTOM, choices);
+
+ if (priv->extreme_supported)
+ set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
+
+ return 0;
+}
+
+static const struct platform_profile_ops lenovo_wmi_gz_platform_profile_ops = {
+ .probe = lenovo_wmi_platform_profile_probe,
+ .profile_get = lenovo_wmi_gz_profile_get,
+ .profile_set = lenovo_wmi_gz_profile_set,
+};
+
+/* Notifier Methods */
+int lenovo_wmi_gz_register_notifier(struct notifier_block *nb)
+{
+ guard(mutex)(&gz_chain_mutex);
+ return blocking_notifier_chain_register(&gz_chain_head, nb);
+}
+EXPORT_SYMBOL_NS_GPL(lenovo_wmi_gz_register_notifier, "GZ_WMI");
+
+int lenovo_wmi_gz_unregister_notifier(struct notifier_block *nb)
+{
+ guard(mutex)(&gz_chain_mutex);
+ return blocking_notifier_chain_unregister(&gz_chain_head, nb);
+}
+EXPORT_SYMBOL_NS_GPL(lenovo_wmi_gz_unregister_notifier, "GZ_WMI");
+
+static void devm_lenovo_wmi_gz_unregister_notifier(void *data)
+{
+ struct notifier_block *nb = data;
+
+ lenovo_wmi_gz_unregister_notifier(nb);
+}
+
+int devm_lenovo_wmi_gz_register_notifier(struct device *dev,
+ struct notifier_block *nb)
+{
+ int ret;
+
+ ret = lenovo_wmi_gz_register_notifier(nb);
+ if (ret < 0)
+ return ret;
+
+ return devm_add_action_or_reset(dev, devm_lenovo_wmi_gz_unregister_notifier, nb);
+}
+EXPORT_SYMBOL_NS_GPL(devm_lenovo_wmi_gz_register_notifier, "GZ_WMI");
+
+/* Driver Methods */
+static void lenovo_wmi_gz_notify(struct wmi_device *wdev,
+ union acpi_object *obj)
+{
+ struct lenovo_wmi_gz_priv *tm_priv = dev_get_drvdata(&wdev->dev);
+ struct lenovo_wmi_gz_priv *gz_priv =
+ container_of(&gz_chain_head, struct lenovo_wmi_gz_priv, nhead);
+ int sel_prof;
+ int ret;
+
+ if (obj->type != ACPI_TYPE_INTEGER)
+ return;
+
+ switch (tm_priv->type) {
+ case THERMAL_MODE:
+ sel_prof = obj->integer.value;
+ break;
+ default:
+ return;
+ }
+
+ /* Update primary Gamezone instance */
+ switch (sel_prof) {
+ case SMARTFAN_MODE_QUIET:
+ gz_priv->current_profile = PLATFORM_PROFILE_LOW_POWER;
+ break;
+ case SMARTFAN_MODE_BALANCED:
+ gz_priv->current_profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case SMARTFAN_MODE_PERFORMANCE:
+ if (gz_priv->extreme_supported) {
+ gz_priv->current_profile =
+ PLATFORM_PROFILE_BALANCED_PERFORMANCE;
+ break;
+ }
+ gz_priv->current_profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case SMARTFAN_MODE_EXTREME:
+ gz_priv->current_profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case SMARTFAN_MODE_CUSTOM:
+ gz_priv->current_profile = PLATFORM_PROFILE_CUSTOM;
+ break;
+ default:
+ break;
+ }
+
+ ret = blocking_notifier_call_chain(&gz_chain_head, THERMAL_MODE_EVENT,
+ &sel_prof);
+ if (ret == NOTIFY_BAD)
+ pr_err("Failed to send notification to call chain for WMI event %u\n",
+ tm_priv->type);
+}
+
+static int lenovo_wmi_gz_probe(struct wmi_device *wdev, const void *context)
+{
+ struct lenovo_wmi_gz_priv *priv =
+ devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
+
+ if (!priv)
+ return -ENOMEM;
+
+ if (!context)
+ return -EINVAL;
+
+ priv->wdev = wdev;
+ priv->type = *((enum lenovo_wmi_gz_type *)context);
+
+ dev_set_drvdata(&wdev->dev, priv);
+
+ if (priv->type != GAMEZONE_FULL)
+ return 0;
+
+ priv->nhead = gz_chain_head;
+ priv->ppdev = platform_profile_register(&wdev->dev, "lenovo-wmi-gamezone",
+ priv, &lenovo_wmi_gz_platform_profile_ops);
+
+ return 0;
+}
+
+static const struct wmi_device_id lenovo_wmi_gz_id_table[] = {
+ { GAMEZONE_WMI_DEVICE(LENOVO_GAMEZONE_GUID, GAMEZONE_FULL) },
+ { GAMEZONE_WMI_DEVICE(THERMAL_MODE_EVENT_GUID, THERMAL_MODE) },
+ {}
+};
+
+static struct wmi_driver lenovo_wmi_gz_driver = {
+ .driver = {
+ .name = "lenovo_wmi_gamezone",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .id_table = lenovo_wmi_gz_id_table,
+ .probe = lenovo_wmi_gz_probe,
+ .notify = lenovo_wmi_gz_notify,
+ .no_singleton = true,
+};
+
+module_wmi_driver(lenovo_wmi_gz_driver);
+
+MODULE_IMPORT_NS("LENOVO_WMI");
+MODULE_DEVICE_TABLE(wmi, lenovo_wmi_gz_id_table);
+MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
+MODULE_DESCRIPTION("Lenovo GameZone WMI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/lenovo-wmi.c b/drivers/platform/x86/lenovo-wmi.c
new file mode 100644
index 000000000000..0de2c37e69bd
--- /dev/null
+++ b/drivers/platform/x86/lenovo-wmi.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Lenovo Legion WMI interface driver. The Lenovo Legion WMI interface is
+ * broken up into multiple GUID interfaces that require cross-references
+ * between GUID's for some functionality. The "Custom Method" interface is a
+ * legacy interface for managing and displaying CPU & GPU power and hwmon
+ * settings and readings. The "Other Mode" interface is a modern interface
+ * that replaces or extends the "Custom Method" interface methods. The
+ * "Gamezone" interface adds advanced features such as fan profiles and
+ * overclocking. The "Lighting" interface adds control of various status
+ * lights related to different hardware components. "Other Mode" uses
+ * the data structs LENOVO_CAPABILITY_DATA_00, LENOVO_CAPABILITY_DATA_01
+ * and LENOVO_CAPABILITY_DATA_02 structs for capability information.
+ *
+ * Copyright(C) 2024 Derek J. Clark <derekjohn.clark@gmail.com>
+ *
+ */
+
+#include <linux/wmi.h>
+#include "lenovo-wmi.h"
+
+/* wmidev_evaluate_method helper functions */
+static int lenovo_wmidev_evaluate_method(struct wmi_device *wdev, u8 instance,
+ u32 method_id, struct acpi_buffer *in,
+ struct acpi_buffer *out)
+{
+ acpi_status status;
+
+ status = wmidev_evaluate_method(wdev, instance, method_id, in, out);
+
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ return 0;
+};
+
+int lenovo_wmidev_evaluate_method_2(struct wmi_device *wdev, u8 instance,
+ u32 method_id, u32 arg0, u32 arg1,
+ u32 *retval)
+{
+ struct wmi_method_args args = { arg0, arg1 };
+ struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *ret_obj __free(kfree) = NULL;
+ int err;
+
+ err = lenovo_wmidev_evaluate_method(wdev, instance, method_id, &input,
+ &output);
+
+ if (err)
+ return err;
+
+ if (retval) {
+ ret_obj = (union acpi_object *)output.pointer;
+ if (!ret_obj)
+ return -ENODATA;
+
+ if (ret_obj->type != ACPI_TYPE_INTEGER)
+ return -ENXIO;
+
+ *retval = (u32)ret_obj->integer.value;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(lenovo_wmidev_evaluate_method_2, "LENOVO_WMI");
+
+int lenovo_wmidev_evaluate_method_1(struct wmi_device *wdev, u8 instance,
+ u32 method_id, u32 arg0, u32 *retval)
+{
+ return lenovo_wmidev_evaluate_method_2(wdev, instance, method_id, arg0,
+ 0, retval);
+}
+EXPORT_SYMBOL_NS_GPL(lenovo_wmidev_evaluate_method_1, "LENOVO_WMI");
+MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
+MODULE_DESCRIPTION("Lenovo WMI Common Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/lenovo-wmi.h b/drivers/platform/x86/lenovo-wmi.h
new file mode 100644
index 000000000000..113928b4fc0f
--- /dev/null
+++ b/drivers/platform/x86/lenovo-wmi.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Lenovo Legion WMI interface driver. The Lenovo Legion WMI interface is
+ * broken up into multiple GUID interfaces that require cross-references
+ * between GUID's for some functionality. The "Custom Method" interface is a
+ * legacy interface for managing and displaying CPU & GPU power and hwmon
+ * settings and readings. The "Other Mode" interface is a modern interface
+ * that replaces or extends the "Custom Method" interface methods. The
+ * "Gamezone" interface adds advanced features such as fan profiles and
+ * overclocking. The "Lighting" interface adds control of various status
+ * lights related to different hardware components. "Other Mode" uses
+ * the data structs LENOVO_CAPABILITY_DATA_00, LENOVO_CAPABILITY_DATA_01
+ * and LENOVO_CAPABILITY_DATA_02 structs for capability information.
+ *
+ * Copyright(C) 2024 Derek J. Clark <derekjohn.clark@gmail.com>
+ *
+ */
+#include <linux/notifier.h>
+#include <linux/platform_profile.h>
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#ifndef _LENOVO_WMI_H_
+#define _LENOVO_WMI_H_
+
+#include <linux/bits.h>
+#include <linux/types.h>
+#include <linux/wmi.h>
+
+struct wmi_method_args {
+ u32 arg0;
+ u32 arg1;
+};
+
+/* gamezone structs */
+enum thermal_mode {
+ SMARTFAN_MODE_QUIET = 0x01,
+ SMARTFAN_MODE_BALANCED = 0x02,
+ SMARTFAN_MODE_PERFORMANCE = 0x03,
+ SMARTFAN_MODE_EXTREME = 0xE0, /* Ver 6+ */
+ SMARTFAN_MODE_CUSTOM = 0xFF,
+};
+
+enum lenovo_wmi_action {
+ THERMAL_MODE_EVENT = 1,
+};
+
+/* wmidev_evaluate_method helper functions */
+int lenovo_wmidev_evaluate_method_2(struct wmi_device *wdev, u8 instance,
+ u32 method_id, u32 arg0, u32 arg1,
+ u32 *retval);
+int lenovo_wmidev_evaluate_method_1(struct wmi_device *wdev, u8 instance,
+ u32 method_id, u32 arg0, u32 *retval);
+
+/* lenovo_wmi_gz_driver notifier functions */
+int lenovo_wmi_gz_notifier_call(struct notifier_block *nb, unsigned long action,
+ enum platform_profile_option *profile);
+int lenovo_wmi_gz_register_notifier(struct notifier_block *nb);
+int lenovo_wmi_gz_unregister_notifier(struct notifier_block *nb);
+int devm_lenovo_wmi_gz_register_notifier(struct device *dev,
+ struct notifier_block *nb);
+#endif /* !_LENOVO_WMI_H_ */
--
2.48.1
next prev parent reply other threads:[~2025-02-25 22:00 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-25 21:59 [PATCH v3 0/4] platform/x86: Add Lenovo Gaming Series WMI Drivers Derek J. Clark
2025-02-25 21:59 ` [PATCH v3 1/4] platform/x86: Add lenovo-wmi drivers Documentation Derek J. Clark
2025-02-26 6:36 ` Mario Limonciello
2025-02-27 0:21 ` Derek John Clark
2025-03-01 18:07 ` kernel test robot
2025-03-07 21:51 ` Armin Wolf
2025-03-10 21:36 ` Derek John Clark
2025-02-25 21:59 ` Derek J. Clark [this message]
2025-02-26 6:41 ` [PATCH v3 2/4] platform/x86: Add Lenovo Gamezone WMI Driver Mario Limonciello
2025-02-27 0:42 ` Derek John Clark
2025-02-27 19:54 ` Mario Limonciello
2025-03-03 4:03 ` kernel test robot
2025-03-07 22:47 ` Armin Wolf
2025-03-08 0:41 ` Armin Wolf
2025-03-10 22:20 ` Derek John Clark
2025-03-11 20:21 ` Armin Wolf
2025-03-10 22:11 ` Derek John Clark
2025-03-11 20:30 ` Armin Wolf
2025-03-14 21:29 ` Derek John Clark
2025-03-16 0:01 ` Armin Wolf
2025-02-25 21:59 ` [PATCH v3 3/4] platform/x86: Add Lenovo Capability Data 01 " Derek J. Clark
2025-02-25 22:33 ` Derek J. Clark
2025-03-07 23:04 ` Armin Wolf
2025-03-10 22:26 ` Derek John Clark
2025-03-11 20:33 ` Armin Wolf
2025-03-16 17:00 ` Derek John Clark
2025-02-25 21:59 ` [PATCH v3 4/4] platform/x86: Add Lenovo Other Mode " Derek J. Clark
2025-02-26 6:47 ` Mario Limonciello
2025-02-27 0:56 ` Derek John Clark
2025-02-27 19:57 ` Mario Limonciello
2025-03-03 0:08 ` kernel test robot
2025-03-08 0:24 ` Armin Wolf
2025-03-10 22:55 ` Derek John Clark
2025-03-11 20:44 ` Armin Wolf
2025-02-26 19:07 ` [PATCH v3 0/4] platform/x86: Add Lenovo Gaming Series WMI Drivers Matthew Schwartz
2025-03-06 22:58 ` Armin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250225220037.16073-3-derekjohn.clark@gmail.com \
--to=derekjohn.clark@gmail.com \
--cc=W_Armin@gmx.de \
--cc=codyit@gmail.com \
--cc=corbet@lwn.net \
--cc=hdegoede@redhat.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=johnfanv2@gmail.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luke@ljones.dev \
--cc=mpearson-lenovo@squebb.ca \
--cc=nijs1@lenovo.com \
--cc=pgriffais@valvesoftware.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=shaohz1@lenovo.com \
--cc=superm1@kernel.org \
--cc=zhangzx36@lenovo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.