Fixing HDMI Audio After Suspend on Linux
Contents
- The Problem
- Why Kernel Fixes Haven’t Stuck
- The Other Power Problem: Idle Suspend
- The Workaround: Profile Cycling
- Automating It
- Installation
- Options
- Links
The Problem
If you use HDMI or DisplayPort audio on a Linux desktop, you’ve probably hit this: you suspend your machine, wake it up, and your audio is gone. The HDMI output shows up as disconnected or silent. The most reliable fix is to open your audio settings and manually toggle the card profile off and back on.
This has been a persistent issue for years. It affects AMD and Intel GPUs across multiple kernel versions and desktop environments. The root cause is that when the system resumes, the kernel re-initializes the GPU but the HDMI audio codec doesn’t always come back cleanly. WirePlumber ends up holding references to stale audio nodes that no longer work.
Why Kernel Fixes Haven’t Stuck
There have been multiple attempts to fix this at the kernel level. In Linux 6.11, a patch was merged that conditionally disabled ALSA snooping for AMD HDMI↗ hardware when IOMMU wasn’t in play. The idea was to work around DMA coherency issues that caused crackling, dropouts, and post-suspend silence.
That patch was reverted↗ because it broke audio on other hardware configurations. The same pattern has repeated several times: a fix goes in, it helps some systems, it causes regressions on others, and it gets pulled. The Arch Linux forums have extensive threads documenting this cycle, including this one on ELD info being empty after resume↗.
The fundamental issue is that HDMI audio depends on a coordination chain between the GPU driver, the HDA controller, the ALSA layer, and the user-space audio server. Suspend/resume interrupts that chain, and rebuilding it reliably across all hardware combinations has proven difficult.
The Other Power Problem: Idle Suspend
System suspend isn’t the only power-related audio issue on Linux. PipeWire’s WirePlumber also suspends audio nodes after a few seconds of silence to save power. On paper this saves about 100mW on mobile devices, but on desktops it causes two problems: an audible pop when audio starts, and a constant hum on connected amplifiers because the unpowered output leaves the line floating, picking up electrical noise.
A popular r/linux thread↗ in December 2025 highlighted how frustrating this is. The configuration has changed across PulseAudio, WirePlumber 0.4 (Lua), and WirePlumber 0.5+ (SPA JSON), so most solutions you find online are outdated. The current fix is a WirePlumber config drop-in:
# ~/.config/wireplumber/wireplumber.conf.d/50-no-suspend.conf
monitor.alsa.rules = [
{
matches = [
{
node.name = "~alsa_output.*"
}
]
actions = {
update-props = {
session.suspend-timeout-seconds = 86400
}
}
}
]
One interesting detail from that thread: setting the timeout to 0 disables suspend entirely, but this breaks audio device sharing on multi-user systems. Setting it to a high value like 86400 (one day) avoids both the pop/hum and the multi-user issue.
For HDMI specifically, I hit both problems: the idle suspend pop between tracks, and complete audio loss after system suspend. The WirePlumber config above handles the idle suspend pop; audio-profile-manager handles the post-suspend audio loss.
The Workaround: Profile Cycling
The manual fix that always works is cycling the PipeWire/PulseAudio card profile off and back on. This forces a full teardown of the audio nodes and rebuilds them from scratch against the current hardware state:
pactl set-card-profile alsa_card.pci-0000_01_00.1 off
sleep 1
pactl set-card-profile alsa_card.pci-0000_01_00.1 pro-audio
The specific profile name varies by system — pro-audio is common for HDMI
cards on PipeWire, but yours might be different.
Automating It
I wrote
audio-profile-manager↗ to
automate this. It’s a bash script that monitors D-Bus for systemd-logind’s
PrepareForSleep signal and runs the profile cycle automatically on wake.
The core of it is a dbus-monitor loop that watches for resume events:
dbus-monitor --system --monitor \
"interface=org.freedesktop.login1.Manager,member=PrepareForSleep" \
| while read -r line; do
# On wake (boolean false), wait for HDMI renegotiation, then cycle profile
done
On startup it auto-detects both the HDMI audio card and the active profile, so
it knows what to restore to after cycling. Both can be overridden with --card
and --profile if needed. Then it sits in the background waiting for
suspend/resume events.
Installation
The repo includes a systemd user service and an install script:
git clone https://github.com/mwolson/audio-profile-manager.git
cd audio-profile-manager
./install.sh
systemctl --user start audio-profile-manager.service
This installs the script to ~/.local/bin/ and enables the systemd user service
(the install script handles systemctl --user enable for you). It uses
graphical-session.target, which is desktop-agnostic — it works with KDE,
GNOME, COSMIC, and any other desktop that properly integrates with systemd.
You can verify it’s working by checking the journal before and after a suspend cycle:
journalctl --user -u audio-profile-manager.service -f
You should see log lines like:
Waking from sleep, waiting 3s for HDMI to renegotiate...
Cycling profile on alsa_card.pci-0000_01_00.1: pro-audio -> off -> pro-audio
Profile restored to pro-audio.
Options
The defaults work for most HDMI setups, but you can customize:
--card CARD_NAMEto target a specific audio card--profile PROFILEto override the target profile (default: auto-detected)--wake-delay SECONDSto adjust the post-wake delay (default: 3 seconds)
Find your card name with pactl list cards short.
Links
- GitHub repository↗
- AMD HDMI audio fix attempted in Linux 6.11↗ (Phoronix)
- Kernel regression report for AMD HDMI/DP audio↗ (amd-gfx mailing list)
- No sound via HDMI after resume: ELD info empty↗ (Arch Linux forums)
- Quick tip: how to disable audio suspend in PipeWire↗ (r/linux)