summaryrefslogtreecommitdiff
path: root/SOURCES/asus-linux.patch
diff options
context:
space:
mode:
Diffstat (limited to 'SOURCES/asus-linux.patch')
-rw-r--r--SOURCES/asus-linux.patch1328
1 files changed, 0 insertions, 1328 deletions
diff --git a/SOURCES/asus-linux.patch b/SOURCES/asus-linux.patch
deleted file mode 100644
index 1276952..0000000
--- a/SOURCES/asus-linux.patch
+++ /dev/null
@@ -1,1328 +0,0 @@
-From 0afaa446a07db0ded4c032511b35485bd12ff80f Mon Sep 17 00:00:00 2001
-From: Jan200101 <sentrycraft123@gmail.com>
-Date: Sat, 17 Dec 2022 18:14:04 +0100
-Subject: [PATCH] asus-linux
-
-Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
----
- .../ABI/testing/sysfs-platform-asus-wmi | 41 ++
- drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 4 +
- drivers/hid/amd-sfh-hid/amd_sfh_pcie.h | 1 +
- .../hid_descriptor/amd_sfh_hid_desc.c | 27 +
- .../hid_descriptor/amd_sfh_hid_desc.h | 8 +
- .../hid_descriptor/amd_sfh_hid_report_desc.h | 19 +
- drivers/platform/x86/asus-nb-wmi.c | 14 +-
- drivers/platform/x86/asus-wmi.c | 677 ++++++++++--------
- include/linux/platform_data/x86/asus-wmi.h | 10 +
- 9 files changed, 503 insertions(+), 298 deletions(-)
-
-diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi
-index 04885738cf15..a77a004a1baa 100644
---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi
-+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi
-@@ -57,3 +57,44 @@ Description:
- * 0 - default,
- * 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
-+Contact: "Luke Jones" <luke@ljones.dev>
-+Description:
-+ Disable discrete GPU:
-+ * 0 - Enable dGPU,
-+ * 1 - Disable dGPU
-+
-+What: /sys/devices/platform/<platform>/egpu_enable
-+Date: Aug 2022
-+KernelVersion: 5.17
-+Contact: "Luke Jones" <luke@ljones.dev>
-+Description:
-+ Enable the external GPU paired with ROG X-Flow laptops.
-+ Toggling this setting will also trigger ACPI to disable the dGPU:
-+
-+ * 0 - Disable,
-+ * 1 - Enable
-+
-+What: /sys/devices/platform/<platform>/panel_od
-+Date: Aug 2022
-+KernelVersion: 5.17
-+Contact: "Luke Jones" <luke@ljones.dev>
-+Description:
-+ Enable an LCD response-time boost to reduce or remove ghosting:
-+ * 0 - Disable,
-+ * 1 - Enable
-diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
-index 47774b9ab3de..a03f0968e82f 100644
---- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
-+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
-@@ -27,6 +27,7 @@
- #define ACEL_EN BIT(0)
- #define GYRO_EN BIT(1)
- #define MAGNO_EN BIT(2)
-+#define KBGUARD_EN BIT(15)
- #define HPD_EN BIT(16)
- #define ALS_EN BIT(19)
-
-@@ -233,6 +234,9 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
- if (HPD_EN & activestatus)
- sensor_id[num_of_sensors++] = HPD_IDX;
-
-+ if (KBGUARD_EN & activestatus)
-+ sensor_id[num_of_sensors++] = KBGUARD_IDX;
-+
- return num_of_sensors;
- }
-
-diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
-index dfb7cabd82ef..5fa15eed43f3 100644
---- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
-+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
-@@ -23,6 +23,7 @@
- #define V2_STATUS 0x2
-
- #define HPD_IDX 16
-+#define KBGUARD_IDX 15
-
- #define SENSOR_DISCOVERY_STATUS_MASK GENMASK(5, 3)
- #define SENSOR_DISCOVERY_STATUS_SHIFT 3
-diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
-index f9a8c02d5a7b..06487eb75dc8 100644
---- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
-+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
-@@ -57,6 +57,11 @@ static int get_report_descriptor(int sensor_idx, u8 *rep_desc)
- memcpy(rep_desc, hpd_report_descriptor,
- sizeof(hpd_report_descriptor));
- break;
-+ case KBGUARD_IDX: /* kbguard ? */
-+ memset(rep_desc, 0, sizeof(kbguard_report_descriptor));
-+ memcpy(rep_desc, kbguard_report_descriptor,
-+ sizeof(kbguard_report_descriptor));
-+ break;
- default:
- break;
- }
-@@ -116,6 +121,16 @@ static u32 get_descr_sz(int sensor_idx, int descriptor_name)
- return sizeof(struct hpd_feature_report);
- }
- break;
-+ case KBGUARD_IDX:
-+ switch (descriptor_name) {
-+ case descr_size:
-+ return sizeof(kbguard_report_descriptor);
-+ case input_size:
-+ return sizeof(struct kbguard_input_report);
-+ case feature_size:
-+ return sizeof(struct kbguard_feature_report);
-+ }
-+ break;
-
- default:
- break;
-@@ -139,6 +154,7 @@ static u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
- struct gyro_feature_report gyro_feature;
- struct magno_feature_report magno_feature;
- struct hpd_feature_report hpd_feature;
-+ struct kbguard_feature_report kbguard_feature;
- struct als_feature_report als_feature;
- u8 report_size = 0;
-
-@@ -186,6 +202,11 @@ static u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
- memcpy(feature_report, &hpd_feature, sizeof(hpd_feature));
- report_size = sizeof(hpd_feature);
- break;
-+ case KBGUARD_IDX: /* auto disable keyboard when flip out */
-+ get_common_features(&kbguard_feature.common_property, report_id);
-+ memcpy(feature_report, &kbguard_feature, sizeof(kbguard_feature));
-+ report_size = sizeof(kbguard_feature);
-+ break;
-
- default:
- break;
-@@ -211,6 +232,7 @@ static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
- struct accel3_input_report acc_input;
- struct gyro_input_report gyro_input;
- struct hpd_input_report hpd_input;
-+ struct kbguard_input_report kbguard_input;
- struct als_input_report als_input;
- struct hpd_status hpdstatus;
- u8 report_size = 0;
-@@ -263,6 +285,11 @@ static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
- report_size = sizeof(hpd_input);
- memcpy(input_report, &hpd_input, sizeof(hpd_input));
- break;
-+ case KBGUARD_IDX: /* kb guard */
-+ get_common_inputs(&kbguard_input.common_property, report_id);
-+ report_size = sizeof(kbguard_input);
-+ memcpy(input_report, &kbguard_input, sizeof(kbguard_input));
-+break;
- default:
- break;
- }
-diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
-index ebd55675eb62..2f2ba9a0cfbc 100644
---- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
-+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
-@@ -111,4 +111,12 @@ struct hpd_input_report {
- u8 human_presence;
- } __packed;
-
-+struct kbguard_feature_report {
-+ struct common_feature_property common_property;
-+} __packed;
-+
-+struct kbguard_input_report {
-+ struct common_input_property common_property;
-+} __packed;
-+
- #endif
-diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
-index 697f2791ea9c..7a62fcec2c73 100644
---- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
-+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
-@@ -644,6 +644,25 @@ static const u8 als_report_descriptor[] = {
- 0xC0 /* HID end collection */
- };
-
-+
-+static const u8 kbguard_report_descriptor[] = {
-+0x06, 0x43, 0xFF, // Usage Page (Vendor Defined 0xFF43)
-+0x0A, 0x02, 0x02, // Usage (0x0202)
-+0xA1, 0x01, // Collection (Application)
-+0x85, 0x11, // Report ID (17)
-+0x15, 0x00, // Logical Minimum (0)
-+0x25, 0x01, // Logical Maximum (1)
-+0x35, 0x00, // Physical Minimum (0)
-+0x45, 0x01, // Physical Maximum (1)
-+0x65, 0x00, // Unit (None)
-+0x55, 0x00, // Unit Exponent (0)
-+0x75, 0x01, // Report Size (1)
-+0x95, 0x98, // Report Count (-104)
-+0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
-+0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
-+0xC1, 0x00, // End Collection
-+};
-+
- /* BIOMETRIC PRESENCE*/
- static const u8 hpd_report_descriptor[] = {
- 0x05, 0x20, /* Usage page */
-diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
-index d9e7cf6e4a0e..fcfe6dddd645 100644
---- a/drivers/platform/x86/asus-nb-wmi.c
-+++ b/drivers/platform/x86/asus-nb-wmi.c
-@@ -504,17 +504,8 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
- else
- wapf = quirks->wapf;
-
-- switch (tablet_mode_sw) {
-- case 0:
-- quirks->tablet_switch_mode = asus_wmi_no_tablet_switch;
-- break;
-- case 1:
-- quirks->tablet_switch_mode = asus_wmi_kbd_dock_devid;
-- break;
-- case 2:
-- quirks->tablet_switch_mode = asus_wmi_lid_flip_devid;
-- break;
-- }
-+ if (tablet_mode_sw != -1)
-+ quirks->tablet_switch_mode = tablet_mode_sw;
-
- if (quirks->i8042_filter) {
- ret = i8042_install_filter(quirks->i8042_filter);
-@@ -586,6 +577,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
- { KE_KEY, 0xA5, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + HDMI */
- { KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */
- { KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */
-+ { KE_KEY, 0xAE, { KEY_FN_F5 } }, /* Fn+F5 fan mode on 2020+ */
- { KE_KEY, 0xB3, { KEY_PROG4 } }, /* AURA */
- { KE_KEY, 0xB5, { KEY_CALC } },
- { KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
-diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
-index dce93187e11f..40e911467037 100644
---- a/drivers/platform/x86/asus-wmi.c
-+++ b/drivers/platform/x86/asus-wmi.c
-@@ -72,6 +72,7 @@ module_param(fnlock_default, bool, 0444);
-
- #define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0)
-
-+#define ASUS_GPU_FAN_DESC "gpu_fan"
- #define ASUS_FAN_DESC "cpu_fan"
- #define ASUS_FAN_MFUN 0x13
- #define ASUS_FAN_SFUN_READ 0x06
-@@ -222,19 +223,25 @@ struct asus_wmi {
- struct asus_rfkill gps;
- struct asus_rfkill uwb;
-
-+ int tablet_switch_event_code;
-+ u32 tablet_switch_dev_id;
-+
- enum fan_type fan_type;
-+ enum fan_type gpu_fan_type;
- int fan_pwm_mode;
-+ int gpu_fan_pwm_mode;
- int agfn_pwm;
-
- bool fan_boost_mode_available;
- u8 fan_boost_mode_mask;
- u8 fan_boost_mode;
-
-- bool egpu_enable_available; // 0 = enable
-- bool egpu_enable;
--
-+ bool egpu_enable_available;
- bool dgpu_disable_available;
-- bool dgpu_disable;
-+ bool gpu_mux_mode_available;
-+
-+ bool kbd_rgb_mode_available;
-+ bool kbd_rgb_state_available;
-
- bool throttle_thermal_policy_available;
- u8 throttle_thermal_policy_mode;
-@@ -250,7 +257,6 @@ struct asus_wmi {
- bool battery_rsoc_available;
-
- bool panel_overdrive_available;
-- bool panel_overdrive;
-
- struct hotplug_slot hotplug_slot;
- struct mutex hotplug_lock;
-@@ -487,13 +493,28 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id)
- }
-
- /* Input **********************************************************************/
-+static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event_code)
-+{
-+ struct device *dev = &asus->platform_device->dev;
-+ int result;
-+
-+ result = asus_wmi_get_devstate_simple(asus, dev_id);
-+ if (result >= 0) {
-+ input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
-+ input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
-+ asus->tablet_switch_dev_id = dev_id;
-+ asus->tablet_switch_event_code = event_code;
-+ } else if (result == -ENODEV) {
-+ dev_err(dev, "This device has tablet-mode-switch quirk but got ENODEV checking it. This is a bug.");
-+ } else {
-+ dev_err(dev, "Error checking for tablet-mode-switch: %d\n", result);
-+ }
-+}
-
- static int asus_wmi_input_init(struct asus_wmi *asus)
- {
-- struct device *dev;
-- int err, result;
--
-- dev = &asus->platform_device->dev;
-+ struct device *dev = &asus->platform_device->dev;
-+ int err;
-
- asus->inputdev = input_allocate_device();
- if (!asus->inputdev)
-@@ -513,39 +534,13 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
- case asus_wmi_no_tablet_switch:
- break;
- case asus_wmi_kbd_dock_devid:
-- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_KBD_DOCK);
-- if (result >= 0) {
-- input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
-- input_report_switch(asus->inputdev, SW_TABLET_MODE, !result);
-- } else if (result != -ENODEV) {
-- dev_err(dev, "Error checking for keyboard-dock: %d\n", result);
-- }
-+ asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_KBD_DOCK, NOTIFY_KBD_DOCK_CHANGE);
- break;
- case asus_wmi_lid_flip_devid:
-- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP);
-- if (result < 0)
-- asus->driver->quirks->tablet_switch_mode = asus_wmi_no_tablet_switch;
-- if (result >= 0) {
-- input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
-- input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
-- } else if (result == -ENODEV) {
-- dev_err(dev, "This device has lid_flip quirk but got ENODEV checking it. This is a bug.");
-- } else {
-- dev_err(dev, "Error checking for lid-flip: %d\n", result);
-- }
-+ asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_LID_FLIP, NOTIFY_LID_FLIP);
- break;
- case asus_wmi_lid_flip_rog_devid:
-- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP_ROG);
-- if (result < 0)
-- asus->driver->quirks->tablet_switch_mode = asus_wmi_no_tablet_switch;
-- if (result >= 0) {
-- input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
-- input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
-- } else if (result == -ENODEV) {
-- dev_err(dev, "This device has lid-flip-rog quirk but got ENODEV checking it. This is a bug.");
-- } else {
-- dev_err(dev, "Error checking for lid-flip: %d\n", result);
-- }
-+ asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_LID_FLIP_ROG, NOTIFY_LID_FLIP_ROG);
- break;
- }
-
-@@ -570,22 +565,14 @@ static void asus_wmi_input_exit(struct asus_wmi *asus)
-
- /* Tablet mode ****************************************************************/
-
--static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus)
-+static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus)
- {
- int result;
-
-- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP);
-- if (result >= 0) {
-- input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
-- input_sync(asus->inputdev);
-- }
--}
--
--static void lid_flip_rog_tablet_mode_get_state(struct asus_wmi *asus)
--{
-- int result;
-+ if (!asus->tablet_switch_dev_id)
-+ return;
-
-- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP_ROG);
-+ result = asus_wmi_get_devstate_simple(asus, asus->tablet_switch_dev_id);
- if (result >= 0) {
- input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
- input_sync(asus->inputdev);
-@@ -593,179 +580,267 @@ static void lid_flip_rog_tablet_mode_get_state(struct asus_wmi *asus)
- }
-
- /* dGPU ********************************************************************/
--static int dgpu_disable_check_present(struct asus_wmi *asus)
-+static ssize_t dgpu_disable_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
- {
-- u32 result;
-- int err;
--
-- asus->dgpu_disable_available = false;
--
-- err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_DGPU, &result);
-- if (err) {
-- if (err == -ENODEV)
-- return 0;
-- return err;
-- }
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ int result;
-
-- if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
-- asus->dgpu_disable_available = true;
-- asus->dgpu_disable = result & ASUS_WMI_DSTS_STATUS_BIT;
-- }
-+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_DGPU);
-+ if (result < 0)
-+ return result;
-
-- return 0;
-+ return sysfs_emit(buf, "%d\n", result);
- }
-
--static int dgpu_disable_write(struct asus_wmi *asus)
-+/*
-+ * 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_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
- {
-- u32 retval;
-- u8 value;
-- int err;
-+ int result, err;
-+ u32 disable;
-
-- /* Don't rely on type conversion */
-- value = asus->dgpu_disable ? 1 : 0;
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, value, &retval);
-+ result = kstrtou32(buf, 10, &disable);
-+ if (result)
-+ return result;
-+
-+ if (disable > 1)
-+ return -EINVAL;
-+
-+ 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 (retval > 1) {
-- pr_warn("Failed to set dgpu disable (retval): 0x%x\n", retval);
-+ if (result > 1) {
-+ pr_warn("Failed to set dgpu disable (result): 0x%x\n", result);
- return -EIO;
- }
-
- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "dgpu_disable");
-
-- return 0;
-+ return count;
- }
-+static DEVICE_ATTR_RW(dgpu_disable);
-
--static ssize_t dgpu_disable_show(struct device *dev,
-+/* eGPU ********************************************************************/
-+static ssize_t egpu_enable_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct asus_wmi *asus = dev_get_drvdata(dev);
-- u8 mode = asus->dgpu_disable;
-+ int result;
-
-- return sysfs_emit(buf, "%d\n", mode);
-+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU);
-+ if (result < 0)
-+ return result;
-+
-+ return sysfs_emit(buf, "%d\n", result);
- }
-
--/*
-- * 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_store(struct device *dev,
-+/* The ACPI call to enable the eGPU also disables the internal dGPU */
-+static ssize_t egpu_enable_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
-- bool disable;
-- int result;
-+ int result, err;
-+ u32 enable;
-
- struct asus_wmi *asus = dev_get_drvdata(dev);
-
-- result = kstrtobool(buf, &disable);
-- if (result)
-- return result;
-+ err = kstrtou32(buf, 10, &enable);
-+ if (err)
-+ return err;
-
-- asus->dgpu_disable = disable;
-+ if (enable > 1)
-+ return -EINVAL;
-
-- result = dgpu_disable_write(asus);
-- if (result)
-- return result;
-+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, enable, &result);
-+ if (err) {
-+ pr_warn("Failed to set egpu disable: %d\n", err);
-+ return err;
-+ }
-+
-+ if (result > 1) {
-+ pr_warn("Failed to set egpu disable (retval): 0x%x\n", result);
-+ return -EIO;
-+ }
-+
-+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "egpu_enable");
-
- return count;
- }
-+static DEVICE_ATTR_RW(egpu_enable);
-
--static DEVICE_ATTR_RW(dgpu_disable);
-+/* 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;
-
--/* eGPU ********************************************************************/
--static int egpu_enable_check_present(struct asus_wmi *asus)
-+ 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)
- {
-- u32 result;
-- int err;
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ int result, err;
-+ u32 optimus;
-
-- asus->egpu_enable_available = false;
-+ err = kstrtou32(buf, 10, &optimus);
-+ if (err)
-+ return err;
-
-- err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_EGPU, &result);
-+ if (optimus > 1)
-+ return -EINVAL;
-+
-+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_MUX, optimus, &result);
- if (err) {
-- if (err == -ENODEV)
-- return 0;
-+ dev_err(dev, "Failed to set GPU MUX mode: %d\n", err);
- return err;
- }
--
-- if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
-- asus->egpu_enable_available = true;
-- asus->egpu_enable = result & ASUS_WMI_DSTS_STATUS_BIT;
-+ /* !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;
- }
-
-- return 0;
-+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "gpu_mux_mode");
-+
-+ return count;
- }
-+static DEVICE_ATTR_RW(gpu_mux_mode);
-
--static int egpu_enable_write(struct asus_wmi *asus)
-+/* TUF Laptop Keyboard RGB Modes **********************************************/
-+static ssize_t kbd_rgb_mode_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
- {
-- u32 retval;
-- u8 value;
-+ u32 cmd, mode, r, g, b, speed;
- int err;
-
-- /* Don't rely on type conversion */
-- value = asus->egpu_enable ? 1 : 0;
-+ if (sscanf(buf, "%d %d %d %d %d %d", &cmd, &mode, &r, &g, &b, &speed) != 6)
-+ return -EINVAL;
-
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, value, &retval);
-+ cmd = !!cmd;
-
-- if (err) {
-- pr_warn("Failed to set egpu disable: %d\n", err);
-- return err;
-- }
-+ /* These are the known usable modes across all TUF/ROG */
-+ if (mode >= 12 || mode == 9)
-+ mode = 10;
-
-- if (retval > 1) {
-- pr_warn("Failed to set egpu disable (retval): 0x%x\n", retval);
-- return -EIO;
-+ switch (speed) {
-+ case 0:
-+ speed = 0xe1;
-+ break;
-+ case 1:
-+ speed = 0xeb;
-+ break;
-+ case 2:
-+ speed = 0xf5;
-+ break;
-+ default:
-+ speed = 0xeb;
- }
-
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "egpu_enable");
-+ err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, ASUS_WMI_DEVID_TUF_RGB_MODE,
-+ cmd | (mode << 8) | (r << 16) | (g << 24), b | (speed << 8), NULL);
-+ if (err)
-+ return err;
-
-- return 0;
-+ return count;
- }
-+static DEVICE_ATTR_WO(kbd_rgb_mode);
-
--static ssize_t egpu_enable_show(struct device *dev,
-- struct device_attribute *attr, char *buf)
-+static ssize_t kbd_rgb_mode_index_show(struct device *device,
-+ struct device_attribute *attr,
-+ char *buf)
- {
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-- bool mode = asus->egpu_enable;
--
-- return sysfs_emit(buf, "%d\n", mode);
-+ return sysfs_emit(buf, "%s\n", "cmd mode red green blue speed");
- }
-+static DEVICE_ATTR_RO(kbd_rgb_mode_index);
-
--/* The ACPI call to enable the eGPU also disables the internal dGPU */
--static ssize_t egpu_enable_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- bool enable;
-- int result;
--
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-+static struct attribute *kbd_rgb_mode_attrs[] = {
-+ &dev_attr_kbd_rgb_mode.attr,
-+ &dev_attr_kbd_rgb_mode_index.attr,
-+ NULL,
-+};
-
-- result = kstrtobool(buf, &enable);
-- if (result)
-- return result;
-+static const struct attribute_group kbd_rgb_mode_group = {
-+ .attrs = kbd_rgb_mode_attrs,
-+};
-
-- asus->egpu_enable = enable;
-+/* TUF Laptop Keyboard RGB State **********************************************/
-+static ssize_t kbd_rgb_state_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ u32 flags, cmd, boot, awake, sleep, keyboard;
-+ int err;
-
-- result = egpu_enable_write(asus);
-- if (result)
-- return result;
-+ if (sscanf(buf, "%d %d %d %d %d", &cmd, &boot, &awake, &sleep, &keyboard) != 5)
-+ return -EINVAL;
-
-- /* Ensure that the kernel status of dgpu is updated */
-- result = dgpu_disable_check_present(asus);
-- if (result)
-- return result;
-+ if (cmd)
-+ cmd = BIT(2);
-+
-+ flags = 0;
-+ if (boot)
-+ flags |= BIT(1);
-+ if (awake)
-+ flags |= BIT(3);
-+ if (sleep)
-+ flags |= BIT(5);
-+ if (keyboard)
-+ flags |= BIT(7);
-+
-+ /* 0xbd is the required default arg0 for the method. Nothing happens otherwise */
-+ err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS,
-+ ASUS_WMI_DEVID_TUF_RGB_STATE, 0xbd | cmd << 8 | (flags << 16), 0, NULL);
-+ if (err)
-+ return err;
-
- return count;
- }
-+static DEVICE_ATTR_WO(kbd_rgb_state);
-
--static DEVICE_ATTR_RW(egpu_enable);
-+static ssize_t kbd_rgb_state_index_show(struct device *device,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ return sysfs_emit(buf, "%s\n", "cmd boot awake sleep keyboard");
-+}
-+static DEVICE_ATTR_RO(kbd_rgb_state_index);
-+
-+static struct attribute *kbd_rgb_state_attrs[] = {
-+ &dev_attr_kbd_rgb_state.attr,
-+ &dev_attr_kbd_rgb_state_index.attr,
-+ NULL,
-+};
-+
-+static const struct attribute_group kbd_rgb_state_group = {
-+ .attrs = kbd_rgb_state_attrs,
-+};
-+
-+const struct attribute_group *kbd_rgb_mode_groups[] = {
-+ NULL,
-+ NULL,
-+ NULL,
-+};
-
- /* Battery ********************************************************************/
-
-@@ -803,7 +878,7 @@ static ssize_t charge_control_end_threshold_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
- {
-- return sprintf(buf, "%d\n", charge_end_threshold);
-+ return sysfs_emit(buf, "%d\n", charge_end_threshold);
- }
-
- static DEVICE_ATTR_RW(charge_control_end_threshold);
-@@ -1085,7 +1160,12 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
-
- static int asus_wmi_led_init(struct asus_wmi *asus)
- {
-- int rv = 0, led_val;
-+ int rv = 0, num_rgb_groups = 0, led_val;
-+
-+ if (asus->kbd_rgb_mode_available)
-+ kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_mode_group;
-+ if (asus->kbd_rgb_state_available)
-+ kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_state_group;
-
- asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
- if (!asus->led_workqueue)
-@@ -1113,6 +1193,9 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
- asus->kbd_led.brightness_get = kbd_led_get;
- asus->kbd_led.max_brightness = 3;
-
-+ if (num_rgb_groups != 0)
-+ asus->kbd_led.groups = kbd_rgb_mode_groups;
-+
- rv = led_classdev_register(&asus->platform_device->dev,
- &asus->kbd_led);
- if (rv)
-@@ -1587,84 +1670,51 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
- }
-
- /* Panel Overdrive ************************************************************/
--static int panel_od_check_present(struct asus_wmi *asus)
--{
-- u32 result;
-- int err;
--
-- asus->panel_overdrive_available = false;
--
-- err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_PANEL_OD, &result);
-- if (err) {
-- if (err == -ENODEV)
-- return 0;
-- return err;
-- }
--
-- if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
-- asus->panel_overdrive_available = true;
-- asus->panel_overdrive = result & ASUS_WMI_DSTS_STATUS_BIT;
-- }
--
-- return 0;
--}
--
--static int panel_od_write(struct asus_wmi *asus)
--{
-- u32 retval;
-- u8 value;
-- int err;
--
-- /* Don't rely on type conversion */
-- value = asus->panel_overdrive ? 1 : 0;
--
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PANEL_OD, value, &retval);
--
-- if (err) {
-- pr_warn("Failed to set panel overdrive: %d\n", err);
-- return err;
-- }
--
-- if (retval > 1) {
-- pr_warn("Failed to set panel overdrive (retval): 0x%x\n", retval);
-- return -EIO;
-- }
--
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "panel_od");
--
-- return 0;
--}
--
- static ssize_t panel_od_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct asus_wmi *asus = dev_get_drvdata(dev);
-+ int result;
-
-- return sysfs_emit(buf, "%d\n", asus->panel_overdrive);
-+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_PANEL_OD);
-+ if (result < 0)
-+ return result;
-+
-+ return sysfs_emit(buf, "%d\n", result);
- }
-
- static ssize_t panel_od_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
-- bool overdrive;
-- int result;
-+ int result, err;
-+ u32 overdrive;
-
- struct asus_wmi *asus = dev_get_drvdata(dev);
-
-- result = kstrtobool(buf, &overdrive);
-+ result = kstrtou32(buf, 10, &overdrive);
- if (result)
- return result;
-
-- asus->panel_overdrive = overdrive;
-- result = panel_od_write(asus);
-+ if (overdrive > 1)
-+ return -EINVAL;
-
-- if (result)
-- return result;
-+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PANEL_OD, overdrive, &result);
-+
-+ if (err) {
-+ pr_warn("Failed to set panel overdrive: %d\n", err);
-+ return err;
-+ }
-+
-+ if (result > 1) {
-+ pr_warn("Failed to set panel overdrive (result): 0x%x\n", result);
-+ return -EIO;
-+ }
-+
-+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "panel_od");
-
- return count;
- }
--
- static DEVICE_ATTR_RW(panel_od);
-
- /* Quirks *********************************************************************/
-@@ -1816,6 +1866,18 @@ static int asus_fan_set_auto(struct asus_wmi *asus)
- return -ENXIO;
- }
-
-+ /*
-+ * Modern models like the G713 also have GPU fan control (this is not AGFN)
-+ */
-+ if (asus->gpu_fan_type == FAN_TYPE_SPEC83) {
-+ status = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_FAN_CTRL,
-+ 0, &retval);
-+ if (status)
-+ return status;
-+
-+ if (retval != 1)
-+ return -EIO;
-+ }
-
- return 0;
- }
-@@ -1853,7 +1915,7 @@ static ssize_t pwm1_show(struct device *dev,
- value = -1;
- }
-
-- return sprintf(buf, "%d\n", value);
-+ return sysfs_emit(buf, "%d\n", value);
- }
-
- static ssize_t pwm1_store(struct device *dev,
-@@ -1913,7 +1975,7 @@ static ssize_t fan1_input_show(struct device *dev,
- return -ENXIO;
- }
-
-- return sprintf(buf, "%d\n", value < 0 ? -1 : value*100);
-+ return sysfs_emit(buf, "%d\n", value < 0 ? -1 : value * 100);
- }
-
- static ssize_t pwm1_enable_show(struct device *dev,
-@@ -1931,7 +1993,7 @@ static ssize_t pwm1_enable_show(struct device *dev,
- * in practice on X532FL at least (the bit is always 0) and there's
- * also nothing in the DSDT to indicate that this behaviour exists.
- */
-- return sprintf(buf, "%d\n", asus->fan_pwm_mode);
-+ return sysfs_emit(buf, "%d\n", asus->fan_pwm_mode);
- }
-
- static ssize_t pwm1_enable_store(struct device *dev,
-@@ -1999,7 +2061,7 @@ static ssize_t fan1_label_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
-- return sprintf(buf, "%s\n", ASUS_FAN_DESC);
-+ return sysfs_emit(buf, "%s\n", ASUS_FAN_DESC);
- }
-
- static ssize_t asus_hwmon_temp1(struct device *dev,
-@@ -2018,11 +2080,86 @@ static ssize_t asus_hwmon_temp1(struct device *dev,
- deci_kelvin_to_millicelsius(value & 0xFFFF));
- }
-
-+/* GPU fan on modern ROG laptops */
-+static ssize_t fan2_input_show(struct device *dev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ int value;
-+ int ret;
-+
-+ ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_GPU_FAN_CTRL, &value);
-+ if (ret < 0)
-+ return ret;
-+
-+ value &= 0xffff;
-+
-+ return sysfs_emit(buf, "%d\n", value < 0 ? -1 : value * 100);
-+}
-+
-+static ssize_t fan2_label_show(struct device *dev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ return sprintf(buf, "%s\n", ASUS_GPU_FAN_DESC);
-+}
-+
-+static ssize_t pwm2_enable_show(struct device *dev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+
-+ return sysfs_emit(buf, "%d\n", asus->gpu_fan_pwm_mode);
-+}
-+
-+static ssize_t pwm2_enable_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ int state;
-+ int value;
-+ int ret;
-+ u32 retval;
-+
-+ ret = kstrtouint(buf, 10, &state);
-+ if (ret)
-+ return ret;
-+
-+ switch (state) { /* standard documented hwmon values */
-+ case ASUS_FAN_CTRL_FULLSPEED:
-+ value = 1;
-+ break;
-+ case ASUS_FAN_CTRL_AUTO:
-+ value = 0;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_FAN_CTRL,
-+ value, &retval);
-+ if (ret)
-+ return ret;
-+
-+ if (retval != 1)
-+ return -EIO;
-+
-+ asus->gpu_fan_pwm_mode = state;
-+ return count;
-+}
-+
- /* Fan1 */
- static DEVICE_ATTR_RW(pwm1);
- static DEVICE_ATTR_RW(pwm1_enable);
- static DEVICE_ATTR_RO(fan1_input);
- static DEVICE_ATTR_RO(fan1_label);
-+/* Fan2 - GPU fan */
-+static DEVICE_ATTR_RW(pwm2_enable);
-+static DEVICE_ATTR_RO(fan2_input);
-+static DEVICE_ATTR_RO(fan2_label);
-
- /* Temperature */
- static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL);
-@@ -2030,8 +2167,11 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL);
- static struct attribute *hwmon_attributes[] = {
- &dev_attr_pwm1.attr,
- &dev_attr_pwm1_enable.attr,
-+ &dev_attr_pwm2_enable.attr,
- &dev_attr_fan1_input.attr,
- &dev_attr_fan1_label.attr,
-+ &dev_attr_fan2_input.attr,
-+ &dev_attr_fan2_label.attr,
-
- &dev_attr_temp1_input.attr,
- NULL
-@@ -2040,7 +2180,7 @@ static struct attribute *hwmon_attributes[] = {
- static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
- struct attribute *attr, int idx)
- {
-- struct device *dev = container_of(kobj, struct device, kobj);
-+ struct device *dev = kobj_to_dev(kobj);
- struct asus_wmi *asus = dev_get_drvdata(dev->parent);
- u32 value = ASUS_WMI_UNSUPPORTED_METHOD;
-
-@@ -2052,6 +2192,11 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
- || attr == &dev_attr_pwm1_enable.attr) {
- if (asus->fan_type == FAN_TYPE_NONE)
- return 0;
-+ } else if (attr == &dev_attr_fan2_input.attr
-+ || attr == &dev_attr_fan2_label.attr
-+ || attr == &dev_attr_pwm2_enable.attr) {
-+ if (asus->gpu_fan_type == FAN_TYPE_NONE)
-+ return 0;
- } else if (attr == &dev_attr_temp1_input.attr) {
- int err = asus_wmi_get_devstate(asus,
- ASUS_WMI_DEVID_THERMAL_CTRL,
-@@ -2094,6 +2239,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
-
- static int asus_wmi_fan_init(struct asus_wmi *asus)
- {
-+ asus->gpu_fan_type = FAN_TYPE_NONE;
- asus->fan_type = FAN_TYPE_NONE;
- asus->agfn_pwm = -1;
-
-@@ -2102,6 +2248,10 @@ static int asus_wmi_fan_init(struct asus_wmi *asus)
- else if (asus_wmi_has_agfn_fan(asus))
- asus->fan_type = FAN_TYPE_AGFN;
-
-+ /* Modern models like G713 also have GPU fan control */
-+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_FAN_CTRL))
-+ asus->gpu_fan_type = FAN_TYPE_SPEC83;
-+
- if (asus->fan_type == FAN_TYPE_NONE)
- return -ENODEV;
-
-@@ -2192,7 +2342,7 @@ static ssize_t fan_boost_mode_show(struct device *dev,
- {
- struct asus_wmi *asus = dev_get_drvdata(dev);
-
-- return scnprintf(buf, PAGE_SIZE, "%d\n", asus->fan_boost_mode);
-+ return sysfs_emit(buf, "%d\n", asus->fan_boost_mode);
- }
-
- static ssize_t fan_boost_mode_store(struct device *dev,
-@@ -2744,7 +2894,7 @@ static ssize_t throttle_thermal_policy_show(struct device *dev,
- struct asus_wmi *asus = dev_get_drvdata(dev);
- u8 mode = asus->throttle_thermal_policy_mode;
-
-- return scnprintf(buf, PAGE_SIZE, "%d\n", mode);
-+ return sysfs_emit(buf, "%d\n", mode);
- }
-
- static ssize_t throttle_thermal_policy_store(struct device *dev,
-@@ -3096,9 +3246,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
- {
- unsigned int key_value = 1;
- bool autorelease = 1;
-- int result, orig_code;
--
-- orig_code = code;
-+ int orig_code = code;
-
- if (asus->driver->key_filter) {
- asus->driver->key_filter(asus->driver, &code, &key_value,
-@@ -3141,38 +3289,18 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
- return;
- }
-
-- if (asus->driver->quirks->tablet_switch_mode == asus_wmi_kbd_dock_devid &&
-- code == NOTIFY_KBD_DOCK_CHANGE) {
-- result = asus_wmi_get_devstate_simple(asus,
-- ASUS_WMI_DEVID_KBD_DOCK);
-- if (result >= 0) {
-- input_report_switch(asus->inputdev, SW_TABLET_MODE,
-- !result);
-- input_sync(asus->inputdev);
-- }
-- return;
-- }
--
-- if (asus->driver->quirks->tablet_switch_mode == asus_wmi_lid_flip_devid &&
-- code == NOTIFY_LID_FLIP) {
-- lid_flip_tablet_mode_get_state(asus);
-- return;
-- }
--
-- if (asus->driver->quirks->tablet_switch_mode == asus_wmi_lid_flip_rog_devid &&
-- code == NOTIFY_LID_FLIP_ROG) {
-- lid_flip_rog_tablet_mode_get_state(asus);
-+ if (code == asus->tablet_switch_event_code) {
-+ asus_wmi_tablet_mode_get_state(asus);
- return;
- }
-
-- if (asus->fan_boost_mode_available && code == NOTIFY_KBD_FBM) {
-- fan_boost_mode_switch_next(asus);
-+ if (code == NOTIFY_KBD_FBM || code == NOTIFY_KBD_TTP) {
-+ if (asus->fan_boost_mode_available)
-+ fan_boost_mode_switch_next(asus);
-+ if (asus->throttle_thermal_policy_available)
-+ throttle_thermal_policy_switch_next(asus);
- return;
-- }
-
-- if (asus->throttle_thermal_policy_available && code == NOTIFY_KBD_TTP) {
-- throttle_thermal_policy_switch_next(asus);
-- return;
- }
-
- if (is_display_toggle(code) && asus->driver->quirks->no_display_toggle)
-@@ -3324,6 +3452,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,
-@@ -3335,7 +3464,7 @@ static struct attribute *platform_attributes[] = {
- static umode_t asus_sysfs_is_visible(struct kobject *kobj,
- struct attribute *attr, int idx)
- {
-- struct device *dev = container_of(kobj, struct device, kobj);
-+ struct device *dev = kobj_to_dev(kobj);
- struct asus_wmi *asus = dev_get_drvdata(dev);
- bool ok = true;
- int devid = -1;
-@@ -3354,6 +3483,10 @@ 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_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)
-@@ -3615,13 +3748,12 @@ static int asus_wmi_add(struct platform_device *pdev)
- if (err)
- goto fail_platform;
-
-- err = egpu_enable_check_present(asus);
-- if (err)
-- goto fail_egpu_enable;
--
-- err = dgpu_disable_check_present(asus);
-- if (err)
-- goto fail_dgpu_disable;
-+ 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->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE);
-+ asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE);
-+ asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD);
-
- err = fan_boost_mode_check_present(asus);
- if (err)
-@@ -3637,10 +3769,6 @@ static int asus_wmi_add(struct platform_device *pdev)
- if (err)
- goto fail_platform_profile_setup;
-
-- err = panel_od_check_present(asus);
-- if (err)
-- goto fail_panel_od;
--
- err = asus_wmi_sysfs_init(asus->platform_device);
- if (err)
- goto fail_sysfs;
-@@ -3735,10 +3863,7 @@ static int asus_wmi_add(struct platform_device *pdev)
- if (asus->platform_profile_support)
- platform_profile_remove();
- fail_fan_boost_mode:
--fail_egpu_enable:
--fail_dgpu_disable:
- fail_platform:
--fail_panel_od:
- kfree(asus);
- return err;
- }
-@@ -3797,18 +3922,7 @@ static int asus_hotk_resume(struct device *device)
- if (asus_wmi_has_fnlock_key(asus))
- asus_wmi_fnlock_update(asus);
-
-- switch (asus->driver->quirks->tablet_switch_mode) {
-- case asus_wmi_no_tablet_switch:
-- case asus_wmi_kbd_dock_devid:
-- break;
-- case asus_wmi_lid_flip_devid:
-- lid_flip_tablet_mode_get_state(asus);
-- break;
-- case asus_wmi_lid_flip_rog_devid:
-- lid_flip_rog_tablet_mode_get_state(asus);
-- break;
-- }
--
-+ asus_wmi_tablet_mode_get_state(asus);
- return 0;
- }
-
-@@ -3848,18 +3962,7 @@ static int asus_hotk_restore(struct device *device)
- if (asus_wmi_has_fnlock_key(asus))
- asus_wmi_fnlock_update(asus);
-
-- switch (asus->driver->quirks->tablet_switch_mode) {
-- case asus_wmi_no_tablet_switch:
-- case asus_wmi_kbd_dock_devid:
-- break;
-- case asus_wmi_lid_flip_devid:
-- lid_flip_tablet_mode_get_state(asus);
-- break;
-- case asus_wmi_lid_flip_rog_devid:
-- lid_flip_rog_tablet_mode_get_state(asus);
-- break;
-- }
--
-+ asus_wmi_tablet_mode_get_state(asus);
- return 0;
- }
-
-diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
-index 7c96db7f3060..28234dc9fa6a 100644
---- a/include/linux/platform_data/x86/asus-wmi.h
-+++ b/include/linux/platform_data/x86/asus-wmi.h
-@@ -79,6 +79,7 @@
- #define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011
- #define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 /* deprecated */
- #define ASUS_WMI_DEVID_CPU_FAN_CTRL 0x00110013
-+#define ASUS_WMI_DEVID_GPU_FAN_CTRL 0x00110014
- #define ASUS_WMI_DEVID_CPU_FAN_CURVE 0x00110024
- #define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025
-
-@@ -100,6 +101,15 @@
- /* dgpu on/off */
- #define ASUS_WMI_DEVID_DGPU 0x00090020
-
-+/* gpu mux switch, 0 = dGPU, 1 = Optimus */
-+#define ASUS_WMI_DEVID_GPU_MUX 0x00090016
-+
-+/* TUF laptop RGB modes/colours */
-+#define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056
-+
-+/* TUF laptop RGB power/state */
-+#define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057
-+
- /* DSTS masks */
- #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
- #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002
---
-2.38.1
-