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:
commit
3114405b0f
310
0001-ucm-Add-ucm-files-for-DB410c-board.patch
Normal file
310
0001-ucm-Add-ucm-files-for-DB410c-board.patch
Normal 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
|
||||
|
76
0002-mixer-Fix-rounding-mode-documentation.patch
Normal file
76
0002-mixer-Fix-rounding-mode-documentation.patch
Normal 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
|
||||
|
39
0003-pcm-Fix-shm-initialization-race-condition.patch
Normal file
39
0003-pcm-Fix-shm-initialization-race-condition.patch
Normal 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
|
||||
|
130
0004-pcm-Better-understandable-locking-code.patch
Normal file
130
0004-pcm-Better-understandable-locking-code.patch
Normal 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
|
||||
|
@ -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
|
||||
|
108
0006-ucm-docs-typeset-lists-of-identifiers-explicitly.patch
Normal file
108
0006-ucm-docs-typeset-lists-of-identifiers-explicitly.patch
Normal 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
|
||||
|
105
0007-Update-include-sound-tlv.h-from-4.9-pre-kernel-uapi.patch
Normal file
105
0007-Update-include-sound-tlv.h-from-4.9-pre-kernel-uapi.patch
Normal 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
|
||||
|
386
0008-test-use-actual-information-for-TLV-operation.patch
Normal file
386
0008-test-use-actual-information-for-TLV-operation.patch
Normal 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
|
||||
|
52
0009-ctl-improve-API-documentation-for-TLV-operation.patch
Normal file
52
0009-ctl-improve-API-documentation-for-TLV-operation.patch
Normal 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
|
||||
|
64
0010-ctl-improve-documentation-about-TLV-related-APIs.patch
Normal file
64
0010-ctl-improve-documentation-about-TLV-related-APIs.patch
Normal 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
|
||||
|
59
0011-ctl-correct-documentation-about-TLV-feature.patch
Normal file
59
0011-ctl-correct-documentation-about-TLV-feature.patch
Normal 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
|
||||
|
313
0012-conf-ucm-skylake-add-skylake-rt286-conf-files.patch
Normal file
313
0012-conf-ucm-skylake-add-skylake-rt286-conf-files.patch
Normal 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
|
||||
|
34
0013-pcm_plug-Clear-plugins-on-all-error-conditions.patch
Normal file
34
0013-pcm_plug-Clear-plugins-on-all-error-conditions.patch
Normal 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
|
||||
|
@ -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
|
||||
|
109
0015-pcm_dshare-Do-not-discard-slave-reported-delay-in-st.patch
Normal file
109
0015-pcm_dshare-Do-not-discard-slave-reported-delay-in-st.patch
Normal 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
|
||||
|
@ -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
|
||||
|
30
0017-pcm-dshare-Fix-endless-playback-of-buffer.patch
Normal file
30
0017-pcm-dshare-Fix-endless-playback-of-buffer.patch
Normal 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
|
||||
|
220
0018-pcm-Add-the-PCM-state-checks-to-plugins.patch
Normal file
220
0018-pcm-Add-the-PCM-state-checks-to-plugins.patch
Normal 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
|
||||
|
103
0019-pcm-dmix-Do-not-discard-slave-reported-delay-in-stat.patch
Normal file
103
0019-pcm-dmix-Do-not-discard-slave-reported-delay-in-stat.patch
Normal 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
|
||||
|
38
alsa.changes
38
alsa.changes
@ -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
|
||||
|
||||
|
41
alsa.spec
41
alsa.spec
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user