Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:Update
pulseaudio
0001-alsa-fix-infinite-loop-with-Intel-HDMI-LPE...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0001-alsa-fix-infinite-loop-with-Intel-HDMI-LPE.patch of Package pulseaudio
From 94fc586c011537536cfb434376354699357af785 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen <tanuk@iki.fi> Date: Thu, 28 Dec 2017 12:09:17 +0200 Subject: [PATCH] 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 --- src/modules/alsa/alsa-mixer.h | 1 + src/modules/alsa/alsa-sink.c | 20 ++++++++++++++++++++ src/modules/alsa/module-alsa-card.c | 34 ++++++++++++++++++++++++++++++++++ src/pulsecore/core.h | 1 + 4 files changed, 56 insertions(+) --- a/src/modules/alsa/alsa-mixer.h +++ b/src/modules/alsa/alsa-mixer.h @@ -364,6 +364,7 @@ int pa_alsa_set_mixer_rtpoll(struct pa_a struct pa_alsa_port_data { pa_alsa_path *path; pa_alsa_setting *setting; + bool suspend_when_unavailable; }; void pa_alsa_add_ports(void *sink_or_source_new_data, pa_alsa_path_set *ps, pa_card *card); --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1513,6 +1513,9 @@ static int sink_set_port_cb(pa_sink *s, s->set_volume(s); } + if (data->suspend_when_unavailable) + pa_sink_suspend(s, p->available == PA_AVAILABLE_NO, PA_SUSPEND_UNAVAILABLE); + return 0; } @@ -2455,6 +2458,23 @@ pa_sink *pa_alsa_sink_new(pa_module *m, 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: --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -427,6 +427,22 @@ static int report_jack_state(snd_mixer_e if (tp->avail == PA_AVAILABLE_NO) pa_device_port_set_available(tp->port, tp->avail); + for (tp = tports; tp->port; tp++) { + pa_alsa_port_data *data; + pa_sink *sink; + uint32_t idx; + + data = PA_DEVICE_PORT_DATA(tp->port); + + if (!data->suspend_when_unavailable) + continue; + + PA_IDXSET_FOREACH(sink, u->core->sinks, idx) { + if (sink->active_port == tp->port) + pa_sink_suspend(sink, tp->avail == PA_AVAILABLE_NO, PA_SUSPEND_UNAVAILABLE); + } + } + /* Update profile availabilities. The logic could be improved; for now we * only set obviously unavailable profiles (those that contain only * unavailable ports) to PA_AVAILABLE_NO and all others to @@ -837,6 +853,24 @@ int pa__init(pa_module *m) { goto fail; } + /* The Intel HDMI LPE driver needs some special handling. When the HDMI + * cable is not plugged in, trying to play audio doesn't work. Any written + * audio is immediately discarded and an underrun is reported, and that + * results in an infinite loop of "fill buffer, handle underrun". To work + * around this issue, the suspend_when_unavailable flag is used to stop + * playback when the HDMI cable is unplugged. */ + if (pa_safe_streq(pa_proplist_gets(data.proplist, "alsa.driver_name"), "snd_hdmi_lpe_audio")) { + pa_device_port *port; + void *state; + + PA_HASHMAP_FOREACH(port, data.ports, state) { + pa_alsa_port_data *port_data; + + port_data = PA_DEVICE_PORT_DATA(port); + port_data->suspend_when_unavailable = true; + } + } + u->card = pa_card_new(m->core, &data); pa_card_new_data_done(&data); --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -34,6 +34,7 @@ typedef enum pa_suspend_cause { PA_SUSPEND_SESSION = 8, /* Used by module-hal for mark inactive sessions */ PA_SUSPEND_PASSTHROUGH = 16, /* Used to suspend monitor sources when the sink is in passthrough mode */ PA_SUSPEND_INTERNAL = 32, /* This is used for short period server-internal suspends, such as for sample rate updates */ + PA_SUSPEND_UNAVAILABLE = 64, /* Used by device implementations that have to suspend when the device is unavailable */ PA_SUSPEND_ALL = 0xFFFF /* Magic cause that can be used to resume forcibly */ } pa_suspend_cause_t;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor