I have the same device. I also got GNA and video encode/decode chips working, and stylus and touchscreen working independently with pressure sensitivity, stereo dmic and headphone jack/mic working and switching with a script. I am running Debian Trixie with custom kernel 7.2.8-rt5 … Here is my script for tablet mode and orientation switching: #!/usr/bin/env python3
“”"auto-rotate — tablet mode for the Chromebook Spin 713.
Folded into tablet mode (the EC’s “Tablet Mode Switch”), the screen follows the
lid accelerometer (iio label “accel-display”), the touchscreen and stylus are
remapped to match, and the keyboard and touchpad are disabled. Unfolded: back
to normal orientation with keyboard and touchpad on.
X11: xrandr + xinput (Coordinate Transformation Matrix on the ELAN touch/stylus,
including the proxied devices from elan_input_daemon.py). Wayland (mango):
wlr-randr output transform. Started from the openbox / mango autostart.
auto-rotate run
auto-rotate --watch only print tablet state + detected orientation
“”"
import glob
import os
import select
import signal
import subprocess
import sys
import fcntl
import evdev
OUTPUT = “eDP-1”
TOUCH = “ELAN90FC” # every touchscreen/stylus device, real + proxied
KEYBOARD, TOUCHPAD = “AT Translated Set 2 keyboard”, “Elan Touchpad”
THRESHOLD = 0.6 # of 1 g on the dominant axis before rotating
Lid accelerometer axis/sign → screen orientation, measured on this machine
(2026-09-27): open laptop +y; tablet hinge on the left -x, hinge on the right
+x, upside down -y. Hinge (screen bottom) on the left = panel turned clockwise,
which xrandr compensates with “left”.
AXIS_ORIENT = {(“y”, 1): “normal”, (“y”, -1): “inverted”, (“x”, -1): “left”, (“x”, 1): “right”}
MATRIX = {“normal”: “1 0 0 0 1 0 0 0 1”, “inverted”: “-1 0 1 0 -1 1 0 0 1”,
“left”: “0 -1 1 1 0 0 0 0 1”, “right”: “0 1 0 -1 0 1 0 0 1”}
WL_TRANSFORM = {“normal”: “normal”, “left”: “90”, “inverted”: “180”, “right”: “270”}
WAYLAND = bool(os.environ.get(“WAYLAND_DISPLAY”))
def find_accel():
for d in glob.glob(“/sys/bus/iio/devices/iio:device*”):
try:
if open(f"{d}/label").read().strip() == “accel-display”:
return d
except OSError:
pass
sys.exit(“auto-rotate: no accel-display iio device”)
def find_tablet_switch():
for path in evdev.list_devices():
d = evdev.InputDevice(path)
if d.name == “Tablet Mode Switch”:
return d
sys.exit(“auto-rotate: no Tablet Mode Switch input device”)
def tablet_mode(dev):
“”“Current SW_TABLET_MODE state via EVIOCGSW (the switch only sends changes).”“”
buf = bytearray(8)
fcntl.ioctl(dev.fd, 0x8008451B, buf) # EVIOCGSW(8)
return bool(buf[0] & (1 << evdev.ecodes.SW_TABLET_MODE))
def orientation(accel):
“”“Orientation the lid accelerometer shows, or None if too flat to tell.”“”
x, y = (int(open(f"{accel}/in_accel_{a}_raw").read()) for a in “xy”) # ~16384 = 1 g
axis, v = (“x”, x) if abs(x) > abs(y) else (“y”, y)
if abs(v) < THRESHOLD * 16384:
return None # lying flat: keep what we have
return AXIS_ORIENT[(axis, 1 if v > 0 else -1)]
def run(*cmd):
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def x_devices():
out = subprocess.run([“xinput”, “list”, “–name-only”], capture_output=True, text=True).stdout
return out.splitlines()
def apply_orientation(orient):
if WAYLAND:
run(“wlr-randr”, “–output”, OUTPUT, “–transform”, WL_TRANSFORM[orient])
return
run(“xrandr”, “–output”, OUTPUT, “–rotate”, orient)
for name in x_devices():
if TOUCH in name:
run(“xinput”, “set-prop”, name, “Coordinate Transformation Matrix”, *MATRIX[orient].split())
def set_keyboard(enabled):
if WAYLAND:
return # mango: no generic per-device toggle
for name in (KEYBOARD, TOUCHPAD):
run(“xinput”, “enable” if enabled else “disable”, name)
def restore(*_):
“”“Never leave the screen rotated or the keyboard off when we stop.”“”
apply_orientation(“normal”)
set_keyboard(True)
sys.exit(0)
def main():
watch = “–watch” in sys.argv
if not watch:
for sig in (signal.SIGTERM, signal.SIGINT, signal.SIGHUP):
signal.signal(sig, restore)
accel, switch = find_accel(), find_tablet_switch()
tablet, current, candidate, seen = tablet_mode(switch), None, None, 0
if not watch:
set_keyboard(not tablet)
print(f"auto-rotate: {‘Wayland’ if WAYLAND else ‘X11’}, tablet={tablet}“, flush=True)
while True:
r, _, _ = select.select([switch.fd], , , 0.4)
if r:
for ev in switch.read():
if ev.type == evdev.ecodes.EV_SW and ev.code == evdev.ecodes.SW_TABLET_MODE:
tablet = bool(ev.value)
print(f"tablet mode {‘ON’ if tablet else ‘OFF’}”, flush=True)
if not watch:
set_keyboard(not tablet)
want = orientation(accel) if tablet else “normal”
if want is None or want == current:
candidate, seen = None, 0
continue
seen = seen + 1 if want == candidate else 1 # two readings in a row: no jitter at 45°
candidate = want
if seen >= 2:
current = want
print(f"orientation → {current}", flush=True)
if not watch:
apply_orientation(current)
if name == “main”:
main()