2026 · Panther Lake · B9406CAA

ASUS ExpertBook Ultra on Linux,
without the broken bits.

Seven surgical, versioned, fully-reversible userspace patches that turn the 2026 ASUS ExpertBook Ultra (B9406CAA) into a working Linux laptop — without rebuilding the kernel and without breaking any of the things that already work.

site MIT Linux 6.18+ B9406CAA No kernel patches

Is this repo for me?

Run this one-liner. It's read-only, no sudo, no system changes — just probes the hardware and tells you which modules apply.

curl -fsSL https://raw.githubusercontent.com/burakgon/asus-expertbook-linux/main/scripts/check-hardware.sh | bash

Expected output on this exact laptop:

asus-expertbook-linux — hardware compatibility probe

Laptop model
  OK   ASUS EXPERTBOOK B9406CAA (full match — every module fits)

CPU
  OK   Intel(R) Core(TM) Ultra X7 358H (Panther Lake / Core Ultra Series 3)

Touchpad
  OK   PixArt 093A:4F05 (ACPI ASCP1D80) — touchpad-fix applies directly

Audio (Cirrus CS42L43 + 2× CS35L56)
  OK   subsystem 1043:15e4 — audio-fix firmware blobs apply directly
  OK   cs35l56 / cs42l43 driver loaded

Wi-Fi
  OK   Intel Wi-Fi 7 BE211 (8086:e440) — wifi-fix applies directly
  OK   iwlmld op_mode loaded (Wi-Fi 7 driver)

Distro
  OK   Arch (or derivative) — patcher's pacman + paths assumed correct

Result: install-all is appropriate for this hardware.

Before / after

Each row is one symptom you'll hit on a fresh Linux install of this laptop, and what changes after the corresponding module is installed. No band-aids in the bad sense — every fix uses the same upstream- recognised mechanism distros already use for other laptops.

PixArt I²C-HID haptic touchpad 093A:4F05 (ACPI ASCP1D80)
Before — touchpad Cursor doesn't move when you touch the pad. Kernel log spams
kernel bug: Touch jump detected and discarded.
After — touchpad-fix Light touch responds normally. libinput quirks list /dev/input/event9 confirms the pressure-axis quirk is loaded.
Cirrus CS42L43 codec + 2× CS35L56 speaker amps (PCI subsystem 1043:15e4)
Before — speakers Completely silent. dmesg: cs35l56: FIRMWARE_MISSING, Calibration disabled. F1 mute LED stuck on.
After — audio-fix Speakers play, volume control works. dmesg: Calibration applied, Tuning PID: 0x23134.
Intel Wi-Fi 7 BE211 Panther Lake CNVi (8086:e440)
Before — Wi-Fi Wi-Fi 7 (802.11be / EHT) unstable: RX collapses to MCS0/NSS1, MLO sessions tear down, missed beacons spam, occasional Microcode SW error freezes.
After — wifi-fix EHT disabled (disable_11be=Y) → rock-solid Wi-Fi 6 / HE (6 GHz, 160 MHz, ~2.1 Gbit/s). Zero beacon spam, no freezes.
Samsung Display Corp eDP panel + Intel xe driver (Xe3 Panther Lake iGPU)
Before — internal panel eDP-1 goes black mid-session. kwin_wayland: Pageflip timed out! Only a reboot recovers.
After — display-fix Internal panel stable indefinitely. PSR / Panel Replay disabled cleanly at boot via kernel cmdline.
Intel Core Ultra X7 / X9 Panther Lake hybrid (P + E + LP-E cores)
Before — idle power ~4–5 W idle. Fans audible. P-cores never deep-sleep.
After — intel-perf-fix ~2–2.5 W idle. All idle work parks on a single LP-E core. P-cores reach C10.
Intel Panther Lake NPU (8086:b03e) + USB UVC webcam
Before — AI camera effects No Linux equivalent of Windows Studio Effects. NPU sits idle, no virtual cam, no background blur / smart framing / voice focus shipped out of the box.
After — webcam-ai-fix OBS pipeline + obs-backgroundremoval plugin + virtual cam (/dev/video10 "AI Camera"). CPU background blur — the OBS plugin has no NPU path on Linux.
ASUS BIOS SLKB ACPI method (BIOS B9406CAA.304)
Before — keyboard backlight KDE slider does nothing; /sys/class/leds/asus::kbd_backlight/brightness writes silently no-op. Firmware SLKB method clamps standard 0..3 range to zero before passing to EC.
After — keyboard-backlight-fix KDE slider / sysfs control works (Fn hotkeys already worked). asusd userspace daemon translates kernel writes into the OEM-tested 0x100..0x103 range that the firmware handles correctly.

