diff options
Diffstat (limited to 'SOURCES/asus-linux.patch')
-rw-r--r-- | SOURCES/asus-linux.patch | 2886 |
1 files changed, 899 insertions, 1987 deletions
diff --git a/SOURCES/asus-linux.patch b/SOURCES/asus-linux.patch index 947accc..1276952 100644 --- a/SOURCES/asus-linux.patch +++ b/SOURCES/asus-linux.patch @@ -1,158 +1,42 @@ -From 170f0da25dac630dacb920d043fb20e12c287520 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Tue, 9 Aug 2022 14:50:53 +1200 -Subject: [PATCH 01/19] platform/x86: asus-wmi: Convert all attr-show to use - sysfs_emit +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 -This changes all *_show attributes in asus-wmi.c to use sysfs_emit() -instead of the older method of writing to the output buffer manually. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> -Link: https://lore.kernel.org/r/20220809025054.1626339-6-luke@ljones.dev -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/platform/x86/asus-wmi.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 89b604e04d7f..b5c977d37bc1 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -771,7 +771,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); -@@ -1819,7 +1819,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, -@@ -1879,7 +1879,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, -@@ -1897,7 +1897,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, -@@ -1965,7 +1965,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, -@@ -2158,7 +2158,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, -@@ -2711,7 +2711,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, --- -2.37.2 - -From a8f9c36c4bb705af4b6054244ff9669cdd8dcf71 Mon Sep 17 00:00:00 2001 -From: ye xingchen <ye.xingchen@zte.com.cn> -Date: Thu, 11 Aug 2022 01:32:03 +0000 -Subject: [PATCH 02/19] platform/x86: asus-wmi: Use kobj_to_dev() - -Use kobj_to_dev() instead of open-coding it. - -Reported-by: Zeal Robot <zealci@zte.com.cn> -Signed-off-by: ye xingchen <ye.xingchen@zte.com.cn> -Link: https://lore.kernel.org/r/20220811013203.16010-1-ye.xingchen@zte.com.cn -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Jan200101 <sentrycraft123@gmail.com> --- - drivers/platform/x86/asus-wmi.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index b5c977d37bc1..e461299d938a 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -2006,7 +2006,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; - -@@ -3294,7 +3294,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; --- -2.37.2 - -From 7e64c486e807c8edfbd3a0c8e44ad7a1896dbec8 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 10:25:04 +1200 -Subject: [PATCH 03/19] platform/x86: asus-wmi: Document the dgpu_disable sysfs - attribute - -The dgpu_disable attribute was not documented, this adds the -required documentation. - -Fixes: 98829e84dc67 ("asus-wmi: Add dgpu disable method") -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Link: https://lore.kernel.org/r/20220812222509.292692-2-luke@ljones.dev -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - Documentation/ABI/testing/sysfs-platform-asus-wmi | 9 +++++++++ - 1 file changed, 9 insertions(+) + .../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..0f8f0772d6f3 100644 +index 04885738cf15..a77a004a1baa 100644 --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -57,3 +57,12 @@ Description: +@@ -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 @@ -161,35 +45,6 @@ index 04885738cf15..0f8f0772d6f3 100644 + Disable discrete GPU: + * 0 - Enable dGPU, + * 1 - Disable dGPU --- -2.37.2 - -From 3206376f099d9c74d9938b9c41cfc0b85ea6e1b0 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 10:25:05 +1200 -Subject: [PATCH 04/19] platform/x86: asus-wmi: Document the egpu_enable sysfs - attribute - -The egpu_enable attribute was not documented, this adds the -required documentation. - -Fixes: 382b91db8044 ("asus-wmi: Add egpu enable method") -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Link: https://lore.kernel.org/r/20220812222509.292692-3-luke@ljones.dev -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - Documentation/ABI/testing/sysfs-platform-asus-wmi | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index 0f8f0772d6f3..ac5ec3a17c51 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -66,3 +66,14 @@ Description: - Disable discrete GPU: - * 0 - Enable dGPU, - * 1 - Disable dGPU + +What: /sys/devices/platform/<platform>/egpu_enable +Date: Aug 2022 @@ -201,35 +56,6 @@ index 0f8f0772d6f3..ac5ec3a17c51 100644 + + * 0 - Disable, + * 1 - Enable --- -2.37.2 - -From d956c889be804742e39fbb3291b054b3cbf505be Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 10:25:06 +1200 -Subject: [PATCH 05/19] platform/x86: asus-wmi: Document the panel_od sysfs - attribute - -The panel_od attribute was not documented, this adds the -required documentation. - -Fixes: ca91ea34778f ("asus-wmi: Add panel overdrive functionality") -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Link: https://lore.kernel.org/r/20220812222509.292692-4-luke@ljones.dev -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - Documentation/ABI/testing/sysfs-platform-asus-wmi | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index ac5ec3a17c51..4d63824713ac 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -77,3 +77,12 @@ Description: - - * 0 - Disable, - * 1 - Enable + +What: /sys/devices/platform/<platform>/panel_od +Date: Aug 2022 @@ -239,1137 +65,243 @@ index ac5ec3a17c51..4d63824713ac 100644 + Enable an LCD response-time boost to reduce or remove ghosting: + * 0 - Disable, + * 1 - Enable --- -2.37.2 - -From cdf36fc865f0aff8de5a9afc3654f114c4d04cba Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 10:25:07 +1200 -Subject: [PATCH 06/19] platform/x86: asus-wmi: Refactor disable_gpu attribute - -The settings for these attributes can be read from the device, this -is now done instead of reading a stored value from module. The stored -value is also removed. - -This means the simpler asus_wmi_dev_is_present() can be used in -*_check_present() - it is not an error for these methods to be -missing. - -The _write() functions have their bodies shifted in to *_store() -which simplifies things further. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Link: https://lore.kernel.org/r/20220812222509.292692-5-luke@ljones.dev -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/platform/x86/asus-wmi.c | 73 +++++++++++---------------------- - 1 file changed, 24 insertions(+), 49 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index e461299d938a..f58cbda862d2 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -233,7 +233,6 @@ struct asus_wmi { - bool egpu_enable; - - bool dgpu_disable_available; -- bool dgpu_disable; - - bool throttle_thermal_policy_available; - u8 throttle_thermal_policy_mode; -@@ -563,47 +562,10 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) - /* dGPU ********************************************************************/ - static int dgpu_disable_check_present(struct asus_wmi *asus) - { -- 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; -- } -- -- if (result & ASUS_WMI_DSTS_PRESENCE_BIT) { -+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU)) - asus->dgpu_disable_available = true; -- asus->dgpu_disable = result & ASUS_WMI_DSTS_STATUS_BIT; -- } -- -- return 0; --} -- --static int dgpu_disable_write(struct asus_wmi *asus) --{ -- u32 retval; -- u8 value; -- int err; -- -- /* Don't rely on type conversion */ -- value = asus->dgpu_disable ? 1 : 0; -- -- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, value, &retval); -- 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); -- return -EIO; -- } -- -- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "dgpu_disable"); - - return 0; - } -@@ -612,9 +574,13 @@ static ssize_t dgpu_disable_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_DGPU); -+ if (result < 0) -+ return result; -+ -+ return sysfs_emit(buf, "%d\n", result); - } - - /* -@@ -627,24 +593,33 @@ static ssize_t dgpu_disable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) - { -- bool disable; -- int result; -+ int result, err; -+ u32 disable; - - struct asus_wmi *asus = dev_get_drvdata(dev); - -- result = kstrtobool(buf, &disable); -+ result = kstrtou32(buf, 10, &disable); - if (result) - return result; - -- asus->dgpu_disable = disable; -+ if (disable > 1) -+ return -EINVAL; - -- result = dgpu_disable_write(asus); -- if (result) -- return result; -+ 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(&asus->platform_device->dev.kobj, NULL, "dgpu_disable"); - - return count; - } -- - static DEVICE_ATTR_RW(dgpu_disable); - - /* eGPU ********************************************************************/ --- -2.37.2 - -From 36450e7db0fe55c338f32059382a2d8342cbc9a1 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 10:25:08 +1200 -Subject: [PATCH 07/19] platform/x86: asus-wmi: Refactor egpu_enable attribute - -The settings for these attributes can be read from the device, this -is now done instead of reading a stored value from module. The stored -value is also removed. - -This means the simpler asus_wmi_dev_is_present() can be used in -*_check_present() - it is not an error for these methods to be -missing. - -The _write() functions have their bodies shifted in to *_store() -which simplifies things further. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Link: https://lore.kernel.org/r/20220812222509.292692-6-luke@ljones.dev -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/platform/x86/asus-wmi.c | 84 ++++++++++----------------------- - 1 file changed, 26 insertions(+), 58 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index f58cbda862d2..c82e7b128444 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -229,9 +229,7 @@ struct asus_wmi { - 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 throttle_thermal_policy_available; -@@ -625,48 +623,10 @@ static DEVICE_ATTR_RW(dgpu_disable); - /* eGPU ********************************************************************/ - static int egpu_enable_check_present(struct asus_wmi *asus) - { -- u32 result; -- int err; -- - asus->egpu_enable_available = false; - -- err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_EGPU, &result); -- if (err) { -- if (err == -ENODEV) -- return 0; -- return err; -- } -- -- if (result & ASUS_WMI_DSTS_PRESENCE_BIT) { -+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU)) - asus->egpu_enable_available = true; -- asus->egpu_enable = result & ASUS_WMI_DSTS_STATUS_BIT; -- } -- -- return 0; --} -- --static int egpu_enable_write(struct asus_wmi *asus) --{ -- u32 retval; -- u8 value; -- int err; -- -- /* Don't rely on type conversion */ -- value = asus->egpu_enable ? 1 : 0; -- -- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, value, &retval); -- -- if (err) { -- pr_warn("Failed to set egpu disable: %d\n", err); -- return err; -- } -- -- if (retval > 1) { -- pr_warn("Failed to set egpu disable (retval): 0x%x\n", retval); -- return -EIO; -- } -- -- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "egpu_enable"); - - return 0; - } -@@ -675,9 +635,13 @@ static ssize_t egpu_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) - { - struct asus_wmi *asus = dev_get_drvdata(dev); -- bool mode = asus->egpu_enable; -+ 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); - } - - /* The ACPI call to enable the eGPU also disables the internal dGPU */ -@@ -685,29 +649,33 @@ static ssize_t egpu_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) - { -- bool enable; -- int result; -+ int result, err; -+ u32 enable; - - struct asus_wmi *asus = dev_get_drvdata(dev); - -- result = kstrtobool(buf, &enable); -- if (result) -- return result; -+ err = kstrtou32(buf, 10, &enable); -+ if (err) -+ return err; - -- asus->egpu_enable = enable; -+ if (enable > 1) -+ return -EINVAL; - -- result = egpu_enable_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; -+ } - -- /* Ensure that the kernel status of dgpu is updated */ -- result = dgpu_disable_check_present(asus); -- if (result) -- return result; -+ 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); - - /* Battery ********************************************************************/ --- -2.37.2 - -From ebc443ad379fad80b8fc350f35cc0652b8447995 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 10:25:09 +1200 -Subject: [PATCH 08/19] platform/x86: asus-wmi: Refactor panel_od attribute - -The settings for these attributes can be read from the device, this -is now done instead of reading a stored value from module. The stored -value is also removed. - -This means the simpler asus_wmi_dev_is_present() can be used in -*_check_present() - it is not an error for these methods to be -missing. - -The _write() functions have their bodies shifted in to *_store() -which simplifies things further. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Link: https://lore.kernel.org/r/20220812222509.292692-7-luke@ljones.dev -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/platform/x86/asus-wmi.c | 74 +++++++++++---------------------- - 1 file changed, 25 insertions(+), 49 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index c82e7b128444..2d9d709aa59f 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -246,7 +246,6 @@ struct asus_wmi { - bool battery_rsoc_available; - - bool panel_overdrive_available; -- bool panel_overdrive; - - struct hotplug_slot hotplug_slot; - struct mutex hotplug_lock; -@@ -1500,48 +1499,10 @@ 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) { -+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD)) - 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; - } -@@ -1550,32 +1511,47 @@ 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 *********************************************************************/ --- -2.37.2 - -From 3c3b55564afa8b7d952ce2ba90e7f522832ed0f7 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 15 Aug 2022 17:05:38 +0200 -Subject: [PATCH 09/19] platform/x86: asus-wmi: Simplify some of the - *_check_present() helpers - -After the recent cleanup patches, some of the *_check_present() helpers -just propagate the result of asus_wmi_dev_is_present(). - -Replace these with direct asus_wmi_dev_is_present() calls as a further -cleanup. - -Cc: Luke D. Jones <luke@ljones.dev> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Link: https://lore.kernel.org/r/20220815150538.474306-1-hdegoede@redhat.com ---- - drivers/platform/x86/asus-wmi.c | 47 +++------------------------------ - 1 file changed, 3 insertions(+), 44 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 2d9d709aa59f..d72491fb218b 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -557,16 +557,6 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) - } - - /* dGPU ********************************************************************/ --static int dgpu_disable_check_present(struct asus_wmi *asus) --{ -- asus->dgpu_disable_available = false; -- -- if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU)) -- asus->dgpu_disable_available = true; -- -- return 0; --} -- - static ssize_t dgpu_disable_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -@@ -620,16 +610,6 @@ static ssize_t dgpu_disable_store(struct device *dev, - static DEVICE_ATTR_RW(dgpu_disable); - - /* eGPU ********************************************************************/ --static int egpu_enable_check_present(struct asus_wmi *asus) --{ -- asus->egpu_enable_available = false; -- -- if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU)) -- asus->egpu_enable_available = true; -- -- return 0; --} -- - static ssize_t egpu_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -@@ -1497,16 +1477,6 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus) - } - - /* Panel Overdrive ************************************************************/ --static int panel_od_check_present(struct asus_wmi *asus) --{ -- asus->panel_overdrive_available = false; -- -- if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD)) -- asus->panel_overdrive_available = true; -- -- return 0; --} -- - static ssize_t panel_od_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -@@ -3493,13 +3463,9 @@ 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->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); - - err = fan_boost_mode_check_present(asus); - if (err) -@@ -3515,10 +3481,6 @@ static int asus_wmi_add(struct platform_device *pdev) - if (err) - goto fail_platform_profile_setup; +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) -- 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; -@@ -3613,10 +3575,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; - } --- -2.37.2 - -From 01ef026ab36357a818c7d8324a36dbb8beff6ff5 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 21:26:24 +1200 -Subject: [PATCH 10/19] 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> ---- - .../ABI/testing/sysfs-platform-asus-wmi | 12 +++++ - drivers/platform/x86/asus-wmi.c | 51 +++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 3 ++ - 3 files changed, 66 insertions(+) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index 4d63824713ac..a77a004a1baa 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -58,6 +58,18 @@ Description: - * 1 - overboost, - * 2 - silent +@@ -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; -+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, ++ if (KBGUARD_EN & activestatus) ++ sensor_id[num_of_sensors++] = KBGUARD_IDX; + - What: /sys/devices/platform/<platform>/dgpu_disable - Date: Aug 2022 - KernelVersion: 5.17 -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index d72491fb218b..46d0dd96a351 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -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, + return num_of_sensors; } - 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); -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 98f2b2f20f3e..70d2347bf6ca 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -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 --- -2.37.2 - -From 00aa846955fbfb04f7bc0c26c49febfe5395eca1 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 21:27:52 +1200 -Subject: [PATCH 11/19] platform/x86: asus-wmi: Adjust tablet/lidflip handling - to use enum - -Due to multiple types of tablet/lidflip, the existing code for -handling these events is refactored to use an enum for each type. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Link: https://lore.kernel.org/r/20220813092753.6635-1-luke@ljones.dev -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/platform/x86/asus-nb-wmi.c | 13 +++----- - drivers/platform/x86/asus-wmi.c | 49 +++++++++++++++++++++--------- - drivers/platform/x86/asus-wmi.h | 9 ++++-- - 3 files changed, 47 insertions(+), 24 deletions(-) - -diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c -index 478dd300b9c9..4672a2b8322e 100644 ---- a/drivers/platform/x86/asus-nb-wmi.c -+++ b/drivers/platform/x86/asus-nb-wmi.c -@@ -115,12 +115,12 @@ static struct quirk_entry quirk_asus_forceals = { - }; - - static struct quirk_entry quirk_asus_use_kbd_dock_devid = { -- .use_kbd_dock_devid = true, -+ .tablet_switch_mode = asus_wmi_kbd_dock_devid, - }; - - static struct quirk_entry quirk_asus_use_lid_flip_devid = { - .wmi_backlight_set_devstate = true, -- .use_lid_flip_devid = true, -+ .tablet_switch_mode = asus_wmi_lid_flip_devid, - }; +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 - static int dmi_matched(const struct dmi_system_id *dmi) -@@ -492,16 +492,13 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) + #define HPD_IDX 16 ++#define KBGUARD_IDX 15 - switch (tablet_mode_sw) { - case 0: -- quirks->use_kbd_dock_devid = false; -- quirks->use_lid_flip_devid = false; -+ quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; - break; - case 1: -- quirks->use_kbd_dock_devid = true; -- quirks->use_lid_flip_devid = false; -+ quirks->tablet_switch_mode = asus_wmi_kbd_dock_devid; + #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 2: -- quirks->use_kbd_dock_devid = false; -- quirks->use_lid_flip_devid = true; -+ quirks->tablet_switch_mode = asus_wmi_lid_flip_devid; ++ 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; } - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 46d0dd96a351..fe2d072e1acc 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -486,8 +486,11 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) - - static int asus_wmi_input_init(struct asus_wmi *asus) - { -+ struct device *dev; - int err, result; - -+ dev = &asus->platform_device->dev; -+ - asus->inputdev = input_allocate_device(); - if (!asus->inputdev) - return -ENOMEM; -@@ -495,35 +498,38 @@ static int asus_wmi_input_init(struct asus_wmi *asus) - asus->inputdev->name = asus->driver->input_name; - asus->inputdev->phys = asus->driver->input_phys; - asus->inputdev->id.bustype = BUS_HOST; -- asus->inputdev->dev.parent = &asus->platform_device->dev; -+ asus->inputdev->dev.parent = dev; - set_bit(EV_REP, asus->inputdev->evbit); - - err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL); - if (err) - goto err_free_dev; - -- if (asus->driver->quirks->use_kbd_dock_devid) { -+ switch (asus->driver->quirks->tablet_switch_mode) { -+ 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) { -- pr_err("Error checking for keyboard-dock: %d\n", result); -+ dev_err(dev, "Error checking for keyboard-dock: %d\n", result); - } -- } -- -- if (asus->driver->quirks->use_lid_flip_devid) { -+ 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->use_lid_flip_devid = 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) { -- pr_err("This device has lid_flip quirk but got ENODEV checking it. This is a bug."); -+ dev_err(dev, "This device has lid_flip quirk but got ENODEV checking it. This is a bug."); - } else { -- pr_err("Error checking for lid-flip: %d\n", result); -+ dev_err(dev, "Error checking for lid-flip: %d\n", result); +@@ -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; - } - - err = input_register_device(asus->inputdev); -@@ -549,8 +555,9 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) - - static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) - { -- int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); -+ 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); -@@ -3044,7 +3051,8 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) - return; - } - -- if (asus->driver->quirks->use_kbd_dock_devid && code == NOTIFY_KBD_DOCK_CHANGE) { -+ 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) { -@@ -3055,7 +3063,8 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) - return; - } -- if (asus->driver->quirks->use_lid_flip_devid && code == NOTIFY_LID_FLIP) { -+ if (asus->driver->quirks->tablet_switch_mode == asus_wmi_lid_flip_devid && -+ code == NOTIFY_LID_FLIP) { - lid_flip_tablet_mode_get_state(asus); - return; - } -@@ -3685,8 +3694,14 @@ static int asus_hotk_resume(struct device *device) - if (asus_wmi_has_fnlock_key(asus)) - asus_wmi_fnlock_update(asus); + 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; -- if (asus->driver->quirks->use_lid_flip_devid) -+ 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); +@@ -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; -+ } - return 0; - } -@@ -3727,8 +3742,14 @@ static int asus_hotk_restore(struct device *device) - if (asus_wmi_has_fnlock_key(asus)) - asus_wmi_fnlock_update(asus); + 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; -- if (asus->driver->quirks->use_lid_flip_devid) -+ 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; -+ } ++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 */ + }; - return 0; - } -diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h -index b302415bf1d9..413920bad0c6 100644 ---- a/drivers/platform/x86/asus-wmi.h -+++ b/drivers/platform/x86/asus-wmi.h -@@ -25,6 +25,12 @@ struct module; - struct key_entry; - struct asus_wmi; - -+enum asus_wmi_tablet_switch_mode { -+ asus_wmi_no_tablet_switch, -+ asus_wmi_kbd_dock_devid, -+ asus_wmi_lid_flip_devid, ++ ++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 +}; + - struct quirk_entry { - bool hotplug_wireless; - bool scalar_panel_brightness; -@@ -33,8 +39,7 @@ struct quirk_entry { - bool wmi_backlight_native; - bool wmi_backlight_set_devstate; - bool wmi_force_als_set; -- bool use_kbd_dock_devid; -- bool use_lid_flip_devid; -+ enum asus_wmi_tablet_switch_mode tablet_switch_mode; - int wapf; - /* - * For machines with AMD graphic chips, it will send out WMI event --- -2.37.2 - -From e397c3c460bf3849384f2f55516d1887617cfca9 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 13 Aug 2022 21:27:53 +1200 -Subject: [PATCH 12/19] platform/x86: asus-wmi: Add support for ROG X13 tablet - mode - -Add quirk for ASUS ROG X13 Flow 2-in-1 to enable tablet mode with -lid flip (all screen rotations). - -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Link: https://lore.kernel.org/r/20220813092753.6635-2-luke@ljones.dev -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/platform/x86/asus-nb-wmi.c | 15 +++++++++ - drivers/platform/x86/asus-wmi.c | 37 ++++++++++++++++++++++ - drivers/platform/x86/asus-wmi.h | 1 + - include/linux/platform_data/x86/asus-wmi.h | 1 + - 4 files changed, 54 insertions(+) - + /* 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 4672a2b8322e..d9e7cf6e4a0e 100644 +index d9e7cf6e4a0e..fcfe6dddd645 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c -@@ -123,6 +123,11 @@ static struct quirk_entry quirk_asus_use_lid_flip_devid = { - .tablet_switch_mode = asus_wmi_lid_flip_devid, - }; - -+static struct quirk_entry quirk_asus_tablet_mode = { -+ .wmi_backlight_set_devstate = true, -+ .tablet_switch_mode = asus_wmi_lid_flip_rog_devid, -+}; -+ - static int dmi_matched(const struct dmi_system_id *dmi) - { - pr_info("Identified laptop model '%s'\n", dmi->ident); -@@ -471,6 +476,15 @@ static const struct dmi_system_id asus_quirks[] = { - }, - .driver_data = &quirk_asus_use_lid_flip_devid, - }, -+ { -+ .callback = dmi_matched, -+ .ident = "ASUS ROG FLOW X13", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "GV301Q"), -+ }, -+ .driver_data = &quirk_asus_tablet_mode, -+ }, - {}, - }; +@@ -504,17 +504,8 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) + else + wapf = quirks->wapf; -@@ -578,6 +592,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { - { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, - { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ - { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */ -+ { KE_KEY, 0xBD, { KEY_PROG2 } }, /* Lid flip action on ROG xflow laptops */ - { KE_END, 0}, - }; +- 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 fe2d072e1acc..5352055848d0 100644 +index dce93187e11f..40e911467037 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c -@@ -68,6 +68,7 @@ module_param(fnlock_default, bool, 0444); - #define NOTIFY_KBD_FBM 0x99 - #define NOTIFY_KBD_TTP 0xae - #define NOTIFY_LID_FLIP 0xfa -+#define NOTIFY_LID_FLIP_ROG 0xbd +@@ -72,6 +72,7 @@ module_param(fnlock_default, bool, 0444); #define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0) -@@ -530,6 +531,19 @@ static int asus_wmi_input_init(struct asus_wmi *asus) - dev_err(dev, "Error checking for lid-flip: %d\n", result); - } - 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); -+ } -+ break; - } - - err = input_register_device(asus->inputdev); -@@ -564,6 +578,17 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) - } - } ++#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; -+static void lid_flip_rog_tablet_mode_get_state(struct asus_wmi *asus) -+{ -+ int result; -+ -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP_ROG); -+ if (result >= 0) { -+ input_report_switch(asus->inputdev, SW_TABLET_MODE, result); -+ input_sync(asus->inputdev); -+ } -+} ++ int tablet_switch_event_code; ++ u32 tablet_switch_dev_id; + - /* dGPU ********************************************************************/ - static ssize_t dgpu_disable_show(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -3069,6 +3094,12 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) - return; - } + enum fan_type fan_type; ++ enum fan_type gpu_fan_type; + int fan_pwm_mode; ++ int gpu_fan_pwm_mode; + int agfn_pwm; -+ 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); -+ return; -+ } + 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; + - if (asus->fan_boost_mode_available && code == NOTIFY_KBD_FBM) { - fan_boost_mode_switch_next(asus); - return; -@@ -3701,6 +3732,9 @@ static int asus_hotk_resume(struct device *device) - 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; - } ++ bool kbd_rgb_mode_available; ++ bool kbd_rgb_state_available; - return 0; -@@ -3749,6 +3783,9 @@ static int asus_hotk_restore(struct device *device) - 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; - } + bool throttle_thermal_policy_available; + u8 throttle_thermal_policy_mode; +@@ -250,7 +257,6 @@ struct asus_wmi { + bool battery_rsoc_available; - return 0; -diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h -index 413920bad0c6..0187f13d2414 100644 ---- a/drivers/platform/x86/asus-wmi.h -+++ b/drivers/platform/x86/asus-wmi.h -@@ -29,6 +29,7 @@ enum asus_wmi_tablet_switch_mode { - asus_wmi_no_tablet_switch, - asus_wmi_kbd_dock_devid, - asus_wmi_lid_flip_devid, -+ asus_wmi_lid_flip_rog_devid, - }; + bool panel_overdrive_available; +- bool panel_overdrive; - struct quirk_entry { -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 70d2347bf6ca..6e8a95c10d17 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -65,6 +65,7 @@ - #define ASUS_WMI_DEVID_PANEL_OD 0x00050019 - #define ASUS_WMI_DEVID_CAMERA 0x00060013 - #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 -+#define ASUS_WMI_DEVID_LID_FLIP_ROG 0x00060077 - - /* Storage */ - #define ASUS_WMI_DEVID_CARDREADER 0x00080013 --- -2.37.2 - -From c98dc61ee08f833e68337700546e120e2edac7c9 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Wed, 24 Aug 2022 17:11:44 +0200 -Subject: [PATCH 13/19] platform/x86: asus-wmi: Simplify tablet-mode-switch - probing - -The 3 different tablet-mode-switch initialization paths repeat a lot -of the same code. Add a helper function for this. - -This also makes the error-handling for the kbd_dock_devid case consistent -with the other 2 cases. - -Cc: Luke D. Jones <luke@ljones.dev> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Link: https://lore.kernel.org/r/20220824151145.1448010-1-hdegoede@redhat.com ---- - drivers/platform/x86/asus-wmi.c | 55 +++++++++++++-------------------- - 1 file changed, 22 insertions(+), 33 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 5352055848d0..d71daa024752 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -484,13 +484,28 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) + 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 **********************************************************************/ @@ -1379,11 +311,11 @@ index 5352055848d0..d71daa024752 100644 + int result; + + result = asus_wmi_get_devstate_simple(asus, dev_id); -+ 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); ++ 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 { @@ -1402,7 +334,7 @@ index 5352055848d0..d71daa024752 100644 asus->inputdev = input_allocate_device(); if (!asus->inputdev) -@@ -510,39 +525,13 @@ static int asus_wmi_input_init(struct asus_wmi *asus) +@@ -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: @@ -1445,86 +377,7 @@ index 5352055848d0..d71daa024752 100644 break; } --- -2.37.2 - -From 1ea0d3b46798afc35c3185f6058b8bc08525d56c Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Wed, 24 Aug 2022 17:11:45 +0200 -Subject: [PATCH 14/19] platform/x86: asus-wmi: Simplify tablet-mode-switch - handling - -Simplify tablet-mode-switch handling: -1. The code is the same for all variants, the only difference is the - dev_id and notify event code. Store the dev_id + code in struct asus_wmi - and unify the handling -2. Make the new unified asus_wmi_tablet_mode_get_state() check dev_id has - been set and make it a no-op when not set. This allows calling it - unconditionally at resume/restore time -3. Simplify the tablet_mode_sw module-param handling, this also allows - selecting the new lid-flip-rog type through the module-param. - -Cc: Luke D. Jones <luke@ljones.dev> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Link: https://lore.kernel.org/r/20220824151145.1448010-2-hdegoede@redhat.com ---- - drivers/platform/x86/asus-nb-wmi.c | 13 +---- - drivers/platform/x86/asus-wmi.c | 76 ++++++------------------------ - 2 files changed, 16 insertions(+), 73 deletions(-) - -diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c -index d9e7cf6e4a0e..cb8af61d684c 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); -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index d71daa024752..0f9f79f249c7 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -222,6 +222,9 @@ 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; - int fan_pwm_mode; - int agfn_pwm; -@@ -490,11 +493,11 @@ static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event - int result; - - result = asus_wmi_get_devstate_simple(asus, dev_id); -- 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); -+ 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 { -@@ -556,22 +559,14 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) +@@ -570,22 +565,14 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) /* Tablet mode ****************************************************************/ @@ -1551,144 +404,246 @@ index d71daa024752..0f9f79f249c7 100644 if (result >= 0) { input_report_switch(asus->inputdev, SW_TABLET_MODE, result); input_sync(asus->inputdev); -@@ -3020,9 +3015,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) +@@ -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) { - unsigned int key_value = 1; - bool autorelease = 1; -- int result, orig_code; +- u32 result; +- int err; - -- orig_code = code; -+ int orig_code = code; +- 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 (asus->driver->key_filter) { - asus->driver->key_filter(asus->driver, &code, &key_value, -@@ -3065,27 +3058,8 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) - return; +- 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 (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 (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; } -@@ -3714,18 +3688,7 @@ static int asus_hotk_resume(struct device *device) - if (asus_wmi_has_fnlock_key(asus)) - asus_wmi_fnlock_update(asus); + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "dgpu_disable"); -- 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; +- return 0; ++ return count; } ++static DEVICE_ATTR_RW(dgpu_disable); -@@ -3765,18 +3728,7 @@ static int asus_hotk_restore(struct device *device) - if (asus_wmi_has_fnlock_key(asus)) - asus_wmi_fnlock_update(asus); +-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; -- 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; +- 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); } --- -2.37.2 - -From 4e821f67963ae0c4dcceadb561077164da5ac79a Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Fri, 26 Aug 2022 10:32:34 +1200 -Subject: [PATCH 17/19] asus-wmi: Implement TUF laptop keyboard LED modes - -Adds support for changing the laptop keyboard LED mode and colour. - -The modes are visible effects such as static, rainbow, pulsing, -colour cycles. - -These sysfs attributes are added to asus::kbd_backlight: -- kbd_rgb_mode -- kbd_rgb_mode_index - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 76 +++++++++++++++++++++- - include/linux/platform_data/x86/asus-wmi.h | 3 + - 2 files changed, 78 insertions(+), 1 deletion(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 0f9f79f249c7..92f16bb9b4ef 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -237,6 +237,8 @@ struct asus_wmi { - bool dgpu_disable_available; - bool gpu_mux_mode_available; +-/* +- * 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; -+ bool kbd_rgb_mode_available; + 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; ++ } + - bool throttle_thermal_policy_available; - u8 throttle_thermal_policy_mode; ++ 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"); -@@ -720,6 +722,69 @@ static ssize_t gpu_mux_mode_store(struct device *dev, + return count; } - static DEVICE_ATTR_RW(gpu_mux_mode); ++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; -+ + 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; @@ -1701,137 +656,56 @@ index 0f9f79f249c7..92f16bb9b4ef 100644 + 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, +}; -+ -+const struct attribute_group *kbd_rgb_mode_groups[] = { -+ NULL, -+ NULL, -+}; -+ - /* Battery ********************************************************************/ - - /* The battery maximum charging percentage */ -@@ -1038,7 +1103,10 @@ 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; - - asus->led_workqueue = create_singlethread_workqueue("led_workqueue"); - if (!asus->led_workqueue) -@@ -1066,6 +1134,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) -@@ -3253,6 +3324,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_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) -@@ -3519,6 +3592,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->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); - asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); - - err = fan_boost_mode_check_present(asus); -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 6e8a95c10d17..3d861477cb20 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -103,6 +103,9 @@ - /* 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 -+ - /* DSTS masks */ - #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 - #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 --- -2.37.2 - -From fa211b90a6ed8973cb50b478a7cb250f5d8d0a12 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Fri, 26 Aug 2022 10:33:20 +1200 -Subject: [PATCH 18/19] asus-wmi: Implement TUF laptop keyboard power states - -Adds support for setting various power states of TUF keyboards. -These states are combinations of: -- boot, set if a boot animation is shown on keyboard -- awake, set if the keyboard LEDs are visible while laptop is on -- sleep, set if an animation is displayed while the laptop is suspended -- keyboard (unknown effect) - -Adds two sysfs attributes to asus::kbd_backlight: -- kbd_rgb_state -- kbd_rgb_state_index - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 57 ++++++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 3 ++ - 2 files changed, 60 insertions(+) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 92f16bb9b4ef..f608a4467d99 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -238,6 +238,7 @@ struct asus_wmi { - 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; -@@ -780,9 +781,62 @@ 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, @@ -1839,10 +713,17 @@ index 92f16bb9b4ef..f608a4467d99 100644 +{ + 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); + @@ -1861,11 +742,12 @@ index 92f16bb9b4ef..f608a4467d99 100644 + ASUS_WMI_DEVID_TUF_RGB_STATE, 0xbd | cmd << 8 | (flags << 16), 0, NULL); + if (err) + return err; -+ -+ return count; -+} + + 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) @@ -1884,312 +766,157 @@ index 92f16bb9b4ef..f608a4467d99 100644 + .attrs = kbd_rgb_state_attrs, +}; + - const struct attribute_group *kbd_rgb_mode_groups[] = { - NULL, - NULL, ++const struct attribute_group *kbd_rgb_mode_groups[] = { + NULL, - }; ++ NULL, ++ NULL, ++}; /* Battery ********************************************************************/ -@@ -1107,6 +1161,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus) - if (asus->kbd_rgb_mode_available) - kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_mode_group; +@@ -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) -@@ -3593,6 +3649,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->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); -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 3d861477cb20..7dd580fdc61c 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -106,6 +106,9 @@ - /* TUF laptop RGB modes/colours */ - #define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 +@@ -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; -+/* TUF laptop RGB power/state */ -+#define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 ++ if (num_rgb_groups != 0) ++ asus->kbd_led.groups = kbd_rgb_mode_groups; + - /* DSTS masks */ - #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 - #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 --- -2.37.2 - -From 802dfc514194e5459397f513b202031228b3315a Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Fri, 26 Aug 2022 12:25:12 +1200 -Subject: [PATCH 19/19] HID: amd_sfh: Add keyguard for ASUS ROG X13 tablet - -Add support for ROG X13 Flow 2-in-1 to disable the keyboard when -the lid is flipped. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - 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 +++++++++++++ - 5 files changed, 59 insertions(+) - -diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c -index 4b90c86ee5f8..0f4db2ce076e 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) + 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) + } -@@ -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; + /* 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; -+ if (KBGUARD_EN & activestatus) -+ sensor_id[num_of_sensors++] = KBGUARD_IDX; +- 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 num_of_sensors; ++ return sysfs_emit(buf, "%d\n", result); } -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; + 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; - 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; + struct asus_wmi *asus = dev_get_drvdata(dev); -@@ -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; +- result = kstrtobool(buf, &overdrive); ++ result = kstrtou32(buf, 10, &overdrive); + if (result) + return result; - 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; +- asus->panel_overdrive = overdrive; +- result = panel_od_write(asus); ++ if (overdrive > 1) ++ return -EINVAL; -+struct kbguard_feature_report { -+ struct common_feature_property common_property; -+} __packed; -+ -+struct kbguard_input_report { -+ struct common_input_property common_property; -+} __packed; +- if (result) +- return result; ++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PANEL_OD, overdrive, &result); + - #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 */ - }; - ++ if (err) { ++ pr_warn("Failed to set panel overdrive: %d\n", err); ++ return err; ++ } + -+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 -+}; ++ if (result > 1) { ++ pr_warn("Failed to set panel overdrive (result): 0x%x\n", result); ++ return -EIO; ++ } + - /* BIOMETRIC PRESENCE*/ - static const u8 hpd_report_descriptor[] = { - 0x05, 0x20, /* Usage page */ --- -2.37.2 - -From 3f73788b14ada783657e5e6303c4e5de5e096be5 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Fri, 26 Aug 2022 12:32:24 +1200 -Subject: [PATCH 20/21] asus-wmi: Modify behaviour of Fn+F5 fan key - -Some more recent TUF laptops have both fan_boost and thermal_throttle. -The key code for Fn+F5 is also different and unmapped. - -This patch adjusts the asus_wmi_handle_event_code() match to match -for both 0x99 and 0xAE, and run both mode switch functions for -fan_boost and/or thermal_throttle if either are available. - -It is required that both are tried, as in some instances the ACPI -set-method for one may not have any code body within it even though -it was returned as supported by the get method. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-nb-wmi.c | 1 + - drivers/platform/x86/asus-wmi.c | 11 +++++------ - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c -index cb8af61d684c..fcfe6dddd645 100644 ---- a/drivers/platform/x86/asus-nb-wmi.c -+++ b/drivers/platform/x86/asus-nb-wmi.c -@@ -577,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 f608a4467d99..ea45e10302f7 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -3190,14 +3190,13 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *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) --- -2.37.2 - -From fe443cc4ff4e12652af1cdae63cff354a2467b67 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Fri, 26 Aug 2022 12:34:02 +1200 -Subject: [PATCH 21/21] asus-wmi: Support the GPU fan on TUF laptops - -Add support for TUF laptops which have the ability to control -the GPU fan. This will show as a second fan in hwmon, and has -the ability to run as boost (fullspeed), or auto. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 71 ++++++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 1 + - 2 files changed, 72 insertions(+) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index ea45e10302f7..d05684194f2d 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -226,7 +226,9 @@ struct asus_wmi { - u32 tablet_switch_dev_id; ++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "panel_od"); - enum fan_type fan_type; -+ enum fan_type gpu_fan_type; - int fan_pwm_mode; -+ int gpu_fan_pwm_mode; - int agfn_pwm; + return count; + } +- + static DEVICE_ATTR_RW(panel_od); - bool fan_boost_mode_available; -@@ -1861,6 +1863,18 @@ static int asus_fan_set_auto(struct asus_wmi *asus) + /* Quirks *********************************************************************/ +@@ -1816,6 +1866,18 @@ static int asus_fan_set_auto(struct asus_wmi *asus) return -ENXIO; } @@ -2208,11 +935,71 @@ index ea45e10302f7..d05684194f2d 100644 return 0; } -@@ -2063,9 +2077,57 @@ static ssize_t asus_hwmon_temp1(struct device *dev, +@@ -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) @@ -2262,29 +1049,49 @@ index ea45e10302f7..d05684194f2d 100644 /* Fan1 */ static DEVICE_ATTR_RW(pwm1); static DEVICE_ATTR_RW(pwm1_enable); -+static DEVICE_ATTR_RW(pwm2_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); -@@ -2075,6 +2137,7 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL); + /* 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; -@@ -2097,6 +2160,9 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, +@@ -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_pwm2_enable.attr) { ++ } 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, -@@ -2139,6 +2205,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus) +@@ -2094,6 +2239,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus) static int asus_wmi_fan_init(struct asus_wmi *asus) { @@ -2292,7 +1099,7 @@ index ea45e10302f7..d05684194f2d 100644 asus->fan_type = FAN_TYPE_NONE; asus->agfn_pwm = -1; -@@ -2147,6 +2214,10 @@ static int asus_wmi_fan_init(struct asus_wmi *asus) +@@ -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; @@ -2303,8 +1110,193 @@ index ea45e10302f7..d05684194f2d 100644 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 7dd580fdc61c..28234dc9fa6a 100644 +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 @@ @@ -2315,102 +1307,22 @@ index 7dd580fdc61c..28234dc9fa6a 100644 #define ASUS_WMI_DEVID_CPU_FAN_CURVE 0x00110024 #define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025 --- -2.37.2 - -From ded47e7197a4ce9d6c34c0c96c6551ecaca0b6bd Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Fri, 16 Sep 2022 11:17:16 +1200 -Subject: [PATCH] asus-wmi: Expand support of GPU fan to read RPM and label - -The previously added patch to add support for pwm change for TUF laptops -also is usuable for more than TUF. The same method `0x00110014` is -used to read the fan RPM. - -Add two extra attributes for reading fan2 plus fan2 label. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 36 +++++++++++++++++++++++++++++++-- - 1 file changed, 34 insertions(+), 2 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index ae46af731de9..7fe6ce25da0a 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 -@@ -2078,6 +2079,30 @@ static ssize_t asus_hwmon_temp1(struct device *dev, - } +@@ -100,6 +101,15 @@ + /* dgpu on/off */ + #define ASUS_WMI_DEVID_DGPU 0x00090020 - /* 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; ++/* gpu mux switch, 0 = dGPU, 1 = Optimus */ ++#define ASUS_WMI_DEVID_GPU_MUX 0x00090016 + -+ return sysfs_emit(buf, "%d\n", value < 0 ? -1 : value * 100); -+} ++/* TUF laptop RGB modes/colours */ ++#define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 + -+static ssize_t fan2_label_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ return sprintf(buf, "%s\n", ASUS_GPU_FAN_DESC); -+} ++/* TUF laptop RGB power/state */ ++#define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 + - static ssize_t pwm2_enable_show(struct device *dev, - struct device_attribute *attr, - char *buf) -@@ -2127,9 +2152,12 @@ static ssize_t pwm2_enable_store(struct device *dev, - /* Fan1 */ - static DEVICE_ATTR_RW(pwm1); - static DEVICE_ATTR_RW(pwm1_enable); --static DEVICE_ATTR_RW(pwm2_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); -@@ -2140,6 +2168,8 @@ static struct attribute *hwmon_attributes[] = { - &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 -@@ -2160,7 +2190,9 @@ 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_pwm2_enable.attr) { -+ } 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) { + /* DSTS masks */ + #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 + #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 -- -2.37.3 +2.38.1 |