Linux Power Management development
 help / color / mirror / Atom feed
From: Antheas Kapenekakis <lkml@antheas.dev>
To: linux-pm@vger.kernel.org
Cc: platform-driver-x86@vger.kernel.org,
	dri-devel@lists.freedesktop.org,
	Mario Limonciello <mario.limonciello@amd.com>,
	Hans de Goede <hdegoede@redhat.com>,
	Kyle Gospodnetich <me@kylegospodneti.ch>,
	Antheas Kapenekakis <lkml@antheas.dev>
Subject: [RFC 11/13] acpi/x86: s2idle: add quirk table for modern standby delays
Date: Thu, 21 Nov 2024 18:22:36 +0100	[thread overview]
Message-ID: <20241121172239.119590-12-lkml@antheas.dev> (raw)
In-Reply-To: <20241121172239.119590-1-lkml@antheas.dev>

Unfortunately, some modern standby systems, including the ROG Ally, rely
on a delay between modern standby transitions. Add a quirk table for
introducing delays between modern standby transitions, and quirk the
ROG Ally on "Display Off", which needs a bit of time to turn off its
controllers prior to suspending.

Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
 drivers/acpi/x86/s2idle.c | 56 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
index d389c57d2963..504e6575d7ad 100644
--- a/drivers/acpi/x86/s2idle.c
+++ b/drivers/acpi/x86/s2idle.c
@@ -18,6 +18,7 @@
 #include <linux/acpi.h>
 #include <linux/device.h>
 #include <linux/dmi.h>
+#include <linux/delay.h>
 #include <linux/suspend.h>
 
 #include "../sleep.h"
@@ -91,11 +92,50 @@ struct lpi_device_constraint_amd {
 	int min_dstate;
 };
 
+struct s2idle_delay_quirks {
+	int delay_display_off;
+	int delay_sleep_entry;
+	int delay_sleep_exit;
+	int delay_display_on;
+};
+
+/*
+ * The ROG Ally series disconnects its controllers on Display Off and performs
+ * a fancy shutdown sequence, which requires around half a second to complete.
+ * If the power is cut earlier by entering it into D3, the original Ally unit
+ * might not disconnect its XInput MCU, causing excess battery drain, and the
+ * Ally X will make the controller restart post-suspend. In addition, the EC
+ * of the device rarely (1/20 attempts) may get stuck asserting PROCHOT after
+ * suspend (for various reasons), so split the delay between Display Off and
+ * Sleep Entry.
+ */
+static const struct s2idle_delay_quirks rog_ally_quirks = {
+	.delay_display_off = 350,
+	.delay_sleep_entry = 150,
+};
+
+static const struct dmi_system_id s2idle_delay_quirks[] = {
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "RC71L"),
+		},
+		.driver_data = (void *)&rog_ally_quirks
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "RC72L"),
+		},
+		.driver_data = (void *)&rog_ally_quirks
+	},
+	{}
+};
+
 static LIST_HEAD(lps0_s2idle_devops_head);
 
 static struct lpi_constraints *lpi_constraints_table;
 static int lpi_constraints_table_size;
 static int rev_id;
+struct s2idle_delay_quirks *delay_quirks;
 
 #define for_each_lpi_constraint(entry)						\
 	for (int i = 0;								\
@@ -566,6 +606,9 @@ static int acpi_s2idle_display_off(void)
 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_OFF,
 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
 
+	if (delay_quirks && delay_quirks->delay_display_off)
+		msleep(delay_quirks->delay_display_off);
+
 	acpi_scan_lock_release();
 
 	return 0;
@@ -587,6 +630,9 @@ static int acpi_s2idle_sleep_entry(void)
 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_ENTRY,
 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
 
+	if (delay_quirks && delay_quirks->delay_sleep_entry)
+		msleep(delay_quirks->delay_sleep_entry);
+
 	acpi_scan_lock_release();
 
 	return 0;
@@ -627,6 +673,9 @@ static int acpi_s2idle_sleep_exit(void)
 	acpi_scan_lock_acquire();
 
 	/* Modern Standby Sleep Exit */
+	if (delay_quirks && delay_quirks->delay_sleep_exit)
+		msleep(delay_quirks->delay_sleep_exit);
+
 	if (lps0_dsm_func_mask_microsoft > 0)
 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_EXIT,
 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
@@ -648,6 +697,9 @@ static int acpi_s2idle_display_on(void)
 	acpi_scan_lock_acquire();
 
 	/* Display on */
+	if (delay_quirks && delay_quirks->delay_display_on)
+		msleep(delay_quirks->delay_display_on);
+
 	if (lps0_dsm_func_mask_microsoft > 0)
 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_ON,
 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
@@ -760,6 +812,10 @@ int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
 
 	sleep_flags = lock_system_sleep();
 	list_add(&arg->list_node, &lps0_s2idle_devops_head);
+	const struct dmi_system_id *s2idle_sysid = dmi_first_match(
+		s2idle_delay_quirks
+	);
+	delay_quirks = s2idle_sysid ? s2idle_sysid->driver_data : NULL;
 	unlock_system_sleep(sleep_flags);
 
 	return 0;
-- 
2.47.0


  parent reply	other threads:[~2024-11-21 17:23 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-21 17:22 [RFC 00/13] acpi/x86: s2idle: implement Modern Standby transition states and expose to userspace Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 01/13] Documentation: PM: Add documentation for S0ix Standby States Antheas Kapenekakis
2024-11-21 18:58   ` Mario Limonciello
2024-11-21 19:11     ` Antheas Kapenekakis
2024-11-21 19:40       ` Mario Limonciello
2024-11-21 20:33         ` Antheas Kapenekakis
2024-11-21 21:08           ` Mario Limonciello
2024-11-21 21:23             ` Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 02/13] acpi/x86: s2idle: add support for Display Off and Display On callbacks Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 03/13] acpi/x86: s2idle: add support for Sleep Entry and Sleep Exit callbacks Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 04/13] acpi/x86: s2idle: add support for Turn On Display callback Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 05/13] acpi/x86: s2idle: add modern standby transition function Antheas Kapenekakis
2024-11-21 18:15   ` Mario Limonciello
2024-11-21 18:29     ` Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 06/13] acpi/x86: s2idle: rename Screen On/Off to Display On/Off Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 07/13] acpi/x86: s2idle: call Display On/Off as part of callbacks Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 08/13] acpi/x86: s2idle: rename MS Exit/Entry to Sleep Exit/Entry Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 09/13] acpi/x86: s2idle: call Sleep Entry/Exit as part of callbacks Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 10/13] acpi/x86: s2idle: add Turn On Display and call as part of callback Antheas Kapenekakis
2024-11-21 17:22 ` Antheas Kapenekakis [this message]
2024-11-21 18:04   ` [RFC 11/13] acpi/x86: s2idle: add quirk table for modern standby delays Mario Limonciello
2024-11-21 18:19     ` Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 12/13] platform/x86: asus-wmi: remove Ally (1st gen) and Ally X suspend quirk Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 13/13] PM: standby: Add sysfs attribute for modern standby transitions Antheas Kapenekakis
2024-11-28 11:45   ` Ilpo Järvinen
2024-11-21 17:41 ` [RFC 00/13] acpi/x86: s2idle: implement Modern Standby transition states and expose to userspace Rafael J. Wysocki
2024-12-06 21:37   ` Antheas Kapenekakis
2024-11-22 19:25 ` Xaver Hugl
2024-11-22 23:55   ` Antheas Kapenekakis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241121172239.119590-12-lkml@antheas.dev \
    --to=lkml@antheas.dev \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hdegoede@redhat.com \
    --cc=linux-pm@vger.kernel.org \
    --cc=mario.limonciello@amd.com \
    --cc=me@kylegospodneti.ch \
    --cc=platform-driver-x86@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox