Skip to content

Commit 21fb472

Browse files
dkulpclaude
andcommitted
fix(audio): stop postNetwork waiting 15s on boards with no audio hardware
Two stacked boot-time waits fired on a board with no audio at all: - AudioOutput gets canonicalized to the synthetic snd-dummy card's ID ("Dummy") when no real card exists, and the next boot then waited the full 10 seconds for a card named Dummy to register -- which can never happen, because snd-dummy is only modprobed after that wait. Treat "Dummy" as an explicit selection: load snd-dummy immediately so every wait is already satisfied, and skip the hardware-bind wait since the user asked for no real audio. - deviceTreeDeclaresSoundCard() only checked that a sound node exists. Some device trees (e.g. AM62x boards) ship the simple-audio-card node with status "disabled" until an audio cape overlay enables it; a disabled node can never bind, so it burned the 5-second bind wait on every capeless board. Honor the status property (absent means enabled per the DT spec). Also keep the preloaded Dummy card out of the noRealSoundcard computation so the PipeWire skip-probe fast paths still fire, and skip the later "No Soundcard Detected" modprobe when Dummy is already registered. Verified on a capeless PocketBeagle2: the postNetwork audio path drops from ~15s to ~1s, and a board with real cape audio (DT status "okay") still gets the bind wait. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent c90c4b0 commit 21fb472

1 file changed

Lines changed: 24 additions & 4 deletions

File tree

src/boot/FPPINIT_Audio.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,13 @@ static bool deviceTreeDeclaresSoundCard() {
145145
std::string name = ep->d_name;
146146
// the node is "sound" or, when addressed, "sound@<unit>"
147147
if (name == "sound" || name.starts_with("sound@")) {
148-
found = true;
148+
// Some boards ship the node with status "disabled" (an audio cape
149+
// overlay flips it to "okay"). A disabled node can never bind, so
150+
// it must not count as "audio is expected". No status property
151+
// means enabled per the DT spec.
152+
std::string status = GetFileContents("/proc/device-tree/" + name + "/status");
153+
TrimWhiteSpace(status);
154+
found = status.empty() || status.starts_with("ok");
149155
}
150156
}
151157
closedir(dp);
@@ -1108,6 +1114,15 @@ static void runAudioSetup(bool recoveryPass) {
11081114
TrimWhiteSpace(audioOutputId);
11091115
bool legacyNumeric = !audioOutputId.empty() && audioOutputId.find_first_not_of("0123456789") == std::string::npos;
11101116

1117+
// "Dummy" selects the synthetic snd-dummy card (a box that wants no real
1118+
// audio). It only ever registers because we modprobe it, so waiting for it
1119+
// below could never succeed -- load it now and every wait in this function
1120+
// is already satisfied.
1121+
if (audioOutputId == "Dummy" && getAlsaCardNumForId("Dummy") < 0) {
1122+
printf("FPP - Audio device 'Dummy' selected; loading snd-dummy\n");
1123+
modprobe("snd-dummy");
1124+
}
1125+
11111126
// A card selected by ID may not have registered yet: cape modules are
11121127
// modprobed back at cape detect, but an ASoC card (e.g. the K32Max's
11131128
// CapeAudio-pcm5102a) binds asynchronously and can land after we get here.
@@ -1164,7 +1179,10 @@ static void runAudioSetup(bool recoveryPass) {
11641179
v = v.substr(0, idx);
11651180
cards[k] = v;
11661181
cardLines[k] = l;
1167-
hasNonHDMI |= !lineHasHDMI(l);
1182+
// The synthetic snd-dummy is not real hardware; with an explicit
1183+
// "Dummy" selection it is loaded before this probe runs and must
1184+
// not defeat the no-real-soundcard fast paths below.
1185+
hasNonHDMI |= !lineHasHDMI(l) && v != "Dummy";
11681186
}
11691187
}
11701188
};
@@ -1201,7 +1219,9 @@ static void runAudioSetup(bool recoveryPass) {
12011219
// already satisfied -- it only pays out when the driver is still being
12021220
// autoloaded. Gated so a board with neither (a BeagleBone with no audio cape,
12031221
// the common case) waits zero.
1204-
if (noRealSoundcard && countRealAlsaCards() == 0 && (deviceTreeDeclaresSoundCard() || usbAudioDevicePresent())) {
1222+
// An explicit "Dummy" selection also skips this: the user asked for no real
1223+
// audio, so there is nothing worth waiting on even if hardware is present.
1224+
if (noRealSoundcard && audioOutputId != "Dummy" && countRealAlsaCards() == 0 && (deviceTreeDeclaresSoundCard() || usbAudioDevicePresent())) {
12051225
printf("FPP - No soundcard yet, but audio hardware is present; waiting...\n");
12061226
// Don't just wait on udev -- it may not have autoloaded the CPU DAI or
12071227
// machine driver yet, and without them the card can never bind no matter
@@ -1225,7 +1245,7 @@ static void runAudioSetup(bool recoveryPass) {
12251245
printf("FPP - No soundcard appeared after %d seconds\n", waited / 10);
12261246
}
12271247
}
1228-
if (noRealSoundcard) {
1248+
if (noRealSoundcard && getAlsaCardNumForId("Dummy") < 0) {
12291249
printf("FPP - No Soundcard Detected, loading snd-dummy\n");
12301250
modprobe("snd-dummy");
12311251
}

0 commit comments

Comments
 (0)