Install

Three idiomatic ways to use the patcher. All are idempotent and reversible.

Option 1 — install everything

git clone https://github.com/burakgon/asus-expertbook-linux.git
cd asus-expertbook-linux
./patch.sh install-all
sudo reboot

Option 2 — pick à la carte

./patch.sh list                       # see what's available + state
./patch.sh install touchpad-fix audio-fix
./patch.sh diff display-fix           # preview changes before applying
./patch.sh uninstall wifi-fix         # back out anytime

Option 3 — interactive menu

./patch.sh    # auto-elevates with sudo

=== asus_expertboot_linux patcher ===

  #   Module                  Version  Installed State          Description
  ----------------------------------------------------------------------------------
  1   audio-fix               2.1.0    2.1.0     up to date     Speakers + mics + clean panel
  2   display-fix             1.1.2    1.1.2     up to date     xe Panel Replay / PSR lockup
  3   intel-perf-fix          1.1.0    1.1.0     up to date     thermald + intel-lpmd
  4   keyboard-backlight-fix  1.1.0    1.1.0     up to date     (optional) KDE backlight slider
  5   touchpad-fix            1.1.1    1.1.1     up to date     PixArt 093A:4F05 pressure quirk
  6   webcam-ai-fix           1.1.0    1.1.0     up to date     OBS CPU background blur
  7   wifi-fix                2.0.0    2.0.0     up to date     BE211: disable broken EHT

Actions
  i <num>    install / update module
  u <num>    uninstall module
  d <num>    diff source vs installed
  s <num>    detailed status
  I          install all modules
  up         update all currently-installed
  U          uninstall all modules
  r          refresh
  q          quit

>

After install, verify any time with:

./patch.sh status

The seven modules

Each is a self-contained folder with a manifest, a payload, and a README. Click any module to open the bug story and the file-level details.

ModuleVersionFixes
touchpad-fix 1.1.1 PixArt 093A:4F05 haptic pad — pressure-axis quirk + libinput override
audio-fix 2.1.0 Cirrus CS35L56 firmware + HiFi UCM (upstream in alsa-ucm-conf 1.2.16) + SSP2-BT noise fix
wifi-fix 2.0.0 BE211: disable broken 802.11be/EHT — deliberate Wi-Fi 7 → stable Wi-Fi 6 (HE) downgrade
display-fix 1.1.2 xe driver Panel Replay / PSR lockup — kernel cmdline disable
intel-perf-fix 1.1.0 Panther Lake idle/thermal — thermald + intel-lpmd
webcam-ai-fix 1.1.0 AI camera stack — OBS + obs-backgroundremoval + v4l2loopback (CPU-only on Linux)
keyboard-backlight-fix 1.1.0 (optional) BIOS SLKB ACPI bug — asusd restores software/KDE backlight control (Fn hotkeys already work)

Module deep dives

touchpad-fix — pressure axis mis-parsed by hid-multitouch

The kernel's HID descriptor parser inflates ABS_MT_PRESSURE max to 2601 — literally the Y-axis max value, suggesting a parser typo — for this PixArt haptic touchpad. Real hardware values top out around 1000. libinput's pressure thresholds are calibrated against the kernel-reported max, so real touches register at 1–6% of the bogus max — well below the activation threshold. Result: every motion is rejected as a "kernel bug: Touch jump."

