114 lines
3.9 KiB
Diff
114 lines
3.9 KiB
Diff
|
From 0a399a37fbe6f6b2b9062e1c076df28608b628c9 Mon Sep 17 00:00:00 2001
|
||
|
From: "Luke D. Jones" <luke@ljones.dev>
|
||
|
Date: Fri, 24 Nov 2023 21:13:11 +1300
|
||
|
Subject: [PATCH v2] platform/x86: asus-wmi: disable USB0 hub on ROG Ally
|
||
|
before suspend
|
||
|
|
||
|
ASUS have worked around an issue in XInput where it doesn't support USB
|
||
|
selective suspend, whcih causes suspend issues in Windows. They worked
|
||
|
around this by adjusting the MCU firmware to disable the USB0 hub when
|
||
|
the screen is switched off during the Microsoft DSM suspend path in ACPI.
|
||
|
|
||
|
The issue we have with this however is one of timing - the call the tells
|
||
|
the MCU to this isn't able to complete before suspend is done so we call
|
||
|
this in a prepare() and add a small msleep() to ensure it is done. This
|
||
|
must be done before the screen is switched off to prevent a variety of
|
||
|
possible races.
|
||
|
|
||
|
Without this the MCU is unable to initialise itself correctly on resume.
|
||
|
|
||
|
Signed-off-by: Luke D. Jones <luke@ljones.dev>
|
||
|
---
|
||
|
drivers/platform/x86/asus-wmi.c | 40 +++++++++++++++++++++++++++++++++
|
||
|
1 file changed, 40 insertions(+)
|
||
|
|
||
|
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
|
||
|
index 6a79f16233ab..563c9ab31bc7 100644
|
||
|
--- a/drivers/platform/x86/asus-wmi.c
|
||
|
+++ b/drivers/platform/x86/asus-wmi.c
|
||
|
@@ -16,6 +16,7 @@
|
||
|
#include <linux/acpi.h>
|
||
|
#include <linux/backlight.h>
|
||
|
#include <linux/debugfs.h>
|
||
|
+#include <linux/delay.h>
|
||
|
#include <linux/dmi.h>
|
||
|
#include <linux/fb.h>
|
||
|
#include <linux/hwmon.h>
|
||
|
@@ -132,6 +133,9 @@ module_param(fnlock_default, bool, 0444);
|
||
|
#define ASUS_SCREENPAD_BRIGHT_MAX 255
|
||
|
#define ASUS_SCREENPAD_BRIGHT_DEFAULT 60
|
||
|
|
||
|
+/* Controls the power state of the USB0 hub on ROG Ally which input is on */
|
||
|
+#define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE"
|
||
|
+
|
||
|
static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
|
||
|
|
||
|
static int throttle_thermal_policy_write(struct asus_wmi *);
|
||
|
@@ -300,6 +304,9 @@ struct asus_wmi {
|
||
|
|
||
|
bool fnlock_locked;
|
||
|
|
||
|
+ /* The ROG Ally device requires the USB hub to be disabled before suspend */
|
||
|
+ bool pre_suspend_ec0_csee_disable;
|
||
|
+
|
||
|
struct asus_wmi_debug debug;
|
||
|
|
||
|
struct asus_wmi_driver *driver;
|
||
|
@@ -4488,6 +4495,8 @@ static int asus_wmi_add(struct platform_device *pdev)
|
||
|
asus->nv_temp_tgt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_THERM_TARGET);
|
||
|
asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD);
|
||
|
asus->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE);
|
||
|
+ asus->pre_suspend_ec0_csee_disable = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE)
|
||
|
+ && dmi_match(DMI_BOARD_NAME, "RC71L");
|
||
|
|
||
|
err = fan_boost_mode_check_present(asus);
|
||
|
if (err)
|
||
|
@@ -4654,6 +4663,35 @@ static int asus_hotk_resume(struct device *device)
|
||
|
asus_wmi_fnlock_update(asus);
|
||
|
|
||
|
asus_wmi_tablet_mode_get_state(asus);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int asus_hotk_resume_early(struct device *device)
|
||
|
+{
|
||
|
+ struct asus_wmi *asus = dev_get_drvdata(device);
|
||
|
+
|
||
|
+ if (asus->pre_suspend_ec0_csee_disable) {
|
||
|
+ /* sleep required to ensure USB0 is enabled before drivers notice */
|
||
|
+ if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB8)))
|
||
|
+ pr_warn("ASUS ROG Ally failed to set USB hub power on\n");
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int asus_hotk_prepare(struct device *device)
|
||
|
+{
|
||
|
+ struct asus_wmi *asus = dev_get_drvdata(device);
|
||
|
+
|
||
|
+ if (asus->pre_suspend_ec0_csee_disable) {
|
||
|
+ /* sleep required to ensure USB0 is disabled before sleep continues */
|
||
|
+ if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB7)))
|
||
|
+ pr_warn("ASUS ROG Ally failed to set USB hub power off\n");
|
||
|
+ else
|
||
|
+ msleep(100);
|
||
|
+ }
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -4701,6 +4739,8 @@ 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 ***************************************************************/
|
||
|
--
|
||
|
2.43.0
|
||
|
|