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:
Takashi Iwai 2015-11-09 13:55:30 +00:00 committed by Git OBS Bridge
parent d42c75a231
commit e99f551749
76 changed files with 120 additions and 11745 deletions

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dfde65d11e82b68f82e562ab6228c1fb7c78854345d3c57e2c68a9dd3dae1f15
size 929874

View File

@ -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
View File

@ -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