alsa: fix infinite loop with Intel HDMI LPE

The Intel HDMI LPE driver works in a peculiar way when the HDMI cable is
not plugged in: any written audio is immediately discarded and underrun
is reported. That resulted in an infinite loop, because PulseAudio tried
to keep the buffer filled, which was futile since the written audio was
immediately consumed/discarded.

This patch adds special handling for the LPE driver: if the active port
of the sink is unavailable, the sink suspends itself. A new suspend
cause is added: PA_SUSPEND_UNAVAILABLE.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=100488
This commit is contained in:
Tanu Kaskinen 2017-12-28 12:09:17 +02:00
parent d9624e0382
commit 94fc586c01
4 changed files with 58 additions and 0 deletions

View file

@ -1527,6 +1527,11 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
s->set_volume(s);
}
if (data->suspend_when_unavailable && p->available == PA_AVAILABLE_NO)
pa_sink_suspend(s, true, PA_SUSPEND_UNAVAILABLE);
else
pa_sink_suspend(s, false, PA_SUSPEND_UNAVAILABLE);
return 0;
}
@ -2460,6 +2465,23 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
if (profile_set)
pa_alsa_profile_set_free(profile_set);
/* Suspend if necessary. FIXME: It would be better to start suspended, but
* that would require some core changes. It's possible to set
* pa_sink_new_data.suspend_cause, but that has to be done before the
* pa_sink_new() call, and we know if we need to suspend only after the
* pa_sink_new() call when the initial port has been chosen. Calling
* pa_sink_suspend() between pa_sink_new() and pa_sink_put() would
* otherwise work, but currently pa_sink_suspend() will crash if
* pa_sink_put() hasn't been called. */
if (u->sink->active_port) {
pa_alsa_port_data *port_data;
port_data = PA_DEVICE_PORT_DATA(u->sink->active_port);
if (port_data->suspend_when_unavailable && u->sink->active_port->available == PA_AVAILABLE_NO)
pa_sink_suspend(u->sink, true, PA_SUSPEND_UNAVAILABLE);
}
return u->sink;
fail: