Misc Fixes for Linux on the ThinkPad L13 Yoga (Gen4)
In October I bought I ThinkPad L13 Yoga G4 to replace my ThinkPad Yoga 370. More and more MATLAB and other compute-heavy work for Uni was starting to show the limits of the 2C/4T CPU and the single channel RAM on that laptop (don’t get me started at how long it took for a single compile of MarlinFW for the Delta 2040 at the FabLab). Usually when I need to do compute-heavy stuff I remote into my Ryzen 7 3700X/64GB RAM/RTX 3060 desktop back at home and do the job there (also to save on battery life on the laptop), but that’s not always possible when I’m in uni and the quality of the internet connection there is very hit-or-miss on a per-room basis.
I snagged the laptop for about 480€ used on ebay, basically mint conditions apart from some light marks on the display which really are not noticeable if not in very low light and with low brightness on the screen. It was also a graduation gift (for my bachelor degree) from myself (and my parents) to myself.
The new laptop is a 2-in-1, meaning I can flip the screen over and use it as a tablet and as a graphics tablet since it has an integrated Wacom Pen. Really nice way to take notes in uni, especially considering how often I rewrite entire sections or proofs or little comments to my notes. Paper is good to review and understand, but you just can’t beat the versatility of the graphics tablet when it comes to having neatly organized notes. Many of my colleagues and friends use an iPad with the Apple Pen for that, but I really couldn’t justify the purchase of a device I’d only use for uni and note taking, while my laptop is arguably the piece of tech I use the most. Besides, I don’t like the feel of an iPad+Apple Pen.
Anyhow, the laptop is supposed to recognize when it is flipped into tablet mode, like my old laptop did. The old one in fact had a SW_TABLET_MODE
switch that sent a ACPI message to KDE to disable the keyboard and enter tablet mode (bigger icons and buttons, auto rotation, etc). Alas, the new one doesn’t do the same thing. I spent a bit of time trying to figure out why, with no success. It works on Windows, I tried. I suspect it’s something to do with some kind of I2C/SMBus sensor not being recognized by the kernel, given this error message in dmesg
and given on Windows tablet mode works only after installing SMBus drivers.
[ 3.698460] thinkpad_acpi: Unknown/reserved multi mode value 0x0000 for type 4, please report this to ibm-acpi-devel@lists.sourceforge.net
...
[ 3.843302] i2c i2c-3: SMBus Timeout!
[ 3.843320] i2c i2c-3: Failed reset at end of transaction (01)
[ 3.843378] i2c i2c-3: Failed! (01)
I could only find a set of workarounds to enable and disable tablet-mode manually.
Obligatory I use Arch btw, hence why the use of yay
and pacman
. The AUR is really nice when it comes to availability of packages. Actually I use EndeavourOS.
Disable inputs when in tablet mode
First of all, disable the keyboard, touchpad and trackpoint when in tablet mode. Also, switch back to laptop mode after closing the lid or when entering suspend, just to be sure I can unlock the laptop with the keyboard on wake. Luckily there’s the tablet-mode
script for that. On Arch, it’s on the AUR.
yay -S tablet-mode
with the config file /etc/tablet-mode.json
{
"tablet": [
"/dev/input/by-path/platform-i8042-serio-0-event-kbd",
"/dev/input/by-path/platform-i8042-serio-1-event-mouse",
"/dev/input/by-path/platform-AMDI0010:02-event-mouse"
],
"notify": true
}
Tablet/Laptop modes can be set using the commands setsysmode
tablet
/laptop
/toggle
. The current user needs to be in the input
group to use the command.
I then used the Run Command
widget for Plasma (needs to be installed from “Get New”) to add two buttons to my panel, one turning into tablet mode, the other into laptop mode.
Enter Plasma Tablet Mode
Tablet Mode in plasma makes icons and window buttons bigger for easier use with a touchscreen and enables autorotation (if enabled in the settings). As an added bonus, when disabling tablet mode the screen rotation is automatically reverted to normal (landscape, no rotation).
Tablet Mode can be toggled with this script I found on the KDE forums. I’m copying it here for archival purposes.
I took the lazy way out and simply made three copies of the script, each one turning tablet mode on or off or toggling it
/opt/tabletscripts/tableton.py
---
#!/usr/bin/env python3
import subprocess
import gi
gi.require_version('Gio', '2.0')
from gi.repository import Gio, GLib
KDE_VERSION = 6
OBJECT_PATH = '/kwinrc'
INTERFACE_NAME = 'org.kde.kconfig.notify'
SIGNAL_NAME = 'ConfigChanged'
subprocess.check_call([f"kwriteconfig{KDE_VERSION}", "--file", "kwinrc", "--group", "Input", "--key", "TabletMode", "on"])
connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
Gio.DBusConnection.emit_signal(connection, None, OBJECT_PATH, INTERFACE_NAME, SIGNAL_NAME, GLib.Variant.new_tuple(GLib.Variant('a{saay}', {'Input': [b'TabletMode']})))
/opt/tabletscripts/tabletoff.py
---
#!/usr/bin/env python3
import subprocess
import gi
gi.require_version('Gio', '2.0')
from gi.repository import Gio, GLib
KDE_VERSION = 6
OBJECT_PATH = '/kwinrc'
INTERFACE_NAME = 'org.kde.kconfig.notify'
SIGNAL_NAME = 'ConfigChanged'
subprocess.check_call([f"kwriteconfig{KDE_VERSION}", "--file", "kwinrc", "--group", "Input", "--key", "TabletMode", "off"])
connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
Gio.DBusConnection.emit_signal(connection, None, OBJECT_PATH, INTERFACE_NAME, SIGNAL_NAME, GLib.Variant.new_tuple(GLib.Variant('a{saay}', {'Input': [b'TabletMode']})))
/opt/tabletscripts/tablettoggle.py
---
#!/usr/bin/env python3
import subprocess
import gi
gi.require_version('Gio', '2.0')
from gi.repository import Gio, GLib
KDE_VERSION = 6
OBJECT_PATH = '/kwinrc'
INTERFACE_NAME = 'org.kde.kconfig.notify'
SIGNAL_NAME = 'ConfigChanged'
current_mode: str = subprocess.check_output([f"kreadconfig{KDE_VERSION}", "--file", "kwinrc", "--group", "Input", "--key", "TabletMode", "--default", "auto"]).decode(encoding='utf-8').strip()
if current_mode == "on":
subprocess.check_call([f"kwriteconfig{KDE_VERSION}", "--file", "kwinrc", "--group", "Input", "--key", "TabletMode", "off"])
else:
subprocess.check_call([f"kwriteconfig{KDE_VERSION}", "--file", "kwinrc", "--group", "Input", "--key", "TabletMode", "on"])
connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
Gio.DBusConnection.emit_signal(connection, None, OBJECT_PATH, INTERFACE_NAME, SIGNAL_NAME, GLib.Variant.new_tuple(GLib.Variant('a{saay}', {'Input': [b'TabletMode']})))
This three python scripts can be called in conjuction with setsysmode
as above. I merged them In a single sh script which is called by the widget.
/opt/tabletscripts/tableton.sh
---
#!/bin/bash
setsysmode tablet
python /opt/tabletscripts/tableton.py
/opt/tabletscripts/tabletoff.sh
---
#!/bin/bash
setsysmode laptop
python /opt/tabletscripts/tabletoff.py
/opt/tabletscripts/tablettoggle.sh
---
#!/bin/bash
setsysmode toggle
python /opt/tabletscripts/tablettoggle.py
Probably they could be mixed at least into a single python script, but I hacked this together late at night and I haven’t come back to it since. It has been holding strong though
Laptop mode on suspend, lid closed
For detecting when the lid gets closed (actually, detecting when it gets opened back) I used acpid
sudo pacman -S acpid
and the handler set to execute the tabletoff.sh
script
/etc/acpid/handler.sh
---
#!/bin/bash
# Default acpi script that takes an entry for all actions
case "$1" in
button/lid)
case "$3" in
close)
logger 'LID closed'
;;
open)
logger 'LID opened'
/opt/tabletscripts/tabletoff.sh
#setsysmode laptop
;;
*)
logger "ACPI action undefined: $3"
;;
esac
;;
*)
logger "ACPI group/action undefined: $1 / $2"
;;
esac
As for suspend, I created a systemd unit
/etc/systemd/system/tabletoff-on-suspend@.service
---
[Unit]
Description=Disable tablet mode before suspend
Before=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target
[Service]
ExecStart=/opt/tabletscripts/tabletoff.sh
User=%I
[Install]
WantedBy=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target
the scripts need to be called as a user, hence the User=%I
line. The unit needs to be enabled using the current user as argument
# systemd enable tabletoff-on-suspend@emamaker.service
Reload accelerometer module after suspend
There’s also this other little problem where the accelerometer stops working after suspend, which means no auto rotation after waking from suspend. If I’m not using it, my laptop is either in suspension or hibernation, so this has to be fixed. I isolated the culprit to the amd_sfh
kernel module. Reloading it with modprobe solves the issue. I added a systemd unit
/etc/systemd/system/reload-amd_sfh-after-resume.service
---
[Unit]
Description=Reload the amd_sfh module after suspend to make the accelerometer work again
After=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target
[Service]
ExecStart=rmmod amd_sfh -s ; modprobe amd_sfh
[Install]
WantedBy=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target
and enabled
# systemd enable reload-amd_sfh-after-resume.service