Accepting request 442730 from multimedia:libs

1

OBS-URL: https://build.opensuse.org/request/show/442730
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/alsa?expand=0&rev=171
This commit is contained in:
Dominique Leuenberger 2016-12-11 12:26:13 +00:00 committed by Git OBS Bridge
commit 3114405b0f
21 changed files with 2396 additions and 2 deletions

View File

@ -0,0 +1,310 @@
From daafa451587b9e1d018f147885f38290a344a65a Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Date: Mon, 8 Aug 2016 16:23:10 +0300
Subject: [PATCH] ucm: Add ucm files for DB410c board.
DB410c board has support for both Digital and Analog audio. Digital
audio is over HDMI and analog is over codec chip integrated inside the
APQ8016 SOC.
It can support:
- 3 Microphones: Primary Mic(Handset mic), Headset Mic and Secondary
- 2 Digital Microphones.
- Earpiece.
- Headset.
- Loud Speaker.
- HDMI.
[Riku: squashed Srinivas's patches together and converted spaces to tabs]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Cc: nicolas.dechesne@linaro.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
configure.ac | 1 +
src/conf/ucm/DB410c/DB410c.conf | 8 ++
src/conf/ucm/DB410c/HDMI | 31 +++++++
src/conf/ucm/DB410c/HiFi | 185 ++++++++++++++++++++++++++++++++++++++++
src/conf/ucm/DB410c/Makefile.am | 4 +
src/conf/ucm/Makefile.am | 2 +-
6 files changed, 230 insertions(+), 1 deletion(-)
create mode 100644 src/conf/ucm/DB410c/DB410c.conf
create mode 100644 src/conf/ucm/DB410c/HDMI
create mode 100644 src/conf/ucm/DB410c/HiFi
create mode 100644 src/conf/ucm/DB410c/Makefile.am
diff --git a/configure.ac b/configure.ac
index f592e8b74360..014af5f3d27b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -675,6 +675,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
src/conf/ucm/broadwell-rt286/Makefile \
src/conf/ucm/VEYRON-I2S/Makefile \
src/conf/ucm/chtrt5645/Makefile \
+ src/conf/ucm/DB410c/Makefile \
src/conf/topology/Makefile \
src/conf/topology/broadwell/Makefile \
modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \
diff --git a/src/conf/ucm/DB410c/DB410c.conf b/src/conf/ucm/DB410c/DB410c.conf
new file mode 100644
index 000000000000..590278fa7bdd
--- /dev/null
+++ b/src/conf/ucm/DB410c/DB410c.conf
@@ -0,0 +1,8 @@
+SectionUseCase."HiFi" {
+ File "HiFi"
+ Comment "Play HiFi quality Music."
+}
+SectionUseCase."HDMI" {
+ File "HDMI"
+ Comment "HDMI output."
+}
diff --git a/src/conf/ucm/DB410c/HDMI b/src/conf/ucm/DB410c/HDMI
new file mode 100644
index 000000000000..8112bc0a7110
--- /dev/null
+++ b/src/conf/ucm/DB410c/HDMI
@@ -0,0 +1,31 @@
+# Use case configuration for DB410c board.
+# Author: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+SectionVerb {
+ EnableSequence [
+ ]
+
+ DisableSequence [
+ ]
+ Value {
+ TQ "HiFi"
+ PlaybackPCM "plughw:0,0"
+ }
+}
+
+SectionDevice."HDMI-stereo" {
+ #Name "HDMI-stereo"
+ Comment "HDMI Digital Stereo Output"
+
+ EnableSequence [
+ cdev "hw:0"
+ ]
+
+ DisableSequence [
+ cdev "hw:0"
+ ]
+
+ Value {
+ PlaybackChannels "2"
+ }
+}
diff --git a/src/conf/ucm/DB410c/HiFi b/src/conf/ucm/DB410c/HiFi
new file mode 100644
index 000000000000..f9cbcf053e84
--- /dev/null
+++ b/src/conf/ucm/DB410c/HiFi
@@ -0,0 +1,185 @@
+# Use case configuration for DB410c board.
+# Author: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+SectionVerb {
+
+ EnableSequence [
+ ]
+
+ DisableSequence [
+ ]
+
+ # ALSA PCM
+ Value {
+ # ALSA PCM device for HiFi
+ PlaybackPCM "plughw:0,1"
+ CapturePCM "plughw:0,2"
+ }
+}
+
+
+SectionDevice."Speaker" {
+ Comment "Speaker playback"
+
+ ConflictingDevice [
+ "Headphones"
+ "Earpiece"
+ ]
+
+ EnableSequence [
+ cdev "hw:0"
+ cset "name='SPK DAC Switch' 1"
+ cset "name='RX3 MIX1 INP1' RX1"
+ ## gain to 0dB
+ cset "name='RX3 Digital Volume' 128"
+ ]
+
+ DisableSequence [
+ cdev "hw:0"
+ cset "name='SPK DAC Switch' 0"
+ cset "name='RX3 MIX1 INP1' ZERO"
+ ]
+
+ Value {
+ PlaybackChannels "2"
+ }
+}
+
+
+SectionDevice."Headphones" {
+ Comment "Headphones playback"
+
+ ConflictingDevice [
+ "Speaker"
+ "Earpiece"
+ ]
+ EnableSequence [
+ cdev "hw:0"
+ cset "name='RX1 MIX1 INP1' RX1"
+ cset "name='RX2 MIX1 INP1' RX2"
+ cset "name='RDAC2 MUX' RX2"
+ cset "name='HPHL' 1"
+ cset "name='HPHR' 1"
+ ## gain to 0dB
+ cset "name='RX1 Digital Volume' 128"
+ ## gain to 0dB
+ cset "name='RX2 Digital Volume' 128"
+ ]
+
+ DisableSequence [
+ cdev "hw:0"
+ cset "name='RX1 Digital Volume' 0"
+ cset "name='RX2 Digital Volume' 0"
+ cset "name='HPHL' 0"
+ cset "name='HPHR' 0"
+ cset "name='RDAC2 MUX' ZERO"
+ cset "name='RX1 MIX1 INP1' ZERO"
+ cset "name='RX2 MIX1 INP1' ZERO"
+ ]
+
+ Value {
+ PlaybackChannels "2"
+ }
+}
+
+SectionDevice."Earpiece" {
+ Comment "Earpiece playback"
+
+ ConflictingDevice [
+ "Speaker"
+ "Headphones"
+ ]
+ EnableSequence [
+ cdev "hw:0"
+ ]
+
+ DisableSequence [
+ cdev "hw:0"
+ ]
+
+ Value {
+ PlaybackChannels "2"
+ }
+}
+
+SectionDevice."Handset" {
+ Comment "Headset Microphone"
+
+ EnableSequence [
+ cdev "hw:0"
+ cset "name='DEC1 MUX' ADC2"
+ cset "name='ADC2 Volume' 8"
+ cset "name='ADC2 MUX' INP2"
+ ]
+
+ DisableSequence [
+ cdev "hw:0"
+ cset "name='ADC2 MUX' ZERO"
+ cset "name='ADC2 Volume' 0"
+ cset "name='DEC1 MUX' ZERO"
+ ]
+
+ Value {
+ CaptureChannels "2"
+ }
+}
+
+SectionDevice."Primarymic" {
+ Comment "Primary Microphone"
+
+ EnableSequence [
+ cdev "hw:0"
+ cset "name='DEC1 MUX' ADC1"
+ cset "name='ADC1 Volume' 8"
+ ]
+
+ DisableSequence [
+ cdev "hw:0"
+ cset "name='DEC1 MUX' ZERO"
+ cset "name='ADC1 Volume' 0"
+ ]
+
+ Value {
+ CaptureChannels "2"
+ }
+}
+
+SectionDevice."Secondarymic" {
+ Comment "Secondary Microphone"
+
+ EnableSequence [
+ cdev "hw:0"
+ cset "name='DEC1 MUX' ADC2"
+ cset "name='ADC2 Volume' 8"
+ cset "name='ADC2 MUX' INP2"
+ ]
+
+ DisableSequence [
+ cdev "hw:0"
+ cset "name='DEC1 MUX' ZERO"
+ cset "name='ADC2 Volume' 0"
+ cset "name='ADC2 MUX' ZERO"
+ ]
+
+ Value {
+ CaptureChannels "2"
+ }
+}
+
+SectionDevice."DMIC" {
+ Comment "Digital Microphone"
+
+ EnableSequence [
+ cdev "hw:0"
+ cset "name='DEC1 MUX' DMIC1"
+ ]
+
+ DisableSequence [
+ cdev "hw:0"
+ cset "name='DEC1 MUX' ZERO"
+ ]
+
+ Value {
+ CaptureChannels "2"
+ }
+}
diff --git a/src/conf/ucm/DB410c/Makefile.am b/src/conf/ucm/DB410c/Makefile.am
new file mode 100644
index 000000000000..e10a1363dc32
--- /dev/null
+++ b/src/conf/ucm/DB410c/Makefile.am
@@ -0,0 +1,4 @@
+alsaconfigdir = @ALSA_CONFIG_DIR@
+ucmdir = $(alsaconfigdir)/ucm/DB410c
+ucm_DATA = DB410c.conf HDMI HiFi
+EXTRA_DIST = $(ucm_DATA)
diff --git a/src/conf/ucm/Makefile.am b/src/conf/ucm/Makefile.am
index 88657708fc68..7bf432e70e26 100644
--- a/src/conf/ucm/Makefile.am
+++ b/src/conf/ucm/Makefile.am
@@ -1 +1 @@
-SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 VEYRON-I2S chtrt5645
+SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 VEYRON-I2S chtrt5645 DB410c
--
2.10.2

View File

