Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

native: don't re-enable Headphone Jack switch in mixer walk — kept silencing amp

The G7 log showed my previous fix reached the right state:
UCM: skip _enadev=Headphones (jack-gated)
Headphone Jack [sw now=OFF] ← UCM boot sequence had it correct
…but the very next line:
Unmuted: Headphone Jack ← audio_init's mixer walker flipped
it right back on, undoing the UCM
BootSequence and routing audio to
the HP DAPM path.

Exclude jack-gated switch names (Headphone Jack, Headphone Jack
Switch, HPOL/HPOR Playback, Headset) from the "unmute everything"
pass in both audio_init and unmute_all_switches. Those switches are
supposed to reflect physical jack state — flipping them manually
bypasses DAPM's routing logic and forces audio off the speaker amp.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+38 -5
+38 -5
fedac/native/src/audio.c
··· 2369 2369 if (snd_mixer_selem_has_capture_volume(elem)) fprintf(stderr, " [cap-vol]"); 2370 2370 fprintf(stderr, "\n"); 2371 2371 2372 - // Unmute every playback switch we find 2372 + // Unmute every playback switch we find — except the ones 2373 + // the UCM BootSequence explicitly turns off to keep audio 2374 + // routed to the speaker amp on unplugged-headphone state. 2375 + // Flipping "Headphone Jack Switch" on re-enables the HP 2376 + // DAPM path and silences MAX98360A even when nothing is 2377 + // plugged in (see G7/Drawcia debug session). 2373 2378 if (snd_mixer_selem_has_playback_switch(elem)) { 2374 - snd_mixer_selem_set_playback_switch_all(elem, 1); 2375 - fprintf(stderr, "[audio] Unmuted: %s\n", name); 2379 + int skip = 0; 2380 + const char *jack_gated[] = { 2381 + "Headphone Jack", /* rt5682 */ 2382 + "Headphone Jack Switch", 2383 + "HPOL Playback", 2384 + "HPOR Playback", 2385 + "Headset", 2386 + NULL 2387 + }; 2388 + for (int j = 0; jack_gated[j]; j++) { 2389 + if (strstr(name, jack_gated[j])) { skip = 1; break; } 2390 + } 2391 + if (!skip) { 2392 + snd_mixer_selem_set_playback_switch_all(elem, 1); 2393 + fprintf(stderr, "[audio] Unmuted: %s\n", name); 2394 + } else { 2395 + fprintf(stderr, "[audio] Skip unmute (jack-gated): %s\n", name); 2396 + } 2376 2397 } 2377 2398 2378 2399 // Set volume to max for output controls ··· 3245 3266 static int muted = 0; 3246 3267 static long pre_mute_volume = -1; 3247 3268 3248 - // Unmute all playback switches in the mixer 3269 + // Unmute all playback switches in the mixer — but skip jack-gated 3270 + // ones so we don't re-enable the headphone DAPM path (see audio_init 3271 + // above for the MAX98360A silencing story). 3249 3272 static void unmute_all_switches(snd_mixer_t *mixer) { 3250 3273 snd_mixer_elem_t *elem; 3274 + const char *jack_gated[] = { 3275 + "Headphone Jack", "Headphone Jack Switch", 3276 + "HPOL Playback", "HPOR Playback", "Headset", NULL 3277 + }; 3251 3278 for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) { 3252 3279 if (!snd_mixer_selem_is_active(elem)) continue; 3253 - if (snd_mixer_selem_has_playback_switch(elem)) 3280 + if (!snd_mixer_selem_has_playback_switch(elem)) continue; 3281 + const char *name = snd_mixer_selem_get_name(elem); 3282 + int skip = 0; 3283 + for (int j = 0; jack_gated[j]; j++) { 3284 + if (name && strstr(name, jack_gated[j])) { skip = 1; break; } 3285 + } 3286 + if (!skip) 3254 3287 snd_mixer_selem_set_playback_switch_all(elem, 1); 3255 3288 } 3256 3289 }