01 March, 2021

ASUS VivoBook 14 (M413IA) with Linux

The VivoBook M413IA is a fine laptop with the right specs (Ryzen 7 4700U, 16GB RAM, 512GB NVMe SSD) and almost works perfectly with Linux...

The almost part revolves around the unreliable suspend/resume.
Increasing number of laptops are dropping support for S3 sleep state for S2idle/modern standby which results mostly issues. In case of this VivoBook resuming is a lottery with 5.10 kernel, switching away from X helped with the odds of success, but not too much. 5.11 should have had fixes for AMD platforms to handle S2idle fine. If nothing else it did made it predictable: the second time the laptop would hard lock. 

The message from ASUS customer support was clear: they will not support Linux issues and they will not enable S3 via BIOS update either, not even with an option so that the user must enable it.

There are reddits, forum posts and wikis on how to get back the S3 sleep state (both Linux and Windows users!) and even ASUS customer support suggested to hack the ACPI DSDT table :o

I have followed mostly the following for Arch Linux:
https://wiki.archlinux.org/index.php/Lenovo_ThinkPad_X1_Yoga_(Gen_3)#Manual_method

This is what dmesg has to say about the laptop:
ASUSTeK COMPUTER INC. VivoBook_ASUSLaptop X421IAY_M413IA/X421IAY, BIOS X421IAY.305 07/31/2020

and these are the steps I have taken (you need iasl and cpio installed):
mkdir acpi && cd acpi
cat /sys/firmware/acpi/tables/DSDT > dsdt.aml
iasl -d dsdt.aml  # decompile the dsdt table
patch -p1 < dsdt.diff
iasl -ve -tc dsdt.dsl # compile the fixed dsdt table
mkdir -p kernel/firmware/acpi
cp dsdt.aml kernel/firmware/acpi
find kernel | cpio -H newc --create > acpi_override
cp acpi_override /boot

Then modify the /etc/default/grub:
GRUB_CMDLINE_LINUX_DEFAULT="quiet mem_sleep_default=deep"
GRUB_EARLY_INITRD_LINUX_CUSTOM="acpi_override"

Reboot and S3 is supported:
dmesg | grep ACPI | grep supports
[    0.334940] ACPI: (supports S0 S3 S4 S5)
 

The laptop now suspends and resumes like charm!
Note: I have tested this on Artix Linux, but it should work on any distro.

dsdt.diff:
--- acpi.orig/dsdt.dsl    2021-02-28 14:12:43.016659203 +0200
+++ acpi/dsdt.dsl    2021-02-28 14:05:23.273330939 +0200
@@ -18,7 +18,7 @@
  *     Compiler ID      "INTL"
  *     Compiler Version 0x20120913 (538052883)
  */
-DefinitionBlock ("", "DSDT", 2, "_ASUS_", "Notebook", 0x01072009)
+DefinitionBlock ("", "DSDT", 2, "_ASUS_", "Notebook", 0x01072010)
 {
     /*
      * iASL Warning: There were 5 external control methods found during
@@ -351,7 +351,7 @@
 
     Name (SS1, Zero)
     Name (SS2, Zero)
-    Name (SS3, Zero)
+    Name (SS3, One)
     Name (SS4, One)
     Name (IOST, 0xFFFF)
     Name (TOPM, 0x00000000)
@@ -2995,7 +2995,7 @@
         Zero,
         Zero
     })
-    Name (XS3, Package (0x04)
+    Name (_S3, Package (0x04) // _S3_: S3 System State
     {
         0x03,
         Zero,