@ -0,0 +1,76 @@
From e2cfe3c6c8483c27b60d9b64e760ba3e8c8a1d43 Mon Sep 17 00:00:00 2001
From: David Henningsson <diwic@ubuntu.com>
Date: Sun, 14 Aug 2016 09:31:25 +0200
Subject: [PATCH] mixer: Fix rounding mode documentation
The documentation specifies three different rounding modes, but this
is wrong, because they all end up calling snd_tlv_convert_from_dB,
which only has two rounding modes.
Signed-off-by: David Henningsson <diwic@ubuntu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/mixer/simple.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/mixer/simple.c b/src/mixer/simple.c
index fd9ba93ee791..82476d5ca0f2 100644
--- a/src/mixer/simple.c
+++ b/src/mixer/simple.c
@@ -376,7 +376,7 @@ int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long
* \brief Return corresponding integer playback volume for given dB value for a mixer simple element
* \param elem Mixer simple element handle
* \param value value to be converted to dB range
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param dir rounding mode - rounds up if dir > 0, otherwise rounds down
* \param dBvalue pointer to returned dB value
* \return 0 on success otherwise a negative error code
*/
@@ -454,7 +454,7 @@ int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_
* \param elem Mixer simple element handle
* \param channel mixer simple element channel identifier
* \param value control value in dB * 100
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param dir rounding mode - rounds up if dir > 0, otherwise rounds down
* \return 0 on success otherwise a negative error code
*/
int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
@@ -491,7 +491,7 @@ int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value)
* \brief Set value in dB of playback volume control for all channels of a mixer simple element
* \param elem Mixer simple element handle
* \param value control value in dB * 100
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param dir rounding mode - rounds up if dir > 0, otherwise rounds down
* \return 0 on success otherwise a negative error code
*/
int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir)
@@ -706,7 +706,7 @@ int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long
* \param elem Mixer simple element handle
* \param dBvalue dB value to be converted to integer range
* \param value pointer to returned integer value
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param dir rounding mode - rounds up if dir > 0, otherwise rounds down
* \return 0 on success otherwise a negative error code
*/
int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
@@ -777,7 +777,7 @@ int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_c
* \param elem Mixer simple element handle
* \param channel mixer simple element channel identifier
* \param value control value in dB * 100
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param dir rounding mode - rounds up if dir > 0, otherwise rounds down
* \return 0 on success otherwise a negative error code
*/
int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
@@ -814,7 +814,7 @@ int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value)
* \brief Set value in dB of capture volume control for all channels of a mixer simple element
* \param elem Mixer simple element handle
* \param value control value in dB * 100
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param dir rounding mode - rounds up if dir > 0, otherwise rounds down
* \return 0 on success otherwise a negative error code
*/
int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir)
--
2.10.2

View File

@ -0,0 +1,39 @@
From 7640856769d2d687877df720af5ef1ecd8938888 Mon Sep 17 00:00:00 2001
From: Ismael Luceno <ismael@iodev.co.uk>
Date: Mon, 22 Aug 2016 13:04:33 -0300
Subject: [PATCH] pcm: Fix shm initialization race-condition
Easily seen when two threads try at the same time, one of them will fail.
The bug was identified by using apulse with Skype.
Fixes: dec428c35221 ("pcm: fix 'unable to create IPC shm instance' caused by fork from a thread")
Fixes: https://github.com/i-rinat/apulse/issues/38
Signed-off-by: Ismael Luceno <ismael@iodev.co.uk>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index c3925cc20fd3..643498375b34 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -96,11 +96,12 @@ int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix)
retryget:
dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t),
dmix->ipc_perm);
- if (dmix->shmid < 0) {
- if (errno == ENOENT)
+ if (dmix->shmid < 0 && errno == ENOENT) {
if ((dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t),
IPC_CREAT | IPC_EXCL | dmix->ipc_perm)) != -1)
first_instance = 1;
+ else if (errno == EEXIST)
+ goto retryget;
}
err = -errno;
if (dmix->shmid < 0) {
--
2.10.2

View File

@ -0,0 +1,130 @@
From 0fc4b4d17bfd0ce44394f6040e1d5f9dfa97a5ad Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 1 Sep 2016 14:05:00 +0200
Subject: [PATCH] pcm: Better understandable locking code
The newly added locking code seems to have confused quite a few
people, as "thread_safe=1" may be considered as if the thread-safety
lock has to be turned on. (It meant that the plugin _is_ thread-safe,
i.e. it needs no extra locking.)
For avoiding such a misunderstanding, this commit renames the relevant
pcm fields and give more comments to explain what is for what.
The former single pcm->thread_safe flag is now split to two boolean
flags, pcm->need_lock and pcm->lock_enabled. It consumes a few more
bytes, but this would be (hopefully) better understandable.
No functional change by this commit.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 16 +++++++++++-----
src/pcm/pcm_hw.c | 2 +-
src/pcm/pcm_local.h | 27 ++++++++++++++++++++++-----
3 files changed, 34 insertions(+), 11 deletions(-)
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index f8323999343e..cd87bc759ded 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2545,14 +2545,20 @@ int snd_pcm_new(snd_pcm_t **pcmp, snd_pcm_type_t type, const char *name,
INIT_LIST_HEAD(&pcm->async_handlers);
#ifdef THREAD_SAFE_API
pthread_mutex_init(&pcm->lock, NULL);
+ /* use locking as default;
+ * each plugin may suppress this in its open call
+ */
+ pcm->need_lock = 1;
{
- static int default_thread_safe = -1;
- if (default_thread_safe < 0) {
+ /* set lock_enabled field depending on $LIBASOUND_THREAD_SAFE */
+ static int do_lock_enable = -1; /* uninitialized */
+
+ /* evaluate env var only once at the first open for consistency */
+ if (do_lock_enable == -1) {
char *p = getenv("LIBASOUND_THREAD_SAFE");
- default_thread_safe = !p || *p != '0';
+ do_lock_enable = !p || *p != '0';
}
- if (!default_thread_safe)
- pcm->thread_safe = -1; /* force to disable */
+ pcm->lock_enabled = do_lock_enable;
}
#endif
*pcmp = pcm;
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c
index 3a5634c1d39a..56e88b6bf6c0 100644
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -1514,7 +1514,7 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name,
pcm->poll_events = info.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
pcm->tstamp_type = tstamp_type;
#ifdef THREAD_SAFE_API
- pcm->thread_safe = 1;
+ pcm->need_lock = 0; /* hw plugin is thread-safe */
#endif
ret = snd_pcm_hw_mmap_status(pcm);
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index bb7964d7833e..bba2f15ac463 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -244,7 +244,12 @@ struct _snd_pcm {
void *private_data;
struct list_head async_handlers;
#ifdef THREAD_SAFE_API
- int thread_safe;
+ int need_lock; /* true = this PCM (plugin) is thread-unsafe,
+ * thus it needs a lock.
+ */
+ int lock_enabled; /* thread-safety lock is enabled on the system;
+ * it's set depending on $LIBASOUND_THREAD_SAFE.
+ */
pthread_mutex_t lock;
#endif
};
@@ -1085,24 +1090,36 @@ static inline void sw_set_period_event(snd_pcm_sw_params_t *params, int val)
#define PCMINABORT(pcm) (((pcm)->mode & SND_PCM_ABORT) != 0)
#ifdef THREAD_SAFE_API
+/*
+ * __snd_pcm_lock() and __snd_pcm_unlock() are used to lock/unlock the plugin
+ * forcibly even if it's declared as thread-safe. It's needed only for some
+ * codes that are thread-unsafe per design (e.g. snd_pcm_nonblock()).
+ *
+ * OTOH, snd_pcm_lock() and snd_pcm_unlock() are used to lock/unlock the plugin
+ * in normal situations. They do lock/unlock only when the plugin is
+ * thread-unsafe.
+ *
+ * Both __snd_pcm_lock() and snd_pcm_lock() (and their unlocks) wouldn't do
+ * any action when the whole locking is disabled via $LIBASOUND_THREAD_SAFE=0.
+ */
static inline void __snd_pcm_lock(snd_pcm_t *pcm)
{
- if (pcm->thread_safe >= 0)
+ if (pcm->lock_enabled)
pthread_mutex_lock(&pcm->lock);
}
static inline void __snd_pcm_unlock(snd_pcm_t *pcm)
{
- if (pcm->thread_safe >= 0)
+ if (pcm->lock_enabled)
pthread_mutex_unlock(&pcm->lock);
}
static inline void snd_pcm_lock(snd_pcm_t *pcm)
{
- if (!pcm->thread_safe)
+ if (pcm->lock_enabled && pcm->need_lock)
pthread_mutex_lock(&pcm->lock);
}
static inline void snd_pcm_unlock(snd_pcm_t *pcm)
{
- if (!pcm->thread_safe)
+ if (pcm->lock_enabled && pcm->need_lock)
pthread_mutex_unlock(&pcm->lock);
}
#else /* THREAD_SAFE_API */
--
2.10.2

View File

@ -0,0 +1,52 @@
From 4ec907c773a807d58b17f909522c27d05878b5b5 Mon Sep 17 00:00:00 2001
From: Antonio Ospite <ao2@ao2.it>
Date: Fri, 23 Sep 2016 18:11:16 +0200
Subject: [PATCH] ucm: fix crash when calling snd_use_case_geti() with no
device or modifier
When calling snd_use_case_geti(uc_mgr, "_devstatus", &lvalue) the code
ends up calling device_status(uc_mgr, NULL), which result in a crash in
strcmp(dev->name, NULL), when there are enabled devices.
This happens because snd_use_case_geti() allows a "_devstatus"
identifier even if it's only supposed to allow the form
"_devstatus/{device}".
So check that the device name is not null.
The same issue occurs with "_modstatus", this change fixes that as well.
Signed-off-by: Antonio Ospite <ao2@ao2.it>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/ucm/main.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/ucm/main.c b/src/ucm/main.c
index 24d9510ecfec..8cc92089a326 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -1528,12 +1528,20 @@ int snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
str = NULL;
}
if (check_identifier(identifier, "_devstatus")) {
+ if (!str) {
+ err = -EINVAL;
+ goto __end;
+ }
err = device_status(uc_mgr, str);
if (err >= 0) {
*value = err;
err = 0;
}
} else if (check_identifier(identifier, "_modstatus")) {
+ if (!str) {
+ err = -EINVAL;
+ goto __end;
+ }
err = modifier_status(uc_mgr, str);
if (err >= 0) {
*value = err;
--
2.10.2

View File

@ -0,0 +1,108 @@
From 64481b3c72d758e8330e742aac95c7b66b863020 Mon Sep 17 00:00:00 2001
From: Antonio Ospite <ao2@ao2.it>
Date: Fri, 23 Sep 2016 18:18:57 +0200
Subject: [PATCH] ucm: docs: typeset lists of identifiers explicitly
Doxygen doesn't preserve formatting that relies only on indentation,
typeset lists of identifiers explicitly.
This makes the HTML docs a lot more readable.
This change comes along the lines of commit 72aa0f8332fb ("ucm: reformat
snd_use_case_get() doc").
Some TABs has been added too in order to preserve the aligned look when
reading the source code.
Signed-off-by: Antonio Ospite <ao2@ao2.it>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/use-case.h | 57 +++++++++++++++++++++++++++---------------------------
1 file changed, 29 insertions(+), 28 deletions(-)
diff --git a/include/use-case.h b/include/use-case.h
index 9aac6e2fb51d..8911645b5c4d 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -192,20 +192,21 @@ int snd_use_case_free_list(const char *list[], int items);
* \return Number of list entries if success, otherwise a negative error code
*
* Defined identifiers:
- * NULL - get card list
- * (in pair cardname+comment)
- * _verbs - get verb list
- * (in pair verb+comment)
- * _devices[/{verb}] - get list of supported devices
- * (in pair device+comment)
- * _modifiers[/{verb}]- get list of supported modifiers
- * (in pair modifier+comment)
- * TQ[/{verb}] - get list of TQ identifiers
- * _enadevs - get list of enabled devices
- * _enamods - get list of enabled modifiers
+ * - NULL - get card list
+ * (in pair cardname+comment)
+ * - _verbs - get verb list
+ * (in pair verb+comment)
+ * - _devices[/{verb}] - get list of supported devices
+ * (in pair device+comment)
+ * - _modifiers[/{verb}] - get list of supported modifiers
+ * (in pair modifier+comment)
+ * - TQ[/{verb}] - get list of TQ identifiers
+ * - _enadevs - get list of enabled devices
+ * - _enamods - get list of enabled modifiers
+ *
+ * - _supporteddevs/{modifier}|{device}[/{verb}] - list of supported devices
+ * - _conflictingdevs/{modifier}|{device}[/{verb}] - list of conflicting devices
*
- * _supporteddevs/{modifier}|{device}[/{verb}] - list of supported devices
- * _conflictingdevs/{modifier}|{device}[/{verb}] - list of conflicting devices
* Note that at most one of the supported/conflicting devs lists has
* any entries, and when neither is present, all devices are supported.
*
@@ -331,8 +332,8 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
* \return Zero if success, otherwise a negative error code
*
* Known identifiers:
- * _devstatus/{device} - return status for given device
- * _modstatus/{modifier} - return status for given modifier
+ * - _devstatus/{device} - return status for given device
+ * - _modstatus/{modifier} - return status for given modifier
*/
int snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
const char *identifier,
@@ -346,19 +347,19 @@ int snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
* \return Zero if success, otherwise a negative error code
*
* Known identifiers:
- * _verb - set current verb = value
- * _enadev - enable given device = value
- * _disdev - disable given device = value
- * _swdev/{old_device} - new_device = value
- * - disable old_device and then enable new_device
- * - if old_device is not enabled just return
- * - check transmit sequence firstly
- * _enamod - enable given modifier = value
- * _dismod - disable given modifier = value
- * _swmod/{old_modifier} - new_modifier = value
- * - disable old_modifier and then enable new_modifier
- * - if old_modifier is not enabled just return
- * - check transmit sequence firstly
+ * - _verb - set current verb = value
+ * - _enadev - enable given device = value
+ * - _disdev - disable given device = value
+ * - _swdev/{old_device} - new_device = value
+ * - disable old_device and then enable new_device
+ * - if old_device is not enabled just return
+ * - check transmit sequence firstly
+ * - _enamod - enable given modifier = value
+ * - _dismod - disable given modifier = value
+ * - _swmod/{old_modifier} - new_modifier = value
+ * - disable old_modifier and then enable new_modifier
+ * - if old_modifier is not enabled just return
+ * - check transmit sequence firstly
*/
int snd_use_case_set(snd_use_case_mgr_t *uc_mgr,
const char *identifier,
--
2.10.2

View File

@ -0,0 +1,105 @@
From 21dcb000c8cfe38d3120419e0bd5360855318e55 Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Thu, 29 Sep 2016 08:57:20 +0900
Subject: [PATCH] Update include/sound/tlv.h from 4.9-pre kernel uapi
The UAPI header in 4.9-pre kernel newly includes existent macros related
to tlv operation, mainly for layout of TLV packet payload.
This commit updates corresponding backport header in this library.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/sound/tlv.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/include/sound/tlv.h b/include/sound/tlv.h
index 33d747df1410..b4df440c015b 100644
--- a/include/sound/tlv.h
+++ b/include/sound/tlv.h
@@ -20,4 +20,81 @@
#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */
#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */
+/*
+ * channel-mapping TLV items
+ * TLV length must match with num_channels
+ */
+#define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */
+#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */
+#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */
+
+/*
+ * TLV structure is right behind the struct snd_ctl_tlv:
+ * unsigned int type - see SNDRV_CTL_TLVT_*
+ * unsigned int length
+ * .... data aligned to sizeof(unsigned int), use
+ * block_length = (length + (sizeof(unsigned int) - 1)) &
+ * ~(sizeof(unsigned int) - 1)) ....
+ */
+#define SNDRV_CTL_TLVD_ITEM(type, ...) \
+ (type), SNDRV_CTL_TLVD_LENGTH(__VA_ARGS__), __VA_ARGS__
+#define SNDRV_CTL_TLVD_LENGTH(...) \
+ ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
+
+#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)
+#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_CONTAINER_ITEM(__VA_ARGS__) \
+ }
+
+#define SNDRV_CTL_TLVD_DB_SCALE_MASK 0xffff
+#define SNDRV_CTL_TLVD_DB_SCALE_MUTE 0x10000
+#define SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \
+ (min), \
+ ((step) & SNDRV_CTL_TLVD_DB_SCALE_MASK) | \
+ ((mute) ? SNDRV_CTL_TLVD_DB_SCALE_MUTE : 0))
+#define SNDRV_CTL_TLVD_DECLARE_DB_SCALE(name, min, step, mute) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
+ }
+
+/* dB scale specified with min/max values instead of step */
+#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(name, min_dB, max_dB) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
+ }
+#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE(name, min_dB, max_dB) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
+ }
+
+/* linear volume between min_dB and max_dB (.01dB unit) */
+#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(name, min_dB, max_dB) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
+ }
+
+/* dB range container:
+ * Items in dB range container must be ordered by their values and by their
+ * dB values. This implies that larger values must correspond with larger
+ * dB values (which is also required for all other mixer controls).
+ */
+/* Each item is: <min> <max> <TLV> */
+#define SNDRV_CTL_TLVD_DB_RANGE_ITEM(...) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__)
+#define SNDRV_CTL_TLVD_DECLARE_DB_RANGE(name, ...) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) \
+ }
+
+#define SNDRV_CTL_TLVD_DB_GAIN_MUTE -9999999
+
#endif
--
2.10.2

View File

@ -0,0 +1,386 @@
From ee1182d2cbb4930ca1166bc03f3b0fcfbb594145 Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Thu, 29 Sep 2016 08:57:21 +0900
Subject: [PATCH] test: use actual information for TLV operation
Currently, this test program uses undefined type of TLV data. This can
bring confusions to userspace applications.
This commit replaces the array with valid information, constructed by newly
exported TLV macros from kernel land.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
test/user-ctl-element-set.c | 214 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 178 insertions(+), 36 deletions(-)
diff --git a/test/user-ctl-element-set.c b/test/user-ctl-element-set.c
index 9b9dc598f0af..75083d219fe6 100644
--- a/test/user-ctl-element-set.c
+++ b/test/user-ctl-element-set.c
@@ -8,6 +8,7 @@
*/
#include "../include/asoundlib.h"
+#include <sound/tlv.h>
struct elem_set_trial {
snd_ctl_t *handle;
@@ -25,8 +26,30 @@ struct elem_set_trial {
snd_ctl_elem_info_t *info);
void (*change_elem_members)(struct elem_set_trial *trial,
snd_ctl_elem_value_t *elem_data);
+ int (*allocate_elem_set_tlv)(struct elem_set_trial *trial,
+ unsigned int **tlv);
};
+struct chmap_entry {
+ unsigned int type;
+ unsigned int length;
+ unsigned int maps[0];
+};
+
+/*
+ * History of TLV feature:
+ *
+ * 2016/09/15: 398fa4db6c69 ("ALSA: control: move layout of TLV payload to UAPI
+ * header")
+ * 2012/07/21: 2d3391ec0ecc ("ALSA: PCM: channel mapping API implementation")
+ * 2011/11/20: bf1d1c9b6179 ("ALSA: tlv: add DECLARE_TLV_DB_RANGE()")
+ * 2009/07/16: 085f30654175 ("ALSA: Add new TLV types for dBwith min/max")
+ * 2006/09/06: 55a29af5ed5d ("[ALSA] Add definition of TLV dB range compound")
+ * 2006/08/28: 063a40d9111c ("Add the definition of linear volume TLV")
+ * 2006/08/28: 42750b04c5ba ("[ALSA] Control API - TLV implementation for
+ * additional information like dB scale")
+ */
+
/* Operations for elements in an element set with boolean type. */
static int add_bool_elem_set(struct elem_set_trial *trial,
snd_ctl_elem_info_t *info)
@@ -47,13 +70,30 @@ static void change_bool_elem_members(struct elem_set_trial *trial,
}
}
+static int allocate_bool_elem_set_tlv(struct elem_set_trial *trial,
+ unsigned int **tlv)
+{
+ /*
+ * Performs like a toggle switch for attenuation, because they're bool
+ * elements.
+ */
+ static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(range, -10000, 0);
+
+ *tlv = malloc(sizeof(range));
+ if (*tlv == NULL)
+ return -ENOMEM;
+ memcpy(*tlv, range, sizeof(range));
+
+ return 0;
+}
+
/* Operations for elements in an element set with integer type. */
static int add_int_elem_set(struct elem_set_trial *trial,
snd_ctl_elem_info_t *info)
{
return snd_ctl_add_integer_elem_set(trial->handle, info,
trial->element_count, trial->member_count,
- 0, 99, 1);
+ 0, 25, 1);
}
static int check_int_elem_props(struct elem_set_trial *trial,
@@ -61,7 +101,7 @@ static int check_int_elem_props(struct elem_set_trial *trial,
{
if (snd_ctl_elem_info_get_min(info) != 0)
return -EIO;
- if (snd_ctl_elem_info_get_max(info) != 99)
+ if (snd_ctl_elem_info_get_max(info) != 25)
return -EIO;
if (snd_ctl_elem_info_get_step(info) != 1)
return -EIO;
@@ -81,6 +121,41 @@ static void change_int_elem_members(struct elem_set_trial *trial,
}
}
+static int allocate_int_elem_set_tlv(struct elem_set_trial *trial,
+ unsigned int **tlv)
+{
+ unsigned int len, pos;
+ unsigned int i, j;
+ struct chmap_entry *entry;
+
+ /* Calculate size of TLV packet for channel-mapping information. */
+ len = 0;
+ for (i = 1; i <= 25; ++i) {
+ len += sizeof(struct chmap_entry);
+ len += i * sizeof(unsigned int);
+ }
+
+ *tlv = malloc(len);
+ if (*tlv == NULL)
+ return -ENOMEM;
+
+ /*
+ * Emulate channel-mapping information in in-kernel implementation.
+ * Here, 25 entries are for each different channel.
+ */
+ pos = 0;
+ for (i = 1; i <= 25 && pos < len; ++i) {
+ entry = (struct chmap_entry *)&(*tlv)[pos];
+ entry->type = SNDRV_CTL_TLVT_CHMAP_FIXED;
+ entry->length = i * sizeof(unsigned int);
+ for (j = 0; j < i; ++j)
+ entry->maps[j] = SND_CHMAP_MONO + j;
+ pos += sizeof(struct chmap_entry) + i * sizeof(unsigned int);
+ }
+
+ return 0;
+}
+
/* Operations for elements in an element set with enumerated type. */
static const char *const labels[] = {
"trusty",
@@ -158,6 +233,24 @@ static void change_bytes_elem_members(struct elem_set_trial *trial,
}
}
+static int allocate_bytes_elem_set_tlv(struct elem_set_trial *trial,
+ unsigned int **tlv)
+{
+ /*
+ * Emulate AK4396.
+ * 20 * log10(x/255) (dB)
+ * Here, x is written value.
+ */
+ static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(range, -4813, 0);
+
+ *tlv = malloc(sizeof(range));
+ if (*tlv == NULL)
+ return -ENOMEM;
+ memcpy(*tlv, range, sizeof(range));
+
+ return 0;
+}
+
/* Operations for elements in an element set with iec958 type. */
static int add_iec958_elem_set(struct elem_set_trial *trial,
snd_ctl_elem_info_t *info)
@@ -197,17 +290,17 @@ static int add_int64_elem_set(struct elem_set_trial *trial,
{
return snd_ctl_add_integer64_elem_set(trial->handle, info,
trial->element_count, trial->member_count,
- 100, 10000, 30);
+ 0, 10000, 1);
}
static int check_int64_elem_props(struct elem_set_trial *trial,
snd_ctl_elem_info_t *info)
{
- if (snd_ctl_elem_info_get_min64(info) != 100)
+ if (snd_ctl_elem_info_get_min64(info) != 0)
return -EIO;
if (snd_ctl_elem_info_get_max64(info) != 10000)
return -EIO;
- if (snd_ctl_elem_info_get_step64(info) != 30)
+ if (snd_ctl_elem_info_get_step64(info) != 1)
return -EIO;
return 0;
@@ -225,6 +318,45 @@ static void change_int64_elem_members(struct elem_set_trial *trial,
}
}
+static int allocate_int64_elem_set_tlv(struct elem_set_trial *trial,
+ unsigned int **tlv)
+{
+ /*
+ * Use this fomula between linear/dB value:
+ *
+ * Linear: dB range (coeff)
+ * 0<-> 4: -59.40<->-56.36 (44)
+ * 4<->22: -56.36<->-45.56 (60)
+ * 22<->33: -45.56<->-40.72 (76)
+ * 33<->37: -40.72<->-38.32 (44)
+ * 37<->48: -38.32<->-29.96 (76)
+ * 48<->66: -29.96<->-22.04 (60)
+ * 66<->84: -22.04<-> -8.36 (44)
+ * 84<->95: -8.36<-> -1.76 (60)
+ * 95<->99: -1.76<-> 0.00 (76)
+ * 100<->..: 0.0
+ */
+ static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(range,
+ 0, 4, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-5940, 44, 1),
+ 4, 22, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-5636, 60, 0),
+ 22, 33, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-4556, 76, 0),
+ 33, 37, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-4072, 44, 0),
+ 37, 48, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-3832, 76, 0),
+ 48, 66, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-2996, 60, 0),
+ 66, 84, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-2204, 44, 0),
+ 84, 95, SNDRV_CTL_TLVD_DB_SCALE_ITEM( -836, 60, 0),
+ 95, 99, SNDRV_CTL_TLVD_DB_SCALE_ITEM( -176, 76, 0),
+ 100, 10000, SNDRV_CTL_TLVD_DB_SCALE_ITEM(0, 0, 0),
+ );
+
+ *tlv = malloc(sizeof(range));
+ if (*tlv == NULL)
+ return -ENOMEM;
+ memcpy(*tlv, range, sizeof(range));
+
+ return 0;
+}
+
/* Common operations. */
static int add_elem_set(struct elem_set_trial *trial)
{
@@ -414,41 +546,41 @@ static int check_elems(struct elem_set_trial *trial)
static int check_tlv(struct elem_set_trial *trial)
{
- unsigned int orig[8], curr[8];
+ unsigned int *tlv;
+ unsigned int len;
+ unsigned int *curr;
int err;
- /*
- * See a layout of 'struct snd_ctl_tlv'. I don't know the reason to
- * construct this buffer with the same layout. It should be abstracted
- * inner userspace library...
- */
- orig[0] = snd_ctl_elem_id_get_numid(trial->id);
- orig[1] = 6 * sizeof(orig[0]);
- orig[2] = 'a';
- orig[3] = 'b';
- orig[4] = 'c';
- orig[5] = 'd';
- orig[6] = 'e';
- orig[7] = 'f';
+ err = trial->allocate_elem_set_tlv(trial, &tlv);
+ if (err < 0)
+ return err;
+
+ len = tlv[1] + sizeof(unsigned int) * 2;
+ curr = malloc(len);
+ if (curr == NULL) {
+ free(tlv);
+ return -ENOMEM;
+ }
/*
* In in-kernel implementation, write and command operations are the
- * same for an element set added by userspace applications. Here, I
+ * same for an element set added by userspace applications. Here, I
* use write.
*/
err = snd_ctl_elem_tlv_write(trial->handle, trial->id,
- (const unsigned int *)orig);
+ (const unsigned int *)tlv);
if (err < 0)
- return err;
+ goto end;
- err = snd_ctl_elem_tlv_read(trial->handle, trial->id, curr,
- sizeof(curr));
+ err = snd_ctl_elem_tlv_read(trial->handle, trial->id, curr, len);
if (err < 0)
- return err;
-
- if (memcmp(curr, orig, sizeof(orig)) != 0)
- return -EIO;
+ goto end;
+ if (memcmp(curr, tlv, len) != 0)
+ err = -EIO;
+end:
+ free(tlv);
+ free(curr);
return 0;
}
@@ -484,6 +616,8 @@ int main(void)
trial.add_elem_set = add_bool_elem_set;
trial.check_elem_props = NULL;
trial.change_elem_members = change_bool_elem_members;
+ trial.allocate_elem_set_tlv =
+ allocate_bool_elem_set_tlv;
break;
case SND_CTL_ELEM_TYPE_INTEGER:
trial.element_count = 900;
@@ -495,6 +629,8 @@ int main(void)
trial.add_elem_set = add_int_elem_set;
trial.check_elem_props = check_int_elem_props;
trial.change_elem_members = change_int_elem_members;
+ trial.allocate_elem_set_tlv =
+ allocate_int_elem_set_tlv;
break;
case SND_CTL_ELEM_TYPE_ENUMERATED:
trial.element_count = 900;
@@ -506,6 +642,7 @@ int main(void)
trial.add_elem_set = add_enum_elem_set;
trial.check_elem_props = check_enum_elem_props;
trial.change_elem_members = change_enum_elem_members;
+ trial.allocate_elem_set_tlv = NULL;
break;
case SND_CTL_ELEM_TYPE_BYTES:
trial.element_count = 900;
@@ -517,6 +654,8 @@ int main(void)
trial.add_elem_set = add_bytes_elem_set;
trial.check_elem_props = NULL;
trial.change_elem_members = change_bytes_elem_members;
+ trial.allocate_elem_set_tlv =
+ allocate_bytes_elem_set_tlv;
break;
case SND_CTL_ELEM_TYPE_IEC958:
trial.element_count = 1;
@@ -528,6 +667,7 @@ int main(void)
trial.add_elem_set = add_iec958_elem_set;
trial.check_elem_props = NULL;
trial.change_elem_members = change_iec958_elem_members;
+ trial.allocate_elem_set_tlv = NULL;
break;
case SND_CTL_ELEM_TYPE_INTEGER64:
default:
@@ -540,6 +680,8 @@ int main(void)
trial.add_elem_set = add_int64_elem_set;
trial.check_elem_props = check_int64_elem_props;
trial.change_elem_members = change_int64_elem_members;
+ trial.allocate_elem_set_tlv =
+ allocate_int64_elem_set_tlv;
break;
}
@@ -589,22 +731,22 @@ int main(void)
}
/*
- * Test an operation to change threshold data of this element set,
- * except for IEC958 type.
+ * Test an operation to change TLV data of this element set,
+ * except for enumerated and IEC958 type.
*/
- if (trial.type != SND_CTL_ELEM_TYPE_IEC958) {
+ if (trial.allocate_elem_set_tlv != NULL) {
err = check_tlv(&trial);
if (err < 0) {
- printf("Fail to change threshold level of an "
- "element set with %s type.\n",
+ printf("Fail to change TLV data of an element "
+ "set with %s type.\n",
snd_ctl_elem_type_name(trial.type));
break;
}
err = check_event(&trial, SND_CTL_EVENT_MASK_TLV, 1);
if (err < 0) {
- printf("Fail to check an event to change "
- "threshold level of an an element set "
- "with %s type.\n",
+ printf("Fail to check an event to change TLV"
+ "data of an an element set with %s "
+ "type.\n",
snd_ctl_elem_type_name(trial.type));
break;
}
--
2.10.2

View File

@ -0,0 +1,52 @@
From d31e37d12c58ca3be72e404a222289a896029ef1 Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Thu, 29 Sep 2016 08:57:22 +0900
Subject: [PATCH] ctl: improve API documentation for TLV operation
A commit fe1b08803db6 ("ctl: improve API documentation for threshold level
operations") changes documentations for some TLV-related APIs with wrong
explanations.
This commit fix it with better explanations.
Fixes: fe1b08803db6 ("ctl: improve API documentation for threshold level operations")
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/control/control.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/control/control.c b/src/control/control.c
index 6c00b8e50d2b..422582d40600 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -912,7 +912,7 @@ static int snd_ctl_tlv_do(snd_ctl_t *ctl, int op_flag,
}
/**
- * \brief Set given data to an element as threshold level.
+ * \brief Read structured data from an element set to given buffer.
* \param ctl A handle of backend module for control interface.
* \param id ID of an element.
* \param tlv An array with members of unsigned int type.
@@ -940,7 +940,7 @@ int snd_ctl_elem_tlv_read(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
}
/**
- * \brief Set given data to an element as threshold level.
+ * \brief Write structured data from given buffer to an element set.
* \param ctl A handle of backend module for control interface.
* \param id ID of an element.
* \param tlv An array with members of unsigned int type. The second member
@@ -957,7 +957,7 @@ int snd_ctl_elem_tlv_write(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
}
/**
- * \brief Set given data to an element as threshold level.
+ * \brief Process structured data from given buffer for an element set.
* \param ctl A handle of backend module for control interface.
* \param id ID of an element.
* \param tlv An array with members of unsigned int type. The second member
--
2.10.2

View File

@ -0,0 +1,64 @@
From e55d735f84364d3b7d38104cee37c968e3797ea4 Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Thu, 29 Sep 2016 08:57:23 +0900
Subject: [PATCH] ctl: improve documentation about TLV-related APIs
The documentation gives no hints to users about format of TLV data.
This commit add hints to construct/parse the information.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/control/control.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/src/control/control.c b/src/control/control.c
index 422582d40600..40ee9b7516a2 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -918,6 +918,13 @@ static int snd_ctl_tlv_do(snd_ctl_t *ctl, int op_flag,
* \param tlv An array with members of unsigned int type.
* \param tlv_size The length of the array.
* \return 0 on success otherwise a negative error code
+ *
+ * The format of an array of \a tlv argument is:
+ * tlv[0]: Type. One of SND_CTL_TLVT_XXX.
+ * tlv[1]: Length. The length of value in units of byte.
+ * tlv[2..]: Value. Depending on the type.
+ *
+ * Details are described in <sound/tlv.h>.
*/
int snd_ctl_elem_tlv_read(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
unsigned int *tlv, unsigned int tlv_size)
@@ -948,6 +955,13 @@ int snd_ctl_elem_tlv_read(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
* \retval 0 on success
* \retval >0 on success when value was changed
* \retval <0 a negative error code
+ *
+ * The format of an array of \a tlv argument is:
+ * tlv[0]: Type. One of SND_CTL_TLVT_XXX.
+ * tlv[1]: Length. The length of value in units of byte.
+ * tlv[2..]: Value. Depending on the type.
+ *
+ * Details are described in <sound/tlv.h>.
*/
int snd_ctl_elem_tlv_write(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
const unsigned int *tlv)
@@ -965,6 +979,13 @@ int snd_ctl_elem_tlv_write(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
* \retval 0 on success
* \retval >0 on success when value was changed
* \retval <0 a negative error code
+ *
+ * The format of an array of \a tlv argument is:
+ * tlv[0]: Type. One of SND_CTL_TLVT_XXX.
+ * tlv[1]: Length. The length of value in units of byte.
+ * tlv[2..]: Value. Depending on the type.
+ *
+ * Details are described in <sound/tlv.h>.
*/
int snd_ctl_elem_tlv_command(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
const unsigned int *tlv)
--
2.10.2

View File

@ -0,0 +1,59 @@
From 4298736ddad3e61dee2d379c8042f304317a6f3c Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Thu, 29 Sep 2016 08:57:24 +0900
Subject: [PATCH] ctl: correct documentation about TLV feature
From my misunderstanding, some explanations are wrong. This commit
corrects them.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/control/control.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/control/control.c b/src/control/control.c
index 40ee9b7516a2..134ba4c8ebea 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -59,27 +59,27 @@ elements included in the element set.
When the value of member is changed, corresponding events are transferred to
userspace applications. The applications should subscribe any events in advance.
-\section tlv_blob Thredshold level and arbitrary data
+\section tlv_blob Supplemental data for elements in an element set
-TLV feature is designed to transfer data about threshold level between a driver
-and any userspace applications. The data is for an element set.
+TLV feature is designed to transfer data in a shape of Type/Length/Value,
+between a driver and any userspace applications. The main purpose is to attach
+supplement information for elements to an element set; e.g. dB range.
At first, this feature was implemented to add pre-defined data readable to
userspace applications. Soon, it was extended to handle several operations;
read, write and command. The original implementation remains as the read
operation. The command operation allows drivers to have own implementations
-against requests from userspace applications. As of 2016, simple write operation
-is not supported yet.
+against requests from userspace applications.
This feature was introduced to ALSA control feature in 2006, at commit
c7a0708a2362, corresponding to a series of work for Linux kernel (42750b04c5ba
and 8aa9b586e420).
-This feature can transfer arbitrary data in a shape of an array with members of
-unsigned int type, therefore it can be used to deliver quite large arbitrary
-data from userspace to in-kernel drivers via ALSA control character device.
-Focusing on this nature, some in-kernel implementations utilize this feature for
-I/O operations.
+There's no limitation about maximum size of the data, therefore it can be used
+to deliver quite large arbitrary data from userspace to in-kernel drivers via
+ALSA control character device. Focusing on this nature, as of 2016, some
+in-kernel implementations utilize this feature for I/O operations. This is
+against the original design.
*/
#include <stdio.h>
--
2.10.2

View File

@ -0,0 +1,313 @@
From 4dfae1adb31440a37e2183626518f1373eb38b15 Mon Sep 17 00:00:00 2001
From: Vinod Koul <vinod.koul@intel.com>
Date: Fri, 7 Oct 2016 16:28:23 +0530
Subject: [PATCH] conf/ucm: skylake: add skylake-rt286 conf files
This add the UCM conf files for skylake enabling I2S audio, HDMI and DMIC
ports.
Signed-off-by: Karthik D M <karthik.d.m@intel.com>
Signed-off-by: Nishit Sharma <nishitx.sharma@intel.com>
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
configure.ac | 1 +
src/conf/ucm/Makefile.am | 2 +-
src/conf/ucm/skylake-rt286/Hdmi1 | 20 ++++
src/conf/ucm/skylake-rt286/Hdmi2 | 20 ++++
src/conf/ucm/skylake-rt286/HiFi | 129 ++++++++++++++++++++++++++
src/conf/ucm/skylake-rt286/Makefile.am | 4 +
src/conf/ucm/skylake-rt286/skylake-rt286.conf | 60 ++++++++++++
7 files changed, 235 insertions(+), 1 deletion(-)
create mode 100644 src/conf/ucm/skylake-rt286/Hdmi1
create mode 100644 src/conf/ucm/skylake-rt286/Hdmi2
create mode 100644 src/conf/ucm/skylake-rt286/HiFi
create mode 100644 src/conf/ucm/skylake-rt286/Makefile.am
create mode 100644 src/conf/ucm/skylake-rt286/skylake-rt286.conf
diff --git a/configure.ac b/configure.ac
index a1de230e588c..0dfbe81c6595 100644
--- a/configure.ac
+++ b/configure.ac
@@ -673,6 +673,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
src/conf/ucm/PAZ00/Makefile \
src/conf/ucm/GoogleNyan/Makefile \
src/conf/ucm/broadwell-rt286/Makefile \
+ src/conf/ucm/skylake-rt286/Makefile \
src/conf/ucm/VEYRON-I2S/Makefile \
src/conf/ucm/chtrt5645/Makefile \
src/conf/ucm/DB410c/Makefile \
diff --git a/src/conf/ucm/Makefile.am b/src/conf/ucm/Makefile.am
index 7bf432e70e26..a11d324e785b 100644
--- a/src/conf/ucm/Makefile.am
+++ b/src/conf/ucm/Makefile.am
@@ -1 +1 @@
-SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 VEYRON-I2S chtrt5645 DB410c
+SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 skylake-rt286 VEYRON-I2S chtrt5645 DB410c
diff --git a/src/conf/ucm/skylake-rt286/Hdmi1 b/src/conf/ucm/skylake-rt286/Hdmi1
new file mode 100644
index 000000000000..0e00fc844301
--- /dev/null
+++ b/src/conf/ucm/skylake-rt286/Hdmi1
@@ -0,0 +1,20 @@
+# Usecase for device HDMI1/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms
+# For Audio in I2S mode
+
+SectionDevice."Hdmi1" {
+ Comment "HDMI/Display Port 1 Stereo"
+
+ EnableSequence [
+ ]
+
+ DisableSequence [
+ ]
+
+ Value {
+ PlaybackPCM "hw:skylakert286,4"
+ PlaybackChannels "2"
+ PlaybackPriority "3"
+ JackControl "HDMI/DP, pcm=4 Jack"
+ }
+}
+
diff --git a/src/conf/ucm/skylake-rt286/Hdmi2 b/src/conf/ucm/skylake-rt286/Hdmi2
new file mode 100644
index 000000000000..89b31aa4b8f9
--- /dev/null
+++ b/src/conf/ucm/skylake-rt286/Hdmi2
@@ -0,0 +1,20 @@
+# Usecase for device HDMI2/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms
+# For Audio in I2S mode
+
+SectionDevice."Hdmi2" {
+ Comment "HDMI/Display Port 2 Stereo"
+
+ EnableSequence [
+ ]
+
+ DisableSequence [
+ ]
+
+ Value {
+ PlaybackPCM "hw:skylakert286,5"
+ PlaybackChannels "2"
+ PlaybackPriority "4"
+ JackControl "HDMI/DP, pcm=5 Jack"
+ }
+}
+
diff --git a/src/conf/ucm/skylake-rt286/HiFi b/src/conf/ucm/skylake-rt286/HiFi
new file mode 100644
index 000000000000..41638f4cb9c8
--- /dev/null
+++ b/src/conf/ucm/skylake-rt286/HiFi
@@ -0,0 +1,129 @@
+# Usecase for stereo playback Speaker and Headset, Recording on DMIC and Headset MIC.
+# For Audio in I2S mode on Intel SKYLAKE/KABYLAKE platforms
+
+SectionVerb {
+
+ EnableSequence [
+ cdev "hw:skylakert286"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
+ ]
+
+ DisableSequence [
+ cdev "hw:skylakert286"
+ ]
+
+ Value {
+ TQ "HiFi"
+ CapturePCM "hw:skylakert286,1"
+ PlaybackPCM "hw:skylakert286,0"
+ }
+}
+
+SectionDevice."Headphones" {
+ Comment "Headphones"
+
+ ConflictingDevice [
+ "Speaker"
+ ]
+ EnableSequence [
+ cdev "hw:skylakert286"
+ cset "name='HPO L Switch' 1"
+ cset "name='HPO R Switch' 1"
+ cset "name='Headphone Jack Switch' 1"
+ cset "name='Speaker Playback Switch' 0,0"
+ ]
+
+ DisableSequence [
+ ]
+ Value {
+ PlaybackChannels "2"
+ PlaybackPriority "1"
+ JackControl "Headphone Jack"
+ JackHWMute "Speaker"
+ }
+}
+
+SectionDevice."Speaker" {
+ Comment "Speaker"
+
+ ConflictingDevice [
+ "Headphones"
+ ]
+ EnableSequence [
+ cdev "hw:skylakert286"
+ cset "name='SPO Switch' 1"
+ cset "name='Speaker Playback Switch' 1,1"
+ cset "name='Speaker Switch' 1"
+ cset "name='HPO L Switch' 0"
+ cset "name='HPO R Switch' 0"
+ ]
+
+ DisableSequence [
+ ]
+ Value {
+ PlaybackChannels "2"
+ PlaybackPriority "1"
+ JackHWMute "Headphones"
+ }
+}
+
+SectionDevice."Headset" {
+ Comment "Headset Mic"
+
+ ConflictingDevice [
+ "dmiccap"
+ ]
+ EnableSequence [
+ cdev "hw:skylakert286"
+ cset "name='media0_out mo codec0_in mi Switch' 1"
+ cset "name='ADC0 Capture Switch' 1,1"
+ cset "name='ADC 0 Mux' 0"
+ cset "name='Mic Jack Switch' 1"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 0"
+ ]
+
+ DisableSequence [
+ cdev "hw:skylakert286"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
+ cset "name='media0_out mo codec0_in mi Switch' 0"
+ ]
+ Value {
+ CaptureChannels "2"
+ CapturePriority "2"
+ JackControl "Mic Jack"
+ }
+}
+
+
+SectionDevice."dmiccap" {
+ Comment "DMIC Stereo"
+
+ ConflictingDevice [
+ "Headpset"
+ ]
+
+ EnableSequence [
+
+ cdev "hw:skylakert286"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
+ cset "name='media0_out mo codec0_in mi Switch' 0"
+ cset "name='ADC0 Capture Switch' 0,0"
+ cset "name='Mic Jack Switch' 0"
+ cset "name='ADC 0 Mux' 0"
+
+ ]
+
+ DisableSequence [
+ cdev "hw:skylakert286"
+ cset "name='media0_out mo codec0_in mi Switch' 1"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 0"
+ cset "name='ADC0 Capture Switch' 1,1"
+ cset "name='Mic Jack Switch' 1"
+ cset "name='ADC 0 Mux' 2"
+ ]
+ Value {
+ CaptureChannels "2"
+ CapturePriority "2"
+ }
+}
+
diff --git a/src/conf/ucm/skylake-rt286/Makefile.am b/src/conf/ucm/skylake-rt286/Makefile.am
new file mode 100644
index 000000000000..9d6a85a5bdcf
--- /dev/null
+++ b/src/conf/ucm/skylake-rt286/Makefile.am
@@ -0,0 +1,4 @@
+alsaconfigdir = @ALSA_CONFIG_DIR@
+ucmdir = $(alsaconfigdir)/ucm/skylake-rt286
+ucm_DATA = skylake-rt286.conf HiFi Hdmi1 Hdmi2
+EXTRA_DIST = $(ucm_DATA)
diff --git a/src/conf/ucm/skylake-rt286/skylake-rt286.conf b/src/conf/ucm/skylake-rt286/skylake-rt286.conf
new file mode 100644
index 000000000000..3e4322864728
--- /dev/null
+++ b/src/conf/ucm/skylake-rt286/skylake-rt286.conf
@@ -0,0 +1,60 @@
+# UCM for Intel SKYLAKE/KABYLAKE platforms
+# For Audio in I2S mode
+
+SectionUseCase."HiFi" {
+ File "HiFi"
+ Comment "Play and record HiFi quality Music"
+}
+
+SectionUseCase."Hdmi1" {
+ File "Hdmi1"
+ Comment "Play on Hdmi/DP 1"
+}
+
+SectionUseCase."Hdmi2" {
+ File "Hdmi2"
+ Comment "Play on Hdmi/DP 2"
+}
+
+ValueDefaults {
+ PlaybackCTL "hw:skylakert286"
+ CaptureCTL "hw:skylakert286"
+ CaptureChannels "2"
+ CapturePriority "2"
+}
+
+SectionDefaults [
+ cdev "hw:skylakert286"
+ cset "name='Headphone Jack Switch' 1"
+ cset "name='Speaker Switch' 1"
+ cset "name='Speaker Playback Switch' 0,0"
+ cset "name='Front DAC Switch' 1"
+ cset "name='Front RECMIX Switch' 0"
+ cset "name='Mic Jack Switch' 1"
+ cset "name='ADC 0 Mux' 2"
+ cset "name='ADC 1 Mux' 0"
+ cset "name='ADC0 Capture Volume' 105,105"
+ cset "name='ADC0 Capture Switch' 1,1"
+ cset "name='AMIC Volume' 3"
+ cset "name='DAC0 Playback Volume' 100,100"
+ cset "name='HPO L Switch' 0"
+ cset "name='HPO Mux' 0"
+ cset "name='HPO R Switch' 0"
+ cset "name='Pin 5 Mux' 1"
+ cset "name='Pin 6 Mux' 2"
+ cset "name='Pin 7 Mux' 3"
+ cset "name='RECMIX Beep Switch' 0"
+ cset "name='RECMIX Line1 Switch' 0"
+ cset "name='RECMIX Mic1 Switch' 0"
+ cset "name='SPK Mux' 0"
+ cset "name='SPO Switch' 1"
+ cset "name='codec0_out mo codec0_in mi Switch' 0"
+ cset "name='codec0_out mo dmic01_hifi_in mi Switch' 0"
+ cset "name='codec0_out mo media0_in mi Switch' 1"
+ cset "name='codec1_out mo codec0_in mi Switch' 0"
+ cset "name='codec1_out mo dmic01_hifi_in mi Switch' 0"
+ cset "name='codec1_out mo media0_in mi Switch' 0"
+ cset "name='media0_out mo codec0_in mi Switch' 1"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
+ cset "name='media0_out mo media0_in mi Switch' 0"
+]
--
2.10.2

View File

@ -0,0 +1,34 @@
From ced8722f7d98c946d1429e46252ccc061272d0db Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Wed, 19 Oct 2016 18:22:56 -0700
Subject: [PATCH] pcm_plug: Clear plugins on all error conditions
Otherwise, they will linger after the error is returned (but pcm->setup == 0).
Then, if the caller tries to clean up and call snd_pcm_close(), the assertion
plug->gen.slave == plug->req_slave will fail.
Signed-off-by: Michael Forney <mforney@mforney.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_plug.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c
index 5639b9ea8044..266707b425c1 100644
--- a/src/pcm/pcm_plug.c
+++ b/src/pcm/pcm_plug.c
@@ -652,8 +652,10 @@ static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
(plug->ttable && !plug->ttable_ok)) {
snd_pcm_t *new;
int err;
- if (k >= sizeof(funcs)/sizeof(*funcs))
+ if (k >= sizeof(funcs)/sizeof(*funcs)) {
+ snd_pcm_plug_clear(pcm);
return -EINVAL;
+ }
err = funcs[k](pcm, &new, client, &p);
if (err < 0) {
snd_pcm_plug_clear(pcm);
--
2.10.2

View File

@ -0,0 +1,47 @@
From a668a94238dc67b19ae187b52a161e027d79ee5d Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 14 Nov 2016 11:46:05 +0100
Subject: [PATCH] mixer: Don't install smixer modules unless python is enabled
Currently the whole smixer stuff depends on python, so it doesn't make
sense to install plugins partially when the python support is
disabled.
This patch changes Makefile.am not to install the smixer stuff at all
when the python support is disabled via configure script.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
modules/mixer/simple/Makefile.am | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/modules/mixer/simple/Makefile.am b/modules/mixer/simple/Makefile.am
index cb64ee8ca665..c21dd07d5180 100644
--- a/modules/mixer/simple/Makefile.am
+++ b/modules/mixer/simple/Makefile.am
@@ -1,3 +1,4 @@
+if BUILD_PYTHON
alsaplugindir = @ALSA_PLUGIN_DIR@
pkglibdir = $(alsaplugindir)/smixer
@@ -9,9 +10,7 @@ pkglib_LTLIBRARIES = smixer-sbase.la \
smixer-ac97.la \
smixer-hda.la
-if BUILD_PYTHON
pkglib_LTLIBRARIES += smixer-python.la
-endif
noinst_HEADERS = sbase.h
@@ -27,7 +26,6 @@ smixer_hda_la_SOURCES = hda.c sbasedl.c
smixer_hda_la_LDFLAGS = -module -avoid-version $(LDFLAGS_NOUNDEFINED)
smixer_hda_la_LIBADD = ../../../src/libasound.la -ldl
-if BUILD_PYTHON
smixer_python_la_SOURCES = python.c
smixer_python_la_LDFLAGS = -module -avoid-version $(LDFLAGS_NOUNDEFINED)
smixer_python_la_CFLAGS = $(PYTHON_INCLUDES)
--
2.10.2

View File

@ -0,0 +1,109 @@
From faf53c197cabeb1eb0fd1f66cd001d1469ebac09 Mon Sep 17 00:00:00 2001
From: Alan Young <consult.awy@gmail.com>
Date: Wed, 2 Nov 2016 17:40:32 +0000
Subject: [PATCH] pcm_dshare: Do not discard slave reported delay in status
result.
snd_pcm_dshare_status() gets the underlying status from the slave PCM.
This may contain a delay value that includes elements such as codec and
other transfer delays. Use this as the base for the returned delay
value, adjusted for any frames buffered locally (within the dshare
plugin).
Note: snd_pcm_dshare_delay() is not updated.
Signed-off-by: Alan Young <consult.awy@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dshare.c | 45 ++++++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index c5b3178a4990..9b478a714468 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -157,23 +157,14 @@ static void snd_pcm_dshare_sync_area(snd_pcm_t *pcm)
/*
* synchronize hardware pointer (hw_ptr) with ours
*/
-static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
+static int snd_pcm_dshare_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr)
{
snd_pcm_direct_t *dshare = pcm->private_data;
- snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
+ snd_pcm_uframes_t old_slave_hw_ptr, avail;
snd_pcm_sframes_t diff;
- switch (snd_pcm_state(dshare->spcm)) {
- case SND_PCM_STATE_DISCONNECTED:
- dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
- return -ENODEV;
- default:
- break;
- }
- if (dshare->slowptr)
- snd_pcm_hwsync(dshare->spcm);
old_slave_hw_ptr = dshare->slave_hw_ptr;
- slave_hw_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr;
+ dshare->slave_hw_ptr = slave_hw_ptr;
diff = slave_hw_ptr - old_slave_hw_ptr;
if (diff == 0) /* fast path */
return 0;
@@ -207,6 +198,24 @@ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
return 0;
}
+static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
+{
+ snd_pcm_direct_t *dshare = pcm->private_data;
+
+ switch (snd_pcm_state(dshare->spcm)) {
+ case SND_PCM_STATE_DISCONNECTED:
+ dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
+ return -ENODEV;
+ default:
+ break;
+ }
+
+ if (dshare->slowptr)
+ snd_pcm_hwsync(dshare->spcm);
+
+ return snd_pcm_dshare_sync_ptr0(pcm, *dshare->spcm->hw.ptr);
+}
+
/*
* plugin implementation
*/
@@ -215,22 +224,24 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
{
snd_pcm_direct_t *dshare = pcm->private_data;
+ memset(status, 0, sizeof(*status));
+ snd_pcm_status(dshare->spcm, status);
+
switch (dshare->state) {
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_RUNNING:
- snd_pcm_dshare_sync_ptr(pcm);
+ snd_pcm_dshare_sync_ptr0(pcm, status->hw_ptr);
+ status->delay += snd_pcm_mmap_playback_delay(pcm)
+ + status->avail - dshare->spcm->buffer_size;
break;
default:
break;
}
- memset(status, 0, sizeof(*status));
- snd_pcm_status(dshare->spcm, status);
- status->state = snd_pcm_state(dshare->spcm);
+
status->trigger_tstamp = dshare->trigger_tstamp;
status->avail = snd_pcm_mmap_playback_avail(pcm);
status->avail_max = status->avail > dshare->avail_max ? status->avail : dshare->avail_max;
dshare->avail_max = 0;
- status->delay = snd_pcm_mmap_playback_delay(pcm);
return 0;
}
--
2.10.2

View File

@ -0,0 +1,82 @@
From 2dd78251ff0c4009b478574cca7aef2eb05c2279 Mon Sep 17 00:00:00 2001
From: Joshua Frkuska <joshua_frkuska@mentor.com>
Date: Fri, 25 Nov 2016 15:43:40 +0530
Subject: [PATCH] pcm: direct: Protect from freeing semaphore when already in
use
In the case of dshare, dsnoop, and dmix when a device is opened twice
and fails the second time, the semaphore is completely discarded. This
creates dangling semaphore data.
This patch removes the possibility for the semaphore to be destroyed during
a typical open failure by first checking if the shared memory can be destroyed
or not. If the shared memory cannot be released it means both it and the
semaphore are still in use and therefore the semaphore is just released.
Signed-off-by: Joshua Frkuska <joshua_frkuska@mentor.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dmix.c | 7 ++++---
src/pcm/pcm_dshare.c | 7 ++++---
src/pcm/pcm_dsnoop.c | 8 +++++---
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index 2714fb93c758..2fedb1c14a3b 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -1154,9 +1154,10 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_close(spcm);
if (dmix->u.dmix.shmid_sum >= 0)
shm_sum_discard(dmix);
- if (dmix->shmid >= 0)
- snd_pcm_direct_shm_discard(dmix);
- if (snd_pcm_direct_semaphore_discard(dmix) < 0)
+ if ((dmix->shmid >= 0) && (snd_pcm_direct_shm_discard(dmix))) {
+ if (snd_pcm_direct_semaphore_discard(dmix))
+ snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
+ } else
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
_err_nosem:
if (dmix) {
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index 9b478a714468..01f5eed8f97a 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -846,9 +846,10 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_direct_client_discard(dshare);
if (spcm)
snd_pcm_close(spcm);
- if (dshare->shmid >= 0)
- snd_pcm_direct_shm_discard(dshare);
- if (snd_pcm_direct_semaphore_discard(dshare) < 0)
+ if ((dshare->shmid >= 0) && (snd_pcm_direct_shm_discard(dshare))) {
+ if (snd_pcm_direct_semaphore_discard(dshare))
+ snd_pcm_direct_semaphore_final(dshare, DIRECT_IPC_SEM_CLIENT);
+ } else
snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
_err_nosem:
if (dshare) {
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
index 4efbc53d177e..1aedf3cb73d2 100644
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -719,10 +719,12 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_direct_client_discard(dsnoop);
if (spcm)
snd_pcm_close(spcm);
- if (dsnoop->shmid >= 0)
- snd_pcm_direct_shm_discard(dsnoop);
- if (snd_pcm_direct_semaphore_discard(dsnoop) < 0)
+ if ((dsnoop->shmid >= 0) && (snd_pcm_direct_shm_discard(dsnoop))) {
+ if (snd_pcm_direct_semaphore_discard(dsnoop))
+ snd_pcm_direct_semaphore_final(dsnoop, DIRECT_IPC_SEM_CLIENT);
+ } else
snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
+
_err_nosem:
if (dsnoop) {
free(dsnoop->bindings);
--
2.10.2

View File

@ -0,0 +1,30 @@
From 876563c824bdecbf771a0e7bda472b0a1c19d900 Mon Sep 17 00:00:00 2001
From: Anant Agrawal <Anant_Agrawal@mentor.com>
Date: Fri, 25 Nov 2016 16:43:34 +0530
Subject: [PATCH] pcm: dshare: Fix endless playback of buffer
On snd_pcm_drain() the slave PCM driven via plugin DSHARE is not filled with
silence. Result is endless playback of buffer content until pcm is closed.
In ALSA pcm dshare plugin, called do_silence method to fix the issue.
Signed-off-by: Anant Agrawal <Anant_Agrawal@mentor.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dshare.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index 01f5eed8f97a..29cd6c6da1d0 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -186,6 +186,7 @@ static int snd_pcm_dshare_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_p
dshare->avail_max = avail;
if (avail >= pcm->stop_threshold) {
snd_timer_stop(dshare->timer);
+ do_silence(pcm);
gettimestamp(&dshare->trigger_tstamp, pcm->tstamp_type);
if (dshare->state == SND_PCM_STATE_RUNNING) {
dshare->state = SND_PCM_STATE_XRUN;
--
2.10.2

View File

@ -0,0 +1,220 @@
From ea74ebbe4db81aeaedcff11bc5eb6ce139db1118 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 29 Nov 2016 14:31:20 +0100
Subject: [PATCH] pcm: Add the PCM state checks to plugins
I noticed that some plugin codes have no proper PCM state checks and
it results in expected outcomes. For example, when snd_pcm_drain() is
called for a dmix PCM after calling snd_pcm_drop(), it stalls
unexpectedly. It's just because its drain callback doesn't expect the
SND_PCM_SETUP state.
We can fix such a bug in each place one by one, but a safer way would
be to filter out all such cases commonly in the PCM API functions
themselves. This patch adds the PCM state sanity checks to major API
functions so that they return -EBADFD when called in the unexpected
PCM states.
As well as for the thread-safety extension, it'd be a question of the
performance; again at this time, the hw PCM is considered as an
exception, and it has pcm->own_state_check flag set, which means that
the common PCM state checks are skipped.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
src/pcm/pcm_hw.c | 1 +
src/pcm/pcm_local.h | 1 +
3 files changed, 50 insertions(+)
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index cd87bc759ded..f2ca02b55973 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -655,6 +655,23 @@ playback devices.
#include <limits.h>
#include "pcm_local.h"
+#ifndef DOC_HIDDEN
+#define P_STATE(x) (1U << SND_PCM_STATE_ ## x)
+#define P_STATE_RUNNABLE (P_STATE(PREPARED) | \
+ P_STATE(RUNNING) | \
+ P_STATE(XRUN) | \
+ P_STATE(PAUSED) | \
+ P_STATE(DRAINING))
+
+/* check whether the PCM is in the unexpected state */
+static int bad_pcm_state(snd_pcm_t *pcm, unsigned int supported_states)
+{
+ if (pcm->own_state_check)
+ return 0; /* don't care, the plugin checks by itself */
+ return !(supported_states & (1U << snd_pcm_state(pcm)));
+}
+#endif
+
/**
* \brief get identifier of PCM handle
* \param pcm PCM handle
@@ -1120,6 +1137,8 @@ int snd_pcm_prepare(snd_pcm_t *pcm)
SNDMSG("PCM not set up");
return -EIO;
}
+ if (bad_pcm_state(pcm, ~P_STATE(DISCONNECTED)))
+ return -EBADFD;
snd_pcm_lock(pcm);
err = pcm->fast_ops->prepare(pcm->fast_op_arg);
snd_pcm_unlock(pcm);
@@ -1166,6 +1185,8 @@ int snd_pcm_start(snd_pcm_t *pcm)
SNDMSG("PCM not set up");
return -EIO;
}
+ if (bad_pcm_state(pcm, P_STATE(PREPARED)))
+ return -EBADFD;
snd_pcm_lock(pcm);
err = __snd_pcm_start(pcm);
snd_pcm_unlock(pcm);
@@ -1194,6 +1215,9 @@ int snd_pcm_drop(snd_pcm_t *pcm)
SNDMSG("PCM not set up");
return -EIO;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE | P_STATE(SETUP) |
+ P_STATE(SUSPENDED)))
+ return -EBADFD;
snd_pcm_lock(pcm);
err = pcm->fast_ops->drop(pcm->fast_op_arg);
snd_pcm_unlock(pcm);
@@ -1222,6 +1246,8 @@ int snd_pcm_drain(snd_pcm_t *pcm)
SNDMSG("PCM not set up");
return -EIO;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
/* lock handled in the callback */
return pcm->fast_ops->drain(pcm->fast_op_arg);
}
@@ -1247,6 +1273,8 @@ int snd_pcm_pause(snd_pcm_t *pcm, int enable)
SNDMSG("PCM not set up");
return -EIO;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
snd_pcm_lock(pcm);
err = pcm->fast_ops->pause(pcm->fast_op_arg, enable);
snd_pcm_unlock(pcm);
@@ -1273,6 +1301,8 @@ snd_pcm_sframes_t snd_pcm_rewindable(snd_pcm_t *pcm)
SNDMSG("PCM not set up");
return -EIO;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
snd_pcm_lock(pcm);
result = pcm->fast_ops->rewindable(pcm->fast_op_arg);
snd_pcm_unlock(pcm);
@@ -1299,6 +1329,8 @@ snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
}
if (frames == 0)
return 0;
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
snd_pcm_lock(pcm);
result = pcm->fast_ops->rewind(pcm->fast_op_arg, frames);
snd_pcm_unlock(pcm);
@@ -1325,6 +1357,8 @@ snd_pcm_sframes_t snd_pcm_forwardable(snd_pcm_t *pcm)
SNDMSG("PCM not set up");
return -EIO;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
snd_pcm_lock(pcm);
result = pcm->fast_ops->forwardable(pcm->fast_op_arg);
snd_pcm_unlock(pcm);
@@ -1355,6 +1389,8 @@ snd_pcm_sframes_t snd_pcm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
}
if (frames == 0)
return 0;
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
snd_pcm_lock(pcm);
result = pcm->fast_ops->forward(pcm->fast_op_arg, frames);
snd_pcm_unlock(pcm);
@@ -1393,6 +1429,8 @@ snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_ufr
SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
return -EINVAL;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
return _snd_pcm_writei(pcm, buffer, size);
}
@@ -1427,6 +1465,8 @@ snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t
SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
return -EINVAL;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
return _snd_pcm_writen(pcm, bufs, size);
}
@@ -1461,6 +1501,8 @@ snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t
SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
return -EINVAL;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
return _snd_pcm_readi(pcm, buffer, size);
}
@@ -1495,6 +1537,8 @@ snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t s
SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
return -EINVAL;
}
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
return _snd_pcm_readn(pcm, bufs, size);
}
@@ -6938,6 +6982,8 @@ int snd_pcm_mmap_begin(snd_pcm_t *pcm,
{
int err;
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
snd_pcm_lock(pcm);
err = __snd_pcm_mmap_begin(pcm, areas, offset, frames);
snd_pcm_unlock(pcm);
@@ -7033,6 +7079,8 @@ snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm,
{
snd_pcm_sframes_t result;
+ if (bad_pcm_state(pcm, P_STATE_RUNNABLE))
+ return -EBADFD;
snd_pcm_lock(pcm);
result = __snd_pcm_mmap_commit(pcm, offset, frames);
snd_pcm_unlock(pcm);
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c
index 56e88b6bf6c0..30cd5d0f6503 100644
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -1516,6 +1516,7 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name,
#ifdef THREAD_SAFE_API
pcm->need_lock = 0; /* hw plugin is thread-safe */
#endif
+ pcm->own_state_check = 1; /* skip the common state check */
ret = snd_pcm_hw_mmap_status(pcm);
if (ret < 0) {
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index bba2f15ac463..32e6dcdf6fcd 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -234,6 +234,7 @@ struct _snd_pcm {
* use the mmaped buffer of the slave
*/
unsigned int donot_close: 1; /* don't close this PCM */
+ unsigned int own_state_check:1; /* plugin has own PCM state check */
snd_pcm_channel_info_t *mmap_channels;
snd_pcm_channel_area_t *running_areas;
snd_pcm_channel_area_t *stopped_areas;
--
2.10.2

View File

@ -0,0 +1,103 @@
From 38a2d2eda880fda9ed5a4a219db498d9c0856d71 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 29 Nov 2016 14:53:53 +0100
Subject: [PATCH] pcm: dmix: Do not discard slave reported delay in status
result
Like the change done for dshare plugin, we can calculate the delay
more precisely from the slave PCM.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dmix.c | 45 ++++++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index 2fedb1c14a3b..825677ffeb3f 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -391,23 +391,14 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
/*
* synchronize hardware pointer (hw_ptr) with ours
*/
-static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
+static int snd_pcm_dmix_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr)
{
snd_pcm_direct_t *dmix = pcm->private_data;
- snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
+ snd_pcm_uframes_t old_slave_hw_ptr, avail;
snd_pcm_sframes_t diff;
- switch (snd_pcm_state(dmix->spcm)) {
- case SND_PCM_STATE_DISCONNECTED:
- dmix->state = SND_PCM_STATE_DISCONNECTED;
- return -ENODEV;
- default:
- break;
- }
- if (dmix->slowptr)
- snd_pcm_hwsync(dmix->spcm);
old_slave_hw_ptr = dmix->slave_hw_ptr;
- slave_hw_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
+ dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
diff = slave_hw_ptr - old_slave_hw_ptr;
if (diff == 0) /* fast path */
return 0;
@@ -440,6 +431,24 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
return 0;
}
+static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
+{
+ snd_pcm_direct_t *dmix = pcm->private_data;
+
+ switch (snd_pcm_state(dmix->spcm)) {
+ case SND_PCM_STATE_DISCONNECTED:
+ dmix->state = SND_PCM_STATE_DISCONNECTED;
+ return -ENODEV;
+ default:
+ break;
+ }
+
+ if (dmix->slowptr)
+ snd_pcm_hwsync(dmix->spcm);
+
+ return snd_pcm_dmix_sync_ptr0(pcm, *dmix->spcm->hw.ptr);
+}
+
/*
* plugin implementation
*/
@@ -467,22 +476,24 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
{
snd_pcm_direct_t *dmix = pcm->private_data;
+ memset(status, 0, sizeof(*status));
+ snd_pcm_status(dmix->spcm, status);
+
switch (dmix->state) {
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_RUNNING:
- snd_pcm_dmix_sync_ptr(pcm);
+ snd_pcm_dmix_sync_ptr0(pcm, status->hw_ptr);
+ status->delay += snd_pcm_mmap_playback_delay(pcm)
+ + status->avail - dmix->spcm->buffer_size;
break;
default:
break;
}
- memset(status, 0, sizeof(*status));
- snd_pcm_status(dmix->spcm, status);
- status->state = snd_pcm_dmix_state(pcm);
+
status->trigger_tstamp = dmix->trigger_tstamp;
status->avail = snd_pcm_mmap_playback_avail(pcm);
status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
dmix->avail_max = 0;
- status->delay = snd_pcm_mmap_playback_delay(pcm);
return 0;
}
--
2.10.2

View File

@ -1,3 +1,41 @@
-------------------------------------------------------------------
Tue Nov 29 15:01:05 CET 2016 - tiwai@suse.de
- Backport upstream fixes (bsc#1012594):
- A few PCM bugs have been fixed:
* Stall of dmix and others in a wrong PCM state
* Refactoring of PCM locking scheme
* SHM initialization race fix
* plug PCM memory leaks
* Improvement of dshare/dmix delay calculation
* Fix endless dshare draining
* Fix semaphore discard race fix of direct plugins
- UCM fixes and updates for DB410c and skylake-r5286
- Mixer code cleanup not to install bogus plugin codes
- Documentation fixes / updates
0001-ucm-Add-ucm-files-for-DB410c-board.patch
0002-mixer-Fix-rounding-mode-documentation.patch
0003-pcm-Fix-shm-initialization-race-condition.patch
0004-pcm-Better-understandable-locking-code.patch
0005-ucm-fix-crash-when-calling-snd_use_case_geti-with-no.patch
0006-ucm-docs-typeset-lists-of-identifiers-explicitly.patch
0007-Update-include-sound-tlv.h-from-4.9-pre-kernel-uapi.patch
0008-test-use-actual-information-for-TLV-operation.patch
0009-ctl-improve-API-documentation-for-TLV-operation.patch
0010-ctl-improve-documentation-about-TLV-related-APIs.patch
0011-ctl-correct-documentation-about-TLV-feature.patch
0012-conf-ucm-skylake-add-skylake-rt286-conf-files.patch
0013-pcm_plug-Clear-plugins-on-all-error-conditions.patch
0014-mixer-Don-t-install-smixer-modules-unless-python-is-.patch
0015-pcm_dshare-Do-not-discard-slave-reported-delay-in-st.patch
0016-pcm-direct-Protect-from-freeing-semaphore-when-alrea.patch
0017-pcm-dshare-Fix-endless-playback-of-buffer.patch
0018-pcm-Add-the-PCM-state-checks-to-plugins.patch
0019-pcm-dmix-Do-not-discard-slave-reported-delay-in-stat.patch
- smixer module files got removed from the file list as well
-------------------------------------------------------------------
Wed Aug 3 11:22:16 CEST 2016 - tiwai@suse.de

View File

@ -48,6 +48,25 @@ Source40: 50-alsa.conf
Source41: install-snd-module
# Patch: alsa-lib-git-fixes.diff
# upstream fixes
Patch1: 0001-ucm-Add-ucm-files-for-DB410c-board.patch
Patch2: 0002-mixer-Fix-rounding-mode-documentation.patch
Patch3: 0003-pcm-Fix-shm-initialization-race-condition.patch
Patch4: 0004-pcm-Better-understandable-locking-code.patch
Patch5: 0005-ucm-fix-crash-when-calling-snd_use_case_geti-with-no.patch
Patch6: 0006-ucm-docs-typeset-lists-of-identifiers-explicitly.patch
Patch7: 0007-Update-include-sound-tlv.h-from-4.9-pre-kernel-uapi.patch
Patch8: 0008-test-use-actual-information-for-TLV-operation.patch
Patch9: 0009-ctl-improve-API-documentation-for-TLV-operation.patch
Patch10: 0010-ctl-improve-documentation-about-TLV-related-APIs.patch
Patch11: 0011-ctl-correct-documentation-about-TLV-feature.patch
Patch12: 0012-conf-ucm-skylake-add-skylake-rt286-conf-files.patch
Patch13: 0013-pcm_plug-Clear-plugins-on-all-error-conditions.patch
Patch14: 0014-mixer-Don-t-install-smixer-modules-unless-python-is-.patch
Patch15: 0015-pcm_dshare-Do-not-discard-slave-reported-delay-in-st.patch
Patch16: 0016-pcm-direct-Protect-from-freeing-semaphore-when-alrea.patch
Patch17: 0017-pcm-dshare-Fix-endless-playback-of-buffer.patch
Patch18: 0018-pcm-Add-the-PCM-state-checks-to-plugins.patch
Patch19: 0019-pcm-dmix-Do-not-discard-slave-reported-delay-in-stat.patch
# rest suse patches
Patch99: alsa-lib-doxygen-avoid-crash-for-11.3.diff
BuildRequires: doxygen
@ -116,6 +135,25 @@ Architecture.
%prep
%setup -q -n alsa-lib-%{package_version}
# %patch -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%if 0%{?suse_version} == 1130
%patch99 -p1
%endif
@ -146,7 +184,7 @@ make -C doc doc %{?_smp_mflags}
make DESTDIR=%{buildroot} install %{?_smp_mflags}
# clean up unneeded files
rm -f %{buildroot}%{_libdir}/*.*a
rm -f %{buildroot}%{_libdir}/alsa-lib/smixer/*.*a
# rm -f %{buildroot}%{_libdir}/alsa-lib/smixer/*.*a
rm -f %{buildroot}%{_bindir}/aserver
#
# install helper scripts
@ -274,7 +312,6 @@ exit 0
%files -n libasound2
%defattr(-, root, root)
%{_libdir}/libasound.so.*
%{_libdir}/alsa-lib
%{_datadir}/alsa
%changelog