Manchmal ist ein Linux-Hardwareproblem kein fehlender Treiber, sondern ein fehlendes Stück Metadaten an der richtigen Stelle. Genau so ein Fall ist mir beim ASUS Vivobook S16 M3607GA begegnet: Der interne Lautsprecher war auf Kernel- und ALSA-Ebene teilweise sichtbar, tauchte im Desktop-Audio-Stack aber nicht als nutzbares Ausgabegerät auf.
Der konkrete Fall betrifft ein System mit AMD ACP70 SoundWire und einem Realtek RT721-SDCA Codec. Der lokale Fix ergänzt im ASoC/SoundWire-Code einen Speaker-Component-Token. Das ist nur eine kleine Änderung im Kernel-Quellbaum, aber sie entscheidet darüber, ob UCM den internen Lautsprecher korrekt in das HiFi-Profil einbindet.
Die relevante Datei im Kernel-Quellbaum ist:
sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
Ausgangslage
Getestet wurde der Fix auf dieser Hardwarekombination:
ASUS Vivobook S16 M3607GA
AMD ACP70 SoundWire
Realtek RT721-SDCA
Das Fehlerbild war auf den ersten Blick widersprüchlich: ALSA zeigte den SmartAmp PCM, aber PipeWire bot nur Headset- oder Headphone-Geräte an. Der interne Lautsprecher fehlte im HiFi-Profil und war damit für den normalen Desktopbetrieb nicht sinnvoll nutzbar.
Das ist ein typischer Fall, bei dem die reine Existenz eines Kernel-Devices nicht reicht. Moderne Linux-Audio-Stacks hängen an mehreren Schichten: Kernel, ALSA, UCM, PipeWire und Desktop-Integration müssen zusammenpassen. Wenn eine Schicht die falschen oder unvollständigen Informationen bekommt, wirkt das Problem oben im Stack schnell wie ein fehlendes Gerät.
Ursache
Der RT721 multifunction SDCA speaker helper registriert die DAPM-Routen für den internen Speaker-Pfad. Was fehlte, war der passende Speaker-Component-Token in card->components.
UCM nutzt diese Component-Tokens, um gerätespezifische Profile und Devices korrekt zuzuordnen. Ohne den Token kann der RT721-Speaker nicht sauber eingebunden werden. Das Ergebnis:
- ALSA sieht den SmartAmp PCM.
- PipeWire sieht nur Headset- oder Headphone-Devices.
- Der interne Lautsprecher fehlt im HiFi-Profil.
- Audioausgabe über den eingebauten Lautsprecher funktioniert im Desktop nicht wie erwartet.
Der relevante Token lautet allgemein:
spk:<codec_name>
Für den RT721 ergibt sich daraus:
spk:rt721
Der Fix
Der Fix gehört in die Funktion asoc_sdw_rt_mf_sdca_spk_rtd_init(). Dort wird nach erfolgreichem Route-Map-Lookup und vor snd_soc_dapm_add_routes() der Speaker-Token an card->components angehängt.
Wichtig ist dabei: Die Funktion deckt nicht nur RT721 ab, sondern auch verwandte Codecs wie RT712 oder RT722. Deshalb sollte der Fix nicht hart spk:rt721 eintragen, sondern den bereits vorhandenen codec_name verwenden. Damit bleibt die Änderung generisch für alle Einträge in codec_routes.
diff --git a/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
--- a/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
@@ -72,6 +72,12 @@ int asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd
return -EINVAL;
}
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s spk:%s",
+ card->components, codec_name);
+ if (!card->components)
+ return -ENOMEM;
+
/* Add routes */
ret = snd_soc_dapm_add_routes(dapm, route_map->route_map, route_map->route_size);
if (ret)
Das ist keine große Architekturänderung. Genau das macht den Fix interessant: Ein fehlender Component-Tag reicht aus, damit ein Gerät in der Desktop-Audio-Konfiguration verschwindet.
Soll-Zustand im Code
Nach der Änderung sollte die Funktion sinngemäß so aussehen:
int asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
{
struct snd_soc_card *card = rtd->card;
struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
char codec_name[CODEC_NAME_SIZE];
int ret;
snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai->name);
const struct codec_route_map *route_map = get_codec_route_map(codec_name);
if (!route_map) {
dev_err(rtd->dev, "failed to get codec name and route map\n");
return -EINVAL;
}
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s spk:%s",
card->components, codec_name);
if (!card->components)
return -ENOMEM;
ret = snd_soc_dapm_add_routes(dapm, route_map->route_map, route_map->route_size);
if (ret)
dev_err(rtd->dev, "failed to add rt sdca spk map: %d\n", ret);
return ret;
}
Bei solchen Änderungen lohnt sich ein kurzer Blick auf den Diff, bevor man baut. Der Patch sollte klein bleiben und nur die betroffene Datei anfassen:
git status --short
git diff -- sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
Prüfen, ob der Fix schon enthalten ist
Nach einem Kernel-Update oder Rebase ist zuerst interessant, ob die Änderung bereits im neuen Kernel enthalten ist. Das lässt sich direkt im Quellbaum prüfen:
rg -n 'spk:%s|asoc_sdw_rt_mf_sdca_spk_rtd_init' sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
Wenn in asoc_sdw_rt_mf_sdca_spk_rtd_init() bereits ein devm_kasprintf() mit "%s spk:%s" steht, ist der Quirk vorhanden. Wenn nicht, muss der Patch erneut eingetragen oder aus dem lokalen Commit übernommen werden.
Der lokale Commit, aus dem diese Notiz stammt, war:
590570096721 ASoC: sdw_utils: Add RT721 speaker component tag
Bauen und installieren
Je nach Distribution und Arbeitsweise kann man den gesamten Kernel oder gezielt die betroffenen Module bauen. Für eine schnelle Entwicklungsrunde ist ein begrenzter Build oft angenehmer, solange die lokale Kernel-Build-Umgebung bereits funktioniert.
make -j"$(nproc)" M=sound/soc/sdw_utils modules
Für einen vollständigen Kernel-Build bleibt der klassische Weg:
make -j"$(nproc)"
sudo make modules_install
sudo make install
Nach dem Neustart sollte zuerst geprüft werden, ob wirklich der erwartete Kernel läuft:
uname -a
Bei Audio-Fixes ist diese Kontrolle wichtig. Sonst testet man schnell den alten Kernel und sucht das Problem an der falschen Stelle.
Validierung
Der erwartete Zustand nach dem Boot mit gepatchtem Kernel ist:
- Das UCM/HiFi-Profil zeigt Speaker, Headphones, internes Mikrofon und Headset-Devices.
- PipeWire bietet den internen Lautsprecher als Ausgabe an.
- Der interne Lautsprecher gibt Audio aus.
- Die Soundcard-Komponentenliste enthält den Token
spk:rt721.
Hilfreiche Checks sind:
aplay -l
wpctl status
pactl list cards
pactl list sinks
Je nach System können zusätzlich Kernel-Logs und ALSA-Informationen helfen:
sudo dmesg | grep -iE 'rt721|soundwire|sdw|ucm|sof|acp'
cat /proc/asound/cards
Entscheidend ist nicht nur, dass irgendwo ein PCM auftaucht sondern ob der interne Lautsprecher als nutzbares Ausgabegerät im normalen Audio-Stack erscheint und tatsächlich Ton ausgibt.
Warum der Token wichtig ist
Der Kernel beschreibt nicht nur Hardware, sondern liefert auch Informationen, die von Userspace-Komponenten weiterverwendet werden. Bei Audio ist diese Grenze besonders sichtbar. UCM entscheidet anhand von Komponenteninformationen, welche Mixer, Devices und Profile zusammengehören.
Fehlt spk:rt721, kann UCM den internen RT721-Speaker-Pfad nicht korrekt zuordnen. Der Kernel kann also technisch einen SmartAmp PCM bereitstellen, während der Desktop trotzdem keinen internen Lautsprecher anbietet. Das wirkt wie ein großes Problem, ist in diesem Fall aber ein sehr präziser Metadatenfehler.
Wiederherstellung nach Kernel-Updates
Für lokale Kernel-Tests ist es hilfreich, den Fix so zu dokumentieren, dass er nach einem Rebase schnell wiederhergestellt werden kann. Der Ablauf ist:
- Neue Kernel-Quellen auschecken oder aktualisieren.
- Mit
rgprüfen, ob"%s spk:%s"bereits vorhanden ist. - Falls der Code fehlt, den Minimalpatch in
soc_sdw_rt_mf_sdca.cerneut eintragen. - Betroffene Module oder Kernel bauen.
- Mit gepatchtem Kernel booten.
- UCM, PipeWire und reale Audioausgabe testen.
Wenn der Fix irgendwann upstream enthalten ist, sollte der lokale Patch natürlich entfallen. Bis dahin ist eine kleine, nachvollziehbare Änderung deutlich besser als eine Sammlung ungeklärter Workarounds im Userspace.
Coding-Agents sind hier massiv hilfreich
Solche Probleme liegen selten sauber in einer einzelnen Schublade. Man muss Kernel-Code lesen, bestehende Patterns erkennen, einen kleinen Patch formulieren, Build-Schritte sauber ausführen und anschließend über ALSA, UCM und PipeWire validieren. Das ist genau die Art Arbeit, bei der ein Coding-Agent Zeit sparen kann.
Die Grenze bleibt aber klar: Der Agent kann den Code vorbereiten, Hypothesen prüfen und den Patch reproduzierbar dokumentieren. Ob der interne Lautsprecher wirklich funktioniert, zeigt erst der Boot mit dem gepatchten Kernel auf der echten Hardware.
Weiterführend
Den Fehlenden Eintrag habe ich in GitHub Issues eingereicht und hoffe, dass er in eine zukünftige Kernel-Version aufgenommen wird.
FAQ zum RT721 SoundWire Speaker Quirk
Was behebt dieser Quirk?
Er ergänzt den Speaker-Component-Token spk:rt721, damit UCM den internen RT721-Speaker korrekt in das HiFi-Profil einbinden kann.
Warum reicht der sichtbare ALSA SmartAmp PCM nicht aus?
Weil der Desktop-Audio-Stack zusätzlich passende UCM-Profile und Component-Tokens braucht. Ohne diese Zuordnung kann PipeWire den internen Lautsprecher trotzdem nicht als normales Ausgabegerät anbieten.
Ist der Fix nur für RT721 gedacht?
Der konkrete Test erfolgte mit RT721-SDCA. Der Patch verwendet aber den vorhandenen codec_name und bleibt damit generisch für die von der Helper-Funktion unterstützten Codec-Routen.
Wie erkenne ich, ob der Fix schon im Kernel steckt?
In sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c sollte in asoc_sdw_rt_mf_sdca_spk_rtd_init() ein devm_kasprintf() mit "%s spk:%s" stehen.
Was sollte nach dem Boot funktionieren?
PipeWire sollte den internen Lautsprecher als Ausgabe anbieten, das HiFi-Profil sollte Speaker und Headphones enthalten, und der Lautsprecher sollte tatsächlich Audio ausgeben.
