Accepting request 343190 from home:tiwai:branches:multimedia:libs
- Update to alsa-lib 1.1.0: including all previous fixes, with more updates for topology API, a fix for dmix/dsnoop slave PCM xrun, some build fixes / improvements. - Fix the build with old gcc on SLE11: 0001-topology-Add-missing-include-sys-stat.h.patch - Dropped patches: 0001-ucm-document-some-standard-values.patch 0002-conf-ucm-broadwell-rt286-add-ucm-config.patch 0003-conf-ucm-Add-Makefile.am-for-broadwell-rt286-ucm-con.patch 0004-ucm-reformat-snd_use_case_get-doc.patch 0005-ucm-improve-jack-configuration-documentation.patch 0006-USB-audio-Sound-Blaster-HD-iec958-is-on-device-1.patch 0007-Sync-include-sound-asound.h-with-4.1-kernel.patch 0008-conf-ucm-broadwell-rt286-change-to-use-the-correct-j.patch 0009-namehint-Fix-invalid-list-access-in-snd_device_name_.patch 0010-namehint-Fix-the-listing-without-device-number.patch 0011-namehint-Fix-bad-free-with-invalid-iface-name.patch 0012-Allow-hint-for-ctl-hwdep-timer-and-seq.patch 0013-conf-Add-hint-descriptions-to-ctl-hwdep-seq-and-time.patch 0014-conf-ucm-broadwell-rt286-change-to-set-capture-volum.patch 0015-ucm-allow-multiple-devices-in-JackHWMute.patch 0016-pcm-Remove-assert-from-snd_pcm_hw_params_slave.patch 0017-test-pcm-Fix-generated-values-with-float-PCM-format.patch 0018-test-pcm_min-Fix-error-messages.patch 0019-pcm-Don-t-assert-in-_snd_pcm_hw_params_internal.patch 0020-pcm-Fix-snd_pcm_status-for-dmix-co.patch 0021-control-Allow-cset-ing-specific-values-in-the-multi-.patch 0022-PCM-snd_pcm_xxxx_drain-maybe-blocked-after-suspend-a.patch 0023-surround41-50.conf-Use-chmap-syntax-for-better-flexi.patch OBS-URL: https://build.opensuse.org/request/show/343190 OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=190
This commit is contained in:
parent
d42c75a231
commit
e99f551749
32
0001-topology-Add-missing-include-sys-stat.h.patch
Normal file
32
0001-topology-Add-missing-include-sys-stat.h.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 3f1dba9a821b53b42001605f9a126a958804884f Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Mon, 9 Nov 2015 13:37:26 +0100
|
||||
Subject: [PATCH] topology: Add missing include sys/stat.h
|
||||
|
||||
Necessary for proper definitions of S_IRUSR & co. Otherwise it
|
||||
results in compile errors with old glibc:
|
||||
parser.c: In function 'snd_tplg_build_file':
|
||||
parser.c:262: error: 'S_IRUSR' undeclared (first use in this function)
|
||||
parser.c:262: error: (Each undeclared identifier is reported only once
|
||||
parser.c:262: error: for each function it appears in.)
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/parser.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/topology/parser.c b/src/topology/parser.c
|
||||
index 80a0ae08148b..18bb9c79f3a8 100644
|
||||
--- a/src/topology/parser.c
|
||||
+++ b/src/topology/parser.c
|
||||
@@ -16,6 +16,7 @@
|
||||
Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
*/
|
||||
|
||||
+#include <sys/stat.h>
|
||||
#include "list.h"
|
||||
#include "tplg_local.h"
|
||||
|
||||
--
|
||||
2.6.2
|
||||
|
@ -1,33 +0,0 @@
|
||||
From c56064e13556322e868c5014a7fb3d0933a97a4f Mon Sep 17 00:00:00 2001
|
||||
From: "Lu, Han" <han.lu@intel.com>
|
||||
Date: Thu, 5 Mar 2015 08:38:54 +0800
|
||||
Subject: [PATCH 01/16] ucm: document some standard values
|
||||
|
||||
add standard value JackDev, JackControl and JackHWMute for speaker
|
||||
mute control on jack insertion. These values will be applied on
|
||||
pulseaudio.
|
||||
|
||||
Signed-off-by: Lu, Han <han.lu@intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/use-case.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/include/use-case.h b/include/use-case.h
|
||||
index 697377a109e2..3728906ec83d 100644
|
||||
--- a/include/use-case.h
|
||||
+++ b/include/use-case.h
|
||||
@@ -284,6 +284,10 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
||||
* PlaybackMixerID - mixer playback ID
|
||||
* CaptureMixer - name of capture mixer
|
||||
* CaptureMixerID - mixer capture ID
|
||||
+ * JackDev - jack device name
|
||||
+ * JackControl - jack control name
|
||||
+ * JackHWMute - indicate if the HW mutes a device on jack insertion
|
||||
+ * or not.
|
||||
*/
|
||||
int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *identifier,
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,168 +0,0 @@
|
||||
From 3c263716fd5bd2d9d5308cb13dba667d138c0097 Mon Sep 17 00:00:00 2001
|
||||
From: Bard Liao <bardliao@realtek.com>
|
||||
Date: Thu, 5 Mar 2015 08:38:55 +0800
|
||||
Subject: [PATCH 02/16] conf/ucm: broadwell-rt286: add ucm config
|
||||
|
||||
The configure should apply to all Broadwell-rt286 boards from Intel,
|
||||
like Wilson Beach SDS Ultrabook.
|
||||
|
||||
Signed-off-by: Lu, Han <han.lu@intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/conf/ucm/broadwell-rt286/HiFi | 128 ++++++++++++++++++++++
|
||||
src/conf/ucm/broadwell-rt286/broadwell-rt286.conf | 8 ++
|
||||
2 files changed, 136 insertions(+)
|
||||
create mode 100644 src/conf/ucm/broadwell-rt286/HiFi
|
||||
create mode 100644 src/conf/ucm/broadwell-rt286/broadwell-rt286.conf
|
||||
|
||||
diff --git a/src/conf/ucm/broadwell-rt286/HiFi b/src/conf/ucm/broadwell-rt286/HiFi
|
||||
new file mode 100644
|
||||
index 000000000000..08f5c50db405
|
||||
--- /dev/null
|
||||
+++ b/src/conf/ucm/broadwell-rt286/HiFi
|
||||
@@ -0,0 +1,128 @@
|
||||
+# Use case Configuration for Nexus 7
|
||||
+# Adapted to Ubuntu Touch by David Henningsson <david.henningsson@canonical.com>
|
||||
+
|
||||
+SectionVerb {
|
||||
+
|
||||
+ EnableSequence [
|
||||
+ ]
|
||||
+
|
||||
+ DisableSequence [
|
||||
+ ]
|
||||
+
|
||||
+ # ALSA PCM
|
||||
+ Value {
|
||||
+ # ALSA PCM device for HiFi
|
||||
+ PlaybackPCM "hw:broadwellrt286"
|
||||
+ CapturePCM "hw:broadwellrt286"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionDevice."Headphones" {
|
||||
+ Comment "Headphones playback"
|
||||
+
|
||||
+ ConflictingDevice [
|
||||
+ "Speaker"
|
||||
+ ]
|
||||
+
|
||||
+ EnableSequence [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+ cset "name='Master Playback Volume' 30"
|
||||
+ cset "name='HPO L Switch' on"
|
||||
+ cset "name='HPO R Switch' on"
|
||||
+ cset "name='Headphone Jack Switch' on"
|
||||
+ cset "name='DAC0 Playback Volume' 100"
|
||||
+ ]
|
||||
+
|
||||
+ DisableSequence [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+ cset "name='Headphone Jack Switch' off"
|
||||
+ cset "name='HPO L Switch' off"
|
||||
+ cset "name='HPO R Switch' off"
|
||||
+ ]
|
||||
+
|
||||
+ Value {
|
||||
+ PlaybackChannels "2"
|
||||
+ JackDev "rt286-jack"
|
||||
+ JackControl "Headset Jack"
|
||||
+ JackHWMute "Speaker"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionDevice."Speaker" {
|
||||
+ Comment "Speaker playback"
|
||||
+
|
||||
+ ConflictingDevice [
|
||||
+ "Headphones"
|
||||
+ ]
|
||||
+
|
||||
+ EnableSequence [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+ cset "name='Master Playback Volume' 30"
|
||||
+ cset "name='DAC0 Playback Volume' 127"
|
||||
+ cset "name='SPO Switch' on"
|
||||
+ cset "name='Speaker Playback Switch' on"
|
||||
+ cset "name='Speaker Switch' on"
|
||||
+ ]
|
||||
+
|
||||
+ DisableSequence [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+ cset "name='Speaker Switch' off"
|
||||
+ cset "name='Speaker Playback Switch' off"
|
||||
+ cset "name='SPO Switch' 0"
|
||||
+ ]
|
||||
+
|
||||
+ Value {
|
||||
+ PlaybackChannels "2"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionDevice."Handset" {
|
||||
+ Comment "Handset Microphone"
|
||||
+
|
||||
+ ConflictingDevice [
|
||||
+ "Mainmic"
|
||||
+ ]
|
||||
+
|
||||
+ EnableSequence [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+
|
||||
+ cset "name='ADC 0 Mux' 0"
|
||||
+ cset "name='ADC0 Capture Switch' on"
|
||||
+ cset "name='ADC0 Capture Volume' 127"
|
||||
+ cset "name='AMIC Volume' 1"
|
||||
+ ]
|
||||
+
|
||||
+ DisableSequence [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+ cset "name='ADC0 Capture Switch' off"
|
||||
+ ]
|
||||
+
|
||||
+ Value {
|
||||
+ CaptureChannels "2"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionDevice."Mainmic" {
|
||||
+ Comment "Main Microphone"
|
||||
+
|
||||
+ ConflictingDevice [
|
||||
+ "Handset"
|
||||
+ ]
|
||||
+
|
||||
+ EnableSequence [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+
|
||||
+ cset "name='ADC 0 Mux' 2"
|
||||
+ cset "name='ADC0 Capture Switch' on"
|
||||
+ cset "name='ADC0 Capture Volume' 127"
|
||||
+ ]
|
||||
+
|
||||
+ DisableSequence [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+ cset "name='ADC0 Capture Switch' off"
|
||||
+ ]
|
||||
+
|
||||
+ Value {
|
||||
+ CaptureChannels "2"
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/conf/ucm/broadwell-rt286/broadwell-rt286.conf b/src/conf/ucm/broadwell-rt286/broadwell-rt286.conf
|
||||
new file mode 100644
|
||||
index 000000000000..4a176cd9a995
|
||||
--- /dev/null
|
||||
+++ b/src/conf/ucm/broadwell-rt286/broadwell-rt286.conf
|
||||
@@ -0,0 +1,8 @@
|
||||
+SectionUseCase."HiFi" {
|
||||
+ File "HiFi"
|
||||
+ Comment "Play HiFi quality Music"
|
||||
+}
|
||||
+
|
||||
+SectionDefaults [
|
||||
+ cdev "hw:broadwellrt286"
|
||||
+]
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,46 +0,0 @@
|
||||
From 9d649add08beb93728ba2943a2c05f8f160f8296 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 5 Mar 2015 11:03:56 +0100
|
||||
Subject: [PATCH 03/16] conf/ucm: Add Makefile.am for broadwell-rt286 ucm
|
||||
config
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
configure.ac | 1 +
|
||||
src/conf/ucm/Makefile.am | 2 +-
|
||||
src/conf/ucm/broadwell-rt286/Makefile.am | 4 ++++
|
||||
3 files changed, 6 insertions(+), 1 deletion(-)
|
||||
create mode 100644 src/conf/ucm/broadwell-rt286/Makefile.am
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index f0995e3ae787..9621d4e9ec2b 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -655,6 +655,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
|
||||
src/conf/ucm/tegraalc5632/Makefile \
|
||||
src/conf/ucm/PAZ00/Makefile \
|
||||
src/conf/ucm/GoogleNyan/Makefile \
|
||||
+ src/conf/ucm/broadwell-rt286/Makefile \
|
||||
modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \
|
||||
alsalisp/Makefile aserver/Makefile \
|
||||
test/Makefile test/lsb/Makefile \
|
||||
diff --git a/src/conf/ucm/Makefile.am b/src/conf/ucm/Makefile.am
|
||||
index 14fc7aee8e6c..e6a6325b5fdc 100644
|
||||
--- a/src/conf/ucm/Makefile.am
|
||||
+++ b/src/conf/ucm/Makefile.am
|
||||
@@ -1 +1 @@
|
||||
-SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan
|
||||
+SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286
|
||||
diff --git a/src/conf/ucm/broadwell-rt286/Makefile.am b/src/conf/ucm/broadwell-rt286/Makefile.am
|
||||
new file mode 100644
|
||||
index 000000000000..73861faaf7a6
|
||||
--- /dev/null
|
||||
+++ b/src/conf/ucm/broadwell-rt286/Makefile.am
|
||||
@@ -0,0 +1,4 @@
|
||||
+alsaconfigdir = @ALSA_CONFIG_DIR@
|
||||
+ucmdir = $(alsaconfigdir)/ucm/broadwell-rt286
|
||||
+ucm_DATA = broadwell-rt286.conf HiFi
|
||||
+EXTRA_DIST = $(ucm_DATA)
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,154 +0,0 @@
|
||||
From 72aa0f8332fb945c4179450f65402ce1cb389594 Mon Sep 17 00:00:00 2001
|
||||
From: Tanu Kaskinen <tanu.kaskinen@linux.intel.com>
|
||||
Date: Thu, 5 Mar 2015 14:51:57 +0200
|
||||
Subject: [PATCH 04/16] ucm: reformat snd_use_case_get() doc
|
||||
|
||||
Doxygen doesn't preserve formatting that relies only on indentation.
|
||||
This fixes it by using lists more liberally.
|
||||
|
||||
There are probably more places to fix than just
|
||||
snd_use_case_get_list(), but I only have motivation for fixing this
|
||||
function's documentation formatting (the next patch will add some more
|
||||
content to the function's documentation).
|
||||
|
||||
Signed-off-by: Tanu Kaskinen <tanu.kaskinen@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/use-case.h | 111 +++++++++++++++++++++++++++++++----------------------
|
||||
1 file changed, 65 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/include/use-case.h b/include/use-case.h
|
||||
index 3728906ec83d..d30952245fde 100644
|
||||
--- a/include/use-case.h
|
||||
+++ b/include/use-case.h
|
||||
@@ -229,10 +229,10 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
||||
* "const", but it's too late to fix it, sorry about that.)
|
||||
*
|
||||
* Known identifiers:
|
||||
- * NULL - return current card
|
||||
- * _verb - return current verb
|
||||
+ * - NULL - return current card
|
||||
+ * - _verb - return current verb
|
||||
*
|
||||
- * [=]{NAME}[/[{modifier}|{/device}][/{verb}]]
|
||||
+ * - [=]{NAME}[/[{modifier}|{/device}][/{verb}]]
|
||||
* - value identifier {NAME}
|
||||
* - Search starts at given modifier or device if any,
|
||||
* else at a verb
|
||||
@@ -243,51 +243,70 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
||||
* device/modifier/verb specified, and not search
|
||||
* through each object in turn.
|
||||
* - Examples:
|
||||
- * "PlaybackPCM/Play Music"
|
||||
- * "CapturePCM/SPDIF"
|
||||
- * From ValueDefaults only:
|
||||
- * "=Variable"
|
||||
- * From current active verb:
|
||||
- * "=Variable//"
|
||||
- * From verb "Verb":
|
||||
- * "=Variable//Verb"
|
||||
- * From "Modifier" in current active verb:
|
||||
- * "=Variable/Modifier/"
|
||||
- * From "Modifier" in "Verb":
|
||||
- * "=Variable/Modifier/Verb"
|
||||
+ * - "PlaybackPCM/Play Music"
|
||||
+ * - "CapturePCM/SPDIF"
|
||||
+ * - From ValueDefaults only:
|
||||
+ * "=Variable"
|
||||
+ * - From current active verb:
|
||||
+ * "=Variable//"
|
||||
+ * - From verb "Verb":
|
||||
+ * "=Variable//Verb"
|
||||
+ * - From "Modifier" in current active verb:
|
||||
+ * "=Variable/Modifier/"
|
||||
+ * - From "Modifier" in "Verb":
|
||||
+ * "=Variable/Modifier/Verb"
|
||||
*
|
||||
* Recommended names for values:
|
||||
- * TQ - Tone Quality
|
||||
- * PlaybackPCM - full PCM playback device name
|
||||
- * PlaybackPCMIsDummy - Valid values: "yes" and "no". If set to "yes", the
|
||||
- * PCM named by the PlaybackPCM value is a dummy device,
|
||||
- * meaning that opening it enables an audio path in the
|
||||
- * hardware, but writing to the PCM device has no
|
||||
- * effect.
|
||||
- * CapturePCM - full PCM capture device name
|
||||
- * CapturePCMIsDummy - Valid values: "yes" and "no". If set to "yes", the
|
||||
- * PCM named by the CapturePCM value is a dummy device,
|
||||
- * meaning that opening it enables an audio path in the
|
||||
- * hardware, but reading from the PCM device has no
|
||||
- * effect.
|
||||
- * PlaybackRate - playback device sample rate
|
||||
- * PlaybackChannels - playback device channel count
|
||||
- * PlaybackCTL - playback control device name
|
||||
- * PlaybackVolume - playback control volume ID string
|
||||
- * PlaybackSwitch - playback control switch ID string
|
||||
- * CaptureRate - capture device sample rate
|
||||
- * CaptureChannels - capture device channel count
|
||||
- * CaptureCTL - capture control device name
|
||||
- * CaptureVolume - capture control volume ID string
|
||||
- * CaptureSwitch - capture control switch ID string
|
||||
- * PlaybackMixer - name of playback mixer
|
||||
- * PlaybackMixerID - mixer playback ID
|
||||
- * CaptureMixer - name of capture mixer
|
||||
- * CaptureMixerID - mixer capture ID
|
||||
- * JackDev - jack device name
|
||||
- * JackControl - jack control name
|
||||
- * JackHWMute - indicate if the HW mutes a device on jack insertion
|
||||
- * or not.
|
||||
+ * - TQ
|
||||
+ * - Tone Quality
|
||||
+ * - PlaybackPCM
|
||||
+ * - full PCM playback device name
|
||||
+ * - PlaybackPCMIsDummy
|
||||
+ * - Valid values: "yes" and "no". If set to "yes", the PCM named by the
|
||||
+ * PlaybackPCM value is a dummy device, meaning that opening it enables
|
||||
+ * an audio path in the hardware, but writing to the PCM device has no
|
||||
+ * effect.
|
||||
+ * - CapturePCM
|
||||
+ * - full PCM capture device name
|
||||
+ * - CapturePCMIsDummy
|
||||
+ * - Valid values: "yes" and "no". If set to "yes", the PCM named by the
|
||||
+ * CapturePCM value is a dummy device, meaning that opening it enables
|
||||
+ * an audio path in the hardware, but reading from the PCM device has no
|
||||
+ * effect.
|
||||
+ * - PlaybackRate
|
||||
+ * - playback device sample rate
|
||||
+ * - PlaybackChannels
|
||||
+ * - playback device channel count
|
||||
+ * - PlaybackCTL
|
||||
+ * - playback control device name
|
||||
+ * - PlaybackVolume
|
||||
+ * - playback control volume ID string
|
||||
+ * - PlaybackSwitch
|
||||
+ * - playback control switch ID string
|
||||
+ * - CaptureRate
|
||||
+ * - capture device sample rate
|
||||
+ * - CaptureChannels
|
||||
+ * - capture device channel count
|
||||
+ * - CaptureCTL
|
||||
+ * - capture control device name
|
||||
+ * - CaptureVolume
|
||||
+ * - capture control volume ID string
|
||||
+ * - CaptureSwitch
|
||||
+ * - capture control switch ID string
|
||||
+ * - PlaybackMixer
|
||||
+ * - name of playback mixer
|
||||
+ * - PlaybackMixerID
|
||||
+ * - mixer playback ID
|
||||
+ * - CaptureMixer
|
||||
+ * - name of capture mixer
|
||||
+ * - CaptureMixerID
|
||||
+ * - mixer capture ID
|
||||
+ * - JackDev
|
||||
+ * - jack device name
|
||||
+ * - JackControl
|
||||
+ * - jack control name
|
||||
+ * - JackHWMute
|
||||
+ * - indicate if the HW mutes a device on jack insertion or not.
|
||||
*/
|
||||
int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *identifier,
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,49 +0,0 @@
|
||||
From ecb38d2bec72a9fbb171e2e89816301d3451c8d3 Mon Sep 17 00:00:00 2001
|
||||
From: Tanu Kaskinen <tanu.kaskinen@linux.intel.com>
|
||||
Date: Thu, 5 Mar 2015 14:51:58 +0200
|
||||
Subject: [PATCH 05/16] ucm: improve jack configuration documentation
|
||||
|
||||
Signed-off-by: Tanu Kaskinen <tanu.kaskinen@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/use-case.h | 24 ++++++++++++++++++------
|
||||
1 file changed, 18 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/include/use-case.h b/include/use-case.h
|
||||
index d30952245fde..e3308b17b105 100644
|
||||
--- a/include/use-case.h
|
||||
+++ b/include/use-case.h
|
||||
@@ -301,12 +301,24 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
||||
* - name of capture mixer
|
||||
* - CaptureMixerID
|
||||
* - mixer capture ID
|
||||
- * - JackDev
|
||||
- * - jack device name
|
||||
- * - JackControl
|
||||
- * - jack control name
|
||||
- * - JackHWMute
|
||||
- * - indicate if the HW mutes a device on jack insertion or not.
|
||||
+ * - JackControl, JackDev, JackHWMute
|
||||
+ * - Jack information for a device. The jack status can be reported via
|
||||
+ * a kcontrol and/or via an input device. **JackControl** is the
|
||||
+ * kcontrol name of the jack, and **JackDev** is the input device id of
|
||||
+ * the jack (if the full input device path is /dev/input/by-id/foo, the
|
||||
+ * JackDev value should be "foo"). UCM configuration files should
|
||||
+ * contain both JackControl and JackDev when possible, because
|
||||
+ * applications are likely to support only one or the other.
|
||||
+ *
|
||||
+ * If **JackHWMute** is set, it indicates that when the jack is plugged
|
||||
+ * in, the hardware automatically mutes some other device. The
|
||||
+ * JackHWMute value is the name of the muted device. Note that
|
||||
+ * JackHWMute should be used only when the hardware enforces the
|
||||
+ * automatic muting. If the hardware doesn't enforce any muting, it may
|
||||
+ * still be tempting to set JackHWMute to trick upper software layers to
|
||||
+ * e.g. automatically mute speakers when headphones are plugged in, but
|
||||
+ * that's application policy configuration that doesn't belong to UCM
|
||||
+ * configuration files.
|
||||
*/
|
||||
int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *identifier,
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,31 +0,0 @@
|
||||
From c39d0834d5ad5ca3f2882457f2d4a14e678bfe76 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Richard=20K=C3=B6rber?= <dev@shredzone.de>
|
||||
Date: Wed, 21 Jan 2015 22:50:27 +0100
|
||||
Subject: [PATCH 06/16] USB-audio: Sound Blaster HD iec958 is on device 1
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Creative Sound Blaster X-Fi HD uses device 1 for iec958 output.
|
||||
|
||||
Signed-off-by: Richard Körber <dev@shredzone.de>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/conf/cards/USB-Audio.conf | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf
|
||||
index 4cbf85e7a17b..031bee0d86fd 100644
|
||||
--- a/src/conf/cards/USB-Audio.conf
|
||||
+++ b/src/conf/cards/USB-Audio.conf
|
||||
@@ -37,6 +37,7 @@ USB-Audio.pcm.surround40_type {
|
||||
# number for the iec958 device can be changed here.
|
||||
USB-Audio.pcm.iec958_device {
|
||||
# "NoiseBlaster 3000" 42
|
||||
+ "USB Sound Blaster HD" 1
|
||||
|
||||
# The below don't have digital in/out, so prevent them from being opened.
|
||||
"Andrea PureAudio USB-SA Headset" 999
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,112 +0,0 @@
|
||||
From b07de7c26b147a19621e35b33fa772de575fa2b8 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 21 Apr 2015 12:49:29 +0200
|
||||
Subject: [PATCH 07/16] Sync include/sound/asound.h with 4.1 kernel
|
||||
|
||||
This adds the new ABI for timestamp stuff and minor fixes.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/sound/asound.h | 42 ++++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 36 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/include/sound/asound.h b/include/sound/asound.h
|
||||
index 1f23cd635957..a45be6bdcf5b 100644
|
||||
--- a/include/sound/asound.h
|
||||
+++ b/include/sound/asound.h
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
+#ifndef __KERNEL__
|
||||
+#include <stdlib.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* protocol version
|
||||
@@ -140,7 +143,7 @@ struct snd_hwdep_dsp_image {
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 12)
|
||||
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 13)
|
||||
|
||||
typedef unsigned long snd_pcm_uframes_t;
|
||||
typedef signed long snd_pcm_sframes_t;
|
||||
@@ -267,9 +270,17 @@ typedef int __bitwise snd_pcm_subformat_t;
|
||||
#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
|
||||
#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
|
||||
#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
|
||||
-#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* has audio wall clock for audio/system time sync */
|
||||
+#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */
|
||||
+#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */
|
||||
+#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */
|
||||
+#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */
|
||||
+#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */
|
||||
+
|
||||
+#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
|
||||
#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
|
||||
|
||||
+
|
||||
+
|
||||
typedef int __bitwise snd_pcm_state_t;
|
||||
#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
|
||||
#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
|
||||
@@ -407,6 +418,22 @@ struct snd_pcm_channel_info {
|
||||
unsigned int step; /* samples distance in bits */
|
||||
};
|
||||
|
||||
+enum {
|
||||
+ /*
|
||||
+ * first definition for backwards compatibility only,
|
||||
+ * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else
|
||||
+ */
|
||||
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0,
|
||||
+
|
||||
+ /* timestamp definitions */
|
||||
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */
|
||||
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */
|
||||
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */
|
||||
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */
|
||||
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */
|
||||
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
|
||||
+};
|
||||
+
|
||||
struct snd_pcm_status {
|
||||
snd_pcm_state_t state; /* stream state */
|
||||
struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
|
||||
@@ -418,9 +445,11 @@ struct snd_pcm_status {
|
||||
snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
|
||||
snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
|
||||
snd_pcm_state_t suspended_state; /* suspended stream state */
|
||||
- __u32 reserved_alignment; /* must be filled with zero */
|
||||
- struct timespec audio_tstamp; /* from sample counter or wall clock */
|
||||
- unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */
|
||||
+ __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
|
||||
+ struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */
|
||||
+ struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */
|
||||
+ __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
|
||||
+ unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
|
||||
};
|
||||
|
||||
struct snd_pcm_mmap_status {
|
||||
@@ -533,6 +562,7 @@ enum {
|
||||
#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
|
||||
#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
|
||||
#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
|
||||
+#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status)
|
||||
#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
|
||||
#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
|
||||
#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
|
||||
@@ -834,7 +864,7 @@ struct snd_ctl_elem_id {
|
||||
snd_ctl_elem_iface_t iface; /* interface identifier */
|
||||
unsigned int device; /* device/client number */
|
||||
unsigned int subdevice; /* subdevice (substream) number */
|
||||
- unsigned char name[44]; /* ASCII name of item */
|
||||
+ unsigned char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* ASCII name of item */
|
||||
unsigned int index; /* index of item */
|
||||
};
|
||||
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,32 +0,0 @@
|
||||
From ba6fa7b5a6a34da98e05df395f70bba3e2993497 Mon Sep 17 00:00:00 2001
|
||||
From: Jie Yang <yang.jie@intel.com>
|
||||
Date: Tue, 28 Apr 2015 15:40:22 +0800
|
||||
Subject: [PATCH 08/16] conf/ucm: broadwell-rt286: change to use the correct
|
||||
jack kcontrol name
|
||||
|
||||
The headset jack has two kctls: "Headphone Jack" and "Mic Jack",
|
||||
we need switch speaker output according to the former JackControl.
|
||||
Here correct it.
|
||||
|
||||
Signed-off-by: Jie Yang <yang.jie@intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/conf/ucm/broadwell-rt286/HiFi | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/conf/ucm/broadwell-rt286/HiFi b/src/conf/ucm/broadwell-rt286/HiFi
|
||||
index 08f5c50db405..58983ea5763c 100644
|
||||
--- a/src/conf/ucm/broadwell-rt286/HiFi
|
||||
+++ b/src/conf/ucm/broadwell-rt286/HiFi
|
||||
@@ -43,7 +43,7 @@ SectionDevice."Headphones" {
|
||||
Value {
|
||||
PlaybackChannels "2"
|
||||
JackDev "rt286-jack"
|
||||
- JackControl "Headset Jack"
|
||||
+ JackControl "Headphone Jack"
|
||||
JackHWMute "Speaker"
|
||||
}
|
||||
}
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,67 +0,0 @@
|
||||
From bf98b4e3166c28343429119135644ba70c6e5277 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 30 Apr 2015 12:26:43 +0200
|
||||
Subject: [PATCH 09/16] namehint: Fix invalid list access in
|
||||
snd_device_name_hint()
|
||||
|
||||
snd_device_name_hint() tries to free the allocated list at the error
|
||||
path via snd_device_name_free_hint(). But snd_device_name_free_hint()
|
||||
expects a list terminated by NULL while snd_device_name_hint() doesn't
|
||||
add it. Adding it may again result in an error and thus isn't
|
||||
guaranteed to work. Hence we can't add NULL at the error path.
|
||||
|
||||
Instead, now the code always allocates one entry more, and zero-clears
|
||||
the newly allocated beforehand to guarantee the NULL termination.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/control/namehint.c | 21 ++++++++++-----------
|
||||
1 file changed, 10 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/control/namehint.c b/src/control/namehint.c
|
||||
index 28975a400b75..66de634d3550 100644
|
||||
--- a/src/control/namehint.c
|
||||
+++ b/src/control/namehint.c
|
||||
@@ -52,10 +52,11 @@ static int hint_list_add(struct hint_list *list,
|
||||
{
|
||||
char *x;
|
||||
|
||||
- if (list->count == list->allocated) {
|
||||
+ if (list->count + 1 >= list->allocated) {
|
||||
char **n = realloc(list->list, (list->allocated + 10) * sizeof(char *));
|
||||
if (n == NULL)
|
||||
return -ENOMEM;
|
||||
+ memset(n + list->allocated, 0, 10 * sizeof(*n));
|
||||
list->allocated += 10;
|
||||
list->list = n;
|
||||
}
|
||||
@@ -620,18 +621,16 @@ int snd_device_name_hint(int card, const char *iface, void ***hints)
|
||||
}
|
||||
err = 0;
|
||||
__error:
|
||||
- if (err < 0) {
|
||||
+ /* add an empty entry if nothing has been added yet; the caller
|
||||
+ * expects non-NULL return
|
||||
+ */
|
||||
+ if (!err && !list.list)
|
||||
+ err = hint_list_add(&list, NULL, NULL);
|
||||
+ if (err < 0)
|
||||
snd_device_name_free_hint((void **)list.list);
|
||||
- if (list.cardname)
|
||||
- free(list.cardname);
|
||||
- } else {
|
||||
- err = hint_list_add(&list, NULL, NULL);
|
||||
- if (err < 0)
|
||||
- goto __error;
|
||||
+ else
|
||||
*hints = (void **)list.list;
|
||||
- if (list.cardname)
|
||||
- free(list.cardname);
|
||||
- }
|
||||
+ free(list.cardname);
|
||||
if (local_config_rw)
|
||||
snd_config_delete(local_config_rw);
|
||||
if (local_config)
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,33 +0,0 @@
|
||||
From c8667e3db4a47b0379562341317f3e868a7b2d51 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 30 Apr 2015 14:32:49 +0200
|
||||
Subject: [PATCH 10/16] namehint: Fix the listing without device number
|
||||
|
||||
The current code of snd_device_name_hint() has a bug when listing up
|
||||
devices without the device index (e.g. ctl). Because it assigns the
|
||||
default device index 0 unconditionally and it has a check at the later
|
||||
point to filter entries with dev >= 0, it ended up with empty
|
||||
outputs.
|
||||
|
||||
The fix is simply to remove the bogus assignment of dev = 0.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/control/namehint.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/src/control/namehint.c b/src/control/namehint.c
|
||||
index 66de634d3550..6c04143a185c 100644
|
||||
--- a/src/control/namehint.c
|
||||
+++ b/src/control/namehint.c
|
||||
@@ -272,7 +272,6 @@ static int try_config(snd_config_t *config,
|
||||
if (snd_config_search(cfg1, "type", &cfg) >= 0 &&
|
||||
snd_config_get_string(cfg, &str) >= 0 &&
|
||||
strcmp(str, "hw") == 0) {
|
||||
- dev = 0;
|
||||
list->device_input = -1;
|
||||
list->device_output = -1;
|
||||
if (snd_config_search(cfg1, "device", &cfg) >= 0) {
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,39 +0,0 @@
|
||||
From 46d98392d0f832e46693c8c06b4927a5eb6f4b28 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 30 Apr 2015 14:38:25 +0200
|
||||
Subject: [PATCH 11/16] namehint: Fix bad free with invalid iface name
|
||||
|
||||
Due to the uninitialized field before the error path, passing an
|
||||
invalid iface argument may result in a bad free() call. Initialize
|
||||
the fields properly beforehand.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/control/namehint.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/control/namehint.c b/src/control/namehint.c
|
||||
index 6c04143a185c..b3e646eb10af 100644
|
||||
--- a/src/control/namehint.c
|
||||
+++ b/src/control/namehint.c
|
||||
@@ -562,6 +562,8 @@ int snd_device_name_hint(int card, const char *iface, void ***hints)
|
||||
list.list = NULL;
|
||||
list.count = list.allocated = 0;
|
||||
list.siface = iface;
|
||||
+ list.show_all = 0;
|
||||
+ list.cardname = NULL;
|
||||
if (strcmp(iface, "card") == 0)
|
||||
list.iface = SND_CTL_ELEM_IFACE_CARD;
|
||||
else if (strcmp(iface, "pcm") == 0)
|
||||
@@ -581,8 +583,6 @@ int snd_device_name_hint(int card, const char *iface, void ***hints)
|
||||
goto __error;
|
||||
}
|
||||
|
||||
- list.show_all = 0;
|
||||
- list.cardname = NULL;
|
||||
if (snd_config_search(local_config, "defaults.namehint.showall", &conf) >= 0)
|
||||
list.show_all = snd_config_get_bool(conf) > 0;
|
||||
if (card >= 0) {
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,245 +0,0 @@
|
||||
From 7d9972c6ad154bc55ccecb555ec84c01a694a050 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 30 Apr 2015 14:52:35 +0200
|
||||
Subject: [PATCH 12/16] Allow hint for ctl, hwdep, timer and seq
|
||||
|
||||
Like pcm and rawmidi, each object parser needs to accept the hint
|
||||
component. Now a new local function _snd_conf_generic_id() was
|
||||
introduced to replace each call of "comment" and "type" field checks.
|
||||
|
||||
Also, the two existing identical functions for pcm and rawmidi are
|
||||
removed and the new function is used commonly.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/local.h | 2 ++
|
||||
src/confmisc.c | 13 +++++++++++++
|
||||
src/control/control_hw.c | 4 +---
|
||||
src/control/control_shm.c | 7 ++-----
|
||||
src/hwdep/hwdep_hw.c | 4 +---
|
||||
src/pcm/pcm.c | 12 ------------
|
||||
src/pcm/pcm_local.h | 5 ++---
|
||||
src/rawmidi/rawmidi.c | 18 ------------------
|
||||
src/rawmidi/rawmidi_local.h | 2 +-
|
||||
src/seq/seq_hw.c | 4 +---
|
||||
src/timer/timer_hw.c | 4 +---
|
||||
src/timer/timer_query_hw.c | 4 +---
|
||||
12 files changed, 25 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/include/local.h b/include/local.h
|
||||
index 2fe9a273f0b0..660081638a1c 100644
|
||||
--- a/include/local.h
|
||||
+++ b/include/local.h
|
||||
@@ -348,4 +348,6 @@ int snd_config_search_alias_hooks(snd_config_t *config,
|
||||
const char *base, const char *key,
|
||||
snd_config_t **result);
|
||||
|
||||
+int _snd_conf_generic_id(const char *id);
|
||||
+
|
||||
#endif
|
||||
diff --git a/src/confmisc.c b/src/confmisc.c
|
||||
index af686bea323c..1fb4f282217e 100644
|
||||
--- a/src/confmisc.c
|
||||
+++ b/src/confmisc.c
|
||||
@@ -1302,3 +1302,16 @@ int snd_func_refer(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
|
||||
#ifndef DOC_HIDDEN
|
||||
SND_DLSYM_BUILD_VERSION(snd_func_refer, SND_CONFIG_DLSYM_VERSION_EVALUATE);
|
||||
#endif
|
||||
+
|
||||
+#ifndef DOC_HIDDEN
|
||||
+int _snd_conf_generic_id(const char *id)
|
||||
+{
|
||||
+ static const char ids[3][8] = { "comment", "type", "hint" };
|
||||
+ unsigned int k;
|
||||
+ for (k = 0; k < sizeof(ids) / sizeof(ids[0]); ++k) {
|
||||
+ if (strcmp(id, ids[k]) == 0)
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
diff --git a/src/control/control_hw.c b/src/control/control_hw.c
|
||||
index dfc9dcd51e20..7d23151c7d75 100644
|
||||
--- a/src/control/control_hw.c
|
||||
+++ b/src/control/control_hw.c
|
||||
@@ -446,9 +446,7 @@ int _snd_ctl_hw_open(snd_ctl_t **handlep, char *name, snd_config_t *root ATTRIBU
|
||||
const char *id;
|
||||
if (snd_config_get_id(n, &id) < 0)
|
||||
continue;
|
||||
- if (strcmp(id, "comment") == 0)
|
||||
- continue;
|
||||
- if (strcmp(id, "type") == 0)
|
||||
+ if (_snd_conf_generic_id(id))
|
||||
continue;
|
||||
if (strcmp(id, "card") == 0) {
|
||||
err = snd_config_get_integer(n, &card);
|
||||
diff --git a/src/control/control_shm.c b/src/control/control_shm.c
|
||||
index 40bc705d8036..bd07d4af503a 100644
|
||||
--- a/src/control/control_shm.c
|
||||
+++ b/src/control/control_shm.c
|
||||
@@ -551,10 +551,7 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd_c
|
||||
const char *id;
|
||||
if (snd_config_get_id(n, &id) < 0)
|
||||
continue;
|
||||
- if (strcmp(id, "comment") == 0)
|
||||
- continue;
|
||||
- if (strcmp(id, "type") == 0)
|
||||
- continue;
|
||||
+ if (_snd_conf_generic_id(id))
|
||||
if (strcmp(id, "server") == 0) {
|
||||
err = snd_config_get_string(n, &server);
|
||||
if (err < 0) {
|
||||
@@ -597,7 +594,7 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd_c
|
||||
const char *id;
|
||||
if (snd_config_get_id(n, &id) < 0)
|
||||
continue;
|
||||
- if (strcmp(id, "comment") == 0)
|
||||
+ if (_snd_conf_generic_id(id))
|
||||
continue;
|
||||
if (strcmp(id, "host") == 0)
|
||||
continue;
|
||||
diff --git a/src/hwdep/hwdep_hw.c b/src/hwdep/hwdep_hw.c
|
||||
index 4314e32bade6..12528c55bac7 100644
|
||||
--- a/src/hwdep/hwdep_hw.c
|
||||
+++ b/src/hwdep/hwdep_hw.c
|
||||
@@ -158,9 +158,7 @@ int _snd_hwdep_hw_open(snd_hwdep_t **hwdep, char *name,
|
||||
const char *id;
|
||||
if (snd_config_get_id(n, &id) < 0)
|
||||
continue;
|
||||
- if (strcmp(id, "comment") == 0)
|
||||
- continue;
|
||||
- if (strcmp(id, "type") == 0)
|
||||
+ if (_snd_conf_generic_id(id))
|
||||
continue;
|
||||
if (strcmp(id, "card") == 0) {
|
||||
err = snd_config_get_integer(n, &card);
|
||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
||||
index e74e02fc568f..bc18954b92da 100644
|
||||
--- a/src/pcm/pcm.c
|
||||
+++ b/src/pcm/pcm.c
|
||||
@@ -7059,18 +7059,6 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
|
||||
return err;
|
||||
}
|
||||
|
||||
-
|
||||
-int snd_pcm_conf_generic_id(const char *id)
|
||||
-{
|
||||
- static const char ids[3][8] = { "comment", "type", "hint" };
|
||||
- unsigned int k;
|
||||
- for (k = 0; k < sizeof(ids) / sizeof(ids[0]); ++k) {
|
||||
- if (strcmp(id, ids[k]) == 0)
|
||||
- return 1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void snd_pcm_set_ptr(snd_pcm_t *pcm, snd_pcm_rbptr_t *rbptr,
|
||||
volatile snd_pcm_uframes_t *hw_ptr, int fd, off_t offset)
|
||||
{
|
||||
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
|
||||
index 394505f978ac..326618ecd0c0 100644
|
||||
--- a/src/pcm/pcm_local.h
|
||||
+++ b/src/pcm/pcm_local.h
|
||||
@@ -262,8 +262,6 @@ struct _snd_pcm {
|
||||
snd1_pcm_areas_from_bufs
|
||||
#define snd_pcm_open_named_slave \
|
||||
snd1_pcm_open_named_slave
|
||||
-#define snd_pcm_conf_generic_id \
|
||||
- snd1_pcm_conf_generic_id
|
||||
#define snd_pcm_hw_open_fd \
|
||||
snd1_pcm_hw_open_fd
|
||||
#define snd_pcm_wait_nocheck \
|
||||
@@ -882,7 +880,8 @@ snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
|
||||
return snd_pcm_open_named_slave(pcmp, NULL, root, conf, stream,
|
||||
mode, parent_conf);
|
||||
}
|
||||
-int snd_pcm_conf_generic_id(const char *id);
|
||||
+
|
||||
+#define snd_pcm_conf_generic_id(id) _snd_conf_generic_id(id)
|
||||
|
||||
int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, int mmap_emulation, int sync_ptr_ioctl);
|
||||
int __snd_pcm_mmap_emul_open(snd_pcm_t **pcmp, const char *name,
|
||||
diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c
|
||||
index ac699b439b11..0c89b8b984b9 100644
|
||||
--- a/src/rawmidi/rawmidi.c
|
||||
+++ b/src/rawmidi/rawmidi.c
|
||||
@@ -990,21 +990,3 @@ ssize_t snd_rawmidi_read(snd_rawmidi_t *rawmidi, void *buffer, size_t size)
|
||||
assert(buffer || size == 0);
|
||||
return (rawmidi->ops->read)(rawmidi, buffer, size);
|
||||
}
|
||||
-
|
||||
-#ifndef DOC_HIDDEN
|
||||
-int snd_rawmidi_conf_generic_id(const char *id)
|
||||
-{
|
||||
- static const char ids[][8] = {
|
||||
- "comment",
|
||||
- "type",
|
||||
- "hint",
|
||||
- };
|
||||
- unsigned int k;
|
||||
-
|
||||
- for (k = 0; k < sizeof ids / sizeof *ids; ++k) {
|
||||
- if (strcmp(id, ids[k]) == 0)
|
||||
- return 1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-#endif
|
||||
diff --git a/src/rawmidi/rawmidi_local.h b/src/rawmidi/rawmidi_local.h
|
||||
index 3388502cece0..8992771eb5d3 100644
|
||||
--- a/src/rawmidi/rawmidi_local.h
|
||||
+++ b/src/rawmidi/rawmidi_local.h
|
||||
@@ -58,4 +58,4 @@ int snd_rawmidi_virtual_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
|
||||
const char *name, snd_seq_t *seq_handle, int port,
|
||||
int merge, int mode);
|
||||
|
||||
-int snd_rawmidi_conf_generic_id(const char *id);
|
||||
+#define snd_rawmidi_conf_generic_id(id) _snd_conf_generic_id(id)
|
||||
diff --git a/src/seq/seq_hw.c b/src/seq/seq_hw.c
|
||||
index 6cb31d6f4c25..d03336738944 100644
|
||||
--- a/src/seq/seq_hw.c
|
||||
+++ b/src/seq/seq_hw.c
|
||||
@@ -546,9 +546,7 @@ int _snd_seq_hw_open(snd_seq_t **handlep, char *name,
|
||||
const char *id;
|
||||
if (snd_config_get_id(n, &id) < 0)
|
||||
continue;
|
||||
- if (strcmp(id, "comment") == 0)
|
||||
- continue;
|
||||
- if (strcmp(id, "type") == 0)
|
||||
+ if (_snd_conf_generic_id(id))
|
||||
continue;
|
||||
return -EINVAL;
|
||||
}
|
||||
diff --git a/src/timer/timer_hw.c b/src/timer/timer_hw.c
|
||||
index aa6a0b1b42f1..e833fc8cbb41 100644
|
||||
--- a/src/timer/timer_hw.c
|
||||
+++ b/src/timer/timer_hw.c
|
||||
@@ -299,9 +299,7 @@ int _snd_timer_hw_open(snd_timer_t **timer, char *name,
|
||||
const char *id;
|
||||
if (snd_config_get_id(n, &id) < 0)
|
||||
continue;
|
||||
- if (strcmp(id, "comment") == 0)
|
||||
- continue;
|
||||
- if (strcmp(id, "type") == 0)
|
||||
+ if (_snd_conf_generic_id(id))
|
||||
continue;
|
||||
if (strcmp(id, "class") == 0) {
|
||||
err = snd_config_get_integer(n, &dev_class);
|
||||
diff --git a/src/timer/timer_query_hw.c b/src/timer/timer_query_hw.c
|
||||
index 9f62b78aeb2e..289ca52f2afa 100644
|
||||
--- a/src/timer/timer_query_hw.c
|
||||
+++ b/src/timer/timer_query_hw.c
|
||||
@@ -134,9 +134,7 @@ int _snd_timer_query_hw_open(snd_timer_query_t **timer, char *name,
|
||||
const char *id;
|
||||
if (snd_config_get_id(n, &id) < 0)
|
||||
continue;
|
||||
- if (strcmp(id, "comment") == 0)
|
||||
- continue;
|
||||
- if (strcmp(id, "type") == 0)
|
||||
+ if (_snd_conf_generic_id(id))
|
||||
continue;
|
||||
SNDERR("Unexpected field %s", id);
|
||||
return -EINVAL;
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,87 +0,0 @@
|
||||
From 434f2f021f00045abcf79c9048b808c5dccfc930 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 30 Apr 2015 15:02:04 +0200
|
||||
Subject: [PATCH 13/16] conf: Add hint descriptions to ctl, hwdep, seq and
|
||||
timer devices
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/conf/alsa.conf | 15 ++++++++++++++-
|
||||
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf
|
||||
index 5c928e8afbcd..f22918fbbf83 100644
|
||||
--- a/src/conf/alsa.conf
|
||||
+++ b/src/conf/alsa.conf
|
||||
@@ -345,6 +345,7 @@ ctl.sysdefault {
|
||||
name defaults.ctl.card
|
||||
}
|
||||
}
|
||||
+ hint.description "Default control device"
|
||||
}
|
||||
ctl.default ctl.sysdefault
|
||||
|
||||
@@ -366,6 +367,7 @@ ctl.hw {
|
||||
}
|
||||
type hw
|
||||
card $CARD
|
||||
+ hint.description "Direct control device"
|
||||
}
|
||||
|
||||
ctl.shm {
|
||||
@@ -408,6 +410,7 @@ rawmidi.default {
|
||||
name defaults.rawmidi.device
|
||||
}
|
||||
}
|
||||
+ hint.description "Default raw MIDI device"
|
||||
}
|
||||
|
||||
rawmidi.hw {
|
||||
@@ -469,6 +472,7 @@ rawmidi.virtual {
|
||||
|
||||
seq.default {
|
||||
type hw
|
||||
+ hint.description "Default sequencer device"
|
||||
}
|
||||
|
||||
seq.hw {
|
||||
@@ -502,6 +506,7 @@ hwdep.default {
|
||||
name defaults.hwdep.device
|
||||
}
|
||||
}
|
||||
+ hint.description "Default hardware dependent device"
|
||||
}
|
||||
|
||||
hwdep.hw {
|
||||
@@ -536,6 +541,10 @@ hwdep.hw {
|
||||
type hw
|
||||
card $CARD
|
||||
device $DEV
|
||||
+ hint {
|
||||
+ description "Direct hardware dependent device"
|
||||
+ device $DEV
|
||||
+ }
|
||||
}
|
||||
|
||||
#
|
||||
@@ -572,7 +581,7 @@ timer.default {
|
||||
@func refer
|
||||
name defaults.timer.subdevice
|
||||
}
|
||||
- hint.description "Default direct hardware timer device"
|
||||
+ hint.description "Default timer device"
|
||||
}
|
||||
|
||||
timer.hw {
|
||||
@@ -618,4 +627,8 @@ timer.hw {
|
||||
card $CARD
|
||||
device $DEV
|
||||
subdevice $SUBDEV
|
||||
+ hint {
|
||||
+ description "Direct timer device"
|
||||
+ device $DEV
|
||||
+ }
|
||||
}
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,52 +0,0 @@
|
||||
From 404951da5ed66c80caf5e3fa3d703f291002cb24 Mon Sep 17 00:00:00 2001
|
||||
From: Jie Yang <yang.jie@intel.com>
|
||||
Date: Fri, 8 May 2015 15:18:47 +0800
|
||||
Subject: [PATCH 14/16] conf/ucm: broadwell-rt286: change to set capture volume
|
||||
and capture device
|
||||
|
||||
Set 'Mic Capture Volume' in capture device EnableSequence, to fix
|
||||
capture no volume by default issue.
|
||||
|
||||
Also add JackHWMute Value item to mute onboard dmic while headset
|
||||
mic is plugged in.
|
||||
|
||||
Signed-off-by: Jie Yang <yang.jie@intel.com>
|
||||
Tested-by: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/conf/ucm/broadwell-rt286/HiFi | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/src/conf/ucm/broadwell-rt286/HiFi b/src/conf/ucm/broadwell-rt286/HiFi
|
||||
index 58983ea5763c..c09a01cca8fd 100644
|
||||
--- a/src/conf/ucm/broadwell-rt286/HiFi
|
||||
+++ b/src/conf/ucm/broadwell-rt286/HiFi
|
||||
@@ -86,6 +86,7 @@ SectionDevice."Handset" {
|
||||
EnableSequence [
|
||||
cdev "hw:broadwellrt286"
|
||||
|
||||
+ cset "name='Mic Capture Volume' 28"
|
||||
cset "name='ADC 0 Mux' 0"
|
||||
cset "name='ADC0 Capture Switch' on"
|
||||
cset "name='ADC0 Capture Volume' 127"
|
||||
@@ -99,6 +100,9 @@ SectionDevice."Handset" {
|
||||
|
||||
Value {
|
||||
CaptureChannels "2"
|
||||
+ JackDev "rt286-jack"
|
||||
+ JackControl "Mic Jack"
|
||||
+ JackHWMute "Mainmic"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +116,7 @@ SectionDevice."Mainmic" {
|
||||
EnableSequence [
|
||||
cdev "hw:broadwellrt286"
|
||||
|
||||
+ cset "name='Mic Capture Volume' 30"
|
||||
cset "name='ADC 0 Mux' 2"
|
||||
cset "name='ADC0 Capture Switch' on"
|
||||
cset "name='ADC0 Capture Volume' 127"
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,47 +0,0 @@
|
||||
From b4222f3fdc13f18fa621d6c6ff2fa6ed52e25de3 Mon Sep 17 00:00:00 2001
|
||||
From: Tanu Kaskinen <tanu.kaskinen@linux.intel.com>
|
||||
Date: Mon, 4 May 2015 19:10:38 +0300
|
||||
Subject: [PATCH 15/16] ucm: allow multiple devices in JackHWMute
|
||||
|
||||
One jack may mute multiple devices, so let's make JackHWMute a list of
|
||||
device names instead of just a single device name.
|
||||
|
||||
Signed-off-by: Tanu Kaskinen <tanu.kaskinen@linux.intel.com>
|
||||
Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Acked-by: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/use-case.h | 17 +++++++++--------
|
||||
1 file changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/include/use-case.h b/include/use-case.h
|
||||
index e3308b17b105..c7789c03c4e8 100644
|
||||
--- a/include/use-case.h
|
||||
+++ b/include/use-case.h
|
||||
@@ -311,14 +311,15 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
||||
* applications are likely to support only one or the other.
|
||||
*
|
||||
* If **JackHWMute** is set, it indicates that when the jack is plugged
|
||||
- * in, the hardware automatically mutes some other device. The
|
||||
- * JackHWMute value is the name of the muted device. Note that
|
||||
- * JackHWMute should be used only when the hardware enforces the
|
||||
- * automatic muting. If the hardware doesn't enforce any muting, it may
|
||||
- * still be tempting to set JackHWMute to trick upper software layers to
|
||||
- * e.g. automatically mute speakers when headphones are plugged in, but
|
||||
- * that's application policy configuration that doesn't belong to UCM
|
||||
- * configuration files.
|
||||
+ * in, the hardware automatically mutes some other device(s). The
|
||||
+ * JackHWMute value is a space-separated list of device names (this
|
||||
+ * isn't compatible with device names with spaces in them, so don't use
|
||||
+ * such device names!). Note that JackHWMute should be used only when
|
||||
+ * the hardware enforces the automatic muting. If the hardware doesn't
|
||||
+ * enforce any muting, it may still be tempting to set JackHWMute to
|
||||
+ * trick upper software layers to e.g. automatically mute speakers when
|
||||
+ * headphones are plugged in, but that's application policy
|
||||
+ * configuration that doesn't belong to UCM configuration files.
|
||||
*/
|
||||
int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *identifier,
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,36 +0,0 @@
|
||||
From 67f73b0fab466e780dcc0442e19894a1cbedc43b Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 21 May 2015 07:26:39 +0200
|
||||
Subject: [PATCH 16/16] pcm: Remove assert() from snd_pcm_hw_params_slave()
|
||||
|
||||
Using assert() for non-fatal error checks is really brain-dead.
|
||||
These are especially bad, as it hits even in the normal operation with
|
||||
plugins and some h/w constraints.
|
||||
|
||||
Reported-by: Alan Horstmann <gineera@aspect135.co.uk>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_params.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c
|
||||
index 6e57904e445b..1d667a583151 100644
|
||||
--- a/src/pcm/pcm_params.c
|
||||
+++ b/src/pcm/pcm_params.c
|
||||
@@ -2244,9 +2244,11 @@ int snd_pcm_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||
snd_pcm_hw_params_t slave_params;
|
||||
int err;
|
||||
err = sprepare(pcm, &slave_params);
|
||||
- assert(err >= 0);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
err = schange(pcm, params, &slave_params);
|
||||
- assert(err >= 0);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
err = sparams(pcm, &slave_params);
|
||||
if (err < 0)
|
||||
cchange(pcm, params, &slave_params);
|
||||
--
|
||||
2.4.1
|
||||
|
@ -1,28 +0,0 @@
|
||||
From 9120f2de8608f49ee1cd4501b9eee39a1c71778f Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Lohr <christophe.lohr@cegetel.net>
|
||||
Date: Mon, 1 Jun 2015 13:41:49 +0200
|
||||
Subject: [PATCH] test/pcm: Fix generated values with float PCM format
|
||||
|
||||
The float format should be generated [-1.0..1.0].
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
test/pcm.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/pcm.c b/test/pcm.c
|
||||
index abb83e4c3014..18b61762b236 100644
|
||||
--- a/test/pcm.c
|
||||
+++ b/test/pcm.c
|
||||
@@ -68,7 +68,7 @@ static void generate_sine(const snd_pcm_channel_area_t *areas,
|
||||
} fval;
|
||||
int res, i;
|
||||
if (is_float) {
|
||||
- fval.f = sin(phase) * maxval;
|
||||
+ fval.f = sin(phase);
|
||||
res = fval.i;
|
||||
} else
|
||||
res = sin(phase) * maxval;
|
||||
--
|
||||
2.4.3
|
||||
|
@ -1,29 +0,0 @@
|
||||
From 8551fe258791c165892583006b0aa5142f41b621 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Lohr <christophe.lohr@cegetel.net>
|
||||
Date: Mon, 1 Jun 2015 13:43:36 +0200
|
||||
Subject: [PATCH] test/pcm_min: Fix error messages
|
||||
|
||||
Fix the wrongly referred error code for error messages from
|
||||
snd_pcm_writei() and other calls.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
test/pcm_min.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/pcm_min.c b/test/pcm_min.c
|
||||
index e971405ee64f..7462a45fef33 100644
|
||||
--- a/test/pcm_min.c
|
||||
+++ b/test/pcm_min.c
|
||||
@@ -39,7 +39,7 @@ int main(void)
|
||||
if (frames < 0)
|
||||
frames = snd_pcm_recover(handle, frames, 0);
|
||||
if (frames < 0) {
|
||||
- printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
|
||||
+ printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
|
||||
break;
|
||||
}
|
||||
if (frames > 0 && frames < (long)sizeof(buffer))
|
||||
--
|
||||
2.4.3
|
||||
|
@ -1,30 +0,0 @@
|
||||
From a5e5e3cd3c85eafcced7a93b1cf37201560f2a28 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Mon, 1 Jun 2015 13:45:01 +0200
|
||||
Subject: [PATCH] pcm: Don't assert in _snd_pcm_hw_params_internal()
|
||||
|
||||
It's no fatal error from sw params, and it's really bad habit to use
|
||||
assert() and abort the operation as a system library.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_params.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c
|
||||
index 1d667a583151..60d99ad96167 100644
|
||||
--- a/src/pcm/pcm_params.c
|
||||
+++ b/src/pcm/pcm_params.c
|
||||
@@ -2361,7 +2361,8 @@ int _snd_pcm_hw_params_internal(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||
memset(&sw, 0, sizeof(sw));
|
||||
snd_pcm_sw_params_default(pcm, &sw);
|
||||
err = snd_pcm_sw_params(pcm, &sw);
|
||||
- assert(err >= 0);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
|
||||
if (pcm->mmap_rw ||
|
||||
pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED ||
|
||||
--
|
||||
2.4.3
|
||||
|
@ -1,78 +0,0 @@
|
||||
From 18ce3ec9caa266086c5f364a2bdbab27a8db9d77 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 2 Jun 2015 16:47:50 +0200
|
||||
Subject: [PATCH] pcm: Fix snd_pcm_status() for dmix & co
|
||||
|
||||
Fetch the timestamp and other status fields by issuing
|
||||
snd_pcm_status() for the slave PCM. Also, fill the delay field
|
||||
properly. This should fix longstanding PA's complaints.
|
||||
|
||||
Reported-by: Dan Hordern <danhordern@gmail.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_dmix.c | 3 ++-
|
||||
src/pcm/pcm_dshare.c | 3 ++-
|
||||
src/pcm/pcm_dsnoop.c | 3 ++-
|
||||
3 files changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
|
||||
index babde6a15efe..4acbaf0e0265 100644
|
||||
--- a/src/pcm/pcm_dmix.c
|
||||
+++ b/src/pcm/pcm_dmix.c
|
||||
@@ -475,12 +475,13 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
||||
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;
|
||||
- gettimestamp(&status->tstamp, pcm->tstamp_type);
|
||||
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;
|
||||
}
|
||||
|
||||
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
|
||||
index 020e6f7d9307..b51758fb22a2 100644
|
||||
--- a/src/pcm/pcm_dshare.c
|
||||
+++ b/src/pcm/pcm_dshare.c
|
||||
@@ -224,12 +224,13 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
||||
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;
|
||||
- gettimestamp(&status->tstamp, pcm->tstamp_type);
|
||||
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;
|
||||
}
|
||||
|
||||
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
|
||||
index 8333eefdaf4c..8a2e87ad0ae1 100644
|
||||
--- a/src/pcm/pcm_dsnoop.c
|
||||
+++ b/src/pcm/pcm_dsnoop.c
|
||||
@@ -187,13 +187,14 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
||||
break;
|
||||
}
|
||||
memset(status, 0, sizeof(*status));
|
||||
+ snd_pcm_status(dsnoop->spcm, status);
|
||||
state = snd_pcm_state(dsnoop->spcm);
|
||||
status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state;
|
||||
status->trigger_tstamp = dsnoop->trigger_tstamp;
|
||||
- status->tstamp = dsnoop->update_tstamp;
|
||||
status->avail = snd_pcm_mmap_capture_avail(pcm);
|
||||
status->avail_max = status->avail > dsnoop->avail_max ? status->avail : dsnoop->avail_max;
|
||||
dsnoop->avail_max = 0;
|
||||
+ status->delay = snd_pcm_mmap_capture_delay(pcm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.4.3
|
||||
|
@ -1,40 +0,0 @@
|
||||
From 2fd098b587e8e5137c05ea6248c2aa87294e13c2 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Wed, 10 Jun 2015 11:56:23 +0200
|
||||
Subject: [PATCH] control: Allow cset'ing specific values in the multi-value
|
||||
case
|
||||
|
||||
Improve the parser to allow empty elements followed by a comma.
|
||||
Now amixer works like below for setting only the third element.
|
||||
% amixer cset 'IIR1 Band1' ,,200
|
||||
|
||||
Reported-and-tested-by: Arun Raghavan <arun@accosted.net>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/control/ctlparse.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/control/ctlparse.c b/src/control/ctlparse.c
|
||||
index 8d6c3859bec4..877a05e3a1f1 100644
|
||||
--- a/src/control/ctlparse.c
|
||||
+++ b/src/control/ctlparse.c
|
||||
@@ -325,6 +325,8 @@ int snd_ctl_ascii_value_parse(snd_ctl_t *handle,
|
||||
snd_ctl_elem_value_set_id(dst, myid);
|
||||
|
||||
for (idx = 0; idx < count && idx < 128 && ptr && *ptr; idx++) {
|
||||
+ if (*ptr == ',')
|
||||
+ goto skip;
|
||||
switch (type) {
|
||||
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
||||
tmp = 0;
|
||||
@@ -375,6 +377,7 @@ int snd_ctl_ascii_value_parse(snd_ctl_t *handle,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
+ skip:
|
||||
if (!strchr(value, ','))
|
||||
ptr = value;
|
||||
else if (*ptr == ',')
|
||||
--
|
||||
2.4.3
|
||||
|
@ -1,87 +0,0 @@
|
||||
From 9ee6ec80b80268932a372522ca192168e7812ccf Mon Sep 17 00:00:00 2001
|
||||
From: Shengjiu Wang <shengjiu.wang@freescale.com>
|
||||
Date: Fri, 12 Jun 2015 16:15:08 +0800
|
||||
Subject: [PATCH] PCM: snd_pcm_xxxx_drain() maybe blocked after suspend and
|
||||
resume
|
||||
|
||||
After suspend and resume, the alsa driver is stopped. But if alsa-lib run
|
||||
into snd_pcm_xxxx_drain(), it need to wait avail >= pcm->stop_threshold,
|
||||
otherwise, it will not exit the loop, so finally it is blocked at poll() of
|
||||
snd_pcm_wait_nocheck(pcm, -1).
|
||||
This patch is to add state check after snd_pcm_wait_nocheck(pcm, -1), if
|
||||
the state is SND_PCM_STATE_SUSPENDED, then return error.
|
||||
|
||||
Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_dmix.c | 14 ++++++++++++++
|
||||
src/pcm/pcm_dshare.c | 14 ++++++++++++++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
|
||||
index 4acbaf0e0265..58e4975d5225 100644
|
||||
--- a/src/pcm/pcm_dmix.c
|
||||
+++ b/src/pcm/pcm_dmix.c
|
||||
@@ -617,6 +617,13 @@ static int snd_pcm_dmix_drain(snd_pcm_t *pcm)
|
||||
snd_pcm_uframes_t stop_threshold;
|
||||
int err;
|
||||
|
||||
+ switch (snd_pcm_state(dmix->spcm)) {
|
||||
+ case SND_PCM_STATE_SUSPENDED:
|
||||
+ return -ESTRPIPE;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (dmix->state == SND_PCM_STATE_OPEN)
|
||||
return -EBADFD;
|
||||
if (pcm->mode & SND_PCM_NONBLOCK)
|
||||
@@ -649,6 +656,13 @@ static int snd_pcm_dmix_drain(snd_pcm_t *pcm)
|
||||
snd_pcm_dmix_sync_area(pcm);
|
||||
snd_pcm_wait_nocheck(pcm, -1);
|
||||
snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */
|
||||
+
|
||||
+ switch (snd_pcm_state(dmix->spcm)) {
|
||||
+ case SND_PCM_STATE_SUSPENDED:
|
||||
+ return -ESTRPIPE;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
} while (dmix->state == SND_PCM_STATE_DRAINING);
|
||||
pcm->stop_threshold = stop_threshold;
|
||||
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
|
||||
index b51758fb22a2..02370dc7082d 100644
|
||||
--- a/src/pcm/pcm_dshare.c
|
||||
+++ b/src/pcm/pcm_dshare.c
|
||||
@@ -368,6 +368,13 @@ static int snd_pcm_dshare_drain(snd_pcm_t *pcm)
|
||||
snd_pcm_uframes_t stop_threshold;
|
||||
int err;
|
||||
|
||||
+ switch (snd_pcm_state(dshare->spcm)) {
|
||||
+ case SND_PCM_STATE_SUSPENDED:
|
||||
+ return -ESTRPIPE;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (dshare->state == SND_PCM_STATE_OPEN)
|
||||
return -EBADFD;
|
||||
if (pcm->mode & SND_PCM_NONBLOCK)
|
||||
@@ -400,6 +407,13 @@ static int snd_pcm_dshare_drain(snd_pcm_t *pcm)
|
||||
snd_pcm_dshare_sync_area(pcm);
|
||||
snd_pcm_wait_nocheck(pcm, -1);
|
||||
snd_pcm_direct_clear_timer_queue(dshare); /* force poll to wait */
|
||||
+
|
||||
+ switch (snd_pcm_state(dshare->spcm)) {
|
||||
+ case SND_PCM_STATE_SUSPENDED:
|
||||
+ return -ESTRPIPE;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
} while (dshare->state == SND_PCM_STATE_DRAINING);
|
||||
pcm->stop_threshold = stop_threshold;
|
||||
--
|
||||
2.4.3
|
||||
|
@ -1,63 +0,0 @@
|
||||
From bbe9248e6788e7a852af15f2110dbaeace4d1907 Mon Sep 17 00:00:00 2001
|
||||
From: David Henningsson <david.henningsson@canonical.com>
|
||||
Date: Thu, 18 Jun 2015 10:47:59 +0200
|
||||
Subject: [PATCH] surround41/50.conf: Use chmap syntax for better flexibility
|
||||
|
||||
In case the hardware only supports a specific channel map,
|
||||
this change would allow surround41/50 to select the correct
|
||||
channel map and channel count in this situation.
|
||||
|
||||
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/conf/pcm/surround41.conf | 11 +++++------
|
||||
src/conf/pcm/surround50.conf | 11 +++++------
|
||||
2 files changed, 10 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/conf/pcm/surround41.conf b/src/conf/pcm/surround41.conf
|
||||
index 10e486e21528..2f823815821a 100644
|
||||
--- a/src/conf/pcm/surround41.conf
|
||||
+++ b/src/conf/pcm/surround41.conf
|
||||
@@ -53,12 +53,11 @@ pcm.!surround41 {
|
||||
]
|
||||
}
|
||||
}
|
||||
- slave.channels 6
|
||||
- ttable.0.0 1
|
||||
- ttable.1.1 1
|
||||
- ttable.2.2 1
|
||||
- ttable.3.3 1
|
||||
- ttable.4.5 1
|
||||
+ ttable.0.FL 1
|
||||
+ ttable.1.FR 1
|
||||
+ ttable.2.RL 1
|
||||
+ ttable.3.RR 1
|
||||
+ ttable.4.LFE 1
|
||||
hint {
|
||||
description "4.1 Surround output to Front, Rear and Subwoofer speakers"
|
||||
device $DEV
|
||||
diff --git a/src/conf/pcm/surround50.conf b/src/conf/pcm/surround50.conf
|
||||
index 7b7b17e10246..dc95c179da68 100644
|
||||
--- a/src/conf/pcm/surround50.conf
|
||||
+++ b/src/conf/pcm/surround50.conf
|
||||
@@ -53,12 +53,11 @@ pcm.!surround50 {
|
||||
]
|
||||
}
|
||||
}
|
||||
- slave.channels 6
|
||||
- ttable.0.0 1
|
||||
- ttable.1.1 1
|
||||
- ttable.2.2 1
|
||||
- ttable.3.3 1
|
||||
- ttable.4.4 1
|
||||
+ ttable.0.FL 1
|
||||
+ ttable.1.FR 1
|
||||
+ ttable.2.RL 1
|
||||
+ ttable.3.RR 1
|
||||
+ ttable.4.FC 1
|
||||
hint {
|
||||
description "5.0 Surround output to Front, Center and Rear speakers"
|
||||
device $DEV
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,28 +0,0 @@
|
||||
From f66c7cc293b13765ffd67f530008e836f8354b13 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Mon, 29 Jun 2015 16:25:57 +0100
|
||||
Subject: [PATCH 24/49] ucm: docs: fix doxygen exclude patch for UCM local
|
||||
header
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
doc/doxygen.cfg.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in
|
||||
index f4499d610290..043e75b2d7eb 100644
|
||||
--- a/doc/doxygen.cfg.in
|
||||
+++ b/doc/doxygen.cfg.in
|
||||
@@ -94,7 +94,7 @@ EXCLUDE = @top_srcdir@/src/control/control_local.h \
|
||||
@top_srcdir@/src/mixer/mixer_local.h \
|
||||
@top_srcdir@/src/rawmidi/rawmidi_local.h \
|
||||
@top_srcdir@/src/seq/seq_local.h \
|
||||
- @top_srcdir@/src/seq/ucm_local.h
|
||||
+ @top_srcdir@/src/ucm/ucm_local.h
|
||||
RECURSIVE = YES
|
||||
FILE_PATTERNS = *.c *.h
|
||||
EXAMPLE_PATH = @top_srcdir@/test
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,69 +0,0 @@
|
||||
From bb92545e064c3e2549878a328277eebe343aae61 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Mon, 29 Jun 2015 16:25:58 +0100
|
||||
Subject: [PATCH 25/49] ucm: docs: Fix doxygen formatting for UCM main page.
|
||||
|
||||
Make sure group is defined and lists dipplayed correctly.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/use-case.h | 20 +++++++++-----------
|
||||
1 file changed, 9 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/include/use-case.h b/include/use-case.h
|
||||
index c7789c03c4e8..9aac6e2fb51d 100644
|
||||
--- a/include/use-case.h
|
||||
+++ b/include/use-case.h
|
||||
@@ -43,15 +43,13 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
- * \defgroup Use Case Interface
|
||||
+ * \defgroup ucm Use Case Interface
|
||||
* The ALSA Use Case manager interface.
|
||||
* See \ref Usecase page for more details.
|
||||
* \{
|
||||
*/
|
||||
|
||||
/*! \page Usecase ALSA Use Case Interface
|
||||
- *
|
||||
- * ALSA Use Case Interface
|
||||
*
|
||||
* The use case manager works by configuring the sound card ALSA kcontrols to
|
||||
* change the hardware digital and analog audio routing to match the requested
|
||||
@@ -69,9 +67,9 @@ extern "C" {
|
||||
*
|
||||
* However there are times when a use case has to be modified at runtime. e.g.
|
||||
*
|
||||
- * o Incoming phone call when the device is playing music
|
||||
- * o Recording sections of a phone call
|
||||
- * o Playing tones during a call.
|
||||
+ * + Incoming phone call when the device is playing music
|
||||
+ * + Recording sections of a phone call
|
||||
+ * + Playing tones during a call.
|
||||
*
|
||||
* In order to allow asynchronous runtime use case adaptations, we have a third
|
||||
* optional modifier parameter that can be used to further configure
|
||||
@@ -79,13 +77,13 @@ extern "C" {
|
||||
*
|
||||
* This interface allows clients to :-
|
||||
*
|
||||
- * o Query the supported use case verbs, devices and modifiers for the machine.
|
||||
- * o Set and Get use case verbs, devices and modifiers for the machine.
|
||||
- * o Get the ALSA PCM playback and capture device PCMs for use case verb,
|
||||
+ * + Query the supported use case verbs, devices and modifiers for the machine.
|
||||
+ * + Set and Get use case verbs, devices and modifiers for the machine.
|
||||
+ * + Get the ALSA PCM playback and capture device PCMs for use case verb,
|
||||
* use case device and modifier.
|
||||
- * o Get the TQ parameter for each use case verb, use case device and
|
||||
+ * + Get the TQ parameter for each use case verb, use case device and
|
||||
* modifier.
|
||||
- * o Get the ALSA master playback and capture volume/switch kcontrols
|
||||
+ * + Get the ALSA master playback and capture volume/switch kcontrols
|
||||
* for each use case.
|
||||
*/
|
||||
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,26 +0,0 @@
|
||||
From c6df8273746645b2c5109537b07af6ed33d268d1 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Mon, 29 Jun 2015 16:25:59 +0100
|
||||
Subject: [PATCH 26/49] docs: Add UCM link to main doxygen page.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
doc/index.doxygen | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/doc/index.doxygen b/doc/index.doxygen
|
||||
index 45aa68a11caa..7d049fe5c32a 100644
|
||||
--- a/doc/index.doxygen
|
||||
+++ b/doc/index.doxygen
|
||||
@@ -40,6 +40,7 @@ may be placed in the library code instead of the kernel driver.</P>
|
||||
<LI>Page \ref rawmidi explains the design of the RawMidi API.
|
||||
<LI>Page \ref timer explains the design of the Timer API.
|
||||
<LI>Page \ref seq explains the design of the Sequencer API.
|
||||
+ <LI>Page \ref ucm explains the use case API.
|
||||
</UL>
|
||||
|
||||
<H2>Configuration</H2>
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,105 +0,0 @@
|
||||
From 4dc44bb34aab2b23ab45c8e61e4b17bf2cf58959 Mon Sep 17 00:00:00 2001
|
||||
From: "Alexander E. Patrakov" <patrakov@gmail.com>
|
||||
Date: Mon, 29 Jun 2015 22:53:53 +0500
|
||||
Subject: [PATCH 27/49] Replace unsafe characters with _ in card name
|
||||
|
||||
Otherwise, they get misinterpreted as argument separators
|
||||
in USB-Audio PCM definitions, and thus prevent SPDIF blacklist entries
|
||||
from working.
|
||||
|
||||
While at it, add my Logitec C910 webcam to the SPDIF blacklist.
|
||||
|
||||
Signed-off-by: Alexander E. Patrakov <patrakov@gmail.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/conf.h | 1 +
|
||||
src/conf.c | 32 ++++++++++++++++++++++++++++++++
|
||||
src/conf/cards/USB-Audio.conf | 3 ++-
|
||||
src/confmisc.c | 2 +-
|
||||
4 files changed, 36 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/conf.h b/include/conf.h
|
||||
index ff270f617383..087c05dc6bcf 100644
|
||||
--- a/include/conf.h
|
||||
+++ b/include/conf.h
|
||||
@@ -126,6 +126,7 @@ int snd_config_imake_integer(snd_config_t **config, const char *key, const long
|
||||
int snd_config_imake_integer64(snd_config_t **config, const char *key, const long long value);
|
||||
int snd_config_imake_real(snd_config_t **config, const char *key, const double value);
|
||||
int snd_config_imake_string(snd_config_t **config, const char *key, const char *ascii);
|
||||
+int snd_config_imake_safe_string(snd_config_t **config, const char *key, const char *ascii);
|
||||
int snd_config_imake_pointer(snd_config_t **config, const char *key, const void *ptr);
|
||||
|
||||
snd_config_type_t snd_config_get_type(const snd_config_t *config);
|
||||
diff --git a/src/conf.c b/src/conf.c
|
||||
index bb256e7ae443..c6a83eef7d2f 100644
|
||||
--- a/src/conf.c
|
||||
+++ b/src/conf.c
|
||||
@@ -2228,6 +2228,38 @@ int snd_config_imake_string(snd_config_t **config, const char *id, const char *v
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int snd_config_imake_safe_string(snd_config_t **config, const char *id, const char *value)
|
||||
+{
|
||||
+ int err;
|
||||
+ snd_config_t *tmp;
|
||||
+ char *c;
|
||||
+
|
||||
+ err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ if (value) {
|
||||
+ tmp->u.string = strdup(value);
|
||||
+ if (!tmp->u.string) {
|
||||
+ snd_config_delete(tmp);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ for (c = tmp->u.string; *c; c++) {
|
||||
+ if (*c == ' ' || *c == '-' || *c == '_' ||
|
||||
+ (*c >= '0' && *c <= '9') ||
|
||||
+ (*c >= 'a' && *c <= 'z') ||
|
||||
+ (*c >= 'A' && *c <= 'Z'))
|
||||
+ continue;
|
||||
+ *c = '_';
|
||||
+ }
|
||||
+ } else {
|
||||
+ tmp->u.string = NULL;
|
||||
+ }
|
||||
+ *config = tmp;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/**
|
||||
* \brief Creates a pointer configuration node with the given initial value.
|
||||
* \param[out] config The function puts the handle to the new node at
|
||||
diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf
|
||||
index 031bee0d86fd..e365f2979e6a 100644
|
||||
--- a/src/conf/cards/USB-Audio.conf
|
||||
+++ b/src/conf/cards/USB-Audio.conf
|
||||
@@ -57,7 +57,8 @@ USB-Audio.pcm.iec958_device {
|
||||
"Scarlett 2i4 USB" 999
|
||||
"Sennheiser USB headset" 999
|
||||
"SWTOR Gaming Headset by Razer" 999
|
||||
- "USB Device 0x46d:0x992" 999
|
||||
+ "USB Device 0x46d_0x821" 999
|
||||
+ "USB Device 0x46d_0x992" 999
|
||||
}
|
||||
|
||||
# Second iec958 device number, if any.
|
||||
diff --git a/src/confmisc.c b/src/confmisc.c
|
||||
index 1fb4f282217e..ae0275ff4de3 100644
|
||||
--- a/src/confmisc.c
|
||||
+++ b/src/confmisc.c
|
||||
@@ -935,7 +935,7 @@ int snd_func_card_name(snd_config_t **dst, snd_config_t *root,
|
||||
}
|
||||
err = snd_config_get_id(src, &id);
|
||||
if (err >= 0)
|
||||
- err = snd_config_imake_string(dst, id,
|
||||
+ err = snd_config_imake_safe_string(dst, id,
|
||||
snd_ctl_card_info_get_name(info));
|
||||
__error:
|
||||
if (ctl)
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,84 +0,0 @@
|
||||
From 6cb31b444442f8ebca939cd78b80993f2ac85350 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Date: Wed, 1 Jul 2015 15:40:54 -0500
|
||||
Subject: [PATCH 28/49] pcm: add helper functions to query timestamping
|
||||
capabilities
|
||||
|
||||
extend support to link, link_estimated and link_synchronized
|
||||
timestamp. wall-clock is deprecated
|
||||
|
||||
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/pcm.h | 3 ++-
|
||||
src/pcm/pcm.c | 35 ++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 36 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/pcm.h b/include/pcm.h
|
||||
index 0655e7f43ef6..2aa1eff36be3 100644
|
||||
--- a/include/pcm.h
|
||||
+++ b/include/pcm.h
|
||||
@@ -668,7 +668,8 @@ int snd_pcm_hw_params_is_half_duplex(const snd_pcm_hw_params_t *params);
|
||||
int snd_pcm_hw_params_is_joint_duplex(const snd_pcm_hw_params_t *params);
|
||||
int snd_pcm_hw_params_can_sync_start(const snd_pcm_hw_params_t *params);
|
||||
int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *params);
|
||||
-int snd_pcm_hw_params_supports_audio_wallclock_ts(const snd_pcm_hw_params_t *params);
|
||||
+int snd_pcm_hw_params_supports_audio_wallclock_ts(const snd_pcm_hw_params_t *params); /* deprecated, use audio_ts_type */
|
||||
+int snd_pcm_hw_params_supports_audio_ts_type(const snd_pcm_hw_params_t *params, int type);
|
||||
int snd_pcm_hw_params_get_rate_numden(const snd_pcm_hw_params_t *params,
|
||||
unsigned int *rate_num,
|
||||
unsigned int *rate_den);
|
||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
||||
index bc18954b92da..846d502a6cb1 100644
|
||||
--- a/src/pcm/pcm.c
|
||||
+++ b/src/pcm/pcm.c
|
||||
@@ -3190,12 +3190,45 @@ int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *param
|
||||
*/
|
||||
int snd_pcm_hw_params_supports_audio_wallclock_ts(const snd_pcm_hw_params_t *params)
|
||||
{
|
||||
+ /* deprecated */
|
||||
+ return snd_pcm_hw_params_supports_audio_ts_type(params,
|
||||
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * \brief Check if hardware supports type of audio timestamps
|
||||
+ * \param params Configuration space
|
||||
+ * \param type Audio timestamp type
|
||||
+ * \retval 0 Hardware doesn't support type of audio timestamps
|
||||
+ * \retval 1 Hardware supports type of audio timestamps
|
||||
+ *
|
||||
+ * This function should only be called when the configuration space
|
||||
+ * contains a single configuration. Call #snd_pcm_hw_params to choose
|
||||
+ * a single configuration from the configuration space.
|
||||
+ */
|
||||
+int snd_pcm_hw_params_supports_audio_ts_type(const snd_pcm_hw_params_t *params, int type)
|
||||
+{
|
||||
assert(params);
|
||||
if (CHECK_SANITY(params->info == ~0U)) {
|
||||
SNDMSG("invalid PCM info field");
|
||||
return 0; /* FIXME: should be a negative error? */
|
||||
}
|
||||
- return !!(params->info & SNDRV_PCM_INFO_HAS_WALL_CLOCK);
|
||||
+ switch (type) {
|
||||
+ case SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT:
|
||||
+ return !!(params->info & SNDRV_PCM_INFO_HAS_WALL_CLOCK); /* deprecated */
|
||||
+ case SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT:
|
||||
+ return 1; /* always supported, based on hw_ptr */
|
||||
+ case SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK:
|
||||
+ return !!(params->info & SNDRV_PCM_INFO_HAS_LINK_ATIME);
|
||||
+ case SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE:
|
||||
+ return !!(params->info & SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME);
|
||||
+ case SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED:
|
||||
+ return !!(params->info & SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME);
|
||||
+ case SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED:
|
||||
+ return !!(params->info & SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME);
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
/**
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,129 +0,0 @@
|
||||
From 6ec2464f397ff401c251057499abea77fd80b60b Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Date: Wed, 1 Jul 2015 15:40:55 -0500
|
||||
Subject: [PATCH 29/49] pcm: add support for get/set_audio_htstamp_config
|
||||
|
||||
Enable kernel-side functionality by letting user select what sort of
|
||||
timestamp it desires
|
||||
|
||||
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/pcm.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/pcm/pcm.c | 38 ++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 82 insertions(+)
|
||||
|
||||
diff --git a/include/pcm.h b/include/pcm.h
|
||||
index 2aa1eff36be3..a1d14a989a47 100644
|
||||
--- a/include/pcm.h
|
||||
+++ b/include/pcm.h
|
||||
@@ -330,6 +330,26 @@ typedef enum _snd_pcm_tstamp_type {
|
||||
SND_PCM_TSTAMP_TYPE_LAST = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
|
||||
} snd_pcm_tstamp_type_t;
|
||||
|
||||
+typedef struct _snd_pcm_audio_tstamp_config {
|
||||
+ /* 5 of max 16 bits used */
|
||||
+ unsigned int type_requested:4;
|
||||
+ unsigned int report_delay:1; /* add total delay to A/D or D/A */
|
||||
+} snd_pcm_audio_tstamp_config_t;
|
||||
+
|
||||
+typedef struct _snd_pcm_audio_tstamp_report {
|
||||
+ /* 6 of max 16 bits used for bit-fields */
|
||||
+
|
||||
+ /* for backwards compatibility */
|
||||
+ unsigned int valid:1;
|
||||
+
|
||||
+ /* actual type if hardware could not support requested timestamp */
|
||||
+ unsigned int actual_type:4;
|
||||
+
|
||||
+ /* accuracy represented in ns units */
|
||||
+ unsigned int accuracy_report:1; /* 0 if accuracy unknown, 1 if accuracy field is valid */
|
||||
+ unsigned int accuracy; /* up to 4.29s, will be packed in separate field */
|
||||
+} snd_pcm_audio_tstamp_report_t;
|
||||
+
|
||||
/** Unsigned frames quantity */
|
||||
typedef unsigned long snd_pcm_uframes_t;
|
||||
/** Signed frames quantity */
|
||||
@@ -981,6 +1001,30 @@ void snd_pcm_status_get_trigger_htstamp(const snd_pcm_status_t *obj, snd_htimest
|
||||
void snd_pcm_status_get_tstamp(const snd_pcm_status_t *obj, snd_timestamp_t *ptr);
|
||||
void snd_pcm_status_get_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
|
||||
void snd_pcm_status_get_audio_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
|
||||
+void snd_pcm_status_get_driver_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
|
||||
+void snd_pcm_status_get_audio_htstamp_report(const snd_pcm_status_t *obj,
|
||||
+ snd_pcm_audio_tstamp_report_t *audio_tstamp_report);
|
||||
+void snd_pcm_status_set_audio_htstamp_config(snd_pcm_status_t *obj,
|
||||
+ snd_pcm_audio_tstamp_config_t *audio_tstamp_config);
|
||||
+
|
||||
+static inline void snd_pcm_pack_audio_tstamp_config(unsigned int *data,
|
||||
+ snd_pcm_audio_tstamp_config_t *config)
|
||||
+{
|
||||
+ *data = config->report_delay;
|
||||
+ *data <<= 4;
|
||||
+ *data |= config->type_requested;
|
||||
+}
|
||||
+
|
||||
+static inline void snd_pcm_unpack_audio_tstamp_report(unsigned int data, unsigned int accuracy,
|
||||
+ snd_pcm_audio_tstamp_report_t *report)
|
||||
+{
|
||||
+ data >>= 16;
|
||||
+ report->valid = data & 1;
|
||||
+ report->actual_type = (data >> 1) & 0xF;
|
||||
+ report->accuracy_report = (data >> 5) & 1;
|
||||
+ report->accuracy = accuracy;
|
||||
+}
|
||||
+
|
||||
snd_pcm_sframes_t snd_pcm_status_get_delay(const snd_pcm_status_t *obj);
|
||||
snd_pcm_uframes_t snd_pcm_status_get_avail(const snd_pcm_status_t *obj);
|
||||
snd_pcm_uframes_t snd_pcm_status_get_avail_max(const snd_pcm_status_t *obj);
|
||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
||||
index 846d502a6cb1..bae1d1653904 100644
|
||||
--- a/src/pcm/pcm.c
|
||||
+++ b/src/pcm/pcm.c
|
||||
@@ -6367,6 +6367,44 @@ void snd_pcm_status_get_audio_htstamp(const snd_pcm_status_t *obj, snd_htimestam
|
||||
}
|
||||
|
||||
/**
|
||||
+ * \brief Get "now" hi-res driver timestamp from a PCM status container. Defines when the status
|
||||
+ * was generated by driver, may differ from normal timestamp.
|
||||
+ * \param obj pointer to #snd_pcm_status_t
|
||||
+ * \param ptr Pointer to returned timestamp
|
||||
+ */
|
||||
+void snd_pcm_status_get_driver_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
|
||||
+{
|
||||
+ assert(obj && ptr);
|
||||
+ *ptr = obj->driver_tstamp;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * \brief Get audio_tstamp_report from a PCM status container
|
||||
+ * \param obj pointer to #snd_pcm_status_t
|
||||
+ * \param ptr Pointer to returned report (valid fields are accuracy and type)
|
||||
+ */
|
||||
+void snd_pcm_status_get_audio_htstamp_report(const snd_pcm_status_t *obj,
|
||||
+ snd_pcm_audio_tstamp_report_t *audio_tstamp_report)
|
||||
+{
|
||||
+ assert(obj && audio_tstamp_report);
|
||||
+ snd_pcm_unpack_audio_tstamp_report(obj->audio_tstamp_data,
|
||||
+ obj->audio_tstamp_accuracy,
|
||||
+ audio_tstamp_report);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * \brief set audio_tstamp_config from a PCM status container
|
||||
+ * \param obj pointer to #snd_pcm_status_t
|
||||
+ * \param ptr Pointer to config (valid fields are type and report_analog_delay)
|
||||
+ */
|
||||
+void snd_pcm_status_set_audio_htstamp_config(snd_pcm_status_t *obj,
|
||||
+ snd_pcm_audio_tstamp_config_t *audio_tstamp_config)
|
||||
+{
|
||||
+ assert(obj && audio_tstamp_config);
|
||||
+ snd_pcm_pack_audio_tstamp_config(&obj->audio_tstamp_data, audio_tstamp_config);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* \brief Get delay from a PCM status container (see #snd_pcm_delay)
|
||||
* \return Delay in frames
|
||||
*
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,45 +0,0 @@
|
||||
From cc8b73436a90c35beda64bfa13b2196df20cfd81 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Date: Wed, 1 Jul 2015 15:40:56 -0500
|
||||
Subject: [PATCH 30/49] pcm: add support for new STATUS_EXT ioctl
|
||||
|
||||
use STATUS_EXT ioctl if PCM protocol is > 2.0.12
|
||||
All audio timestamp configuration will be ignored with an
|
||||
older protocol.
|
||||
|
||||
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_hw.c | 16 ++++++++++++----
|
||||
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c
|
||||
index c34b766ee035..232b19736db9 100644
|
||||
--- a/src/pcm/pcm_hw.c
|
||||
+++ b/src/pcm/pcm_hw.c
|
||||
@@ -510,10 +510,18 @@ static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
||||
{
|
||||
snd_pcm_hw_t *hw = pcm->private_data;
|
||||
int fd = hw->fd, err;
|
||||
- if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS, status) < 0) {
|
||||
- err = -errno;
|
||||
- SYSMSG("SNDRV_PCM_IOCTL_STATUS failed (%i)", err);
|
||||
- return err;
|
||||
+ if (SNDRV_PROTOCOL_VERSION(2, 0, 13) > hw->version) {
|
||||
+ if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS, status) < 0) {
|
||||
+ err = -errno;
|
||||
+ SYSMSG("SNDRV_PCM_IOCTL_STATUS failed (%i)", err);
|
||||
+ return err;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS_EXT, status) < 0) {
|
||||
+ err = -errno;
|
||||
+ SYSMSG("SNDRV_PCM_IOCTL_STATUS_EXT failed (%i)", err);
|
||||
+ return err;
|
||||
+ }
|
||||
}
|
||||
if (SNDRV_PROTOCOL_VERSION(2, 0, 5) > hw->version) {
|
||||
status->tstamp.tv_nsec *= 1000L;
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,596 +0,0 @@
|
||||
From 7bb3a74c4dbcfb01b0b91d94452d994b845b4ff3 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Date: Wed, 1 Jul 2015 15:40:57 -0500
|
||||
Subject: [PATCH 31/49] test: fix audio_time with new get/set
|
||||
audio_tstamp_config
|
||||
|
||||
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
test/audio_time.c | 491 ++++++++++++++++++++++++++++++++++--------------------
|
||||
1 file changed, 313 insertions(+), 178 deletions(-)
|
||||
|
||||
diff --git a/test/audio_time.c b/test/audio_time.c
|
||||
index 7435db6a7fd8..e369e59b4ff2 100644
|
||||
--- a/test/audio_time.c
|
||||
+++ b/test/audio_time.c
|
||||
@@ -4,13 +4,39 @@
|
||||
* helpful to verify the information reported by drivers.
|
||||
*/
|
||||
|
||||
-#include "../include/asoundlib.h"
|
||||
+#include <stdio.h>
|
||||
+#include <malloc.h>
|
||||
+#include <unistd.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <getopt.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <ctype.h>
|
||||
+#include <errno.h>
|
||||
+#include <limits.h>
|
||||
+#include <time.h>
|
||||
+#include <locale.h>
|
||||
#include <math.h>
|
||||
+#include "../include/asoundlib.h"
|
||||
|
||||
-static char *device = "hw:0,0";
|
||||
-
|
||||
+static char *command;
|
||||
+static char *pcm_name = "hw:0";
|
||||
snd_output_t *output = NULL;
|
||||
|
||||
+static void usage(char *command)
|
||||
+{
|
||||
+ printf("Usage: %s [OPTION]... \n"
|
||||
+ "\n"
|
||||
+ "-h, --help help\n"
|
||||
+ "-c, --capture capture tstamps \n"
|
||||
+ "-d, --delay add delay \n"
|
||||
+ "-D, --device=NAME select PCM by name \n"
|
||||
+ "-p, --playback playback tstamps \n"
|
||||
+ "-t, --ts_type=TYPE Default(0),link(1),link_estimated(2),synchronized(3) \n"
|
||||
+ , command);
|
||||
+}
|
||||
+
|
||||
+
|
||||
long long timestamp2ns(snd_htimestamp_t t)
|
||||
{
|
||||
long long nsec;
|
||||
@@ -31,15 +57,20 @@ long long timediff(snd_htimestamp_t t1, snd_htimestamp_t t2)
|
||||
return nsec1 - nsec2;
|
||||
}
|
||||
|
||||
-void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
|
||||
- snd_htimestamp_t *trigger_timestamp,
|
||||
- snd_htimestamp_t *audio_timestamp,
|
||||
- snd_pcm_uframes_t *avail, snd_pcm_sframes_t *delay)
|
||||
+void _gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
|
||||
+ snd_htimestamp_t *trigger_timestamp,
|
||||
+ snd_htimestamp_t *audio_timestamp,
|
||||
+ snd_pcm_audio_tstamp_config_t *audio_tstamp_config,
|
||||
+ snd_pcm_audio_tstamp_report_t *audio_tstamp_report,
|
||||
+ snd_pcm_uframes_t *avail, snd_pcm_sframes_t *delay)
|
||||
{
|
||||
int err;
|
||||
snd_pcm_status_t *status;
|
||||
|
||||
snd_pcm_status_alloca(&status);
|
||||
+
|
||||
+ snd_pcm_status_set_audio_htstamp_config(status, audio_tstamp_config);
|
||||
+
|
||||
if ((err = snd_pcm_status(handle, status)) < 0) {
|
||||
printf("Stream status error: %s\n", snd_strerror(err));
|
||||
exit(0);
|
||||
@@ -47,26 +78,30 @@ void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
|
||||
snd_pcm_status_get_trigger_htstamp(status, trigger_timestamp);
|
||||
snd_pcm_status_get_htstamp(status, timestamp);
|
||||
snd_pcm_status_get_audio_htstamp(status, audio_timestamp);
|
||||
+ snd_pcm_status_get_audio_htstamp_report(status, audio_tstamp_report);
|
||||
*avail = snd_pcm_status_get_avail(status);
|
||||
*delay = snd_pcm_status_get_delay(status);
|
||||
}
|
||||
|
||||
-#define PERIOD 6000
|
||||
+#define TIMESTAMP_FREQ 8 /* Hz */
|
||||
+#define SAMPLE_FREQ 48000
|
||||
+#define PERIOD (SAMPLE_FREQ/TIMESTAMP_FREQ)
|
||||
#define PCM_LINK /* sync start for playback and capture */
|
||||
#define TRACK_CAPTURE /* dump capture timing info */
|
||||
#define TRACK_PLAYBACK /* dump playback timing info */
|
||||
-#define TRACK_SAMPLE_COUNTS /* show difference between sample counters and audiotimestamps returned by driver */
|
||||
+/*#define TRACK_SAMPLE_COUNTS */ /* show difference between sample counters and audiotimestamps returned by driver */
|
||||
#define PLAYBACK_BUFFERS 4
|
||||
-#define TSTAMP_TYPE SND_PCM_TSTAMP_TYPE_MONOTONIC
|
||||
+#define TSTAMP_TYPE SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW
|
||||
|
||||
|
||||
-int main(void)
|
||||
+int main(int argc, char *argv[])
|
||||
{
|
||||
- int err;
|
||||
- unsigned int i;
|
||||
- snd_pcm_t *handle_p = NULL;
|
||||
- snd_pcm_t *handle_c = NULL;
|
||||
- snd_pcm_sframes_t frames;
|
||||
+ int c;
|
||||
+ int err;
|
||||
+ unsigned int i;
|
||||
+ snd_pcm_t *handle_p = NULL;
|
||||
+ snd_pcm_t *handle_c = NULL;
|
||||
+ snd_pcm_sframes_t frames;
|
||||
snd_htimestamp_t tstamp_c, tstamp_p;
|
||||
snd_htimestamp_t trigger_tstamp_c, trigger_tstamp_p;
|
||||
snd_htimestamp_t audio_tstamp_c, audio_tstamp_p;
|
||||
@@ -87,206 +122,306 @@ int main(void)
|
||||
snd_pcm_sframes_t delay_p, delay_c;
|
||||
snd_pcm_uframes_t avail_p, avail_c;
|
||||
|
||||
- if ((err = snd_pcm_open(&handle_p, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
||||
- printf("Playback open error: %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
- if ((err = snd_pcm_set_params(handle_p,
|
||||
- SND_PCM_FORMAT_S16,
|
||||
- SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
- 2,
|
||||
- 48000,
|
||||
- 0,
|
||||
- 500000)) < 0) { /* 0.5sec */
|
||||
- printf("Playback open error: %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
+ snd_pcm_audio_tstamp_config_t audio_tstamp_config_p;
|
||||
+ snd_pcm_audio_tstamp_config_t audio_tstamp_config_c;
|
||||
+ snd_pcm_audio_tstamp_report_t audio_tstamp_report_p;
|
||||
+ snd_pcm_audio_tstamp_report_t audio_tstamp_report_c;
|
||||
+
|
||||
+ int option_index;
|
||||
+ static const char short_options[] = "hcpdD:t:";
|
||||
+
|
||||
+ static const struct option long_options[] = {
|
||||
+ {"capture", 0, 0, 'c'},
|
||||
+ {"delay", 0, 0, 'd'},
|
||||
+ {"device", required_argument, 0, 'D'},
|
||||
+ {"help", no_argument, 0, 'h'},
|
||||
+ {"playback", 0, 0, 'p'},
|
||||
+ {"ts_type", required_argument, 0, 't'},
|
||||
+ {0, 0, 0, 0}
|
||||
+ };
|
||||
+
|
||||
+ int do_delay = 0;
|
||||
+ int do_playback = 0;
|
||||
+ int do_capture = 0;
|
||||
+ int type = 0;
|
||||
+
|
||||
+ while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) {
|
||||
+ switch (c) {
|
||||
+ case 'h':
|
||||
+ usage(command);
|
||||
+ return 0;
|
||||
+ case 'p':
|
||||
+ do_playback = 1;
|
||||
+ break;
|
||||
+ case 'c':
|
||||
+ do_capture = 1;
|
||||
+ break;
|
||||
+ case 'd':
|
||||
+ do_delay = 1;
|
||||
+ break;
|
||||
+ case 'D':
|
||||
+ pcm_name = optarg;
|
||||
+ break;
|
||||
+ case 't':
|
||||
+ type = atoi(optarg);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
- snd_pcm_hw_params_alloca(&hwparams_p);
|
||||
- /* get the current hwparams */
|
||||
- err = snd_pcm_hw_params_current(handle_p, hwparams_p);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to determine current hwparams_p: %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
- if (snd_pcm_hw_params_supports_audio_wallclock_ts(hwparams_p))
|
||||
- printf("Playback relies on audio wallclock timestamps\n");
|
||||
- else
|
||||
- printf("Playback relies on audio sample counter timestamps\n");
|
||||
-
|
||||
- snd_pcm_sw_params_alloca(&swparams_p);
|
||||
- /* get the current swparams */
|
||||
- err = snd_pcm_sw_params_current(handle_p, swparams_p);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to determine current swparams_p: %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
+ memset(&audio_tstamp_config_p, 0, sizeof(snd_pcm_audio_tstamp_config_t));
|
||||
+ memset(&audio_tstamp_config_c, 0, sizeof(snd_pcm_audio_tstamp_config_t));
|
||||
+ memset(&audio_tstamp_report_p, 0, sizeof(snd_pcm_audio_tstamp_report_t));
|
||||
+ memset(&audio_tstamp_report_c, 0, sizeof(snd_pcm_audio_tstamp_report_t));
|
||||
|
||||
- /* enable tstamp */
|
||||
- err = snd_pcm_sw_params_set_tstamp_mode(handle_p, swparams_p, SND_PCM_TSTAMP_ENABLE);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
+ if (do_playback) {
|
||||
+ if ((err = snd_pcm_open(&handle_p, pcm_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
||||
+ printf("Playback open error: %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
|
||||
- err = snd_pcm_sw_params_set_tstamp_type(handle_p, swparams_p, TSTAMP_TYPE);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to set tstamp type : %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
+ if ((err = snd_pcm_set_params(handle_p,
|
||||
+ SND_PCM_FORMAT_S16,
|
||||
+ SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
+ 2,
|
||||
+ SAMPLE_FREQ,
|
||||
+ 0,
|
||||
+ 4*1000000/TIMESTAMP_FREQ)) < 0) {
|
||||
+ printf("Playback open error: %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
|
||||
- /* write the sw parameters */
|
||||
- err = snd_pcm_sw_params(handle_p, swparams_p);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to set swparams_p : %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
+ snd_pcm_hw_params_alloca(&hwparams_p);
|
||||
+/* get the current hwparams */
|
||||
+ err = snd_pcm_hw_params_current(handle_p, hwparams_p);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to determine current hwparams_p: %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
|
||||
- if ((err = snd_pcm_open(&handle_c, device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
|
||||
- printf("Capture open error: %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
- if ((err = snd_pcm_set_params(handle_c,
|
||||
- SND_PCM_FORMAT_S16,
|
||||
- SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
- 2,
|
||||
- 48000,
|
||||
- 0,
|
||||
- 500000)) < 0) { /* 0.5sec */
|
||||
- printf("Capture open error: %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 0))
|
||||
+ printf("Playback supports audio compat timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 1))
|
||||
+ printf("Playback supports audio default timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 2))
|
||||
+ printf("Playback supports audio link timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 3))
|
||||
+ printf("Playback supports audio link absolute timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 4))
|
||||
+ printf("Playback supports audio link estimated timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, 5))
|
||||
+ printf("Playback supports audio link synchronized timestamps\n");
|
||||
+
|
||||
+ snd_pcm_sw_params_alloca(&swparams_p);
|
||||
+ /* get the current swparams */
|
||||
+ err = snd_pcm_sw_params_current(handle_p, swparams_p);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to determine current swparams_p: %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
|
||||
- snd_pcm_hw_params_alloca(&hwparams_c);
|
||||
- /* get the current hwparams */
|
||||
- err = snd_pcm_hw_params_current(handle_c, hwparams_c);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to determine current hwparams_c: %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
- if (snd_pcm_hw_params_supports_audio_wallclock_ts(hwparams_c))
|
||||
- printf("Capture relies on audio wallclock timestamps\n");
|
||||
- else
|
||||
- printf("Capture relies on audio sample counter timestamps\n");
|
||||
-
|
||||
- snd_pcm_sw_params_alloca(&swparams_c);
|
||||
- /* get the current swparams */
|
||||
- err = snd_pcm_sw_params_current(handle_c, swparams_c);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to determine current swparams_c: %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
+ /* enable tstamp */
|
||||
+ err = snd_pcm_sw_params_set_tstamp_mode(handle_p, swparams_p, SND_PCM_TSTAMP_ENABLE);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
|
||||
- /* enable tstamp */
|
||||
- err = snd_pcm_sw_params_set_tstamp_mode(handle_c, swparams_c, SND_PCM_TSTAMP_ENABLE);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
- }
|
||||
+ err = snd_pcm_sw_params_set_tstamp_type(handle_p, swparams_p, TSTAMP_TYPE);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to set tstamp type : %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+
|
||||
+ /* write the sw parameters */
|
||||
+ err = snd_pcm_sw_params(handle_p, swparams_p);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to set swparams_p : %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
|
||||
- err = snd_pcm_sw_params_set_tstamp_type(handle_c, swparams_c, TSTAMP_TYPE);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to set tstamp type : %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
}
|
||||
|
||||
- /* write the sw parameters */
|
||||
- err = snd_pcm_sw_params(handle_c, swparams_c);
|
||||
- if (err < 0) {
|
||||
- printf("Unable to set swparams_c : %s\n", snd_strerror(err));
|
||||
- goto _exit;
|
||||
+ if (do_capture) {
|
||||
+
|
||||
+ if ((err = snd_pcm_open(&handle_c, pcm_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
|
||||
+ printf("Capture open error: %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+ if ((err = snd_pcm_set_params(handle_c,
|
||||
+ SND_PCM_FORMAT_S16,
|
||||
+ SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
+ 2,
|
||||
+ SAMPLE_FREQ,
|
||||
+ 0,
|
||||
+ 4*1000000/TIMESTAMP_FREQ)) < 0) {
|
||||
+ printf("Capture open error: %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+
|
||||
+ snd_pcm_hw_params_alloca(&hwparams_c);
|
||||
+ /* get the current hwparams */
|
||||
+ err = snd_pcm_hw_params_current(handle_c, hwparams_c);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to determine current hwparams_c: %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 0))
|
||||
+ printf("Capture supports audio compat timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 1))
|
||||
+ printf("Capture supports audio default timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 2))
|
||||
+ printf("Capture supports audio link timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 3))
|
||||
+ printf("Capture supports audio link absolute timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 4))
|
||||
+ printf("Capture supports audio link estimated timestamps\n");
|
||||
+ if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, 5))
|
||||
+ printf("Capture supports audio link synchronized timestamps\n");
|
||||
+
|
||||
+ snd_pcm_sw_params_alloca(&swparams_c);
|
||||
+ /* get the current swparams */
|
||||
+ err = snd_pcm_sw_params_current(handle_c, swparams_c);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to determine current swparams_c: %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+
|
||||
+ /* enable tstamp */
|
||||
+ err = snd_pcm_sw_params_set_tstamp_mode(handle_c, swparams_c, SND_PCM_TSTAMP_ENABLE);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+
|
||||
+ err = snd_pcm_sw_params_set_tstamp_type(handle_c, swparams_c, TSTAMP_TYPE);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to set tstamp type : %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+
|
||||
+ /* write the sw parameters */
|
||||
+ err = snd_pcm_sw_params(handle_c, swparams_c);
|
||||
+ if (err < 0) {
|
||||
+ printf("Unable to set swparams_c : %s\n", snd_strerror(err));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ if (do_playback && do_capture) {
|
||||
#ifdef PCM_LINK
|
||||
- if ((err = snd_pcm_link(handle_c, handle_p)) < 0) {
|
||||
- printf("Streams link error: %s\n", snd_strerror(err));
|
||||
- exit(0);
|
||||
- }
|
||||
+ if ((err = snd_pcm_link(handle_c, handle_p)) < 0) {
|
||||
+ printf("Streams link error: %s\n", snd_strerror(err));
|
||||
+ exit(0);
|
||||
+ }
|
||||
#endif
|
||||
-
|
||||
- i = PLAYBACK_BUFFERS;
|
||||
- while (i--) {
|
||||
- frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
|
||||
- if (frames < 0) {
|
||||
- printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
|
||||
- goto _exit;
|
||||
- }
|
||||
- frame_count_p += frames;
|
||||
}
|
||||
|
||||
- if (PLAYBACK_BUFFERS != 4)
|
||||
- snd_pcm_start(handle_p);
|
||||
+ if (do_playback) {
|
||||
+ i = PLAYBACK_BUFFERS;
|
||||
+ while (i--) {
|
||||
+ frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
|
||||
+ if (frames < 0) {
|
||||
+ printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+ frame_count_p += frames;
|
||||
+ }
|
||||
+
|
||||
+ if (PLAYBACK_BUFFERS != 4)
|
||||
+ snd_pcm_start(handle_p);
|
||||
+ }
|
||||
|
||||
+ if (do_capture) {
|
||||
#ifndef PCM_LINK
|
||||
- /* need to start capture explicitly */
|
||||
- snd_pcm_start(handle_c);
|
||||
+ /* need to start capture explicitly */
|
||||
+ snd_pcm_start(handle_c);
|
||||
+#else
|
||||
+ if (!do_playback)
|
||||
+ /* need to start capture explicitly */
|
||||
+ snd_pcm_start(handle_c);
|
||||
#endif
|
||||
+ }
|
||||
|
||||
- while (1) {
|
||||
-
|
||||
- frames = snd_pcm_wait(handle_c, -1);
|
||||
- if (frames < 0) {
|
||||
- printf("snd_pcm_wait failed: %s\n", snd_strerror(frames));
|
||||
- goto _exit;
|
||||
- }
|
||||
-
|
||||
- frames = snd_pcm_readi(handle_c, buffer_c, PERIOD);
|
||||
- if (frames < 0) {
|
||||
- printf("snd_pcm_readi failed: %s\n", snd_strerror(frames));
|
||||
- goto _exit;
|
||||
- }
|
||||
- frame_count_c += frames;
|
||||
+ while (1) {
|
||||
|
||||
- frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
|
||||
- if (frames < 0) {
|
||||
- printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
|
||||
- goto _exit;
|
||||
- }
|
||||
+ if (do_capture) {
|
||||
|
||||
- frame_count_p += frames;
|
||||
+ frames = snd_pcm_wait(handle_c, -1);
|
||||
+ if (frames < 0) {
|
||||
+ printf("snd_pcm_wait failed: %s\n", snd_strerror(frames));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
|
||||
-#if defined(TRACK_PLAYBACK)
|
||||
- gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, &audio_tstamp_p, &avail_p, &delay_p);
|
||||
+ frames = snd_pcm_readi(handle_c, buffer_c, PERIOD);
|
||||
+ if (frames < 0) {
|
||||
+ printf("snd_pcm_readi failed: %s\n", snd_strerror(frames));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
+ frame_count_c += frames;
|
||||
|
||||
+#if defined(TRACK_CAPTURE)
|
||||
+ audio_tstamp_config_c.type_requested = type;
|
||||
+ audio_tstamp_config_c.report_delay = do_delay;
|
||||
+ _gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c,
|
||||
+ &audio_tstamp_c, &audio_tstamp_config_c, &audio_tstamp_report_c,
|
||||
+ &avail_c, &delay_c);
|
||||
#if defined(TRACK_SAMPLE_COUNTS)
|
||||
- curr_count_p = frame_count_p - delay_p; /* written minus queued */
|
||||
+ curr_count_c = frame_count_c + delay_c; /* read plus queued */
|
||||
|
||||
- printf("playback: curr_count %lli driver count %lli, delta %lli\n",
|
||||
- (long long)curr_count_p * 1000000000LL / 48000 ,
|
||||
- timestamp2ns(audio_tstamp_p),
|
||||
- (long long)curr_count_p * 1000000000LL / 48000 - timestamp2ns(audio_tstamp_p)
|
||||
- );
|
||||
+
|
||||
+ printf("capture: curr_count %lli driver count %lli, delta %lli\n",
|
||||
+ (long long)curr_count_c * 1000000000LL / SAMPLE_FREQ ,
|
||||
+ timestamp2ns(audio_tstamp_c),
|
||||
+ (long long)curr_count_c * 1000000000LL / SAMPLE_FREQ - timestamp2ns(audio_tstamp_c)
|
||||
+ );
|
||||
#endif
|
||||
|
||||
- printf("playback: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
|
||||
- timediff(tstamp_p, trigger_tstamp_p),
|
||||
- timestamp2ns(audio_tstamp_p),
|
||||
- timediff(tstamp_p, trigger_tstamp_p) - timestamp2ns(audio_tstamp_p)
|
||||
- );
|
||||
+ printf("\t capture: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
|
||||
+ timediff(tstamp_c, trigger_tstamp_c),
|
||||
+ timestamp2ns(audio_tstamp_c),
|
||||
+ timediff(tstamp_c, trigger_tstamp_c) - timestamp2ns(audio_tstamp_c)
|
||||
+ );
|
||||
#endif
|
||||
+ }
|
||||
|
||||
-#if defined(TRACK_CAPTURE)
|
||||
- gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, &audio_tstamp_c, &avail_c, &delay_c);
|
||||
+ if (do_playback) {
|
||||
+ frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
|
||||
+ if (frames < 0) {
|
||||
+ printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
|
||||
+ goto _exit;
|
||||
+ }
|
||||
|
||||
-#if defined(TRACK_SAMPLE_COUNTS)
|
||||
- curr_count_c = frame_count_c + delay_c; /* read plus queued */
|
||||
+ frame_count_p += frames;
|
||||
+
|
||||
+#if defined(TRACK_PLAYBACK)
|
||||
|
||||
+ audio_tstamp_config_p.type_requested = type;
|
||||
+ audio_tstamp_config_p.report_delay = do_delay;
|
||||
+ _gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p,
|
||||
+ &audio_tstamp_p, &audio_tstamp_config_p, &audio_tstamp_report_p,
|
||||
+ &avail_p, &delay_p);
|
||||
|
||||
- printf("capture: curr_count %lli driver count %lli, delta %lli\n",
|
||||
- (long long)curr_count_c * 1000000000LL / 48000 ,
|
||||
- timestamp2ns(audio_tstamp_c),
|
||||
- (long long)curr_count_c * 1000000000LL / 48000 - timestamp2ns(audio_tstamp_c)
|
||||
- );
|
||||
+#if defined(TRACK_SAMPLE_COUNTS)
|
||||
+ curr_count_p = frame_count_p - delay_p; /* written minus queued */
|
||||
+
|
||||
+ printf("playback: curr_count %lli driver count %lli, delta %lli\n",
|
||||
+ (long long)curr_count_p * 1000000000LL / SAMPLE_FREQ ,
|
||||
+ timestamp2ns(audio_tstamp_p),
|
||||
+ (long long)curr_count_p * 1000000000LL / SAMPLE_FREQ - timestamp2ns(audio_tstamp_p)
|
||||
+ );
|
||||
#endif
|
||||
|
||||
- printf("\t capture: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
|
||||
- timediff(tstamp_c, trigger_tstamp_c),
|
||||
- timestamp2ns(audio_tstamp_c),
|
||||
- timediff(tstamp_c, trigger_tstamp_c) - timestamp2ns(audio_tstamp_c)
|
||||
- );
|
||||
+ printf("playback: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
|
||||
+ timediff(tstamp_p, trigger_tstamp_p),
|
||||
+ timestamp2ns(audio_tstamp_p),
|
||||
+ timediff(tstamp_p, trigger_tstamp_p) - timestamp2ns(audio_tstamp_p)
|
||||
+ );
|
||||
#endif
|
||||
+ }
|
||||
+
|
||||
|
||||
- }
|
||||
+ } /* while(1) */
|
||||
|
||||
_exit:
|
||||
if (handle_p)
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,106 +0,0 @@
|
||||
From 6849d7dc88e0fe22cddb6b2d06ddc967ad4c3a6c Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Date: Wed, 1 Jul 2015 15:40:58 -0500
|
||||
Subject: [PATCH 32/49] test: audio_time: show report validity and accuracy
|
||||
|
||||
Add checks to show if driver reports valid report and resolution
|
||||
information. disabled by default
|
||||
|
||||
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
test/audio_time.c | 30 +++++++++++++++++++++++++-----
|
||||
1 file changed, 25 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/test/audio_time.c b/test/audio_time.c
|
||||
index e369e59b4ff2..a54c10dc9ebd 100644
|
||||
--- a/test/audio_time.c
|
||||
+++ b/test/audio_time.c
|
||||
@@ -33,6 +33,7 @@ static void usage(char *command)
|
||||
"-D, --device=NAME select PCM by name \n"
|
||||
"-p, --playback playback tstamps \n"
|
||||
"-t, --ts_type=TYPE Default(0),link(1),link_estimated(2),synchronized(3) \n"
|
||||
+ "-r, --report show audio timestamp and accuracy validity\n"
|
||||
, command);
|
||||
}
|
||||
|
||||
@@ -128,7 +129,7 @@ int main(int argc, char *argv[])
|
||||
snd_pcm_audio_tstamp_report_t audio_tstamp_report_c;
|
||||
|
||||
int option_index;
|
||||
- static const char short_options[] = "hcpdD:t:";
|
||||
+ static const char short_options[] = "hcpdrD:t:";
|
||||
|
||||
static const struct option long_options[] = {
|
||||
{"capture", 0, 0, 'c'},
|
||||
@@ -137,6 +138,7 @@ int main(int argc, char *argv[])
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"playback", 0, 0, 'p'},
|
||||
{"ts_type", required_argument, 0, 't'},
|
||||
+ {"report", 0, 0, 'r'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -144,6 +146,7 @@ int main(int argc, char *argv[])
|
||||
int do_playback = 0;
|
||||
int do_capture = 0;
|
||||
int type = 0;
|
||||
+ int do_report = 0;
|
||||
|
||||
while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
@@ -165,6 +168,8 @@ int main(int argc, char *argv[])
|
||||
case 't':
|
||||
type = atoi(optarg);
|
||||
break;
|
||||
+ case 'r':
|
||||
+ do_report = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,11 +381,19 @@ int main(int argc, char *argv[])
|
||||
(long long)curr_count_c * 1000000000LL / SAMPLE_FREQ - timestamp2ns(audio_tstamp_c)
|
||||
);
|
||||
#endif
|
||||
+ if (do_report) {
|
||||
+ if (audio_tstamp_report_c.valid == 0)
|
||||
+ printf("Audio capture timestamp report invalid - ");
|
||||
+ if (audio_tstamp_report_c.accuracy_report == 0)
|
||||
+ printf("Audio capture timestamp accuracy report invalid");
|
||||
+ printf("\n");
|
||||
+ }
|
||||
+
|
||||
|
||||
- printf("\t capture: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
|
||||
+ printf("\t capture: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli \t resolution %d ns \n",
|
||||
timediff(tstamp_c, trigger_tstamp_c),
|
||||
timestamp2ns(audio_tstamp_c),
|
||||
- timediff(tstamp_c, trigger_tstamp_c) - timestamp2ns(audio_tstamp_c)
|
||||
+ timediff(tstamp_c, trigger_tstamp_c) - timestamp2ns(audio_tstamp_c), audio_tstamp_report_c.accuracy
|
||||
);
|
||||
#endif
|
||||
}
|
||||
@@ -411,11 +424,18 @@ int main(int argc, char *argv[])
|
||||
(long long)curr_count_p * 1000000000LL / SAMPLE_FREQ - timestamp2ns(audio_tstamp_p)
|
||||
);
|
||||
#endif
|
||||
+ if (do_report) {
|
||||
+ if (audio_tstamp_report_p.valid == 0)
|
||||
+ printf("Audio playback timestamp report invalid - ");
|
||||
+ if (audio_tstamp_report_p.accuracy_report == 0)
|
||||
+ printf("Audio playback timestamp accuracy report invalid");
|
||||
+ printf("\n");
|
||||
+ }
|
||||
|
||||
- printf("playback: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
|
||||
+ printf("playback: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli resolution %d ns\n",
|
||||
timediff(tstamp_p, trigger_tstamp_p),
|
||||
timestamp2ns(audio_tstamp_p),
|
||||
- timediff(tstamp_p, trigger_tstamp_p) - timestamp2ns(audio_tstamp_p)
|
||||
+ timediff(tstamp_p, trigger_tstamp_p) - timestamp2ns(audio_tstamp_p), audio_tstamp_report_p.accuracy
|
||||
);
|
||||
#endif
|
||||
}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,44 +0,0 @@
|
||||
From 77b6be63876ee46a95320e77735d977edeedd44a Mon Sep 17 00:00:00 2001
|
||||
From: Martin Geier <martin.geier@streamunlimited.com>
|
||||
Date: Fri, 24 Jul 2015 09:30:57 +0200
|
||||
Subject: [PATCH 33/49] pcm: restore hw params on set latency failed
|
||||
|
||||
When method snd_pcm_set_params sets sample rate to 22050 and latency to 50000
|
||||
to davinci soc driver method snd_pcm_hw_params_set_buffer_time_near fails
|
||||
and variable params is already changed in the method so the next method
|
||||
snd_pcm_hw_params_set_period_time_near fails also.
|
||||
|
||||
Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
||||
index bae1d1653904..f5fc728518d8 100644
|
||||
--- a/src/pcm/pcm.c
|
||||
+++ b/src/pcm/pcm.c
|
||||
@@ -8004,7 +8004,7 @@ int snd_pcm_set_params(snd_pcm_t *pcm,
|
||||
int soft_resample,
|
||||
unsigned int latency)
|
||||
{
|
||||
- snd_pcm_hw_params_t *params;
|
||||
+ snd_pcm_hw_params_t *params, params_saved;
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
const char *s = snd_pcm_stream_name(snd_pcm_stream(pcm));
|
||||
snd_pcm_uframes_t buffer_size, period_size;
|
||||
@@ -8057,9 +8057,11 @@ int snd_pcm_set_params(snd_pcm_t *pcm,
|
||||
return -EINVAL;
|
||||
}
|
||||
/* set the buffer time */
|
||||
+ params_saved = *params;
|
||||
err = INTERNAL(snd_pcm_hw_params_set_buffer_time_near)(pcm, params, &latency, NULL);
|
||||
if (err < 0) {
|
||||
/* error path -> set period size as first */
|
||||
+ *params = params_saved;
|
||||
/* set the period time */
|
||||
period_time = latency / 4;
|
||||
err = INTERNAL(snd_pcm_hw_params_set_period_time_near)(pcm, params, &period_time, NULL);
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,274 +0,0 @@
|
||||
From d0e13f87742e923edfb638d4b16b69b8dc2136d8 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Mon, 27 Jul 2015 12:32:37 +0200
|
||||
Subject: [PATCH 34/49] Replace list.h with its own version
|
||||
|
||||
We copied include/list.h from Linux kernel, and it's of course in
|
||||
GPLv2. This has raised concerns to many people, as it's not clear
|
||||
whether such a code is considered to be completely trivial, thus it
|
||||
might be seen as a derivative work, which takes effect in GPL, as
|
||||
suggested by Clemens.
|
||||
|
||||
For clearing the situation, this patch replaces the existing list.h
|
||||
implementation from a new version. The API is kept to be compatible,
|
||||
but the codes were written from full scratch under LGPL, to be aligned
|
||||
with other alsa-lib codes.
|
||||
|
||||
Reported-by: Clemens Lang <clemens.lang@bmw-carit.de>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/list.h | 212 +++++++++++++++++++--------------------------------------
|
||||
1 file changed, 70 insertions(+), 142 deletions(-)
|
||||
|
||||
diff --git a/include/list.h b/include/list.h
|
||||
index 4d9895feba05..947c1f8411e2 100644
|
||||
--- a/include/list.h
|
||||
+++ b/include/list.h
|
||||
@@ -1,174 +1,102 @@
|
||||
+/* Doubly linked list macros compatible with Linux kernel's version
|
||||
+ * Copyright (c) 2015 by Takashi Iwai <tiwai@suse.de>
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU Lesser General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2.1 of
|
||||
+ * the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU Lesser General Public License for more details.
|
||||
+ */
|
||||
+
|
||||
#ifndef _LIST_H
|
||||
#define _LIST_H
|
||||
|
||||
-/*
|
||||
- * This code was taken from the Linux 2.4.0 kernel. [jaroslav]
|
||||
- */
|
||||
+#include <stddef.h>
|
||||
|
||||
-/*
|
||||
- * Simple doubly linked list implementation.
|
||||
- *
|
||||
- * Some of the internal functions ("__xxx") are useful when
|
||||
- * manipulating whole lists rather than single entries, as
|
||||
- * sometimes we already know the next/prev entries and we can
|
||||
- * generate better code by using them directly rather than
|
||||
- * using the generic single-entry routines.
|
||||
- */
|
||||
-
|
||||
-#ifndef LIST_HEAD_IS_DEFINED
|
||||
struct list_head {
|
||||
- struct list_head *next, *prev;
|
||||
+ struct list_head *next;
|
||||
+ struct list_head *prev;
|
||||
};
|
||||
-#endif
|
||||
-
|
||||
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
-#define LIST_HEAD(name) \
|
||||
- struct list_head name = LIST_HEAD_INIT(name)
|
||||
+/* one-shot definition of a list head */
|
||||
+#define LIST_HEAD(x) \
|
||||
+ struct list_head x = { &x, &x }
|
||||
|
||||
-#define INIT_LIST_HEAD(ptr) do { \
|
||||
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
-} while (0)
|
||||
-
|
||||
-/*
|
||||
- * Insert a new entry between two known consecutive entries.
|
||||
- *
|
||||
- * This is only for internal list manipulation where we know
|
||||
- * the prev/next entries already!
|
||||
- */
|
||||
-static __inline__ void __list_add(struct list_head * _new,
|
||||
- struct list_head * prev,
|
||||
- struct list_head * next)
|
||||
+/* initialize a list head explicitly */
|
||||
+static inline void INIT_LIST_HEAD(struct list_head *p)
|
||||
{
|
||||
- next->prev = _new;
|
||||
- _new->next = next;
|
||||
- _new->prev = prev;
|
||||
- prev->next = _new;
|
||||
+ p->next = p->prev = p;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * list_add - add a new entry
|
||||
- * @new: new entry to be added
|
||||
- * @head: list head to add it after
|
||||
- *
|
||||
- * Insert a new entry after the specified head.
|
||||
- * This is good for implementing stacks.
|
||||
+#define list_entry_offset(p, type, offset) \
|
||||
+ ((type *)((char *)(p) - (offset)))
|
||||
+
|
||||
+/* list_entry - retrieve the original struct from list_head
|
||||
+ * @p: list_head pointer
|
||||
+ * @type: struct type
|
||||
+ * @member: struct field member containing the list_head
|
||||
*/
|
||||
-static __inline__ void list_add(struct list_head *_new, struct list_head *head)
|
||||
-{
|
||||
- __list_add(_new, head, head->next);
|
||||
-}
|
||||
+#define list_entry(p, type, member) \
|
||||
+ list_entry_offset(p, type, offsetof(type, member))
|
||||
|
||||
-/**
|
||||
- * list_add_tail - add a new entry
|
||||
- * @new: new entry to be added
|
||||
- * @head: list head to add it before
|
||||
- *
|
||||
- * Insert a new entry before the specified head.
|
||||
- * This is useful for implementing queues.
|
||||
+/* list_for_each - iterate over the linked list
|
||||
+ * @p: iterator, a list_head pointer variable
|
||||
+ * @list: list_head pointer containing the list
|
||||
*/
|
||||
-static __inline__ void list_add_tail(struct list_head *_new, struct list_head *head)
|
||||
-{
|
||||
- __list_add(_new, head->prev, head);
|
||||
-}
|
||||
+#define list_for_each(p, list) \
|
||||
+ for (p = (list)->next; p != (list); p = p->next)
|
||||
|
||||
-/*
|
||||
- * Delete a list entry by making the prev/next entries
|
||||
- * point to each other.
|
||||
- *
|
||||
- * This is only for internal list manipulation where we know
|
||||
- * the prev/next entries already!
|
||||
+/* list_for_each_safe - iterate over the linked list, safe to delete
|
||||
+ * @p: iterator, a list_head pointer variable
|
||||
+ * @s: a temporary variable to keep the next, a list_head pointer, too
|
||||
+ * @list: list_head pointer containing the list
|
||||
*/
|
||||
-static __inline__ void __list_del(struct list_head * prev,
|
||||
- struct list_head * next)
|
||||
-{
|
||||
- next->prev = prev;
|
||||
- prev->next = next;
|
||||
-}
|
||||
+#define list_for_each_safe(p, s, list) \
|
||||
+ for (p = (list)->next; s = p->next, p != (list); p = s)
|
||||
|
||||
-/**
|
||||
- * list_del - deletes entry from list.
|
||||
- * @entry: the element to delete from the list.
|
||||
- * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||
+/* list_add - prepend a list entry at the head
|
||||
+ * @p: the new list entry to add
|
||||
+ * @list: the list head
|
||||
*/
|
||||
-static __inline__ void list_del(struct list_head *entry)
|
||||
+static inline void list_add(struct list_head *p, struct list_head *list)
|
||||
{
|
||||
- __list_del(entry->prev, entry->next);
|
||||
+ struct list_head *first = list->next;
|
||||
+
|
||||
+ p->next = first;
|
||||
+ first->prev = p;
|
||||
+ list->next = p;
|
||||
+ p->prev = list;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * list_del_init - deletes entry from list and reinitialize it.
|
||||
- * @entry: the element to delete from the list.n
|
||||
+/* list_add_tail - append a list entry at the tail
|
||||
+ * @p: the new list entry to add
|
||||
+ * @list: the list head
|
||||
*/
|
||||
-static __inline__ void list_del_init(struct list_head *entry)
|
||||
+static inline void list_add_tail(struct list_head *p, struct list_head *list)
|
||||
{
|
||||
- __list_del(entry->prev, entry->next);
|
||||
- INIT_LIST_HEAD(entry);
|
||||
+ struct list_head *last = list->prev;
|
||||
+
|
||||
+ last->next = p;
|
||||
+ p->prev = last;
|
||||
+ p->next = list;
|
||||
+ list->prev = p;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * list_empty - tests whether a list is empty
|
||||
- * @head: the list to test.
|
||||
- */
|
||||
-static __inline__ int list_empty(struct list_head *head)
|
||||
+/* list_del - delete the given list entry */
|
||||
+static inline void list_del(struct list_head *p)
|
||||
{
|
||||
- return head->next == head;
|
||||
+ p->prev->next = p->next;
|
||||
+ p->next->prev = p->prev;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * list_splice - join two lists
|
||||
- * @list: the new list to add.
|
||||
- * @head: the place to add it in the first list.
|
||||
- */
|
||||
-static __inline__ void list_splice(struct list_head *list, struct list_head *head)
|
||||
+/* list_empty - returns 1 if the given list is empty */
|
||||
+static inline int list_empty(const struct list_head *p)
|
||||
{
|
||||
- struct list_head *first = list->next;
|
||||
-
|
||||
- if (first != list) {
|
||||
- struct list_head *last = list->prev;
|
||||
- struct list_head *at = head->next;
|
||||
-
|
||||
- first->prev = head;
|
||||
- head->next = first;
|
||||
-
|
||||
- last->next = at;
|
||||
- at->prev = last;
|
||||
- }
|
||||
+ return p->next == p;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * list_for_each - iterate over a list
|
||||
- * @pos: the &struct list_head to use as a loop counter.
|
||||
- * @head: the head for your list.
|
||||
- */
|
||||
-#define list_for_each(pos, head) \
|
||||
- for (pos = (head)->next ; pos != (head); pos = pos->next)
|
||||
-
|
||||
-/**
|
||||
- * list_for_each_safe - iterate over a list safely (actual pointer can be invalidated)
|
||||
- * @pos: the &struct list_head to use as a loop counter.
|
||||
- * @next: the &struct list_head to use to save next.
|
||||
- * @head: the head for your list.
|
||||
- */
|
||||
-#define list_for_each_safe(pos, npos, head) \
|
||||
- for (pos = (head)->next, npos = pos->next ; pos != (head); pos = npos, npos = pos->next)
|
||||
-
|
||||
-/**
|
||||
- * list_entry - get the struct for this entry
|
||||
- * @ptr: the &struct list_head pointer.
|
||||
- * @type: the type of the struct this is embedded in.
|
||||
- * @member: the name of the list_struct within the struct.
|
||||
- */
|
||||
-#define list_entry(ptr, type, member) \
|
||||
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
-
|
||||
-/**
|
||||
- * list_entry - get the struct for this entry
|
||||
- * @ptr: the &struct list_head pointer.
|
||||
- * @type: the type of the struct this is embedded in.
|
||||
- * @offset: offset of entry inside a struct
|
||||
- */
|
||||
-#define list_entry_offset(ptr, type, offset) \
|
||||
- ((type *)((char *)(ptr)-(offset)))
|
||||
-
|
||||
#endif /* _LIST_H */
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,454 +0,0 @@
|
||||
From 227c790c16db17a986df06c9a3ad79edade78db7 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:13 +0100
|
||||
Subject: [PATCH 35/49] topology: uapi: Add UAPI headers for topology ABI
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/sound/Makefile.am | 3 +-
|
||||
include/sound/asoc.h | 388 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
include/sound/tlv.h | 23 +++
|
||||
3 files changed, 413 insertions(+), 1 deletion(-)
|
||||
create mode 100644 include/sound/asoc.h
|
||||
create mode 100644 include/sound/tlv.h
|
||||
|
||||
diff --git a/include/sound/Makefile.am b/include/sound/Makefile.am
|
||||
index 31aa2db43d27..b659985e7e36 100644
|
||||
--- a/include/sound/Makefile.am
|
||||
+++ b/include/sound/Makefile.am
|
||||
@@ -1,6 +1,7 @@
|
||||
alsasoundincludedir = ${includedir}/alsa/sound
|
||||
|
||||
alsasoundinclude_HEADERS = asound_fm.h hdsp.h hdspm.h sb16_csp.h \
|
||||
- sscape_ioctl.h emu10k1.h type_compat.h
|
||||
+ sscape_ioctl.h emu10k1.h type_compat.h \
|
||||
+ asoc.h tlv.h
|
||||
|
||||
noinst_HEADERS = asound.h asoundef.h asequencer.h
|
||||
diff --git a/include/sound/asoc.h b/include/sound/asoc.h
|
||||
new file mode 100644
|
||||
index 000000000000..bb6dcf3ff7b4
|
||||
--- /dev/null
|
||||
+++ b/include/sound/asoc.h
|
||||
@@ -0,0 +1,388 @@
|
||||
+/*
|
||||
+ * uapi/sound/asoc.h -- ALSA SoC Firmware Controls and DAPM
|
||||
+ *
|
||||
+ * Copyright (C) 2012 Texas Instruments Inc.
|
||||
+ * Copyright (C) 2015 Intel Corporation.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * Simple file API to load FW that includes mixers, coefficients, DAPM graphs,
|
||||
+ * algorithms, equalisers, DAIs, widgets etc.
|
||||
+*/
|
||||
+
|
||||
+#ifndef __LINUX_UAPI_SND_ASOC_H
|
||||
+#define __LINUX_UAPI_SND_ASOC_H
|
||||
+
|
||||
+/*
|
||||
+ * Maximum number of channels topology kcontrol can represent.
|
||||
+ */
|
||||
+#define SND_SOC_TPLG_MAX_CHAN 8
|
||||
+
|
||||
+/*
|
||||
+ * Maximum number of PCM formats capability
|
||||
+ */
|
||||
+#define SND_SOC_TPLG_MAX_FORMATS 16
|
||||
+
|
||||
+/*
|
||||
+ * Maximum number of PCM stream configs
|
||||
+ */
|
||||
+#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8
|
||||
+
|
||||
+/* individual kcontrol info types - can be mixed with other types */
|
||||
+#define SND_SOC_TPLG_CTL_VOLSW 1
|
||||
+#define SND_SOC_TPLG_CTL_VOLSW_SX 2
|
||||
+#define SND_SOC_TPLG_CTL_VOLSW_XR_SX 3
|
||||
+#define SND_SOC_TPLG_CTL_ENUM 4
|
||||
+#define SND_SOC_TPLG_CTL_BYTES 5
|
||||
+#define SND_SOC_TPLG_CTL_ENUM_VALUE 6
|
||||
+#define SND_SOC_TPLG_CTL_RANGE 7
|
||||
+#define SND_SOC_TPLG_CTL_STROBE 8
|
||||
+
|
||||
+
|
||||
+/* individual widget kcontrol info types - can be mixed with other types */
|
||||
+#define SND_SOC_TPLG_DAPM_CTL_VOLSW 64
|
||||
+#define SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE 65
|
||||
+#define SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT 66
|
||||
+#define SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE 67
|
||||
+#define SND_SOC_TPLG_DAPM_CTL_PIN 68
|
||||
+
|
||||
+/* DAPM widget types - add new items to the end */
|
||||
+#define SND_SOC_TPLG_DAPM_INPUT 0
|
||||
+#define SND_SOC_TPLG_DAPM_OUTPUT 1
|
||||
+#define SND_SOC_TPLG_DAPM_MUX 2
|
||||
+#define SND_SOC_TPLG_DAPM_MIXER 3
|
||||
+#define SND_SOC_TPLG_DAPM_PGA 4
|
||||
+#define SND_SOC_TPLG_DAPM_OUT_DRV 5
|
||||
+#define SND_SOC_TPLG_DAPM_ADC 6
|
||||
+#define SND_SOC_TPLG_DAPM_DAC 7
|
||||
+#define SND_SOC_TPLG_DAPM_SWITCH 8
|
||||
+#define SND_SOC_TPLG_DAPM_PRE 9
|
||||
+#define SND_SOC_TPLG_DAPM_POST 10
|
||||
+#define SND_SOC_TPLG_DAPM_AIF_IN 11
|
||||
+#define SND_SOC_TPLG_DAPM_AIF_OUT 12
|
||||
+#define SND_SOC_TPLG_DAPM_DAI_IN 13
|
||||
+#define SND_SOC_TPLG_DAPM_DAI_OUT 14
|
||||
+#define SND_SOC_TPLG_DAPM_DAI_LINK 15
|
||||
+#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DAI_LINK
|
||||
+
|
||||
+/* Header magic number and string sizes */
|
||||
+#define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */
|
||||
+
|
||||
+/* string sizes */
|
||||
+#define SND_SOC_TPLG_NUM_TEXTS 16
|
||||
+
|
||||
+/* ABI version */
|
||||
+#define SND_SOC_TPLG_ABI_VERSION 0x3
|
||||
+
|
||||
+/* Max size of TLV data */
|
||||
+#define SND_SOC_TPLG_TLV_SIZE 32
|
||||
+
|
||||
+/*
|
||||
+ * File and Block header data types.
|
||||
+ * Add new generic and vendor types to end of list.
|
||||
+ * Generic types are handled by the core whilst vendors types are passed
|
||||
+ * to the component drivers for handling.
|
||||
+ */
|
||||
+#define SND_SOC_TPLG_TYPE_MIXER 1
|
||||
+#define SND_SOC_TPLG_TYPE_BYTES 2
|
||||
+#define SND_SOC_TPLG_TYPE_ENUM 3
|
||||
+#define SND_SOC_TPLG_TYPE_DAPM_GRAPH 4
|
||||
+#define SND_SOC_TPLG_TYPE_DAPM_WIDGET 5
|
||||
+#define SND_SOC_TPLG_TYPE_DAI_LINK 6
|
||||
+#define SND_SOC_TPLG_TYPE_PCM 7
|
||||
+#define SND_SOC_TPLG_TYPE_MANIFEST 8
|
||||
+#define SND_SOC_TPLG_TYPE_CODEC_LINK 9
|
||||
+#define SND_SOC_TPLG_TYPE_PDATA 10
|
||||
+#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_PDATA
|
||||
+
|
||||
+/* vendor block IDs - please add new vendor types to end */
|
||||
+#define SND_SOC_TPLG_TYPE_VENDOR_FW 1000
|
||||
+#define SND_SOC_TPLG_TYPE_VENDOR_CONFIG 1001
|
||||
+#define SND_SOC_TPLG_TYPE_VENDOR_COEFF 1002
|
||||
+#define SND_SOC_TPLG_TYPEVENDOR_CODEC 1003
|
||||
+
|
||||
+#define SND_SOC_TPLG_STREAM_PLAYBACK 0
|
||||
+#define SND_SOC_TPLG_STREAM_CAPTURE 1
|
||||
+
|
||||
+/*
|
||||
+ * Block Header.
|
||||
+ * This header precedes all object and object arrays below.
|
||||
+ */
|
||||
+struct snd_soc_tplg_hdr {
|
||||
+ __le32 magic; /* magic number */
|
||||
+ __le32 abi; /* ABI version */
|
||||
+ __le32 version; /* optional vendor specific version details */
|
||||
+ __le32 type; /* SND_SOC_TPLG_TYPE_ */
|
||||
+ __le32 size; /* size of this structure */
|
||||
+ __le32 vendor_type; /* optional vendor specific type info */
|
||||
+ __le32 payload_size; /* data bytes, excluding this header */
|
||||
+ __le32 index; /* identifier for block */
|
||||
+ __le32 count; /* number of elements in block */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Private data.
|
||||
+ * All topology objects may have private data that can be used by the driver or
|
||||
+ * firmware. Core will ignore this data.
|
||||
+ */
|
||||
+struct snd_soc_tplg_private {
|
||||
+ __le32 size; /* in bytes of private data */
|
||||
+ char data[0];
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Kcontrol TLV data.
|
||||
+ */
|
||||
+struct snd_soc_tplg_ctl_tlv {
|
||||
+ __le32 size; /* in bytes aligned to 4 */
|
||||
+ __le32 numid; /* control element numeric identification */
|
||||
+ __le32 count; /* number of elem in data array */
|
||||
+ __le32 data[SND_SOC_TPLG_TLV_SIZE];
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Kcontrol channel data
|
||||
+ */
|
||||
+struct snd_soc_tplg_channel {
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le32 reg;
|
||||
+ __le32 shift;
|
||||
+ __le32 id; /* ID maps to Left, Right, LFE etc */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Kcontrol Operations IDs
|
||||
+ */
|
||||
+struct snd_soc_tplg_kcontrol_ops_id {
|
||||
+ __le32 get;
|
||||
+ __le32 put;
|
||||
+ __le32 info;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * kcontrol header
|
||||
+ */
|
||||
+struct snd_soc_tplg_ctl_hdr {
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le32 type;
|
||||
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+ __le32 access;
|
||||
+ struct snd_soc_tplg_kcontrol_ops_id ops;
|
||||
+ __le32 tlv_size; /* non zero means control has TLV data */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Stream Capabilities
|
||||
+ */
|
||||
+struct snd_soc_tplg_stream_caps {
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+ __le64 formats[SND_SOC_TPLG_MAX_FORMATS]; /* supported formats SNDRV_PCM_FMTBIT_* */
|
||||
+ __le32 rates; /* supported rates SNDRV_PCM_RATE_* */
|
||||
+ __le32 rate_min; /* min rate */
|
||||
+ __le32 rate_max; /* max rate */
|
||||
+ __le32 channels_min; /* min channels */
|
||||
+ __le32 channels_max; /* max channels */
|
||||
+ __le32 periods_min; /* min number of periods */
|
||||
+ __le32 periods_max; /* max number of periods */
|
||||
+ __le32 period_size_min; /* min period size bytes */
|
||||
+ __le32 period_size_max; /* max period size bytes */
|
||||
+ __le32 buffer_size_min; /* min buffer size bytes */
|
||||
+ __le32 buffer_size_max; /* max buffer size bytes */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * FE or BE Stream configuration supported by SW/FW
|
||||
+ */
|
||||
+struct snd_soc_tplg_stream {
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le64 format; /* SNDRV_PCM_FMTBIT_* */
|
||||
+ __le32 rate; /* SNDRV_PCM_RATE_* */
|
||||
+ __le32 period_bytes; /* size of period in bytes */
|
||||
+ __le32 buffer_bytes; /* size of buffer in bytes */
|
||||
+ __le32 channels; /* channels */
|
||||
+ __le32 tdm_slot; /* optional BE bitmask of supported TDM slots */
|
||||
+ __le32 dai_fmt; /* SND_SOC_DAIFMT_ */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Duplex stream configuration supported by SW/FW.
|
||||
+ */
|
||||
+struct snd_soc_tplg_stream_config {
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+ struct snd_soc_tplg_stream playback;
|
||||
+ struct snd_soc_tplg_stream capture;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Manifest. List totals for each payload type. Not used in parsing, but will
|
||||
+ * be passed to the component driver before any other objects in order for any
|
||||
+ * global component resource allocations.
|
||||
+ *
|
||||
+ * File block representation for manifest :-
|
||||
+ * +-----------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_hdr | 1 |
|
||||
+ * +-----------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_manifest | 1 |
|
||||
+ * +-----------------------------------+----+
|
||||
+ */
|
||||
+struct snd_soc_tplg_manifest {
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le32 control_elems; /* number of control elements */
|
||||
+ __le32 widget_elems; /* number of widget elements */
|
||||
+ __le32 graph_elems; /* number of graph elements */
|
||||
+ __le32 dai_elems; /* number of DAI elements */
|
||||
+ __le32 dai_link_elems; /* number of DAI link elements */
|
||||
+ struct snd_soc_tplg_private priv;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Mixer kcontrol.
|
||||
+ *
|
||||
+ * File block representation for mixer kcontrol :-
|
||||
+ * +-----------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_hdr | 1 |
|
||||
+ * +-----------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_mixer_control | N |
|
||||
+ * +-----------------------------------+----+
|
||||
+ */
|
||||
+struct snd_soc_tplg_mixer_control {
|
||||
+ struct snd_soc_tplg_ctl_hdr hdr;
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le32 min;
|
||||
+ __le32 max;
|
||||
+ __le32 platform_max;
|
||||
+ __le32 invert;
|
||||
+ __le32 num_channels;
|
||||
+ struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
|
||||
+ struct snd_soc_tplg_ctl_tlv tlv;
|
||||
+ struct snd_soc_tplg_private priv;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Enumerated kcontrol
|
||||
+ *
|
||||
+ * File block representation for enum kcontrol :-
|
||||
+ * +-----------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_hdr | 1 |
|
||||
+ * +-----------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_enum_control | N |
|
||||
+ * +-----------------------------------+----+
|
||||
+ */
|
||||
+struct snd_soc_tplg_enum_control {
|
||||
+ struct snd_soc_tplg_ctl_hdr hdr;
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le32 num_channels;
|
||||
+ struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
|
||||
+ __le32 items;
|
||||
+ __le32 mask;
|
||||
+ __le32 count;
|
||||
+ char texts[SND_SOC_TPLG_NUM_TEXTS][SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+ __le32 values[SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN / 4];
|
||||
+ struct snd_soc_tplg_private priv;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Bytes kcontrol
|
||||
+ *
|
||||
+ * File block representation for bytes kcontrol :-
|
||||
+ * +-----------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_hdr | 1 |
|
||||
+ * +-----------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_bytes_control | N |
|
||||
+ * +-----------------------------------+----+
|
||||
+ */
|
||||
+struct snd_soc_tplg_bytes_control {
|
||||
+ struct snd_soc_tplg_ctl_hdr hdr;
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le32 max;
|
||||
+ __le32 mask;
|
||||
+ __le32 base;
|
||||
+ __le32 num_regs;
|
||||
+ struct snd_soc_tplg_private priv;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * DAPM Graph Element
|
||||
+ *
|
||||
+ * File block representation for DAPM graph elements :-
|
||||
+ * +-------------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_hdr | 1 |
|
||||
+ * +-------------------------------------+----+
|
||||
+ * | struct snd_soc_tplg_dapm_graph_elem | N |
|
||||
+ * +-------------------------------------+----+
|
||||
+ */
|
||||
+struct snd_soc_tplg_dapm_graph_elem {
|
||||
+ char sink[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+ char control[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+ char source[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * DAPM Widget.
|
||||
+ *
|
||||
+ * File block representation for DAPM widget :-
|
||||
+ * +-------------------------------------+-----+
|
||||
+ * | struct snd_soc_tplg_hdr | 1 |
|
||||
+ * +-------------------------------------+-----+
|
||||
+ * | struct snd_soc_tplg_dapm_widget | N |
|
||||
+ * +-------------------------------------+-----+
|
||||
+ * | struct snd_soc_tplg_enum_control | 0|1 |
|
||||
+ * | struct snd_soc_tplg_mixer_control | 0|N |
|
||||
+ * +-------------------------------------+-----+
|
||||
+ *
|
||||
+ * Optional enum or mixer control can be appended to the end of each widget
|
||||
+ * in the block.
|
||||
+ */
|
||||
+struct snd_soc_tplg_dapm_widget {
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le32 id; /* SND_SOC_DAPM_CTL */
|
||||
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+ char sname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+
|
||||
+ __le32 reg; /* negative reg = no direct dapm */
|
||||
+ __le32 shift; /* bits to shift */
|
||||
+ __le32 mask; /* non-shifted mask */
|
||||
+ __le32 subseq; /* sort within widget type */
|
||||
+ __u32 invert; /* invert the power bit */
|
||||
+ __u32 ignore_suspend; /* kept enabled over suspend */
|
||||
+ __u16 event_flags;
|
||||
+ __u16 event_type;
|
||||
+ __u16 num_kcontrols;
|
||||
+ struct snd_soc_tplg_private priv;
|
||||
+ /*
|
||||
+ * kcontrols that relate to this widget
|
||||
+ * follow here after widget private data
|
||||
+ */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+struct snd_soc_tplg_pcm_cfg_caps {
|
||||
+ struct snd_soc_tplg_stream_caps caps;
|
||||
+ struct snd_soc_tplg_stream_config configs[SND_SOC_TPLG_STREAM_CONFIG_MAX];
|
||||
+ __le32 num_configs; /* number of configs */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/*
|
||||
+ * Describes SW/FW specific features of PCM or DAI link.
|
||||
+ *
|
||||
+ * File block representation for PCM/DAI-Link :-
|
||||
+ * +-----------------------------------+-----+
|
||||
+ * | struct snd_soc_tplg_hdr | 1 |
|
||||
+ * +-----------------------------------+-----+
|
||||
+ * | struct snd_soc_tplg_dapm_pcm_dai | N |
|
||||
+ * +-----------------------------------+-----+
|
||||
+ */
|
||||
+struct snd_soc_tplg_pcm_dai {
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
+ __le32 id; /* unique ID - used to match */
|
||||
+ __le32 playback; /* supports playback mode */
|
||||
+ __le32 capture; /* supports capture mode */
|
||||
+ __le32 compress; /* 1 = compressed; 0 = PCM */
|
||||
+ struct snd_soc_tplg_pcm_cfg_caps capconf[2]; /* capabilities and configs */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+#endif
|
||||
diff --git a/include/sound/tlv.h b/include/sound/tlv.h
|
||||
new file mode 100644
|
||||
index 000000000000..33d747df1410
|
||||
--- /dev/null
|
||||
+++ b/include/sound/tlv.h
|
||||
@@ -0,0 +1,23 @@
|
||||
+/*
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __UAPI_SOUND_TLV_H
|
||||
+#define __UAPI_SOUND_TLV_H
|
||||
+
|
||||
+#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */
|
||||
+#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
|
||||
+#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */
|
||||
+#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */
|
||||
+#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 */
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
2.5.0
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,112 +0,0 @@
|
||||
From 408396a8ca092846c840baa79c04b5f7dbe5da69 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:15 +0100
|
||||
Subject: [PATCH 37/49] topology: Add text section parser.
|
||||
|
||||
Parse text lists (like enum values) and store for later attachment
|
||||
to other objects.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/text.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 88 insertions(+)
|
||||
create mode 100644 src/topology/text.c
|
||||
|
||||
diff --git a/src/topology/text.c b/src/topology/text.c
|
||||
new file mode 100644
|
||||
index 000000000000..ebb6e3840d62
|
||||
--- /dev/null
|
||||
+++ b/src/topology/text.c
|
||||
@@ -0,0 +1,88 @@
|
||||
+/*
|
||||
+ Copyright(c) 2014-2015 Intel Corporation
|
||||
+ All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ Authors: Mengdong Lin <mengdong.lin@intel.com>
|
||||
+ Yao Jin <yao.jin@intel.com>
|
||||
+ Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
+
|
||||
+*/
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "tplg_local.h"
|
||||
+
|
||||
+#define TEXT_SIZE_MAX \
|
||||
+ (SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
|
||||
+
|
||||
+static int parse_text_values(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *value = NULL;
|
||||
+ int j = 0;
|
||||
+
|
||||
+ tplg_dbg(" Text Values: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+
|
||||
+ if (j == SND_SOC_TPLG_NUM_TEXTS) {
|
||||
+ tplg_dbg("error: text string number exceeds %d\n", j);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ /* get value */
|
||||
+ if (snd_config_get_string(n, &value) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ elem_copy_text(&elem->texts[j][0], value,
|
||||
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ tplg_dbg("\t%s\n", &elem->texts[j][0]);
|
||||
+
|
||||
+ j++;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse Text data */
|
||||
+int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
+ void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id;
|
||||
+ int err = 0;
|
||||
+ struct tplg_elem *elem;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_TEXT);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "values") == 0) {
|
||||
+ err = parse_text_values(n, elem);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to parse text values");
|
||||
+ return err;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,664 +0,0 @@
|
||||
From 4db19506c3e7a68a0d0be40422172f22605c58d8 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:16 +0100
|
||||
Subject: [PATCH 38/49] topology: Add PCM parser.
|
||||
|
||||
Parse PCM configurations and capabilities. These can then be used to define
|
||||
the capabilities and config for FE DAI links, PCM devices and
|
||||
codec <-> codec style links.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/pcm.c | 639 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 639 insertions(+)
|
||||
create mode 100644 src/topology/pcm.c
|
||||
|
||||
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
|
||||
new file mode 100644
|
||||
index 000000000000..8f23a6f12ec4
|
||||
--- /dev/null
|
||||
+++ b/src/topology/pcm.c
|
||||
@@ -0,0 +1,639 @@
|
||||
+/*
|
||||
+ Copyright(c) 2014-2015 Intel Corporation
|
||||
+ All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ Authors: Mengdong Lin <mengdong.lin@intel.com>
|
||||
+ Yao Jin <yao.jin@intel.com>
|
||||
+ Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
+*/
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "tplg_local.h"
|
||||
+
|
||||
+struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base, const char* id)
|
||||
+{
|
||||
+ struct list_head *pos;
|
||||
+ struct tplg_elem *elem;
|
||||
+ struct snd_soc_tplg_pcm_dai *pcm_dai;
|
||||
+
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+ if (elem->type != OBJECT_TYPE_PCM)
|
||||
+ return NULL;
|
||||
+
|
||||
+ pcm_dai = elem->pcm;
|
||||
+
|
||||
+ if (pcm_dai && (!strcmp(pcm_dai->capconf[0].caps.name, id)
|
||||
+ || !strcmp(pcm_dai->capconf[1].caps.name, id)))
|
||||
+ return elem;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* copy referenced caps to the pcm */
|
||||
+static void copy_pcm_caps(const char *id, struct snd_soc_tplg_stream_caps *caps,
|
||||
+ struct tplg_elem *ref_elem)
|
||||
+{
|
||||
+ struct snd_soc_tplg_stream_caps *ref_caps = ref_elem->stream_caps;
|
||||
+
|
||||
+ tplg_dbg("Copy pcm caps (%ld bytes) from '%s' to '%s' \n",
|
||||
+ sizeof(*caps), ref_elem->id, id);
|
||||
+
|
||||
+ *caps = *ref_caps;
|
||||
+}
|
||||
+
|
||||
+/* copy referenced config to the pcm */
|
||||
+static void copy_pcm_config(const char *id,
|
||||
+ struct snd_soc_tplg_stream_config *cfg, struct tplg_elem *ref_elem)
|
||||
+{
|
||||
+ struct snd_soc_tplg_stream_config *ref_cfg = ref_elem->stream_cfg;
|
||||
+
|
||||
+ tplg_dbg("Copy pcm config (%ld bytes) from '%s' to '%s' \n",
|
||||
+ sizeof(*cfg), ref_elem->id, id);
|
||||
+
|
||||
+ *cfg = *ref_cfg;
|
||||
+}
|
||||
+
|
||||
+/* check referenced config and caps for a pcm */
|
||||
+static int tplg_build_pcm_cfg_caps(snd_tplg_t *tplg, struct tplg_elem *elem)
|
||||
+{
|
||||
+ struct tplg_elem *ref_elem = NULL;
|
||||
+ struct snd_soc_tplg_pcm_cfg_caps *capconf;
|
||||
+ struct snd_soc_tplg_pcm_dai *pcm_dai;
|
||||
+ unsigned int i, j;
|
||||
+
|
||||
+ switch (elem->type) {
|
||||
+ case OBJECT_TYPE_PCM:
|
||||
+ pcm_dai = elem->pcm;
|
||||
+ break;
|
||||
+ case OBJECT_TYPE_BE:
|
||||
+ pcm_dai = elem->be;
|
||||
+ break;
|
||||
+ case OBJECT_TYPE_CC:
|
||||
+ pcm_dai = elem->cc;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 2; i++) {
|
||||
+ capconf = &pcm_dai->capconf[i];
|
||||
+
|
||||
+ ref_elem = tplg_elem_lookup(&tplg->pcm_caps_list,
|
||||
+ capconf->caps.name, OBJECT_TYPE_STREAM_CAPS);
|
||||
+
|
||||
+ if (ref_elem != NULL)
|
||||
+ copy_pcm_caps(elem->id, &capconf->caps, ref_elem);
|
||||
+
|
||||
+ for (j = 0; j < capconf->num_configs; j++) {
|
||||
+ ref_elem = tplg_elem_lookup(&tplg->pcm_config_list,
|
||||
+ capconf->configs[j].name,
|
||||
+ OBJECT_TYPE_STREAM_CONFIG);
|
||||
+
|
||||
+ if (ref_elem != NULL)
|
||||
+ copy_pcm_config(elem->id,
|
||||
+ &capconf->configs[j],
|
||||
+ ref_elem);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_build_pcm_dai(snd_tplg_t *tplg, unsigned int type)
|
||||
+{
|
||||
+ struct list_head *base, *pos;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case OBJECT_TYPE_PCM:
|
||||
+ base = &tplg->pcm_list;
|
||||
+ break;
|
||||
+ case OBJECT_TYPE_BE:
|
||||
+ base = &tplg->be_list;
|
||||
+ break;
|
||||
+ case OBJECT_TYPE_CC:
|
||||
+ base = &tplg->cc_list;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+ if (elem->type != type) {
|
||||
+ SNDERR("error: invalid elem '%s'\n", elem->id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ err = tplg_build_pcm_cfg_caps(tplg, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* PCM stream configuration */
|
||||
+static int tplg_parse_stream_cfg(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
+ snd_config_t *cfg, void *private)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ struct snd_soc_tplg_stream_config *sc = private;
|
||||
+ struct snd_soc_tplg_stream *stream;
|
||||
+ const char *id, *val;
|
||||
+ snd_pcm_format_t format;
|
||||
+ int ret;
|
||||
+
|
||||
+ snd_config_get_id(cfg, &id);
|
||||
+
|
||||
+ if (strcmp(id, "playback") == 0)
|
||||
+ stream = &sc->playback;
|
||||
+ else if (strcmp(id, "capture") == 0)
|
||||
+ stream = &sc->capture;
|
||||
+ else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tplg_dbg("\t%s:\n", id);
|
||||
+
|
||||
+ stream->size = sizeof(*stream);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (strcmp(id, "format") == 0) {
|
||||
+ format = snd_pcm_format_value(val);
|
||||
+ if (format == SND_PCM_FORMAT_UNKNOWN) {
|
||||
+ SNDERR("error: unsupported stream format %s\n",
|
||||
+ val);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ stream->format = format;
|
||||
+ tplg_dbg("\t\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "rate") == 0) {
|
||||
+ stream->rate = atoi(val);
|
||||
+ tplg_dbg("\t\t%s: %d\n", id, stream->rate);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "channels") == 0) {
|
||||
+ stream->channels = atoi(val);
|
||||
+ tplg_dbg("\t\t%s: %d\n", id, stream->channels);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "tdm_slot") == 0) {
|
||||
+ stream->tdm_slot = strtol(val, NULL, 16);
|
||||
+ tplg_dbg("\t\t%s: 0x%x\n", id, stream->tdm_slot);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse pcm configuration */
|
||||
+int tplg_parse_pcm_config(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_stream_config *sc;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id;
|
||||
+ int err;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_STREAM_CONFIG);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ sc = elem->stream_cfg;
|
||||
+ sc->size = elem->size;
|
||||
+
|
||||
+ tplg_dbg(" PCM Config: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "config") == 0) {
|
||||
+ err = tplg_parse_compound(tplg, n,
|
||||
+ tplg_parse_stream_cfg, sc);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int split_format(struct snd_soc_tplg_stream_caps *caps, char *str)
|
||||
+{
|
||||
+ char *s = NULL;
|
||||
+ snd_pcm_format_t format;
|
||||
+ int i = 0, ret;
|
||||
+
|
||||
+ s = strtok(str, ",");
|
||||
+ while ((s != NULL) && (i < SND_SOC_TPLG_MAX_FORMATS)) {
|
||||
+ format = snd_pcm_format_value(s);
|
||||
+ if (format == SND_PCM_FORMAT_UNKNOWN) {
|
||||
+ SNDERR("error: unsupported stream format %s\n", s);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ caps->formats[i] = format;
|
||||
+ s = strtok(NULL, ", ");
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse pcm Capabilities */
|
||||
+int tplg_parse_pcm_caps(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_stream_caps *sc;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val;
|
||||
+ char *s;
|
||||
+ int err;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_STREAM_CAPS);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ sc = elem->stream_caps;
|
||||
+ sc->size = elem->size;
|
||||
+ elem_copy_text(sc->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+
|
||||
+ tplg_dbg(" PCM Capabilities: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (strcmp(id, "formats") == 0) {
|
||||
+ s = strdup(val);
|
||||
+ if (s == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ err = split_format(sc, s);
|
||||
+ free(s);
|
||||
+
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ tplg_dbg("\t\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "rate_min") == 0) {
|
||||
+ sc->rate_min = atoi(val);
|
||||
+ tplg_dbg("\t\t%s: %d\n", id, sc->rate_min);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "rate_max") == 0) {
|
||||
+ sc->rate_max = atoi(val);
|
||||
+ tplg_dbg("\t\t%s: %d\n", id, sc->rate_max);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "channels_min") == 0) {
|
||||
+ sc->channels_min = atoi(val);
|
||||
+ tplg_dbg("\t\t%s: %d\n", id, sc->channels_min);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "channels_max") == 0) {
|
||||
+ sc->channels_max = atoi(val);
|
||||
+ tplg_dbg("\t\t%s: %d\n", id, sc->channels_max);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int tplg_parse_pcm_cfg(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
+ snd_config_t *cfg, void *private)
|
||||
+{
|
||||
+ struct snd_soc_tplg_pcm_cfg_caps *capconf = private;
|
||||
+ struct snd_soc_tplg_stream_config *configs = capconf->configs;
|
||||
+ unsigned int *num_configs = &capconf->num_configs;
|
||||
+ const char *value;
|
||||
+
|
||||
+ if (*num_configs == SND_SOC_TPLG_STREAM_CONFIG_MAX)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (snd_config_get_string(cfg, &value) < 0)
|
||||
+ return EINVAL;
|
||||
+
|
||||
+ elem_copy_text(configs[*num_configs].name, value,
|
||||
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+
|
||||
+ *num_configs += 1;
|
||||
+
|
||||
+ tplg_dbg("\t\t\t%s\n", value);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse the cap and config of a pcm */
|
||||
+int tplg_parse_pcm_cap_cfg(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
+ void *private)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ struct tplg_elem *elem = private;
|
||||
+ struct snd_soc_tplg_pcm_dai *pcm_dai;
|
||||
+ const char *id, *value;
|
||||
+ int err, stream;
|
||||
+
|
||||
+ if (elem->type == OBJECT_TYPE_PCM)
|
||||
+ pcm_dai = elem->pcm;
|
||||
+ else if (elem->type == OBJECT_TYPE_BE)
|
||||
+ pcm_dai = elem->be;
|
||||
+ else if (elem->type == OBJECT_TYPE_CC)
|
||||
+ pcm_dai = elem->cc;
|
||||
+ else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ snd_config_get_id(cfg, &id);
|
||||
+
|
||||
+ tplg_dbg("\t%s:\n", id);
|
||||
+
|
||||
+ if (strcmp(id, "playback") == 0) {
|
||||
+ stream = SND_SOC_TPLG_STREAM_PLAYBACK;
|
||||
+ pcm_dai->playback = 1;
|
||||
+ } else if (strcmp(id, "capture") == 0) {
|
||||
+ stream = SND_SOC_TPLG_STREAM_CAPTURE;
|
||||
+ pcm_dai->capture = 1;
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+
|
||||
+ /* get id */
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "capabilities") == 0) {
|
||||
+ if (snd_config_get_string(n, &value) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ elem_copy_text(pcm_dai->capconf[stream].caps.name, value,
|
||||
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+
|
||||
+ tplg_dbg("\t\t%s\n\t\t\t%s\n", id, value);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "configs") == 0) {
|
||||
+ tplg_dbg("\t\tconfigs:\n");
|
||||
+ err = tplg_parse_compound(tplg, n, tplg_parse_pcm_cfg,
|
||||
+ &pcm_dai->capconf[stream]);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse pcm */
|
||||
+int tplg_parse_pcm(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_pcm_dai *pcm_dai;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val = NULL;
|
||||
+ int err;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_PCM);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ pcm_dai = elem->pcm;
|
||||
+ pcm_dai->size = elem->size;
|
||||
+ elem_copy_text(pcm_dai->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+
|
||||
+ tplg_dbg(" PCM: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "index") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->index = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "id") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ pcm_dai->id = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, pcm_dai->id);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "pcm") == 0) {
|
||||
+ err = tplg_parse_compound(tplg, n,
|
||||
+ tplg_parse_pcm_cap_cfg, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse be */
|
||||
+int tplg_parse_be(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_pcm_dai *pcm_dai;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val = NULL;
|
||||
+ int err;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_BE);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ pcm_dai = elem->be;
|
||||
+ pcm_dai->size = elem->size;
|
||||
+ elem_copy_text(pcm_dai->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+
|
||||
+ tplg_dbg(" BE: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "index") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->index = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "id") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ pcm_dai->id = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, pcm_dai->id);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "be") == 0) {
|
||||
+ err = tplg_parse_compound(tplg, n,
|
||||
+ tplg_parse_pcm_cap_cfg, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse cc */
|
||||
+int tplg_parse_cc(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_pcm_dai *pcm_dai;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val = NULL;
|
||||
+ int err;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_CC);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ pcm_dai = elem->cc;
|
||||
+ pcm_dai->size = elem->size;
|
||||
+
|
||||
+ tplg_dbg(" CC: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "index") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->index = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "id") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ pcm_dai->id = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, pcm_dai->id);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "cc") == 0) {
|
||||
+ err = tplg_parse_compound(tplg, n,
|
||||
+ tplg_parse_pcm_cap_cfg, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,107 +0,0 @@
|
||||
From 353f1eddb608a837157342155fc061f85bf0a5f8 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:17 +0100
|
||||
Subject: [PATCH 39/49] topology: Add operations parser
|
||||
|
||||
Parse operations so we can bind them to kcontrols in the kernel.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/ops.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 84 insertions(+)
|
||||
create mode 100644 src/topology/ops.c
|
||||
|
||||
diff --git a/src/topology/ops.c b/src/topology/ops.c
|
||||
new file mode 100644
|
||||
index 000000000000..243d8c5e2bbc
|
||||
--- /dev/null
|
||||
+++ b/src/topology/ops.c
|
||||
@@ -0,0 +1,84 @@
|
||||
+/*
|
||||
+ Copyright(c) 2014-2015 Intel Corporation
|
||||
+ All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ Authors: Mengdong Lin <mengdong.lin@intel.com>
|
||||
+ Yao Jin <yao.jin@intel.com>
|
||||
+ Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
+*/
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "tplg_local.h"
|
||||
+
|
||||
+/* mapping of kcontrol text names to types */
|
||||
+static const struct map_elem control_map[] = {
|
||||
+ {"volsw", SND_SOC_TPLG_CTL_VOLSW},
|
||||
+ {"volsw_sx", SND_SOC_TPLG_CTL_VOLSW_SX},
|
||||
+ {"volsw_xr_sx", SND_SOC_TPLG_CTL_VOLSW_XR_SX},
|
||||
+ {"enum", SND_SOC_TPLG_CTL_ENUM},
|
||||
+ {"bytes", SND_SOC_TPLG_CTL_BYTES},
|
||||
+ {"enum_value", SND_SOC_TPLG_CTL_ENUM_VALUE},
|
||||
+ {"range", SND_SOC_TPLG_CTL_RANGE},
|
||||
+ {"strobe", SND_SOC_TPLG_CTL_STROBE},
|
||||
+};
|
||||
+
|
||||
+static int lookup_ops(const char *c)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(control_map); i++) {
|
||||
+ if (strcmp(control_map[i].name, c) == 0)
|
||||
+ return control_map[i].id;
|
||||
+ }
|
||||
+
|
||||
+ /* cant find string name in our table so we use its ID number */
|
||||
+ return atoi(c);
|
||||
+}
|
||||
+
|
||||
+/* Parse Control operations. Ops can come from standard names above or
|
||||
+ * bespoke driver controls with numbers >= 256
|
||||
+ */
|
||||
+int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
+ snd_config_t *cfg, void *private)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ struct snd_soc_tplg_ctl_hdr *hdr = private;
|
||||
+ const char *id, *value;
|
||||
+
|
||||
+ tplg_dbg("\tOps\n");
|
||||
+ hdr->size = sizeof(*hdr);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+
|
||||
+ /* get id */
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* get value - try strings then ints */
|
||||
+ if (snd_config_get_string(n, &value) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "info") == 0)
|
||||
+ hdr->ops.info = lookup_ops(value);
|
||||
+ else if (strcmp(id, "put") == 0)
|
||||
+ hdr->ops.put = lookup_ops(value);
|
||||
+ else if (strcmp(id, "get") == 0)
|
||||
+ hdr->ops.get = lookup_ops(value);
|
||||
+
|
||||
+ tplg_dbg("\t\t%s = %s\n", id, value);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,420 +0,0 @@
|
||||
From 5b379da2a0a1084349e918a52f471c03e37af703 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:18 +0100
|
||||
Subject: [PATCH 40/49] topology: Add private data parser
|
||||
|
||||
Parse private data and store for attachment to other objects. Data can come
|
||||
file or be locally defined as bytes, shorts or words.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/data.c | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 396 insertions(+)
|
||||
create mode 100644 src/topology/data.c
|
||||
|
||||
diff --git a/src/topology/data.c b/src/topology/data.c
|
||||
new file mode 100644
|
||||
index 000000000000..ae664721935d
|
||||
--- /dev/null
|
||||
+++ b/src/topology/data.c
|
||||
@@ -0,0 +1,396 @@
|
||||
+/*
|
||||
+ Copyright(c) 2014-2015 Intel Corporation
|
||||
+ All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ Authors: Mengdong Lin <mengdong.lin@intel.com>
|
||||
+ Yao Jin <yao.jin@intel.com>
|
||||
+ Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
+*/
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "tplg_local.h"
|
||||
+
|
||||
+/* Get Private data from a file. */
|
||||
+static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
+{
|
||||
+ struct snd_soc_tplg_private *priv = NULL;
|
||||
+ const char *value = NULL;
|
||||
+ char filename[MAX_FILE];
|
||||
+ char *env = getenv(ALSA_CONFIG_TPLG_VAR);
|
||||
+ FILE *fp;
|
||||
+ size_t size, bytes_read;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ tplg_dbg("data DataFile: %s\n", elem->id);
|
||||
+
|
||||
+ if (snd_config_get_string(cfg, &value) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* prepend alsa config directory to path */
|
||||
+ snprintf(filename, sizeof(filename), "%s/%s",
|
||||
+ env ? env : ALSA_TPLG_DIR, value);
|
||||
+
|
||||
+ fp = fopen(filename, "r");
|
||||
+ if (fp == NULL) {
|
||||
+ SNDERR("error: invalid data file path '%s'\n",
|
||||
+ filename);
|
||||
+ ret = -errno;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ fseek(fp, 0L, SEEK_END);
|
||||
+ size = ftell(fp);
|
||||
+ fseek(fp, 0L, SEEK_SET);
|
||||
+ if (size <= 0) {
|
||||
+ SNDERR("error: invalid data file size %zu\n", size);
|
||||
+ ret = -EINVAL;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ if (size > TPLG_MAX_PRIV_SIZE) {
|
||||
+ SNDERR("error: data file too big %zu\n", size);
|
||||
+ ret = -EINVAL;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ priv = calloc(1, sizeof(*priv) + size);
|
||||
+ if (!priv) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ bytes_read = fread(&priv->data, 1, size, fp);
|
||||
+ if (bytes_read != size) {
|
||||
+ ret = -errno;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ elem->data = priv;
|
||||
+ priv->size = size;
|
||||
+ elem->size = sizeof(*priv) + size;
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ if (priv)
|
||||
+ free(priv);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void dump_priv_data(struct tplg_elem *elem)
|
||||
+{
|
||||
+ struct snd_soc_tplg_private *priv = elem->data;
|
||||
+ unsigned char *p = (unsigned char *)priv->data;
|
||||
+ unsigned int i, j = 0;
|
||||
+
|
||||
+ tplg_dbg(" elem size = %d, priv data size = %d\n",
|
||||
+ elem->size, priv->size);
|
||||
+
|
||||
+ for (i = 0; i < priv->size; i++) {
|
||||
+ if (j++ % 8 == 0)
|
||||
+ tplg_dbg("\n");
|
||||
+
|
||||
+ tplg_dbg(" 0x%x", *p++);
|
||||
+ }
|
||||
+
|
||||
+ tplg_dbg("\n\n");
|
||||
+}
|
||||
+
|
||||
+/* get number of hex value elements in CSV list */
|
||||
+static int get_hex_num(const char *str)
|
||||
+{
|
||||
+ int commas = 0, values = 0, len = strlen(str);
|
||||
+ const char *end = str + len;
|
||||
+
|
||||
+ /* we expect "0x0, 0x0, 0x0" */
|
||||
+ while (str < end) {
|
||||
+
|
||||
+ /* skip white space */
|
||||
+ if (isspace(*str)) {
|
||||
+ str++;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* find delimeters */
|
||||
+ if (*str == ',') {
|
||||
+ commas++;
|
||||
+ str++;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* find 0x[0-9] values */
|
||||
+ if (*str == '0' && str + 2 <= end) {
|
||||
+ if (str[1] == 'x' && str[2] >= '0' && str[2] <= 'f') {
|
||||
+ values++;
|
||||
+ str += 3;
|
||||
+ } else {
|
||||
+ str++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ str++;
|
||||
+ }
|
||||
+
|
||||
+ /* there should always be one less comma than value */
|
||||
+ if (values -1 != commas)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return values;
|
||||
+}
|
||||
+
|
||||
+static int write_hex(char *buf, char *str, int width)
|
||||
+{
|
||||
+ long val;
|
||||
+ void *p = &val;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ val = strtol(str, NULL, 16);
|
||||
+
|
||||
+ if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
|
||||
+ || (errno != 0 && val == 0)) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ switch (width) {
|
||||
+ case 1:
|
||||
+ *(unsigned char *)buf = *(unsigned char *)p;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ *(unsigned short *)buf = *(unsigned short *)p;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ *(unsigned int *)buf = *(unsigned int *)p;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int copy_data_hex(char *data, int off, const char *str, int width)
|
||||
+{
|
||||
+ char *tmp, *s = NULL, *p = data;
|
||||
+ int ret;
|
||||
+
|
||||
+ tmp = strdup(str);
|
||||
+ if (tmp == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ p += off;
|
||||
+ s = strtok(tmp, ",");
|
||||
+
|
||||
+ while (s != NULL) {
|
||||
+ ret = write_hex(p, s, width);
|
||||
+ if (ret < 0) {
|
||||
+ free(tmp);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ s = strtok(NULL, ",");
|
||||
+ p += width;
|
||||
+ }
|
||||
+
|
||||
+ free(tmp);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
|
||||
+ int width)
|
||||
+{
|
||||
+ struct snd_soc_tplg_private *priv;
|
||||
+ const char *value = NULL;
|
||||
+ int size, esize, off, num;
|
||||
+ int ret;
|
||||
+
|
||||
+ tplg_dbg(" data: %s\n", elem->id);
|
||||
+
|
||||
+ if (snd_config_get_string(cfg, &value) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ num = get_hex_num(value);
|
||||
+ if (num <= 0) {
|
||||
+ SNDERR("error: malformed hex variable list %s\n", value);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ size = num * width;
|
||||
+ priv = elem->data;
|
||||
+
|
||||
+ if (esize > TPLG_MAX_PRIV_SIZE) {
|
||||
+ SNDERR("error: data too big %d\n", esize);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (priv != NULL) {
|
||||
+ off = priv->size;
|
||||
+ esize = elem->size + size;
|
||||
+ priv = realloc(priv, esize);
|
||||
+ } else {
|
||||
+ off = 0;
|
||||
+ esize = sizeof(*priv) + size;
|
||||
+ priv = calloc(1, esize);
|
||||
+ }
|
||||
+
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ elem->data = priv;
|
||||
+ priv->size += size;
|
||||
+ elem->size = esize;
|
||||
+
|
||||
+ ret = copy_data_hex(priv->data, off, value, width);
|
||||
+
|
||||
+ dump_priv_data(elem);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Parse Private data.
|
||||
+ *
|
||||
+ * Object private data can either be from file or defined as bytes, shorts,
|
||||
+ * words.
|
||||
+ */
|
||||
+int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
+ void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val = NULL;
|
||||
+ int err = 0;
|
||||
+ struct tplg_elem *elem;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_DATA);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "file") == 0) {
|
||||
+ err = tplg_parse_data_file(n, elem);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to parse data file\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "bytes") == 0) {
|
||||
+ err = tplg_parse_data_hex(n, elem, 1);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to parse data bytes\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "shorts") == 0) {
|
||||
+ err = tplg_parse_data_hex(n, elem, 2);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to parse data shorts\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "words") == 0) {
|
||||
+ err = tplg_parse_data_hex(n, elem, 4);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to parse data words\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "index") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->index = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "type") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->vendor_type = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/* copy private data into the bytes extended control */
|
||||
+int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
+{
|
||||
+ struct snd_soc_tplg_private *priv;
|
||||
+ int priv_data_size;
|
||||
+
|
||||
+ if (!ref)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tplg_dbg("Data '%s' used by '%s'\n", ref->id, elem->id);
|
||||
+ priv_data_size = ref->data->size;
|
||||
+
|
||||
+ switch (elem->type) {
|
||||
+ case OBJECT_TYPE_MIXER:
|
||||
+ elem->mixer_ctrl = realloc(elem->mixer_ctrl,
|
||||
+ elem->size + priv_data_size);
|
||||
+ if (!elem->mixer_ctrl)
|
||||
+ return -ENOMEM;
|
||||
+ priv = &elem->mixer_ctrl->priv;
|
||||
+ break;
|
||||
+
|
||||
+ case OBJECT_TYPE_ENUM:
|
||||
+ elem->enum_ctrl = realloc(elem->enum_ctrl,
|
||||
+ elem->size + priv_data_size);
|
||||
+ if (!elem->enum_ctrl)
|
||||
+ return -ENOMEM;
|
||||
+ priv = &elem->enum_ctrl->priv;
|
||||
+ break;
|
||||
+
|
||||
+ case OBJECT_TYPE_BYTES:
|
||||
+ elem->bytes_ext = realloc(elem->bytes_ext,
|
||||
+ elem->size + priv_data_size);
|
||||
+ if (!elem->bytes_ext)
|
||||
+ return -ENOMEM;
|
||||
+ priv = &elem->bytes_ext->priv;
|
||||
+ break;
|
||||
+
|
||||
+
|
||||
+ case OBJECT_TYPE_DAPM_WIDGET:
|
||||
+ elem->widget = realloc(elem->widget,
|
||||
+ elem->size + priv_data_size);
|
||||
+ if (!elem->widget)
|
||||
+ return -ENOMEM;
|
||||
+ priv = &elem->widget->priv;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ SNDERR("elem '%s': type %d private data not supported \n",
|
||||
+ elem->id, elem->type);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ elem->size += priv_data_size;
|
||||
+ priv->size = priv_data_size;
|
||||
+ ref->compound_elem = 1;
|
||||
+ memcpy(priv->data, ref->data->data, priv_data_size);
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,585 +0,0 @@
|
||||
From 01a0e1a1c2196967d2522092ca993098a7c66613 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:19 +0100
|
||||
Subject: [PATCH 41/49] topology: Add DAPM object parser
|
||||
|
||||
Parse DAPM objects including widgets and graph elements.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/dapm.c | 562 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 562 insertions(+)
|
||||
create mode 100644 src/topology/dapm.c
|
||||
|
||||
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
|
||||
new file mode 100644
|
||||
index 000000000000..1da82adea470
|
||||
--- /dev/null
|
||||
+++ b/src/topology/dapm.c
|
||||
@@ -0,0 +1,562 @@
|
||||
+/*
|
||||
+ Copyright(c) 2014-2015 Intel Corporation
|
||||
+ All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ Authors: Mengdong Lin <mengdong.lin@intel.com>
|
||||
+ Yao Jin <yao.jin@intel.com>
|
||||
+ Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
+*/
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "tplg_local.h"
|
||||
+
|
||||
+/* mapping of widget text names to types */
|
||||
+static const struct map_elem widget_map[] = {
|
||||
+ {"input", SND_SOC_TPLG_DAPM_INPUT},
|
||||
+ {"output", SND_SOC_TPLG_DAPM_OUTPUT},
|
||||
+ {"mux", SND_SOC_TPLG_DAPM_MUX},
|
||||
+ {"mixer", SND_SOC_TPLG_DAPM_MIXER},
|
||||
+ {"pga", SND_SOC_TPLG_DAPM_PGA},
|
||||
+ {"out_drv", SND_SOC_TPLG_DAPM_OUT_DRV},
|
||||
+ {"adc", SND_SOC_TPLG_DAPM_ADC},
|
||||
+ {"dac", SND_SOC_TPLG_DAPM_DAC},
|
||||
+ {"switch", SND_SOC_TPLG_DAPM_SWITCH},
|
||||
+ {"pre", SND_SOC_TPLG_DAPM_PRE},
|
||||
+ {"post", SND_SOC_TPLG_DAPM_POST},
|
||||
+ {"aif_in", SND_SOC_TPLG_DAPM_AIF_IN},
|
||||
+ {"aif_out", SND_SOC_TPLG_DAPM_AIF_OUT},
|
||||
+ {"dai_in", SND_SOC_TPLG_DAPM_DAI_IN},
|
||||
+ {"dai_out", SND_SOC_TPLG_DAPM_DAI_OUT},
|
||||
+ {"dai_link", SND_SOC_TPLG_DAPM_DAI_LINK},
|
||||
+};
|
||||
+
|
||||
+/* mapping of widget kcontrol text names to types */
|
||||
+static const struct map_elem widget_control_map[] = {
|
||||
+ {"volsw", SND_SOC_TPLG_DAPM_CTL_VOLSW},
|
||||
+ {"enum_double", SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE},
|
||||
+ {"enum_virt", SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT},
|
||||
+ {"enum_value", SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE},
|
||||
+};
|
||||
+
|
||||
+static int lookup_widget(const char *w)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(widget_map); i++) {
|
||||
+ if (strcmp(widget_map[i].name, w) == 0)
|
||||
+ return widget_map[i].id;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int tplg_parse_dapm_mixers(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *value = NULL;
|
||||
+
|
||||
+ tplg_dbg(" DAPM Mixer Controls: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+
|
||||
+ /* get value */
|
||||
+ if (snd_config_get_string(n, &value) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ tplg_ref_add(elem, OBJECT_TYPE_MIXER, value);
|
||||
+ tplg_dbg("\t\t %s\n", value);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int tplg_parse_dapm_enums(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *value = NULL;
|
||||
+
|
||||
+ tplg_dbg(" DAPM Enum Controls: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+
|
||||
+ /* get value */
|
||||
+ if (snd_config_get_string(n, &value) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ tplg_ref_add(elem, OBJECT_TYPE_ENUM, value);
|
||||
+ tplg_dbg("\t\t %s\n", value);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* move referenced controls to the widget */
|
||||
+static int copy_dapm_control(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
+{
|
||||
+ struct snd_soc_tplg_dapm_widget *widget = elem->widget;
|
||||
+ struct snd_soc_tplg_mixer_control *mixer_ctrl = ref->mixer_ctrl;
|
||||
+ struct snd_soc_tplg_enum_control *enum_ctrl = ref->enum_ctrl;
|
||||
+
|
||||
+ tplg_dbg("Control '%s' used by '%s'\n", ref->id, elem->id);
|
||||
+ tplg_dbg("\tparent size: %d + %d -> %d, priv size -> %d\n",
|
||||
+ elem->size, ref->size, elem->size + ref->size,
|
||||
+ widget->priv.size);
|
||||
+
|
||||
+ widget = realloc(widget, elem->size + ref->size);
|
||||
+ if (!widget)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ elem->widget = widget;
|
||||
+
|
||||
+ /* copy new widget at the end */
|
||||
+ if (ref->type == OBJECT_TYPE_MIXER)
|
||||
+ memcpy((void*)widget + elem->size, mixer_ctrl, ref->size);
|
||||
+ else if (ref->type == OBJECT_TYPE_ENUM)
|
||||
+ memcpy((void*)widget + elem->size, enum_ctrl, ref->size);
|
||||
+
|
||||
+ elem->size += ref->size;
|
||||
+ widget->num_kcontrols++;
|
||||
+ ref->compound_elem = 1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* check referenced controls for a widget */
|
||||
+static int tplg_build_widget(snd_tplg_t *tplg,
|
||||
+ struct tplg_elem *elem)
|
||||
+{
|
||||
+ struct tplg_ref *ref;
|
||||
+ struct list_head *base, *pos;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ base = &elem->ref_list;
|
||||
+
|
||||
+ /* for each ref in this control elem */
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ ref = list_entry(pos, struct tplg_ref, list);
|
||||
+ if (ref->id == NULL || ref->elem)
|
||||
+ continue;
|
||||
+
|
||||
+ switch (ref->type) {
|
||||
+ case OBJECT_TYPE_MIXER:
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->mixer_list,
|
||||
+ ref->id, OBJECT_TYPE_MIXER);
|
||||
+ if (ref->elem)
|
||||
+ err = copy_dapm_control(elem, ref->elem);
|
||||
+ break;
|
||||
+
|
||||
+ case OBJECT_TYPE_ENUM:
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->enum_list,
|
||||
+ ref->id, OBJECT_TYPE_ENUM);
|
||||
+ if (ref->elem)
|
||||
+ err = copy_dapm_control(elem, ref->elem);
|
||||
+ break;
|
||||
+
|
||||
+ case OBJECT_TYPE_DATA:
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
+ ref->id, OBJECT_TYPE_DATA);
|
||||
+ if (ref->elem)
|
||||
+ err = tplg_copy_data(elem, ref->elem);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!ref->elem) {
|
||||
+ SNDERR("error: cannot find control '%s'"
|
||||
+ " referenced by widget '%s'\n",
|
||||
+ ref->id, elem->id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_build_widgets(snd_tplg_t *tplg)
|
||||
+{
|
||||
+
|
||||
+ struct list_head *base, *pos;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int err;
|
||||
+
|
||||
+ base = &tplg->widget_list;
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+ if (!elem->widget || elem->type != OBJECT_TYPE_DAPM_WIDGET) {
|
||||
+ SNDERR("error: invalid widget '%s'\n",
|
||||
+ elem->id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ err = tplg_build_widget(tplg, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ /* add widget to manifest */
|
||||
+ tplg->manifest.widget_elems++;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_build_routes(snd_tplg_t *tplg)
|
||||
+{
|
||||
+ struct list_head *base, *pos;
|
||||
+ struct tplg_elem *elem;
|
||||
+ struct snd_soc_tplg_dapm_graph_elem *route;
|
||||
+
|
||||
+ base = &tplg->route_list;
|
||||
+
|
||||
+ list_for_each(pos, base) {
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+
|
||||
+ if (!elem->route || elem->type != OBJECT_TYPE_DAPM_GRAPH) {
|
||||
+ SNDERR("error: invalid route '%s'\n",
|
||||
+ elem->id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ route = elem->route;
|
||||
+ tplg_dbg("\nCheck route: sink '%s', control '%s', source '%s'\n",
|
||||
+ route->sink, route->control, route->source);
|
||||
+
|
||||
+ /* validate sink */
|
||||
+ if (strlen(route->sink) <= 0) {
|
||||
+ SNDERR("error: no sink\n");
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ }
|
||||
+ if (!tplg_elem_lookup(&tplg->widget_list, route->sink,
|
||||
+ OBJECT_TYPE_DAPM_WIDGET)) {
|
||||
+ SNDERR("warning: undefined sink widget/stream '%s'\n",
|
||||
+ route->sink);
|
||||
+ }
|
||||
+
|
||||
+ /* validate control name */
|
||||
+ if (strlen(route->control)) {
|
||||
+ if (!tplg_elem_lookup(&tplg->mixer_list,
|
||||
+ route->control, OBJECT_TYPE_MIXER) &&
|
||||
+ !tplg_elem_lookup(&tplg->enum_list,
|
||||
+ route->control, OBJECT_TYPE_ENUM)) {
|
||||
+ SNDERR("warning: Undefined mixer/enum control '%s'\n",
|
||||
+ route->control);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* validate source */
|
||||
+ if (strlen(route->source) <= 0) {
|
||||
+ SNDERR("error: no source\n");
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ }
|
||||
+ if (!tplg_elem_lookup(&tplg->widget_list, route->source,
|
||||
+ OBJECT_TYPE_DAPM_WIDGET)) {
|
||||
+ SNDERR("warning: Undefined source widget/stream '%s'\n",
|
||||
+ route->source);
|
||||
+ }
|
||||
+
|
||||
+ /* add graph to manifest */
|
||||
+ tplg->manifest.graph_elems++;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define LINE_SIZE 1024
|
||||
+
|
||||
+/* line is defined as '"source, control, sink"' */
|
||||
+static int tplg_parse_line(const char *text,
|
||||
+ struct snd_soc_tplg_dapm_graph_elem *line)
|
||||
+{
|
||||
+ char buf[LINE_SIZE];
|
||||
+ unsigned int len, i;
|
||||
+ const char *source = NULL, *sink = NULL, *control = NULL;
|
||||
+
|
||||
+ elem_copy_text(buf, text, LINE_SIZE);
|
||||
+
|
||||
+ len = strlen(buf);
|
||||
+ if (len <= 2) {
|
||||
+ SNDERR("error: invalid route \"%s\"\n", buf);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* find first , */
|
||||
+ for (i = 1; i < len; i++) {
|
||||
+ if (buf[i] == ',')
|
||||
+ goto second;
|
||||
+ }
|
||||
+ SNDERR("error: invalid route \"%s\"\n", buf);
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+second:
|
||||
+ /* find second , */
|
||||
+ sink = buf;
|
||||
+ control = &buf[i + 2];
|
||||
+ buf[i] = 0;
|
||||
+
|
||||
+ for (; i < len; i++) {
|
||||
+ if (buf[i] == ',')
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ SNDERR("error: invalid route \"%s\"\n", buf);
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+done:
|
||||
+ buf[i] = 0;
|
||||
+ source = &buf[i + 2];
|
||||
+
|
||||
+ strcpy(line->source, source);
|
||||
+ strcpy(line->control, control);
|
||||
+ strcpy(line->sink, sink);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t *cfg)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ struct tplg_elem *elem;
|
||||
+ struct snd_soc_tplg_dapm_graph_elem *line = NULL;
|
||||
+ int err;
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ const char *val;
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ elem = tplg_elem_new();
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ list_add_tail(&elem->list, &tplg->route_list);
|
||||
+ strcpy(elem->id, "line");
|
||||
+ elem->type = OBJECT_TYPE_DAPM_GRAPH;
|
||||
+ elem->size = sizeof(*line);
|
||||
+
|
||||
+ line = calloc(1, sizeof(*line));
|
||||
+ if (!line)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ elem->route = line;
|
||||
+
|
||||
+ err = tplg_parse_line(val, line);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ tplg_dbg("route: sink '%s', control '%s', source '%s'\n",
|
||||
+ line->sink, line->control, line->source);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
+ void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ int err;
|
||||
+ const char *graph_id;
|
||||
+
|
||||
+ if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
|
||||
+ SNDERR("error: compound is expected for dapm graph definition\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ snd_config_get_id(cfg, &graph_id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ const char *id;
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "lines") == 0) {
|
||||
+ err = tplg_parse_routes(tplg, n);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to parse dapm graph %s\n",
|
||||
+ graph_id);
|
||||
+ return err;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* DAPM Widget */
|
||||
+int tplg_parse_dapm_widget(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_dapm_widget *widget;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val = NULL;
|
||||
+ int widget_type, err;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_DAPM_WIDGET);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ tplg_dbg(" Widget: %s\n", elem->id);
|
||||
+
|
||||
+ widget = elem->widget;
|
||||
+ elem_copy_text(widget->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ widget->size = elem->size;
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "index") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->index = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "type") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ widget_type = lookup_widget(val);
|
||||
+ if (widget_type < 0){
|
||||
+ SNDERR("Widget '%s': Unsupported widget type %s\n",
|
||||
+ elem->id, val);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ widget->id = widget_type;
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "no_pm") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (strcmp(val, "true") == 0)
|
||||
+ widget->reg = -1;
|
||||
+
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "shift") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ widget->shift = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, widget->shift);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "reg") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ widget->reg = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, widget->reg);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "invert") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ widget->invert = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, widget->invert);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "subseq") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ widget->subseq= atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, widget->subseq);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "event_type") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ widget->event_type = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, widget->event_type);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "event_flags") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ widget->event_flags = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, widget->event_flags);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "enum") == 0) {
|
||||
+ err = tplg_parse_dapm_enums(n, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "mixer") == 0) {
|
||||
+ err = tplg_parse_dapm_mixers(n, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "data") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tplg_ref_add(elem, OBJECT_TYPE_DATA, val);
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,636 +0,0 @@
|
||||
From 694b857ce7b44a333c4f5e8b12f1b6cdf1c12388 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:20 +0100
|
||||
Subject: [PATCH 42/49] topology: Add CTL parser
|
||||
|
||||
Add support to parse mixers, enums and byte controls.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/ctl.c | 613 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 613 insertions(+)
|
||||
create mode 100644 src/topology/ctl.c
|
||||
|
||||
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
|
||||
new file mode 100644
|
||||
index 000000000000..9c1333c1fc88
|
||||
--- /dev/null
|
||||
+++ b/src/topology/ctl.c
|
||||
@@ -0,0 +1,613 @@
|
||||
+/*
|
||||
+ Copyright(c) 2014-2015 Intel Corporation
|
||||
+ All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ Authors: Mengdong Lin <mengdong.lin@intel.com>
|
||||
+ Yao Jin <yao.jin@intel.com>
|
||||
+ Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
+*/
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "tplg_local.h"
|
||||
+
|
||||
+/* copy referenced TLV to the mixer control */
|
||||
+static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
+{
|
||||
+ struct snd_soc_tplg_mixer_control *mixer_ctrl = elem->mixer_ctrl;
|
||||
+ struct snd_soc_tplg_ctl_tlv *tlv = ref->tlv;
|
||||
+
|
||||
+ tplg_dbg("TLV '%s' used by '%s\n", ref->id, elem->id);
|
||||
+
|
||||
+ /* TLV has a fixed size */
|
||||
+ mixer_ctrl->tlv = *tlv;
|
||||
+
|
||||
+ /* set size of TLV data */
|
||||
+ mixer_ctrl->hdr.tlv_size = tlv->count * sizeof(uint32_t);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* check referenced TLV for a mixer control */
|
||||
+static int tplg_build_mixer_control(snd_tplg_t *tplg,
|
||||
+ struct tplg_elem *elem)
|
||||
+{
|
||||
+ struct tplg_ref *ref;
|
||||
+ struct list_head *base, *pos;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ base = &elem->ref_list;
|
||||
+
|
||||
+ /* for each ref in this control elem */
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ ref = list_entry(pos, struct tplg_ref, list);
|
||||
+ if (ref->id == NULL || ref->elem)
|
||||
+ continue;
|
||||
+
|
||||
+ if (ref->type == OBJECT_TYPE_TLV) {
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->tlv_list,
|
||||
+ ref->id, OBJECT_TYPE_TLV);
|
||||
+ if (ref->elem)
|
||||
+ err = copy_tlv(elem, ref->elem);
|
||||
+
|
||||
+ } else if (ref->type == OBJECT_TYPE_DATA) {
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
+ ref->id, OBJECT_TYPE_DATA);
|
||||
+ err = tplg_copy_data(elem, ref->elem);
|
||||
+ }
|
||||
+
|
||||
+ if (!ref->elem) {
|
||||
+ SNDERR("error: cannot find '%s' referenced by"
|
||||
+ " control '%s'\n", ref->id, elem->id);
|
||||
+ return -EINVAL;
|
||||
+ } else if (err < 0)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void copy_enum_texts(struct tplg_elem *enum_elem,
|
||||
+ struct tplg_elem *ref_elem)
|
||||
+{
|
||||
+ struct snd_soc_tplg_enum_control *ec = enum_elem->enum_ctrl;
|
||||
+
|
||||
+ memcpy(ec->texts, ref_elem->texts,
|
||||
+ SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+}
|
||||
+
|
||||
+/* check referenced text for a enum control */
|
||||
+static int tplg_build_enum_control(snd_tplg_t *tplg,
|
||||
+ struct tplg_elem *elem)
|
||||
+{
|
||||
+ struct tplg_ref *ref;
|
||||
+ struct list_head *base, *pos;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ base = &elem->ref_list;
|
||||
+
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ ref = list_entry(pos, struct tplg_ref, list);
|
||||
+ if (ref->id == NULL || ref->elem)
|
||||
+ continue;
|
||||
+
|
||||
+ if (ref->type == OBJECT_TYPE_TEXT) {
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->text_list,
|
||||
+ ref->id, OBJECT_TYPE_TEXT);
|
||||
+ if (ref->elem)
|
||||
+ copy_enum_texts(elem, ref->elem);
|
||||
+
|
||||
+ } else if (ref->type == OBJECT_TYPE_DATA) {
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
+ ref->id, OBJECT_TYPE_DATA);
|
||||
+ err = tplg_copy_data(elem, ref->elem);
|
||||
+ }
|
||||
+ if (!ref->elem) {
|
||||
+ SNDERR("error: cannot find '%s' referenced by"
|
||||
+ " control '%s'\n", ref->id, elem->id);
|
||||
+ return -EINVAL;
|
||||
+ } else if (err < 0)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* check referenced private data for a byte control */
|
||||
+static int tplg_build_bytes_control(snd_tplg_t *tplg, struct tplg_elem *elem)
|
||||
+{
|
||||
+ struct tplg_ref *ref;
|
||||
+ struct list_head *base, *pos;
|
||||
+
|
||||
+ base = &elem->ref_list;
|
||||
+
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ ref = list_entry(pos, struct tplg_ref, list);
|
||||
+ if (ref->id == NULL || ref->elem)
|
||||
+ continue;
|
||||
+
|
||||
+ /* bytes control only reference one private data section */
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
+ ref->id, OBJECT_TYPE_DATA);
|
||||
+ if (!ref->elem) {
|
||||
+ SNDERR("error: cannot find data '%s'"
|
||||
+ " referenced by control '%s'\n",
|
||||
+ ref->id, elem->id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* copy texts to enum elem */
|
||||
+ return tplg_copy_data(elem, ref->elem);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_build_controls(snd_tplg_t *tplg)
|
||||
+{
|
||||
+ struct list_head *base, *pos;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ base = &tplg->mixer_list;
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+ err = tplg_build_mixer_control(tplg, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ /* add control to manifest */
|
||||
+ tplg->manifest.control_elems++;
|
||||
+ }
|
||||
+
|
||||
+ base = &tplg->enum_list;
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+ err = tplg_build_enum_control(tplg, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ /* add control to manifest */
|
||||
+ tplg->manifest.control_elems++;
|
||||
+ }
|
||||
+
|
||||
+ base = &tplg->bytes_ext_list;
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+ err = tplg_build_bytes_control(tplg, elem);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ /* add control to manifest */
|
||||
+ tplg->manifest.control_elems++;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Parse TLV of DBScale type.
|
||||
+ *
|
||||
+ * Parse DBScale describing min, step, mute in DB.
|
||||
+ */
|
||||
+static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ struct snd_soc_tplg_ctl_tlv *tplg_tlv;
|
||||
+ const char *id = NULL, *value = NULL;
|
||||
+ int *data;
|
||||
+
|
||||
+ tplg_dbg(" scale: %s\n", elem->id);
|
||||
+
|
||||
+ tplg_tlv = calloc(1, sizeof(*tplg_tlv));
|
||||
+ if (!tplg_tlv)
|
||||
+ return -ENOMEM;
|
||||
+ data = (int*)(tplg_tlv->data);
|
||||
+
|
||||
+ elem->tlv = tplg_tlv;
|
||||
+ tplg_tlv->numid = SNDRV_CTL_TLVT_DB_SCALE;
|
||||
+ tplg_tlv->count = 8;
|
||||
+ tplg_tlv->size = sizeof(*tplg_tlv);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+
|
||||
+ /* get ID */
|
||||
+ if (snd_config_get_id(n, &id) < 0) {
|
||||
+ SNDERR("error: cant get ID\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* get value */
|
||||
+ if (snd_config_get_string(n, &value) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ tplg_dbg("\t%s = %s\n", id, value);
|
||||
+
|
||||
+ /* get TLV data */
|
||||
+ if (strcmp(id, "min") == 0)
|
||||
+ data[0] = atoi(value);
|
||||
+ else if (strcmp(id, "step") == 0)
|
||||
+ data[1] = atoi(value);
|
||||
+ else if (strcmp(id, "mute") == 0)
|
||||
+ data[2] = atoi(value);
|
||||
+ else
|
||||
+ SNDERR("error: unknown key %s\n", id);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse TLV */
|
||||
+int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
+ void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id;
|
||||
+ int err = 0;
|
||||
+ struct tplg_elem *elem;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_TLV);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "scale") == 0) {
|
||||
+ err = tplg_parse_tlv_dbscale(n, elem);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to DBScale");
|
||||
+ return err;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/* Parse Control Bytes */
|
||||
+int tplg_parse_control_bytes(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_bytes_control *be;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val = NULL;
|
||||
+ int err;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_BYTES);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ be = elem->bytes_ext;
|
||||
+ be->size = elem->size;
|
||||
+ elem_copy_text(be->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ be->hdr.type = SND_SOC_TPLG_TYPE_BYTES;
|
||||
+
|
||||
+ tplg_dbg(" Control Bytes: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "index") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->index = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "base") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ be->base = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, be->base);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "num_regs") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ be->num_regs = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, be->num_regs);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "max") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ be->max = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, be->num_regs);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "mask") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ be->mask = strtol(val, NULL, 16);
|
||||
+ tplg_dbg("\t%s: %d\n", id, be->mask);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "data") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tplg_ref_add(elem, OBJECT_TYPE_DATA, val);
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "tlv") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = tplg_ref_add(elem, OBJECT_TYPE_TLV, val);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ be->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
|
||||
+ SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse Control Enums. */
|
||||
+int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
+ void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_enum_control *ec;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val = NULL;
|
||||
+ int err, j;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_ENUM);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* init new mixer */
|
||||
+ ec = elem->enum_ctrl;
|
||||
+ elem_copy_text(ec->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ ec->hdr.type = SND_SOC_TPLG_TYPE_ENUM;
|
||||
+ ec->size = elem->size;
|
||||
+ tplg->channel_idx = 0;
|
||||
+
|
||||
+ /* set channel reg to default state */
|
||||
+ for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++)
|
||||
+ ec->channel[j].reg = -1;
|
||||
+
|
||||
+ tplg_dbg(" Control Enum: %s\n", elem->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "index") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->index = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "texts") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tplg_ref_add(elem, OBJECT_TYPE_TEXT, val);
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "channel") == 0) {
|
||||
+ if (ec->num_channels >= SND_SOC_TPLG_MAX_CHAN) {
|
||||
+ SNDERR("error: too many channels %s\n",
|
||||
+ elem->id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ err = tplg_parse_compound(tplg, n, tplg_parse_channel,
|
||||
+ ec->channel);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ ec->num_channels = tplg->channel_idx;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "ops") == 0) {
|
||||
+ err = tplg_parse_compound(tplg, n, tplg_parse_ops,
|
||||
+ &ec->hdr);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "data") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tplg_ref_add(elem, OBJECT_TYPE_DATA, val);
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse Controls.
|
||||
+ *
|
||||
+ * Mixer control. Supports multiple channels.
|
||||
+ */
|
||||
+int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ struct snd_soc_tplg_mixer_control *mc;
|
||||
+ struct tplg_elem *elem;
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ const char *id, *val = NULL;
|
||||
+ int err, j;
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_MIXER);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* init new mixer */
|
||||
+ mc = elem->mixer_ctrl;
|
||||
+ elem_copy_text(mc->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ mc->hdr.type = SND_SOC_TPLG_TYPE_MIXER;
|
||||
+ mc->size = elem->size;
|
||||
+ tplg->channel_idx = 0;
|
||||
+
|
||||
+ /* set channel reg to default state */
|
||||
+ for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++)
|
||||
+ mc->channel[j].reg = -1;
|
||||
+
|
||||
+ tplg_dbg(" Control Mixer: %s\n", elem->id);
|
||||
+
|
||||
+ /* giterate trough each mixer elment */
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* skip comments */
|
||||
+ if (strcmp(id, "comment") == 0)
|
||||
+ continue;
|
||||
+ if (id[0] == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "index") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem->index = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, elem->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "channel") == 0) {
|
||||
+ if (mc->num_channels >= SND_SOC_TPLG_MAX_CHAN) {
|
||||
+ SNDERR("error: too many channels %s\n",
|
||||
+ elem->id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ err = tplg_parse_compound(tplg, n, tplg_parse_channel,
|
||||
+ mc->channel);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ mc->num_channels = tplg->channel_idx;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "max") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mc->max = atoi(val);
|
||||
+ tplg_dbg("\t%s: %d\n", id, mc->max);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "invert") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (strcmp(val, "true") == 0)
|
||||
+ mc->invert = 1;
|
||||
+ else if (strcmp(val, "false") == 0)
|
||||
+ mc->invert = 0;
|
||||
+
|
||||
+ tplg_dbg("\t%s: %d\n", id, mc->invert);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "ops") == 0) {
|
||||
+ err = tplg_parse_compound(tplg, n, tplg_parse_ops,
|
||||
+ &mc->hdr);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "tlv") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = tplg_ref_add(elem, OBJECT_TYPE_TLV, val);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ mc->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
|
||||
+ SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(id, "data") == 0) {
|
||||
+ if (snd_config_get_string(n, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tplg_ref_add(elem, OBJECT_TYPE_DATA, val);
|
||||
+ tplg_dbg("\t%s: %s\n", id, val);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,145 +0,0 @@
|
||||
From 9764a4b891737e6b4363c09b5e5ce8384acecc11 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:21 +0100
|
||||
Subject: [PATCH 43/49] topology: Add Channel map parser.
|
||||
|
||||
Add support for parsing channel map to control registers.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/channel.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 122 insertions(+)
|
||||
create mode 100644 src/topology/channel.c
|
||||
|
||||
diff --git a/src/topology/channel.c b/src/topology/channel.c
|
||||
new file mode 100644
|
||||
index 000000000000..9bc5d5a77c57
|
||||
--- /dev/null
|
||||
+++ b/src/topology/channel.c
|
||||
@@ -0,0 +1,122 @@
|
||||
+/*
|
||||
+ Copyright(c) 2014-2015 Intel Corporation
|
||||
+ All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ Authors: Mengdong Lin <mengdong.lin@intel.com>
|
||||
+ Yao Jin <yao.jin@intel.com>
|
||||
+ Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
+*/
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "tplg_local.h"
|
||||
+
|
||||
+/* mapping of channel text names to types */
|
||||
+static const struct map_elem channel_map[] = {
|
||||
+ {"mono", SNDRV_CHMAP_MONO}, /* mono stream */
|
||||
+ {"fl", SNDRV_CHMAP_FL}, /* front left */
|
||||
+ {"fr", SNDRV_CHMAP_FR}, /* front right */
|
||||
+ {"rl", SNDRV_CHMAP_RL}, /* rear left */
|
||||
+ {"rr", SNDRV_CHMAP_RR}, /* rear right */
|
||||
+ {"fc", SNDRV_CHMAP_FC}, /* front center */
|
||||
+ {"lfe", SNDRV_CHMAP_LFE}, /* LFE */
|
||||
+ {"sl", SNDRV_CHMAP_SL}, /* side left */
|
||||
+ {"sr", SNDRV_CHMAP_SR}, /* side right */
|
||||
+ {"rc", SNDRV_CHMAP_RC}, /* rear center */
|
||||
+ {"flc", SNDRV_CHMAP_FLC}, /* front left center */
|
||||
+ {"frc", SNDRV_CHMAP_FRC}, /* front right center */
|
||||
+ {"rlc", SNDRV_CHMAP_RLC}, /* rear left center */
|
||||
+ {"rrc", SNDRV_CHMAP_RRC}, /* rear right center */
|
||||
+ {"flw", SNDRV_CHMAP_FLW}, /* front left wide */
|
||||
+ {"frw", SNDRV_CHMAP_FRW}, /* front right wide */
|
||||
+ {"flh", SNDRV_CHMAP_FLH}, /* front left high */
|
||||
+ {"fch", SNDRV_CHMAP_FCH}, /* front center high */
|
||||
+ {"frh", SNDRV_CHMAP_FRH}, /* front right high */
|
||||
+ {"tc", SNDRV_CHMAP_TC}, /* top center */
|
||||
+ {"tfl", SNDRV_CHMAP_TFL}, /* top front left */
|
||||
+ {"tfr", SNDRV_CHMAP_TFR}, /* top front right */
|
||||
+ {"tfc", SNDRV_CHMAP_TFC}, /* top front center */
|
||||
+ {"trl", SNDRV_CHMAP_TRL}, /* top rear left */
|
||||
+ {"trr", SNDRV_CHMAP_TRR}, /* top rear right */
|
||||
+ {"trc", SNDRV_CHMAP_TRC}, /* top rear center */
|
||||
+ {"tflc", SNDRV_CHMAP_TFLC}, /* top front left center */
|
||||
+ {"tfrc", SNDRV_CHMAP_TFRC}, /* top front right center */
|
||||
+ {"tsl", SNDRV_CHMAP_TSL}, /* top side left */
|
||||
+ {"tsr", SNDRV_CHMAP_TSR}, /* top side right */
|
||||
+ {"llfe", SNDRV_CHMAP_LLFE}, /* left LFE */
|
||||
+ {"rlfe", SNDRV_CHMAP_RLFE}, /* right LFE */
|
||||
+ {"bc", SNDRV_CHMAP_BC}, /* bottom center */
|
||||
+ {"blc", SNDRV_CHMAP_BLC}, /* bottom left center */
|
||||
+ {"brc", SNDRV_CHMAP_BRC}, /* bottom right center */
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static int lookup_channel(const char *c)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(channel_map); i++) {
|
||||
+ if (strcasecmp(channel_map[i].name, c) == 0) {
|
||||
+ return channel_map[i].id;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+/* Parse a channel mapping. */
|
||||
+int tplg_parse_channel(snd_tplg_t *tplg,
|
||||
+ snd_config_t *cfg, void *private)
|
||||
+{
|
||||
+ snd_config_iterator_t i, next;
|
||||
+ snd_config_t *n;
|
||||
+ struct snd_soc_tplg_channel *channel = private;
|
||||
+ const char *id, *value;
|
||||
+
|
||||
+ if (tplg->channel_idx >= SND_SOC_TPLG_MAX_CHAN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ channel += tplg->channel_idx;
|
||||
+ snd_config_get_id(cfg, &id);
|
||||
+ tplg_dbg("\tChannel %s at index %d\n", id, tplg->channel_idx);
|
||||
+
|
||||
+ channel->id = lookup_channel(id);
|
||||
+ if (channel->id < 0) {
|
||||
+ SNDERR("error: invalid channel %s\n", id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ channel->size = sizeof(*channel);
|
||||
+ tplg_dbg("\tChan %s = %d\n", id, channel->id);
|
||||
+
|
||||
+ snd_config_for_each(i, next, cfg) {
|
||||
+
|
||||
+ n = snd_config_iterator_entry(i);
|
||||
+
|
||||
+ /* get id */
|
||||
+ if (snd_config_get_id(n, &id) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* get value */
|
||||
+ if (snd_config_get_string(n, &value) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(id, "reg") == 0)
|
||||
+ channel->reg = atoi(value);
|
||||
+ else if (strcmp(id, "shift") == 0)
|
||||
+ channel->shift = atoi(value);
|
||||
+
|
||||
+ tplg_dbg("\t\t%s = %s\n", id, value);
|
||||
+ }
|
||||
+
|
||||
+ tplg->channel_idx++;
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,350 +0,0 @@
|
||||
From 1d1dff56767842a99d2e06a6997079c0516dec68 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:22 +0100
|
||||
Subject: [PATCH 44/49] topology: Add binary file builder.
|
||||
|
||||
Build the binary output file from all the locally parsed objects and elements.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/builder.c | 327 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 327 insertions(+)
|
||||
create mode 100644 src/topology/builder.c
|
||||
|
||||
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
||||
new file mode 100644
|
||||
index 000000000000..0066b220353c
|
||||
--- /dev/null
|
||||
+++ b/src/topology/builder.c
|
||||
@@ -0,0 +1,327 @@
|
||||
+/*
|
||||
+ Copyright(c) 2014-2015 Intel Corporation
|
||||
+ All rights reserved.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of version 2 of the GNU General Public License as
|
||||
+ published by the Free Software Foundation.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ Authors: Mengdong Lin <mengdong.lin@intel.com>
|
||||
+ Yao Jin <yao.jin@intel.com>
|
||||
+ Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
+*/
|
||||
+
|
||||
+#include "list.h"
|
||||
+#include "tplg_local.h"
|
||||
+
|
||||
+/* verbose output detailing each object size and file position */
|
||||
+static void verbose(snd_tplg_t *tplg, const char *fmt, ...)
|
||||
+{
|
||||
+ int offset;
|
||||
+ va_list va;
|
||||
+
|
||||
+ if (!tplg->verbose)
|
||||
+ return;
|
||||
+
|
||||
+ offset = lseek(tplg->out_fd, 0, SEEK_CUR);
|
||||
+
|
||||
+ va_start(va, fmt);
|
||||
+ fprintf(stdout, "0x%6.6x/%6.6d -", offset, offset);
|
||||
+ vfprintf(stdout, fmt, va);
|
||||
+ va_end(va);
|
||||
+}
|
||||
+
|
||||
+/* write out block header to output file */
|
||||
+static int write_block_header(snd_tplg_t *tplg, unsigned int type,
|
||||
+ unsigned int vendor_type, unsigned int version, unsigned int index,
|
||||
+ size_t payload_size, int count)
|
||||
+{
|
||||
+ struct snd_soc_tplg_hdr hdr;
|
||||
+ size_t bytes;
|
||||
+ int offset = lseek(tplg->out_fd, 0, SEEK_CUR);
|
||||
+
|
||||
+ memset(&hdr, 0, sizeof(hdr));
|
||||
+ hdr.magic = SND_SOC_TPLG_MAGIC;
|
||||
+ hdr.abi = SND_SOC_TPLG_ABI_VERSION;
|
||||
+ hdr.type = type;
|
||||
+ hdr.vendor_type = vendor_type;
|
||||
+ hdr.version = version;
|
||||
+ hdr.payload_size = payload_size;
|
||||
+ hdr.index = index;
|
||||
+ hdr.size = sizeof(hdr);
|
||||
+ hdr.count = count;
|
||||
+
|
||||
+ /* make sure file offset is aligned with the calculated HDR offset */
|
||||
+ if ((unsigned int)offset != tplg->next_hdr_pos) {
|
||||
+ SNDERR("error: New header is at offset 0x%x but file"
|
||||
+ " offset 0x%x is %s by %d bytes\n",
|
||||
+ tplg->next_hdr_pos, offset,
|
||||
+ (unsigned int)offset > tplg->next_hdr_pos ? "ahead" : "behind",
|
||||
+ abs(offset - tplg->next_hdr_pos));
|
||||
+ exit(-EINVAL);
|
||||
+ }
|
||||
+
|
||||
+ verbose(tplg, " header type %d size 0x%lx/%ld vendor %d "
|
||||
+ "version %d\n", type, (long unsigned int)payload_size,
|
||||
+ (long int)payload_size, vendor_type, version);
|
||||
+
|
||||
+ tplg->next_hdr_pos += hdr.payload_size + sizeof(hdr);
|
||||
+
|
||||
+ bytes = write(tplg->out_fd, &hdr, sizeof(hdr));
|
||||
+ if (bytes != sizeof(hdr)) {
|
||||
+ SNDERR("error: can't write section header %lu\n",
|
||||
+ (long unsigned int)bytes);
|
||||
+ return bytes;
|
||||
+ }
|
||||
+
|
||||
+ return bytes;
|
||||
+}
|
||||
+
|
||||
+static int write_data_block(snd_tplg_t *tplg, int size, int tplg_type,
|
||||
+ const char *obj_name, void *data)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /* write the header for this block */
|
||||
+ ret = write_block_header(tplg, tplg_type, 0,
|
||||
+ SND_SOC_TPLG_ABI_VERSION, 0, size, 1);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("error: failed to write %s block %d\n", obj_name, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ verbose(tplg, " %s : write %d bytes\n", obj_name, size);
|
||||
+
|
||||
+ ret = write(tplg->out_fd, data, size);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("error: failed to write %s %d\n", obj_name, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int write_elem_block(snd_tplg_t *tplg,
|
||||
+ struct list_head *base, int size, int tplg_type, const char *obj_name)
|
||||
+{
|
||||
+ struct list_head *pos;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int ret, wsize = 0, count = 0, vendor_type;
|
||||
+
|
||||
+ /* count number of elements */
|
||||
+ list_for_each(pos, base)
|
||||
+ count++;
|
||||
+
|
||||
+ /* write the header for this block */
|
||||
+ list_for_each(pos, base) {
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+ vendor_type = elem->vendor_type;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ ret = write_block_header(tplg, tplg_type, vendor_type,
|
||||
+ SND_SOC_TPLG_ABI_VERSION, 0, size, count);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("error: failed to write %s block %d\n",
|
||||
+ obj_name, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write each elem to block */
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+
|
||||
+ /* compound elems have already been copied to other elems */
|
||||
+ if (elem->compound_elem)
|
||||
+ continue;
|
||||
+
|
||||
+ if (elem->type != OBJECT_TYPE_DAPM_GRAPH)
|
||||
+ verbose(tplg, " %s '%s': write %d bytes\n",
|
||||
+ obj_name, elem->id, elem->size);
|
||||
+ else
|
||||
+ verbose(tplg, " %s '%s': write %d bytes\n",
|
||||
+ obj_name, elem->route->source, elem->size);
|
||||
+
|
||||
+ count = write(tplg->out_fd, elem->obj, elem->size);
|
||||
+ if (count < 0) {
|
||||
+ SNDERR("error: failed to write %s %d\n",
|
||||
+ obj_name, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ wsize += count;
|
||||
+ }
|
||||
+
|
||||
+ /* make sure we have written the correct size */
|
||||
+ if (wsize != size) {
|
||||
+ SNDERR("error: size mismatch. Expected %d wrote %d\n",
|
||||
+ size, wsize);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int calc_block_size(struct list_head *base)
|
||||
+{
|
||||
+ struct list_head *pos;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int size = 0;
|
||||
+
|
||||
+ list_for_each(pos, base) {
|
||||
+
|
||||
+ elem = list_entry(pos, struct tplg_elem, list);
|
||||
+
|
||||
+ /* compound elems have already been copied to other elems */
|
||||
+ if (elem->compound_elem)
|
||||
+ continue;
|
||||
+
|
||||
+ size += elem->size;
|
||||
+ }
|
||||
+
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+static int write_block(snd_tplg_t *tplg, struct list_head *base,
|
||||
+ int type)
|
||||
+{
|
||||
+ int size;
|
||||
+
|
||||
+ /* calculate the block size in bytes for all elems in this list */
|
||||
+ size = calc_block_size(base);
|
||||
+ if (size <= 0)
|
||||
+ return size;
|
||||
+
|
||||
+ verbose(tplg, " block size for type %d is %d\n", type, size);
|
||||
+
|
||||
+ /* write each elem for this block */
|
||||
+ switch (type) {
|
||||
+ case OBJECT_TYPE_MIXER:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_MIXER, "mixer");
|
||||
+ case OBJECT_TYPE_BYTES:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_BYTES, "bytes");
|
||||
+ case OBJECT_TYPE_ENUM:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_ENUM, "enum");
|
||||
+ case OBJECT_TYPE_DAPM_GRAPH:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_DAPM_GRAPH, "route");
|
||||
+ case OBJECT_TYPE_DAPM_WIDGET:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_DAPM_WIDGET, "widget");
|
||||
+ case OBJECT_TYPE_PCM:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_PCM, "pcm");
|
||||
+ case OBJECT_TYPE_BE:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_DAI_LINK, "be");
|
||||
+ case OBJECT_TYPE_CC:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_DAI_LINK, "cc");
|
||||
+ case OBJECT_TYPE_MANIFEST:
|
||||
+ return write_data_block(tplg, size, SND_SOC_TPLG_TYPE_MANIFEST,
|
||||
+ "manifest", &tplg->manifest);
|
||||
+ case OBJECT_TYPE_DATA:
|
||||
+ return write_elem_block(tplg, base, size,
|
||||
+ SND_SOC_TPLG_TYPE_PDATA, "data");
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_write_data(snd_tplg_t *tplg)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /* write manifest */
|
||||
+ ret = write_data_block(tplg, sizeof(tplg->manifest),
|
||||
+ OBJECT_TYPE_MANIFEST, "manifest", &tplg->manifest);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write manifest %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write mixer elems. */
|
||||
+ ret = write_block(tplg, &tplg->mixer_list,
|
||||
+ OBJECT_TYPE_MIXER);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write control elems %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write enum control elems. */
|
||||
+ ret = write_block(tplg, &tplg->enum_list,
|
||||
+ OBJECT_TYPE_ENUM);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write control elems %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write bytes extended control elems. */
|
||||
+ ret = write_block(tplg, &tplg->bytes_ext_list,
|
||||
+ OBJECT_TYPE_BYTES);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write control elems %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write widget elems */
|
||||
+ ret = write_block(tplg, &tplg->widget_list,
|
||||
+ OBJECT_TYPE_DAPM_WIDGET);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write widget elems %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write pcm elems */
|
||||
+ ret = write_block(tplg, &tplg->pcm_list,
|
||||
+ OBJECT_TYPE_PCM);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write pcm elems %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write be elems */
|
||||
+ ret = write_block(tplg, &tplg->be_list,
|
||||
+ OBJECT_TYPE_BE);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write be elems %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write cc elems */
|
||||
+ ret = write_block(tplg, &tplg->cc_list,
|
||||
+ OBJECT_TYPE_CC);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write cc elems %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write route elems */
|
||||
+ ret = write_block(tplg, &tplg->route_list,
|
||||
+ OBJECT_TYPE_DAPM_GRAPH);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write graph elems %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* write private data */
|
||||
+ ret = write_block(tplg, &tplg->pdata_list,
|
||||
+ OBJECT_TYPE_DATA);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("failed to write private data %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,125 +0,0 @@
|
||||
From fec1e8f25374ec8eb4d57ee43e94e9689a748678 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:23 +0100
|
||||
Subject: [PATCH 45/49] topology: autotools: Add build support for topology
|
||||
core
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
configure.ac | 9 ++++++++-
|
||||
include/Makefile.am | 4 ++++
|
||||
src/Makefile.am | 7 +++++++
|
||||
src/topology/Makefile.am | 19 +++++++++++++++++++
|
||||
4 files changed, 38 insertions(+), 1 deletion(-)
|
||||
create mode 100644 src/topology/Makefile.am
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 9621d4e9ec2b..b6bea2dca434 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -380,6 +380,9 @@ AC_ARG_ENABLE(seq,
|
||||
AC_ARG_ENABLE(ucm,
|
||||
AS_HELP_STRING([--disable-ucm], [disable the use-case-manager component]),
|
||||
[build_ucm="$enableval"], [build_ucm="yes"])
|
||||
+AC_ARG_ENABLE(topology,
|
||||
+ AS_HELP_STRING([--disable-topology], [disable the DSP topology component]),
|
||||
+ [build_topology="$enableval"], [build_topology="yes"])
|
||||
AC_ARG_ENABLE(alisp,
|
||||
AS_HELP_STRING([--disable-alisp], [disable the alisp component]),
|
||||
[build_alisp="$enableval"], [build_alisp="yes"])
|
||||
@@ -422,6 +425,7 @@ AM_CONDITIONAL([BUILD_RAWMIDI], [test x$build_rawmidi = xyes])
|
||||
AM_CONDITIONAL([BUILD_HWDEP], [test x$build_hwdep = xyes])
|
||||
AM_CONDITIONAL([BUILD_SEQ], [test x$build_seq = xyes])
|
||||
AM_CONDITIONAL([BUILD_UCM], [test x$build_ucm = xyes])
|
||||
+AM_CONDITIONAL([BUILD_TOPOLOGY], [test x$build_topology = xyes])
|
||||
AM_CONDITIONAL([BUILD_ALISP], [test x$build_alisp = xyes])
|
||||
AM_CONDITIONAL([BUILD_PYTHON], [test x$build_python = xyes])
|
||||
|
||||
@@ -443,6 +447,9 @@ fi
|
||||
if test "$build_ucm" = "yes"; then
|
||||
AC_DEFINE([BUILD_UCM], "1", [Build UCM component])
|
||||
fi
|
||||
+if test "$build_topology" = "yes"; then
|
||||
+ AC_DEFINE([BUILD_TOPOLOGY], "1", [Build DSP Topology component])
|
||||
+fi
|
||||
|
||||
dnl PCM Plugins
|
||||
|
||||
@@ -643,7 +650,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
|
||||
src/pcm/Makefile src/pcm/scopes/Makefile \
|
||||
src/rawmidi/Makefile src/timer/Makefile \
|
||||
src/hwdep/Makefile src/seq/Makefile src/ucm/Makefile \
|
||||
- src/alisp/Makefile \
|
||||
+ src/alisp/Makefile src/topology/Makefile \
|
||||
src/conf/Makefile src/conf/alsa.conf.d/Makefile \
|
||||
src/conf/cards/Makefile \
|
||||
src/conf/pcm/Makefile \
|
||||
diff --git a/include/Makefile.am b/include/Makefile.am
|
||||
index 4baa03af69e1..ff931fda24d5 100644
|
||||
--- a/include/Makefile.am
|
||||
+++ b/include/Makefile.am
|
||||
@@ -50,6 +50,10 @@ if BUILD_UCM
|
||||
alsainclude_HEADERS += use-case.h
|
||||
endif
|
||||
|
||||
+if BUILD_TOPOLOGY
|
||||
+alsainclude_HEADERS += topology.h
|
||||
+endif
|
||||
+
|
||||
if BUILD_ALISP
|
||||
alsainclude_HEADERS += alisp.h
|
||||
endif
|
||||
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||
index fa255ff43ee0..57686a612fd8 100644
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -42,6 +42,10 @@ if BUILD_UCM
|
||||
SUBDIRS += ucm
|
||||
libasound_la_LIBADD += ucm/libucm.la
|
||||
endif
|
||||
+if BUILD_TOPOLOGY
|
||||
+SUBDIRS += topology
|
||||
+libasound_la_LIBADD += topology/libtopology.la
|
||||
+endif
|
||||
if BUILD_ALISP
|
||||
SUBDIRS += alisp
|
||||
libasound_la_LIBADD += alisp/libalisp.la
|
||||
@@ -81,6 +85,9 @@ seq/libseq.la:
|
||||
ucm/libucm.la:
|
||||
$(MAKE) -C ucm libucm.la
|
||||
|
||||
+topology/libtopology.la:
|
||||
+ $(MAKE) -C topology libtopology.la
|
||||
+
|
||||
instr/libinstr.la:
|
||||
$(MAKE) -C instr libinstr.la
|
||||
|
||||
diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am
|
||||
new file mode 100644
|
||||
index 000000000000..3fb8bf7a9290
|
||||
--- /dev/null
|
||||
+++ b/src/topology/Makefile.am
|
||||
@@ -0,0 +1,19 @@
|
||||
+EXTRA_LTLIBRARIES = libtopology.la
|
||||
+
|
||||
+libtopology_la_SOURCES =\
|
||||
+ parser.c \
|
||||
+ builder.c \
|
||||
+ ctl.c \
|
||||
+ dapm.c \
|
||||
+ pcm.c \
|
||||
+ data.c \
|
||||
+ text.c \
|
||||
+ channel.c \
|
||||
+ ops.c \
|
||||
+ elem.c
|
||||
+
|
||||
+noinst_HEADERS = tplg_local.h
|
||||
+
|
||||
+all: libtopology.la
|
||||
+
|
||||
+AM_CPPFLAGS=-I$(top_srcdir)/include
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,60 +0,0 @@
|
||||
From 22603237b09ed50744030f550248ade135d4f73b Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:24 +0100
|
||||
Subject: [PATCH 46/49] topology: doxygen: Add doxygen support for topology
|
||||
core.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
doc/doxygen.cfg.in | 7 +++++--
|
||||
doc/index.doxygen | 1 +
|
||||
2 files changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in
|
||||
index 043e75b2d7eb..92bd52ba67a2 100644
|
||||
--- a/doc/doxygen.cfg.in
|
||||
+++ b/doc/doxygen.cfg.in
|
||||
@@ -29,6 +29,7 @@ INPUT = @top_srcdir@/doc/index.doxygen \
|
||||
@top_srcdir@/include/control_external.h \
|
||||
@top_srcdir@/include/mixer.h \
|
||||
@top_srcdir@/include/use-case.h \
|
||||
+ @top_srcdir@/include/topology.h \
|
||||
@top_srcdir@/src/error.c \
|
||||
@top_srcdir@/src/dlmisc.c \
|
||||
@top_srcdir@/src/async.c \
|
||||
@@ -78,7 +79,8 @@ INPUT = @top_srcdir@/doc/index.doxygen \
|
||||
@top_srcdir@/src/timer \
|
||||
@top_srcdir@/src/hwdep \
|
||||
@top_srcdir@/src/seq \
|
||||
- @top_srcdir@/src/ucm
|
||||
+ @top_srcdir@/src/ucm \
|
||||
+ @top_srcdir@/src/topology
|
||||
EXCLUDE = @top_srcdir@/src/control/control_local.h \
|
||||
@top_srcdir@/src/pcm/atomic.h \
|
||||
@top_srcdir@/src/pcm/interval.h \
|
||||
@@ -94,7 +96,8 @@ EXCLUDE = @top_srcdir@/src/control/control_local.h \
|
||||
@top_srcdir@/src/mixer/mixer_local.h \
|
||||
@top_srcdir@/src/rawmidi/rawmidi_local.h \
|
||||
@top_srcdir@/src/seq/seq_local.h \
|
||||
- @top_srcdir@/src/ucm/ucm_local.h
|
||||
+ @top_srcdir@/src/ucm/ucm_local.h \
|
||||
+ @top_srcdir@/src/topology/tplg_local.h
|
||||
RECURSIVE = YES
|
||||
FILE_PATTERNS = *.c *.h
|
||||
EXAMPLE_PATH = @top_srcdir@/test
|
||||
diff --git a/doc/index.doxygen b/doc/index.doxygen
|
||||
index 7d049fe5c32a..b40c75a5239b 100644
|
||||
--- a/doc/index.doxygen
|
||||
+++ b/doc/index.doxygen
|
||||
@@ -41,6 +41,7 @@ may be placed in the library code instead of the kernel driver.</P>
|
||||
<LI>Page \ref timer explains the design of the Timer API.
|
||||
<LI>Page \ref seq explains the design of the Sequencer API.
|
||||
<LI>Page \ref ucm explains the use case API.
|
||||
+ <LI>Page \ref topology explains the DSP topology API.
|
||||
</UL>
|
||||
|
||||
<H2>Configuration</H2>
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,443 +0,0 @@
|
||||
From 00a51b5bacb0f966d0e323bd9d3057c0eb0e6f23 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Wed, 29 Jul 2015 17:45:25 +0100
|
||||
Subject: [PATCH 47/49] conf: topology: Add topology file for broadwell audio
|
||||
DSP
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
configure.ac | 2 +
|
||||
src/conf/Makefile.am | 2 +-
|
||||
src/conf/topology/Makefile.am | 1 +
|
||||
src/conf/topology/broadwell/Makefile.am | 4 +
|
||||
src/conf/topology/broadwell/broadwell.conf | 375 +++++++++++++++++++++++++++++
|
||||
5 files changed, 383 insertions(+), 1 deletion(-)
|
||||
create mode 100644 src/conf/topology/Makefile.am
|
||||
create mode 100644 src/conf/topology/broadwell/Makefile.am
|
||||
create mode 100644 src/conf/topology/broadwell/broadwell.conf
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index b6bea2dca434..a482b3e7f6ca 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -663,6 +663,8 @@ 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/topology/Makefile \
|
||||
+ src/conf/topology/broadwell/Makefile \
|
||||
modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \
|
||||
alsalisp/Makefile aserver/Makefile \
|
||||
test/Makefile test/lsb/Makefile \
|
||||
diff --git a/src/conf/Makefile.am b/src/conf/Makefile.am
|
||||
index 948d5a1c822e..a04f73fddc65 100644
|
||||
--- a/src/conf/Makefile.am
|
||||
+++ b/src/conf/Makefile.am
|
||||
@@ -1,4 +1,4 @@
|
||||
-SUBDIRS=cards pcm alsa.conf.d ucm
|
||||
+SUBDIRS=cards pcm alsa.conf.d ucm topology
|
||||
|
||||
cfg_files = alsa.conf
|
||||
if BUILD_ALISP
|
||||
diff --git a/src/conf/topology/Makefile.am b/src/conf/topology/Makefile.am
|
||||
new file mode 100644
|
||||
index 000000000000..f56a96c651e5
|
||||
--- /dev/null
|
||||
+++ b/src/conf/topology/Makefile.am
|
||||
@@ -0,0 +1 @@
|
||||
+SUBDIRS=broadwell
|
||||
diff --git a/src/conf/topology/broadwell/Makefile.am b/src/conf/topology/broadwell/Makefile.am
|
||||
new file mode 100644
|
||||
index 000000000000..35d1e83cb645
|
||||
--- /dev/null
|
||||
+++ b/src/conf/topology/broadwell/Makefile.am
|
||||
@@ -0,0 +1,4 @@
|
||||
+alsaconfigdir = @ALSA_CONFIG_DIR@
|
||||
+topologydir = $(alsaconfigdir)/topology/broadwell
|
||||
+topology_DATA = broadwell.conf
|
||||
+EXTRA_DIST = $(topology_DATA)
|
||||
diff --git a/src/conf/topology/broadwell/broadwell.conf b/src/conf/topology/broadwell/broadwell.conf
|
||||
new file mode 100644
|
||||
index 000000000000..05b3889bec58
|
||||
--- /dev/null
|
||||
+++ b/src/conf/topology/broadwell/broadwell.conf
|
||||
@@ -0,0 +1,375 @@
|
||||
+# Dynamic Firmware Configuration for Broadwell
|
||||
+
|
||||
+# TLV
|
||||
+SectionTLV."hsw_vol_tlv" {
|
||||
+ Comment "TLV used by both global and stream volumes"
|
||||
+
|
||||
+ scale {
|
||||
+ min "-9000"
|
||||
+ step "300"
|
||||
+ mute "1"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Controls
|
||||
+SectionControlMixer."Master Playback Volume" {
|
||||
+ Comment "Global DSP volume"
|
||||
+
|
||||
+ # control belongs to this index group
|
||||
+ index "1"
|
||||
+
|
||||
+ # Channel register and shift for Front Left/Right
|
||||
+ channel."FL" {
|
||||
+ reg "0"
|
||||
+ shift "0"
|
||||
+ }
|
||||
+ channel."FR" {
|
||||
+ reg "0"
|
||||
+ shift "8"
|
||||
+ }
|
||||
+
|
||||
+ # max control value and whether value is inverted
|
||||
+ max "31"
|
||||
+ invert "false"
|
||||
+
|
||||
+ # control uses bespoke driver get/put/info ID 0
|
||||
+ ops."ctl" {
|
||||
+ info "volsw"
|
||||
+ get "256"
|
||||
+ put "256"
|
||||
+ }
|
||||
+
|
||||
+ # uses TLV data above
|
||||
+ tlv "hsw_vol_tlv"
|
||||
+}
|
||||
+
|
||||
+SectionControlMixer."Media0 Playback Volume" {
|
||||
+ Comment "Offload 0 volume"
|
||||
+
|
||||
+ # control belongs to this index group
|
||||
+ index "1"
|
||||
+
|
||||
+ # Channel register and shift for Front Left/Right
|
||||
+ channel."FL" {
|
||||
+ reg "1"
|
||||
+ shift "0"
|
||||
+ }
|
||||
+ channel."FR" {
|
||||
+ reg "1"
|
||||
+ shift "8"
|
||||
+ }
|
||||
+
|
||||
+ # max control value and whether value is inverted
|
||||
+ max "31"
|
||||
+ invert "false"
|
||||
+
|
||||
+ # control uses bespoke driver get/put/info ID 0
|
||||
+ ops."ctl" {
|
||||
+ info "volsw"
|
||||
+ get "257"
|
||||
+ put "257"
|
||||
+ }
|
||||
+
|
||||
+ # uses TLV data above
|
||||
+ tlv "hsw_vol_tlv"
|
||||
+}
|
||||
+
|
||||
+SectionControlMixer."Media1 Playback Volume" {
|
||||
+ Comment "Offload 1 volume"
|
||||
+
|
||||
+ # control belongs to this index group
|
||||
+ index "1"
|
||||
+
|
||||
+ # Channel register and shift for Front Left/Right
|
||||
+ channel."FL" {
|
||||
+ reg "2"
|
||||
+ shift "0"
|
||||
+ }
|
||||
+ channel."FR" {
|
||||
+ reg "2"
|
||||
+ shift "8"
|
||||
+ }
|
||||
+
|
||||
+ # max control value and whether value is inverted
|
||||
+ max "31"
|
||||
+ invert "false"
|
||||
+
|
||||
+ # control uses bespoke driver get/put/info ID 0
|
||||
+ ops."ctl" {
|
||||
+ info "volsw"
|
||||
+ get "257"
|
||||
+ put "257"
|
||||
+ }
|
||||
+
|
||||
+ # uses TLV data above
|
||||
+ tlv "hsw_vol_tlv"
|
||||
+}
|
||||
+
|
||||
+SectionControlMixer."Mic Capture Volume" {
|
||||
+ Comment "Mic Capture volume"
|
||||
+
|
||||
+ # control belongs to this index group
|
||||
+ index "1"
|
||||
+
|
||||
+ # Channel register and shift for Front Left/Right
|
||||
+ channel."FL" {
|
||||
+ reg "0"
|
||||
+ shift "0"
|
||||
+ }
|
||||
+ channel."FR" {
|
||||
+ reg "0"
|
||||
+ shift "8"
|
||||
+ }
|
||||
+
|
||||
+ # max control value and whether value is inverted
|
||||
+ max "31"
|
||||
+ invert "false"
|
||||
+
|
||||
+ # control uses bespoke driver get/put/info ID 0
|
||||
+ ops."ctl" {
|
||||
+ info "volsw"
|
||||
+ get "257"
|
||||
+ put "257"
|
||||
+ }
|
||||
+
|
||||
+ # uses TLV data above
|
||||
+ tlv "hsw_vol_tlv"
|
||||
+}
|
||||
+
|
||||
+SectionWidget."SSP0 CODEC IN" {
|
||||
+
|
||||
+ index "1"
|
||||
+ type "aif_in"
|
||||
+ no_pm "true"
|
||||
+ shift "0"
|
||||
+ invert "0"
|
||||
+}
|
||||
+
|
||||
+SectionWidget."SSP0 CODEC OUT" {
|
||||
+
|
||||
+ index "1"
|
||||
+ type "aif_out"
|
||||
+ no_pm "true"
|
||||
+ shift "0"
|
||||
+ invert "0"
|
||||
+}
|
||||
+
|
||||
+SectionWidget."SSP1 BT IN" {
|
||||
+
|
||||
+ index "1"
|
||||
+ type "aif_in"
|
||||
+ no_pm "true"
|
||||
+ shift "0"
|
||||
+ invert "0"
|
||||
+}
|
||||
+
|
||||
+SectionWidget."SSP1 BT OUT" {
|
||||
+
|
||||
+ index "1"
|
||||
+ type "aif_out"
|
||||
+ no_pm "true"
|
||||
+ shift "0"
|
||||
+ invert "0"
|
||||
+}
|
||||
+
|
||||
+SectionWidget."Playback VMixer" {
|
||||
+
|
||||
+ index "1"
|
||||
+ type "mixer"
|
||||
+ no_pm "true"
|
||||
+ shift "0"
|
||||
+ invert "0"
|
||||
+}
|
||||
+
|
||||
+# PCM Configurations supported by FW
|
||||
+SectionPCMConfig."PCM 48k Stereo 24bit" {
|
||||
+
|
||||
+ config."playback" {
|
||||
+ format "S24_LE"
|
||||
+ rate "48000"
|
||||
+ channels "2"
|
||||
+ tdm_slot "0xf"
|
||||
+ }
|
||||
+
|
||||
+ config."capture" {
|
||||
+ format "S24_LE"
|
||||
+ rate "48000"
|
||||
+ channels "2"
|
||||
+ tdm_slot "0xf"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionPCMConfig."PCM 48k Stereo 16bit" {
|
||||
+
|
||||
+ config."playback" {
|
||||
+ format "S16_LE"
|
||||
+ rate "48000"
|
||||
+ channels "2"
|
||||
+ tdm_slot "0xf"
|
||||
+ }
|
||||
+
|
||||
+ config."capture" {
|
||||
+ format "S16_LE"
|
||||
+ rate "48000"
|
||||
+ channels "2"
|
||||
+ tdm_slot "0xf"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionPCMConfig."PCM 48k 2P/4C 16bit" {
|
||||
+
|
||||
+ config."playback" {
|
||||
+ format "S16_LE"
|
||||
+ rate "48000"
|
||||
+ channels "2"
|
||||
+ tdm_slot "0xf"
|
||||
+ }
|
||||
+
|
||||
+ config."capture" {
|
||||
+ format "S16_LE"
|
||||
+ rate "48000"
|
||||
+ channels "4"
|
||||
+ tdm_slot "0xf"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# PCM capabilities supported by FW
|
||||
+SectionPCMCapabilities."System Playback" {
|
||||
+
|
||||
+ formats "S24_LE,S16_LE"
|
||||
+ rate_min "48000"
|
||||
+ rate_max "48000"
|
||||
+ channels_min "2"
|
||||
+ channels_max "2"
|
||||
+}
|
||||
+
|
||||
+SectionPCMCapabilities."Analog Capture" {
|
||||
+
|
||||
+ formats "S24_LE,S16_LE"
|
||||
+ rate_min "48000"
|
||||
+ rate_max "48000"
|
||||
+ channels_min "2"
|
||||
+ channels_max "4"
|
||||
+}
|
||||
+
|
||||
+SectionPCMCapabilities."Loopback Capture" {
|
||||
+
|
||||
+ formats "S24_LE,S16_LE"
|
||||
+ rate_min "48000"
|
||||
+ rate_max "48000"
|
||||
+ channels_min "2"
|
||||
+ channels_max "2"
|
||||
+}
|
||||
+
|
||||
+SectionPCMCapabilities."Offload0 Playback" {
|
||||
+ formats "S24_LE,S16_LE"
|
||||
+ rate_min "8000"
|
||||
+ rate_max "192000"
|
||||
+ channels_min "2"
|
||||
+ channels_max "2"
|
||||
+}
|
||||
+
|
||||
+SectionPCMCapabilities."Offload1 Playback" {
|
||||
+ formats "S24_LE,S16_LE"
|
||||
+ rate_min "8000"
|
||||
+ rate_max "48000"
|
||||
+ channels_min "2"
|
||||
+ channels_max "2"
|
||||
+}
|
||||
+
|
||||
+# PCM devices exported by Firmware
|
||||
+SectionPCM."System Pin" {
|
||||
+
|
||||
+ index "1"
|
||||
+
|
||||
+ # used for binding to the PCM
|
||||
+ ID "0"
|
||||
+
|
||||
+ pcm."playback" {
|
||||
+
|
||||
+ capabilities "System Playback"
|
||||
+
|
||||
+ configs [
|
||||
+ "PCM 48k Stereo 24bit"
|
||||
+ "PCM 48k Stereo 16bit"
|
||||
+ ]
|
||||
+ }
|
||||
+
|
||||
+ pcm."capture" {
|
||||
+
|
||||
+ capabilities "Analog Capture"
|
||||
+
|
||||
+ configs [
|
||||
+ "PCM 48k Stereo 24bit"
|
||||
+ "PCM 48k Stereo 16bit"
|
||||
+ "PCM 48k 2P/4C 16bit"
|
||||
+ ]
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionPCM."Offload0 Pin" {
|
||||
+
|
||||
+ index "1"
|
||||
+
|
||||
+ # used for binding to the PCM
|
||||
+ ID "1"
|
||||
+
|
||||
+ pcm."playback" {
|
||||
+
|
||||
+ capabilities "Offload0 Playback"
|
||||
+
|
||||
+ configs [
|
||||
+ "PCM 48k Stereo 24bit"
|
||||
+ "PCM 48k Stereo 16bit"
|
||||
+ ]
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionPCM."Offload1 Pin" {
|
||||
+
|
||||
+ index "1"
|
||||
+
|
||||
+ # used for binding to the PCM
|
||||
+ ID "2"
|
||||
+
|
||||
+ pcm."playback" {
|
||||
+
|
||||
+ capabilities "Offload1 Playback"
|
||||
+
|
||||
+ configs [
|
||||
+ "PCM 48k Stereo 24bit"
|
||||
+ "PCM 48k Stereo 16bit"
|
||||
+ ]
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionPCM."Loopback Pin" {
|
||||
+
|
||||
+ index "1"
|
||||
+
|
||||
+ # used for binding to the PCM
|
||||
+ ID "3"
|
||||
+
|
||||
+ pcm."capture" {
|
||||
+
|
||||
+ capabilities "Loopback Capture"
|
||||
+
|
||||
+ configs [
|
||||
+ "PCM 48k Stereo 24bit"
|
||||
+ "PCM 48k Stereo 16bit"
|
||||
+ ]
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+SectionGraph."dsp" {
|
||||
+ index "1"
|
||||
+
|
||||
+ lines [
|
||||
+ "Playback VMixer, , System Playback"
|
||||
+ "Playback VMixer, , Offload0 Playback"
|
||||
+ "Playback VMixer, , Offload1 Playback"
|
||||
+ "SSP0 CODEC OUT, , Playback VMixer"
|
||||
+ "Loopback Capture, , Playback VMixer"
|
||||
+ "Analog Capture, , SSP0 CODEC IN"
|
||||
+ ]
|
||||
+}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,28 +0,0 @@
|
||||
From 907e464593a2acf51c2e2be4c3d4e098efdd95ff Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 30 Jul 2015 16:34:50 +0200
|
||||
Subject: [PATCH 48/49] topology: Fix missing inclusion of ctype.h
|
||||
|
||||
Fix a compile warning:
|
||||
data.c:116:7: warning: implicit declaration of function 'isspace' [-Wimplicit-function-declaration]
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/data.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/topology/data.c b/src/topology/data.c
|
||||
index ae664721935d..13e1e2bb60fb 100644
|
||||
--- a/src/topology/data.c
|
||||
+++ b/src/topology/data.c
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "list.h"
|
||||
#include "tplg_local.h"
|
||||
+#include <ctype.h>
|
||||
|
||||
/* Get Private data from a file. */
|
||||
static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,96 +0,0 @@
|
||||
From 66ce9f9a1177de3b8e8304323b4d3a16d78ead32 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Thu, 30 Jul 2015 16:43:19 +0200
|
||||
Subject: [PATCH 49/49] topology: Fix typos
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/topology.h | 18 +++++++++---------
|
||||
1 file changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/include/topology.h b/include/topology.h
|
||||
index f604ed1450d3..0cb2d79e5574 100644
|
||||
--- a/include/topology.h
|
||||
+++ b/include/topology.h
|
||||
@@ -48,7 +48,7 @@ extern "C" {
|
||||
*
|
||||
* The topology text format uses the standard ALSA configuration file format to
|
||||
* describe each topology object type. This allows topology objects to include
|
||||
- * other topology objects as part of thier definition. i.e. a TLV data object
|
||||
+ * other topology objects as part of their definition. i.e. a TLV data object
|
||||
* can be shared amongst many control objects that use the same TLV data.
|
||||
*
|
||||
*
|
||||
@@ -174,7 +174,7 @@ extern "C" {
|
||||
* words "0xaabbccdd,0x11223344,0x66aa77bb,0xefef1234"
|
||||
* };
|
||||
* </pre>
|
||||
- * The file, bytes, shorts and words keywords are all mutulally exclusive as
|
||||
+ * The file, bytes, shorts and words keywords are all mutually exclusive as
|
||||
* the private data should only be taken from one source. The private data can
|
||||
* either be read from a separate file or defined in the topology file using
|
||||
* the bytes, shorts or words keywords.
|
||||
@@ -247,7 +247,7 @@ extern "C" {
|
||||
* can include channel mapping, callback operations, private data and
|
||||
* text strings to represent the enumerated control options.<br>
|
||||
*
|
||||
- * The text strings for the enumerated controls are defined in a seperate
|
||||
+ * The text strings for the enumerated controls are defined in a separate
|
||||
* section as follows :-
|
||||
*
|
||||
* <pre>
|
||||
@@ -306,7 +306,7 @@ extern "C" {
|
||||
* graph with other graphs, it's not used by the kernel atm.
|
||||
*
|
||||
* <h4>DAPM Widgets</h4>
|
||||
- * DAPM wigets are similar to controls in that they can include many other
|
||||
+ * DAPM widgets are similar to controls in that they can include many other
|
||||
* objects. Widgets can contain private data, mixer controls and enum controls.
|
||||
*
|
||||
* The following widget types are supported and match the driver types :-
|
||||
@@ -367,13 +367,13 @@ extern "C" {
|
||||
*
|
||||
* formats "S24_LE,S16_LE" # Supported formats
|
||||
* rate_min "48000" # Max supported sample rate
|
||||
- * rate_max "48000" # Min suppoprted sample rate
|
||||
+ * rate_max "48000" # Min supported sample rate
|
||||
* channels_min "2" # Min number of channels
|
||||
* channels_max "2" # max number of channels
|
||||
* }
|
||||
* </pre>
|
||||
* The supported formats use the same naming convention as the driver macros.
|
||||
- * The PCM capabilities name can be reffered to and included by BE, PCM and
|
||||
+ * The PCM capabilities name can be referred to and included by BE, PCM and
|
||||
* Codec <-> codec topology sections.
|
||||
*
|
||||
* <h4>PCM Configurations</h4>
|
||||
@@ -400,7 +400,7 @@ extern "C" {
|
||||
* </pre>
|
||||
*
|
||||
* The supported formats use the same naming convention as the driver macros.
|
||||
- * The PCM configuration name can be reffered to and included by BE, PCM and
|
||||
+ * The PCM configuration name can be referred to and included by BE, PCM and
|
||||
* Codec <-> codec topology sections.
|
||||
*
|
||||
* <h4>PCM Configurations</h4>
|
||||
@@ -434,7 +434,7 @@ extern "C" {
|
||||
* id "0" # used for binding to the PCM
|
||||
*
|
||||
* pcm."playback" {
|
||||
- * capabilities "capabilities1" # capbilities for playback
|
||||
+ * capabilities "capabilities1" # capabilities for playback
|
||||
*
|
||||
* configs [ # supported configs for playback
|
||||
* "config1"
|
||||
@@ -476,7 +476,7 @@ void snd_tplg_free(snd_tplg_t *tplg);
|
||||
* \param tplg Topology instance.
|
||||
* \param infile Topology text input file to be parsed
|
||||
* \param outfile Binary topology output file.
|
||||
- * \return Zero on sucess, otherwise a negative error code
|
||||
+ * \return Zero on success, otherwise a negative error code
|
||||
*/
|
||||
int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
|
||||
const char *outfile);
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,29 +0,0 @@
|
||||
From 1bb4c2fc304515278e6510ba7288b94f99f50bcd Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Tue, 4 Aug 2015 18:06:55 +0100
|
||||
Subject: [PATCH] topology: fix element object type is switch()
|
||||
|
||||
Use the correct type for this object.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/elem.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/topology/elem.c b/src/topology/elem.c
|
||||
index 32ba2c12375b..d7a1fd715d49 100644
|
||||
--- a/src/topology/elem.c
|
||||
+++ b/src/topology/elem.c
|
||||
@@ -137,7 +137,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
|
||||
list_add_tail(&elem->list, &tplg->enum_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_enum_control);
|
||||
break;
|
||||
- case SND_SOC_TPLG_TYPE_MIXER:
|
||||
+ case OBJECT_TYPE_MIXER:
|
||||
list_add_tail(&elem->list, &tplg->mixer_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_mixer_control);
|
||||
break;
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,207 +0,0 @@
|
||||
From 120b3b8eadd9a2a4c2ede0a246bffa1cfac562a9 Mon Sep 17 00:00:00 2001
|
||||
From: Jin Yao <yao.jin@linux.intel.com>
|
||||
Date: Tue, 4 Aug 2015 18:09:12 +0100
|
||||
Subject: [PATCH] topology: Add element ID so we can look up references by
|
||||
name.
|
||||
|
||||
Add support to lookup elements by name. This is in preparation for adding
|
||||
some new API calls that will allow building topology data using a C API. This
|
||||
will allow applications to build their own topology data directly.
|
||||
|
||||
Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
|
||||
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/ctl.c | 9 ++++-----
|
||||
src/topology/dapm.c | 2 +-
|
||||
src/topology/data.c | 2 +-
|
||||
src/topology/elem.c | 15 +++++++++++----
|
||||
src/topology/pcm.c | 10 +++++-----
|
||||
src/topology/text.c | 2 +-
|
||||
src/topology/tplg_local.h | 2 +-
|
||||
7 files changed, 24 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
|
||||
index 9c1333c1fc88..aa06ff64bc48 100644
|
||||
--- a/src/topology/ctl.c
|
||||
+++ b/src/topology/ctl.c
|
||||
@@ -264,7 +264,7 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
int err = 0;
|
||||
struct tplg_elem *elem;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_TLV);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_TLV);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -298,7 +298,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_BYTES);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_BYTES);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -403,11 +403,10 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
const char *id, *val = NULL;
|
||||
int err, j;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_ENUM);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_ENUM);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
- /* init new mixer */
|
||||
ec = elem->enum_ctrl;
|
||||
elem_copy_text(ec->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
ec->hdr.type = SND_SOC_TPLG_TYPE_ENUM;
|
||||
@@ -501,7 +500,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err, j;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_MIXER);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_MIXER);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
|
||||
index 1da82adea470..7e26ea0326ec 100644
|
||||
--- a/src/topology/dapm.c
|
||||
+++ b/src/topology/dapm.c
|
||||
@@ -420,7 +420,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int widget_type, err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_DAPM_WIDGET);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_DAPM_WIDGET);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/topology/data.c b/src/topology/data.c
|
||||
index 13e1e2bb60fb..c768bc5b0b04 100644
|
||||
--- a/src/topology/data.c
|
||||
+++ b/src/topology/data.c
|
||||
@@ -268,7 +268,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
int err = 0;
|
||||
struct tplg_elem *elem;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_DATA);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_DATA);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/topology/elem.c b/src/topology/elem.c
|
||||
index d7a1fd715d49..7fee65332124 100644
|
||||
--- a/src/topology/elem.c
|
||||
+++ b/src/topology/elem.c
|
||||
@@ -103,20 +103,27 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
|
||||
|
||||
/* create a new common element and object */
|
||||
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
|
||||
- snd_config_t *cfg, enum object_type type)
|
||||
+ snd_config_t *cfg, const char *name, enum object_type type)
|
||||
{
|
||||
struct tplg_elem *elem;
|
||||
const char *id;
|
||||
int obj_size = 0;
|
||||
void *obj;
|
||||
|
||||
+ if (!cfg && !name)
|
||||
+ return NULL;
|
||||
+
|
||||
elem = tplg_elem_new();
|
||||
if (!elem)
|
||||
return NULL;
|
||||
|
||||
- snd_config_get_id(cfg, &id);
|
||||
- strncpy(elem->id, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
- elem->id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1] = 0;
|
||||
+ /* do we get name from cfg */
|
||||
+ if (cfg) {
|
||||
+ snd_config_get_id(cfg, &id);
|
||||
+ elem_copy_text(elem->id, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ elem->id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1] = 0;
|
||||
+ } else if (name != NULL)
|
||||
+ elem_copy_text(elem->id, name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
|
||||
switch (type) {
|
||||
case OBJECT_TYPE_DATA:
|
||||
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
|
||||
index 8f23a6f12ec4..deae47b771be 100644
|
||||
--- a/src/topology/pcm.c
|
||||
+++ b/src/topology/pcm.c
|
||||
@@ -228,7 +228,7 @@ int tplg_parse_pcm_config(snd_tplg_t *tplg,
|
||||
const char *id;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_STREAM_CONFIG);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_STREAM_CONFIG);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -294,7 +294,7 @@ int tplg_parse_pcm_caps(snd_tplg_t *tplg,
|
||||
char *s;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_STREAM_CAPS);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_STREAM_CAPS);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -461,7 +461,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_PCM);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_PCM);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -524,7 +524,7 @@ int tplg_parse_be(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_BE);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_BE);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -587,7 +587,7 @@ int tplg_parse_cc(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_CC);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_CC);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/topology/text.c b/src/topology/text.c
|
||||
index ebb6e3840d62..7128056d5d34 100644
|
||||
--- a/src/topology/text.c
|
||||
+++ b/src/topology/text.c
|
||||
@@ -64,7 +64,7 @@ int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
int err = 0;
|
||||
struct tplg_elem *elem;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, OBJECT_TYPE_TEXT);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_TEXT);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
|
||||
index 688c78f3a6a4..62788e4b7ca1 100644
|
||||
--- a/src/topology/tplg_local.h
|
||||
+++ b/src/topology/tplg_local.h
|
||||
@@ -216,7 +216,7 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base,
|
||||
const char* id,
|
||||
unsigned int type);
|
||||
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
|
||||
- snd_config_t *cfg, enum object_type type);
|
||||
+ snd_config_t *cfg, const char *name, enum object_type type);
|
||||
|
||||
static inline void elem_copy_text(char *dest, const char *src, int len)
|
||||
{
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,90 +0,0 @@
|
||||
From d5e7e8bb38681c2cbf3777314c422130a740810e Mon Sep 17 00:00:00 2001
|
||||
From: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Date: Tue, 4 Aug 2015 18:09:46 +0100
|
||||
Subject: [PATCH] topology: Add support for writing manifest private data.
|
||||
|
||||
Allow manifest to contain private data and write this data to file.
|
||||
|
||||
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/builder.c | 37 ++++++++++++++++++++++++++++++++-----
|
||||
src/topology/tplg_local.h | 1 +
|
||||
2 files changed, 33 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
||||
index 0066b220353c..a944866a2d68 100644
|
||||
--- a/src/topology/builder.c
|
||||
+++ b/src/topology/builder.c
|
||||
@@ -226,9 +226,6 @@ static int write_block(snd_tplg_t *tplg, struct list_head *base,
|
||||
case OBJECT_TYPE_CC:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_DAI_LINK, "cc");
|
||||
- case OBJECT_TYPE_MANIFEST:
|
||||
- return write_data_block(tplg, size, SND_SOC_TPLG_TYPE_MANIFEST,
|
||||
- "manifest", &tplg->manifest);
|
||||
case OBJECT_TYPE_DATA:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_PDATA, "data");
|
||||
@@ -239,13 +236,43 @@ static int write_block(snd_tplg_t *tplg, struct list_head *base,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* write the manifest including its private data */
|
||||
+static int write_manifest_data(snd_tplg_t *tplg)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /* write the header for this block */
|
||||
+ ret = write_block_header(tplg, SND_SOC_TPLG_TYPE_MANIFEST, 0,
|
||||
+ SND_SOC_TPLG_ABI_VERSION, 0,
|
||||
+ sizeof(tplg->manifest) + tplg->manifest.priv.size, 1);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("error: failed to write manifest block %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ verbose(tplg, "manifest : write %d bytes\n", sizeof(tplg->manifest));
|
||||
+ ret = write(tplg->out_fd, &tplg->manifest, sizeof(tplg->manifest));
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("error: failed to write manifest %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ verbose(tplg, "manifest : write %d priv bytes\n", tplg->manifest.priv.size);
|
||||
+ ret = write(tplg->out_fd, tplg->manifest_pdata, tplg->manifest.priv.size);
|
||||
+ if (ret < 0) {
|
||||
+ SNDERR("error: failed to write manifest priv data %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int tplg_write_data(snd_tplg_t *tplg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* write manifest */
|
||||
- ret = write_data_block(tplg, sizeof(tplg->manifest),
|
||||
- OBJECT_TYPE_MANIFEST, "manifest", &tplg->manifest);
|
||||
+ ret = write_manifest_data(tplg);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write manifest %d\n", ret);
|
||||
return ret;
|
||||
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
|
||||
index 62788e4b7ca1..ad38945056df 100644
|
||||
--- a/src/topology/tplg_local.h
|
||||
+++ b/src/topology/tplg_local.h
|
||||
@@ -77,6 +77,7 @@ struct snd_tplg {
|
||||
|
||||
/* manifest */
|
||||
struct snd_soc_tplg_manifest manifest;
|
||||
+ const void *manifest_pdata; /* copied by builder at file write */
|
||||
|
||||
/* list of each element type */
|
||||
struct list_head tlv_list;
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,136 +0,0 @@
|
||||
From 8c8372cc060ec16776db28f927c9402dcc09b001 Mon Sep 17 00:00:00 2001
|
||||
From: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Date: Wed, 5 Aug 2015 14:41:50 +0100
|
||||
Subject: [PATCH] topology: update ABI to improve support for different TLV
|
||||
object types.
|
||||
|
||||
Currently the TLV topology structure is targeted at only supporting the
|
||||
DB scale data. This patch extends support for the other TLV types so they
|
||||
can be easily added at a later stage.
|
||||
|
||||
TLV structure is moved to common topology control header since it's a
|
||||
common field for controls and can be processed in a general way.
|
||||
|
||||
Users must set a proper access flag for a control since it's used to decide
|
||||
if the TLV field is valid and if a TLV callback is needed.
|
||||
|
||||
Removed the following fields from topology TLV struct:
|
||||
- size/count: type can decide the size.
|
||||
- numid: not needed to initialize TLV for kcontrol.
|
||||
- data: replaced by the type specific struct.
|
||||
|
||||
Added TLV structure to generic control header and removed TLV structure from
|
||||
mixer control.
|
||||
|
||||
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/sound/asoc.h | 19 +++++++++++++------
|
||||
src/topology/ctl.c | 20 ++++++++------------
|
||||
2 files changed, 21 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/include/sound/asoc.h b/include/sound/asoc.h
|
||||
index bb6dcf3ff7b4..73eb80ef17cc 100644
|
||||
--- a/include/sound/asoc.h
|
||||
+++ b/include/sound/asoc.h
|
||||
@@ -135,11 +135,19 @@ struct snd_soc_tplg_private {
|
||||
/*
|
||||
* Kcontrol TLV data.
|
||||
*/
|
||||
+struct snd_soc_tplg_tlv_dbscale {
|
||||
+ __le32 min;
|
||||
+ __le32 step;
|
||||
+ __le32 mute;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
struct snd_soc_tplg_ctl_tlv {
|
||||
- __le32 size; /* in bytes aligned to 4 */
|
||||
- __le32 numid; /* control element numeric identification */
|
||||
- __le32 count; /* number of elem in data array */
|
||||
- __le32 data[SND_SOC_TPLG_TLV_SIZE];
|
||||
+ __le32 size; /* in bytes of this structure */
|
||||
+ __le32 type; /* SNDRV_CTL_TLVT_*, type of TLV */
|
||||
+ union {
|
||||
+ __le32 data[SND_SOC_TPLG_TLV_SIZE];
|
||||
+ struct snd_soc_tplg_tlv_dbscale scale;
|
||||
+ };
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
@@ -170,7 +178,7 @@ struct snd_soc_tplg_ctl_hdr {
|
||||
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
__le32 access;
|
||||
struct snd_soc_tplg_kcontrol_ops_id ops;
|
||||
- __le32 tlv_size; /* non zero means control has TLV data */
|
||||
+ struct snd_soc_tplg_ctl_tlv tlv;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
@@ -258,7 +266,6 @@ struct snd_soc_tplg_mixer_control {
|
||||
__le32 invert;
|
||||
__le32 num_channels;
|
||||
struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
|
||||
- struct snd_soc_tplg_ctl_tlv tlv;
|
||||
struct snd_soc_tplg_private priv;
|
||||
} __attribute__((packed));
|
||||
|
||||
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
|
||||
index aa06ff64bc48..930b50897220 100644
|
||||
--- a/src/topology/ctl.c
|
||||
+++ b/src/topology/ctl.c
|
||||
@@ -28,10 +28,7 @@ static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
tplg_dbg("TLV '%s' used by '%s\n", ref->id, elem->id);
|
||||
|
||||
/* TLV has a fixed size */
|
||||
- mixer_ctrl->tlv = *tlv;
|
||||
-
|
||||
- /* set size of TLV data */
|
||||
- mixer_ctrl->hdr.tlv_size = tlv->count * sizeof(uint32_t);
|
||||
+ mixer_ctrl->hdr.tlv = *tlv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -209,20 +206,19 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
snd_config_iterator_t i, next;
|
||||
snd_config_t *n;
|
||||
struct snd_soc_tplg_ctl_tlv *tplg_tlv;
|
||||
+ struct snd_soc_tplg_tlv_dbscale *scale;
|
||||
const char *id = NULL, *value = NULL;
|
||||
- int *data;
|
||||
|
||||
tplg_dbg(" scale: %s\n", elem->id);
|
||||
|
||||
tplg_tlv = calloc(1, sizeof(*tplg_tlv));
|
||||
if (!tplg_tlv)
|
||||
return -ENOMEM;
|
||||
- data = (int*)(tplg_tlv->data);
|
||||
|
||||
elem->tlv = tplg_tlv;
|
||||
- tplg_tlv->numid = SNDRV_CTL_TLVT_DB_SCALE;
|
||||
- tplg_tlv->count = 8;
|
||||
- tplg_tlv->size = sizeof(*tplg_tlv);
|
||||
+ tplg_tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
|
||||
+ tplg_tlv->type = SNDRV_CTL_TLVT_DB_SCALE;
|
||||
+ scale = &tplg_tlv->scale;
|
||||
|
||||
snd_config_for_each(i, next, cfg) {
|
||||
|
||||
@@ -242,11 +238,11 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
|
||||
/* get TLV data */
|
||||
if (strcmp(id, "min") == 0)
|
||||
- data[0] = atoi(value);
|
||||
+ scale->min = atoi(value);
|
||||
else if (strcmp(id, "step") == 0)
|
||||
- data[1] = atoi(value);
|
||||
+ scale->step = atoi(value);
|
||||
else if (strcmp(id, "mute") == 0)
|
||||
- data[2] = atoi(value);
|
||||
+ scale->mute = atoi(value);
|
||||
else
|
||||
SNDERR("error: unknown key %s\n", id);
|
||||
}
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,54 +0,0 @@
|
||||
From 80a8283d179739f73ad007b5d60dbf28b80fddb9 Mon Sep 17 00:00:00 2001
|
||||
From: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Date: Wed, 5 Aug 2015 14:41:51 +0100
|
||||
Subject: [PATCH] topology: Add ops support to byte control objects.
|
||||
|
||||
Rename the control ops structure to make it more generic so we can use it
|
||||
with other objects like bytes controls. Add this structure to the byte
|
||||
control structure.
|
||||
|
||||
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/sound/asoc.h | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/include/sound/asoc.h b/include/sound/asoc.h
|
||||
index 73eb80ef17cc..c642855e4b0c 100644
|
||||
--- a/include/sound/asoc.h
|
||||
+++ b/include/sound/asoc.h
|
||||
@@ -161,9 +161,11 @@ struct snd_soc_tplg_channel {
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
- * Kcontrol Operations IDs
|
||||
+ * Genericl Operations IDs, for binding Kcontrol or Bytes ext ops
|
||||
+ * Kcontrol ops need get/put/info.
|
||||
+ * Bytes ext ops need get/put.
|
||||
*/
|
||||
-struct snd_soc_tplg_kcontrol_ops_id {
|
||||
+struct snd_soc_tplg_io_ops {
|
||||
__le32 get;
|
||||
__le32 put;
|
||||
__le32 info;
|
||||
@@ -177,7 +179,7 @@ struct snd_soc_tplg_ctl_hdr {
|
||||
__le32 type;
|
||||
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
__le32 access;
|
||||
- struct snd_soc_tplg_kcontrol_ops_id ops;
|
||||
+ struct snd_soc_tplg_io_ops ops;
|
||||
struct snd_soc_tplg_ctl_tlv tlv;
|
||||
} __attribute__((packed));
|
||||
|
||||
@@ -309,6 +311,7 @@ struct snd_soc_tplg_bytes_control {
|
||||
__le32 mask;
|
||||
__le32 base;
|
||||
__le32 num_regs;
|
||||
+ struct snd_soc_tplg_io_ops ext_ops;
|
||||
struct snd_soc_tplg_private priv;
|
||||
} __attribute__((packed));
|
||||
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,47 +0,0 @@
|
||||
From ecf7fdaeef57d300b94a1cd00db8a8b04a2edceb Mon Sep 17 00:00:00 2001
|
||||
From: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Date: Fri, 7 Aug 2015 16:39:15 +0100
|
||||
Subject: [PATCH] topology: treat all DAPM controls types the same when copying
|
||||
|
||||
Copy all DAPM controls types using the same method.
|
||||
|
||||
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/dapm.c | 11 +++--------
|
||||
1 file changed, 3 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
|
||||
index 7e26ea0326ec..a0a8b8656c21 100644
|
||||
--- a/src/topology/dapm.c
|
||||
+++ b/src/topology/dapm.c
|
||||
@@ -107,8 +107,6 @@ static int tplg_parse_dapm_enums(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
static int copy_dapm_control(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
{
|
||||
struct snd_soc_tplg_dapm_widget *widget = elem->widget;
|
||||
- struct snd_soc_tplg_mixer_control *mixer_ctrl = ref->mixer_ctrl;
|
||||
- struct snd_soc_tplg_enum_control *enum_ctrl = ref->enum_ctrl;
|
||||
|
||||
tplg_dbg("Control '%s' used by '%s'\n", ref->id, elem->id);
|
||||
tplg_dbg("\tparent size: %d + %d -> %d, priv size -> %d\n",
|
||||
@@ -121,13 +119,10 @@ static int copy_dapm_control(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
|
||||
elem->widget = widget;
|
||||
|
||||
- /* copy new widget at the end */
|
||||
- if (ref->type == OBJECT_TYPE_MIXER)
|
||||
- memcpy((void*)widget + elem->size, mixer_ctrl, ref->size);
|
||||
- else if (ref->type == OBJECT_TYPE_ENUM)
|
||||
- memcpy((void*)widget + elem->size, enum_ctrl, ref->size);
|
||||
-
|
||||
+ /* append the control to the end of the widget */
|
||||
+ memcpy((void*)widget + elem->size, ref->obj, ref->size);
|
||||
elem->size += ref->size;
|
||||
+
|
||||
widget->num_kcontrols++;
|
||||
ref->compound_elem = 1;
|
||||
return 0;
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,29 +0,0 @@
|
||||
From b47cf00197420d7dc9dc01dce75b41aaad49278e Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Fri, 7 Aug 2015 16:39:16 +0100
|
||||
Subject: [PATCH] topology: print error prefix on error message.
|
||||
|
||||
Let the user know it's an error.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/data.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/topology/data.c b/src/topology/data.c
|
||||
index c768bc5b0b04..090185174ce4 100644
|
||||
--- a/src/topology/data.c
|
||||
+++ b/src/topology/data.c
|
||||
@@ -384,7 +384,7 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
break;
|
||||
|
||||
default:
|
||||
- SNDERR("elem '%s': type %d private data not supported \n",
|
||||
+ SNDERR("error: elem '%s': type %d private data not supported \n",
|
||||
elem->id, elem->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,782 +0,0 @@
|
||||
From 634712d21c07a229a6b37658e900f0fd4c304a59 Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Mon, 10 Aug 2015 19:13:47 +0100
|
||||
Subject: [PATCH] topology: rename OBJECT_TYPE_ to SND_TPLG_TYPE_
|
||||
|
||||
rename OBJECT_TYPE_ to SND_TPLG_TYPE_ in preparation for exporting via
|
||||
a new public API.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/builder.c | 38 +++++++++++++++++++-------------------
|
||||
src/topology/ctl.c | 38 +++++++++++++++++++-------------------
|
||||
src/topology/dapm.c | 43 +++++++++++++++++++++++--------------------
|
||||
src/topology/data.c | 10 +++++-----
|
||||
src/topology/elem.c | 26 +++++++++++++-------------
|
||||
src/topology/parser.c | 6 +++---
|
||||
src/topology/pcm.c | 34 +++++++++++++++++-----------------
|
||||
src/topology/text.c | 2 +-
|
||||
src/topology/tplg_local.h | 36 ++++++++++++++++++------------------
|
||||
9 files changed, 118 insertions(+), 115 deletions(-)
|
||||
|
||||
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
||||
index a944866a2d68..3bccd44827cc 100644
|
||||
--- a/src/topology/builder.c
|
||||
+++ b/src/topology/builder.c
|
||||
@@ -141,7 +141,7 @@ static int write_elem_block(snd_tplg_t *tplg,
|
||||
if (elem->compound_elem)
|
||||
continue;
|
||||
|
||||
- if (elem->type != OBJECT_TYPE_DAPM_GRAPH)
|
||||
+ if (elem->type != SND_TPLG_TYPE_DAPM_GRAPH)
|
||||
verbose(tplg, " %s '%s': write %d bytes\n",
|
||||
obj_name, elem->id, elem->size);
|
||||
else
|
||||
@@ -202,31 +202,31 @@ static int write_block(snd_tplg_t *tplg, struct list_head *base,
|
||||
|
||||
/* write each elem for this block */
|
||||
switch (type) {
|
||||
- case OBJECT_TYPE_MIXER:
|
||||
+ case SND_TPLG_TYPE_MIXER:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_MIXER, "mixer");
|
||||
- case OBJECT_TYPE_BYTES:
|
||||
+ case SND_TPLG_TYPE_BYTES:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_BYTES, "bytes");
|
||||
- case OBJECT_TYPE_ENUM:
|
||||
+ case SND_TPLG_TYPE_ENUM:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_ENUM, "enum");
|
||||
- case OBJECT_TYPE_DAPM_GRAPH:
|
||||
+ case SND_TPLG_TYPE_DAPM_GRAPH:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_DAPM_GRAPH, "route");
|
||||
- case OBJECT_TYPE_DAPM_WIDGET:
|
||||
+ case SND_TPLG_TYPE_DAPM_WIDGET:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_DAPM_WIDGET, "widget");
|
||||
- case OBJECT_TYPE_PCM:
|
||||
+ case SND_TPLG_TYPE_PCM:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_PCM, "pcm");
|
||||
- case OBJECT_TYPE_BE:
|
||||
+ case SND_TPLG_TYPE_BE:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_DAI_LINK, "be");
|
||||
- case OBJECT_TYPE_CC:
|
||||
+ case SND_TPLG_TYPE_CC:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_DAI_LINK, "cc");
|
||||
- case OBJECT_TYPE_DATA:
|
||||
+ case SND_TPLG_TYPE_DATA:
|
||||
return write_elem_block(tplg, base, size,
|
||||
SND_SOC_TPLG_TYPE_PDATA, "data");
|
||||
default:
|
||||
@@ -280,7 +280,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write mixer elems. */
|
||||
ret = write_block(tplg, &tplg->mixer_list,
|
||||
- OBJECT_TYPE_MIXER);
|
||||
+ SND_TPLG_TYPE_MIXER);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write control elems %d\n", ret);
|
||||
return ret;
|
||||
@@ -288,7 +288,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write enum control elems. */
|
||||
ret = write_block(tplg, &tplg->enum_list,
|
||||
- OBJECT_TYPE_ENUM);
|
||||
+ SND_TPLG_TYPE_ENUM);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write control elems %d\n", ret);
|
||||
return ret;
|
||||
@@ -296,7 +296,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write bytes extended control elems. */
|
||||
ret = write_block(tplg, &tplg->bytes_ext_list,
|
||||
- OBJECT_TYPE_BYTES);
|
||||
+ SND_TPLG_TYPE_BYTES);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write control elems %d\n", ret);
|
||||
return ret;
|
||||
@@ -304,7 +304,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write widget elems */
|
||||
ret = write_block(tplg, &tplg->widget_list,
|
||||
- OBJECT_TYPE_DAPM_WIDGET);
|
||||
+ SND_TPLG_TYPE_DAPM_WIDGET);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write widget elems %d\n", ret);
|
||||
return ret;
|
||||
@@ -312,7 +312,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write pcm elems */
|
||||
ret = write_block(tplg, &tplg->pcm_list,
|
||||
- OBJECT_TYPE_PCM);
|
||||
+ SND_TPLG_TYPE_PCM);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write pcm elems %d\n", ret);
|
||||
return ret;
|
||||
@@ -320,7 +320,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write be elems */
|
||||
ret = write_block(tplg, &tplg->be_list,
|
||||
- OBJECT_TYPE_BE);
|
||||
+ SND_TPLG_TYPE_BE);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write be elems %d\n", ret);
|
||||
return ret;
|
||||
@@ -328,7 +328,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write cc elems */
|
||||
ret = write_block(tplg, &tplg->cc_list,
|
||||
- OBJECT_TYPE_CC);
|
||||
+ SND_TPLG_TYPE_CC);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write cc elems %d\n", ret);
|
||||
return ret;
|
||||
@@ -336,7 +336,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write route elems */
|
||||
ret = write_block(tplg, &tplg->route_list,
|
||||
- OBJECT_TYPE_DAPM_GRAPH);
|
||||
+ SND_TPLG_TYPE_DAPM_GRAPH);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write graph elems %d\n", ret);
|
||||
return ret;
|
||||
@@ -344,7 +344,7 @@ int tplg_write_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write private data */
|
||||
ret = write_block(tplg, &tplg->pdata_list,
|
||||
- OBJECT_TYPE_DATA);
|
||||
+ SND_TPLG_TYPE_DATA);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to write private data %d\n", ret);
|
||||
return ret;
|
||||
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
|
||||
index 930b50897220..35f684ba8067 100644
|
||||
--- a/src/topology/ctl.c
|
||||
+++ b/src/topology/ctl.c
|
||||
@@ -49,15 +49,15 @@ static int tplg_build_mixer_control(snd_tplg_t *tplg,
|
||||
if (ref->id == NULL || ref->elem)
|
||||
continue;
|
||||
|
||||
- if (ref->type == OBJECT_TYPE_TLV) {
|
||||
+ if (ref->type == SND_TPLG_TYPE_TLV) {
|
||||
ref->elem = tplg_elem_lookup(&tplg->tlv_list,
|
||||
- ref->id, OBJECT_TYPE_TLV);
|
||||
+ ref->id, SND_TPLG_TYPE_TLV);
|
||||
if (ref->elem)
|
||||
err = copy_tlv(elem, ref->elem);
|
||||
|
||||
- } else if (ref->type == OBJECT_TYPE_DATA) {
|
||||
+ } else if (ref->type == SND_TPLG_TYPE_DATA) {
|
||||
ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
- ref->id, OBJECT_TYPE_DATA);
|
||||
+ ref->id, SND_TPLG_TYPE_DATA);
|
||||
err = tplg_copy_data(elem, ref->elem);
|
||||
}
|
||||
|
||||
@@ -97,15 +97,15 @@ static int tplg_build_enum_control(snd_tplg_t *tplg,
|
||||
if (ref->id == NULL || ref->elem)
|
||||
continue;
|
||||
|
||||
- if (ref->type == OBJECT_TYPE_TEXT) {
|
||||
+ if (ref->type == SND_TPLG_TYPE_TEXT) {
|
||||
ref->elem = tplg_elem_lookup(&tplg->text_list,
|
||||
- ref->id, OBJECT_TYPE_TEXT);
|
||||
+ ref->id, SND_TPLG_TYPE_TEXT);
|
||||
if (ref->elem)
|
||||
copy_enum_texts(elem, ref->elem);
|
||||
|
||||
- } else if (ref->type == OBJECT_TYPE_DATA) {
|
||||
+ } else if (ref->type == SND_TPLG_TYPE_DATA) {
|
||||
ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
- ref->id, OBJECT_TYPE_DATA);
|
||||
+ ref->id, SND_TPLG_TYPE_DATA);
|
||||
err = tplg_copy_data(elem, ref->elem);
|
||||
}
|
||||
if (!ref->elem) {
|
||||
@@ -135,7 +135,7 @@ static int tplg_build_bytes_control(snd_tplg_t *tplg, struct tplg_elem *elem)
|
||||
|
||||
/* bytes control only reference one private data section */
|
||||
ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
- ref->id, OBJECT_TYPE_DATA);
|
||||
+ ref->id, SND_TPLG_TYPE_DATA);
|
||||
if (!ref->elem) {
|
||||
SNDERR("error: cannot find data '%s'"
|
||||
" referenced by control '%s'\n",
|
||||
@@ -260,7 +260,7 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
int err = 0;
|
||||
struct tplg_elem *elem;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_TLV);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TLV);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -294,7 +294,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_BYTES);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -365,7 +365,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- tplg_ref_add(elem, OBJECT_TYPE_DATA, val);
|
||||
+ tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
|
||||
tplg_dbg("\t%s: %s\n", id, val);
|
||||
continue;
|
||||
}
|
||||
@@ -374,7 +374,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- err = tplg_ref_add(elem, OBJECT_TYPE_TLV, val);
|
||||
+ err = tplg_ref_add(elem, SND_TPLG_TYPE_TLV, val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -399,7 +399,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
const char *id, *val = NULL;
|
||||
int err, j;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_ENUM);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_ENUM);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -440,7 +440,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- tplg_ref_add(elem, OBJECT_TYPE_TEXT, val);
|
||||
+ tplg_ref_add(elem, SND_TPLG_TYPE_TEXT, val);
|
||||
tplg_dbg("\t%s: %s\n", id, val);
|
||||
continue;
|
||||
}
|
||||
@@ -473,7 +473,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- tplg_ref_add(elem, OBJECT_TYPE_DATA, val);
|
||||
+ tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
|
||||
tplg_dbg("\t%s: %s\n", id, val);
|
||||
continue;
|
||||
}
|
||||
@@ -496,7 +496,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err, j;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_MIXER);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -584,7 +584,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- err = tplg_ref_add(elem, OBJECT_TYPE_TLV, val);
|
||||
+ err = tplg_ref_add(elem, SND_TPLG_TYPE_TLV, val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -598,7 +598,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- tplg_ref_add(elem, OBJECT_TYPE_DATA, val);
|
||||
+ tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
|
||||
tplg_dbg("\t%s: %s\n", id, val);
|
||||
continue;
|
||||
}
|
||||
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
|
||||
index a0a8b8656c21..3458aa77838b 100644
|
||||
--- a/src/topology/dapm.c
|
||||
+++ b/src/topology/dapm.c
|
||||
@@ -74,7 +74,7 @@ static int tplg_parse_dapm_mixers(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
if (snd_config_get_string(n, &value) < 0)
|
||||
continue;
|
||||
|
||||
- tplg_ref_add(elem, OBJECT_TYPE_MIXER, value);
|
||||
+ tplg_ref_add(elem, SND_TPLG_TYPE_MIXER, value);
|
||||
tplg_dbg("\t\t %s\n", value);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ static int tplg_parse_dapm_enums(snd_config_t *cfg, struct tplg_elem *elem)
|
||||
if (snd_config_get_string(n, &value) < 0)
|
||||
continue;
|
||||
|
||||
- tplg_ref_add(elem, OBJECT_TYPE_ENUM, value);
|
||||
+ tplg_ref_add(elem, SND_TPLG_TYPE_ENUM, value);
|
||||
tplg_dbg("\t\t %s\n", value);
|
||||
}
|
||||
|
||||
@@ -146,23 +146,26 @@ static int tplg_build_widget(snd_tplg_t *tplg,
|
||||
continue;
|
||||
|
||||
switch (ref->type) {
|
||||
- case OBJECT_TYPE_MIXER:
|
||||
- ref->elem = tplg_elem_lookup(&tplg->mixer_list,
|
||||
- ref->id, OBJECT_TYPE_MIXER);
|
||||
+ case SND_TPLG_TYPE_MIXER:
|
||||
+ if (!ref->elem)
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->mixer_list,
|
||||
+ ref->id, SND_TPLG_TYPE_MIXER);
|
||||
if (ref->elem)
|
||||
err = copy_dapm_control(elem, ref->elem);
|
||||
break;
|
||||
|
||||
- case OBJECT_TYPE_ENUM:
|
||||
- ref->elem = tplg_elem_lookup(&tplg->enum_list,
|
||||
- ref->id, OBJECT_TYPE_ENUM);
|
||||
+ case SND_TPLG_TYPE_ENUM:
|
||||
+ if (!ref->elem)
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->enum_list,
|
||||
+ ref->id, SND_TPLG_TYPE_ENUM);
|
||||
if (ref->elem)
|
||||
err = copy_dapm_control(elem, ref->elem);
|
||||
break;
|
||||
|
||||
- case OBJECT_TYPE_DATA:
|
||||
- ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
- ref->id, OBJECT_TYPE_DATA);
|
||||
+ case SND_TPLG_TYPE_DATA:
|
||||
+ if (!ref->elem)
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
+ ref->id, SND_TPLG_TYPE_DATA);
|
||||
if (ref->elem)
|
||||
err = tplg_copy_data(elem, ref->elem);
|
||||
break;
|
||||
@@ -195,7 +198,7 @@ int tplg_build_widgets(snd_tplg_t *tplg)
|
||||
list_for_each(pos, base) {
|
||||
|
||||
elem = list_entry(pos, struct tplg_elem, list);
|
||||
- if (!elem->widget || elem->type != OBJECT_TYPE_DAPM_WIDGET) {
|
||||
+ if (!elem->widget || elem->type != SND_TPLG_TYPE_DAPM_WIDGET) {
|
||||
SNDERR("error: invalid widget '%s'\n",
|
||||
elem->id);
|
||||
return -EINVAL;
|
||||
@@ -223,7 +226,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
|
||||
list_for_each(pos, base) {
|
||||
elem = list_entry(pos, struct tplg_elem, list);
|
||||
|
||||
- if (!elem->route || elem->type != OBJECT_TYPE_DAPM_GRAPH) {
|
||||
+ if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH) {
|
||||
SNDERR("error: invalid route '%s'\n",
|
||||
elem->id);
|
||||
return -EINVAL;
|
||||
@@ -240,7 +243,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
|
||||
|
||||
}
|
||||
if (!tplg_elem_lookup(&tplg->widget_list, route->sink,
|
||||
- OBJECT_TYPE_DAPM_WIDGET)) {
|
||||
+ SND_TPLG_TYPE_DAPM_WIDGET)) {
|
||||
SNDERR("warning: undefined sink widget/stream '%s'\n",
|
||||
route->sink);
|
||||
}
|
||||
@@ -248,9 +251,9 @@ int tplg_build_routes(snd_tplg_t *tplg)
|
||||
/* validate control name */
|
||||
if (strlen(route->control)) {
|
||||
if (!tplg_elem_lookup(&tplg->mixer_list,
|
||||
- route->control, OBJECT_TYPE_MIXER) &&
|
||||
+ route->control, SND_TPLG_TYPE_MIXER) &&
|
||||
!tplg_elem_lookup(&tplg->enum_list,
|
||||
- route->control, OBJECT_TYPE_ENUM)) {
|
||||
+ route->control, SND_TPLG_TYPE_ENUM)) {
|
||||
SNDERR("warning: Undefined mixer/enum control '%s'\n",
|
||||
route->control);
|
||||
}
|
||||
@@ -263,7 +266,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
|
||||
|
||||
}
|
||||
if (!tplg_elem_lookup(&tplg->widget_list, route->source,
|
||||
- OBJECT_TYPE_DAPM_WIDGET)) {
|
||||
+ SND_TPLG_TYPE_DAPM_WIDGET)) {
|
||||
SNDERR("warning: Undefined source widget/stream '%s'\n",
|
||||
route->source);
|
||||
}
|
||||
@@ -347,7 +350,7 @@ static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t *cfg)
|
||||
|
||||
list_add_tail(&elem->list, &tplg->route_list);
|
||||
strcpy(elem->id, "line");
|
||||
- elem->type = OBJECT_TYPE_DAPM_GRAPH;
|
||||
+ elem->type = SND_TPLG_TYPE_DAPM_GRAPH;
|
||||
elem->size = sizeof(*line);
|
||||
|
||||
line = calloc(1, sizeof(*line));
|
||||
@@ -415,7 +418,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int widget_type, err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_DAPM_WIDGET);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DAPM_WIDGET);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -547,7 +550,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- tplg_ref_add(elem, OBJECT_TYPE_DATA, val);
|
||||
+ tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
|
||||
tplg_dbg("\t%s: %s\n", id, val);
|
||||
continue;
|
||||
}
|
||||
diff --git a/src/topology/data.c b/src/topology/data.c
|
||||
index 090185174ce4..4ee1f8a15f95 100644
|
||||
--- a/src/topology/data.c
|
||||
+++ b/src/topology/data.c
|
||||
@@ -268,7 +268,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
int err = 0;
|
||||
struct tplg_elem *elem;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_DATA);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DATA);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -350,7 +350,7 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
priv_data_size = ref->data->size;
|
||||
|
||||
switch (elem->type) {
|
||||
- case OBJECT_TYPE_MIXER:
|
||||
+ case SND_TPLG_TYPE_MIXER:
|
||||
elem->mixer_ctrl = realloc(elem->mixer_ctrl,
|
||||
elem->size + priv_data_size);
|
||||
if (!elem->mixer_ctrl)
|
||||
@@ -358,7 +358,7 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
priv = &elem->mixer_ctrl->priv;
|
||||
break;
|
||||
|
||||
- case OBJECT_TYPE_ENUM:
|
||||
+ case SND_TPLG_TYPE_ENUM:
|
||||
elem->enum_ctrl = realloc(elem->enum_ctrl,
|
||||
elem->size + priv_data_size);
|
||||
if (!elem->enum_ctrl)
|
||||
@@ -366,7 +366,7 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
priv = &elem->enum_ctrl->priv;
|
||||
break;
|
||||
|
||||
- case OBJECT_TYPE_BYTES:
|
||||
+ case SND_TPLG_TYPE_BYTES:
|
||||
elem->bytes_ext = realloc(elem->bytes_ext,
|
||||
elem->size + priv_data_size);
|
||||
if (!elem->bytes_ext)
|
||||
@@ -375,7 +375,7 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
break;
|
||||
|
||||
|
||||
- case OBJECT_TYPE_DAPM_WIDGET:
|
||||
+ case SND_TPLG_TYPE_DAPM_WIDGET:
|
||||
elem->widget = realloc(elem->widget,
|
||||
elem->size + priv_data_size);
|
||||
if (!elem->widget)
|
||||
diff --git a/src/topology/elem.c b/src/topology/elem.c
|
||||
index 7fee65332124..daabe75ebdd2 100644
|
||||
--- a/src/topology/elem.c
|
||||
+++ b/src/topology/elem.c
|
||||
@@ -103,7 +103,7 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
|
||||
|
||||
/* create a new common element and object */
|
||||
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
|
||||
- snd_config_t *cfg, const char *name, enum object_type type)
|
||||
+ snd_config_t *cfg, const char *name, enum snd_tplg_type type)
|
||||
{
|
||||
struct tplg_elem *elem;
|
||||
const char *id;
|
||||
@@ -126,49 +126,49 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
|
||||
elem_copy_text(elem->id, name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
|
||||
switch (type) {
|
||||
- case OBJECT_TYPE_DATA:
|
||||
+ case SND_TPLG_TYPE_DATA:
|
||||
list_add_tail(&elem->list, &tplg->pdata_list);
|
||||
break;
|
||||
- case OBJECT_TYPE_TEXT:
|
||||
+ case SND_TPLG_TYPE_TEXT:
|
||||
list_add_tail(&elem->list, &tplg->text_list);
|
||||
break;
|
||||
- case OBJECT_TYPE_TLV:
|
||||
+ case SND_TPLG_TYPE_TLV:
|
||||
list_add_tail(&elem->list, &tplg->tlv_list);
|
||||
elem->size = sizeof(struct snd_soc_tplg_ctl_tlv);
|
||||
break;
|
||||
- case OBJECT_TYPE_BYTES:
|
||||
+ case SND_TPLG_TYPE_BYTES:
|
||||
list_add_tail(&elem->list, &tplg->bytes_ext_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_bytes_control);
|
||||
break;
|
||||
- case OBJECT_TYPE_ENUM:
|
||||
+ case SND_TPLG_TYPE_ENUM:
|
||||
list_add_tail(&elem->list, &tplg->enum_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_enum_control);
|
||||
break;
|
||||
- case OBJECT_TYPE_MIXER:
|
||||
+ case SND_TPLG_TYPE_MIXER:
|
||||
list_add_tail(&elem->list, &tplg->mixer_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_mixer_control);
|
||||
break;
|
||||
- case OBJECT_TYPE_DAPM_WIDGET:
|
||||
+ case SND_TPLG_TYPE_DAPM_WIDGET:
|
||||
list_add_tail(&elem->list, &tplg->widget_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_dapm_widget);
|
||||
break;
|
||||
- case OBJECT_TYPE_STREAM_CONFIG:
|
||||
+ case SND_TPLG_TYPE_STREAM_CONFIG:
|
||||
list_add_tail(&elem->list, &tplg->pcm_config_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_stream_config);
|
||||
break;
|
||||
- case OBJECT_TYPE_STREAM_CAPS:
|
||||
+ case SND_TPLG_TYPE_STREAM_CAPS:
|
||||
list_add_tail(&elem->list, &tplg->pcm_caps_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_stream_caps);
|
||||
break;
|
||||
- case OBJECT_TYPE_PCM:
|
||||
+ case SND_TPLG_TYPE_PCM:
|
||||
list_add_tail(&elem->list, &tplg->pcm_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_pcm_dai);
|
||||
break;
|
||||
- case OBJECT_TYPE_BE:
|
||||
+ case SND_TPLG_TYPE_BE:
|
||||
list_add_tail(&elem->list, &tplg->be_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_pcm_dai);
|
||||
break;
|
||||
- case OBJECT_TYPE_CC:
|
||||
+ case SND_TPLG_TYPE_CC:
|
||||
list_add_tail(&elem->list, &tplg->cc_list);
|
||||
obj_size = sizeof(struct snd_soc_tplg_pcm_dai);
|
||||
break;
|
||||
diff --git a/src/topology/parser.c b/src/topology/parser.c
|
||||
index ed25bb88d446..3e3e2b35da83 100644
|
||||
--- a/src/topology/parser.c
|
||||
+++ b/src/topology/parser.c
|
||||
@@ -241,15 +241,15 @@ static int tplg_build_integ(snd_tplg_t *tplg)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
- err = tplg_build_pcm_dai(tplg, OBJECT_TYPE_PCM);
|
||||
+ err = tplg_build_pcm_dai(tplg, SND_TPLG_TYPE_PCM);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
- err = tplg_build_pcm_dai(tplg, OBJECT_TYPE_BE);
|
||||
+ err = tplg_build_pcm_dai(tplg, SND_TPLG_TYPE_BE);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
- err = tplg_build_pcm_dai(tplg, OBJECT_TYPE_CC);
|
||||
+ err = tplg_build_pcm_dai(tplg, SND_TPLG_TYPE_CC);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
|
||||
index deae47b771be..6e42aa18b99b 100644
|
||||
--- a/src/topology/pcm.c
|
||||
+++ b/src/topology/pcm.c
|
||||
@@ -28,7 +28,7 @@ struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base, const char* id)
|
||||
list_for_each(pos, base) {
|
||||
|
||||
elem = list_entry(pos, struct tplg_elem, list);
|
||||
- if (elem->type != OBJECT_TYPE_PCM)
|
||||
+ if (elem->type != SND_TPLG_TYPE_PCM)
|
||||
return NULL;
|
||||
|
||||
pcm_dai = elem->pcm;
|
||||
@@ -74,13 +74,13 @@ static int tplg_build_pcm_cfg_caps(snd_tplg_t *tplg, struct tplg_elem *elem)
|
||||
unsigned int i, j;
|
||||
|
||||
switch (elem->type) {
|
||||
- case OBJECT_TYPE_PCM:
|
||||
+ case SND_TPLG_TYPE_PCM:
|
||||
pcm_dai = elem->pcm;
|
||||
break;
|
||||
- case OBJECT_TYPE_BE:
|
||||
+ case SND_TPLG_TYPE_BE:
|
||||
pcm_dai = elem->be;
|
||||
break;
|
||||
- case OBJECT_TYPE_CC:
|
||||
+ case SND_TPLG_TYPE_CC:
|
||||
pcm_dai = elem->cc;
|
||||
break;
|
||||
default:
|
||||
@@ -91,7 +91,7 @@ static int tplg_build_pcm_cfg_caps(snd_tplg_t *tplg, struct tplg_elem *elem)
|
||||
capconf = &pcm_dai->capconf[i];
|
||||
|
||||
ref_elem = tplg_elem_lookup(&tplg->pcm_caps_list,
|
||||
- capconf->caps.name, OBJECT_TYPE_STREAM_CAPS);
|
||||
+ capconf->caps.name, SND_TPLG_TYPE_STREAM_CAPS);
|
||||
|
||||
if (ref_elem != NULL)
|
||||
copy_pcm_caps(elem->id, &capconf->caps, ref_elem);
|
||||
@@ -99,7 +99,7 @@ static int tplg_build_pcm_cfg_caps(snd_tplg_t *tplg, struct tplg_elem *elem)
|
||||
for (j = 0; j < capconf->num_configs; j++) {
|
||||
ref_elem = tplg_elem_lookup(&tplg->pcm_config_list,
|
||||
capconf->configs[j].name,
|
||||
- OBJECT_TYPE_STREAM_CONFIG);
|
||||
+ SND_TPLG_TYPE_STREAM_CONFIG);
|
||||
|
||||
if (ref_elem != NULL)
|
||||
copy_pcm_config(elem->id,
|
||||
@@ -118,13 +118,13 @@ int tplg_build_pcm_dai(snd_tplg_t *tplg, unsigned int type)
|
||||
int err = 0;
|
||||
|
||||
switch (type) {
|
||||
- case OBJECT_TYPE_PCM:
|
||||
+ case SND_TPLG_TYPE_PCM:
|
||||
base = &tplg->pcm_list;
|
||||
break;
|
||||
- case OBJECT_TYPE_BE:
|
||||
+ case SND_TPLG_TYPE_BE:
|
||||
base = &tplg->be_list;
|
||||
break;
|
||||
- case OBJECT_TYPE_CC:
|
||||
+ case SND_TPLG_TYPE_CC:
|
||||
base = &tplg->cc_list;
|
||||
break;
|
||||
default:
|
||||
@@ -228,7 +228,7 @@ int tplg_parse_pcm_config(snd_tplg_t *tplg,
|
||||
const char *id;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_STREAM_CONFIG);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_STREAM_CONFIG);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -294,7 +294,7 @@ int tplg_parse_pcm_caps(snd_tplg_t *tplg,
|
||||
char *s;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_STREAM_CAPS);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_STREAM_CAPS);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -396,11 +396,11 @@ int tplg_parse_pcm_cap_cfg(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
const char *id, *value;
|
||||
int err, stream;
|
||||
|
||||
- if (elem->type == OBJECT_TYPE_PCM)
|
||||
+ if (elem->type == SND_TPLG_TYPE_PCM)
|
||||
pcm_dai = elem->pcm;
|
||||
- else if (elem->type == OBJECT_TYPE_BE)
|
||||
+ else if (elem->type == SND_TPLG_TYPE_BE)
|
||||
pcm_dai = elem->be;
|
||||
- else if (elem->type == OBJECT_TYPE_CC)
|
||||
+ else if (elem->type == SND_TPLG_TYPE_CC)
|
||||
pcm_dai = elem->cc;
|
||||
else
|
||||
return -EINVAL;
|
||||
@@ -461,7 +461,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_PCM);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_PCM);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -524,7 +524,7 @@ int tplg_parse_be(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_BE);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BE);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -587,7 +587,7 @@ int tplg_parse_cc(snd_tplg_t *tplg,
|
||||
const char *id, *val = NULL;
|
||||
int err;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_CC);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_CC);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/topology/text.c b/src/topology/text.c
|
||||
index 7128056d5d34..0c6594a1307d 100644
|
||||
--- a/src/topology/text.c
|
||||
+++ b/src/topology/text.c
|
||||
@@ -64,7 +64,7 @@ int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
int err = 0;
|
||||
struct tplg_elem *elem;
|
||||
|
||||
- elem = tplg_elem_new_common(tplg, cfg, NULL, OBJECT_TYPE_TEXT);
|
||||
+ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TEXT);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
|
||||
index ad38945056df..febc1772fd04 100644
|
||||
--- a/src/topology/tplg_local.h
|
||||
+++ b/src/topology/tplg_local.h
|
||||
@@ -40,22 +40,22 @@
|
||||
struct tplg_ref;
|
||||
struct tplg_elem;
|
||||
|
||||
-/* internal topology object type not used by kernel */
|
||||
-enum object_type {
|
||||
- OBJECT_TYPE_TLV = 0,
|
||||
- OBJECT_TYPE_MIXER,
|
||||
- OBJECT_TYPE_ENUM,
|
||||
- OBJECT_TYPE_TEXT,
|
||||
- OBJECT_TYPE_DATA,
|
||||
- OBJECT_TYPE_BYTES,
|
||||
- OBJECT_TYPE_STREAM_CONFIG,
|
||||
- OBJECT_TYPE_STREAM_CAPS,
|
||||
- OBJECT_TYPE_PCM,
|
||||
- OBJECT_TYPE_DAPM_WIDGET,
|
||||
- OBJECT_TYPE_DAPM_GRAPH,
|
||||
- OBJECT_TYPE_BE,
|
||||
- OBJECT_TYPE_CC,
|
||||
- OBJECT_TYPE_MANIFEST,
|
||||
+/** Topology object types */
|
||||
+enum snd_tplg_type {
|
||||
+ SND_TPLG_TYPE_TLV = 0, /*!< TLV Data */
|
||||
+ SND_TPLG_TYPE_MIXER, /*!< Mixer control*/
|
||||
+ SND_TPLG_TYPE_ENUM, /*!< Enumerated control */
|
||||
+ SND_TPLG_TYPE_TEXT, /*!< Text data */
|
||||
+ SND_TPLG_TYPE_DATA, /*!< Private data */
|
||||
+ SND_TPLG_TYPE_BYTES, /*!< Byte control */
|
||||
+ SND_TPLG_TYPE_STREAM_CONFIG, /*!< PCM Stream configuration */
|
||||
+ SND_TPLG_TYPE_STREAM_CAPS, /*!< PCM Stream capabilities */
|
||||
+ SND_TPLG_TYPE_PCM, /*!< PCM stream device */
|
||||
+ SND_TPLG_TYPE_DAPM_WIDGET, /*!< DAPM widget */
|
||||
+ SND_TPLG_TYPE_DAPM_GRAPH, /*!< DAPM graph elements */
|
||||
+ SND_TPLG_TYPE_BE, /*!< BE DAI link */
|
||||
+ SND_TPLG_TYPE_CC, /*!< Hostless codec <-> codec link */
|
||||
+ SND_TPLG_TYPE_MANIFEST, /*!< Topology manifest */
|
||||
};
|
||||
|
||||
struct snd_tplg {
|
||||
@@ -114,7 +114,7 @@ struct tplg_elem {
|
||||
char texts[SND_SOC_TPLG_NUM_TEXTS][SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
|
||||
int index;
|
||||
- enum object_type type;
|
||||
+ enum snd_tplg_type type;
|
||||
|
||||
int size; /* total size of this object inc pdata and ref objects */
|
||||
int compound_elem; /* dont write this element as individual elem */
|
||||
@@ -217,7 +217,7 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base,
|
||||
const char* id,
|
||||
unsigned int type);
|
||||
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
|
||||
- snd_config_t *cfg, const char *name, enum object_type type);
|
||||
+ snd_config_t *cfg, const char *name, enum snd_tplg_type type);
|
||||
|
||||
static inline void elem_copy_text(char *dest, const char *src, int len)
|
||||
{
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,47 +0,0 @@
|
||||
From ab9633d581110a5da08bd2d2c7c070f3862fe9af Mon Sep 17 00:00:00 2001
|
||||
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Date: Tue, 11 Aug 2015 18:23:15 +0100
|
||||
Subject: [PATCH] core: add convenience macros to local.h
|
||||
|
||||
Move ARRAY_SIZE() from tplg_local.h to local.h and add container_of()
|
||||
macro to local.h. Both macros are generic but are initially used by
|
||||
topology.
|
||||
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/local.h | 7 +++++++
|
||||
src/topology/tplg_local.h | 1 -
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/local.h b/include/local.h
|
||||
index 660081638a1c..b429f5d0094c 100644
|
||||
--- a/include/local.h
|
||||
+++ b/include/local.h
|
||||
@@ -350,4 +350,11 @@ int snd_config_search_alias_hooks(snd_config_t *config,
|
||||
|
||||
int _snd_conf_generic_id(const char *id);
|
||||
|
||||
+/* convenience macros */
|
||||
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
+
|
||||
+#define container_of(ptr, type, member) ({ \
|
||||
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
+ (type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
+
|
||||
#endif
|
||||
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
|
||||
index febc1772fd04..3982cc70dce5 100644
|
||||
--- a/src/topology/tplg_local.h
|
||||
+++ b/src/topology/tplg_local.h
|
||||
@@ -32,7 +32,6 @@
|
||||
#define MAX_FILE 256
|
||||
#define TPLG_MAX_PRIV_SIZE (1024 * 128)
|
||||
#define ALSA_TPLG_DIR ALSA_CONFIG_DIR "/topology"
|
||||
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
/** The name of the environment variable containing the tplg directory */
|
||||
#define ALSA_CONFIG_TPLG_VAR "ALSA_CONFIG_TPLG"
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,248 +0,0 @@
|
||||
From 1b148ef590f94fc30b4c814c1ce2bc31621af840 Mon Sep 17 00:00:00 2001
|
||||
From: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Date: Tue, 11 Aug 2015 18:23:16 +0100
|
||||
Subject: [PATCH] topology: Add C templates structure for building topology
|
||||
from C programs
|
||||
|
||||
Define structures that can be used by applications to directly build topology
|
||||
data instead of using text files. The application will build up the topology
|
||||
data by populating the template structures for each object type and then
|
||||
registering the template with the topology core.
|
||||
|
||||
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/topology.h | 176 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/topology/tplg_local.h | 18 -----
|
||||
2 files changed, 176 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/include/topology.h b/include/topology.h
|
||||
index 0cb2d79e5574..aee43de6e009 100644
|
||||
--- a/include/topology.h
|
||||
+++ b/include/topology.h
|
||||
@@ -456,9 +456,30 @@ extern "C" {
|
||||
*
|
||||
*/
|
||||
|
||||
+/** Maximum number of channels supported in one control */
|
||||
+#define SND_TPLG_MAX_CHAN 8
|
||||
+
|
||||
/** Topology context */
|
||||
typedef struct snd_tplg snd_tplg_t;
|
||||
|
||||
+/** Topology object types */
|
||||
+enum snd_tplg_type {
|
||||
+ SND_TPLG_TYPE_TLV = 0, /*!< TLV Data */
|
||||
+ SND_TPLG_TYPE_MIXER, /*!< Mixer control*/
|
||||
+ SND_TPLG_TYPE_ENUM, /*!< Enumerated control */
|
||||
+ SND_TPLG_TYPE_TEXT, /*!< Text data */
|
||||
+ SND_TPLG_TYPE_DATA, /*!< Private data */
|
||||
+ SND_TPLG_TYPE_BYTES, /*!< Byte control */
|
||||
+ SND_TPLG_TYPE_STREAM_CONFIG, /*!< PCM Stream configuration */
|
||||
+ SND_TPLG_TYPE_STREAM_CAPS, /*!< PCM Stream capabilities */
|
||||
+ SND_TPLG_TYPE_PCM, /*!< PCM stream device */
|
||||
+ SND_TPLG_TYPE_DAPM_WIDGET, /*!< DAPM widget */
|
||||
+ SND_TPLG_TYPE_DAPM_GRAPH, /*!< DAPM graph elements */
|
||||
+ SND_TPLG_TYPE_BE, /*!< BE DAI link */
|
||||
+ SND_TPLG_TYPE_CC, /*!< Hostless codec <-> codec link */
|
||||
+ SND_TPLG_TYPE_MANIFEST, /*!< Topology manifest */
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* \brief Create a new topology parser instance.
|
||||
* \return New topology parser instance
|
||||
@@ -488,6 +509,161 @@ int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
|
||||
*/
|
||||
void snd_tplg_verbose(snd_tplg_t *tplg, int verbose);
|
||||
|
||||
+/** \struct snd_tplg_tlv_template
|
||||
+ * \brief Template type for all TLV objects.
|
||||
+ */
|
||||
+struct snd_tplg_tlv_template {
|
||||
+ int type; /*!< TLV type SNDRV_CTL_TLVT_ */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_tlv_dbscale_template
|
||||
+ * \brief Template type for TLV Scale objects.
|
||||
+ */
|
||||
+struct snd_tplg_tlv_dbscale_template {
|
||||
+ struct snd_tplg_tlv_template hdr; /*!< TLV type header */
|
||||
+ int min; /*!< dB minimum value in 0.1dB */
|
||||
+ int step; /*!< dB step size in 0.1dB */
|
||||
+ int mute; /*!< is min dB value mute ? */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_channel_template
|
||||
+ * \brief Template type for single channel mapping.
|
||||
+ */
|
||||
+struct snd_tplg_channel_elem {
|
||||
+ int size; /*!< size in bytes of this structure */
|
||||
+ int reg; /*!< channel control register */
|
||||
+ int shift; /*!< channel shift for control bits */
|
||||
+ int id; /*!< ID maps to Left, Right, LFE etc */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_channel_map_template
|
||||
+ * \brief Template type for channel mapping.
|
||||
+ */
|
||||
+struct snd_tplg_channel_map_template {
|
||||
+ int num_channels; /*!< number of channel mappings */
|
||||
+ struct snd_tplg_channel_elem channel[SND_TPLG_MAX_CHAN]; /*!< mapping */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_pdata_template
|
||||
+ * \brief Template type for private data objects.
|
||||
+ */
|
||||
+struct snd_tplg_pdata_template {
|
||||
+ unsigned int length; /*!< data length */
|
||||
+ const void *data; /*!< data */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_io_ops_template
|
||||
+ * \brief Template type for object operations mapping.
|
||||
+ */
|
||||
+struct snd_tplg_io_ops_template {
|
||||
+ int get; /*!< get callback ID */
|
||||
+ int put; /*!< put callback ID */
|
||||
+ int info; /*!< info callback ID */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_ctl_template
|
||||
+ * \brief Template type for control objects.
|
||||
+ */
|
||||
+struct snd_tplg_ctl_template {
|
||||
+ int type; /*!< Control type */
|
||||
+ const char *name; /*!< Control name */
|
||||
+ int access; /*!< Control access */
|
||||
+ struct snd_tplg_io_ops_template ops; /*!< operations */
|
||||
+ struct snd_tplg_tlv_template *tlv; /*!< non NULL means we have TLV data */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_mixer_template
|
||||
+ * \brief Template type for mixer control objects.
|
||||
+ */
|
||||
+struct snd_tplg_mixer_template {
|
||||
+ struct snd_tplg_ctl_template hdr; /*!< control type header */
|
||||
+ struct snd_tplg_channel_map_template *map; /*!< channel map */
|
||||
+ int min; /*!< min value for mixer */
|
||||
+ int max; /*!< max value for mixer */
|
||||
+ int platform_max; /*!< max value for platform control */
|
||||
+ int invert; /*!< whether controls bits are inverted */
|
||||
+ struct snd_soc_tplg_private *priv; /*!< control private data */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_enum_template
|
||||
+ * \brief Template type for enumerated control objects.
|
||||
+ */
|
||||
+struct snd_tplg_enum_template {
|
||||
+ struct snd_tplg_ctl_template hdr; /*!< control type header */
|
||||
+ struct snd_tplg_channel_map_template *map; /*!< channel map */
|
||||
+ int items; /*!< number of enumerated items in control */
|
||||
+ int mask; /*!< register mask size */
|
||||
+ const char **texts; /*!< control text items */
|
||||
+ const int **values; /*!< control value items */
|
||||
+ struct snd_soc_tplg_private *priv; /*!< control private data */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_bytes_template
|
||||
+ * \brief Template type for TLV Scale objects.
|
||||
+ */
|
||||
+struct snd_tplg_bytes_template {
|
||||
+ struct snd_tplg_ctl_template hdr; /*!< control type header */
|
||||
+ int max; /*!< max byte control value */
|
||||
+ int mask; /*!< byte control mask */
|
||||
+ int base; /*!< base register */
|
||||
+ int num_regs; /*!< number of registers */
|
||||
+ struct snd_tplg_io_ops_template ext_ops; /*!< ops mapping */
|
||||
+ struct snd_soc_tplg_private *priv; /*!< control private data */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_graph_elem
|
||||
+ * \brief Template type for single DAPM graph element.
|
||||
+ */
|
||||
+struct snd_tplg_graph_elem {
|
||||
+ const char *src; /*!< source widget name */
|
||||
+ const char *ctl; /*!< control name or NULL if no control */
|
||||
+ const char *sink; /*!< sink widget name */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_graph_template
|
||||
+ * \brief Template type for array of DAPM graph elements.
|
||||
+ */
|
||||
+struct snd_tplg_graph_template {
|
||||
+ int count; /*!< Number of graph elements */
|
||||
+ struct snd_tplg_graph_elem elem[0]; /*!< graph elements */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_widget_template
|
||||
+ * \brief Template type for DAPM widget objects.
|
||||
+ */
|
||||
+struct snd_tplg_widget_template {
|
||||
+ int id; /*!< SND_SOC_DAPM_CTL */
|
||||
+ const char *name; /*!< widget name */
|
||||
+ const char *sname; /*!< stream name (certain widgets only) */
|
||||
+ int reg; /*!< negative reg = no direct dapm */
|
||||
+ int shift; /*!< bits to shift */
|
||||
+ int mask; /*!< non-shifted mask */
|
||||
+ int subseq; /*!< sort within widget type */
|
||||
+ unsigned int invert; /*!< invert the power bit */
|
||||
+ unsigned int ignore_suspend; /*!< kept enabled over suspend */
|
||||
+ unsigned short event_flags; /*!< PM event sequence flags */
|
||||
+ unsigned short event_type; /*!< PM event sequence type */
|
||||
+ struct snd_soc_tplg_private *priv; /*!< widget private data */
|
||||
+ int num_ctls; /*!< Number of controls used by widget */
|
||||
+ struct snd_tplg_ctl_template *ctl[0]; /*!< array of widget controls */
|
||||
+};
|
||||
+
|
||||
+/** \struct snd_tplg_obj_template
|
||||
+ * \brief Generic Template Object
|
||||
+ */
|
||||
+typedef struct snd_tplg_obj_template {
|
||||
+ enum snd_tplg_type type; /*!< template object type */
|
||||
+ int index; /*!< group index for object */
|
||||
+ int version; /*!< optional vendor specific version details */
|
||||
+ int vendor_type; /*!< optional vendor specific type info */
|
||||
+ union {
|
||||
+ struct snd_tplg_widget_template *widget; /*!< DAPM widget */
|
||||
+ struct snd_tplg_mixer_template *mixer; /*!< Mixer control */
|
||||
+ struct snd_tplg_bytes_template *bytes_ctl; /*!< Bytes control */
|
||||
+ struct snd_tplg_enum_template *enum_ctl; /*!< Enum control */
|
||||
+ struct snd_tplg_graph_template *graph; /*!< Graph elements */
|
||||
+ };
|
||||
+} snd_tplg_obj_template_t;
|
||||
/* \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
|
||||
index 3982cc70dce5..ec6304599538 100644
|
||||
--- a/src/topology/tplg_local.h
|
||||
+++ b/src/topology/tplg_local.h
|
||||
@@ -39,24 +39,6 @@
|
||||
struct tplg_ref;
|
||||
struct tplg_elem;
|
||||
|
||||
-/** Topology object types */
|
||||
-enum snd_tplg_type {
|
||||
- SND_TPLG_TYPE_TLV = 0, /*!< TLV Data */
|
||||
- SND_TPLG_TYPE_MIXER, /*!< Mixer control*/
|
||||
- SND_TPLG_TYPE_ENUM, /*!< Enumerated control */
|
||||
- SND_TPLG_TYPE_TEXT, /*!< Text data */
|
||||
- SND_TPLG_TYPE_DATA, /*!< Private data */
|
||||
- SND_TPLG_TYPE_BYTES, /*!< Byte control */
|
||||
- SND_TPLG_TYPE_STREAM_CONFIG, /*!< PCM Stream configuration */
|
||||
- SND_TPLG_TYPE_STREAM_CAPS, /*!< PCM Stream capabilities */
|
||||
- SND_TPLG_TYPE_PCM, /*!< PCM stream device */
|
||||
- SND_TPLG_TYPE_DAPM_WIDGET, /*!< DAPM widget */
|
||||
- SND_TPLG_TYPE_DAPM_GRAPH, /*!< DAPM graph elements */
|
||||
- SND_TPLG_TYPE_BE, /*!< BE DAI link */
|
||||
- SND_TPLG_TYPE_CC, /*!< Hostless codec <-> codec link */
|
||||
- SND_TPLG_TYPE_MANIFEST, /*!< Topology manifest */
|
||||
-};
|
||||
-
|
||||
struct snd_tplg {
|
||||
|
||||
/* opaque vendor data */
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,732 +0,0 @@
|
||||
From 5b518c91594d3b0c8847a87d9b65877f74c7a87b Mon Sep 17 00:00:00 2001
|
||||
From: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Date: Tue, 11 Aug 2015 18:23:17 +0100
|
||||
Subject: [PATCH] topology: A API calls to directly build topology data from
|
||||
templates
|
||||
|
||||
Add some new API calls so that applications can directly build topology data
|
||||
using template structures.
|
||||
|
||||
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/topology.h | 26 +++++
|
||||
src/topology/ctl.c | 292 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/topology/dapm.c | 183 ++++++++++++++++++++++++++---
|
||||
src/topology/elem.c | 17 +++
|
||||
src/topology/parser.c | 59 +++++++++-
|
||||
src/topology/tplg_local.h | 14 +++
|
||||
6 files changed, 573 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/include/topology.h b/include/topology.h
|
||||
index aee43de6e009..6ff8c5fb4609 100644
|
||||
--- a/include/topology.h
|
||||
+++ b/include/topology.h
|
||||
@@ -664,6 +664,32 @@ typedef struct snd_tplg_obj_template {
|
||||
struct snd_tplg_graph_template *graph; /*!< Graph elements */
|
||||
};
|
||||
} snd_tplg_obj_template_t;
|
||||
+
|
||||
+/**
|
||||
+ * \brief Register topology template object.
|
||||
+ * \param tplg Topology instance.
|
||||
+ * \param t Template object.
|
||||
+ * \return Zero on success, otherwise a negative error code
|
||||
+ */
|
||||
+int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Build all registered topology data into binary file.
|
||||
+ * \param tplg Topology instance.
|
||||
+ * \param outfile Binary topology output file.
|
||||
+ * \return Zero on success, otherwise a negative error code
|
||||
+ */
|
||||
+int snd_tplg_build(snd_tplg_t *tplg, const char *outfile);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Attach private data to topology manifest.
|
||||
+ * \param tplg Topology instance.
|
||||
+ * \param data Private data.
|
||||
+ * \param len Length of data in bytes.
|
||||
+ * \return Zero on success, otherwise a negative error code
|
||||
+ */
|
||||
+int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len);
|
||||
+
|
||||
/* \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
|
||||
index 35f684ba8067..68c4ce5803d1 100644
|
||||
--- a/src/topology/ctl.c
|
||||
+++ b/src/topology/ctl.c
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "list.h"
|
||||
#include "tplg_local.h"
|
||||
|
||||
+#define ENUM_VAL_SIZE (SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
|
||||
+
|
||||
/* copy referenced TLV to the mixer control */
|
||||
static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
|
||||
{
|
||||
@@ -606,3 +608,293 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
|
||||
+ struct snd_tplg_ctl_template *t)
|
||||
+{
|
||||
+ hdr->size = sizeof(struct snd_soc_tplg_ctl_hdr);
|
||||
+ hdr->type = t->type;
|
||||
+
|
||||
+ elem_copy_text(hdr->name, t->name,
|
||||
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+
|
||||
+ /* clean up access flag */
|
||||
+ if (t->access == 0)
|
||||
+ t->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
||||
+ t->access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE |
|
||||
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE |
|
||||
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE |
|
||||
+ SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE |
|
||||
+ SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND |
|
||||
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
|
||||
+
|
||||
+ hdr->access = t->access;
|
||||
+ hdr->ops.get = t->ops.get;
|
||||
+ hdr->ops.put = t->ops.put;
|
||||
+ hdr->ops.info = t->ops.info;
|
||||
+
|
||||
+ /* TLV */
|
||||
+ if (hdr->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
|
||||
+ && !(hdr->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
|
||||
+
|
||||
+ struct snd_tplg_tlv_template *tlvt = t->tlv;
|
||||
+ struct snd_soc_tplg_ctl_tlv *tlv = &hdr->tlv;
|
||||
+ struct snd_tplg_tlv_dbscale_template *scalet;
|
||||
+ struct snd_soc_tplg_tlv_dbscale *scale;
|
||||
+
|
||||
+ if (!tlvt) {
|
||||
+ SNDERR("error: missing TLV data\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
|
||||
+ tlv->type = tlvt->type;
|
||||
+
|
||||
+ switch (tlvt->type) {
|
||||
+ case SNDRV_CTL_TLVT_DB_SCALE:
|
||||
+ scalet = container_of(tlvt,
|
||||
+ struct snd_tplg_tlv_dbscale_template, hdr);
|
||||
+ scale = &tlv->scale;
|
||||
+ scale->min = scalet->min;
|
||||
+ scale->step = scalet->step;
|
||||
+ scale->mute = scalet->mute;
|
||||
+ break;
|
||||
+
|
||||
+ /* TODO: add support for other TLV types */
|
||||
+ default:
|
||||
+ SNDERR("error: unsupported TLV type %d\n", tlv->type);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
|
||||
+ struct tplg_elem **e)
|
||||
+{
|
||||
+ struct snd_soc_tplg_private *priv = mixer->priv;
|
||||
+ struct snd_soc_tplg_mixer_control *mc;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ tplg_dbg(" Control Mixer: %s\n", mixer->hdr.name);
|
||||
+
|
||||
+ if (mixer->hdr.type != SND_SOC_TPLG_TYPE_MIXER) {
|
||||
+ SNDERR("error: invalid mixer type %d\n", mixer->hdr.type);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, NULL, mixer->hdr.name,
|
||||
+ SND_TPLG_TYPE_MIXER);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* init new mixer */
|
||||
+ mc = elem->mixer_ctrl;
|
||||
+ mc->size = elem->size;
|
||||
+ ret = init_ctl_hdr(&mc->hdr, &mixer->hdr);
|
||||
+ if (ret < 0) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ mc->min = mixer->min;
|
||||
+ mc->max = mixer->max;
|
||||
+ mc->platform_max = mixer->platform_max;
|
||||
+ mc->invert = mixer->invert;
|
||||
+
|
||||
+ /* set channel reg to default state */
|
||||
+ for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++)
|
||||
+ mc->channel[i].reg = -1;
|
||||
+
|
||||
+ if (mixer->map)
|
||||
+ mc->num_channels = mixer->map->num_channels;
|
||||
+ for (i = 0; i < mc->num_channels; i++) {
|
||||
+ struct snd_tplg_channel_elem *channel = &mixer->map->channel[i];
|
||||
+
|
||||
+ mc->channel[i].size = channel->size;
|
||||
+ mc->channel[i].reg = channel->reg;
|
||||
+ mc->channel[i].shift = channel->shift;
|
||||
+ mc->channel[i].id = channel->id;
|
||||
+ }
|
||||
+
|
||||
+ /* priv data */
|
||||
+ if (priv) {
|
||||
+ mc = realloc(mc, elem->size + priv->size);
|
||||
+ if (!mc) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ elem->mixer_ctrl = mc;
|
||||
+ elem->size += priv->size;
|
||||
+ mc->priv.size = priv->size;
|
||||
+ memcpy(mc->priv.data, priv->data, priv->size);
|
||||
+ }
|
||||
+
|
||||
+ if (e)
|
||||
+ *e = elem;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
|
||||
+ struct tplg_elem **e)
|
||||
+{
|
||||
+ struct snd_soc_tplg_enum_control *ec;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ tplg_dbg(" Control Enum: %s\n", enum_ctl->hdr.name);
|
||||
+
|
||||
+ if (enum_ctl->hdr.type != SND_SOC_TPLG_TYPE_ENUM) {
|
||||
+ SNDERR("error: invalid enum type %d\n", enum_ctl->hdr.type);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, NULL, enum_ctl->hdr.name,
|
||||
+ SND_TPLG_TYPE_ENUM);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ec = elem->enum_ctrl;
|
||||
+ ec->size = elem->size;
|
||||
+ ret = init_ctl_hdr(&ec->hdr, &enum_ctl->hdr);
|
||||
+ if (ret < 0) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ec->items = enum_ctl->items;
|
||||
+ if (ec->items > SND_SOC_TPLG_NUM_TEXTS)
|
||||
+ ec->items = SND_SOC_TPLG_NUM_TEXTS;
|
||||
+
|
||||
+ ec->mask = enum_ctl->mask;
|
||||
+ ec->count = enum_ctl->items;
|
||||
+
|
||||
+ if (enum_ctl->texts != NULL) {
|
||||
+ for (i = 0; i < ec->items; i++) {
|
||||
+ if (enum_ctl->texts[i] != NULL)
|
||||
+ strncpy(ec->texts[i], enum_ctl->texts[i],
|
||||
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (enum_ctl->values != NULL) {
|
||||
+ for (i = 0; i < ec->items; i++) {
|
||||
+ if (enum_ctl->values[i])
|
||||
+ continue;
|
||||
+
|
||||
+ memcpy(&ec->values[i * sizeof(int) * ENUM_VAL_SIZE],
|
||||
+ enum_ctl->values[i],
|
||||
+ sizeof(int) * ENUM_VAL_SIZE);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (enum_ctl->priv != NULL) {
|
||||
+ ec = realloc(ec,
|
||||
+ elem->size + enum_ctl->priv->size);
|
||||
+ if (!ec) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ elem->enum_ctrl = ec;
|
||||
+ elem->size += enum_ctl->priv->size;
|
||||
+
|
||||
+ memcpy(ec->priv.data, enum_ctl->priv->data,
|
||||
+ enum_ctl->priv->size);
|
||||
+
|
||||
+ ec->priv.size = enum_ctl->priv->size;
|
||||
+ }
|
||||
+
|
||||
+ if (e)
|
||||
+ *e = elem;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
|
||||
+ struct tplg_elem **e)
|
||||
+{
|
||||
+ struct snd_soc_tplg_bytes_control *be;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int ret;
|
||||
+
|
||||
+ tplg_dbg(" Control Bytes: %s\n", bytes_ctl->hdr.name);
|
||||
+
|
||||
+ if (bytes_ctl->hdr.type != SND_SOC_TPLG_TYPE_BYTES) {
|
||||
+ SNDERR("error: invalid bytes type %d\n", bytes_ctl->hdr.type);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, NULL, bytes_ctl->hdr.name,
|
||||
+ SND_TPLG_TYPE_BYTES);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ be = elem->bytes_ext;
|
||||
+ be->size = elem->size;
|
||||
+ ret = init_ctl_hdr(&be->hdr, &bytes_ctl->hdr);
|
||||
+ if (ret < 0) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ be->max = bytes_ctl->max;
|
||||
+ be->mask = bytes_ctl->mask;
|
||||
+ be->base = bytes_ctl->base;
|
||||
+ be->num_regs = bytes_ctl->num_regs;
|
||||
+ be->ext_ops.put = bytes_ctl->ext_ops.put;
|
||||
+ be->ext_ops.get = bytes_ctl->ext_ops.get;
|
||||
+
|
||||
+ if (bytes_ctl->priv != NULL) {
|
||||
+ be = realloc(be,
|
||||
+ elem->size + bytes_ctl->priv->size);
|
||||
+ if (!be) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ elem->bytes_ext = be;
|
||||
+ elem->size += bytes_ctl->priv->size;
|
||||
+
|
||||
+ memcpy(be->priv.data, bytes_ctl->priv->data,
|
||||
+ bytes_ctl->priv->size);
|
||||
+
|
||||
+ be->priv.size = bytes_ctl->priv->size;
|
||||
+ }
|
||||
+
|
||||
+ /* check on TLV bytes control */
|
||||
+ if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
|
||||
+ if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
|
||||
+ != SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
|
||||
+ SNDERR("error: Invalid TLV bytes control access 0x%x\n",
|
||||
+ be->hdr.access);
|
||||
+ tplg_elem_free(elem);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!be->max) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (e)
|
||||
+ *e = elem;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_add_mixer_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
|
||||
+{
|
||||
+ return tplg_add_mixer(tplg, t->mixer, NULL);
|
||||
+}
|
||||
+
|
||||
+int tplg_add_enum_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
|
||||
+{
|
||||
+ return tplg_add_enum(tplg, t->enum_ctl, NULL);
|
||||
+}
|
||||
+
|
||||
+int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
|
||||
+{
|
||||
+ return tplg_add_bytes(tplg, t->bytes_ctl, NULL);
|
||||
+}
|
||||
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
|
||||
index 3458aa77838b..14969eedeea0 100644
|
||||
--- a/src/topology/dapm.c
|
||||
+++ b/src/topology/dapm.c
|
||||
@@ -142,8 +142,6 @@ static int tplg_build_widget(snd_tplg_t *tplg,
|
||||
list_for_each(pos, base) {
|
||||
|
||||
ref = list_entry(pos, struct tplg_ref, list);
|
||||
- if (ref->id == NULL || ref->elem)
|
||||
- continue;
|
||||
|
||||
switch (ref->type) {
|
||||
case SND_TPLG_TYPE_MIXER:
|
||||
@@ -162,6 +160,14 @@ static int tplg_build_widget(snd_tplg_t *tplg,
|
||||
err = copy_dapm_control(elem, ref->elem);
|
||||
break;
|
||||
|
||||
+ case SND_TPLG_TYPE_BYTES:
|
||||
+ if (!ref->elem)
|
||||
+ ref->elem = tplg_elem_lookup(&tplg->bytes_ext_list,
|
||||
+ ref->id, SND_TPLG_TYPE_BYTES);
|
||||
+ if (ref->elem)
|
||||
+ err = copy_dapm_control(elem, ref->elem);
|
||||
+ break;
|
||||
+
|
||||
case SND_TPLG_TYPE_DATA:
|
||||
if (!ref->elem)
|
||||
ref->elem = tplg_elem_lookup(&tplg->pdata_list,
|
||||
@@ -278,6 +284,30 @@ int tplg_build_routes(snd_tplg_t *tplg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+struct tplg_elem* tplg_elem_new_route(snd_tplg_t *tplg)
|
||||
+{
|
||||
+ struct tplg_elem *elem;
|
||||
+ struct snd_soc_tplg_dapm_graph_elem *line;
|
||||
+
|
||||
+ elem = tplg_elem_new();
|
||||
+ if (!elem)
|
||||
+ return NULL;
|
||||
+
|
||||
+ list_add_tail(&elem->list, &tplg->route_list);
|
||||
+ strcpy(elem->id, "line");
|
||||
+ elem->type = SND_TPLG_TYPE_DAPM_GRAPH;
|
||||
+ elem->size = sizeof(*line);
|
||||
+
|
||||
+ line = calloc(1, sizeof(*line));
|
||||
+ if (!line) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ elem->route = line;
|
||||
+
|
||||
+ return elem;
|
||||
+}
|
||||
+
|
||||
#define LINE_SIZE 1024
|
||||
|
||||
/* line is defined as '"source, control, sink"' */
|
||||
@@ -334,7 +364,7 @@ static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t *cfg)
|
||||
snd_config_iterator_t i, next;
|
||||
snd_config_t *n;
|
||||
struct tplg_elem *elem;
|
||||
- struct snd_soc_tplg_dapm_graph_elem *line = NULL;
|
||||
+ struct snd_soc_tplg_dapm_graph_elem *line;
|
||||
int err;
|
||||
|
||||
snd_config_for_each(i, next, cfg) {
|
||||
@@ -344,20 +374,11 @@ static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t *cfg)
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
continue;
|
||||
|
||||
- elem = tplg_elem_new();
|
||||
+ elem = tplg_elem_new_route(tplg);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
|
||||
- list_add_tail(&elem->list, &tplg->route_list);
|
||||
- strcpy(elem->id, "line");
|
||||
- elem->type = SND_TPLG_TYPE_DAPM_GRAPH;
|
||||
- elem->size = sizeof(*line);
|
||||
-
|
||||
- line = calloc(1, sizeof(*line));
|
||||
- if (!line)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- elem->route = line;
|
||||
+ line = elem->route;
|
||||
|
||||
err = tplg_parse_line(val, line);
|
||||
if (err < 0)
|
||||
@@ -558,3 +579,137 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t)
|
||||
+{
|
||||
+ struct tplg_elem *elem;
|
||||
+ struct snd_soc_tplg_dapm_graph_elem *line;
|
||||
+
|
||||
+ if (!t->src || !t->sink)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ elem = tplg_elem_new_route(tplg);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ line = elem->route;
|
||||
+ elem_copy_text(line->source, t->src, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ if (t->ctl)
|
||||
+ elem_copy_text(line->control, t->ctl,
|
||||
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ elem_copy_text(line->sink, t->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_add_graph_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
|
||||
+{
|
||||
+ struct snd_tplg_graph_template *gt = t->graph;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ for (i = 0; i < gt->count; i++) {
|
||||
+ ret = tplg_add_route(tplg, gt->elem + i);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
|
||||
+{
|
||||
+ struct snd_tplg_widget_template *wt = t->widget;
|
||||
+ struct snd_soc_tplg_dapm_widget *w;
|
||||
+ struct tplg_elem *elem;
|
||||
+ int i, ret = 0;
|
||||
+
|
||||
+ tplg_dbg("Widget: %s\n", wt->name);
|
||||
+
|
||||
+ elem = tplg_elem_new_common(tplg, NULL, wt->name,
|
||||
+ SND_TPLG_TYPE_DAPM_WIDGET);
|
||||
+ if (!elem)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* init new widget */
|
||||
+ w = elem->widget;
|
||||
+ w->size = elem->size;
|
||||
+
|
||||
+ w->id = wt->id;
|
||||
+ elem_copy_text(w->name, wt->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ if (wt->sname)
|
||||
+ elem_copy_text(w->sname, wt->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+ w->reg = wt->reg;
|
||||
+ w->shift = wt->shift;
|
||||
+ w->mask = wt->mask;
|
||||
+ w->subseq = wt->subseq;
|
||||
+ w->invert = wt->invert;
|
||||
+ w->ignore_suspend = wt->ignore_suspend;
|
||||
+ w->event_flags = wt->event_flags;
|
||||
+ w->event_type = wt->event_type;
|
||||
+
|
||||
+ if (wt->priv != NULL) {
|
||||
+ w = realloc(w,
|
||||
+ elem->size + wt->priv->size);
|
||||
+ if (!w) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ elem->widget = w;
|
||||
+ elem->size += wt->priv->size;
|
||||
+
|
||||
+ memcpy(w->priv.data, wt->priv->data,
|
||||
+ wt->priv->size);
|
||||
+ w->priv.size = wt->priv->size;
|
||||
+ }
|
||||
+
|
||||
+ /* add controls to the widget's reference list */
|
||||
+ for (i = 0 ; i < wt->num_ctls; i++) {
|
||||
+ struct snd_tplg_ctl_template *ct = wt->ctl[i];
|
||||
+ struct tplg_elem *elem_ctl;
|
||||
+ struct snd_tplg_mixer_template *mt;
|
||||
+ struct snd_tplg_bytes_template *bt;
|
||||
+ struct snd_tplg_enum_template *et;
|
||||
+
|
||||
+ if (!ct) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ switch (ct->type) {
|
||||
+ case SND_SOC_TPLG_TYPE_MIXER:
|
||||
+ mt = container_of(ct, struct snd_tplg_mixer_template, hdr);
|
||||
+ ret = tplg_add_mixer(tplg, mt, &elem_ctl);
|
||||
+ break;
|
||||
+
|
||||
+ case SND_SOC_TPLG_TYPE_BYTES:
|
||||
+ bt = container_of(ct, struct snd_tplg_bytes_template, hdr);
|
||||
+ ret = tplg_add_bytes(tplg, bt, &elem_ctl);
|
||||
+ break;
|
||||
+
|
||||
+ case SND_SOC_TPLG_TYPE_ENUM:
|
||||
+ et = container_of(ct, struct snd_tplg_enum_template, hdr);
|
||||
+ ret = tplg_add_enum(tplg, et, &elem_ctl);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ SNDERR("error: widget %s: invalid type %d for ctl %d\n",
|
||||
+ wt->name, ct->type, i);
|
||||
+ ret = -EINVAL;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = tplg_ref_add_elem(elem, elem_ctl);
|
||||
+ if (ret < 0) {
|
||||
+ tplg_elem_free(elem);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/topology/elem.c b/src/topology/elem.c
|
||||
index daabe75ebdd2..d7842361e444 100644
|
||||
--- a/src/topology/elem.c
|
||||
+++ b/src/topology/elem.c
|
||||
@@ -35,6 +35,23 @@ int tplg_ref_add(struct tplg_elem *elem, int type, const char* id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* directly add a reference elem */
|
||||
+int tplg_ref_add_elem(struct tplg_elem *elem, struct tplg_elem *elem_ref)
|
||||
+{
|
||||
+ struct tplg_ref *ref;
|
||||
+
|
||||
+ ref = calloc(1, sizeof(*ref));
|
||||
+ if (!ref)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ref->type = elem_ref->type;
|
||||
+ ref->elem = elem_ref;
|
||||
+ elem_copy_text(ref->id, elem_ref->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
|
||||
+
|
||||
+ list_add_tail(&ref->list, &elem->ref_list);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void tplg_ref_free_list(struct list_head *base)
|
||||
{
|
||||
struct list_head *pos, *npos;
|
||||
diff --git a/src/topology/parser.c b/src/topology/parser.c
|
||||
index 3e3e2b35da83..ca7de0689cea 100644
|
||||
--- a/src/topology/parser.c
|
||||
+++ b/src/topology/parser.c
|
||||
@@ -266,11 +266,8 @@ int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
|
||||
snd_config_t *cfg = NULL;
|
||||
int err = 0;
|
||||
|
||||
- /* delete any old output files */
|
||||
- unlink(outfile);
|
||||
-
|
||||
tplg->out_fd =
|
||||
- open(outfile, O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
+ open(outfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (tplg->out_fd < 0) {
|
||||
SNDERR("error: failed to open %s err %d\n",
|
||||
outfile, -errno);
|
||||
@@ -309,6 +306,60 @@ out_close:
|
||||
return err;
|
||||
}
|
||||
|
||||
+int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
|
||||
+{
|
||||
+ switch (t->type) {
|
||||
+ case SND_TPLG_TYPE_MIXER:
|
||||
+ return tplg_add_mixer_object(tplg, t);
|
||||
+ case SND_TPLG_TYPE_ENUM:
|
||||
+ return tplg_add_enum_object(tplg, t);
|
||||
+ case SND_TPLG_TYPE_BYTES:
|
||||
+ return tplg_add_bytes_object(tplg, t);
|
||||
+ case SND_TPLG_TYPE_DAPM_WIDGET:
|
||||
+ return tplg_add_widget_object(tplg, t);
|
||||
+ case SND_TPLG_TYPE_DAPM_GRAPH:
|
||||
+ return tplg_add_graph_object(tplg, t);
|
||||
+ default:
|
||||
+ SNDERR("error: invalid object type %d\n", t->type);
|
||||
+ return -EINVAL;
|
||||
+ };
|
||||
+}
|
||||
+
|
||||
+int snd_tplg_build(snd_tplg_t *tplg, const char *outfile)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ tplg->out_fd =
|
||||
+ open(outfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
+ if (tplg->out_fd < 0) {
|
||||
+ SNDERR("error: failed to open %s err %d\n",
|
||||
+ outfile, -errno);
|
||||
+ return -errno;
|
||||
+ }
|
||||
+
|
||||
+ err = tplg_build_integ(tplg);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to check topology integrity\n");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ err = tplg_write_data(tplg);
|
||||
+ if (err < 0) {
|
||||
+ SNDERR("error: failed to write data %d\n", err);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ close(tplg->out_fd);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len)
|
||||
+{
|
||||
+ tplg->manifest.priv.size = len;
|
||||
+ tplg->manifest_pdata = data;
|
||||
+}
|
||||
+
|
||||
void snd_tplg_verbose(snd_tplg_t *tplg, int verbose)
|
||||
{
|
||||
tplg->verbose = verbose;
|
||||
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
|
||||
index ec6304599538..d2b9aa6ff8ab 100644
|
||||
--- a/src/topology/tplg_local.h
|
||||
+++ b/src/topology/tplg_local.h
|
||||
@@ -190,6 +190,7 @@ int tplg_build_pcm_dai(snd_tplg_t *tplg, unsigned int type);
|
||||
int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref);
|
||||
|
||||
int tplg_ref_add(struct tplg_elem *elem, int type, const char* id);
|
||||
+int tplg_ref_add_elem(struct tplg_elem *elem, struct tplg_elem *elem_ref);
|
||||
|
||||
struct tplg_elem *tplg_elem_new(void);
|
||||
void tplg_elem_free(struct tplg_elem *elem);
|
||||
@@ -214,3 +215,16 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
|
||||
struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base,
|
||||
const char* id);
|
||||
+
|
||||
+int tplg_add_mixer_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
|
||||
+int tplg_add_enum_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
|
||||
+int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
|
||||
+int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
|
||||
+int tplg_add_graph_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
|
||||
+
|
||||
+int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
|
||||
+ struct tplg_elem **e);
|
||||
+int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
|
||||
+ struct tplg_elem **e);
|
||||
+int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
|
||||
+ struct tplg_elem **e);
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,50 +0,0 @@
|
||||
From 3313f8740d936b1dbc6391ce3227ba467c6f603d Mon Sep 17 00:00:00 2001
|
||||
From: David Henningsson <david.henningsson@canonical.com>
|
||||
Date: Mon, 24 Aug 2015 20:37:29 +0200
|
||||
Subject: [PATCH] pcm: Fix doxygen for two enums
|
||||
|
||||
The doxygen comments were wrong, making doxygen output weird.
|
||||
|
||||
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/pcm.h | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/include/pcm.h b/include/pcm.h
|
||||
index a1d14a989a47..0be1a321adba 100644
|
||||
--- a/include/pcm.h
|
||||
+++ b/include/pcm.h
|
||||
@@ -324,9 +324,9 @@ typedef enum _snd_pcm_tstamp {
|
||||
} snd_pcm_tstamp_t;
|
||||
|
||||
typedef enum _snd_pcm_tstamp_type {
|
||||
- SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /** gettimeofday equivalent */
|
||||
- SND_PCM_TSTAMP_TYPE_MONOTONIC, /** posix_clock_monotonic equivalent */
|
||||
- SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /** monotonic_raw (no NTP) */
|
||||
+ SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /**< gettimeofday equivalent */
|
||||
+ SND_PCM_TSTAMP_TYPE_MONOTONIC, /**< posix_clock_monotonic equivalent */
|
||||
+ SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /**< monotonic_raw (no NTP) */
|
||||
SND_PCM_TSTAMP_TYPE_LAST = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
|
||||
} snd_pcm_tstamp_type_t;
|
||||
|
||||
@@ -527,11 +527,11 @@ int snd_pcm_unlink(snd_pcm_t *pcm);
|
||||
|
||||
/** channel map list type */
|
||||
enum snd_pcm_chmap_type {
|
||||
- SND_CHMAP_TYPE_NONE = 0,/** unspecified channel position */
|
||||
- SND_CHMAP_TYPE_FIXED, /** fixed channel position */
|
||||
- SND_CHMAP_TYPE_VAR, /** freely swappable channel position */
|
||||
- SND_CHMAP_TYPE_PAIRED, /** pair-wise swappable channel position */
|
||||
- SND_CHMAP_TYPE_LAST = SND_CHMAP_TYPE_PAIRED, /** last entry */
|
||||
+ SND_CHMAP_TYPE_NONE = 0,/**< unspecified channel position */
|
||||
+ SND_CHMAP_TYPE_FIXED, /**< fixed channel position */
|
||||
+ SND_CHMAP_TYPE_VAR, /**< freely swappable channel position */
|
||||
+ SND_CHMAP_TYPE_PAIRED, /**< pair-wise swappable channel position */
|
||||
+ SND_CHMAP_TYPE_LAST = SND_CHMAP_TYPE_PAIRED, /**< last entry */
|
||||
};
|
||||
|
||||
/** channel positions */
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,80 +0,0 @@
|
||||
From fe8bb1fe02f9c7b7cb6048a17a8ff1ea30f97fc8 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 8 Sep 2015 20:57:47 +0200
|
||||
Subject: [PATCH] pcm: ioplug,extplug: Fix logic errors in type checks
|
||||
|
||||
A few error checks are wrongly performed with logical and (&&) instead
|
||||
of logical or (||), which condition never met.
|
||||
|
||||
Reported-by: David Binderman <dcb314@hotmail.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_extplug.c | 8 ++++----
|
||||
src/pcm/pcm_ioplug.c | 4 ++--
|
||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_extplug.c b/src/pcm/pcm_extplug.c
|
||||
index a5de6d848e21..a04f826c90a0 100644
|
||||
--- a/src/pcm/pcm_extplug.c
|
||||
+++ b/src/pcm/pcm_extplug.c
|
||||
@@ -766,7 +766,7 @@ void snd_pcm_extplug_params_reset(snd_pcm_extplug_t *extplug)
|
||||
int snd_pcm_extplug_set_slave_param_list(snd_pcm_extplug_t *extplug, int type, unsigned int num_list, const unsigned int *list)
|
||||
{
|
||||
extplug_priv_t *ext = extplug->pcm->private_data;
|
||||
- if (type < 0 && type >= SND_PCM_EXTPLUG_HW_PARAMS) {
|
||||
+ if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
|
||||
SNDERR("EXTPLUG: invalid parameter type %d", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -788,7 +788,7 @@ int snd_pcm_extplug_set_slave_param_list(snd_pcm_extplug_t *extplug, int type, u
|
||||
int snd_pcm_extplug_set_slave_param_minmax(snd_pcm_extplug_t *extplug, int type, unsigned int min, unsigned int max)
|
||||
{
|
||||
extplug_priv_t *ext = extplug->pcm->private_data;
|
||||
- if (type < 0 && type >= SND_PCM_EXTPLUG_HW_PARAMS) {
|
||||
+ if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
|
||||
SNDERR("EXTPLUG: invalid parameter type %d", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -814,7 +814,7 @@ int snd_pcm_extplug_set_slave_param_minmax(snd_pcm_extplug_t *extplug, int type,
|
||||
int snd_pcm_extplug_set_param_list(snd_pcm_extplug_t *extplug, int type, unsigned int num_list, const unsigned int *list)
|
||||
{
|
||||
extplug_priv_t *ext = extplug->pcm->private_data;
|
||||
- if (type < 0 && type >= SND_PCM_EXTPLUG_HW_PARAMS) {
|
||||
+ if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
|
||||
SNDERR("EXTPLUG: invalid parameter type %d", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -836,7 +836,7 @@ int snd_pcm_extplug_set_param_list(snd_pcm_extplug_t *extplug, int type, unsigne
|
||||
int snd_pcm_extplug_set_param_minmax(snd_pcm_extplug_t *extplug, int type, unsigned int min, unsigned int max)
|
||||
{
|
||||
extplug_priv_t *ext = extplug->pcm->private_data;
|
||||
- if (type < 0 && type >= SND_PCM_EXTPLUG_HW_PARAMS) {
|
||||
+ if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
|
||||
SNDERR("EXTPLUG: invalid parameter type %d", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
|
||||
index fe9347c835d5..43550c03875b 100644
|
||||
--- a/src/pcm/pcm_ioplug.c
|
||||
+++ b/src/pcm/pcm_ioplug.c
|
||||
@@ -1019,7 +1019,7 @@ void snd_pcm_ioplug_params_reset(snd_pcm_ioplug_t *ioplug)
|
||||
int snd_pcm_ioplug_set_param_list(snd_pcm_ioplug_t *ioplug, int type, unsigned int num_list, const unsigned int *list)
|
||||
{
|
||||
ioplug_priv_t *io = ioplug->pcm->private_data;
|
||||
- if (type < 0 && type >= SND_PCM_IOPLUG_HW_PARAMS) {
|
||||
+ if (type < 0 || type >= SND_PCM_IOPLUG_HW_PARAMS) {
|
||||
SNDERR("IOPLUG: invalid parameter type %d", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1043,7 +1043,7 @@ int snd_pcm_ioplug_set_param_list(snd_pcm_ioplug_t *ioplug, int type, unsigned i
|
||||
int snd_pcm_ioplug_set_param_minmax(snd_pcm_ioplug_t *ioplug, int type, unsigned int min, unsigned int max)
|
||||
{
|
||||
ioplug_priv_t *io = ioplug->pcm->private_data;
|
||||
- if (type < 0 && type >= SND_PCM_IOPLUG_HW_PARAMS) {
|
||||
+ if (type < 0 || type >= SND_PCM_IOPLUG_HW_PARAMS) {
|
||||
SNDERR("IOPLUG: invalid parameter type %d", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,39 +0,0 @@
|
||||
From 03d6b15291e3534afb72c5aa36495a932ef0cc6a Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 8 Sep 2015 21:48:17 +0200
|
||||
Subject: [PATCH] pcm: route: Remove bogus ! in snd_config_get_id() checks
|
||||
|
||||
There are strange "!" added before snd_config_get_id() return value
|
||||
checks in a couple of places in pcm_route.c. This essentially makes
|
||||
the result always positive, making checks bogus.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_route.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c
|
||||
index 2a437e88b93c..646517d2a9d2 100644
|
||||
--- a/src/pcm/pcm_route.c
|
||||
+++ b/src/pcm/pcm_route.c
|
||||
@@ -770,7 +770,7 @@ static int determine_chmap(snd_config_t *tt, snd_pcm_chmap_t **tt_chmap)
|
||||
snd_config_iterator_t j, jnext;
|
||||
snd_config_t *in = snd_config_iterator_entry(i);
|
||||
|
||||
- if (!snd_config_get_id(in, &id) < 0)
|
||||
+ if (snd_config_get_id(in, &id) < 0)
|
||||
continue;
|
||||
if (snd_config_get_type(in) != SND_CONFIG_TYPE_COMPOUND)
|
||||
goto err;
|
||||
@@ -1070,7 +1070,7 @@ static int _snd_pcm_route_determine_ttable(snd_config_t *tt,
|
||||
snd_config_iterator_t j, jnext;
|
||||
long cchannel;
|
||||
const char *id;
|
||||
- if (!snd_config_get_id(in, &id) < 0)
|
||||
+ if (snd_config_get_id(in, &id) < 0)
|
||||
continue;
|
||||
err = safe_strtol(id, &cchannel);
|
||||
if (err < 0) {
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,52 +0,0 @@
|
||||
From 76b9cae026bf73a00ccf3ec8833ec56f0e64f451 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 8 Sep 2015 22:04:48 +0200
|
||||
Subject: [PATCH] topology: builder: Fix possibly uninitialized variable in
|
||||
write_elem_block()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When an empty list is passed to write_elem_block(), it may leave
|
||||
vendor_type uninitialized.
|
||||
builder.c: In function ‘write_elem_block’:
|
||||
builder.c:127:8: warning: ‘vendor_type’ may be used uninitialized in this function [-Wmaybe-uninitialized]
|
||||
ret = write_block_header(tplg, tplg_type, vendor_type,
|
||||
^
|
||||
builder.c:114:33: note: ‘vendor_type’ was declared here
|
||||
int ret, wsize = 0, count = 0, vendor_type;
|
||||
^
|
||||
|
||||
Add an immediate return for count = 0 for avoiding it, and simplify
|
||||
the code initializing vendor_type without using a one-shot loop.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/builder.c | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
||||
index 3bccd44827cc..91412aadd098 100644
|
||||
--- a/src/topology/builder.c
|
||||
+++ b/src/topology/builder.c
|
||||
@@ -116,13 +116,12 @@ static int write_elem_block(snd_tplg_t *tplg,
|
||||
/* count number of elements */
|
||||
list_for_each(pos, base)
|
||||
count++;
|
||||
+ if (!count)
|
||||
+ return 0;
|
||||
|
||||
/* write the header for this block */
|
||||
- list_for_each(pos, base) {
|
||||
- elem = list_entry(pos, struct tplg_elem, list);
|
||||
- vendor_type = elem->vendor_type;
|
||||
- break;
|
||||
- }
|
||||
+ elem = list_entry(base->next, struct tplg_elem, list);
|
||||
+ vendor_type = elem->vendor_type;
|
||||
|
||||
ret = write_block_header(tplg, tplg_type, vendor_type,
|
||||
SND_SOC_TPLG_ABI_VERSION, 0, size, count);
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,35 +0,0 @@
|
||||
From f41fe763e9bc80783bf1471141ac06d514ffaef3 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 8 Sep 2015 22:09:44 +0200
|
||||
Subject: [PATCH] topology: ctl: Fix access type checks
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Fix the wrong bit-and check by adding parentheses properly:
|
||||
ctl.c: In function ‘tplg_add_bytes’:
|
||||
ctl.c:868:22: warning: suggest parentheses around comparison in operand of ‘&’ [-Wparentheses]
|
||||
if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
|
||||
^
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/ctl.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
|
||||
index 68c4ce5803d1..7d8787f347b8 100644
|
||||
--- a/src/topology/ctl.c
|
||||
+++ b/src/topology/ctl.c
|
||||
@@ -865,7 +865,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
|
||||
|
||||
/* check on TLV bytes control */
|
||||
if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
|
||||
- if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
|
||||
+ if ((be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)
|
||||
!= SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
|
||||
SNDERR("error: Invalid TLV bytes control access 0x%x\n",
|
||||
be->hdr.access);
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,41 +0,0 @@
|
||||
From 5b21400c42877ff6c2a386c7c5ed5c6c6c9bf664 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 8 Sep 2015 22:11:48 +0200
|
||||
Subject: [PATCH] topology: data: Fix wrong size check in tplg_parse_data_hex()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
A wrong, uninitialized variable is referred as the size to check in
|
||||
tplg_parse_data_hex(). Spotted by gcc warning:
|
||||
data.c: In function ‘tplg_parse_data_hex’:
|
||||
data.c:228:5: warning: ‘esize’ may be used uninitialized in this function [-Wmaybe-uninitialized]
|
||||
if (esize > TPLG_MAX_PRIV_SIZE) {
|
||||
^
|
||||
data.c:211:12: note: ‘esize’ was declared here
|
||||
int size, esize, off, num;
|
||||
^
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/data.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/topology/data.c b/src/topology/data.c
|
||||
index 4ee1f8a15f95..370c0faead36 100644
|
||||
--- a/src/topology/data.c
|
||||
+++ b/src/topology/data.c
|
||||
@@ -225,8 +225,8 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
|
||||
size = num * width;
|
||||
priv = elem->data;
|
||||
|
||||
- if (esize > TPLG_MAX_PRIV_SIZE) {
|
||||
- SNDERR("error: data too big %d\n", esize);
|
||||
+ if (size > TPLG_MAX_PRIV_SIZE) {
|
||||
+ SNDERR("error: data too big %d\n", size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,35 +0,0 @@
|
||||
From e38b13f128c743fe1f664e4491fdd0c880265da1 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 8 Sep 2015 22:13:50 +0200
|
||||
Subject: [PATCH] topology: parser: Add missing return value to
|
||||
snd_tplg_set_manifest_data()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Spotted by gcc warning:
|
||||
parser.c: In function ‘snd_tplg_set_manifest_data’:
|
||||
parser.c:361:1: warning: control reaches end of non-void function [-Wreturn-type]
|
||||
}
|
||||
^
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/parser.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/topology/parser.c b/src/topology/parser.c
|
||||
index ca7de0689cea..44c6146b22f2 100644
|
||||
--- a/src/topology/parser.c
|
||||
+++ b/src/topology/parser.c
|
||||
@@ -358,6 +358,7 @@ int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len)
|
||||
{
|
||||
tplg->manifest.priv.size = len;
|
||||
tplg->manifest_pdata = data;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
void snd_tplg_verbose(snd_tplg_t *tplg, int verbose)
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,47 +0,0 @@
|
||||
From 9a2fe5399c6ff987fe4e23907c6467c3d2baa307 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Tue, 8 Sep 2015 22:15:02 +0200
|
||||
Subject: [PATCH] topology: pcm: Remove unused variables
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Fix gcc warnings:
|
||||
pcm.c: In function ‘tplg_parse_stream_cfg’:
|
||||
pcm.c:160:6: warning: unused variable ‘ret’ [-Wunused-variable]
|
||||
int ret;
|
||||
^
|
||||
pcm.c: In function ‘split_format’:
|
||||
pcm.c:267:13: warning: unused variable ‘ret’ [-Wunused-variable]
|
||||
int i = 0, ret;
|
||||
^
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/topology/pcm.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
|
||||
index 6e42aa18b99b..18d5f0b1b040 100644
|
||||
--- a/src/topology/pcm.c
|
||||
+++ b/src/topology/pcm.c
|
||||
@@ -157,7 +157,6 @@ static int tplg_parse_stream_cfg(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct snd_soc_tplg_stream *stream;
|
||||
const char *id, *val;
|
||||
snd_pcm_format_t format;
|
||||
- int ret;
|
||||
|
||||
snd_config_get_id(cfg, &id);
|
||||
|
||||
@@ -264,7 +263,7 @@ static int split_format(struct snd_soc_tplg_stream_caps *caps, char *str)
|
||||
{
|
||||
char *s = NULL;
|
||||
snd_pcm_format_t format;
|
||||
- int i = 0, ret;
|
||||
+ int i = 0;
|
||||
|
||||
s = strtok(str, ",");
|
||||
while ((s != NULL) && (i < SND_SOC_TPLG_MAX_FORMATS)) {
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,44 +0,0 @@
|
||||
From c82417650a1ea4446c19dd82bfab9d8e6cd5a969 Mon Sep 17 00:00:00 2001
|
||||
From: Khem Raj <raj.khem@gmail.com>
|
||||
Date: Tue, 15 Sep 2015 18:48:02 +0300
|
||||
Subject: [PATCH] build: Do not try to detect cross-compiler
|
||||
|
||||
cross compilers are passed via path may not be a gcc based cross
|
||||
compiler in such cases this check fails and try's to force gcc based
|
||||
cross compiler detection, This code is a convenience that limits the
|
||||
build system
|
||||
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
configure.ac | 14 --------------
|
||||
1 file changed, 14 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index a482b3e7f6ca..a14e52de5e3b 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -27,20 +27,6 @@ AC_PREFIX_DEFAULT(/usr)
|
||||
|
||||
dnl Checks for programs.
|
||||
|
||||
-dnl try to gues cross-compiler if not set
|
||||
-if test "x$host" != "x$build" -a -z "`echo $CC | grep -e '-gcc'`";
|
||||
-then
|
||||
- AC_MSG_CHECKING(for cross-compiler)
|
||||
-
|
||||
- which ${program_prefix}gcc >/dev/null 2>&1 && CC=${program_prefix}gcc
|
||||
- which ${host_cpu}-${host_os}-gcc >/dev/null 2>&1 \
|
||||
- && CC=${host_cpu}-${host_os}-gcc
|
||||
- which ${host_cpu}-${host_vendor}-${host_os}-gcc >/dev/null 2>&1 \
|
||||
- && CC=${host_cpu}-${host_vendor}-${host_os}-gcc
|
||||
-
|
||||
- AC_MSG_RESULT($CC)
|
||||
-fi
|
||||
-
|
||||
CFLAGS="$CFLAGS -D_GNU_SOURCE"
|
||||
|
||||
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,92 +0,0 @@
|
||||
From 8b0a5310bf3cb6ca1f7d70e3f4149b25b17b453a Mon Sep 17 00:00:00 2001
|
||||
From: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Date: Wed, 16 Sep 2015 17:07:13 +0800
|
||||
Subject: [PATCH] topology: Add API to set a vendor specific version number
|
||||
|
||||
This vendor-specific version number is optional. It will be written to
|
||||
the 'version' field of each block header of the binary toplogy data file.
|
||||
The vendor driver can check this number for further processing in kernel.
|
||||
|
||||
The topology ABI version number is still stored in the 'abi' field of
|
||||
block headers.
|
||||
|
||||
Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>
|
||||
Reviewed-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
include/topology.h | 8 ++++++++
|
||||
src/topology/builder.c | 6 +++---
|
||||
src/topology/parser.c | 7 +++++++
|
||||
3 files changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/include/topology.h b/include/topology.h
|
||||
index 6ff8c5fb4609..9b84bd9331dc 100644
|
||||
--- a/include/topology.h
|
||||
+++ b/include/topology.h
|
||||
@@ -690,6 +690,14 @@ int snd_tplg_build(snd_tplg_t *tplg, const char *outfile);
|
||||
*/
|
||||
int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len);
|
||||
|
||||
+/**
|
||||
+ * \brief Set an optional vendor specific version number.
|
||||
+ * \param tplg Topology instance.
|
||||
+ * \param version Vendor specific version number.
|
||||
+ * \return Zero on success, otherwise a negative error code
|
||||
+ */
|
||||
+int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version);
|
||||
+
|
||||
/* \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
||||
index 91412aadd098..8d57a8b719f7 100644
|
||||
--- a/src/topology/builder.c
|
||||
+++ b/src/topology/builder.c
|
||||
@@ -89,7 +89,7 @@ static int write_data_block(snd_tplg_t *tplg, int size, int tplg_type,
|
||||
|
||||
/* write the header for this block */
|
||||
ret = write_block_header(tplg, tplg_type, 0,
|
||||
- SND_SOC_TPLG_ABI_VERSION, 0, size, 1);
|
||||
+ tplg->version, 0, size, 1);
|
||||
if (ret < 0) {
|
||||
SNDERR("error: failed to write %s block %d\n", obj_name, ret);
|
||||
return ret;
|
||||
@@ -124,7 +124,7 @@ static int write_elem_block(snd_tplg_t *tplg,
|
||||
vendor_type = elem->vendor_type;
|
||||
|
||||
ret = write_block_header(tplg, tplg_type, vendor_type,
|
||||
- SND_SOC_TPLG_ABI_VERSION, 0, size, count);
|
||||
+ tplg->version, 0, size, count);
|
||||
if (ret < 0) {
|
||||
SNDERR("error: failed to write %s block %d\n",
|
||||
obj_name, ret);
|
||||
@@ -242,7 +242,7 @@ static int write_manifest_data(snd_tplg_t *tplg)
|
||||
|
||||
/* write the header for this block */
|
||||
ret = write_block_header(tplg, SND_SOC_TPLG_TYPE_MANIFEST, 0,
|
||||
- SND_SOC_TPLG_ABI_VERSION, 0,
|
||||
+ tplg->version, 0,
|
||||
sizeof(tplg->manifest) + tplg->manifest.priv.size, 1);
|
||||
if (ret < 0) {
|
||||
SNDERR("error: failed to write manifest block %d\n", ret);
|
||||
diff --git a/src/topology/parser.c b/src/topology/parser.c
|
||||
index 44c6146b22f2..6671055ae226 100644
|
||||
--- a/src/topology/parser.c
|
||||
+++ b/src/topology/parser.c
|
||||
@@ -361,6 +361,13 @@ int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version)
|
||||
+{
|
||||
+ tplg->version = version;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void snd_tplg_verbose(snd_tplg_t *tplg, int verbose)
|
||||
{
|
||||
tplg->verbose = verbose;
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,40 +0,0 @@
|
||||
From f07e9af7eeebc950fd7bf4101a6af7f53ac741b6 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Fri, 2 Oct 2015 11:55:36 +0200
|
||||
Subject: [PATCH] pcm: ladspa: Fix segfault due to a wrong channel reference
|
||||
|
||||
Because of a typo in referencing the input array in
|
||||
snd_pcm_ladspa_allocate_memory(), ladpsa PCM plugin may cause a
|
||||
segfault at prepare when input and and output channels are different:
|
||||
#0 0x00007ffff78623ef in snd_pcm_ladspa_allocate_memory (pcm=0x626fa0, pcm=0x626fa0, pcm=0x626fa0, ladspa=0x621ad0) at pcm_ladspa.c:753
|
||||
#1 snd_pcm_ladspa_init (pcm=0x626fa0) at pcm_ladspa.c:834
|
||||
#2 0x00007ffff7842946 in snd_pcm_plugin_prepare (pcm=0x626fa0) at pcm_plugin.c:171
|
||||
#3 0x00007ffff784290f in snd_pcm_plugin_prepare (pcm=0x62c760) at pcm_plugin.c:162
|
||||
#4 0x000000000040256a in ?? ()
|
||||
#5 0x00007ffff7222ec5 in __libc_start_main (main=0x401d80,a argc=4, argv=0x7fffffffde28, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffde18) at libc-start.c:287
|
||||
#6 0x0000000000402fdd in ?? ()
|
||||
|
||||
This patch corrects the wrong reference.
|
||||
|
||||
Reported-and-tested-by: Andreas Hartmann <mail@andreashartmann.eu>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
src/pcm/pcm_ladspa.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/pcm/pcm_ladspa.c b/src/pcm/pcm_ladspa.c
|
||||
index 631ee0f35b73..6552b4379ec0 100644
|
||||
--- a/src/pcm/pcm_ladspa.c
|
||||
+++ b/src/pcm/pcm_ladspa.c
|
||||
@@ -749,7 +749,7 @@ static int snd_pcm_ladspa_allocate_memory(snd_pcm_t *pcm, snd_pcm_ladspa_t *lads
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (idx = 0; idx < instance->input.channels.size; idx++) {
|
||||
- chn = instance->output.channels.array[idx];
|
||||
+ chn = instance->input.channels.array[idx];
|
||||
if (pchannels[chn] == NULL && chn < ichannels) {
|
||||
instance->input.data[idx] = NULL;
|
||||
continue;
|
||||
--
|
||||
2.5.3
|
||||
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:73043c35eb9636be0f4af6a240235c213f12a25feb1f04aeeac8cb7e30fcbdd0
|
||||
size 905417
|
3
alsa-lib-1.1.0.tar.bz2
Normal file
3
alsa-lib-1.1.0.tar.bz2
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dfde65d11e82b68f82e562ab6228c1fb7c78854345d3c57e2c68a9dd3dae1f15
|
||||
size 929874
|
82
alsa.changes
82
alsa.changes
@ -1,3 +1,85 @@
|
||||
-------------------------------------------------------------------
|
||||
Mon Nov 9 11:32:40 CET 2015 - tiwai@suse.de
|
||||
|
||||
- Update to alsa-lib 1.1.0:
|
||||
including all previous fixes, with more updates for topology API,
|
||||
a fix for dmix/dsnoop slave PCM xrun, some build fixes /
|
||||
improvements.
|
||||
- Fix the build with old gcc on SLE11:
|
||||
0001-topology-Add-missing-include-sys-stat.h.patch
|
||||
- Dropped patches:
|
||||
0001-ucm-document-some-standard-values.patch
|
||||
0002-conf-ucm-broadwell-rt286-add-ucm-config.patch
|
||||
0003-conf-ucm-Add-Makefile.am-for-broadwell-rt286-ucm-con.patch
|
||||
0004-ucm-reformat-snd_use_case_get-doc.patch
|
||||
0005-ucm-improve-jack-configuration-documentation.patch
|
||||
0006-USB-audio-Sound-Blaster-HD-iec958-is-on-device-1.patch
|
||||
0007-Sync-include-sound-asound.h-with-4.1-kernel.patch
|
||||
0008-conf-ucm-broadwell-rt286-change-to-use-the-correct-j.patch
|
||||
0009-namehint-Fix-invalid-list-access-in-snd_device_name_.patch
|
||||
0010-namehint-Fix-the-listing-without-device-number.patch
|
||||
0011-namehint-Fix-bad-free-with-invalid-iface-name.patch
|
||||
0012-Allow-hint-for-ctl-hwdep-timer-and-seq.patch
|
||||
0013-conf-Add-hint-descriptions-to-ctl-hwdep-seq-and-time.patch
|
||||
0014-conf-ucm-broadwell-rt286-change-to-set-capture-volum.patch
|
||||
0015-ucm-allow-multiple-devices-in-JackHWMute.patch
|
||||
0016-pcm-Remove-assert-from-snd_pcm_hw_params_slave.patch
|
||||
0017-test-pcm-Fix-generated-values-with-float-PCM-format.patch
|
||||
0018-test-pcm_min-Fix-error-messages.patch
|
||||
0019-pcm-Don-t-assert-in-_snd_pcm_hw_params_internal.patch
|
||||
0020-pcm-Fix-snd_pcm_status-for-dmix-co.patch
|
||||
0021-control-Allow-cset-ing-specific-values-in-the-multi-.patch
|
||||
0022-PCM-snd_pcm_xxxx_drain-maybe-blocked-after-suspend-a.patch
|
||||
0023-surround41-50.conf-Use-chmap-syntax-for-better-flexi.patch
|
||||
0024-ucm-docs-fix-doxygen-exclude-patch-for-UCM-local-hea.patch
|
||||
0025-ucm-docs-Fix-doxygen-formatting-for-UCM-main-page.patch
|
||||
0026-docs-Add-UCM-link-to-main-doxygen-page.patch
|
||||
0027-Replace-unsafe-characters-with-_-in-card-name.patch
|
||||
0028-pcm-add-helper-functions-to-query-timestamping-capab.patch
|
||||
0029-pcm-add-support-for-get-set_audio_htstamp_config.patch
|
||||
0030-pcm-add-support-for-new-STATUS_EXT-ioctl.patch
|
||||
0031-test-fix-audio_time-with-new-get-set-audio_tstamp_co.patch
|
||||
0032-test-audio_time-show-report-validity-and-accuracy.patch
|
||||
0033-pcm-restore-hw-params-on-set-latency-failed.patch
|
||||
0034-Replace-list.h-with-its-own-version.patch
|
||||
0035-topology-uapi-Add-UAPI-headers-for-topology-ABI.patch
|
||||
0036-topology-Add-topology-core-parser.patch
|
||||
0037-topology-Add-text-section-parser.patch
|
||||
0038-topology-Add-PCM-parser.patch
|
||||
0039-topology-Add-operations-parser.patch
|
||||
0040-topology-Add-private-data-parser.patch
|
||||
0041-topology-Add-DAPM-object-parser.patch
|
||||
0042-topology-Add-CTL-parser.patch
|
||||
0043-topology-Add-Channel-map-parser.patch
|
||||
0044-topology-Add-binary-file-builder.patch
|
||||
0045-topology-autotools-Add-build-support-for-topology-co.patch
|
||||
0046-topology-doxygen-Add-doxygen-support-for-topology-co.patch
|
||||
0047-conf-topology-Add-topology-file-for-broadwell-audio-.patch
|
||||
0048-topology-Fix-missing-inclusion-of-ctype.h.patch
|
||||
0049-topology-Fix-typos.patch
|
||||
0050-topology-fix-element-object-type-is-switch.patch
|
||||
0051-topology-Add-element-ID-so-we-can-look-up-references.patch
|
||||
0052-topology-Add-support-for-writing-manifest-private-da.patch
|
||||
0053-topology-update-ABI-to-improve-support-for-different.patch
|
||||
0054-topology-Add-ops-support-to-byte-control-objects.patch
|
||||
0055-topology-treat-all-DAPM-controls-types-the-same-when.patch
|
||||
0056-topology-print-error-prefix-on-error-message.patch
|
||||
0057-topology-rename-OBJECT_TYPE_-to-SND_TPLG_TYPE_.patch
|
||||
0058-core-add-convenience-macros-to-local.h.patch
|
||||
0059-topology-Add-C-templates-structure-for-building-topo.patch
|
||||
0060-topology-A-API-calls-to-directly-build-topology-data.patch
|
||||
0061-pcm-Fix-doxygen-for-two-enums.patch
|
||||
0062-pcm-ioplug-extplug-Fix-logic-errors-in-type-checks.patch
|
||||
0063-pcm-route-Remove-bogus-in-snd_config_get_id-checks.patch
|
||||
0064-topology-builder-Fix-possibly-uninitialized-variable.patch
|
||||
0065-topology-ctl-Fix-access-type-checks.patch
|
||||
0066-topology-data-Fix-wrong-size-check-in-tplg_parse_dat.patch
|
||||
0067-topology-parser-Add-missing-return-value-to-snd_tplg.patch
|
||||
0068-topology-pcm-Remove-unused-variables.patch
|
||||
0069-build-Do-not-try-to-detect-cross-compiler.patch
|
||||
0070-topology-Add-API-to-set-a-vendor-specific-version-nu.patch
|
||||
0071-pcm-ladspa-Fix-segfault-due-to-a-wrong-channel-refer.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Oct 2 12:11:24 CEST 2015 - tiwai@suse.de
|
||||
|
||||
|
146
alsa.spec
146
alsa.spec
@ -16,14 +16,14 @@
|
||||
#
|
||||
|
||||
|
||||
%define package_version 1.0.29
|
||||
%define package_version 1.1.0
|
||||
%if 0%{?suse_version} > 1200
|
||||
%define _udevdir %(pkg-config --variable=udevdir udev)
|
||||
%else
|
||||
%define _udevdir /lib/udev
|
||||
%endif
|
||||
Name: alsa
|
||||
Version: 1.0.29
|
||||
Version: 1.1.0
|
||||
Release: 0
|
||||
#
|
||||
Summary: Advanced Linux Sound Architecture
|
||||
@ -49,77 +49,7 @@ Source40: 50-alsa.conf
|
||||
Source41: install-snd-module
|
||||
# Patch: alsa-lib-git-fixes.diff
|
||||
# upstream fixes
|
||||
Patch1: 0001-ucm-document-some-standard-values.patch
|
||||
Patch2: 0002-conf-ucm-broadwell-rt286-add-ucm-config.patch
|
||||
Patch3: 0003-conf-ucm-Add-Makefile.am-for-broadwell-rt286-ucm-con.patch
|
||||
Patch4: 0004-ucm-reformat-snd_use_case_get-doc.patch
|
||||
Patch5: 0005-ucm-improve-jack-configuration-documentation.patch
|
||||
Patch6: 0006-USB-audio-Sound-Blaster-HD-iec958-is-on-device-1.patch
|
||||
Patch7: 0007-Sync-include-sound-asound.h-with-4.1-kernel.patch
|
||||
Patch8: 0008-conf-ucm-broadwell-rt286-change-to-use-the-correct-j.patch
|
||||
Patch9: 0009-namehint-Fix-invalid-list-access-in-snd_device_name_.patch
|
||||
Patch10: 0010-namehint-Fix-the-listing-without-device-number.patch
|
||||
Patch11: 0011-namehint-Fix-bad-free-with-invalid-iface-name.patch
|
||||
Patch12: 0012-Allow-hint-for-ctl-hwdep-timer-and-seq.patch
|
||||
Patch13: 0013-conf-Add-hint-descriptions-to-ctl-hwdep-seq-and-time.patch
|
||||
Patch14: 0014-conf-ucm-broadwell-rt286-change-to-set-capture-volum.patch
|
||||
Patch15: 0015-ucm-allow-multiple-devices-in-JackHWMute.patch
|
||||
Patch16: 0016-pcm-Remove-assert-from-snd_pcm_hw_params_slave.patch
|
||||
Patch17: 0017-test-pcm-Fix-generated-values-with-float-PCM-format.patch
|
||||
Patch18: 0018-test-pcm_min-Fix-error-messages.patch
|
||||
Patch19: 0019-pcm-Don-t-assert-in-_snd_pcm_hw_params_internal.patch
|
||||
Patch20: 0020-pcm-Fix-snd_pcm_status-for-dmix-co.patch
|
||||
Patch21: 0021-control-Allow-cset-ing-specific-values-in-the-multi-.patch
|
||||
Patch22: 0022-PCM-snd_pcm_xxxx_drain-maybe-blocked-after-suspend-a.patch
|
||||
Patch23: 0023-surround41-50.conf-Use-chmap-syntax-for-better-flexi.patch
|
||||
Patch24: 0024-ucm-docs-fix-doxygen-exclude-patch-for-UCM-local-hea.patch
|
||||
Patch25: 0025-ucm-docs-Fix-doxygen-formatting-for-UCM-main-page.patch
|
||||
Patch26: 0026-docs-Add-UCM-link-to-main-doxygen-page.patch
|
||||
Patch27: 0027-Replace-unsafe-characters-with-_-in-card-name.patch
|
||||
Patch28: 0028-pcm-add-helper-functions-to-query-timestamping-capab.patch
|
||||
Patch29: 0029-pcm-add-support-for-get-set_audio_htstamp_config.patch
|
||||
Patch30: 0030-pcm-add-support-for-new-STATUS_EXT-ioctl.patch
|
||||
Patch31: 0031-test-fix-audio_time-with-new-get-set-audio_tstamp_co.patch
|
||||
Patch32: 0032-test-audio_time-show-report-validity-and-accuracy.patch
|
||||
Patch33: 0033-pcm-restore-hw-params-on-set-latency-failed.patch
|
||||
Patch34: 0034-Replace-list.h-with-its-own-version.patch
|
||||
Patch35: 0035-topology-uapi-Add-UAPI-headers-for-topology-ABI.patch
|
||||
Patch36: 0036-topology-Add-topology-core-parser.patch
|
||||
Patch37: 0037-topology-Add-text-section-parser.patch
|
||||
Patch38: 0038-topology-Add-PCM-parser.patch
|
||||
Patch39: 0039-topology-Add-operations-parser.patch
|
||||
Patch40: 0040-topology-Add-private-data-parser.patch
|
||||
Patch41: 0041-topology-Add-DAPM-object-parser.patch
|
||||
Patch42: 0042-topology-Add-CTL-parser.patch
|
||||
Patch43: 0043-topology-Add-Channel-map-parser.patch
|
||||
Patch44: 0044-topology-Add-binary-file-builder.patch
|
||||
Patch45: 0045-topology-autotools-Add-build-support-for-topology-co.patch
|
||||
Patch46: 0046-topology-doxygen-Add-doxygen-support-for-topology-co.patch
|
||||
Patch47: 0047-conf-topology-Add-topology-file-for-broadwell-audio-.patch
|
||||
Patch48: 0048-topology-Fix-missing-inclusion-of-ctype.h.patch
|
||||
Patch49: 0049-topology-Fix-typos.patch
|
||||
Patch50: 0050-topology-fix-element-object-type-is-switch.patch
|
||||
Patch51: 0051-topology-Add-element-ID-so-we-can-look-up-references.patch
|
||||
Patch52: 0052-topology-Add-support-for-writing-manifest-private-da.patch
|
||||
Patch53: 0053-topology-update-ABI-to-improve-support-for-different.patch
|
||||
Patch54: 0054-topology-Add-ops-support-to-byte-control-objects.patch
|
||||
Patch55: 0055-topology-treat-all-DAPM-controls-types-the-same-when.patch
|
||||
Patch56: 0056-topology-print-error-prefix-on-error-message.patch
|
||||
Patch57: 0057-topology-rename-OBJECT_TYPE_-to-SND_TPLG_TYPE_.patch
|
||||
Patch58: 0058-core-add-convenience-macros-to-local.h.patch
|
||||
Patch59: 0059-topology-Add-C-templates-structure-for-building-topo.patch
|
||||
Patch60: 0060-topology-A-API-calls-to-directly-build-topology-data.patch
|
||||
Patch61: 0061-pcm-Fix-doxygen-for-two-enums.patch
|
||||
Patch62: 0062-pcm-ioplug-extplug-Fix-logic-errors-in-type-checks.patch
|
||||
Patch63: 0063-pcm-route-Remove-bogus-in-snd_config_get_id-checks.patch
|
||||
Patch64: 0064-topology-builder-Fix-possibly-uninitialized-variable.patch
|
||||
Patch65: 0065-topology-ctl-Fix-access-type-checks.patch
|
||||
Patch66: 0066-topology-data-Fix-wrong-size-check-in-tplg_parse_dat.patch
|
||||
Patch67: 0067-topology-parser-Add-missing-return-value-to-snd_tplg.patch
|
||||
Patch68: 0068-topology-pcm-Remove-unused-variables.patch
|
||||
Patch69: 0069-build-Do-not-try-to-detect-cross-compiler.patch
|
||||
Patch70: 0070-topology-Add-API-to-set-a-vendor-specific-version-nu.patch
|
||||
Patch71: 0071-pcm-ladspa-Fix-segfault-due-to-a-wrong-channel-refer.patch
|
||||
Patch1: 0001-topology-Add-missing-include-sys-stat.h.patch
|
||||
# rest suse patches
|
||||
Patch99: alsa-lib-doxygen-avoid-crash-for-11.3.diff
|
||||
# suppress timestamp in documents
|
||||
@ -191,76 +121,6 @@ Architecture.
|
||||
%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
|
||||
%patch20 -p1
|
||||
%patch21 -p1
|
||||
%patch22 -p1
|
||||
%patch23 -p1
|
||||
%patch24 -p1
|
||||
%patch25 -p1
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
%patch34 -p1
|
||||
%patch35 -p1
|
||||
%patch36 -p1
|
||||
%patch37 -p1
|
||||
%patch38 -p1
|
||||
%patch39 -p1
|
||||
%patch40 -p1
|
||||
%patch41 -p1
|
||||
%patch42 -p1
|
||||
%patch43 -p1
|
||||
%patch44 -p1
|
||||
%patch45 -p1
|
||||
%patch46 -p1
|
||||
%patch47 -p1
|
||||
%patch48 -p1
|
||||
%patch49 -p1
|
||||
%patch50 -p1
|
||||
%patch51 -p1
|
||||
%patch52 -p1
|
||||
%patch53 -p1
|
||||
%patch54 -p1
|
||||
%patch55 -p1
|
||||
%patch56 -p1
|
||||
%patch57 -p1
|
||||
%patch58 -p1
|
||||
%patch59 -p1
|
||||
%patch60 -p1
|
||||
%patch61 -p1
|
||||
%patch62 -p1
|
||||
%patch63 -p1
|
||||
%patch64 -p1
|
||||
%patch65 -p1
|
||||
%patch66 -p1
|
||||
%patch67 -p1
|
||||
%patch68 -p1
|
||||
%patch69 -p1
|
||||
%patch70 -p1
|
||||
%patch71 -p1
|
||||
%if 0%{?suse_version} == 1130
|
||||
%patch99 -p1
|
||||
%endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user