platform/x86: asus-wmi: Support the hardware GPU MUX on some laptops
Support the hardware GPU MUX switch available on some models. This switch can toggle the MUX between: - 0, Dedicated mode - 1, Optimus mode Optimus mode is the regular iGPU + dGPU available, while dedicated mode switches the system to have only the dGPU available. Signed-off-by: Luke D. Jones <luke@ljones.dev> Link: https://lore.kernel.org/r/20220813092624.6228-1-luke@ljones.dev Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
3c3b55564a
commit
01ef026ab3
@ -58,6 +58,18 @@ Description:
|
||||
* 1 - overboost,
|
||||
* 2 - silent
|
||||
|
||||
What: /sys/devices/platform/<platform>/gpu_mux_mode
|
||||
Date: Aug 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: "Luke Jones" <luke@ljones.dev>
|
||||
Description:
|
||||
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:
|
||||
|
||||
* 0 - Discrete GPU,
|
||||
* 1 - Optimus/Hybrid,
|
||||
|
||||
What: /sys/devices/platform/<platform>/dgpu_disable
|
||||
Date: Aug 2022
|
||||
KernelVersion: 5.17
|
||||
|
@ -231,6 +231,7 @@ struct asus_wmi {
|
||||
|
||||
bool egpu_enable_available;
|
||||
bool dgpu_disable_available;
|
||||
bool gpu_mux_mode_available;
|
||||
|
||||
bool throttle_thermal_policy_available;
|
||||
u8 throttle_thermal_policy_mode;
|
||||
@ -657,6 +658,52 @@ static ssize_t egpu_enable_store(struct device *dev,
|
||||
}
|
||||
static DEVICE_ATTR_RW(egpu_enable);
|
||||
|
||||
/* gpu mux switch *************************************************************/
|
||||
static ssize_t gpu_mux_mode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct asus_wmi *asus = dev_get_drvdata(dev);
|
||||
int result;
|
||||
|
||||
result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
return sysfs_emit(buf, "%d\n", result);
|
||||
}
|
||||
|
||||
static ssize_t gpu_mux_mode_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct asus_wmi *asus = dev_get_drvdata(dev);
|
||||
int result, err;
|
||||
u32 optimus;
|
||||
|
||||
err = kstrtou32(buf, 10, &optimus);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (optimus > 1)
|
||||
return -EINVAL;
|
||||
|
||||
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_MUX, optimus, &result);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to set GPU MUX mode: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
/* !1 is considered a fail by ASUS */
|
||||
if (result != 1) {
|
||||
dev_warn(dev, "Failed to set GPU MUX mode (result): 0x%x\n", result);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
sysfs_notify(&asus->platform_device->dev.kobj, NULL, "gpu_mux_mode");
|
||||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(gpu_mux_mode);
|
||||
|
||||
/* Battery ********************************************************************/
|
||||
|
||||
/* The battery maximum charging percentage */
|
||||
@ -3172,6 +3219,7 @@ static struct attribute *platform_attributes[] = {
|
||||
&dev_attr_touchpad.attr,
|
||||
&dev_attr_egpu_enable.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,
|
||||
@ -3202,6 +3250,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
|
||||
ok = asus->egpu_enable_available;
|
||||
else if (attr == &dev_attr_dgpu_disable.attr)
|
||||
ok = asus->dgpu_disable_available;
|
||||
else if (attr == &dev_attr_gpu_mux_mode.attr)
|
||||
ok = asus->gpu_mux_mode_available;
|
||||
else if (attr == &dev_attr_fan_boost_mode.attr)
|
||||
ok = asus->fan_boost_mode_available;
|
||||
else if (attr == &dev_attr_throttle_thermal_policy.attr)
|
||||
@ -3465,6 +3515,7 @@ 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->gpu_mux_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX);
|
||||
asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD);
|
||||
|
||||
err = fan_boost_mode_check_present(asus);
|
||||
|
@ -99,6 +99,9 @@
|
||||
/* dgpu on/off */
|
||||
#define ASUS_WMI_DEVID_DGPU 0x00090020
|
||||
|
||||
/* gpu mux switch, 0 = dGPU, 1 = Optimus */
|
||||
#define ASUS_WMI_DEVID_GPU_MUX 0x00090016
|
||||
|
||||
/* DSTS masks */
|
||||
#define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
|
||||
#define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002
|
||||
|
Loading…
Reference in New Issue
Block a user