$ sudo dmesg | grep "Touch jump" | wc -l
1873      ← without the module
0         ← with the module

Files installed:

  • /etc/udev/hwdb.d/61-pixart-4f05-pressure-fix.hwdb — clamps the pressure axes via EVDEV_ABS_18 / EVDEV_ABS_3A
  • /etc/libinput/local-overrides.quirks — tells libinput to ignore pressure entirely (AttrEventCode=-ABS_MT_PRESSURE;-ABS_PRESSURE)
audio-fix — three things stacked
  1. Cirrus CS35L56 amps boot in FIRMWARE_MISSING because linux-firmware-cirrus < 20260519 doesn't ship per-OEM blobs for PCI subsystem 1043:15e4.
  2. The combined sidecar codec cs35l56+cs42l43-spk has no UCM in alsa-ucm-conf < 1.2.16, and its SpeakerCodec regex drops the -spk suffix — so the UCM fails to open. (Fixed upstream in alsa-ucm-conf 1.2.16.)
  3. WirePlumber then falls back to stereo-fallback, which plays to the Jack PCM, never the speaker output PCM.
$ sudo dmesg | grep cs35l56
cs35l56 sdw:0:2:01fa:3556:01:0: FIRMWARE_MISSING                    ← without
cs35l56 sdw:0:2:01fa:3556:01:1: FIRMWARE_MISSING                    ← without
─────────────────────────────────────────────────────────────────────────
cs35l56 sdw:0:2:01fa:3556:01:0: Calibration applied                 ← with
cs35l56 sdw:0:2:01fa:3556:01:0: Tuning PID: 0x23134, SID: 0x470200  ← with

Files installed (v2.1.0):

  • /lib/firmware/cirrus/cs35l56-b0-dsp1-misc-104315e4-l2u{0,1}.bin — per-OEM tuning blobs (fallback for linux-firmware-cirrus < 20260519)
  • /lib/firmware/cirrus/cs35l56-b0-dsp1-misc-104315e4-l2u{0,1}.wmfw — generic CS35L56 Rev 3.13.4 firmware patch (chip ROM upgrades 3.4.4 → 3.13.4)
  • /etc/wireplumber/wireplumber.conf.d/52-disable-bt-sco-offload.conf — silences the dead SSP2-BT offload PCM that spams the kernel log
  • HiFi UCM — only on alsa-ucm-conf < 1.2.16 (1.2.16+ ships it in the package): sof-soundwire.conf (fixed -spk regex), the cs35l56+cs42l43-spk / cs42l43-spk+cs35l56 speaker confs, and codecs/cs42l43-spk+cs35l56/init.conf
wifi-fix — 802.11be/EHT is broken on the BE211, so disable it

The core problem is 802.11be (EHT / Wi-Fi 7) itself on the Intel BE211 (8086:e440) under iwlwifi/iwlmld: the EHT RX path collapses to MCS0 / NSS1 and MLO sessions tear down, so the "Wi-Fi 7" link is slower and flakier than plain Wi-Fi 6. Not fixed upstream as of Linux 7.1-rc7. Two secondary irritants pile on: iwlmld defaults to power_scheme=2 (beacon-loss recovery churn), and the iwlwifi TX-segmentation offload bug can throw Microcode SW error freezes under heavy traffic.

$ sudo dmesg | grep -E "missed beacons|Microcode SW error" | wc -l
2046      ← with EHT on
0         ← with disable_11be=Y (Wi-Fi 6 fallback)

Core fix — drop the broken 802.11be layer so the radio runs as rock-solid Wi-Fi 6 (HE). Same approach Omarchy ships; verified at ~2.1 Gbit/s over 160 MHz 6 GHz HE here.

Files installed:

  • /etc/modprobe.d/iwlwifi-disable-eht.confoptions iwlwifi disable_11be=Y; disables EHT / Wi-Fi 7, link falls back to stable Wi-Fi 6 / HE
  • /etc/modprobe.d/iwlmld-active.confoptions iwlmld power_scheme=1 (secondary; trims HE-mode instability)
  • /etc/tmpfiles.d/pcie-aspm-performance.conf — global ASPM = performance at boot (secondary)
  • /etc/NetworkManager/dispatcher.d/90-iwlwifi-no-offloadethtool -K $iface tso off gso off gro off on every iwlwifi up (secondary)

This is a deliberate Wi-Fi 7 → Wi-Fi 6 downgrade — EHT is the problem on this silicon, and the secondary tunables do not keep Wi-Fi 7 alive. Bluetooth coex (bt_coex_active=Y) is left untouched, so Bluetooth keeps working.

display-fix — xe driver Panel Replay handshake hangs

The Samsung Display Corp panel reports IEEE OUI 00:aa:01 in DPCD register 0x300 and supports Panel Replay Selective Update (Early Transport). The xe driver's PSR idle wait times out on this panel firmware:

xe 0000:00:02.0: [drm] *ERROR* Timed out waiting PSR idle state
xe 0000:00:02.0: [drm] *ERROR* [CRTC:151:pipe A] DSB 0 timed out waiting for idle
kwin_wayland: Pageflip timed out! This is a bug in the xe kernel driver

Once wedged, only a reboot recovers — modeset cycle, GPU reset, and runtime PSR-disable via debugfs all fail to unstick the display state buffer. Worse than a black panel: when the PSR2 selective-fetch path deadlocks the DSB during heavy compositing (a screen capture is enough), it can take the whole kernel down — a silent hard hang with no oops, no MCE, empty pstore/BERT. Same pattern Intel addresses for Dell XPS 14/16 in mainline (per-device disable in intel_quirks.c) — our upstream-patches/0001 ports the same disable to our subsystem ID.

There is no dedicated upstream tracker for this Panther Lake PSR2 selective-fetch / DSB hang; it's reproduced locally on linux-cachyos 7.0.11 and linux-cachyos-rc 7.1-rc7. (drm/xe #7513 — "Lunar lake, rare shutdown under load" — is a distinct Lunar Lake PMC-firmware bug that leaves a BERT: [Hardware Error] record and is not cured by disabling PSR, so it is not this one.)

Files installed:

  • /etc/modprobe.d/xe-disable-psr.conf — belt-and-suspenders for late module load
  • (managed block) /etc/default/limine — appends xe.enable_psr=0 xe.enable_psr2_sel_fetch=0 xe.enable_panel_replay=0 to kernel cmdline; the post-install hook calls limine-update
intel-perf-fix — Panther Lake hybrid topology tuning

Without a userspace thermal daemon, the kernel's only lever is "cap CPU frequency". On Panther Lake's hybrid topology (P + E + LP-E cores) a P/E-aware throttle is far smarter — it can park work on slower cores instead of slowing everything down. Without intel-lpmd, idle work spreads; with it, all idle work concentrates on a single LP-E core and P-cores deep-sleep.

Packages installed (no payload files):

  • thermald (extra repo) — thermald.service enabled
  • intel-lpmd (extra / cachyos repo, plain pacman) — intel_lpmd.service enabled

Both daemons coexist with the existing power-profiles-daemon: PPD handles user profile, thermald handles thermal, intel-lpmd handles idle topology. Different layers, no conflict.

webcam-ai-fix — Linux equivalent of Windows Studio Effects

Windows Studio Effects on Copilot+ PCs runs background blur, smart framing, eye-contact correction, and voice focus on the NPU. None of these are shipped on Linux out of the box, even though the Intel Panther Lake NPU itself is fully supported by the kernel (intel_vpu driver, /dev/accel/accel0 exposed) and the userspace stack (OpenVINO 2026, level-zero) is available via the AUR.

