mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
alsa: Enable IEC958 switches on device activation
IEC958 (S/PDIF, HDMI, DisplayPort) switches default to muted in ALSA drivers, causing no audio output on digital devices. While UCM configurations and mixer paths can handle IEC958 unmuting, several scenarios lack coverage: - Pro-audio profiles (bypass UCM and mixer paths by design) - Devices without UCM configurations - Devices with incomplete mixer path definitions - Cards with multiple HDMI/DP outputs (indexed switches) This ensures IEC958 switches are enabled during device activation and port changes. The implementation uses the device mixer when available, falls back to the card mixer for pro-audio profiles, and enables all IEC958 switches regardless of index. Safe for all configurations: the operation is idempotent and provides defense-in-depth even when UCM or mixer paths handle it correctly. Tested on AMD Rembrandt GPU with 3 HDMI outputs in pro-audio mode.
This commit is contained in:
parent
87d34335f3
commit
b7a2fcf27e
1 changed files with 57 additions and 0 deletions
|
|
@ -1615,6 +1615,59 @@ static int device_disable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_devic
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Synchronize IEC958 digital output/input switch states.
|
||||
*
|
||||
* IEC958 switches default to muted in ALSA drivers. Cards with multiple
|
||||
* HDMI/DP outputs have indexed switches (IEC958,0 IEC958,1 etc). We enable
|
||||
* all switches since we cannot reliably map device numbers to indices.
|
||||
*/
|
||||
static void sync_iec958_controls(pa_alsa_device *d)
|
||||
{
|
||||
snd_mixer_t *mixer_handle;
|
||||
snd_mixer_elem_t *elem;
|
||||
pa_card *impl;
|
||||
int r;
|
||||
|
||||
mixer_handle = d->mixer_handle;
|
||||
|
||||
/* Pro-audio profiles don't have per-device mixers, use card mixer */
|
||||
if (!mixer_handle) {
|
||||
impl = d->card;
|
||||
if (!impl || impl->card.index == ACP_INVALID_INDEX)
|
||||
return;
|
||||
|
||||
mixer_handle = pa_alsa_open_mixer(impl->ucm.mixers, impl->card.index, true);
|
||||
if (!mixer_handle)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable all IEC958 switches */
|
||||
for (elem = snd_mixer_first_elem(mixer_handle); elem;
|
||||
elem = snd_mixer_elem_next(elem)) {
|
||||
|
||||
if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE)
|
||||
continue;
|
||||
|
||||
const char *name = snd_mixer_selem_get_name(elem);
|
||||
if (!name || !pa_startswith(name, "IEC958"))
|
||||
continue;
|
||||
|
||||
if (snd_mixer_selem_has_playback_switch(elem)) {
|
||||
r = snd_mixer_selem_set_playback_switch_all(elem, 1);
|
||||
if (r < 0)
|
||||
pa_log_warn("Failed to enable IEC958 playback switch: %s",
|
||||
pa_alsa_strerror(r));
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_has_capture_switch(elem)) {
|
||||
r = snd_mixer_selem_set_capture_switch_all(elem, 1);
|
||||
if (r < 0)
|
||||
pa_log_warn("Failed to enable IEC958 capture switch: %s",
|
||||
pa_alsa_strerror(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int device_enable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_device *dev)
|
||||
{
|
||||
const char *mod_name;
|
||||
|
|
@ -1681,6 +1734,9 @@ static int device_enable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_device
|
|||
}
|
||||
}
|
||||
|
||||
/* Enable IEC958 switches for digital outputs */
|
||||
sync_iec958_controls(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2179,6 +2235,7 @@ int acp_device_set_port(struct acp_device *dev, uint32_t port_index, uint32_t fl
|
|||
pa_sink_suspend(s, false, PA_SUSPEND_UNAVAILABLE);
|
||||
#endif
|
||||
}
|
||||
sync_iec958_controls(d);
|
||||
if (impl->events && impl->events->port_changed)
|
||||
impl->events->port_changed(impl->user_data,
|
||||
old ? old->port.index : 0, p->port.index);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue