Accepting request 395038 from home:tiwai:branches:multimedia:libs
- Backport various upstream fixes for PCM (bnc#979702): 0001-pcm_plugin-fix-appl-pointer-not-correct-when-mmap_co.patch 0002-pcm-Clean-up-error-paths-in-snd_pcm_plugin_-helpers.patch 0003-pcm-Fallback-open-as-the-first-instance-for-dmix-co.patch 0004-pcm-softvol-fix-conversion-of-TLVs-min_db-and-max_dB.patch 0005-pcm-Fix-suspend-resume-regression-with-dmix-co.patch 0006-pcm-dmix-Fix-doubly-resume-of-slave-PCM.patch OBS-URL: https://build.opensuse.org/request/show/395038 OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=196
This commit is contained in:
parent
b6b02f55ac
commit
75216f4ef8
135
0001-pcm_plugin-fix-appl-pointer-not-correct-when-mmap_co.patch
Normal file
135
0001-pcm_plugin-fix-appl-pointer-not-correct-when-mmap_co.patch
Normal file
@ -0,0 +1,135 @@
|
||||
From 7c424edd116e76eee6218a1e9a6ff6c4daaf2a4d Mon Sep 17 00:00:00 2001
|
||||
From: Shengjiu Wang <shengjiu.wang@freescale.com>
|
||||
Date: Wed, 6 Apr 2016 19:02:12 +0800
|
||||
Subject: [PATCH] pcm_plugin: fix appl pointer not correct when mmap_commit()
|
||||
return error
|
||||
|
||||
When snd_pcm_mmap_commit() return error, the appl pointer is also updated.
|
||||
which cause the avail_update()'s result wrong.
|
||||
This patch move the snd_pcm_mmap_appl_forward() to the place when
|
||||
snd_pcm_mmap_commit() is successfully returned.
|
||||
|
||||
Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_plugin.c | 48 ++++++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 32 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
|
||||
index d007e8c8bd4a..940491dbc84b 100644
|
||||
--- a/src/pcm/pcm_plugin.c
|
||||
+++ b/src/pcm/pcm_plugin.c
|
||||
@@ -279,18 +279,22 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
|
||||
return -EPIPE;
|
||||
}
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
- snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
|
||||
snd_pcm_sframes_t res;
|
||||
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
|
||||
- if (res < 0)
|
||||
+ if (res < 0) {
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
|
||||
+ }
|
||||
frames -= res;
|
||||
}
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- if (result <= 0)
|
||||
+ if (result <= 0) {
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
|
||||
+ }
|
||||
+ snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
offset += frames;
|
||||
xfer += frames;
|
||||
size -= frames;
|
||||
@@ -325,19 +329,23 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
|
||||
return -EPIPE;
|
||||
}
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
- snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
|
||||
snd_pcm_sframes_t res;
|
||||
|
||||
res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result);
|
||||
- if (res < 0)
|
||||
+ if (res < 0) {
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
|
||||
+ }
|
||||
frames -= res;
|
||||
}
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- if (result <= 0)
|
||||
+ if (result <= 0) {
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
|
||||
+ }
|
||||
+ snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
offset += frames;
|
||||
xfer += frames;
|
||||
size -= frames;
|
||||
@@ -423,19 +431,23 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
|
||||
frames = plugin->write(pcm, areas, appl_offset, frames,
|
||||
slave_areas, slave_offset, &slave_frames);
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
- snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
|
||||
snd_pcm_sframes_t res;
|
||||
|
||||
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
|
||||
- if (res < 0)
|
||||
+ if (res < 0) {
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
return xfer > 0 ? xfer : res;
|
||||
+ }
|
||||
frames -= res;
|
||||
}
|
||||
- if (result <= 0)
|
||||
+ if (result <= 0) {
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
return xfer > 0 ? xfer : result;
|
||||
+ }
|
||||
+ snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
if (frames == cont)
|
||||
appl_offset = 0;
|
||||
else
|
||||
@@ -490,19 +502,23 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
||||
frames = (plugin->read)(pcm, areas, hw_offset, frames,
|
||||
slave_areas, slave_offset, &slave_frames);
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
- snd_pcm_mmap_hw_forward(pcm, frames);
|
||||
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
|
||||
snd_pcm_sframes_t res;
|
||||
|
||||
res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
|
||||
- if (res < 0)
|
||||
+ if (res < 0) {
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
|
||||
+ }
|
||||
frames -= res;
|
||||
}
|
||||
- if (result <= 0)
|
||||
+ if (result <= 0) {
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
|
||||
+ }
|
||||
+ snd_pcm_mmap_hw_forward(pcm, frames);
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
if (frames == cont)
|
||||
hw_offset = 0;
|
||||
else
|
||||
--
|
||||
2.8.2
|
||||
|
213
0002-pcm-Clean-up-error-paths-in-snd_pcm_plugin_-helpers.patch
Normal file
213
0002-pcm-Clean-up-error-paths-in-snd_pcm_plugin_-helpers.patch
Normal file
@ -0,0 +1,213 @@
|
||||
From 503a285ed60164d8c65c6ee9ba6f23631da753df Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 7 Apr 2016 16:29:41 +0200
|
||||
Subject: [PATCH] pcm: Clean up error paths in snd_pcm_plugin_*() helpers
|
||||
|
||||
Minor code refactoring to unify the error return paths.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_plugin.c | 67 +++++++++++++++++++++++++++++++++++-----------------
|
||||
1 file changed, 45 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
|
||||
index 940491dbc84b..8527783c3569 100644
|
||||
--- a/src/pcm/pcm_plugin.c
|
||||
+++ b/src/pcm/pcm_plugin.c
|
||||
@@ -276,7 +276,8 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
|
||||
if (CHECK_SANITY(slave_frames > snd_pcm_mmap_playback_avail(slave))) {
|
||||
SNDMSG("write overflow %ld > %ld", slave_frames,
|
||||
snd_pcm_mmap_playback_avail(slave));
|
||||
- return -EPIPE;
|
||||
+ err = -EPIPE;
|
||||
+ goto error;
|
||||
}
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
@@ -284,14 +285,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
|
||||
snd_pcm_sframes_t res;
|
||||
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
|
||||
if (res < 0) {
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
|
||||
+ err = res;
|
||||
+ goto error_atomic;
|
||||
}
|
||||
frames -= res;
|
||||
}
|
||||
if (result <= 0) {
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
|
||||
+ err = result;
|
||||
+ goto error_atomic;
|
||||
}
|
||||
snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
snd_atomic_write_end(&plugin->watom);
|
||||
@@ -300,6 +301,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
|
||||
size -= frames;
|
||||
}
|
||||
return (snd_pcm_sframes_t)xfer;
|
||||
+
|
||||
+ error_atomic:
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
+ error:
|
||||
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
|
||||
@@ -311,6 +317,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
|
||||
snd_pcm_t *slave = plugin->gen.slave;
|
||||
snd_pcm_uframes_t xfer = 0;
|
||||
snd_pcm_sframes_t result;
|
||||
+ int err;
|
||||
|
||||
while (size > 0) {
|
||||
snd_pcm_uframes_t frames = size;
|
||||
@@ -326,7 +333,8 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
|
||||
if (CHECK_SANITY(slave_frames > snd_pcm_mmap_capture_avail(slave))) {
|
||||
SNDMSG("read overflow %ld > %ld", slave_frames,
|
||||
snd_pcm_mmap_playback_avail(slave));
|
||||
- return -EPIPE;
|
||||
+ err = -EPIPE;
|
||||
+ goto error;
|
||||
}
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
@@ -335,14 +343,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
|
||||
|
||||
res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result);
|
||||
if (res < 0) {
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
|
||||
+ err = res;
|
||||
+ goto error_atomic;
|
||||
}
|
||||
frames -= res;
|
||||
}
|
||||
if (result <= 0) {
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
|
||||
+ err = result;
|
||||
+ goto error_atomic;
|
||||
}
|
||||
snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
snd_atomic_write_end(&plugin->watom);
|
||||
@@ -351,6 +359,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
|
||||
size -= frames;
|
||||
}
|
||||
return (snd_pcm_sframes_t)xfer;
|
||||
+
|
||||
+ error_atomic:
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
+ error:
|
||||
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
|
||||
}
|
||||
|
||||
|
||||
@@ -401,6 +414,7 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t appl_offset;
|
||||
snd_pcm_sframes_t slave_size;
|
||||
snd_pcm_sframes_t xfer;
|
||||
+ int err;
|
||||
|
||||
if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
@@ -421,11 +435,10 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t slave_offset;
|
||||
snd_pcm_uframes_t slave_frames = ULONG_MAX;
|
||||
snd_pcm_sframes_t result;
|
||||
- int err;
|
||||
|
||||
err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
||||
if (err < 0)
|
||||
- return xfer > 0 ? xfer : err;
|
||||
+ goto error;
|
||||
if (frames > cont)
|
||||
frames = cont;
|
||||
frames = plugin->write(pcm, areas, appl_offset, frames,
|
||||
@@ -437,14 +450,14 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
|
||||
|
||||
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
|
||||
if (res < 0) {
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- return xfer > 0 ? xfer : res;
|
||||
+ err = res;
|
||||
+ goto error_atomic;
|
||||
}
|
||||
frames -= res;
|
||||
}
|
||||
if (result <= 0) {
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- return xfer > 0 ? xfer : result;
|
||||
+ err = result;
|
||||
+ goto error_atomic;
|
||||
}
|
||||
snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
snd_atomic_write_end(&plugin->watom);
|
||||
@@ -461,6 +474,11 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
|
||||
return -EPIPE;
|
||||
}
|
||||
return xfer;
|
||||
+
|
||||
+ error_atomic:
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
+ error:
|
||||
+ return xfer > 0 ? xfer : err;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
||||
@@ -468,6 +486,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
||||
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||
snd_pcm_t *slave = plugin->gen.slave;
|
||||
snd_pcm_sframes_t slave_size;
|
||||
+ int err;
|
||||
|
||||
slave_size = snd_pcm_avail_update(slave);
|
||||
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
|
||||
@@ -492,11 +511,10 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
||||
snd_pcm_uframes_t slave_offset;
|
||||
snd_pcm_uframes_t slave_frames = ULONG_MAX;
|
||||
snd_pcm_sframes_t result;
|
||||
- int err;
|
||||
|
||||
err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
||||
if (err < 0)
|
||||
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
|
||||
+ goto error;
|
||||
if (frames > cont)
|
||||
frames = cont;
|
||||
frames = (plugin->read)(pcm, areas, hw_offset, frames,
|
||||
@@ -508,14 +526,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
||||
|
||||
res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
|
||||
if (res < 0) {
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
|
||||
+ err = res;
|
||||
+ goto error_atomic;
|
||||
}
|
||||
frames -= res;
|
||||
}
|
||||
if (result <= 0) {
|
||||
- snd_atomic_write_end(&plugin->watom);
|
||||
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
|
||||
+ err = result;
|
||||
+ goto error_atomic;
|
||||
}
|
||||
snd_pcm_mmap_hw_forward(pcm, frames);
|
||||
snd_atomic_write_end(&plugin->watom);
|
||||
@@ -528,6 +546,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
||||
xfer += frames;
|
||||
}
|
||||
return (snd_pcm_sframes_t)xfer;
|
||||
+
|
||||
+ error_atomic:
|
||||
+ snd_atomic_write_end(&plugin->watom);
|
||||
+ error:
|
||||
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.8.2
|
||||
|
106
0003-pcm-Fallback-open-as-the-first-instance-for-dmix-co.patch
Normal file
106
0003-pcm-Fallback-open-as-the-first-instance-for-dmix-co.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From fdba9e1bad8f769a6137e565471f0227f23a3132 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 14 Apr 2016 17:33:03 +0200
|
||||
Subject: [PATCH] pcm: Fallback open as the first instance for dmix & co
|
||||
|
||||
dmix and other PCM plugins tries to open a secondary stream with
|
||||
O_APPEND flag when the shmem was already attached by another.
|
||||
However, when another streams have been already closed after the
|
||||
shmem check, this open may return the error EBADFD, since the kernel
|
||||
accepts O_APPEND only for the secondary streams.
|
||||
|
||||
This patch adds a workaround for such a case. It just retries opening
|
||||
the stream as the first instance (i.e. without O_APPEND flag).
|
||||
This is basically safe behavior (the kernel takes care of races), even
|
||||
we may do this even unconditionally. But it's bad from the
|
||||
performance POV, so we do it only when really needed.
|
||||
|
||||
Reported-by: Lars Lindqvist <lars.lindqvist@yandex.ru>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_dmix.c | 8 ++++++++
|
||||
src/pcm/pcm_dshare.c | 8 ++++++++
|
||||
src/pcm/pcm_dsnoop.c | 8 ++++++++
|
||||
3 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
|
||||
index b26a5c790e7e..007d35664ce7 100644
|
||||
--- a/src/pcm/pcm_dmix.c
|
||||
+++ b/src/pcm/pcm_dmix.c
|
||||
@@ -1020,6 +1020,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
|
||||
dmix->max_periods = opts->max_periods;
|
||||
dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
|
||||
|
||||
+ retry:
|
||||
if (first_instance) {
|
||||
/* recursion is already checked in
|
||||
snd_pcm_direct_get_slave_ipc_offset() */
|
||||
@@ -1076,6 +1077,13 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
|
||||
SND_PCM_APPEND,
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
+ /* all other streams have been closed;
|
||||
+ * retry as the first instance
|
||||
+ */
|
||||
+ if (ret == -EBADFD) {
|
||||
+ first_instance = 1;
|
||||
+ goto retry;
|
||||
+ }
|
||||
SNDERR("unable to open slave");
|
||||
goto _err;
|
||||
}
|
||||
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
|
||||
index 58e47bbeac67..adb3587a2869 100644
|
||||
--- a/src/pcm/pcm_dshare.c
|
||||
+++ b/src/pcm/pcm_dshare.c
|
||||
@@ -690,6 +690,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
|
||||
break;
|
||||
}
|
||||
|
||||
+ retry:
|
||||
first_instance = ret = snd_pcm_direct_shm_create_or_connect(dshare);
|
||||
if (ret < 0) {
|
||||
SNDERR("unable to create IPC shm instance");
|
||||
@@ -758,6 +759,13 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
|
||||
SND_PCM_APPEND,
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
+ /* all other streams have been closed;
|
||||
+ * retry as the first instance
|
||||
+ */
|
||||
+ if (ret == -EBADFD) {
|
||||
+ first_instance = 1;
|
||||
+ goto retry;
|
||||
+ }
|
||||
SNDERR("unable to open slave");
|
||||
goto _err;
|
||||
}
|
||||
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
|
||||
index 576c35b111cd..8ff0ba57cb14 100644
|
||||
--- a/src/pcm/pcm_dsnoop.c
|
||||
+++ b/src/pcm/pcm_dsnoop.c
|
||||
@@ -583,6 +583,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
|
||||
break;
|
||||
}
|
||||
|
||||
+ retry:
|
||||
first_instance = ret = snd_pcm_direct_shm_create_or_connect(dsnoop);
|
||||
if (ret < 0) {
|
||||
SNDERR("unable to create IPC shm instance");
|
||||
@@ -651,6 +652,13 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
|
||||
SND_PCM_APPEND,
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
+ /* all other streams have been closed;
|
||||
+ * retry as the first instance
|
||||
+ */
|
||||
+ if (ret == -EBADFD) {
|
||||
+ first_instance = 1;
|
||||
+ goto retry;
|
||||
+ }
|
||||
SNDERR("unable to open slave");
|
||||
goto _err;
|
||||
}
|
||||
--
|
||||
2.8.2
|
||||
|
@ -0,0 +1,89 @@
|
||||
From 85bf9915989e0a338632739684c75192c1753239 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?J=C3=B6rg=20Krause?= <joerg.krause@embedded.rocks>
|
||||
Date: Sun, 8 May 2016 20:48:42 +0200
|
||||
Subject: [PATCH] pcm: softvol: fix conversion of TLVs min_db and max_dB value
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Both, min_dB and max_dB, are floating type whereas the TLV is (always)
|
||||
unsigned.
|
||||
|
||||
The problem with the conversion of a negative floating-point number into an
|
||||
unsigned integer is, that the behavior is undefined. This may, depending on
|
||||
the platform, result in a wrong TLV, i.e. for the default values of min_dB
|
||||
(-51dB) and max_dB (0dB), alsactl generates the following state on an ARM
|
||||
cpu build with GCC:
|
||||
|
||||
control.1 {
|
||||
iface MIXER
|
||||
name Master
|
||||
value.0 255
|
||||
value.1 255
|
||||
comment {
|
||||
access 'read write user'
|
||||
type INTEGER
|
||||
count 2
|
||||
range '0 - 255'
|
||||
tlv '00000001000000080000000000000014'
|
||||
dbmin 0
|
||||
dbmax 5100
|
||||
dbvalue.0 5100
|
||||
dbvalue.1 5100
|
||||
}
|
||||
}
|
||||
|
||||
With the fix applied, alsactl stores the correct TLV:
|
||||
|
||||
control.1 {
|
||||
iface MIXER
|
||||
name Master
|
||||
value.0 255
|
||||
value.1 255
|
||||
comment {
|
||||
access 'read write user'
|
||||
type INTEGER
|
||||
count 2
|
||||
range '0 - 255'
|
||||
tlv '0000000100000008ffffec1400000014'
|
||||
dbmin -5100
|
||||
dbmax 0
|
||||
dbvalue.0 0
|
||||
dbvalue.1 0
|
||||
}
|
||||
}
|
||||
|
||||
Also tested for different combinations of min_dB and max_dB other than the
|
||||
default values.
|
||||
|
||||
Replaces:
|
||||
http://mailman.alsa-project.org/pipermail/alsa-devel/2016-May/107733.html
|
||||
|
||||
Fixes:
|
||||
http://mailman.alsa-project.org/pipermail/alsa-devel/2016-May/107628.html
|
||||
|
||||
Cc: Clemens Ladisch <clemens@ladisch.de>
|
||||
Signed-off-by: Jörg Krause <joerg.krause@embedded.rocks>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_softvol.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c
|
||||
index 802aa4b7cb68..5492db8cf9f1 100644
|
||||
--- a/src/pcm/pcm_softvol.c
|
||||
+++ b/src/pcm/pcm_softvol.c
|
||||
@@ -658,8 +658,8 @@ static int add_tlv_info(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo)
|
||||
unsigned int tlv[4];
|
||||
tlv[0] = SND_CTL_TLVT_DB_SCALE;
|
||||
tlv[1] = 2 * sizeof(int);
|
||||
- tlv[2] = svol->min_dB * 100;
|
||||
- tlv[3] = (svol->max_dB - svol->min_dB) * 100 / svol->max_val;
|
||||
+ tlv[2] = (int)(svol->min_dB * 100);
|
||||
+ tlv[3] = (int)((svol->max_dB - svol->min_dB) * 100 / svol->max_val);
|
||||
return snd_ctl_elem_tlv_write(svol->ctl, &cinfo->id, tlv);
|
||||
}
|
||||
|
||||
--
|
||||
2.8.2
|
||||
|
40
0005-pcm-Fix-suspend-resume-regression-with-dmix-co.patch
Normal file
40
0005-pcm-Fix-suspend-resume-regression-with-dmix-co.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From c14b0a08f0bf58e4f62307c68f8ff0137b4dec19 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Wed, 11 May 2016 09:06:47 +0200
|
||||
Subject: [PATCH] pcm: Fix suspend/resume regression with dmix & co
|
||||
|
||||
The recent fix commit [8985742d91db: pcm: dmix: Handle slave PCM xrun
|
||||
and unexpected states properly] caused a regression in dmix and other
|
||||
plugins regarding suspend/resume. For example, aplay endlessly prints
|
||||
"Suspended. Trying resume. Done." message if suspend and resume are
|
||||
performed in the middle of playback.
|
||||
|
||||
The reason is that the commit above changed the shadow PCM state
|
||||
(dmix->state) to SUSPENDED when the slave PCM is in suspend, while it
|
||||
doesn't restore the shadow state upon resume. Thus it appears as if
|
||||
it's always suspended even after the resume is invoked.
|
||||
|
||||
The fix is just to add the proper update of the shadow state in
|
||||
snd_pcm_direct_resume().
|
||||
|
||||
Reported-by: Shengjiu Wang <shengjiu.wang@freescale.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_direct.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
|
||||
index 14de734d98eb..e28738b0de96 100644
|
||||
--- a/src/pcm/pcm_direct.c
|
||||
+++ b/src/pcm/pcm_direct.c
|
||||
@@ -848,6 +848,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
|
||||
snd_pcm_start(dmix->spcm);
|
||||
err = 0;
|
||||
}
|
||||
+ dmix->state = snd_pcm_state(dmix->spcm);
|
||||
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
|
||||
return err;
|
||||
}
|
||||
--
|
||||
2.8.2
|
||||
|
48
0006-pcm-dmix-Fix-doubly-resume-of-slave-PCM.patch
Normal file
48
0006-pcm-dmix-Fix-doubly-resume-of-slave-PCM.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 5610b356b5f110f7f8e586f56e5b74e0f0c2db38 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Wed, 11 May 2016 13:06:25 +0200
|
||||
Subject: [PATCH] pcm: dmix: Fix doubly resume of slave PCM
|
||||
|
||||
The dmix plugin and co may trigger the resume for each instance in
|
||||
snd_pcm_direct_resume(). It means that the slave PCM gets resumed or
|
||||
re-prepared/started by each opened dmix stream, and this may end up
|
||||
with the doubly triggers even though the slave PCM has been already
|
||||
resumed by another dmix stream.
|
||||
|
||||
For avoiding this conflicts, check the slave PCM state and resume only
|
||||
when it's still in the suspended state. Meanwhile we keep the shadow
|
||||
state updated no matter whether the slave was triggered or not.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_direct.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
|
||||
index e28738b0de96..ac082f1a73b2 100644
|
||||
--- a/src/pcm/pcm_direct.c
|
||||
+++ b/src/pcm/pcm_direct.c
|
||||
@@ -841,6 +841,12 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
|
||||
int err;
|
||||
|
||||
snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
|
||||
+ /* resume only when the slave PCM is still in suspended state */
|
||||
+ if (snd_pcm_state(dmix->spcm) != SND_PCM_STATE_SUSPENDED) {
|
||||
+ err = 0;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
err = snd_pcm_resume(dmix->spcm);
|
||||
if (err == -ENOSYS) {
|
||||
/* FIXME: error handling? */
|
||||
@@ -848,6 +854,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
|
||||
snd_pcm_start(dmix->spcm);
|
||||
err = 0;
|
||||
}
|
||||
+ out:
|
||||
dmix->state = snd_pcm_state(dmix->spcm);
|
||||
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
|
||||
return err;
|
||||
--
|
||||
2.8.2
|
||||
|
11
alsa.changes
11
alsa.changes
@ -1,3 +1,14 @@
|
||||
-------------------------------------------------------------------
|
||||
Thu May 12 14:44:48 CEST 2016 - tiwai@suse.de
|
||||
|
||||
- Backport various upstream fixes for PCM (bnc#979702):
|
||||
0001-pcm_plugin-fix-appl-pointer-not-correct-when-mmap_co.patch
|
||||
0002-pcm-Clean-up-error-paths-in-snd_pcm_plugin_-helpers.patch
|
||||
0003-pcm-Fallback-open-as-the-first-instance-for-dmix-co.patch
|
||||
0004-pcm-softvol-fix-conversion-of-TLVs-min_db-and-max_dB.patch
|
||||
0005-pcm-Fix-suspend-resume-regression-with-dmix-co.patch
|
||||
0006-pcm-dmix-Fix-doubly-resume-of-slave-PCM.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Mar 31 15:19:33 CEST 2016 - tiwai@suse.de
|
||||
|
||||
|
12
alsa.spec
12
alsa.spec
@ -49,6 +49,12 @@ Source40: 50-alsa.conf
|
||||
Source41: install-snd-module
|
||||
# Patch: alsa-lib-git-fixes.diff
|
||||
# upstream fixes
|
||||
Patch1: 0001-pcm_plugin-fix-appl-pointer-not-correct-when-mmap_co.patch
|
||||
Patch2: 0002-pcm-Clean-up-error-paths-in-snd_pcm_plugin_-helpers.patch
|
||||
Patch3: 0003-pcm-Fallback-open-as-the-first-instance-for-dmix-co.patch
|
||||
Patch4: 0004-pcm-softvol-fix-conversion-of-TLVs-min_db-and-max_dB.patch
|
||||
Patch5: 0005-pcm-Fix-suspend-resume-regression-with-dmix-co.patch
|
||||
Patch6: 0006-pcm-dmix-Fix-doubly-resume-of-slave-PCM.patch
|
||||
# rest suse patches
|
||||
Patch99: alsa-lib-doxygen-avoid-crash-for-11.3.diff
|
||||
# suppress timestamp in documents
|
||||
@ -119,6 +125,12 @@ Architecture.
|
||||
%prep
|
||||
%setup -q -n alsa-lib-%{package_version}
|
||||
# %patch -p1
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
%if 0%{?suse_version} == 1130
|
||||
%patch99 -p1
|
||||
%endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user