This module bundles the userspace plumbing: a virtual camera target via v4l2loopback, OBS Studio as the capture + filter pipeline, and the obs-backgroundremoval plugin which runs ONNX models. On Linux that plugin is CPU-only — its execution providers are CUDA / ROCm / MIGraphX, and there is no OpenVINO/NPU path in the OBS plugin (installing openvino does not add an "NPU" device). CPU is fine for 720p30 background blur.

Files installed:

  • /etc/modules-load.d/v4l2loopback.conf — auto-load at boot
  • /etc/modprobe.d/v4l2loopback-options.confdevices=1 video_nr=10 card_label='AI Camera' exclusive_caps=1

Packages installed:

  • v4l2loopback-dkms (extra) — kernel module
  • obs-studio (extra) — orchestrator
  • obs-backgroundremoval (AUR) — ML segmentation plugin (ONNX); CPU-only on Linux

Use: open OBS, add a Video Capture Device source pointing at the real webcam, attach the Background Removal filter, and start the virtual camera (Tools → Start Virtual Camera). Apps then see "AI Camera" as a webcam choice.

Reality check — no NPU offload in OBS on Linux. For an actual NPU route see ericjchang/linux-studio-effects (OpenVINO + v4l2loopback), but it's validated on Arrow Lake, not yet Panther Lake, and installs via git + pip.

keyboard-backlight-fix(optional) BIOS SLKB bug breaks software backlight control

The backlight is not dead — the Fn hotkeys toggle it fine (handled by the EC in hardware, bypassing the buggy ACPI path). This module is optional: it only restores software control (the KDE slider / brightnessctl / sysfs).

On BIOS B9406CAA.304, the SLKB ACPI method that sets keyboard-backlight brightness has a broken branch. Disassembled from the live DSDT:

Method (SLKB, 1, NotSerialized) {
    If    ((Arg0 >= 0x0100) && (Arg0 <= 0x0106)) { Local0 = (Arg0 - 0x0100) }
    ElseIf((Arg0 >= 0x80)   && (Arg0 <= 0x83))   { Local0 = (Arg0 - 0x80) * 0x21 ... }
    ElseIf((Arg0 >= Zero)   && (Arg0 <= 0x03))   { Local0 = Zero }   // ← BUG
    STBC (Zero, Local0)
    Return (One)
}

The mainline asus-wmi Linux driver writes the standard kernel range 0..3 to set keyboard brightness. That hits the third branch which unconditionally clamps Local0 to zero. So every software write — KDE / brightnessctl / direct /sys/class/leds/ — is silently turned into "set brightness 0" and no-ops. (The Fn hotkeys are unaffected; they go through the EC, not this method.) The OEM-tested 0x100..0x103 range works correctly.

Workaround: the userspace daemon asusd (shipped in asusctl) translates standard kernel-level brightness writes into the OEM range before invoking ACPI, side-stepping the buggy branch. Once asusd is running, KDE PowerDevil's keyboard-brightness control reaches the EC correctly.

Files installed:

  • /usr/share/dbus-1/system-services/xyz.ljones.Asusd.service — D-Bus activation entry that ASUS doesn't ship; without it asusd.service (Type=dbus) never auto-starts
  • /etc/modules-load.d/acpi_call.conf — auto-load acpi_call for any direct ACPI fallback debugging
  • /etc/asusd/ directory — asusd refuses to start without it; pacman package leaves it absent

Packages installed:

  • asusctl (extra) — provides the asusd daemon
  • acpi_call-dkms (AUR, manual) — kernel module for direct ACPI invocations during debugging

If a future ASUS BIOS revision fixes the SLKB branch, this entire module becomes redundant — uninstall it.

The patcher

patch.sh is a small bash module manager (~500 lines). Each subfolder containing a module.sh manifest is a discoverable module. The patcher records the installed version under /var/lib/asus_expertboot_patcher/ so subsequent operations know whether each module needs an update.

Commands

./patch.sh                # interactive menu
./patch.sh list           # discover + state
./patch.sh status         # detailed
./patch.sh diff           # source vs installed
./patch.sh install <mod>  # idempotent (also "update")
./patch.sh update-all     # only re-installs out-of-date
./patch.sh uninstall <mod>

