The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
To: "Kürşat Abaylı" <hello@kursatabayli.dev>
Cc: Hans de Goede <hansg@kernel.org>,
	platform-driver-x86@vger.kernel.org,
	 LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v3] platform/x86: hp-wmi: Add GPU MUX switch support
Date: Fri, 10 Jul 2026 12:44:22 +0300 (EEST)	[thread overview]
Message-ID: <30a06947-86a1-8952-0556-c6dc3fe46fc4@linux.intel.com> (raw)
In-Reply-To: <20260709220512.20619-1-hello@kursatabayli.dev>

[-- Attachment #1: Type: text/plain, Size: 6940 bytes --]

On Fri, 10 Jul 2026, Kürşat Abaylı wrote:

> Add support for querying and switching the graphics MUX mode on HP
> systems via WMI. This introduces the 'gpu_mux_mode' sysfs attribute
> under the hp-wmi platform device, allowing userspace tools to check
> and safely switch between available graphics modes (e.g., UMA, Hybrid,
> Discrete).
> 
> The hardware capabilities mask is primarily read using the modern
> 128-byte System Design Data query. However, to ensure backward
> compatibility with older models, a fallback mechanism is implemented.
> By mirroring the behavior of the Windows Omen Gaming Hub software, if
> the modern query fails but the MUX WMI endpoint (0x52) responds
> successfully to a read request, the driver defaults to a standard
> Hybrid + Discrete support mask (0x06).
> 
> Signed-off-by: Kürşat Abaylı <hello@kursatabayli.dev>
> ---
> Changes in v3:
>  - Rebased for the for-next branch (no functional changes).
> 
> Changes in v2:
>  - Replaced hardcoded bitmask with GENMASK(6, 0).
>  - Added specific defines for MUX modes instead of using raw BIT() macros.
>  - Initialized arrays with {} instead of { 0 }.
>  - Fixed reverse xmas-tree ordering for local variable declarations.
>  - Removed empty lines between function calls and their return value checks.
>  - Split ternary operators into standard if-statements for better readability.
>  - Added missing <linux/array_size.h> include.
>  - Removed unnecessary cast in hp_wmi_set_mux_mode.
> ---
>  drivers/platform/x86/hp/hp-wmi.c | 137 +++++++++++++++++++++++++++++++
>  1 file changed, 137 insertions(+)
> 
> diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> index 34c9b941bdd8..3e50eaf6570c 100644
> --- a/drivers/platform/x86/hp/hp-wmi.c
> +++ b/drivers/platform/x86/hp/hp-wmi.c
> @@ -14,6 +14,8 @@
>  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>  
>  #include <linux/acpi.h>
> +#include <linux/array_size.h>
> +#include <linux/bits.h>
>  #include <linux/cleanup.h>
>  #include <linux/compiler_attributes.h>
>  #include <linux/dmi.h>
> @@ -58,6 +60,12 @@ enum hp_ec_offsets {
>  #define HP_FAN_SPEED_AUTOMATIC	 0x00
>  #define HP_POWER_LIMIT_DEFAULT	 0x00
>  #define HP_POWER_LIMIT_NO_CHANGE 0xFF
> +#define HPWMI_MUX_MODE_UMA		BIT(0)
> +#define HPWMI_MUX_MODE_HYBRID		BIT(1)
> +#define HPWMI_MUX_MODE_DISCRETE		BIT(2)
> +#define HPWMI_MUX_MODE_OPTIMUS		BIT(3)
> +#define HPWMI_MUX_MODE_MASK		GENMASK(6, 0)
> +#define HPWMI_MUX_LEGACY_MASK		(HPWMI_MUX_MODE_HYBRID | HPWMI_MUX_MODE_DISCRETE)
>  
>  #define zero_if_sup(tmp) (zero_insize_support?0:sizeof(tmp)) // use when zero insize is required
>  
> @@ -381,6 +389,7 @@ enum hp_wmi_commandtype {
>  	HPWMI_POSTCODEERROR_QUERY	= 0x2a,
>  	HPWMI_SYSTEM_DEVICE_MODE	= 0x40,
>  	HPWMI_THERMAL_PROFILE_QUERY	= 0x4c,
> +	HPWMI_GRAPHICS_MUX_QUERY	= 0x52,
>  };
>  
>  struct victus_power_limits {
> @@ -1173,12 +1182,139 @@ static int camera_shutter_input_setup(void)
>  	return err;
>  }
>  
> +static const u8 mux_bitmask_map[] = {
> +	[0] = HPWMI_MUX_MODE_HYBRID,
> +	[1] = HPWMI_MUX_MODE_DISCRETE,
> +	[2] = HPWMI_MUX_MODE_OPTIMUS,
> +	[3] = HPWMI_MUX_MODE_UMA,
> +};
> +
> +static int hp_wmi_get_mux_supported_modes(u8 *supported)
> +{
> +	u8 legacy_buffer[4] = {};
> +	u8 buffer[128] = {};
> +	u32 req_packet = 0;
> +	int ret;
> +
> +	if (!supported)
> +		return -EINVAL;
> +
> +	/* Try modern BIOS design data query (128-byte buffer) */
> +	ret = hp_wmi_perform_query(HPWMI_GET_SYSTEM_DESIGN_DATA, HPWMI_GM,
> +				   buffer, zero_if_sup(req_packet), sizeof(buffer));
> +	if (ret == 0) {
> +		*supported = buffer[7];
> +		return 0;
> +	}
> +
> +	/*
> +	 * (Fallback): Legacy BIOS behavior based on Omen Gaming Hub.
> +	 * If the modern query is not supported, check if the MUX query endpoint
> +	 * responds to a read request. If it succeeds, the hardware has MUX
> +	 * capability but lacks the mode map, defaulting to Hybrid + Discrete.
> +	 */
> +	ret = hp_wmi_perform_query(HPWMI_GRAPHICS_MUX_QUERY, HPWMI_READ,
> +				   legacy_buffer, sizeof(legacy_buffer), 0);
> +	if (ret == 0) {
> +		*supported = HPWMI_MUX_LEGACY_MASK;
> +		return 0;
> +	}
> +
> +	if (ret < 0)
> +		return ret;
> +	return -EINVAL;
> +}
> +
> +static int hp_wmi_get_mux_mode(u8 *mode)
> +{
> +	u8 buffer[4] = {};
> +	int ret;
> +
> +	if (!mode)
> +		return -EINVAL;
> +
> +	ret = hp_wmi_perform_query(HPWMI_GRAPHICS_MUX_QUERY, HPWMI_READ,
> +				   buffer, sizeof(buffer), sizeof(buffer));
> +
> +	if (ret < 0)

Remove empty line in between call and its error handling.

> +		return ret;
> +	if (ret > 0)
> +		return -EINVAL;
> +
> +	/* Mask the highest bit, which might be used as a BIOS status flag */
> +	*mode = buffer[0] & HPWMI_MUX_MODE_MASK;
> +
> +	return 0;
> +}
> +
> +static int hp_wmi_set_mux_mode(u8 mode)
> +{
> +	u8 buffer[4] = { mode, 0x00, 0x00, 0x00 };
> +	int ret;
> +
> +	ret = hp_wmi_perform_query(HPWMI_GRAPHICS_MUX_QUERY, HPWMI_WRITE,
> +				   buffer, sizeof(buffer), sizeof(buffer));
> +
> +	if (ret < 0)

Ditto.

> +		return ret;
> +	if (ret > 0)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static ssize_t gpu_mux_mode_show(struct device *dev,
> +				 struct device_attribute *attr,
> +				 char *buf)
> +{
> +	u8 mode;
> +	int ret;
> +
> +	ret = hp_wmi_get_mux_mode(&mode);
> +	if (ret)
> +		return ret;
> +
> +	return sysfs_emit(buf, "%u\n", mode);
> +}
> +
> +static ssize_t gpu_mux_mode_store(struct device *dev,
> +				  struct device_attribute *attr,
> +				  const char *buf,
> +				  size_t count)
> +{
> +	u32 requested;
> +	u8 supported;
> +	int ret;
> +
> +	ret = kstrtou32(buf, 0, &requested);
> +	if (ret)
> +		return ret;
> +
> +	if (requested >= ARRAY_SIZE(mux_bitmask_map))

This is part of error handling for the kstrtou32() so please remove blank 
line in between here as well.

> +		return -EINVAL;
> +
> +	ret = hp_wmi_get_mux_supported_modes(&supported);
> +	if (ret)
> +		return ret;
> +
> +	/* Verify if the requested mode is allowed by the hardware mask */
> +	if (!(supported & mux_bitmask_map[requested]))
> +		return -EOPNOTSUPP;
> +
> +	ret = hp_wmi_set_mux_mode(requested);
> +	if (ret)
> +		return ret;
> +
> +	return count;
> +}
> +
>  static DEVICE_ATTR_RO(display);
>  static DEVICE_ATTR_RO(hddtemp);
>  static DEVICE_ATTR_RW(als);
>  static DEVICE_ATTR_RO(dock);
>  static DEVICE_ATTR_RO(tablet);
>  static DEVICE_ATTR_RW(postcode);
> +static DEVICE_ATTR_RW(gpu_mux_mode);
>  
>  static struct attribute *hp_wmi_attrs[] = {
>  	&dev_attr_display.attr,
> @@ -1187,6 +1323,7 @@ static struct attribute *hp_wmi_attrs[] = {
>  	&dev_attr_dock.attr,
>  	&dev_attr_tablet.attr,
>  	&dev_attr_postcode.attr,
> +	&dev_attr_gpu_mux_mode.attr,
>  	NULL,
>  };
>  ATTRIBUTE_GROUPS(hp_wmi);
> 

-- 
 i.

      reply	other threads:[~2026-07-10  9:44 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-09 22:05 [PATCH v3] platform/x86: hp-wmi: Add GPU MUX switch support Kürşat Abaylı
2026-07-10  9:44 ` Ilpo Järvinen [this message]

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=30a06947-86a1-8952-0556-c6dc3fe46fc4@linux.intel.com \
    --to=ilpo.jarvinen@linux.intel.com \
    --cc=hansg@kernel.org \
    --cc=hello@kursatabayli.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=platform-driver-x86@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox