From 362ea901b8997d274fa1eea2d04109e2f808b319 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Sun, 21 Jul 2024 21:19:53 +0200 Subject: kernel 6.9.9 Ally X Quirk Patch Two: Electric Boogaloo --- ...d-ally-x-dmi-quirk-for-controller-suspend.patch | 227 ++++++++++++--------- 1 file changed, 127 insertions(+), 100 deletions(-) (limited to 'SOURCES') diff --git a/SOURCES/0001-add-ally-x-dmi-quirk-for-controller-suspend.patch b/SOURCES/0001-add-ally-x-dmi-quirk-for-controller-suspend.patch index e0f47aa..6e5747a 100644 --- a/SOURCES/0001-add-ally-x-dmi-quirk-for-controller-suspend.patch +++ b/SOURCES/0001-add-ally-x-dmi-quirk-for-controller-suspend.patch @@ -1,125 +1,152 @@ -From 650af3af1d5ebd5e5b759c503147f2fbc88ac3b7 Mon Sep 17 00:00:00 2001 +From bb91e2a266689d3549d06c0db57d898fce7cfd89 Mon Sep 17 00:00:00 2001 From: antheas -Date: Sat, 20 Jul 2024 19:43:36 +0300 -Subject: [PATCH v2 1/3] allyx: add quirk for suspending controllers +Date: Sun, 21 Jul 2024 22:15:10 +0300 +Subject: [PATCH v2] allyx: switch to lps0 delay for controller suspend --- - drivers/platform/x86/asus-wmi.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) + drivers/platform/x86/asus-wmi.c | 86 ++++++++++++++++++--------------- + 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 3f9b6285c..8e362726b 100644 +index 4b78c4f..0345d52 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c -@@ -4645,8 +4645,10 @@ 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->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); -- asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) -- && dmi_match(DMI_BOARD_NAME, "RC71L"); -+ asus->ally_mcu_usb_switch = -+ acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) && -+ (dmi_match(DMI_BOARD_NAME, "RC71L") || -+ dmi_match(DMI_BOARD_NAME, "RC72LA")); - - if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE)) - asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; --- -2.45.2 - - -From 013f01137eab6cb7ebbc6e7345185bd44456cbf6 Mon Sep 17 00:00:00 2001 -From: antheas -Date: Sat, 20 Jul 2024 19:57:34 +0300 -Subject: [PATCH v2 2/3] allyx: tweak suspend and resume suspends - ---- - drivers/platform/x86/asus-wmi.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 8e362726b..b51b0153e 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -139,8 +139,11 @@ module_param(fnlock_default, bool, 0444); +@@ -144,10 +144,24 @@ module_param(fnlock_default, bool, 0444); + #define ASUS_MINI_LED_2024_STRONG 0x01 + #define ASUS_MINI_LED_2024_OFF 0x02 - /* Controls the power state of the USB0 hub on ROG Ally which input is on */ +-/* Controls the power state of the USB0 hub on ROG Ally which input is on */ ++/* ++ * For Ally and Ally X, which are handheld consoles with controllers: ++ * ++ * This function yanks the controller before suspend to fix Modern Standby in ++ * Windows. Due to the linux caller implementation of the relevant _DSM function ++ * which calls CSEE (named Display On and Off) Linux calls it both too close to ++ * suspend and too close out of suspend. This causes the MCU to either get ++ * confused or ignore the restore command. If it gets confused, both the yank ++ * (arg0 is b7) and restore (arg0 is b8) need to be called in sequence. If it ++ * ignores the command, only the restore needs to be called. ++ * ++ * Therefore, we require LSP0 to wait for a bit before suspending after yanking ++ * the controllers and wait a bit before restoring them on on resume, to let ++ * the MCU prepare for suspend and re-initialize properly after suspend. ++ */ #define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE" -/* 300ms so far seems to produce a reliable result on AC and battery */ -#define ASUS_USB0_PWR_EC0_CSEE_WAIT 1500 -+/* Use different delays for the ally depending on context. */ +#define ASUS_USB0_PWR_EC0_CSEE_PREPARE 1200 -+#define ASUS_USB0_PWR_EC0_CSEE_RESUME_BEFORE 1000 -+#define ASUS_USB0_PWR_EC0_CSEE_RESUME_AFTER 1500 -+ ++#define ASUS_USB0_PWR_EC0_CSEE_RESTORE 1200 static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL }; -@@ -4847,10 +4850,11 @@ static int asus_hotk_resume_early(struct device *device) +@@ -284,9 +298,6 @@ struct asus_wmi { + u32 tablet_switch_dev_id; + bool tablet_switch_inverted; + +- /* The ROG Ally device requires the MCU USB device be disconnected before suspend */ +- bool ally_mcu_usb_switch; +- + enum fan_type fan_type; + enum fan_type gpu_fan_type; + enum fan_type mid_fan_type; +@@ -4617,6 +4628,21 @@ static void init_rog_tunables(struct asus_wmi *asus) - if (asus->ally_mcu_usb_switch) { - /* sleep required to prevent USB0 being yanked then reappearing rapidly */ -+ msleep(ASUS_USB0_PWR_EC0_CSEE_RESUME_BEFORE); - if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB8))) - dev_err(device, "ROG Ally MCU failed to connect USB dev\n"); - else -- msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); -+ msleep(ASUS_USB0_PWR_EC0_CSEE_RESUME_AFTER); - } - return 0; } -@@ -4864,7 +4868,7 @@ static int asus_hotk_prepare(struct device *device) - if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB7))) - dev_err(device, "ROG Ally MCU failed to disconnect USB dev\n"); - else -- msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); -+ msleep(ASUS_USB0_PWR_EC0_CSEE_PREPARE); - } + ++static void asus_wmi_ally_s2idle_prepare(void) ++{ ++ msleep(ASUS_USB0_PWR_EC0_CSEE_PREPARE); ++} ++ ++static void asus_wmi_ally_s2idle_restore(void) ++{ ++ msleep(ASUS_USB0_PWR_EC0_CSEE_RESTORE); ++} ++ ++static struct acpi_s2idle_dev_ops asus_wmi_ally_s2idle_dev_ops = { ++ .prepare = asus_wmi_ally_s2idle_prepare, ++ .restore = asus_wmi_ally_s2idle_restore, ++}; ++ + static int asus_wmi_add(struct platform_device *pdev) + { + struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); +@@ -4646,8 +4672,20 @@ 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->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); +- asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) +- && dmi_match(DMI_BOARD_NAME, "RC71L"); ++ ++ bool ally_mcu_usb_switch = ++ acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) && ++ (dmi_match(DMI_BOARD_NAME, "RC71L") || ++ dmi_match(DMI_BOARD_NAME, "RC72LA")); ++ ++ if (ally_mcu_usb_switch && IS_ENABLED(CONFIG_SUSPEND)) { ++ err = acpi_register_lps0_dev(&asus_wmi_ally_s2idle_dev_ops); ++ if (err) ++ dev_err(&pdev->dev, ++ "Ally MCU: failed to register LPS0 sleep delays, a race condition might prevent controller restore after sleep.\n"); ++ else ++ dev_info(&pdev->dev, "Ally MCU: registered LPS0 sleep delays for resuming controller after sleep.\n"); ++ } + + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE)) + asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; +@@ -4838,34 +4876,6 @@ static int asus_hotk_resume(struct device *device) return 0; } --- -2.45.2 - - -From f508c14d1ca1c8161088da37752b1e4c816cd6a9 Mon Sep 17 00:00:00 2001 -From: antheas -Date: Sat, 20 Jul 2024 20:07:37 +0300 -Subject: [PATCH v2 3/3] add logging to allyx suspend quirk - ---- - drivers/platform/x86/asus-wmi.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index b51b0153e..3122d2c27 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -4853,8 +4853,11 @@ static int asus_hotk_resume_early(struct device *device) - msleep(ASUS_USB0_PWR_EC0_CSEE_RESUME_BEFORE); - if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB8))) - dev_err(device, "ROG Ally MCU failed to connect USB dev\n"); + +-static int asus_hotk_resume_early(struct device *device) +-{ +- struct asus_wmi *asus = dev_get_drvdata(device); +- +- if (asus->ally_mcu_usb_switch) { +- /* sleep required to prevent USB0 being yanked then reappearing rapidly */ +- if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB8))) +- dev_err(device, "ROG Ally MCU failed to connect USB dev\n"); - else -+ else { -+ dev_info(device, -+ "ROG Ally MCU resume command sent after suspend\n"); - msleep(ASUS_USB0_PWR_EC0_CSEE_RESUME_AFTER); -+ } - } - return 0; - } -@@ -4867,8 +4870,11 @@ static int asus_hotk_prepare(struct device *device) - /* sleep required to ensure USB0 is disabled before sleep continues */ - if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB7))) - dev_err(device, "ROG Ally MCU failed to disconnect USB dev\n"); +- msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); +- } +- return 0; +-} +- +-static int asus_hotk_prepare(struct device *device) +-{ +- struct asus_wmi *asus = dev_get_drvdata(device); +- +- if (asus->ally_mcu_usb_switch) { +- /* sleep required to ensure USB0 is disabled before sleep continues */ +- if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB7))) +- dev_err(device, "ROG Ally MCU failed to disconnect USB dev\n"); - else -+ else { -+ dev_info(device, -+ "ROG Ally MCU disconnect command sent before suspend.\n"); - msleep(ASUS_USB0_PWR_EC0_CSEE_PREPARE); -+ } - } - return 0; +- msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); +- } +- return 0; +-} +- + static int asus_hotk_restore(struct device *device) + { + struct asus_wmi *asus = dev_get_drvdata(device); +@@ -4910,8 +4920,6 @@ static const struct dev_pm_ops asus_pm_ops = { + .thaw = asus_hotk_thaw, + .restore = asus_hotk_restore, + .resume = asus_hotk_resume, +- .resume_early = asus_hotk_resume_early, +- .prepare = asus_hotk_prepare, + }; + + /* Registration ***************************************************************/ +@@ -4972,6 +4980,8 @@ void asus_wmi_unregister_driver(struct asus_wmi_driver *driver) + { + platform_device_unregister(driver->platform_device); + platform_driver_unregister(&driver->platform_driver); ++ if (IS_ENABLED(CONFIG_SUSPEND)) ++ acpi_unregister_lps0_dev(&asus_wmi_ally_s2idle_dev_ops); + used = false; } + EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver); -- 2.45.2 -- cgit v1.2.3