State table

FilesState fileReported as
nonenot installed
alluntracked
allmatchesup to date
allolderupdate available
someanypartial

Upstream submissions

The repo ships three submission-ready patches that turn each module into a permanent upstream entry, structurally identical to existing Dell / Lenovo / ASUS Zenbook quirks already accepted by the relevant trees. When all three land upstream, the corresponding modules become deletable.

#TreeReplaces
0001 drivers/gpu/drm/i915/display/intel_quirks.c display-fix's cmdline workaround
0002 sound/soc/intel/boards/sof_sdw.c most of audio-fix (combined-codec UCM routing)
0003 libinput/quirks/30-vendor-pixart.quirks touchpad-fix's libinput override

All three dry-run apply cleanly against current torvalds/linux master, drm-intel-next, and libinput main respectively. See upstream-patches/README.md for the hardware identifiers used, mailing list addresses, and submission instructions.

FAQ

Does this work on similar 2026 ExpertBook Ultra models?

Most of it transfers. The audio-fix firmware blobs are matched on PCI subsystem 1043:15e4 (this exact laptop). Sibling subsystems 104315d4 and 104315f4 ship different per-OEM tuning files in upstream linux-firmware. The touchpad-fix, wifi-fix, display-fix, intel-perf-fix, webcam-ai-fix, and keyboard-backlight-fix modules are hardware-agnostic or match by family-level identifiers and apply more broadly. PRs adding sibling-model entries are welcome.

Does this break Bluetooth?

No. The Wi-Fi module deliberately leaves iwlwifi.bt_coex_active=Y alone. Bluetooth audio, HID, and file transfer keep working as usual.

Does this downgrade Wi-Fi 7?

Yes — on purpose. 802.11be / EHT is broken on the BE211 (RX collapses to MCS0/NSS1, MLO tears down), so wifi-fix disables it (disable_11be=Y) and the link runs as stable Wi-Fi 6 / HE instead — ~2.1 Gbit/s over 160 MHz 6 GHz here, faster in practice than the flaky EHT link. Drop the module (or set disable_11be=N) once Intel fixes the iwlwifi EHT path upstream.

What about the F1 mute LED?

The HiFi UCM (active since audio-fix v2.0.0, and upstream in alsa-ucm-conf 1.2.16) drives the mic-mute LED (platform::micmute) correctly. The speaker-mute LED (F1) stays in its EC default state because this laptop exposes no speaker-mute LED device to Linux at all — there's nothing for the UCM SetLED hook to bind to. It's a missing-device limitation, not a profile issue.

Why not just upstream all of this and skip the repo?

That's the goal — see upstream-patches/. Two of the audio pieces already landed: alsa-ucm-conf 1.2.16 ships the cs42l43-spk+cs35l56 codec dir and linux-firmware-cirrus >= 20260519 ships the OEM blobs, so on an up-to-date system audio-fix is already down to a single SSP2-BT topology-noise drop-in. As the remaining kernel/quirk patches land and your distro picks them up, every module here becomes deletable.

Is this safe to install on a working setup?

Yes. Every module is reversible (./patch.sh uninstall <mod> removes the files it placed and reverts service enables). All file targets are well-known config paths (/etc/modprobe.d, /etc/udev/hwdb.d, /etc/libinput, /lib/firmware, /usr/share/alsa, /etc/wireplumber/wireplumber.conf.d, /etc/NetworkManager/dispatcher.d) — no kernel binary replacement, no pacman lock manipulation, no boot partition rewriting except the cmdline injection in display-fix's case (which is also fully reversible via the uninstall hook).

How do I test changes before installing?
./patch.sh diff <module>
# shows source vs installed for every file the module manages,
# marked unchanged / would update / would create
Where's the project licensed?

MIT for code (scripts, configs, patches). Firmware blobs under audio-fix/ are redistributed verbatim from upstream linux-firmware under their original Cirrus Logic redistribution license; see NOTICE.