From b65520924e2b65f2ab9c0a8f744cdb760484e497 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2016 06:04:01 +0000 Subject: import alsa-lib-1.1.1-1.el7 --- diff --git a/.alsa-lib.metadata b/.alsa-lib.metadata index 056632a..de4b8b4 100644 --- a/.alsa-lib.metadata +++ b/.alsa-lib.metadata @@ -1 +1 @@ -3130b50835ce5e9ce061dd7916eac1121e1a83e3 SOURCES/alsa-lib-1.0.28.tar.bz2 +09f7e9b2d88287e04a4bb0d56e0cbc9018e524ec SOURCES/alsa-lib-1.1.1.tar.bz2 diff --git a/.gitignore b/.gitignore index fb23555..07630c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/alsa-lib-1.0.28.tar.bz2 +SOURCES/alsa-lib-1.1.1.tar.bz2 diff --git a/SOURCES/alsa-lib-1.0.14-glibc-open.patch b/SOURCES/alsa-lib-1.0.14-glibc-open.patch deleted file mode 100644 index bc625bd..0000000 --- a/SOURCES/alsa-lib-1.0.14-glibc-open.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- alsa-lib-1.0.14/aserver/aserver.c 2007-05-31 10:05:13.000000000 +0200 -+++ alsa-lib-1.0.14.lennart/aserver/aserver.c 2007-08-15 15:53:32.000000000 +0200 -@@ -35,6 +35,8 @@ - - #include "aserver.h" - -+#undef open -+ - char *command; - - #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) diff --git a/SOURCES/alsa-lib-1.0.24-config.patch b/SOURCES/alsa-lib-1.0.24-config.patch deleted file mode 100644 index f0e50e3..0000000 --- a/SOURCES/alsa-lib-1.0.24-config.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf -index 1889f01..60c12ac 100644 ---- a/src/conf/alsa.conf -+++ b/src/conf/alsa.conf -@@ -66,8 +66,7 @@ defaults.pcm.nonblock 1 - defaults.pcm.compat 0 - defaults.pcm.minperiodtime 5000 # in us - defaults.pcm.ipc_key 5678293 --defaults.pcm.ipc_gid audio --defaults.pcm.ipc_perm 0660 -+defaults.pcm.ipc_perm 0600 - defaults.pcm.dmix.max_periods 0 - defaults.pcm.dmix.rate 48000 - defaults.pcm.dmix.format "unchanged" -diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf -index e62cb29..a005488 100644 ---- a/src/conf/pcm/dmix.conf -+++ b/src/conf/pcm/dmix.conf -@@ -41,10 +41,6 @@ pcm.!dmix { - @func refer - name defaults.pcm.ipc_key - } -- ipc_gid { -- @func refer -- name defaults.pcm.ipc_gid -- } - ipc_perm { - @func refer - name defaults.pcm.ipc_perm -diff --git a/src/conf/pcm/dsnoop.conf b/src/conf/pcm/dsnoop.conf -index 49cfca9..842e1fb 100644 ---- a/src/conf/pcm/dsnoop.conf -+++ b/src/conf/pcm/dsnoop.conf -@@ -41,10 +41,6 @@ pcm.!dsnoop { - @func refer - name defaults.pcm.ipc_key - } -- ipc_gid { -- @func refer -- name defaults.pcm.ipc_gid -- } - ipc_perm { - @func refer - name defaults.pcm.ipc_perm diff --git a/SOURCES/alsa-lib-1.0.28-post.patch b/SOURCES/alsa-lib-1.0.28-post.patch deleted file mode 100644 index c9472df..0000000 --- a/SOURCES/alsa-lib-1.0.28-post.patch +++ /dev/null @@ -1,2820 +0,0 @@ -From 7a748af4db17cb0b26d19e5f9939d277128ec94b Mon Sep 17 00:00:00 2001 -From: Tanu Kaskinen -Date: Thu, 26 Jun 2014 13:30:25 +0300 -Subject: [PATCH 01/35] ucm: Document PlaybackPCMIsDummy and CapturePCMIsDummy - values - -At least PulseAudio needs special handling for dummy devices. To allow -that to happen automatically, the UCM configuration should contain the -information about which PCMs are dummy. - -Signed-off-by: Tanu Kaskinen -Acked-by: Liam Girdwood -Signed-off-by: Takashi Iwai ---- - include/use-case.h | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/include/use-case.h b/include/use-case.h -index 4e13249..f30168f 100644 ---- a/include/use-case.h -+++ b/include/use-case.h -@@ -258,7 +258,17 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, - * 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 --- -1.9.3 - - -From 27cc710b5784cb3ab68cff2a9d9daf9fa479149e Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Tue, 1 Jul 2014 00:40:48 +0600 -Subject: [PATCH 02/35] ICE1712: add surround71 pcm definition - -The M-Audio Delta 1010 card has 7.1 analog output, but no ready-made pcm -definition to use it. - -Signed-off-by: Alexander E. Patrakov -Reported-and-tested-by: Matt Zagrabelny -Signed-off-by: Takashi Iwai ---- - src/conf/cards/ICE1712.conf | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/src/conf/cards/ICE1712.conf b/src/conf/cards/ICE1712.conf -index 398fa7a..db62684 100644 ---- a/src/conf/cards/ICE1712.conf -+++ b/src/conf/cards/ICE1712.conf -@@ -78,6 +78,7 @@ ICE1712.pcm.surround40.0 { - - - -+ - - ICE1712.pcm.surround51.0 { - @args [ CARD ] -@@ -98,6 +99,27 @@ ICE1712.pcm.surround51.0 { - slave.channels 10 - } - -+ICE1712.pcm.surround71.0 { -+ @args [ CARD ] -+ @args.CARD { -+ type string -+ } -+ type route -+ ttable.0.0 1 -+ ttable.1.1 1 -+ ttable.2.2 1 -+ ttable.3.3 1 -+ ttable.4.4 1 -+ ttable.5.5 1 -+ ttable.6.6 1 -+ ttable.7.7 1 -+ slave.pcm { -+ type hw -+ card $CARD -+ } -+ slave.channels 10 -+} -+ - - - ICE1712.pcm.iec958.0 { --- -1.9.3 - - -From ea865bba4615d906144ae5d4f72a4aad2baffe1f Mon Sep 17 00:00:00 2001 -From: Anssi Hannula -Date: Tue, 8 Jul 2014 11:19:20 +0300 -Subject: [PATCH 03/35] USB-Audio: Add second S/PDIF device on Phiree U2 - -Phiree U2 has an unusual configuration. It only has S/PDIF output, but -there are still two devices presented: -- device 0: PCM audio, subject to volume control -- device 1: non-PCM data (passthrough), not subject to volume control - -It looks like the AES bits are set according to the selected device, -since outputting PCM data via device 1 will not work (silence). - -Currently only the device 0 is shown via the "iec958" alias, and the -second device is not accessible via hinted aliases. - -Simply provide access to both of these devices via the "iec958" alias. - -Reported-by: touc @ XBMC forum -Signed-off-by: Anssi Hannula -Signed-off-by: Takashi Iwai ---- - src/conf/cards/USB-Audio.conf | 40 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 40 insertions(+) - -diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf -index ce3ae01..77a48b9 100644 ---- a/src/conf/cards/USB-Audio.conf -+++ b/src/conf/cards/USB-Audio.conf -@@ -52,6 +52,11 @@ USB-Audio.pcm.iec958_device { - "USB Device 0x46d:0x992" 999 - } - -+# Second iec958 device number, if any. -+USB-Audio.pcm.iec958_2_device { -+ "PHIREE U2" 1 # 0 = PCM S/PDIF, 1 = non-PCM S/PDIF -+} -+ - - # If a device requires non-standard definitions for front, surround40, - # surround51, surround71 or iec958, they can be defined here. -@@ -422,4 +427,39 @@ USB-Audio.pcm.iec958.0 { - } - } - -+USB-Audio.pcm.iec958.1 { -+ @args [ CARD AES0 AES1 AES2 AES3 ] -+ @args.CARD { type string } -+ @args.AES0 { type integer } -+ @args.AES1 { type integer } -+ @args.AES2 { type integer } -+ @args.AES3 { type integer } -+ @func refer -+ name { -+ @func concat -+ strings [ -+ "cards.USB-Audio." -+ { @func card_name card $CARD } -+ ".pcm.iec958_2:CARD=" $CARD -+ ",AES0=" $AES0 ",AES1=" $AES1 ",AES2=" $AES2 ",AES3=" $AES3 -+ ] -+ } -+ default { -+ # FIXME: we cannot set the AES parameters -+ type hw -+ card $CARD -+ device { -+ @func refer -+ name { -+ @func concat -+ strings [ -+ "cards.USB-Audio.pcm.iec958_2_device." -+ { @func card_name card $CARD } -+ ] -+ } -+ default 999 -+ } -+ } -+} -+ - # vim: ft=alsaconf --- -1.9.3 - - -From 035f196bcdc1e9903ed52ad1859dc23d3aa74e72 Mon Sep 17 00:00:00 2001 -From: Shengjiu Wang -Date: Mon, 14 Jul 2014 16:55:48 +0800 -Subject: [PATCH 04/35] pcm: rate: fix hw_ptr exceed the boundary - -For long time test case, the hw_ptr will exceed the boundary, then cause -the avail size wrong. - -Signed-off-by: Shengjiu Wang -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_rate.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c -index 7f667d4..2563d82 100644 ---- a/src/pcm/pcm_rate.c -+++ b/src/pcm/pcm_rate.c -@@ -574,6 +574,8 @@ static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm) - rate->hw_ptr = - (slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size + - rate->ops.input_frames(rate->obj, slave_hw_ptr % rate->gen.slave->period_size); -+ -+ rate->hw_ptr %= pcm->boundary; - } - - static int snd_pcm_rate_hwsync(snd_pcm_t *pcm) --- -1.9.3 - - -From 85e4704151677b8fcc5ccfc396071828e9ec1b8e Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Tue, 8 Jul 2014 16:52:32 +0200 -Subject: [PATCH 05/35] pcm: Provide a CLOCK_MONOTONIC_RAW timestamp type - -For applications which need to synchronise with external timebases such -as broadcast TV applications the kernel monotonic time is not optimal as -it includes adjustments from NTP and so may still include discontinuities -due to that. A raw monotonic time which does not include any adjustments -is available in the kernel from getrawmonotonic() so provide userspace with -a new timestamp type SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW which provides -timestamps based on this as an option. - -Reported-by: Daniel Thompson -Signed-off-by: Mark Brown -Signed-off-by: Takashi Iwai ---- - include/sound/asound.h | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/include/sound/asound.h b/include/sound/asound.h -index 1774a5c..9061cdd 100644 ---- a/include/sound/asound.h -+++ b/include/sound/asound.h -@@ -457,7 +457,8 @@ struct snd_xfern { - enum { - SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */ - SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */ -- SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, -+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */ -+ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, - }; - - /* channel positions */ --- -1.9.3 - - -From 5250a8e212fd927735cfc27612b060c31dc3a230 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Thu, 10 Jul 2014 14:22:33 +0200 -Subject: [PATCH 06/35] Add timestamp type to sw_params (internal only) - -This patch is just the udpate of sound/asound.h taken from the kernel -commit. The API changes and PCM structure changes will follow after -this. - -Signed-off-by: Takashi Iwai ---- - include/sound/asound.h | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/include/sound/asound.h b/include/sound/asound.h -index 9061cdd..552f41b 100644 ---- a/include/sound/asound.h -+++ b/include/sound/asound.h -@@ -136,7 +136,7 @@ struct snd_hwdep_dsp_image { - * * - *****************************************************************************/ - --#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 11) -+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 12) - - typedef unsigned long snd_pcm_uframes_t; - typedef signed long snd_pcm_sframes_t; -@@ -386,7 +386,9 @@ struct snd_pcm_sw_params { - snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ - snd_pcm_uframes_t silence_size; /* silence block size */ - snd_pcm_uframes_t boundary; /* pointers wrap point */ -- unsigned char reserved[64]; /* reserved for future */ -+ unsigned int tstamp_type; /* timestamp type */ -+ int pads; /* alignment, reserved */ -+ unsigned char reserved[56]; /* reserved for future */ - }; - - struct snd_pcm_channel_info { --- -1.9.3 - - -From 0d393c29a272b6fc97e9fca3252fb1c58f86e75b Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Thu, 10 Jul 2014 14:26:37 +0200 -Subject: [PATCH 07/35] pcm: Add sw_params API functions to get/set timestamp - type - -For obtaining / changing the timestamp type, add the corresponding -sw_params accessor API functions together with the public definitions -of timestamp types. - -This patch only adds the functions and defines but doesn't bring the -functional changes yet. - -Signed-off-by: Takashi Iwai ---- - include/pcm.h | 9 +++++++++ - src/pcm/pcm.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - src/pcm/pcm_local.h | 1 + - src/pcm/pcm_params.c | 1 + - 4 files changed, 64 insertions(+) - -diff --git a/include/pcm.h b/include/pcm.h -index 95b8aed..11e9f0d 100644 ---- a/include/pcm.h -+++ b/include/pcm.h -@@ -317,6 +317,13 @@ typedef enum _snd_pcm_tstamp { - SND_PCM_TSTAMP_LAST = SND_PCM_TSTAMP_ENABLE - } 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_LAST = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW, -+} snd_pcm_tstamp_type_t; -+ - /** Unsigned frames quantity */ - typedef unsigned long snd_pcm_uframes_t; - /** Signed frames quantity */ -@@ -844,6 +851,8 @@ int snd_pcm_sw_params_get_boundary(const snd_pcm_sw_params_t *params, snd_pcm_uf - - int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_t val); - int snd_pcm_sw_params_get_tstamp_mode(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_t *val); -+int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t val); -+int snd_pcm_sw_params_get_tstamp_type(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t *val); - int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); - int snd_pcm_sw_params_get_avail_min(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val); - int snd_pcm_sw_params_set_period_event(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, int val); -diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c -index 7e46014..8984443 100644 ---- a/src/pcm/pcm.c -+++ b/src/pcm/pcm.c -@@ -1483,6 +1483,7 @@ int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsign - #define XRUN(v) [SND_PCM_XRUN_##v] = #v - #define SILENCE(v) [SND_PCM_SILENCE_##v] = #v - #define TSTAMP(v) [SND_PCM_TSTAMP_##v] = #v -+#define TSTAMP_TYPE(v) [SND_PCM_TSTAMP_TYPE_##v] = #v - #define ACCESS(v) [SND_PCM_ACCESS_##v] = #v - #define START(v) [SND_PCM_START_##v] = #v - #define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v -@@ -1680,6 +1681,12 @@ static const char *const snd_pcm_tstamp_mode_names[] = { - TSTAMP(NONE), - TSTAMP(ENABLE), - }; -+ -+static const char *const snd_pcm_tstamp_type_names[] = { -+ TSTAMP_TYPE(GETTIMEOFDAY), -+ TSTAMP_TYPE(MONOTONIC), -+ TSTAMP_TYPE(MONOTONIC_RAW), -+}; - #endif - - /** -@@ -1826,6 +1833,18 @@ const char *snd_pcm_tstamp_mode_name(snd_pcm_tstamp_t mode) - } - - /** -+ * \brief get name of PCM tstamp type setting -+ * \param mode PCM tstamp type -+ * \return ascii name of PCM tstamp type setting -+ */ -+const char *snd_pcm_tstamp_type_name(snd_pcm_tstamp_t type) -+{ -+ if (type > SND_PCM_TSTAMP_TYPE_LAST) -+ return NULL; -+ return snd_pcm_tstamp_type_names[type]; -+} -+ -+/** - * \brief get name of PCM state - * \param state PCM state - * \return ascii name of PCM state -@@ -1899,6 +1918,7 @@ int snd_pcm_dump_sw_setup(snd_pcm_t *pcm, snd_output_t *out) - return -EIO; - } - snd_output_printf(out, " tstamp_mode : %s\n", snd_pcm_tstamp_mode_name(pcm->tstamp_mode)); -+ snd_output_printf(out, " tstamp_type : %s\n", snd_pcm_tstamp_type_name(pcm->tstamp_mode)); - snd_output_printf(out, " period_step : %d\n", pcm->period_step); - snd_output_printf(out, " avail_min : %ld\n", pcm->avail_min); - snd_output_printf(out, " period_event : %i\n", pcm->period_event); -@@ -5591,6 +5611,7 @@ int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) - return -EIO; - } - params->tstamp_mode = pcm->tstamp_mode; -+ params->tstamp_type = pcm->tstamp_type; - params->period_step = pcm->period_step; - params->sleep_min = 0; - params->avail_min = pcm->avail_min; -@@ -5613,6 +5634,7 @@ int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) - int snd_pcm_sw_params_dump(snd_pcm_sw_params_t *params, snd_output_t *out) - { - snd_output_printf(out, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(params->tstamp_mode)); -+ snd_output_printf(out, "tstamp_type: %s\n", snd_pcm_tstamp_type_name(params->tstamp_type)); - snd_output_printf(out, "period_step: %u\n", params->period_step); - snd_output_printf(out, "avail_min: %lu\n", params->avail_min); - snd_output_printf(out, "start_threshold: %ld\n", params->start_threshold); -@@ -5811,6 +5833,37 @@ int snd_pcm_sw_params_get_tstamp_mode(const snd_pcm_sw_params_t *params, snd_pcm - } - - /** -+ * \brief Set timestamp type inside a software configuration container -+ * \param pcm PCM handle -+ * \param params Software configuration container -+ * \param val Timestamp type -+ * \return 0 otherwise a negative error code -+ */ -+int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t val) -+{ -+ assert(pcm && params); -+ if (CHECK_SANITY(val > SND_PCM_TSTAMP_TYPE_LAST)) { -+ SNDMSG("invalid tstamp_type value %d", val); -+ return -EINVAL; -+ } -+ params->tstamp_type = val; -+ return 0; -+} -+ -+/** -+ * \brief Get timestamp type from a software configuration container -+ * \param params Software configuration container -+ * \param val Returned timestamp type -+ * \return 0 otherwise a negative error code -+ */ -+int snd_pcm_sw_params_get_tstamp_type(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t *val) -+{ -+ assert(params && val); -+ *val = params->tstamp_type; -+ return 0; -+} -+ -+/** - * \brief (DEPRECATED) Set minimum number of ticks to sleep inside a software configuration container - * \param pcm PCM handle - * \param params Software configuration container -diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h -index 8a6c743..3ed7e1a 100644 ---- a/src/pcm/pcm_local.h -+++ b/src/pcm/pcm_local.h -@@ -202,6 +202,7 @@ struct _snd_pcm { - unsigned int period_time; /* period duration */ - snd_interval_t periods; - snd_pcm_tstamp_t tstamp_mode; /* timestamp mode */ -+ snd_pcm_tstamp_type_t tstamp_type; /* timestamp type */ - unsigned int period_step; - snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */ - int period_event; -diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c -index 0b66e8c..4adbefa 100644 ---- a/src/pcm/pcm_params.c -+++ b/src/pcm/pcm_params.c -@@ -2258,6 +2258,7 @@ static int snd_pcm_sw_params_default(snd_pcm_t *pcm, snd_pcm_sw_params_t *params - assert(pcm && params); - assert(pcm->setup); - params->tstamp_mode = SND_PCM_TSTAMP_NONE; -+ params->tstamp_type = pcm->tstamp_type; - params->period_step = 1; - params->sleep_min = 0; - params->avail_min = pcm->period_size; --- -1.9.3 - - -From 9b716075de4f2f7f15e428ee7efaa8960ef45b9c Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Thu, 10 Jul 2014 14:32:50 +0200 -Subject: [PATCH 08/35] pcm: Implement timestamp type setup in hw plugin - -This patch implements the support for sw_params timestamp type in PCM -hw layer. As gettimestamp() is still unchanged, the resultant -timstamps may be still with CLOCK_MONOTONIC even if you pass monotonic -raw type. More fixes will follow. - -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_hw.c | 37 ++++++++++++++++++++++++++++++++----- - 1 file changed, 32 insertions(+), 5 deletions(-) - -diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c -index ed83197..bafa8de 100644 ---- a/src/pcm/pcm_hw.c -+++ b/src/pcm/pcm_hw.c -@@ -304,7 +304,8 @@ static int snd_pcm_hw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) - - if (params->info != ~0U) { - params->info &= ~0xf0000000; -- params->info |= (pcm->monotonic ? SND_PCM_INFO_MONOTONIC : 0); -+ if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY) -+ params->info |= SND_PCM_INFO_MONOTONIC; - } - - return 0; -@@ -328,7 +329,8 @@ static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - return err; - } - params->info &= ~0xf0000000; -- params->info |= (pcm->monotonic ? SND_PCM_INFO_MONOTONIC : 0); -+ if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY) -+ params->info |= SND_PCM_INFO_MONOTONIC; - err = sync_ptr(hw, 0); - if (err < 0) - return err; -@@ -435,6 +437,7 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) - int old_period_event = sw_get_period_event(params); - sw_set_period_event(params, 0); - if ((snd_pcm_tstamp_t) params->tstamp_mode == pcm->tstamp_mode && -+ (snd_pcm_tstamp_type_t) params->tstamp_type == pcm->tstamp_type && - params->period_step == pcm->period_step && - params->start_threshold == pcm->start_threshold && - params->stop_threshold == pcm->stop_threshold && -@@ -444,11 +447,33 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) - hw->mmap_control->avail_min = params->avail_min; - return sync_ptr(hw, 0); - } -+ if (params->tstamp_type == SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW && -+ hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 12)) { -+ SYSMSG("Kernel doesn't support SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW"); -+ return -EINVAL; -+ } -+ if (params->tstamp_type == SND_PCM_TSTAMP_TYPE_MONOTONIC && -+ hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 5)) { -+ SYSMSG("Kernel doesn't support SND_PCM_TSTAMP_TYPE_MONOTONIC"); -+ return -EINVAL; -+ } - if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) { - err = -errno; - SYSMSG("SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err); - return err; - } -+ if ((snd_pcm_tstamp_type_t) params->tstamp_type != pcm->tstamp_type) { -+ if (hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 12)) { -+ int on = (snd_pcm_tstamp_type_t) params->tstamp_type == -+ SND_PCM_TSTAMP_TYPE_MONOTONIC; -+ if (ioctl(fd, SNDRV_PCM_IOCTL_TSTAMP, &on) < 0) { -+ err = -errno; -+ SNDMSG("TSTAMP failed\n"); -+ return err; -+ } -+ } -+ pcm->tstamp_type = params->tstamp_type; -+ } - sw_set_period_event(params, old_period_event); - hw->mmap_control->avail_min = params->avail_min; - if (hw->period_event != old_period_event) { -@@ -1381,7 +1406,8 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, - int fd, int mmap_emulation ATTRIBUTE_UNUSED, - int sync_ptr_ioctl) - { -- int ver, mode, monotonic = 0; -+ int ver, mode; -+ snd_pcm_tstamp_type_t tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY; - long fmode; - snd_pcm_t *pcm = NULL; - snd_pcm_hw_t *hw = NULL; -@@ -1429,7 +1455,7 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, - SNDMSG("TTSTAMP failed\n"); - return ret; - } -- monotonic = 1; -+ tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC; - } - } else - #endif -@@ -1471,7 +1497,8 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, - pcm->private_data = hw; - pcm->poll_fd = fd; - pcm->poll_events = info.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN; -- pcm->monotonic = monotonic; -+ pcm->tstamp_type = tstamp_type; -+ pcm->monotonic = tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY; - - ret = snd_pcm_hw_mmap_status(pcm); - if (ret < 0) { --- -1.9.3 - - -From 65ff6fdafb705b5e2e6d4b9a94a80e5de89f5de1 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Thu, 10 Jul 2014 14:37:49 +0200 -Subject: [PATCH 09/35] pcm: Implement timestamp type handling in all plugins - -Now all PCM plugins do support the proper timestamp type or pass it -over slaves. The internal monotonic flag is dropped and replaced with -tstamp_type in all places. - -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_adpcm.c | 2 +- - src/pcm/pcm_alaw.c | 2 +- - src/pcm/pcm_copy.c | 2 +- - src/pcm/pcm_direct.c | 4 ++-- - src/pcm/pcm_direct.h | 2 +- - src/pcm/pcm_dmix.c | 8 ++++---- - src/pcm/pcm_dshare.c | 8 ++++---- - src/pcm/pcm_dsnoop.c | 4 ++-- - src/pcm/pcm_file.c | 6 +++--- - src/pcm/pcm_generic.c | 2 +- - src/pcm/pcm_hooks.c | 2 +- - src/pcm/pcm_hw.c | 1 - - src/pcm/pcm_iec958.c | 2 +- - src/pcm/pcm_ioplug.c | 9 ++++++--- - src/pcm/pcm_ladspa.c | 2 +- - src/pcm/pcm_lfloat.c | 2 +- - src/pcm/pcm_linear.c | 2 +- - src/pcm/pcm_local.h | 45 +++++++++++++++++++++++++++++---------------- - src/pcm/pcm_meter.c | 2 +- - src/pcm/pcm_mmap_emul.c | 2 +- - src/pcm/pcm_mulaw.c | 2 +- - src/pcm/pcm_multi.c | 2 +- - src/pcm/pcm_null.c | 2 +- - src/pcm/pcm_plug.c | 2 +- - src/pcm/pcm_rate.c | 4 ++-- - src/pcm/pcm_route.c | 2 +- - src/pcm/pcm_share.c | 6 +++--- - src/pcm/pcm_softvol.c | 2 +- - 28 files changed, 73 insertions(+), 58 deletions(-) - -diff --git a/src/pcm/pcm_adpcm.c b/src/pcm/pcm_adpcm.c -index 6f0e7c4..1a83c5a 100644 ---- a/src/pcm/pcm_adpcm.c -+++ b/src/pcm/pcm_adpcm.c -@@ -579,7 +579,7 @@ int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor - pcm->private_data = adpcm; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &adpcm->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &adpcm->plug.appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_alaw.c b/src/pcm/pcm_alaw.c -index 1b1bab8..db759e3 100644 ---- a/src/pcm/pcm_alaw.c -+++ b/src/pcm/pcm_alaw.c -@@ -453,7 +453,7 @@ int snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform - pcm->private_data = alaw; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &alaw->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &alaw->plug.appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_copy.c b/src/pcm/pcm_copy.c -index 56a1f6b..66d3a47 100644 ---- a/src/pcm/pcm_copy.c -+++ b/src/pcm/pcm_copy.c -@@ -209,7 +209,7 @@ int snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int - pcm->private_data = copy; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, ©->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, ©->plug.appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c -index 5416cf7..8e37bcb 100644 ---- a/src/pcm/pcm_direct.c -+++ b/src/pcm/pcm_direct.c -@@ -840,6 +840,7 @@ static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) - COPY_SLAVE(period_time); - COPY_SLAVE(periods); - COPY_SLAVE(tstamp_mode); -+ COPY_SLAVE(tstamp_type); - COPY_SLAVE(period_step); - COPY_SLAVE(avail_min); - COPY_SLAVE(start_threshold); -@@ -857,7 +858,6 @@ static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) - COPY_SLAVE(buffer_time); - COPY_SLAVE(sample_bits); - COPY_SLAVE(frame_bits); -- COPY_SLAVE(monotonic); - } - - #undef COPY_SLAVE -@@ -1204,6 +1204,7 @@ static void copy_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) - COPY_SLAVE(period_time); - COPY_SLAVE(periods); - COPY_SLAVE(tstamp_mode); -+ COPY_SLAVE(tstamp_type); - COPY_SLAVE(period_step); - COPY_SLAVE(avail_min); - COPY_SLAVE(start_threshold); -@@ -1221,7 +1222,6 @@ static void copy_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) - COPY_SLAVE(buffer_time); - COPY_SLAVE(sample_bits); - COPY_SLAVE(frame_bits); -- COPY_SLAVE(monotonic); - - spcm->info &= ~SND_PCM_INFO_PAUSE; - spcm->boundary = recalc_boundary_size(dmix->shmptr->s.boundary, spcm->buffer_size); -diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h -index 5ae39c0..9b1ddbc 100644 ---- a/src/pcm/pcm_direct.h -+++ b/src/pcm/pcm_direct.h -@@ -85,8 +85,8 @@ typedef struct { - unsigned int period_size; - unsigned int period_time; - snd_interval_t periods; -- unsigned int monotonic; - snd_pcm_tstamp_t tstamp_mode; -+ snd_pcm_tstamp_type_t tstamp_type; - unsigned int period_step; - unsigned int sleep_min; /* not used */ - unsigned int avail_min; -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index 4aa6d4e..7c53509 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -428,7 +428,7 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm) - dmix->avail_max = avail; - if (avail >= pcm->stop_threshold) { - snd_timer_stop(dmix->timer); -- gettimestamp(&dmix->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&dmix->trigger_tstamp, pcm->tstamp_type); - if (dmix->state == SND_PCM_STATE_RUNNING) { - dmix->state = SND_PCM_STATE_XRUN; - return -EPIPE; -@@ -477,7 +477,7 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status) - memset(status, 0, sizeof(*status)); - status->state = snd_pcm_dmix_state(pcm); - status->trigger_tstamp = dmix->trigger_tstamp; -- gettimestamp(&status->tstamp, pcm->monotonic); -+ 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; -@@ -596,7 +596,7 @@ static int snd_pcm_dmix_start(snd_pcm_t *pcm) - return err; - snd_pcm_dmix_sync_area(pcm); - } -- gettimestamp(&dmix->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&dmix->trigger_tstamp, pcm->tstamp_type); - return 0; - } - -@@ -1104,7 +1104,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, - - pcm->poll_fd = dmix->poll_fd; - pcm->poll_events = POLLIN; /* it's different than other plugins */ -- pcm->monotonic = spcm->monotonic; -+ pcm->tstamp_type = spcm->tstamp_type; - pcm->mmap_rw = 1; - snd_pcm_set_hw_ptr(pcm, &dmix->hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &dmix->appl_ptr, -1, 0); -diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c -index f2d1103..b985172 100644 ---- a/src/pcm/pcm_dshare.c -+++ b/src/pcm/pcm_dshare.c -@@ -195,7 +195,7 @@ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm) - dshare->avail_max = avail; - if (avail >= pcm->stop_threshold) { - snd_timer_stop(dshare->timer); -- gettimestamp(&dshare->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&dshare->trigger_tstamp, pcm->tstamp_type); - if (dshare->state == SND_PCM_STATE_RUNNING) { - dshare->state = SND_PCM_STATE_XRUN; - return -EPIPE; -@@ -226,7 +226,7 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status) - memset(status, 0, sizeof(*status)); - status->state = snd_pcm_state(dshare->spcm); - status->trigger_tstamp = dshare->trigger_tstamp; -- gettimestamp(&status->tstamp, pcm->monotonic); -+ 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; -@@ -346,7 +346,7 @@ static int snd_pcm_dshare_start(snd_pcm_t *pcm) - return err; - snd_pcm_dshare_sync_area(pcm); - } -- gettimestamp(&dshare->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&dshare->trigger_tstamp, pcm->tstamp_type); - return 0; - } - -@@ -792,7 +792,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, - - pcm->poll_fd = dshare->poll_fd; - pcm->poll_events = POLLIN; /* it's different than other plugins */ -- pcm->monotonic = spcm->monotonic; -+ pcm->tstamp_type = spcm->tstamp_type; - pcm->mmap_rw = 1; - snd_pcm_set_hw_ptr(pcm, &dshare->hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &dshare->appl_ptr, -1, 0); -diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c -index 7637914..0f9c9df 100644 ---- a/src/pcm/pcm_dsnoop.c -+++ b/src/pcm/pcm_dsnoop.c -@@ -159,7 +159,7 @@ static int snd_pcm_dsnoop_sync_ptr(snd_pcm_t *pcm) - if (pcm->stop_threshold >= pcm->boundary) /* don't care */ - return 0; - if ((avail = snd_pcm_mmap_capture_hw_avail(pcm)) >= pcm->stop_threshold) { -- gettimestamp(&dsnoop->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&dsnoop->trigger_tstamp, pcm->tstamp_type); - dsnoop->state = SND_PCM_STATE_XRUN; - dsnoop->avail_max = avail; - return -EPIPE; -@@ -690,7 +690,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, - - pcm->poll_fd = dsnoop->poll_fd; - pcm->poll_events = POLLIN; /* it's different than other plugins */ -- pcm->monotonic = spcm->monotonic; -+ pcm->tstamp_type = spcm->tstamp_type; - pcm->mmap_rw = 1; - snd_pcm_set_hw_ptr(pcm, &dsnoop->hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &dsnoop->appl_ptr, -1, 0); -diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c -index b139f7f..a0b8bf4 100644 ---- a/src/pcm/pcm_file.c -+++ b/src/pcm/pcm_file.c -@@ -781,10 +781,10 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; - pcm->mmap_shadow = 1; -+ pcm->tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY; - #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) -- pcm->monotonic = clock_gettime(CLOCK_MONOTONIC, ×pec) == 0; --#else -- pcm->monotonic = 0; -+ if (clock_gettime(CLOCK_MONOTONIC, ×pec) == 0) -+ pcm->tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC; - #endif - pcm->stream = stream; - snd_pcm_link_hw_ptr(pcm, slave); -diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c -index f068ee2..9b60591 100644 ---- a/src/pcm/pcm_generic.c -+++ b/src/pcm/pcm_generic.c -@@ -294,7 +294,7 @@ int snd_pcm_generic_real_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail, - if (ok && (snd_pcm_uframes_t)avail1 == *avail) - break; - *avail = avail1; -- gettimestamp(tstamp, pcm->monotonic); -+ gettimestamp(tstamp, pcm->tstamp_type); - ok = 1; - } - return 0; -diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c -index f837282..0b93c64 100644 ---- a/src/pcm/pcm_hooks.c -+++ b/src/pcm/pcm_hooks.c -@@ -240,7 +240,7 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; - pcm->mmap_shadow = 1; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_link_hw_ptr(pcm, slave); - snd_pcm_link_appl_ptr(pcm, slave); - *pcmp = pcm; -diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c -index bafa8de..74cff67 100644 ---- a/src/pcm/pcm_hw.c -+++ b/src/pcm/pcm_hw.c -@@ -1498,7 +1498,6 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, - pcm->poll_fd = fd; - pcm->poll_events = info.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN; - pcm->tstamp_type = tstamp_type; -- pcm->monotonic = tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY; - - ret = snd_pcm_hw_mmap_status(pcm); - if (ret < 0) { -diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c -index 0c61fc1..38c4ce7 100644 ---- a/src/pcm/pcm_iec958.c -+++ b/src/pcm/pcm_iec958.c -@@ -534,7 +534,7 @@ int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo - pcm->private_data = iec; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &iec->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &iec->plug.appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c -index c1c3a98..85a8891 100644 ---- a/src/pcm/pcm_ioplug.c -+++ b/src/pcm/pcm_ioplug.c -@@ -448,7 +448,7 @@ static int snd_pcm_ioplug_start(snd_pcm_t *pcm) - if (err < 0) - return err; - -- gettimestamp(&io->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&io->trigger_tstamp, pcm->tstamp_type); - io->data->state = SND_PCM_STATE_RUNNING; - - return 0; -@@ -463,7 +463,7 @@ static int snd_pcm_ioplug_drop(snd_pcm_t *pcm) - - io->data->callback->stop(io->data); - -- gettimestamp(&io->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&io->trigger_tstamp, pcm->tstamp_type); - io->data->state = SND_PCM_STATE_SETUP; - - return 0; -@@ -1069,7 +1069,10 @@ int snd_pcm_ioplug_reinit_status(snd_pcm_ioplug_t *ioplug) - { - ioplug->pcm->poll_fd = ioplug->poll_fd; - ioplug->pcm->poll_events = ioplug->poll_events; -- ioplug->pcm->monotonic = (ioplug->flags & SND_PCM_IOPLUG_FLAG_MONOTONIC) != 0; -+ if (ioplug->flags & SND_PCM_IOPLUG_FLAG_MONOTONIC) -+ ioplug->pcm->tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC; -+ else -+ ioplug->pcm->tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY; - ioplug->pcm->mmap_rw = ioplug->mmap_rw; - return 0; - } -diff --git a/src/pcm/pcm_ladspa.c b/src/pcm/pcm_ladspa.c -index 7d1e3df..631ee0f 100644 ---- a/src/pcm/pcm_ladspa.c -+++ b/src/pcm/pcm_ladspa.c -@@ -1641,7 +1641,7 @@ int snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name, - pcm->private_data = ladspa; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &ladspa->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &ladspa->plug.appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_lfloat.c b/src/pcm/pcm_lfloat.c -index bbf72c2..324282f 100644 ---- a/src/pcm/pcm_lfloat.c -+++ b/src/pcm/pcm_lfloat.c -@@ -412,7 +412,7 @@ int snd_pcm_lfloat_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo - pcm->private_data = lfloat; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &lfloat->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &lfloat->plug.appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c -index 7aa8941..3d5bbb8 100644 ---- a/src/pcm/pcm_linear.c -+++ b/src/pcm/pcm_linear.c -@@ -484,7 +484,7 @@ int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo - pcm->private_data = linear; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &linear->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &linear->plug.appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h -index 3ed7e1a..2206afe 100644 ---- a/src/pcm/pcm_local.h -+++ b/src/pcm/pcm_local.h -@@ -191,7 +191,6 @@ struct _snd_pcm { - int poll_fd; - unsigned short poll_events; - int setup: 1, -- monotonic: 1, - compat: 1; - snd_pcm_access_t access; /* access mode */ - snd_pcm_format_t format; /* SND_PCM_FORMAT_* */ -@@ -960,26 +959,40 @@ typedef union snd_tmp_double { - } snd_tmp_double_t; - - /* get the current timestamp */ --static inline void gettimestamp(snd_htimestamp_t *tstamp, int monotonic) -+#ifdef HAVE_CLOCK_GETTIME -+static inline void gettimestamp(snd_htimestamp_t *tstamp, -+ snd_pcm_tstamp_type_t tstamp_type) - { --#if defined(HAVE_CLOCK_GETTIME) --#if defined(CLOCK_MONOTONIC) -- if (monotonic) { -- clock_gettime(CLOCK_MONOTONIC, tstamp); -- } else { --#endif -- clock_gettime(CLOCK_REALTIME, tstamp); --#else -- struct timeval tv; -+ clockid_t id; - -- gettimeofday(&tv, 0); -- tstamp->tv_sec = tv.tv_sec; -- tstamp->tv_nsec = tv.tv_usec * 1000L; -+ switch (tstamp_type) { -+#ifdef CLOCK_MONOTONIC_RAW -+ case SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW: -+ id = CLOCK_MONOTONIC_RAW; -+ break; - #endif --#if defined(HAVE_CLOCK_GETTIME) -- } -+#ifdef CLOCK_MONOTONIC -+ case SND_PCM_TSTAMP_TYPE_MONOTONIC: -+ id = CLOCK_MONOTONIC; -+ break; - #endif -+ default: -+ id = CLOCK_REALTIME; -+ break; -+ } -+ clock_gettime(id, tstamp); -+} -+#else /* HAVE_CLOCK_GETTIME */ -+static inline void gettimestamp(snd_htimestamp_t *tstamp, -+ snd_pcm_tstamp_type_t tstamp_type) -+{ -+ struct timeval tv; -+ -+ gettimeofday(&tv, 0); -+ tstamp->tv_sec = tv.tv_sec; -+ tstamp->tv_nsec = tv.tv_usec * 1000L; - } -+#endif /* HAVE_CLOCK_GETTIME */ - - snd_pcm_chmap_query_t ** - _snd_pcm_make_single_query_chmaps(const snd_pcm_chmap_t *src); -diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c -index 676fbef..034f582 100644 ---- a/src/pcm/pcm_meter.c -+++ b/src/pcm/pcm_meter.c -@@ -591,7 +591,7 @@ int snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, unsigned int frequenc - pcm->private_data = meter; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_link_hw_ptr(pcm, slave); - snd_pcm_link_appl_ptr(pcm, slave); - *pcmp = pcm; -diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c -index 63789bc..b2b15ef 100644 ---- a/src/pcm/pcm_mmap_emul.c -+++ b/src/pcm/pcm_mmap_emul.c -@@ -428,7 +428,7 @@ int __snd_pcm_mmap_emul_open(snd_pcm_t **pcmp, const char *name, - pcm->private_data = map; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &map->hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &map->appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c -index 7adce38..011b2a5 100644 ---- a/src/pcm/pcm_mulaw.c -+++ b/src/pcm/pcm_mulaw.c -@@ -467,7 +467,7 @@ int snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor - pcm->private_data = mulaw; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &mulaw->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &mulaw->plug.appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c -index a84e0ce..4b8299e 100644 ---- a/src/pcm/pcm_multi.c -+++ b/src/pcm/pcm_multi.c -@@ -1077,7 +1077,7 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, - pcm->private_data = multi; - pcm->poll_fd = multi->slaves[master_slave].pcm->poll_fd; - pcm->poll_events = multi->slaves[master_slave].pcm->poll_events; -- pcm->monotonic = multi->slaves[master_slave].pcm->monotonic; -+ pcm->tstamp_type = multi->slaves[master_slave].pcm->tstamp_type; - snd_pcm_link_hw_ptr(pcm, multi->slaves[master_slave].pcm); - snd_pcm_link_appl_ptr(pcm, multi->slaves[master_slave].pcm); - *pcmp = pcm; -diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c -index 655261f..f11a102 100644 ---- a/src/pcm/pcm_null.c -+++ b/src/pcm/pcm_null.c -@@ -100,7 +100,7 @@ static int snd_pcm_null_status(snd_pcm_t *pcm, snd_pcm_status_t * status) - memset(status, 0, sizeof(*status)); - status->state = null->state; - status->trigger_tstamp = null->trigger_tstamp; -- gettimestamp(&status->tstamp, pcm->monotonic); -+ gettimestamp(&status->tstamp, pcm->tstamp_type); - status->avail = snd_pcm_null_avail_update(pcm); - status->avail_max = pcm->buffer_size; - return 0; -diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c -index 7a6c2b9..5639b9e 100644 ---- a/src/pcm/pcm_plug.c -+++ b/src/pcm/pcm_plug.c -@@ -1127,7 +1127,7 @@ int snd_pcm_plug_open(snd_pcm_t **pcmp, - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; - pcm->mmap_shadow = 1; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_link_hw_ptr(pcm, slave); - snd_pcm_link_appl_ptr(pcm, slave); - *pcmp = pcm; -diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c -index 2563d82..5e811bb 100644 ---- a/src/pcm/pcm_rate.c -+++ b/src/pcm/pcm_rate.c -@@ -1069,7 +1069,7 @@ static int snd_pcm_rate_start(snd_pcm_t *pcm) - if (snd_pcm_state(rate->gen.slave) != SND_PCM_STATE_PREPARED) - return -EBADFD; - -- gettimestamp(&rate->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&rate->trigger_tstamp, pcm->tstamp_type); - - avail = snd_pcm_mmap_playback_hw_avail(rate->gen.slave); - if (avail == 0) { -@@ -1372,7 +1372,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; - pcm->mmap_rw = 1; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &rate->hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &rate->appl_ptr, -1, 0); - *pcmp = pcm; -diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c -index 751e36f..2f0be38 100644 ---- a/src/pcm/pcm_route.c -+++ b/src/pcm/pcm_route.c -@@ -1122,7 +1122,7 @@ int snd_pcm_route_open(snd_pcm_t **pcmp, const char *name, - pcm->private_data = route; - pcm->poll_fd = slave->poll_fd; - pcm->poll_events = slave->poll_events; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &route->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &route->plug.appl_ptr, -1, 0); - err = route_load_ttable(&route->params, pcm->stream, tt_ssize, ttable, tt_cused, tt_sused); -diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c -index 118ab26..9770544 100644 ---- a/src/pcm/pcm_share.c -+++ b/src/pcm/pcm_share.c -@@ -971,7 +971,7 @@ static int snd_pcm_share_start(snd_pcm_t *pcm) - } - slave->running_count++; - _snd_pcm_share_update(pcm); -- gettimestamp(&share->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&share->trigger_tstamp, pcm->tstamp_type); - _end: - Pthread_mutex_unlock(&slave->mutex); - return err; -@@ -1126,7 +1126,7 @@ static void _snd_pcm_share_stop(snd_pcm_t *pcm, snd_pcm_state_t state) - return; - } - #endif -- gettimestamp(&share->trigger_tstamp, pcm->monotonic); -+ gettimestamp(&share->trigger_tstamp, pcm->tstamp_type); - if (pcm->stream == SND_PCM_STREAM_CAPTURE) { - snd_pcm_areas_copy(pcm->stopped_areas, 0, - pcm->running_areas, 0, -@@ -1526,7 +1526,7 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname, - pcm->private_data = share; - pcm->poll_fd = share->client_socket; - pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN; -- pcm->monotonic = slave->pcm->monotonic; -+ pcm->tstamp_type = slave->pcm->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &share->hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &share->appl_ptr, -1, 0); - -diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c -index 5da9204..c6cfd88 100644 ---- a/src/pcm/pcm_softvol.c -+++ b/src/pcm/pcm_softvol.c -@@ -903,7 +903,7 @@ int snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name, - * an extra buffer. - */ - pcm->mmap_shadow = 1; -- pcm->monotonic = slave->monotonic; -+ pcm->tstamp_type = slave->tstamp_type; - snd_pcm_set_hw_ptr(pcm, &svol->plug.hw_ptr, -1, 0); - snd_pcm_set_appl_ptr(pcm, &svol->plug.appl_ptr, -1, 0); - *pcmp = pcm; --- -1.9.3 - - -From 52444bd43afbadb8637f5fac3fe5fd90575ee216 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Mon, 14 Jul 2014 18:12:49 +0200 -Subject: [PATCH 10/35] test/audio_time: Set timestamp type explicitly - -Signed-off-by: Takashi Iwai ---- - test/audio_time.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/test/audio_time.c b/test/audio_time.c -index 03817c7..7435db6 100644 ---- a/test/audio_time.c -+++ b/test/audio_time.c -@@ -57,6 +57,7 @@ void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp, - #define TRACK_PLAYBACK /* dump playback timing info */ - #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 - - - int main(void) -@@ -128,6 +129,12 @@ int main(void) - 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) { -@@ -177,6 +184,12 @@ int main(void) - 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) { --- -1.9.3 - - -From de63b942acf520a25ff469cf338a99eb3da65570 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Mon, 21 Jul 2014 16:30:54 +0200 -Subject: [PATCH 11/35] pcm: route: Use get/put labels for all 3 byte formats - -So far, use_getput flag is set only when the src or dest format is -24bit physical width. But, also 18 and 20 bit physical width formats -should set the flag, too. This patch makes the check broader to cover -all 3 bytes formats. - -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_route.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c -index 2f0be38..72c198c 100644 ---- a/src/pcm/pcm_route.c -+++ b/src/pcm/pcm_route.c -@@ -644,8 +644,10 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - } - if (err < 0) - return err; -- route->params.use_getput = snd_pcm_format_physical_width(src_format) == 24 || -- snd_pcm_format_physical_width(dst_format) == 24; -+ /* 3 bytes formats? */ -+ route->params.use_getput = -+ (snd_pcm_format_physical_width(src_format) + 7) / 3 == 3 || -+ (snd_pcm_format_physical_width(dst_format) + 7) / 3 == 3; - route->params.get_idx = snd_pcm_linear_get_index(src_format, SND_PCM_FORMAT_S16); - route->params.put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, dst_format); - route->params.conv_idx = snd_pcm_linear_convert_index(src_format, dst_format); --- -1.9.3 - - -From 55c53625212702debf55c719ec62f6c81c780927 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Wed, 16 Jul 2014 17:48:34 +0200 -Subject: [PATCH 12/35] pcm: Fill sw_params proto field - -Fill the new proto field introduced to sw_params with the current PCM -protocol version. This makes tstamp_type evaluated properly in the -kernel. - -Signed-off-by: Takashi Iwai ---- - include/sound/asound.h | 4 ++-- - src/pcm/pcm.c | 1 + - src/pcm/pcm_params.c | 1 + - 3 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/include/sound/asound.h b/include/sound/asound.h -index 552f41b..c819df4 100644 ---- a/include/sound/asound.h -+++ b/include/sound/asound.h -@@ -386,8 +386,8 @@ struct snd_pcm_sw_params { - snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ - snd_pcm_uframes_t silence_size; /* silence block size */ - snd_pcm_uframes_t boundary; /* pointers wrap point */ -- unsigned int tstamp_type; /* timestamp type */ -- int pads; /* alignment, reserved */ -+ unsigned int proto; /* protocol version */ -+ unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */ - unsigned char reserved[56]; /* reserved for future */ - }; - -diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c -index 8984443..1399a5b 100644 ---- a/src/pcm/pcm.c -+++ b/src/pcm/pcm.c -@@ -5610,6 +5610,7 @@ int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) - SNDMSG("PCM not set up"); - return -EIO; - } -+ params->proto = SNDRV_PCM_VERSION; - params->tstamp_mode = pcm->tstamp_mode; - params->tstamp_type = pcm->tstamp_type; - params->period_step = pcm->period_step; -diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c -index 4adbefa..6e57904 100644 ---- a/src/pcm/pcm_params.c -+++ b/src/pcm/pcm_params.c -@@ -2257,6 +2257,7 @@ static int snd_pcm_sw_params_default(snd_pcm_t *pcm, snd_pcm_sw_params_t *params - { - assert(pcm && params); - assert(pcm->setup); -+ params->proto = SNDRV_PCM_VERSION; - params->tstamp_mode = SND_PCM_TSTAMP_NONE; - params->tstamp_type = pcm->tstamp_type; - params->period_step = 1; --- -1.9.3 - - -From fd84adc63e307572d05274be44c782a787087cda Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Tue, 22 Jul 2014 11:55:40 +0200 -Subject: [PATCH 13/35] pcm: route: Use get32 for multi-source route - calculation - -The PCM route plugin can assign the destination value from average of -multiple sources with attenuation. This requires the read of each -channel value, sums and writes the resultant value in the requested -format. - -Currently, get_labels is used for reading source values while -put32_labels is used for writing the dest value. This is, however, -a buggy implementation; get_labels gives the value as is only with -endianness and signedness conversions, but put32_labels assumes that -the value is normalized to 32bit int and it shifts down to the dest -format. In addition, the current code lacks get_labels entries for -the 24bit formats, as Shengjiu Wang spotted out. - -For fixing these bugs, this patch replaces the read with -get32_labels and use always 64bit int for sum. This simplifies the -code a lot and drops many lines. - -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_route.c | 128 +++++++++------------------------------------------ - src/pcm/plugin_ops.h | 81 -------------------------------- - 2 files changed, 23 insertions(+), 186 deletions(-) - -diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c -index 72c198c..5dac7eb 100644 ---- a/src/pcm/pcm_route.c -+++ b/src/pcm/pcm_route.c -@@ -60,7 +60,7 @@ typedef struct { - typedef struct snd_pcm_route_ttable_dst snd_pcm_route_ttable_dst_t; - - typedef struct { -- enum {UINT32=0, UINT64=1, FLOAT=2} sum_idx; -+ enum {UINT64, FLOAT} sum_idx; - unsigned int get_idx; - unsigned int put_idx; - unsigned int conv_idx; -@@ -233,55 +233,34 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, - const snd_pcm_route_ttable_dst_t* ttable, - const snd_pcm_route_params_t *params) - { --#define GETS_LABELS -+#define GET32_LABELS - #define PUT32_LABELS - #include "plugin_ops.h" --#undef GETS_LABELS -+#undef GET32_LABELS - #undef PUT32_LABELS -- static void *const zero_labels[3] = { -- &&zero_int32, &&zero_int64, -+ static void *const zero_labels[2] = { -+ &&zero_int64, - #if SND_PCM_PLUGIN_ROUTE_FLOAT - &&zero_float - #endif - }; - /* sum_type att */ -- static void *const add_labels[3 * 2] = { -- &&add_int32_noatt, &&add_int32_att, -+ static void *const add_labels[2 * 2] = { - &&add_int64_noatt, &&add_int64_att, - #if SND_PCM_PLUGIN_ROUTE_FLOAT - &&add_float_noatt, &&add_float_att - #endif - }; -- /* sum_type att shift */ -- static void *const norm_labels[3 * 2 * 4] = { -- 0, -- &&norm_int32_8_noatt, -- &&norm_int32_16_noatt, -- &&norm_int32_24_noatt, -- 0, -- &&norm_int32_8_att, -- &&norm_int32_16_att, -- &&norm_int32_24_att, -- &&norm_int64_0_noatt, -- &&norm_int64_8_noatt, -- &&norm_int64_16_noatt, -- &&norm_int64_24_noatt, -- &&norm_int64_0_att, -- &&norm_int64_8_att, -- &&norm_int64_16_att, -- &&norm_int64_24_att, -+ /* sum_type att */ -+ static void *const norm_labels[2 * 2] = { -+ &&norm_int64_noatt, -+ &&norm_int64_att, - #if SND_PCM_PLUGIN_ROUTE_FLOAT -- &&norm_float_0, -- &&norm_float_8, -- &&norm_float_16, -- &&norm_float_24, -- &&norm_float_0, -- &&norm_float_8, -- &&norm_float_16, -- &&norm_float_24, -+ &&norm_float, -+ &&norm_float, - #endif - }; -- void *zero, *get, *add, *norm, *put32; -+ void *zero, *get32, *add, *norm, *put32; - int nsrcs = ttable->nsrcs; - char *dst; - int dst_step; -@@ -323,9 +302,9 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, - } - - zero = zero_labels[params->sum_idx]; -- get = gets_labels[params->get_idx]; -+ get32 = get32_labels[params->get_idx]; - add = add_labels[params->sum_idx * 2 + ttable->att]; -- norm = norm_labels[params->sum_idx * 8 + ttable->att * 4 + 4 - params->src_size]; -+ norm = norm_labels[params->sum_idx * 2 + ttable->att]; - put32 = put32_labels[params->put_idx]; - dst = snd_pcm_channel_area_addr(dst_area, dst_offset); - dst_step = snd_pcm_channel_area_step(dst_area); -@@ -336,9 +315,6 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, - - /* Zero sum */ - goto *zero; -- zero_int32: -- sum.as_sint32 = 0; -- goto zero_end; - zero_int64: - sum.as_sint64 = 0; - goto zero_end; -@@ -352,21 +328,14 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, - const char *src = srcs[srcidx]; - - /* Get sample */ -- goto *get; --#define GETS_END after_get -+ goto *get32; -+#define GET32_END after_get - #include "plugin_ops.h" --#undef GETS_END -+#undef GET32_END - after_get: - - /* Sum */ - goto *add; -- add_int32_att: -- sum.as_sint32 += sample * ttp->as_int; -- goto after_sum; -- add_int32_noatt: -- if (ttp->as_int) -- sum.as_sint32 += sample; -- goto after_sum; - add_int64_att: - sum.as_sint64 += (int64_t) sample * ttp->as_int; - goto after_sum; -@@ -390,48 +359,10 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, - - /* Normalization */ - goto *norm; -- norm_int32_8_att: -- sum.as_sint64 = sum.as_sint32; -- norm_int64_8_att: -- sum.as_sint64 <<= 8; -- norm_int64_0_att: -+ norm_int64_att: - div(sum.as_sint64); -- goto norm_int; -- -- norm_int32_16_att: -- sum.as_sint64 = sum.as_sint32; -- norm_int64_16_att: -- sum.as_sint64 <<= 16; -- div(sum.as_sint64); -- goto norm_int; -- -- norm_int32_24_att: -- sum.as_sint64 = sum.as_sint32; -- norm_int64_24_att: -- sum.as_sint64 <<= 24; -- div(sum.as_sint64); -- goto norm_int; -- -- norm_int32_8_noatt: -- sum.as_sint64 = sum.as_sint32; -- norm_int64_8_noatt: -- sum.as_sint64 <<= 8; -- goto norm_int; -- -- norm_int32_16_noatt: -- sum.as_sint64 = sum.as_sint32; -- norm_int64_16_noatt: -- sum.as_sint64 <<= 16; -- goto norm_int; -- -- norm_int32_24_noatt: -- sum.as_sint64 = sum.as_sint32; -- norm_int64_24_noatt: -- sum.as_sint64 <<= 24; -- goto norm_int; -- -- norm_int64_0_noatt: -- norm_int: -+ /* fallthru */ -+ norm_int64_noatt: - if (sum.as_sint64 > (int64_t)0x7fffffff) - sample = 0x7fffffff; /* maximum positive value */ - else if (sum.as_sint64 < -(int64_t)0x80000000) -@@ -441,16 +372,6 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, - goto after_norm; - - #if SND_PCM_PLUGIN_ROUTE_FLOAT -- norm_float_8: -- sum.as_float *= 1 << 8; -- goto norm_float; -- norm_float_16: -- sum.as_float *= 1 << 16; -- goto norm_float; -- norm_float_24: -- sum.as_float *= 1 << 24; -- goto norm_float; -- norm_float_0: - norm_float: - sum.as_float = rint(sum.as_float); - if (sum.as_float > (int64_t)0x7fffffff) -@@ -648,7 +569,7 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - route->params.use_getput = - (snd_pcm_format_physical_width(src_format) + 7) / 3 == 3 || - (snd_pcm_format_physical_width(dst_format) + 7) / 3 == 3; -- route->params.get_idx = snd_pcm_linear_get_index(src_format, SND_PCM_FORMAT_S16); -+ route->params.get_idx = snd_pcm_linear_get32_index(src_format, SND_PCM_FORMAT_S32); - route->params.put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, dst_format); - route->params.conv_idx = snd_pcm_linear_convert_index(src_format, dst_format); - route->params.src_size = snd_pcm_format_width(src_format) / 8; -@@ -656,10 +577,7 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - #if SND_PCM_PLUGIN_ROUTE_FLOAT - route->params.sum_idx = FLOAT; - #else -- if (snd_pcm_format_width(src_format) == 32) -- route->params.sum_idx = UINT64; -- else -- route->params.sum_idx = UINT32; -+ route->params.sum_idx = UINT64; - #endif - return 0; - } -diff --git a/src/pcm/plugin_ops.h b/src/pcm/plugin_ops.h -index 21535c9..eb8c2c4 100644 ---- a/src/pcm/plugin_ops.h -+++ b/src/pcm/plugin_ops.h -@@ -668,87 +668,6 @@ getu_1234_C321: sample = bswap_32(as_u32c(src) ^ 0x80); goto GETU_END; - } - #endif - --#ifdef GETS_LABELS --/* width endswap sign_toggle */ --static void *const gets_labels[4 * 2 * 2] = { -- &&gets_1_1, /* 8h -> 8h */ -- &&gets_1_9, /* 8h ^> 8h */ -- &&gets_1_1, /* 8s -> 8h */ -- &&gets_1_9, /* 8s ^> 8h */ -- &&gets_12_12, /* 16h -> 16h */ -- &&gets_12_92, /* 16h ^> 16h */ -- &&gets_12_21, /* 16s -> 16h */ -- &&gets_12_A1, /* 16s ^> 16h */ -- &&gets_0123_0123, /* 24h -> 24h */ -- &&gets_0123_0923, /* 24h ^> 24h */ -- &&gets_1230_0321, /* 24s -> 24h */ -- &&gets_1230_0B21, /* 24s ^> 24h */ -- &&gets_1234_1234, /* 32h -> 32h */ -- &&gets_1234_9234, /* 32h ^> 32h */ -- &&gets_1234_4321, /* 32s -> 32h */ -- &&gets_1234_C321, /* 32s ^> 32h */ --}; --#endif -- --#ifdef GETS_END --while (0) { --gets_1_1: sample = as_s8c(src); goto GETS_END; --gets_1_9: sample = (int8_t)(as_s8c(src) ^ 0x80); goto GETS_END; --gets_12_12: sample = as_s16c(src); goto GETS_END; --gets_12_92: sample = (int16_t)(as_s16c(src) ^ 0x8000); goto GETS_END; --gets_12_21: sample = (int16_t)bswap_16(as_s16c(src)); goto GETS_END; --gets_12_A1: sample = (int16_t)bswap_16(as_s16c(src) ^ 0x80); goto GETS_END; --gets_0123_0123: sample = sx24((int32_t)(as_s32c(src) << 8) >> 8); goto GETS_END; --gets_0123_0923: sample = sx24((int32_t)((as_s32c(src) ^ 0x800000) << 8) >> 8); goto GETS_END; --gets_1230_0321: sample = sx24((int32_t)(bswap_32(as_s32c(src)) << 8) >> 8); goto GETS_END; --gets_1230_0B21: sample = sx24((int32_t)(bswap_32(as_s32c(src) ^ 0x8000) << 8) >> 8); goto GETS_END; --gets_1234_1234: sample = as_s32c(src); goto GETS_END; --gets_1234_9234: sample = (int32_t)(as_s32c(src) ^ 0x80000000); goto GETS_END; --gets_1234_4321: sample = (int32_t)bswap_32(as_s32c(src)); goto GETS_END; --gets_1234_C321: sample = (int32_t)bswap_32(as_s32c(src) ^ 0x80); goto GETS_END; --} --#endif -- --#ifdef PUT_LABELS --/* width endswap sign_toggle */ --static void *const put_labels[4 * 2 * 2] = { -- &&put_1_1, /* 8h -> 8h */ -- &&put_1_9, /* 8h ^> 8h */ -- &&put_1_1, /* 8h -> 8s */ -- &&put_1_9, /* 8h ^> 8s */ -- &&put_12_12, /* 16h -> 16h */ -- &&put_12_92, /* 16h ^> 16h */ -- &&put_12_21, /* 16h -> 16s */ -- &&put_12_29, /* 16h ^> 16s */ -- &&put_0123_0123, /* 24h -> 24h */ -- &&put_0123_0923, /* 24h ^> 24h */ -- &&put_0123_3210, /* 24h -> 24s */ -- &&put_0123_3290, /* 24h ^> 24s */ -- &&put_1234_1234, /* 32h -> 32h */ -- &&put_1234_9234, /* 32h ^> 32h */ -- &&put_1234_4321, /* 32h -> 32s */ -- &&put_1234_4329, /* 32h ^> 32s */ --}; --#endif -- --#ifdef PUT_END --put_1_1: as_s8(dst) = sample; goto PUT_END; --put_1_9: as_u8(dst) = sample ^ 0x80; goto PUT_END; --put_12_12: as_s16(dst) = sample; goto PUT_END; --put_12_92: as_u16(dst) = sample ^ 0x8000; goto PUT_END; --put_12_21: as_s16(dst) = bswap_16(sample); goto PUT_END; --put_12_29: as_u16(dst) = bswap_16(sample) ^ 0x80; goto PUT_END; --/* this always writes the unused byte in 24-bit formats as 0x00 */ --put_0123_0123: as_s32(dst) = sx24(sample & 0x00ffffff); goto PUT_END; --put_0123_0923: as_u32(dst) = sx24((sample & 0x00ffffff) ^ 0x800000); goto PUT_END; --put_0123_3210: as_s32(dst) = sx24s(bswap_32(sample) & 0xffffff00); goto PUT_END; --put_0123_3290: as_u32(dst) = sx24s((bswap_32(sample) & 0xffffff00) ^ 0x8000); goto PUT_END; --put_1234_1234: as_s32(dst) = sample; goto PUT_END; --put_1234_9234: as_u32(dst) = sample ^ 0x80000000; goto PUT_END; --put_1234_4321: as_s32(dst) = bswap_32(sample); goto PUT_END; --put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END; --#endif -- - #ifdef PUT32F_LABELS - /* type (0 = float, 1 = float64), endswap */ - static void *const put32float_labels[2 * 2] = { --- -1.9.3 - - -From 7a5646f58ba2e8154a274a5ae0f8ec963f331f97 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Tue, 22 Jul 2014 12:20:50 +0200 -Subject: [PATCH 14/35] pcm: Drop snd_pcm_linear_{get|put}32_index() - -These are identical with snd_pcm_linear_{get|put}_index(). - -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_lfloat.c | 4 ++-- - src/pcm/pcm_linear.c | 44 ++++---------------------------------------- - src/pcm/pcm_plugin.h | 4 ---- - src/pcm/pcm_route.c | 4 ++-- - 4 files changed, 8 insertions(+), 48 deletions(-) - -diff --git a/src/pcm/pcm_lfloat.c b/src/pcm/pcm_lfloat.c -index 324282f..2f3e578 100644 ---- a/src/pcm/pcm_lfloat.c -+++ b/src/pcm/pcm_lfloat.c -@@ -286,11 +286,11 @@ static int snd_pcm_lfloat_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) - err = INTERNAL(snd_pcm_hw_params_get_format)(params, &dst_format); - } - if (snd_pcm_format_linear(src_format)) { -- lfloat->int32_idx = snd_pcm_linear_get32_index(src_format, SND_PCM_FORMAT_S32); -+ lfloat->int32_idx = snd_pcm_linear_get_index(src_format, SND_PCM_FORMAT_S32); - lfloat->float32_idx = snd_pcm_lfloat_put_s32_index(dst_format); - lfloat->func = snd_pcm_lfloat_convert_integer_float; - } else { -- lfloat->int32_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, dst_format); -+ lfloat->int32_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S32, dst_format); - lfloat->float32_idx = snd_pcm_lfloat_get_s32_index(src_format); - lfloat->func = snd_pcm_lfloat_convert_float_integer; - } -diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c -index 3d5bbb8..9a92abd 100644 ---- a/src/pcm/pcm_linear.c -+++ b/src/pcm/pcm_linear.c -@@ -107,11 +107,6 @@ int snd_pcm_linear_get_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_f - } - } - --int snd_pcm_linear_get32_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format) --{ -- return snd_pcm_linear_get_index(src_format, dst_format); --} -- - int snd_pcm_linear_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format) - { - int sign, width, pwidth, endian; -@@ -143,37 +138,6 @@ int snd_pcm_linear_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_f - } - } - --int snd_pcm_linear_put32_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format) --{ -- int sign, width, pwidth, endian; -- sign = (snd_pcm_format_signed(src_format) != -- snd_pcm_format_signed(dst_format)); --#ifdef SND_LITTLE_ENDIAN -- endian = snd_pcm_format_big_endian(dst_format); --#else -- endian = snd_pcm_format_little_endian(dst_format); --#endif -- if (endian < 0) -- endian = 0; -- pwidth = snd_pcm_format_physical_width(dst_format); -- width = snd_pcm_format_width(dst_format); -- if (pwidth == 24) { -- switch (width) { -- case 24: -- width = 0; break; -- case 20: -- width = 1; break; -- case 18: -- default: -- width = 2; break; -- } -- return width * 4 + endian * 2 + sign + 16; -- } else { -- width = width / 8 - 1; -- return width * 4 + endian * 2 + sign; -- } --} -- - void snd_pcm_linear_convert(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, - const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset, - unsigned int channels, snd_pcm_uframes_t frames, -@@ -342,11 +306,11 @@ static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) - snd_pcm_format_physical_width(linear->sformat) == 24); - if (linear->use_getput) { - if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { -- linear->get_idx = snd_pcm_linear_get32_index(format, SND_PCM_FORMAT_S32); -- linear->put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, linear->sformat); -+ linear->get_idx = snd_pcm_linear_get_index(format, SND_PCM_FORMAT_S32); -+ linear->put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S32, linear->sformat); - } else { -- linear->get_idx = snd_pcm_linear_get32_index(linear->sformat, SND_PCM_FORMAT_S32); -- linear->put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, format); -+ linear->get_idx = snd_pcm_linear_get_index(linear->sformat, SND_PCM_FORMAT_S32); -+ linear->put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S32, format); - } - } else { - if (pcm->stream == SND_PCM_STREAM_PLAYBACK) -diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h -index 19e82c3..b0a3e18 100644 ---- a/src/pcm/pcm_plugin.h -+++ b/src/pcm/pcm_plugin.h -@@ -86,8 +86,6 @@ snd_pcm_sframes_t snd_pcm_plugin_undo_write_generic - /* make local functions really local */ - #define snd_pcm_linear_get_index snd1_pcm_linear_get_index - #define snd_pcm_linear_put_index snd1_pcm_linear_put_index --#define snd_pcm_linear_get32_index snd1_pcm_linear_get32_index --#define snd_pcm_linear_put32_index snd1_pcm_linear_put32_index - #define snd_pcm_linear_convert_index snd1_pcm_linear_convert_index - #define snd_pcm_linear_convert snd1_pcm_linear_convert - #define snd_pcm_linear_getput snd1_pcm_linear_getput -@@ -100,8 +98,6 @@ snd_pcm_sframes_t snd_pcm_plugin_undo_write_generic - - int snd_pcm_linear_get_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format); - int snd_pcm_linear_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format); --int snd_pcm_linear_get32_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format); --int snd_pcm_linear_put32_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format); - int snd_pcm_linear_convert_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format); - - void snd_pcm_linear_convert(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, -diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c -index 5dac7eb..e7de9b5 100644 ---- a/src/pcm/pcm_route.c -+++ b/src/pcm/pcm_route.c -@@ -569,8 +569,8 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - route->params.use_getput = - (snd_pcm_format_physical_width(src_format) + 7) / 3 == 3 || - (snd_pcm_format_physical_width(dst_format) + 7) / 3 == 3; -- route->params.get_idx = snd_pcm_linear_get32_index(src_format, SND_PCM_FORMAT_S32); -- route->params.put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, dst_format); -+ route->params.get_idx = snd_pcm_linear_get_index(src_format, SND_PCM_FORMAT_S32); -+ route->params.put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S32, dst_format); - route->params.conv_idx = snd_pcm_linear_convert_index(src_format, dst_format); - route->params.src_size = snd_pcm_format_width(src_format) / 8; - route->params.dst_sfmt = dst_format; --- -1.9.3 - - -From f6b879e7cc87d83343f5004369146881d1d1e335 Mon Sep 17 00:00:00 2001 -From: Shengjiu Wang -Date: Wed, 23 Jul 2014 15:09:58 +0800 -Subject: [PATCH 15/35] pcm: pcm_local.h: include to enable - CLOCK_MONOTONIC - -CLOCK_MONITONIC is defined in , add before -. - -Signed-off-by: Shengjiu Wang -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_local.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h -index 2206afe..80bbe59 100644 ---- a/src/pcm/pcm_local.h -+++ b/src/pcm/pcm_local.h -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - - #define _snd_mask sndrv_mask --- -1.9.3 - - -From 87df9f3b7a650418b9aef943ac246549c132672a Mon Sep 17 00:00:00 2001 -From: Jurgen Kramer -Date: Sat, 9 Aug 2014 12:09:21 +0200 -Subject: [PATCH 16/35] pcm: Fix DSD formats userland usability - -Support for DSD sample formats has been added a while ago. This patch makes -those sample formats beter usable from userland (e.g. aplay). - -[These implementation details have been forgotten in the previous DSD - support patch -- tiwai] - -Signed-off-by: Takashi Iwai ---- - include/sound/asound.h | 4 +++- - src/pcm/pcm_misc.c | 4 ++++ - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/include/sound/asound.h b/include/sound/asound.h -index c819df4..5194524 100644 ---- a/include/sound/asound.h -+++ b/include/sound/asound.h -@@ -214,7 +214,9 @@ typedef int __bitwise snd_pcm_format_t; - #define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */ - #define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */ - #define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ --#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B -+#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* 8 1-bit samples in 1 byte */ -+#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* 16 1-bit samples in 2 bytes */ -+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U16_LE - - #ifdef SNDRV_LITTLE_ENDIAN - #define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE -diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c -index d52160c..44bb89c 100644 ---- a/src/pcm/pcm_misc.c -+++ b/src/pcm/pcm_misc.c -@@ -195,11 +195,13 @@ int snd_pcm_format_width(snd_pcm_format_t format) - switch (format) { - case SNDRV_PCM_FORMAT_S8: - case SNDRV_PCM_FORMAT_U8: -+ case SNDRV_PCM_FORMAT_DSD_U8: - return 8; - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_U16_BE: -+ case SNDRV_PCM_FORMAT_DSD_U16_LE: - return 16; - case SNDRV_PCM_FORMAT_S18_3LE: - case SNDRV_PCM_FORMAT_S18_3BE: -@@ -253,11 +255,13 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) - switch (format) { - case SNDRV_PCM_FORMAT_S8: - case SNDRV_PCM_FORMAT_U8: -+ case SNDRV_PCM_FORMAT_DSD_U8: - return 8; - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_U16_BE: -+ case SNDRV_PCM_FORMAT_DSD_U16_LE: - return 16; - case SNDRV_PCM_FORMAT_S18_3LE: - case SNDRV_PCM_FORMAT_S18_3BE: --- -1.9.3 - - -From 717ae3dd90c37f3a5ea9809370bdf56e2590a1c4 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Mon, 11 Aug 2014 11:51:29 +0200 -Subject: [PATCH 17/35] Sync include/sound/asound.h with 3.17-rc1 kernel - -Signed-off-by: Takashi Iwai ---- - include/sound/asound.h | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/include/sound/asound.h b/include/sound/asound.h -index 5194524..32168f7 100644 ---- a/include/sound/asound.h -+++ b/include/sound/asound.h -@@ -93,9 +93,12 @@ enum { - SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ - SNDRV_HWDEP_IFACE_HDA, /* HD-audio */ - SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */ -+ SNDRV_HWDEP_IFACE_FW_DICE, /* TC DICE FireWire device */ -+ SNDRV_HWDEP_IFACE_FW_FIREWORKS, /* Echo Audio Fireworks based device */ -+ SNDRV_HWDEP_IFACE_FW_BEBOB, /* BridgeCo BeBoB based device */ - - /* Don't forget to change the following: */ -- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM -+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_BEBOB - }; - - struct snd_hwdep_info { -@@ -214,8 +217,8 @@ typedef int __bitwise snd_pcm_format_t; - #define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */ - #define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */ - #define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ --#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* 8 1-bit samples in 1 byte */ --#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* 16 1-bit samples in 2 bytes */ -+#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */ -+#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */ - #define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U16_LE - - #ifdef SNDRV_LITTLE_ENDIAN -@@ -461,7 +464,7 @@ struct snd_xfern { - enum { - SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */ - SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */ -- SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */ -+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */ - SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, - }; - -@@ -820,6 +823,8 @@ typedef int __bitwise snd_ctl_elem_iface_t; - #define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */ - #define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */ - -+#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 -+ - struct snd_ctl_elem_id { - unsigned int numid; /* numeric identifier, zero = invalid */ - snd_ctl_elem_iface_t iface; /* interface identifier */ --- -1.9.3 - - -From e8e54811339b13d6df648bb48b35157d9fba352c Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Mon, 11 Aug 2014 11:55:03 +0200 -Subject: [PATCH 18/35] pcm: Add missing signed and endianess definitions for - DSD formats - -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_misc.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c -index 44bb89c..24d52f9 100644 ---- a/src/pcm/pcm_misc.c -+++ b/src/pcm/pcm_misc.c -@@ -62,6 +62,8 @@ int snd_pcm_format_signed(snd_pcm_format_t format) - case SNDRV_PCM_FORMAT_U20_3BE: - case SNDRV_PCM_FORMAT_U18_3LE: - case SNDRV_PCM_FORMAT_U18_3BE: -+ case SNDRV_PCM_FORMAT_DSD_U8: -+ case SNDRV_PCM_FORMAT_DSD_U16_LE: - return 0; - default: - return -EINVAL; -@@ -150,6 +152,8 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) - case SNDRV_PCM_FORMAT_U24_3BE: - case SNDRV_PCM_FORMAT_U20_3BE: - case SNDRV_PCM_FORMAT_U18_3BE: -+ case SNDRV_PCM_FORMAT_DSD_U8: -+ case SNDRV_PCM_FORMAT_DSD_U16_LE: - return 0; - default: - return -EINVAL; --- -1.9.3 - - -From dfc3bf97bf45bd78d498d20fcf930541350f836d Mon Sep 17 00:00:00 2001 -From: Takashi Sakamoto -Date: Mon, 18 Aug 2014 18:45:17 +0900 -Subject: [PATCH 19/35] Sync enum snd_hwdep_iface_t with - include/asound/asound.h - -Some members in this enumerated type has not updated for 9 years, although -kernel-drivers added them during this period. This commit adds them following -to a commit 87df9f3 'sync include/asound/asound.h with 3.17-rc1 kernel'. - -Signed-off-by: Takashi Sakamoto -Signed-off-by: Takashi Iwai ---- - include/hwdep.h | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/include/hwdep.h b/include/hwdep.h -index ab12822..6496fa2 100644 ---- a/include/hwdep.h -+++ b/include/hwdep.h -@@ -68,8 +68,13 @@ typedef enum _snd_hwdep_iface { - SND_HWDEP_IFACE_USX2Y_PCM, /**< Tascam US122, US224 & US428 raw USB PCM */ - SND_HWDEP_IFACE_PCXHR, /**< Digigram PCXHR */ - SND_HWDEP_IFACE_SB_RC, /**< SB Extigy/Audigy2NX remote control */ -- -- SND_HWDEP_IFACE_LAST = SND_HWDEP_IFACE_SB_RC /**< last known hwdep interface */ -+ SND_HWDEP_IFACE_HDA, /**< HD-audio */ -+ SND_HWDEP_IFACE_USB_STREAM, /**< direct access to usb stream */ -+ SND_HWDEP_IFACE_FW_DICE, /**< TC DICE FireWire device */ -+ SND_HWDEP_IFACE_FW_FIREWORKS, /**< Echo Audio Fireworks based device */ -+ SND_HWDEP_IFACE_FW_BEBOB, /**< BridgeCo BeBoB based device */ -+ -+ SND_HWDEP_IFACE_LAST = SND_HWDEP_IFACE_FW_BEBOB /**< last known hwdep interface */ - } snd_hwdep_iface_t; - - /** open for reading */ --- -1.9.3 - - -From b9f58dcc6f91fde42e6dd2bb831d6063855512a7 Mon Sep 17 00:00:00 2001 -From: Jurgen Kramer -Date: Fri, 22 Aug 2014 10:15:10 +0200 -Subject: [PATCH 20/35] pcm: 2nd round of pcm_misc DSD fixes - -Functions 'snd_pcm_format_silence_64' and 'snd_pcm_format_size' also need to be -able to handle the DSD smaple format. - -Changes from v1: -- Correct silence pattern for DSD - -Signed-off-by: Jurgen Kramer -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_misc.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c -index 24d52f9..46fc771 100644 ---- a/src/pcm/pcm_misc.c -+++ b/src/pcm/pcm_misc.c -@@ -317,11 +317,13 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) - switch (format) { - case SNDRV_PCM_FORMAT_S8: - case SNDRV_PCM_FORMAT_U8: -+ case SNDRV_PCM_FORMAT_DSD_U8: - return samples; - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_U16_BE: -+ case SNDRV_PCM_FORMAT_DSD_U16_LE: - return samples * 2; - case SNDRV_PCM_FORMAT_S18_3LE: - case SNDRV_PCM_FORMAT_S18_3BE: -@@ -390,6 +392,9 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) - return 0; - case SNDRV_PCM_FORMAT_U8: - return 0x8080808080808080ULL; -+ case SNDRV_PCM_FORMAT_DSD_U8: -+ case SNDRV_PCM_FORMAT_DSD_U16_LE: -+ return 0x6969696969696969ULL; - #ifdef SNDRV_LITTLE_ENDIAN - case SNDRV_PCM_FORMAT_U16_LE: - return 0x8000800080008000ULL; --- -1.9.3 - - -From 5f1960e3d8d56aa63afe2c37c6a3f4aa03571627 Mon Sep 17 00:00:00 2001 -From: Dmitry Voytik -Date: Fri, 22 Aug 2014 14:17:10 +0400 -Subject: [PATCH 21/35] doc: fix cross-compiling example - -Simplest way to configure cross-compilation with configure -script is to pass '--host' option. -Passing just '--target' doesn't work. - -Signed-off-by: Dmitry Voytik -Signed-off-by: Takashi Iwai ---- - INSTALL | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - -diff --git a/INSTALL b/INSTALL -index 91a8648..47086e3 100644 ---- a/INSTALL -+++ b/INSTALL -@@ -78,16 +78,13 @@ When you would like to cross-compile ALSA library (e.g. compile on - i686 host but for arm architecture) you will need to call ./configure - script with additional parameters: - --CC=arm-linux-gcc ./configure --target=arm-linux -+CC=arm-linux-gcc ./configure --host=arm-linux - --In this example host where the library is build is guessed (should be --given with --host=platform) and target for which is the library build is --Linux on ARM architecture. You should omit setting 'CC' variable and --cross-compiler will be guessed too. -+You can omit setting 'CC' variable and cross-compiler will be guessed too. - - So simplest version would be: - --./configure --target=arm-linux -+./configure --host=arm-linux - - For platform names in the form cpu-vendor-os (or aliases for this) - you should look in 'config.guess' script. Target and all paths --- -1.9.3 - - -From 99a2254f5f2a085b81efcc80950033a2b6110ecd Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Sun, 31 Aug 2014 22:23:47 +0600 -Subject: [PATCH 22/35] pcm: fix snd_pcm_mmap_hw_avail() near the boundary - -This function returned incorrect results when hw.ptr was near the -boundary and hw.appl_ptr was near zero. Here "incorrect" means "greater -than the boundary". - -The result was incorrect, because it was used as a return value of -various *_rewindable() functions and also as the delay for ioplug. - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_local.h | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - -diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h -index 80bbe59..74ebd60 100644 ---- a/src/pcm/pcm_local.h -+++ b/src/pcm/pcm_local.h -@@ -461,13 +461,7 @@ static inline snd_pcm_sframes_t snd_pcm_mmap_capture_hw_avail(snd_pcm_t *pcm) - - static inline snd_pcm_sframes_t snd_pcm_mmap_hw_avail(snd_pcm_t *pcm) - { -- snd_pcm_sframes_t avail; -- avail = *pcm->hw.ptr - *pcm->appl.ptr; -- if (pcm->stream == SND_PCM_STREAM_PLAYBACK) -- avail += pcm->buffer_size; -- if (avail < 0) -- avail += pcm->boundary; -- return pcm->buffer_size - avail; -+ return pcm->buffer_size - snd_pcm_mmap_avail(pcm); - } - - static inline const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm) --- -1.9.3 - - -From 622b1b6bdbb34baca885b65643d4796057574eb7 Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Tue, 2 Sep 2014 01:29:36 +0600 -Subject: [PATCH 23/35] pcm: fix return value of snd_pcm_share_slave_avail - -The return value was wrong for playback if slave->hw_ptr was near the -boundary and *pcm->appl.ptr was near zero. The wrong result was greater -than the boundary. - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_share.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c -index 9770544..c301c7a 100644 ---- a/src/pcm/pcm_share.c -+++ b/src/pcm/pcm_share.c -@@ -128,6 +128,8 @@ static snd_pcm_uframes_t snd_pcm_share_slave_avail(snd_pcm_share_slave_t *slave) - avail += pcm->buffer_size; - if (avail < 0) - avail += pcm->boundary; -+ else if ((snd_pcm_uframes_t) avail >= pcm->boundary) -+ avail -= pcm->boundary; - return avail; - } - --- -1.9.3 - - -From e59ffbf30ec13f7f1615ba266ec2f3e770801d6f Mon Sep 17 00:00:00 2001 -From: Jurgen Kramer -Date: Wed, 10 Sep 2014 09:00:28 +0200 -Subject: [PATCH 24/35] pcm: add new 32-bit DSD sample format - -Add the new DSD_U32_LE sample format to alsa-lib. - -NB include/pcm.h and include/sound/asound.h are updated so a new sync with the -kernel headers is not needed - -Signed-off-by: Jurgen Kramer -Signed-off-by: Takashi Iwai ---- - include/pcm.h | 4 +++- - include/sound/asound.h | 3 ++- - src/pcm/pcm.c | 2 ++ - src/pcm/pcm_misc.c | 6 ++++++ - 4 files changed, 13 insertions(+), 2 deletions(-) - -diff --git a/include/pcm.h b/include/pcm.h -index 11e9f0d..db88ad5 100644 ---- a/include/pcm.h -+++ b/include/pcm.h -@@ -211,7 +211,9 @@ typedef enum _snd_pcm_format { - SND_PCM_FORMAT_DSD_U8, - /* Direct Stream Digital (DSD) in 2-byte samples (x16) */ - SND_PCM_FORMAT_DSD_U16_LE, -- SND_PCM_FORMAT_LAST = SND_PCM_FORMAT_DSD_U16_LE, -+ /* Direct Stream Digital (DSD) in 4-byte samples (x32) */ -+ SND_PCM_FORMAT_DSD_U32_LE, -+ SND_PCM_FORMAT_LAST = SND_PCM_FORMAT_DSD_U32_LE, - - #if __BYTE_ORDER == __LITTLE_ENDIAN - /** Signed 16 bit CPU endian */ -diff --git a/include/sound/asound.h b/include/sound/asound.h -index 32168f7..6ee5867 100644 ---- a/include/sound/asound.h -+++ b/include/sound/asound.h -@@ -219,7 +219,8 @@ typedef int __bitwise snd_pcm_format_t; - #define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ - #define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */ - #define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */ --#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U16_LE -+#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */ -+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_LE - - #ifdef SNDRV_LITTLE_ENDIAN - #define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE -diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c -index 1399a5b..2e24338 100644 ---- a/src/pcm/pcm.c -+++ b/src/pcm/pcm.c -@@ -1565,6 +1565,7 @@ static const char *const snd_pcm_format_names[] = { - FORMAT(G723_40_1B), - FORMAT(DSD_U8), - FORMAT(DSD_U16_LE), -+ FORMAT(DSD_U32_LE), - }; - - static const char *const snd_pcm_format_aliases[SND_PCM_FORMAT_LAST+1] = { -@@ -1624,6 +1625,7 @@ static const char *const snd_pcm_format_descriptions[] = { - FORMATD(G723_40_1B, "G.723 (ADPCM) 40 kbit/s, 1 sample in 1 byte"), - FORMATD(DSD_U8, "Direct Stream Digital, 1-byte (x8), oldest bit in MSB"), - FORMATD(DSD_U16_LE, "Direct Stream Digital, 2-byte (x16), little endian, oldest bits in MSB"), -+ FORMATD(DSD_U32_LE, "Direct Stream Digital, 4-byte (x32), little endian, oldest bits in MSB"), - }; - - static const char *const snd_pcm_type_names[] = { -diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c -index 46fc771..9272179 100644 ---- a/src/pcm/pcm_misc.c -+++ b/src/pcm/pcm_misc.c -@@ -64,6 +64,7 @@ int snd_pcm_format_signed(snd_pcm_format_t format) - case SNDRV_PCM_FORMAT_U18_3BE: - case SNDRV_PCM_FORMAT_DSD_U8: - case SNDRV_PCM_FORMAT_DSD_U16_LE: -+ case SNDRV_PCM_FORMAT_DSD_U32_LE: - return 0; - default: - return -EINVAL; -@@ -154,6 +155,7 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) - case SNDRV_PCM_FORMAT_U18_3BE: - case SNDRV_PCM_FORMAT_DSD_U8: - case SNDRV_PCM_FORMAT_DSD_U16_LE: -+ case SNDRV_PCM_FORMAT_DSD_U32_LE: - return 0; - default: - return -EINVAL; -@@ -232,6 +234,7 @@ int snd_pcm_format_width(snd_pcm_format_t format) - case SNDRV_PCM_FORMAT_U32_BE: - case SNDRV_PCM_FORMAT_FLOAT_LE: - case SNDRV_PCM_FORMAT_FLOAT_BE: -+ case SNDRV_PCM_FORMAT_DSD_U32_LE: - return 32; - case SNDRV_PCM_FORMAT_FLOAT64_LE: - case SNDRV_PCM_FORMAT_FLOAT64_BE: -@@ -292,6 +295,7 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) - case SNDRV_PCM_FORMAT_FLOAT_BE: - case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: - case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE: -+ case SNDRV_PCM_FORMAT_DSD_U32_LE: - return 32; - case SNDRV_PCM_FORMAT_FLOAT64_LE: - case SNDRV_PCM_FORMAT_FLOAT64_BE: -@@ -348,6 +352,7 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) - case SNDRV_PCM_FORMAT_U32_BE: - case SNDRV_PCM_FORMAT_FLOAT_LE: - case SNDRV_PCM_FORMAT_FLOAT_BE: -+ case SNDRV_PCM_FORMAT_DSD_U32_LE: - return samples * 4; - case SNDRV_PCM_FORMAT_FLOAT64_LE: - case SNDRV_PCM_FORMAT_FLOAT64_BE: -@@ -394,6 +399,7 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) - return 0x8080808080808080ULL; - case SNDRV_PCM_FORMAT_DSD_U8: - case SNDRV_PCM_FORMAT_DSD_U16_LE: -+ case SNDRV_PCM_FORMAT_DSD_U32_LE: - return 0x6969696969696969ULL; - #ifdef SNDRV_LITTLE_ENDIAN - case SNDRV_PCM_FORMAT_U16_LE: --- -1.9.3 - - -From 9a56a673a6cd7343a9345921e2b1cbbb43fb725f Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Sun, 14 Sep 2014 00:30:13 +0600 -Subject: [PATCH 25/35] dmix: actually rewind when running or being drained - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dmix.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index 7c53509..73cbe3f 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -669,11 +669,15 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f - snd_pcm_direct_t *dmix = pcm->private_data; - snd_pcm_uframes_t slave_appl_ptr, slave_size; - snd_pcm_uframes_t appl_ptr, size, transfer, result; -+ int err; - const snd_pcm_channel_area_t *src_areas, *dst_areas; - - if (dmix->state == SND_PCM_STATE_RUNNING || -- dmix->state == SND_PCM_STATE_DRAINING) -- return snd_pcm_dmix_hwsync(pcm); -+ dmix->state == SND_PCM_STATE_DRAINING) { -+ err = snd_pcm_dmix_hwsync(pcm); -+ if (err < 0) -+ return err; -+ } - - if (dmix->last_appl_ptr < dmix->appl_ptr) - size = dmix->appl_ptr - dmix->last_appl_ptr; --- -1.9.3 - - -From 9a43dc15b2979ed6d8850b033b594fbef829c991 Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Sun, 14 Sep 2014 00:30:14 +0600 -Subject: [PATCH 26/35] pcm: express the rewind size limitation logic better - -There are a few places where the argument of the .rewind or .forward -callback is checked against the same value as returned by .rewindable or -.forwardable. Express this "don't rewind more than rewindable" logic -explicitly, so that the future fixes to the rewindable size can go to -one function instead of two. - -While at it, take advantage of the fact that snd_pcm_mmap_avail() cannot -return negative values (except due to integer overflow, which is AFAICS -impossible given the current boundary choice). - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dmix.c | 4 +--- - src/pcm/pcm_dshare.c | 6 ++---- - src/pcm/pcm_dsnoop.c | 6 ++---- - src/pcm/pcm_plugin.c | 4 ++-- - 4 files changed, 7 insertions(+), 13 deletions(-) - -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index 73cbe3f..ffde12a 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -751,9 +751,7 @@ static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t - { - snd_pcm_sframes_t avail; - -- avail = snd_pcm_mmap_playback_avail(pcm); -- if (avail < 0) -- return 0; -+ avail = snd_pcm_dmix_forwardable(pcm); - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - snd_pcm_mmap_appl_forward(pcm, frames); -diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c -index b985172..f1a1a1d 100644 ---- a/src/pcm/pcm_dshare.c -+++ b/src/pcm/pcm_dshare.c -@@ -419,7 +419,7 @@ static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t - { - snd_pcm_sframes_t avail; - -- avail = snd_pcm_mmap_playback_hw_avail(pcm); -+ avail = snd_pcm_dshare_rewindable(pcm); - if (avail < 0) - return 0; - if (frames > (snd_pcm_uframes_t)avail) -@@ -437,9 +437,7 @@ static snd_pcm_sframes_t snd_pcm_dshare_forward(snd_pcm_t *pcm, snd_pcm_uframes_ - { - snd_pcm_sframes_t avail; - -- avail = snd_pcm_mmap_playback_avail(pcm); -- if (avail < 0) -- return 0; -+ avail = snd_pcm_dshare_forwardable(pcm); - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - snd_pcm_mmap_appl_forward(pcm, frames); -diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c -index 0f9c9df..e56e402 100644 ---- a/src/pcm/pcm_dsnoop.c -+++ b/src/pcm/pcm_dsnoop.c -@@ -342,9 +342,7 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t - { - snd_pcm_sframes_t avail; - -- avail = snd_pcm_mmap_capture_avail(pcm); -- if (avail < 0) -- return 0; -+ avail = snd_pcm_dsnoop_rewindable(pcm); - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - snd_pcm_mmap_appl_backward(pcm, frames); -@@ -360,7 +358,7 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_forward(snd_pcm_t *pcm, snd_pcm_uframes_ - { - snd_pcm_sframes_t avail; - -- avail = snd_pcm_mmap_capture_hw_avail(pcm); -+ avail = snd_pcm_dsnoop_forwardable(pcm); - if (avail < 0) - return 0; - if (frames > (snd_pcm_uframes_t)avail) -diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c -index 4ddf10c..a607ccf 100644 ---- a/src/pcm/pcm_plugin.c -+++ b/src/pcm/pcm_plugin.c -@@ -204,7 +204,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm) - snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) - { - snd_pcm_plugin_t *plugin = pcm->private_data; -- snd_pcm_sframes_t n = snd_pcm_mmap_hw_avail(pcm); -+ snd_pcm_sframes_t n = snd_pcm_plugin_rewindable(pcm); - snd_pcm_sframes_t sframes; - - if ((snd_pcm_uframes_t)n < frames) -@@ -232,7 +232,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm) - snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) - { - snd_pcm_plugin_t *plugin = pcm->private_data; -- snd_pcm_sframes_t n = snd_pcm_mmap_avail(pcm); -+ snd_pcm_sframes_t n = snd_pcm_plugin_forwardable(pcm); - snd_pcm_sframes_t sframes; - - if ((snd_pcm_uframes_t)n < frames) --- -1.9.3 - - -From 78c804fc9348e4c29f1c77dd4b6ad586393aa628 Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Sun, 14 Sep 2014 00:30:15 +0600 -Subject: [PATCH 27/35] pcm: handle negative values from snd_pcm_mmap_hw_avail - -Such negative values can happen when an underrun happens and xrun -detection is disabled. Another situation is if the device updated the -pointer before alsa-lib has a chance to detect the xrun. - -The problem is that these negative values could propagate to the -snd_pcm_rewindable return value, where it is specified that negative -returns must be interpreted as error codes and not as negative amount of -samples. - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dmix.c | 2 +- - src/pcm/pcm_dshare.c | 4 +--- - src/pcm/pcm_hw.c | 2 +- - src/pcm/pcm_ioplug.c | 2 +- - src/pcm/pcm_local.h | 18 ++++++++++++++++++ - src/pcm/pcm_plugin.c | 2 +- - 6 files changed, 23 insertions(+), 7 deletions(-) - -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index ffde12a..babde6a 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -661,7 +661,7 @@ static int snd_pcm_dmix_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIB - - static snd_pcm_sframes_t snd_pcm_dmix_rewindable(snd_pcm_t *pcm) - { -- return snd_pcm_mmap_hw_avail(pcm); -+ return snd_pcm_mmap_playback_hw_rewindable(pcm); - } - - static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) -diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c -index f1a1a1d..020e6f7 100644 ---- a/src/pcm/pcm_dshare.c -+++ b/src/pcm/pcm_dshare.c -@@ -412,7 +412,7 @@ static int snd_pcm_dshare_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTR - - static snd_pcm_sframes_t snd_pcm_dshare_rewindable(snd_pcm_t *pcm) - { -- return snd_pcm_mmap_playback_hw_avail(pcm); -+ return snd_pcm_mmap_playback_hw_rewindable(pcm); - } - - static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) -@@ -420,8 +420,6 @@ static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t - snd_pcm_sframes_t avail; - - avail = snd_pcm_dshare_rewindable(pcm); -- if (avail < 0) -- return 0; - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - snd_pcm_mmap_appl_backward(pcm, frames); -diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c -index 74cff67..c34b766 100644 ---- a/src/pcm/pcm_hw.c -+++ b/src/pcm/pcm_hw.c -@@ -659,7 +659,7 @@ static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable) - - static snd_pcm_sframes_t snd_pcm_hw_rewindable(snd_pcm_t *pcm) - { -- return snd_pcm_mmap_hw_avail(pcm); -+ return snd_pcm_mmap_hw_rewindable(pcm); - } - - static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) -diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c -index 85a8891..fe9347c 100644 ---- a/src/pcm/pcm_ioplug.c -+++ b/src/pcm/pcm_ioplug.c -@@ -503,7 +503,7 @@ static int snd_pcm_ioplug_pause(snd_pcm_t *pcm, int enable) - - static snd_pcm_sframes_t snd_pcm_ioplug_rewindable(snd_pcm_t *pcm) - { -- return snd_pcm_mmap_hw_avail(pcm); -+ return snd_pcm_mmap_hw_rewindable(pcm); - } - - static snd_pcm_sframes_t snd_pcm_ioplug_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) -diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h -index 74ebd60..394505f 100644 ---- a/src/pcm/pcm_local.h -+++ b/src/pcm/pcm_local.h -@@ -464,6 +464,24 @@ static inline snd_pcm_sframes_t snd_pcm_mmap_hw_avail(snd_pcm_t *pcm) - return pcm->buffer_size - snd_pcm_mmap_avail(pcm); - } - -+static inline snd_pcm_sframes_t snd_pcm_mmap_playback_hw_rewindable(snd_pcm_t *pcm) -+{ -+ snd_pcm_sframes_t ret = snd_pcm_mmap_playback_hw_avail(pcm); -+ return (ret >= 0) ? ret : 0; -+} -+ -+static inline snd_pcm_sframes_t snd_pcm_mmap_capture_hw_rewindable(snd_pcm_t *pcm) -+{ -+ snd_pcm_sframes_t ret = snd_pcm_mmap_capture_hw_avail(pcm); -+ return (ret >= 0) ? ret : 0; -+} -+ -+static inline snd_pcm_uframes_t snd_pcm_mmap_hw_rewindable(snd_pcm_t *pcm) -+{ -+ snd_pcm_sframes_t ret = snd_pcm_mmap_hw_avail(pcm); -+ return (ret >= 0) ? ret : 0; -+} -+ - static inline const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm) - { - if (pcm->stopped_areas && -diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c -index a607ccf..c19e2f1 100644 ---- a/src/pcm/pcm_plugin.c -+++ b/src/pcm/pcm_plugin.c -@@ -198,7 +198,7 @@ static int snd_pcm_plugin_reset(snd_pcm_t *pcm) - - static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm) - { -- return snd_pcm_mmap_hw_avail(pcm); -+ return snd_pcm_mmap_hw_rewindable(pcm); - } - - snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) --- -1.9.3 - - -From 0889e9470667dd68d5a0ce47a10a8c6d61b7bc79 Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Sun, 14 Sep 2014 00:30:16 +0600 -Subject: [PATCH 28/35] pcm, rate: use the snd_pcm_mmap_hw_avail function - -instead of the open-coded equivalent - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_rate.c | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c -index 5e811bb..b436a8e 100644 ---- a/src/pcm/pcm_rate.c -+++ b/src/pcm/pcm_rate.c -@@ -593,10 +593,7 @@ static int snd_pcm_rate_hwsync(snd_pcm_t *pcm) - static int snd_pcm_rate_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) - { - snd_pcm_rate_hwsync(pcm); -- if (pcm->stream == SND_PCM_STREAM_PLAYBACK) -- *delayp = snd_pcm_mmap_playback_hw_avail(pcm); -- else -- *delayp = snd_pcm_mmap_capture_hw_avail(pcm); -+ *delayp = snd_pcm_mmap_hw_avail(pcm); - return 0; - } - --- -1.9.3 - - -From 4fafa468d4bb4618cfde7183f820d8fdd373dcb1 Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Sun, 14 Sep 2014 00:30:17 +0600 -Subject: [PATCH 29/35] pcm, null: use the snd_pcm_mmap_avail function - -instead of the open-coded equivalent - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_null.c | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c -index f11a102..0529820 100644 ---- a/src/pcm/pcm_null.c -+++ b/src/pcm/pcm_null.c -@@ -86,10 +86,7 @@ static snd_pcm_sframes_t snd_pcm_null_avail_update(snd_pcm_t *pcm) - if (null->state == SND_PCM_STATE_PREPARED) { - /* it is required to return the correct avail count for */ - /* the prepared stream, otherwise the start is not called */ -- if (pcm->stream == SND_PCM_STREAM_PLAYBACK) -- return snd_pcm_mmap_playback_avail(pcm); -- else -- return snd_pcm_mmap_capture_avail(pcm); -+ return snd_pcm_mmap_avail(pcm); - } - return pcm->buffer_size; - } --- -1.9.3 - - -From ff9d213ff80f6fe0456565d4f524366443217174 Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Sun, 14 Sep 2014 00:30:18 +0600 -Subject: [PATCH 30/35] rate: handle negative values from - snd_pcm_mmap_playback_hw_avail - -Such negative returns are possible during an underrun if xrun detection -is disabled. - -So, don't store the result in an unsigned variable (where it will -overflow), and postpone the trigger in such case, too. - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_rate.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c -index b436a8e..736d558 100644 ---- a/src/pcm/pcm_rate.c -+++ b/src/pcm/pcm_rate.c -@@ -1058,7 +1058,7 @@ static snd_pcm_state_t snd_pcm_rate_state(snd_pcm_t *pcm) - static int snd_pcm_rate_start(snd_pcm_t *pcm) - { - snd_pcm_rate_t *rate = pcm->private_data; -- snd_pcm_uframes_t avail; -+ snd_pcm_sframes_t avail; - - if (pcm->stream == SND_PCM_STREAM_CAPTURE) - return snd_pcm_start(rate->gen.slave); -@@ -1069,7 +1069,7 @@ static int snd_pcm_rate_start(snd_pcm_t *pcm) - gettimestamp(&rate->trigger_tstamp, pcm->tstamp_type); - - avail = snd_pcm_mmap_playback_hw_avail(rate->gen.slave); -- if (avail == 0) { -+ if (avail <= 0) { - /* postpone the trigger since we have no data committed yet */ - rate->start_pending = 1; - return 0; --- -1.9.3 - - -From e5e1af83881e4dbe20749a314703db7d0fd091c7 Mon Sep 17 00:00:00 2001 -From: "Alexander E. Patrakov" -Date: Sun, 14 Sep 2014 00:30:19 +0600 -Subject: [PATCH 31/35] dsnoop: rewindable and forwardable logic was swapped - -Signed-off-by: Alexander E. Patrakov -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dsnoop.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c -index e56e402..8333eef 100644 ---- a/src/pcm/pcm_dsnoop.c -+++ b/src/pcm/pcm_dsnoop.c -@@ -335,7 +335,7 @@ static int snd_pcm_dsnoop_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTR - - static snd_pcm_sframes_t snd_pcm_dsnoop_rewindable(snd_pcm_t *pcm) - { -- return snd_pcm_mmap_capture_avail(pcm); -+ return snd_pcm_mmap_capture_hw_avail(pcm); - } - - static snd_pcm_sframes_t snd_pcm_dsnoop_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) -@@ -351,7 +351,7 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t - - static snd_pcm_sframes_t snd_pcm_dsnoop_forwardable(snd_pcm_t *pcm) - { -- return snd_pcm_mmap_capture_hw_avail(pcm); -+ return snd_pcm_mmap_capture_avail(pcm); - } - - static snd_pcm_sframes_t snd_pcm_dsnoop_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) -@@ -359,8 +359,6 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_forward(snd_pcm_t *pcm, snd_pcm_uframes_ - snd_pcm_sframes_t avail; - - avail = snd_pcm_dsnoop_forwardable(pcm); -- if (avail < 0) -- return 0; - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - snd_pcm_mmap_appl_forward(pcm, frames); --- -1.9.3 - - -From 650b8c975cd5c3f7dca6e78e74db587b57bcdfd8 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Tue, 16 Sep 2014 09:00:39 +0200 -Subject: [PATCH 35/35] pcm route: Fix the bad condition (always false) - ---- - src/pcm/pcm_route.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c -index e7de9b5..2a437e8 100644 ---- a/src/pcm/pcm_route.c -+++ b/src/pcm/pcm_route.c -@@ -1147,7 +1147,7 @@ static int _snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_ent - 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 || --- -1.9.3 - diff --git a/SOURCES/alsa-lib-1.1.0-config.patch b/SOURCES/alsa-lib-1.1.0-config.patch new file mode 100644 index 0000000..76aaa8e --- /dev/null +++ b/SOURCES/alsa-lib-1.1.0-config.patch @@ -0,0 +1,40 @@ +--- alsa-lib-1.1.0/src/conf/alsa.conf.config 2016-01-12 13:07:56.904218949 +0100 ++++ alsa-lib-1.1.0/src/conf/alsa.conf 2016-01-12 13:09:16.164164628 +0100 +@@ -73,8 +73,7 @@ + defaults.pcm.compat 0 + defaults.pcm.minperiodtime 5000 # in us + defaults.pcm.ipc_key 5678293 +-defaults.pcm.ipc_gid audio +-defaults.pcm.ipc_perm 0660 ++defaults.pcm.ipc_perm 0600 + defaults.pcm.dmix.max_periods 0 + defaults.pcm.dmix.rate 48000 + defaults.pcm.dmix.format "unchanged" +diff -ruNp alsa-lib-1.0.17.orig/src/conf/pcm/dmix.conf alsa-lib-1.0.17/src/conf/pcm/dmix.conf +--- alsa-lib-1.0.17.orig/src/conf/pcm/dmix.conf 2008-07-14 10:57:56.000000000 +0200 ++++ alsa-lib-1.0.17/src/conf/pcm/dmix.conf 2008-07-21 11:51:45.000000000 +0200 +@@ -41,10 +41,6 @@ pcm.!dmix { + @func refer + name defaults.pcm.ipc_key + } +- ipc_gid { +- @func refer +- name defaults.pcm.ipc_gid +- } + ipc_perm { + @func refer + name defaults.pcm.ipc_perm +diff -ruNp alsa-lib-1.0.17.orig/src/conf/pcm/dsnoop.conf alsa-lib-1.0.17/src/conf/pcm/dsnoop.conf +--- alsa-lib-1.0.17.orig/src/conf/pcm/dsnoop.conf 2008-07-14 10:57:56.000000000 +0200 ++++ alsa-lib-1.0.17/src/conf/pcm/dsnoop.conf 2008-07-21 11:51:45.000000000 +0200 +@@ -41,10 +41,6 @@ pcm.!dsnoop { + @func refer + name defaults.pcm.ipc_key + } +- ipc_gid { +- @func refer +- name defaults.pcm.ipc_gid +- } + ipc_perm { + @func refer + name defaults.pcm.ipc_perm diff --git a/SOURCES/alsa-lib-1.1.1-post.patch b/SOURCES/alsa-lib-1.1.1-post.patch new file mode 100644 index 0000000..0227a2d --- /dev/null +++ b/SOURCES/alsa-lib-1.1.1-post.patch @@ -0,0 +1,6314 @@ +From 7c424edd116e76eee6218a1e9a6ff6c4daaf2a4d Mon Sep 17 00:00:00 2001 +From: Shengjiu Wang +Date: Wed, 6 Apr 2016 19:02:12 +0800 +Subject: [PATCH 01/34] pcm_plugin: fix appl pointer not correct when + mmap_commit() return error + +When snd_pcm_mmap_commit() return error, the appl pointer is also updated. +which cause the avail_update()'s result wrong. +This patch move the snd_pcm_mmap_appl_forward() to the place when +snd_pcm_mmap_commit() is successfully returned. + +Signed-off-by: Shengjiu Wang +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_plugin.c | 48 ++++++++++++++++++++++++++++++++---------------- + 1 file changed, 32 insertions(+), 16 deletions(-) + +diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c +index d007e8c..940491d 100644 +--- a/src/pcm/pcm_plugin.c ++++ b/src/pcm/pcm_plugin.c +@@ -279,18 +279,22 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm, + return -EPIPE; + } + snd_atomic_write_begin(&plugin->watom); +- snd_pcm_mmap_appl_forward(pcm, frames); + result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); + if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) { + snd_pcm_sframes_t res; + res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result); +- if (res < 0) ++ if (res < 0) { ++ snd_atomic_write_end(&plugin->watom); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : res; ++ } + frames -= res; + } +- snd_atomic_write_end(&plugin->watom); +- if (result <= 0) ++ if (result <= 0) { ++ snd_atomic_write_end(&plugin->watom); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : result; ++ } ++ snd_pcm_mmap_appl_forward(pcm, frames); ++ snd_atomic_write_end(&plugin->watom); + offset += frames; + xfer += frames; + size -= frames; +@@ -325,19 +329,23 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, + return -EPIPE; + } + snd_atomic_write_begin(&plugin->watom); +- snd_pcm_mmap_appl_forward(pcm, frames); + result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); + if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) { + snd_pcm_sframes_t res; + + res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result); +- if (res < 0) ++ if (res < 0) { ++ snd_atomic_write_end(&plugin->watom); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : res; ++ } + frames -= res; + } +- snd_atomic_write_end(&plugin->watom); +- if (result <= 0) ++ if (result <= 0) { ++ snd_atomic_write_end(&plugin->watom); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : result; ++ } ++ snd_pcm_mmap_appl_forward(pcm, frames); ++ snd_atomic_write_end(&plugin->watom); + offset += frames; + xfer += frames; + size -= frames; +@@ -423,19 +431,23 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, + frames = plugin->write(pcm, areas, appl_offset, frames, + slave_areas, slave_offset, &slave_frames); + snd_atomic_write_begin(&plugin->watom); +- snd_pcm_mmap_appl_forward(pcm, frames); + result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); +- snd_atomic_write_end(&plugin->watom); + if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) { + snd_pcm_sframes_t res; + + res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result); +- if (res < 0) ++ if (res < 0) { ++ snd_atomic_write_end(&plugin->watom); + return xfer > 0 ? xfer : res; ++ } + frames -= res; + } +- if (result <= 0) ++ if (result <= 0) { ++ snd_atomic_write_end(&plugin->watom); + return xfer > 0 ? xfer : result; ++ } ++ snd_pcm_mmap_appl_forward(pcm, frames); ++ snd_atomic_write_end(&plugin->watom); + if (frames == cont) + appl_offset = 0; + else +@@ -490,19 +502,23 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) + frames = (plugin->read)(pcm, areas, hw_offset, frames, + slave_areas, slave_offset, &slave_frames); + snd_atomic_write_begin(&plugin->watom); +- snd_pcm_mmap_hw_forward(pcm, frames); + result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); +- snd_atomic_write_end(&plugin->watom); + if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) { + snd_pcm_sframes_t res; + + res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result); +- if (res < 0) ++ if (res < 0) { ++ snd_atomic_write_end(&plugin->watom); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : res; ++ } + frames -= res; + } +- if (result <= 0) ++ if (result <= 0) { ++ snd_atomic_write_end(&plugin->watom); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : result; ++ } ++ snd_pcm_mmap_hw_forward(pcm, frames); ++ snd_atomic_write_end(&plugin->watom); + if (frames == cont) + hw_offset = 0; + else +-- +2.5.5 + +From 503a285ed60164d8c65c6ee9ba6f23631da753df Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 7 Apr 2016 16:29:41 +0200 +Subject: [PATCH 02/34] pcm: Clean up error paths in snd_pcm_plugin_*() helpers + +Minor code refactoring to unify the error return paths. + +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_plugin.c | 67 +++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 45 insertions(+), 22 deletions(-) + +diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c +index 940491d..8527783 100644 +--- a/src/pcm/pcm_plugin.c ++++ b/src/pcm/pcm_plugin.c +@@ -276,7 +276,8 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm, + if (CHECK_SANITY(slave_frames > snd_pcm_mmap_playback_avail(slave))) { + SNDMSG("write overflow %ld > %ld", slave_frames, + snd_pcm_mmap_playback_avail(slave)); +- return -EPIPE; ++ err = -EPIPE; ++ goto error; + } + snd_atomic_write_begin(&plugin->watom); + result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); +@@ -284,14 +285,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm, + snd_pcm_sframes_t res; + res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result); + if (res < 0) { +- snd_atomic_write_end(&plugin->watom); +- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res; ++ err = res; ++ goto error_atomic; + } + frames -= res; + } + if (result <= 0) { +- snd_atomic_write_end(&plugin->watom); +- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result; ++ err = result; ++ goto error_atomic; + } + snd_pcm_mmap_appl_forward(pcm, frames); + snd_atomic_write_end(&plugin->watom); +@@ -300,6 +301,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm, + size -= frames; + } + return (snd_pcm_sframes_t)xfer; ++ ++ error_atomic: ++ snd_atomic_write_end(&plugin->watom); ++ error: ++ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; + } + + static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, +@@ -311,6 +317,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, + snd_pcm_t *slave = plugin->gen.slave; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t result; ++ int err; + + while (size > 0) { + snd_pcm_uframes_t frames = size; +@@ -326,7 +333,8 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, + if (CHECK_SANITY(slave_frames > snd_pcm_mmap_capture_avail(slave))) { + SNDMSG("read overflow %ld > %ld", slave_frames, + snd_pcm_mmap_playback_avail(slave)); +- return -EPIPE; ++ err = -EPIPE; ++ goto error; + } + snd_atomic_write_begin(&plugin->watom); + result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); +@@ -335,14 +343,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, + + res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result); + if (res < 0) { +- snd_atomic_write_end(&plugin->watom); +- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res; ++ err = res; ++ goto error_atomic; + } + frames -= res; + } + if (result <= 0) { +- snd_atomic_write_end(&plugin->watom); +- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result; ++ err = result; ++ goto error_atomic; + } + snd_pcm_mmap_appl_forward(pcm, frames); + snd_atomic_write_end(&plugin->watom); +@@ -351,6 +359,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, + size -= frames; + } + return (snd_pcm_sframes_t)xfer; ++ ++ error_atomic: ++ snd_atomic_write_end(&plugin->watom); ++ error: ++ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; + } + + +@@ -401,6 +414,7 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, + snd_pcm_uframes_t appl_offset; + snd_pcm_sframes_t slave_size; + snd_pcm_sframes_t xfer; ++ int err; + + if (pcm->stream == SND_PCM_STREAM_CAPTURE) { + snd_atomic_write_begin(&plugin->watom); +@@ -421,11 +435,10 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, + snd_pcm_uframes_t slave_offset; + snd_pcm_uframes_t slave_frames = ULONG_MAX; + snd_pcm_sframes_t result; +- int err; + + err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames); + if (err < 0) +- return xfer > 0 ? xfer : err; ++ goto error; + if (frames > cont) + frames = cont; + frames = plugin->write(pcm, areas, appl_offset, frames, +@@ -437,14 +450,14 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, + + res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result); + if (res < 0) { +- snd_atomic_write_end(&plugin->watom); +- return xfer > 0 ? xfer : res; ++ err = res; ++ goto error_atomic; + } + frames -= res; + } + if (result <= 0) { +- snd_atomic_write_end(&plugin->watom); +- return xfer > 0 ? xfer : result; ++ err = result; ++ goto error_atomic; + } + snd_pcm_mmap_appl_forward(pcm, frames); + snd_atomic_write_end(&plugin->watom); +@@ -461,6 +474,11 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, + return -EPIPE; + } + return xfer; ++ ++ error_atomic: ++ snd_atomic_write_end(&plugin->watom); ++ error: ++ return xfer > 0 ? xfer : err; + } + + static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) +@@ -468,6 +486,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) + snd_pcm_plugin_t *plugin = pcm->private_data; + snd_pcm_t *slave = plugin->gen.slave; + snd_pcm_sframes_t slave_size; ++ int err; + + slave_size = snd_pcm_avail_update(slave); + if (pcm->stream == SND_PCM_STREAM_CAPTURE && +@@ -492,11 +511,10 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) + snd_pcm_uframes_t slave_offset; + snd_pcm_uframes_t slave_frames = ULONG_MAX; + snd_pcm_sframes_t result; +- int err; + + err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames); + if (err < 0) +- return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; ++ goto error; + if (frames > cont) + frames = cont; + frames = (plugin->read)(pcm, areas, hw_offset, frames, +@@ -508,14 +526,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) + + res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result); + if (res < 0) { +- snd_atomic_write_end(&plugin->watom); +- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res; ++ err = res; ++ goto error_atomic; + } + frames -= res; + } + if (result <= 0) { +- snd_atomic_write_end(&plugin->watom); +- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result; ++ err = result; ++ goto error_atomic; + } + snd_pcm_mmap_hw_forward(pcm, frames); + snd_atomic_write_end(&plugin->watom); +@@ -528,6 +546,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) + xfer += frames; + } + return (snd_pcm_sframes_t)xfer; ++ ++ error_atomic: ++ snd_atomic_write_end(&plugin->watom); ++ error: ++ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; + } + } + +-- +2.5.5 + +From 374c5fa9c5cb80efa41ef8a3afd215aa48b48436 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Thu, 7 Apr 2016 15:28:42 +0800 +Subject: [PATCH 03/34] topology: Use the generic pointer to free an element's + object + +The element is a wrapper for different types of objects.So use the +generic pointer 'obj' instead of the type-specific pointer to free +the object. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + src/topology/elem.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/topology/elem.c b/src/topology/elem.c +index 12d6a72..00f9eea 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -83,8 +83,8 @@ void tplg_elem_free(struct tplg_elem *elem) + /* free struct snd_tplg_ object, + * the union pointers share the same address + */ +- if (elem->mixer_ctrl) +- free(elem->mixer_ctrl); ++ if (elem->obj) ++ free(elem->obj); + + free(elem); + } +-- +2.5.5 + +From 6b31bf8edb407f4c184576909f40c41bdc8439e4 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Thu, 7 Apr 2016 15:29:01 +0800 +Subject: [PATCH 04/34] topology: Define a free handler for the element + +This handler is defined for type-specific destruction of an element. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + src/topology/elem.c | 6 +++++- + src/topology/tplg_local.h | 2 ++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/topology/elem.c b/src/topology/elem.c +index 00f9eea..f2afaaf 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -83,8 +83,12 @@ void tplg_elem_free(struct tplg_elem *elem) + /* free struct snd_tplg_ object, + * the union pointers share the same address + */ +- if (elem->obj) ++ if (elem->obj) { ++ if (elem->free) ++ elem->free(elem->obj); ++ + free(elem->obj); ++ } + + free(elem); + } +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 4915b1a..7368a86 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -127,6 +127,8 @@ struct tplg_elem { + */ + struct list_head ref_list; + struct list_head list; /* list of all elements with same type */ ++ ++ void (*free)(void *obj); + }; + + struct map_elem { +-- +2.5.5 + +From 2fd8d388f530b03872d8afb51b0f98c6474646c7 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Thu, 7 Apr 2016 15:29:15 +0800 +Subject: [PATCH 05/34] topology: Add doc for vendor tuples + +Describe how to define vendor tokens and tuples in the text conf file. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + include/topology.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 73 insertions(+), 4 deletions(-) + +diff --git a/include/topology.h b/include/topology.h +index 011f6ae..51d282f 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -203,12 +203,77 @@ extern "C" { + * bytes "0x12,0x34,0x56,0x78" + * shorts "0x1122,0x3344,0x5566,0x7788" + * words "0xaabbccdd,0x11223344,0x66aa77bb,0xefef1234" ++ * tuples "section id of the vendor tuples" + * }; + * +- * 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. ++ * The file, bytes, shorts, words and tuples 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, words or tuples keywords. ++ * The keyword tuples is to define vendor specific tuples. Please refer to ++ * section Vendor Tokens and Vendor tuples. ++ * ++ *
Vendor Tokens
++ * A vendor token list is defined as a new section. Each token element is ++ * a pair of string ID and integer value. And both the ID and value are ++ * vendor-specific. ++ * ++ *
++ * SectionVendorTokens."id of the vendor tokens" {
++ *	comment "optional comments"
++ *	VENDOR_TOKEN_ID1 "1"
++ *	VENDOR_TOKEN_ID2 "2"
++ *	VENDOR_TOKEN_ID3 "3"
++ *	...
++ * }
++ * 
++ * ++ *
Vendor Tuples
++ * Vendor tuples are defined as a new section. It contains a reference to ++ * a vendor token list and several tuple arrays. ++ * All arrays share a vendor token list, defined by the tokens keyword. ++ * Each tuple array is for a specific type, defined by the string following ++ * the tuples keyword. Supported types are: string, uuid, bool, byte, ++ * short and word. ++ * ++ *
++ * SectionVendorTuples."id of the vendor tuples" {
++ *	tokens "id of the vendor tokens"
++ *
++ *	tuples."string" {
++ *		VENDOR_TOKEN_ID1 "character string"
++ *		...
++ *	}
++ *
++ *	tuples."uuid" {
++ *		VENDOR_TOKEN_ID2 "16 character uuid"
++ *		...
++ *	}
++ *
++ *	tuples."bool" {
++ *		VENDOR_TOKEN_ID3 "true/false"
++ *		...
++ *	}
++ *
++ *	tuples."byte" {
++ *		VENDOR_TOKEN_ID4 "0x11"
++ *		VENDOR_TOKEN_ID5 "0x22"
++ *		...
++ *	}
++ *
++ *	tuples."short" {
++ *		VENDOR_TOKEN_ID6 "0x1122"
++ *		VENDOR_TOKEN_ID7 "0x3344"
++ *		...
++ *	}
++ *
++ *	tuples."word" {
++ *		VENDOR_TOKEN_ID8 "0x11223344"
++ *		VENDOR_TOKEN_ID9 "0x55667788"
++ *		...
++ *	}
++ * }
++ * 
+ * + *
Mixer Controls
+ * A mixer control is defined as a new section that can include channel mapping, +@@ -389,6 +454,10 @@ extern "C" { + * fields are the same for widgets as they are for controls whilst the other + * fields map on very closely to the driver widget fields. + * ++ *
Widget Private Data
++ * Widget can have private data. For the format of the private data, please ++ * refer to section Control Private Data. ++ * + *

PCM Capabilities

+ * Topology can also define the capabilities of FE and BE PCMs. Capabilities + * can be defined with the following section :- +-- +2.5.5 + +From 768a006089fab94d5aeffd9115da3fbe951a94f8 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Thu, 7 Apr 2016 15:29:27 +0800 +Subject: [PATCH 06/34] topology: ABI - Define types for vendor tuples + +Tuples, a pair of token and value, can be used to define vendor specific +data, for controls and widgets. This can avoid importing binary data blob +from other files. + +Vendor specific tuple arrays will be embeded in the private data buffer +of a control or widget object. To be backward compatible, union is used +to define the tuple arrays in the existing private data ABI object +'struct snd_soc_tplg_private'. + +Vendors need to make sure the token values defined by the topology conf +file match those defined by their driver. + +Now supported tuple types are uuid, string, bool, byte, short and word. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + include/sound/asoc.h | 42 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 41 insertions(+), 1 deletion(-) + +diff --git a/include/sound/asoc.h b/include/sound/asoc.h +index a29c05c..920c9e0 100644 +--- a/include/sound/asoc.h ++++ b/include/sound/asoc.h +@@ -107,6 +107,14 @@ + #define SND_SOC_TPLG_STREAM_PLAYBACK 0 + #define SND_SOC_TPLG_STREAM_CAPTURE 1 + ++/* vendor tuple types */ ++#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0 ++#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1 ++#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2 ++#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3 ++#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 ++#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5 ++ + /* + * Block Header. + * This header precedes all object and object arrays below. +@@ -123,6 +131,35 @@ struct snd_soc_tplg_hdr { + __le32 count; /* number of elements in block */ + } __attribute__((packed)); + ++/* vendor tuple for uuid */ ++struct snd_soc_tplg_vendor_uuid_elem { ++ __le32 token; ++ char uuid[16]; ++} __attribute__((packed)); ++ ++/* vendor tuple for a bool/byte/short/word value */ ++struct snd_soc_tplg_vendor_value_elem { ++ __le32 token; ++ __le32 value; ++} __attribute__((packed)); ++ ++/* vendor tuple for string */ ++struct snd_soc_tplg_vendor_string_elem { ++ __le32 token; ++ char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++} __attribute__((packed)); ++ ++struct snd_soc_tplg_vendor_array { ++ __le32 size; /* size in bytes of the array, including all elements */ ++ __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */ ++ __le32 num_elems; /* number of elements in array */ ++ union { ++ struct snd_soc_tplg_vendor_uuid_elem uuid[0]; ++ struct snd_soc_tplg_vendor_value_elem value[0]; ++ struct snd_soc_tplg_vendor_string_elem string[0]; ++ }; ++} __attribute__((packed)); ++ + /* + * Private data. + * All topology objects may have private data that can be used by the driver or +@@ -130,7 +167,10 @@ struct snd_soc_tplg_hdr { + */ + struct snd_soc_tplg_private { + __le32 size; /* in bytes of private data */ +- char data[0]; ++ union { ++ char data[0]; ++ struct snd_soc_tplg_vendor_array array[0]; ++ }; + } __attribute__((packed)); + + /* +-- +2.5.5 + +From 9b751b38cbb60bfb08ee796a59d72f40e3cd196d Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Thu, 7 Apr 2016 15:29:36 +0800 +Subject: [PATCH 07/34] topology: Add support for vendor tokens + +Vendor can define a token list in SectionVendorTokens. Each token element +is a pair of string ID and integer value. And both the ID and value are +vendor-specific. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + include/topology.h | 1 + + src/topology/data.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ + src/topology/elem.c | 3 +++ + src/topology/parser.c | 10 ++++++++++ + src/topology/tplg_local.h | 15 ++++++++++++++ + 5 files changed, 79 insertions(+) + +diff --git a/include/topology.h b/include/topology.h +index 51d282f..0df112c 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -578,6 +578,7 @@ enum snd_tplg_type { + SND_TPLG_TYPE_BE, /*!< BE DAI link */ + SND_TPLG_TYPE_CC, /*!< Hostless codec <-> codec link */ + SND_TPLG_TYPE_MANIFEST, /*!< Topology manifest */ ++ SND_TPLG_TYPE_TOKEN, /*!< Vendor tokens */ + }; + + /** +diff --git a/src/topology/data.c b/src/topology/data.c +index 370c0fa..8455c15 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -253,6 +253,56 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, + return ret; + } + ++/* Parse vendor tokens ++ */ ++int tplg_parse_tokens(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, *value; ++ struct tplg_elem *elem; ++ struct tplg_vendor_tokens *tokens; ++ int num_tokens = 0; ++ ++ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TOKEN); ++ if (!elem) ++ return -ENOMEM; ++ ++ snd_config_for_each(i, next, cfg) { ++ num_tokens++; ++ } ++ ++ if (!num_tokens) ++ return 0; ++ ++ tplg_dbg(" Vendor tokens: %s, %d tokens\n", elem->id, num_tokens); ++ ++ tokens = calloc(1, sizeof(*tokens) ++ + num_tokens * sizeof(struct tplg_token)); ++ if (!tokens) ++ return -ENOMEM; ++ elem->tokens = tokens; ++ ++ snd_config_for_each(i, next, cfg) { ++ ++ n = snd_config_iterator_entry(i); ++ if (snd_config_get_id(n, &id) < 0) ++ continue; ++ ++ if (snd_config_get_string(n, &value) < 0) ++ continue; ++ ++ elem_copy_text(tokens->token[tokens->num_tokens].id, id, ++ SNDRV_CTL_ELEM_ID_NAME_MAXLEN); ++ tokens->token[tokens->num_tokens].value = atoi(value); ++ tplg_dbg("\t\t %s : %d\n", tokens->token[tokens->num_tokens].id, ++ tokens->token[tokens->num_tokens].value); ++ tokens->num_tokens++; ++ } ++ ++ return 0; ++} + + /* Parse Private data. + * +diff --git a/src/topology/elem.c b/src/topology/elem.c +index f2afaaf..95e3fd4 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -193,6 +193,9 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + list_add_tail(&elem->list, &tplg->cc_list); + obj_size = sizeof(struct snd_soc_tplg_link_config); + break; ++ case SND_TPLG_TYPE_TOKEN: ++ list_add_tail(&elem->list, &tplg->token_list); ++ break; + default: + free(elem); + return NULL; +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 4546257..264abc8 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -173,6 +173,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + continue; + } + ++ if (strcmp(id, "SectionVendorTokens") == 0) { ++ err = tplg_parse_compound(tplg, n, tplg_parse_tokens, ++ NULL); ++ if (err < 0) ++ return err; ++ continue; ++ } ++ + SNDERR("error: unknown section %s\n", id); + } + return 0; +@@ -407,6 +415,7 @@ snd_tplg_t *snd_tplg_new(void) + INIT_LIST_HEAD(&tplg->mixer_list); + INIT_LIST_HEAD(&tplg->enum_list); + INIT_LIST_HEAD(&tplg->bytes_ext_list); ++ INIT_LIST_HEAD(&tplg->token_list); + + return tplg; + } +@@ -426,6 +435,7 @@ void snd_tplg_free(snd_tplg_t *tplg) + tplg_elem_free_list(&tplg->mixer_list); + tplg_elem_free_list(&tplg->enum_list); + tplg_elem_free_list(&tplg->bytes_ext_list); ++ tplg_elem_free_list(&tplg->token_list); + + free(tplg); + } +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 7368a86..679bfff 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -69,6 +69,7 @@ struct snd_tplg { + struct list_head route_list; + struct list_head text_list; + struct list_head pdata_list; ++ struct list_head token_list; + struct list_head pcm_config_list; + struct list_head pcm_caps_list; + +@@ -86,6 +87,16 @@ struct tplg_ref { + struct list_head list; + }; + ++/* element for vendor tokens */ ++struct tplg_token { ++ char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ unsigned int value; ++}; ++ ++struct tplg_vendor_tokens { ++ unsigned int num_tokens; ++ struct tplg_token token[0]; ++}; + /* topology element */ + struct tplg_elem { + +@@ -118,6 +129,7 @@ struct tplg_elem { + /* these do not map to UAPI structs but are internal only */ + struct snd_soc_tplg_ctl_tlv *tlv; + struct snd_soc_tplg_private *data; ++ struct tplg_vendor_tokens *tokens; + }; + + /* an element may refer to other elements: +@@ -151,6 +163,9 @@ int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg, + int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + void *private ATTRIBUTE_UNUSED); + ++int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, ++ void *private ATTRIBUTE_UNUSED); ++ + int tplg_parse_control_bytes(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); + +-- +2.5.5 + +From fdb9a6d19f8b7cc8252d27e83907d8d1c5e4b53d Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Thu, 7 Apr 2016 15:29:43 +0800 +Subject: [PATCH 08/34] topology: Add support for parsing vendor tuples + +Vendor can define several tuple arrays in 'SectionVendorTuples', as +well as the reference to a vendor token list object. + +A later patche will copy vendor tuples in ABI format to the private +buffer of its parent data object in the building phase. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + include/topology.h | 1 + + src/topology/data.c | 240 +++++++++++++++++++++++++++++++++++++++++++++- + src/topology/elem.c | 4 + + src/topology/parser.c | 10 ++ + src/topology/tplg_local.h | 29 ++++++ + 5 files changed, 283 insertions(+), 1 deletion(-) + +diff --git a/include/topology.h b/include/topology.h +index 0df112c..b47f422 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -579,6 +579,7 @@ enum snd_tplg_type { + SND_TPLG_TYPE_CC, /*!< Hostless codec <-> codec link */ + SND_TPLG_TYPE_MANIFEST, /*!< Topology manifest */ + SND_TPLG_TYPE_TOKEN, /*!< Vendor tokens */ ++ SND_TPLG_TYPE_TUPLE, /*!< Vendor tuples */ + }; + + /** +diff --git a/src/topology/data.c b/src/topology/data.c +index 8455c15..606fcd3 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -253,6 +253,175 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, + return ret; + } + ++static int parse_tuple_set(snd_tplg_t *tplg, snd_config_t *cfg, ++ struct tplg_tuple_set **s) ++{ ++ snd_config_iterator_t i, next; ++ snd_config_t *n; ++ const char *id, *value; ++ struct tplg_tuple_set *set; ++ unsigned int type, num_tuples = 0; ++ struct tplg_tuple *tuple; ++ unsigned long int tuple_val; ++ int len; ++ ++ snd_config_get_id(cfg, &id); ++ ++ if (strcmp(id, "uuid") == 0) ++ type = SND_SOC_TPLG_TUPLE_TYPE_UUID; ++ else if (strcmp(id, "string") == 0) ++ type = SND_SOC_TPLG_TUPLE_TYPE_STRING; ++ else if (strcmp(id, "bool") == 0) ++ type = SND_SOC_TPLG_TUPLE_TYPE_BOOL; ++ else if (strcmp(id, "byte") == 0) ++ type = SND_SOC_TPLG_TUPLE_TYPE_BYTE; ++ else if (strcmp(id, "short") == 0) ++ type = SND_SOC_TPLG_TUPLE_TYPE_SHORT; ++ else if (strcmp(id, "word") == 0) ++ type = SND_SOC_TPLG_TUPLE_TYPE_WORD; ++ else { ++ SNDERR("error: invalid tuple type '%s'\n", id); ++ return -EINVAL; ++ } ++ ++ snd_config_for_each(i, next, cfg) ++ num_tuples++; ++ if (!num_tuples) ++ return 0; ++ ++ tplg_dbg("\t %d %s tuples:\n", num_tuples, id); ++ set = calloc(1, sizeof(*set) + num_tuples * sizeof(struct tplg_tuple)); ++ if (!set) ++ return -ENOMEM; ++ ++ set->type = type; ++ ++ 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; ++ ++ tuple = &set->tuple[set->num_tuples]; ++ elem_copy_text(tuple->token, id, ++ SNDRV_CTL_ELEM_ID_NAME_MAXLEN); ++ ++ switch (type) { ++ case SND_SOC_TPLG_TUPLE_TYPE_UUID: ++ len = strlen(value); ++ if (len > 16 || len == 0) { ++ SNDERR("error: tuple %s: invalid uuid\n", id); ++ goto err; ++ } ++ ++ memcpy(tuple->uuid, value, len); ++ tplg_dbg("\t\t%s = %s\n", tuple->token, tuple->uuid); ++ break; ++ ++ case SND_SOC_TPLG_TUPLE_TYPE_STRING: ++ elem_copy_text(tuple->string, value, ++ SNDRV_CTL_ELEM_ID_NAME_MAXLEN); ++ tplg_dbg("\t\t%s = %s\n", tuple->token, tuple->string); ++ break; ++ ++ case SND_SOC_TPLG_TUPLE_TYPE_BOOL: ++ if (strcmp(value, "true") == 0) ++ tuple->value = 1; ++ tplg_dbg("\t\t%s = %d\n", tuple->token, tuple->value); ++ break; ++ ++ case SND_SOC_TPLG_TUPLE_TYPE_BYTE: ++ case SND_SOC_TPLG_TUPLE_TYPE_SHORT: ++ case SND_SOC_TPLG_TUPLE_TYPE_WORD: ++ errno = 0; ++ /* no support for negative value */ ++ tuple_val = strtoul(value, NULL, 0); ++ if ((errno == ERANGE && tuple_val == ULONG_MAX) ++ || (errno != 0 && tuple_val == 0)) { ++ SNDERR("error: tuple %s:strtoul fail\n", id); ++ goto err; ++ } ++ ++ if ((type == SND_SOC_TPLG_TUPLE_TYPE_WORD ++ && tuple_val > UINT_MAX) ++ || (type == SND_SOC_TPLG_TUPLE_TYPE_SHORT ++ && tuple_val > USHRT_MAX) ++ || (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE ++ && tuple_val > UCHAR_MAX)) { ++ SNDERR("error: tuple %s: invalid value\n", id); ++ goto err; ++ } ++ ++ tuple->value = (unsigned int) tuple_val; ++ tplg_dbg("\t\t%s = 0x%x\n", tuple->token, tuple->value); ++ break; ++ ++ default: ++ break; ++ } ++ ++ set->num_tuples++; ++ } ++ ++ *s = set; ++ return 0; ++ ++err: ++ free(set); ++ return -EINVAL; ++} ++ ++static int parse_tuple_sets(snd_tplg_t *tplg, snd_config_t *cfg, ++ struct tplg_vendor_tuples *tuples) ++{ ++ snd_config_iterator_t i, next; ++ snd_config_t *n; ++ const char *id; ++ unsigned int num_tuple_sets = 0; ++ int err; ++ ++ if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { ++ SNDERR("error: compound type expected for %s", id); ++ return -EINVAL; ++ } ++ ++ snd_config_for_each(i, next, cfg) { ++ num_tuple_sets++; ++ } ++ ++ if (!num_tuple_sets) ++ return 0; ++ ++ tuples->set = calloc(1, num_tuple_sets * sizeof(void *)); ++ if (!tuples->set) ++ return -ENOMEM; ++ ++ snd_config_for_each(i, next, cfg) { ++ n = snd_config_iterator_entry(i); ++ if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { ++ SNDERR("error: compound type expected for %s, is %d", ++ id, snd_config_get_type(n)); ++ return -EINVAL; ++ } ++ ++ err = parse_tuple_set(tplg, n, &tuples->set[tuples->num_sets]); ++ if (err < 0) ++ return err; ++ ++ /* overlook empty tuple sets */ ++ if (tuples->set[tuples->num_sets]) ++ tuples->num_sets++; ++ } ++ ++ return 0; ++} ++ + /* Parse vendor tokens + */ + int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, +@@ -304,10 +473,71 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* Parse vendor tuples. ++ */ ++int tplg_parse_tuples(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, *value; ++ struct tplg_elem *elem; ++ struct tplg_vendor_tuples *tuples; ++ int err; ++ ++ elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TUPLE); ++ if (!elem) ++ return -ENOMEM; ++ ++ tplg_dbg(" Vendor Tuples: %s\n", elem->id); ++ ++ tuples = calloc(1, sizeof(*tuples)); ++ if (!tuples) ++ return -ENOMEM; ++ elem->tuples = tuples; ++ ++ 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, "tokens") == 0) { ++ if (snd_config_get_string(n, &value) < 0) ++ return -EINVAL; ++ tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, value); ++ tplg_dbg("\t refer to vendor tokens: %s\n", value); ++ } ++ ++ if (strcmp(id, "tuples") == 0) { ++ err = parse_tuple_sets(tplg, n, tuples); ++ if (err < 0) ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++/* Free handler of tuples */ ++void tplg_free_tuples(void *obj) ++{ ++ struct tplg_vendor_tuples *tuples = (struct tplg_vendor_tuples *)obj; ++ int i; ++ ++ if (!tuples || !tuples->set) ++ return; ++ ++ for (i = 0; i < tuples->num_sets; i++) ++ free(tuples->set[i]); ++ ++ free(tuples->set); ++} ++ + /* Parse Private data. + * + * Object private data can either be from file or defined as bytes, shorts, +- * words. ++ * words, tuples. + */ + int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + void *private ATTRIBUTE_UNUSED) +@@ -365,6 +595,14 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + continue; + } + ++ if (strcmp(id, "tuples") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ tplg_dbg(" Data: %s\n", val); ++ tplg_ref_add(elem, SND_TPLG_TYPE_TUPLE, val); ++ continue; ++ } ++ + if (strcmp(id, "index") == 0) { + if (snd_config_get_string(n, &val) < 0) + return -EINVAL; +diff --git a/src/topology/elem.c b/src/topology/elem.c +index 95e3fd4..50414f0 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -196,6 +196,10 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + case SND_TPLG_TYPE_TOKEN: + list_add_tail(&elem->list, &tplg->token_list); + break; ++ case SND_TPLG_TYPE_TUPLE: ++ list_add_tail(&elem->list, &tplg->tuple_list); ++ elem->free = tplg_free_tuples; ++ break; + default: + free(elem); + return NULL; +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 264abc8..0d967b4 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -181,6 +181,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + continue; + } + ++ if (strcmp(id, "SectionVendorTuples") == 0) { ++ err = tplg_parse_compound(tplg, n, tplg_parse_tuples, ++ NULL); ++ if (err < 0) ++ return err; ++ continue; ++ } ++ + SNDERR("error: unknown section %s\n", id); + } + return 0; +@@ -416,6 +424,7 @@ snd_tplg_t *snd_tplg_new(void) + INIT_LIST_HEAD(&tplg->enum_list); + INIT_LIST_HEAD(&tplg->bytes_ext_list); + INIT_LIST_HEAD(&tplg->token_list); ++ INIT_LIST_HEAD(&tplg->tuple_list); + + return tplg; + } +@@ -436,6 +445,7 @@ void snd_tplg_free(snd_tplg_t *tplg) + tplg_elem_free_list(&tplg->enum_list); + tplg_elem_free_list(&tplg->bytes_ext_list); + tplg_elem_free_list(&tplg->token_list); ++ tplg_elem_free_list(&tplg->tuple_list); + + free(tplg); + } +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 679bfff..4d59a1f 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -70,6 +70,7 @@ struct snd_tplg { + struct list_head text_list; + struct list_head pdata_list; + struct list_head token_list; ++ struct list_head tuple_list; + struct list_head pcm_config_list; + struct list_head pcm_caps_list; + +@@ -97,6 +98,28 @@ struct tplg_vendor_tokens { + unsigned int num_tokens; + struct tplg_token token[0]; + }; ++ ++/* element for vendor tuples */ ++struct tplg_tuple { ++ char token[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ union { ++ char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ char uuid[16]; ++ unsigned int value; ++ }; ++}; ++ ++struct tplg_tuple_set { ++ unsigned int type; /* uuid, bool, byte, short, word, string*/ ++ unsigned int num_tuples; ++ struct tplg_tuple tuple[0]; ++}; ++ ++struct tplg_vendor_tuples { ++ unsigned int num_sets; ++ struct tplg_tuple_set **set; ++}; ++ + /* topology element */ + struct tplg_elem { + +@@ -130,6 +153,7 @@ struct tplg_elem { + struct snd_soc_tplg_ctl_tlv *tlv; + struct snd_soc_tplg_private *data; + struct tplg_vendor_tokens *tokens; ++ struct tplg_vendor_tuples *tuples; + }; + + /* an element may refer to other elements: +@@ -166,6 +190,11 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, + void *private ATTRIBUTE_UNUSED); + ++int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, ++ void *private ATTRIBUTE_UNUSED); ++ ++void tplg_free_tuples(void *obj); ++ + int tplg_parse_control_bytes(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); + +-- +2.5.5 + +From 0c5e5c1801e5b1b55e46144ee29ca7a71f2812b0 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Thu, 7 Apr 2016 15:29:49 +0800 +Subject: [PATCH 09/34] topology: Build data objects with tuples + +For data objects with tuples, the parser will bind the vendor tuples +and tokens, copy the tuples to the private buffer of its parent data +object. Then later the builder will export the vendor tuples as private +binary data for the control or widgets objects. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + src/topology/data.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++ + src/topology/parser.c | 4 + + src/topology/tplg_local.h | 1 + + 3 files changed, 218 insertions(+) + +diff --git a/src/topology/data.c b/src/topology/data.c +index 606fcd3..19c31bf 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -253,6 +253,198 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, + return ret; + } + ++/* get the token integer value from its id */ ++static int get_token_value(const char *token_id, ++ struct tplg_vendor_tokens *tokens) ++{ ++ int i; ++ ++ for (i = 0; i < tokens->num_tokens; i++) { ++ if (strcmp(token_id, tokens->token[i].id) == 0) ++ return tokens->token[i].value; ++ } ++ ++ SNDERR("error: cannot find token id '%s'\n", token_id); ++ return -1; ++} ++ ++/* get the vendor tokens referred by the vendor tuples */ ++static struct tplg_elem *get_tokens(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 || ref->type != SND_TPLG_TYPE_TOKEN) ++ continue; ++ ++ if (!ref->elem) { ++ ref->elem = tplg_elem_lookup(&tplg->token_list, ++ ref->id, SND_TPLG_TYPE_TOKEN); ++ } ++ ++ return ref->elem; ++ } ++ ++ return NULL; ++} ++ ++/* check if a data element has tuples */ ++static bool has_tuples(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 && ref->type == SND_TPLG_TYPE_TUPLE) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* get size of a tuple element from its type */ ++static unsigned int get_tuple_size(int type) ++{ ++ switch (type) { ++ ++ case SND_SOC_TPLG_TUPLE_TYPE_UUID: ++ return sizeof(struct snd_soc_tplg_vendor_uuid_elem); ++ ++ case SND_SOC_TPLG_TUPLE_TYPE_STRING: ++ return sizeof(struct snd_soc_tplg_vendor_string_elem); ++ ++ default: ++ return sizeof(struct snd_soc_tplg_vendor_value_elem); ++ } ++} ++ ++/* fill a data element's private buffer with its tuples */ ++static int copy_tuples(struct tplg_elem *elem, ++ struct tplg_vendor_tuples *tuples, struct tplg_vendor_tokens *tokens) ++{ ++ struct snd_soc_tplg_private *priv = elem->data; ++ struct tplg_tuple_set *tuple_set; ++ struct tplg_tuple *tuple; ++ struct snd_soc_tplg_vendor_array *array; ++ struct snd_soc_tplg_vendor_uuid_elem *uuid; ++ struct snd_soc_tplg_vendor_string_elem *string; ++ struct snd_soc_tplg_vendor_value_elem *value; ++ int set_size, size, off; ++ int i, j, token_val; ++ ++ if (priv) { ++ SNDERR("error: %s has more data than tuples\n", elem->id); ++ return -EINVAL; ++ } ++ ++ size = 0; ++ for (i = 0; i < tuples->num_sets ; i++) { ++ tuple_set = tuples->set[i]; ++ set_size = sizeof(struct snd_soc_tplg_vendor_array) ++ + get_tuple_size(tuple_set->type) ++ * tuple_set->num_tuples; ++ size += set_size; ++ if (size > TPLG_MAX_PRIV_SIZE) { ++ SNDERR("error: data too big %d\n", size); ++ return -EINVAL; ++ } ++ ++ if (priv != NULL) ++ priv = realloc(priv, sizeof(*priv) + size); ++ else ++ priv = calloc(1, sizeof(*priv) + size); ++ if (!priv) ++ return -ENOMEM; ++ ++ off = priv->size; ++ priv->size = size; ++ ++ array = (struct snd_soc_tplg_vendor_array *)(priv->data + off); ++ array->size = set_size; ++ array->type = tuple_set->type; ++ array->num_elems = tuple_set->num_tuples; ++ ++ /* fill the private data buffer */ ++ for (j = 0; j < tuple_set->num_tuples; j++) { ++ tuple = &tuple_set->tuple[j]; ++ token_val = get_token_value(tuple->token, tokens); ++ if (token_val < 0) ++ return -EINVAL; ++ ++ switch (tuple_set->type) { ++ case SND_SOC_TPLG_TUPLE_TYPE_UUID: ++ uuid = &array->uuid[j]; ++ uuid->token = token_val; ++ memcpy(uuid->uuid, tuple->uuid, 16); ++ break; ++ ++ case SND_SOC_TPLG_TUPLE_TYPE_STRING: ++ string = &array->string[j]; ++ string->token = token_val; ++ elem_copy_text(string->string, tuple->string, ++ SNDRV_CTL_ELEM_ID_NAME_MAXLEN); ++ break; ++ ++ default: ++ value = &array->value[j]; ++ value->token = token_val; ++ value->value = tuple->value; ++ break; ++ } ++ } ++ } ++ ++ elem->data = priv; ++ return 0; ++} ++ ++/* build a data element from its tuples */ ++static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem) ++{ ++ struct tplg_ref *ref; ++ struct list_head *base, *pos; ++ struct tplg_elem *tuples, *tokens; ++ ++ base = &elem->ref_list; ++ list_for_each(pos, base) { ++ ++ ref = list_entry(pos, struct tplg_ref, list); ++ ++ if (!ref->id || ref->type != SND_TPLG_TYPE_TUPLE) ++ continue; ++ ++ tplg_dbg("look up tuples %s\n", ref->id); ++ ++ if (!ref->elem) ++ ref->elem = tplg_elem_lookup(&tplg->tuple_list, ++ ref->id, SND_TPLG_TYPE_TUPLE); ++ tuples = ref->elem; ++ if (!tuples) ++ return -EINVAL; ++ ++ tplg_dbg("found tuples %s\n", tuples->id); ++ tokens = get_tokens(tplg, tuples); ++ if (!tokens) ++ return -EINVAL; ++ ++ tplg_dbg("found tokens %s\n", tokens->id); ++ /* a data object can only have one tuples object */ ++ return copy_tuples(elem, tuples->tuples, tokens->tokens); ++ } ++ ++ return 0; ++} ++ + static int parse_tuple_set(snd_tplg_t *tplg, snd_config_t *cfg, + struct tplg_tuple_set **s) + { +@@ -683,3 +875,24 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref) + memcpy(priv->data, ref->data->data, priv_data_size); + return 0; + } ++ ++/* check data objects and build those with tuples */ ++int tplg_build_data(snd_tplg_t *tplg) ++{ ++ struct list_head *base, *pos; ++ struct tplg_elem *elem; ++ int err = 0; ++ ++ base = &tplg->pdata_list; ++ list_for_each(pos, base) { ++ ++ elem = list_entry(pos, struct tplg_elem, list); ++ if (has_tuples(elem)) { ++ err = build_tuples(tplg, elem); ++ if (err < 0) ++ return err; ++ } ++ } ++ ++ return 0; ++} +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 0d967b4..30d91f9 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -242,6 +242,10 @@ static int tplg_build_integ(snd_tplg_t *tplg) + { + int err; + ++ err = tplg_build_data(tplg); ++ if (err < 0) ++ return err; ++ + err = tplg_build_controls(tplg); + if (err < 0) + return err; +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 4d59a1f..4c601d4 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -222,6 +222,7 @@ int tplg_parse_be(snd_tplg_t *tplg, + int tplg_parse_cc(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); + ++int tplg_build_data(snd_tplg_t *tplg); + int tplg_build_controls(snd_tplg_t *tplg); + int tplg_build_widgets(snd_tplg_t *tplg); + int tplg_build_routes(snd_tplg_t *tplg); +-- +2.5.5 + +From e57b521c61f0df14b660ce6ba8c5009a63f5b115 Mon Sep 17 00:00:00 2001 +From: Hsin-Yu Chao +Date: Wed, 13 Apr 2016 18:53:09 +0800 +Subject: [PATCH 10/34] ucm: add cset-tlv + +This patch enables UCM to set a file in TLV format to kcontrol by: +cset-tlv "name='' " +This new 'cset-tlv' command will be used to write audio DSP to +specific alsa control, where the driver expectes a file in TLV +format. +The TLV file to set to kcontrol will be checked first by file size +not larger than 16 MB, and then examine if the length field reports +correct number of bytes in the TLV file. + +Signed-off-by: Hsin-Yu Chao +Reviewed-by: Vinod Koul +Signed-off-by: Takashi Iwai +--- + src/ucm/main.c | 94 +++++++++++++++++++++++++++++++++++++++++++++-------- + src/ucm/parser.c | 10 ++++++ + src/ucm/ucm_local.h | 1 + + 3 files changed, 92 insertions(+), 13 deletions(-) + +diff --git a/src/ucm/main.c b/src/ucm/main.c +index 7e44603..24d9510 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -161,6 +161,57 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr, + return 0; + } + ++static int read_tlv_file(unsigned int **res, ++ const char *filepath) ++{ ++ int err = 0; ++ int fd; ++ struct stat st; ++ size_t sz; ++ ssize_t sz_read; ++ struct snd_ctl_tlv *tlv; ++ ++ fd = open(filepath, O_RDONLY); ++ if (fd < 0) { ++ err = -errno; ++ return err; ++ } ++ if (fstat(fd, &st) == -1) { ++ err = -errno; ++ goto __fail; ++ } ++ sz = st.st_size; ++ if (sz > 16 * 1024 * 1024 || sz < 8 || sz % 4) { ++ uc_error("File size should be less than 16 MB " ++ "and multiple of 4"); ++ err = -EINVAL; ++ goto __fail; ++ } ++ *res = malloc(sz); ++ if (res == NULL) { ++ err = -ENOMEM; ++ goto __fail; ++ } ++ sz_read = read(fd, *res, sz); ++ if (sz_read < 0 || (size_t)sz_read != sz) { ++ err = -EIO; ++ free(*res); ++ *res = NULL; ++ } ++ /* Check if the tlv file specifies valid size. */ ++ tlv = (struct snd_ctl_tlv *)(*res); ++ if (tlv->length + 2 * sizeof(unsigned int) != sz) { ++ uc_error("Invalid tlv size: %d", tlv->length); ++ err = -EINVAL; ++ free(*res); ++ *res = NULL; ++ } ++ ++__fail: ++ close(fd); ++ return err; ++} ++ + static int binary_file_parse(snd_ctl_elem_value_t *dst, + snd_ctl_elem_info_t *info, + const char *filepath) +@@ -226,6 +277,7 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type) + snd_ctl_elem_id_t *id; + snd_ctl_elem_value_t *value; + snd_ctl_elem_info_t *info; ++ unsigned int *res = NULL; + + snd_ctl_elem_id_malloc(&id); + snd_ctl_elem_value_malloc(&value); +@@ -241,23 +293,36 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type) + err = -EINVAL; + goto __fail; + } +- snd_ctl_elem_value_set_id(value, id); + snd_ctl_elem_info_set_id(info, id); +- err = snd_ctl_elem_read(ctl, value); +- if (err < 0) +- goto __fail; + err = snd_ctl_elem_info(ctl, info); + if (err < 0) + goto __fail; +- if (type == SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE) +- err = binary_file_parse(value, info, pos); +- else +- err = snd_ctl_ascii_value_parse(ctl, value, info, pos); +- if (err < 0) +- goto __fail; +- err = snd_ctl_elem_write(ctl, value); +- if (err < 0) +- goto __fail; ++ if (type == SEQUENCE_ELEMENT_TYPE_CSET_TLV) { ++ if (!snd_ctl_elem_info_is_tlv_writable(info)) { ++ err = -EINVAL; ++ goto __fail; ++ } ++ err = read_tlv_file(&res, pos); ++ if (err < 0) ++ goto __fail; ++ err = snd_ctl_elem_tlv_write(ctl, id, res); ++ if (err < 0) ++ goto __fail; ++ } else { ++ snd_ctl_elem_value_set_id(value, id); ++ err = snd_ctl_elem_read(ctl, value); ++ if (err < 0) ++ goto __fail; ++ if (type == SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE) ++ err = binary_file_parse(value, info, pos); ++ else ++ err = snd_ctl_ascii_value_parse(ctl, value, info, pos); ++ if (err < 0) ++ goto __fail; ++ err = snd_ctl_elem_write(ctl, value); ++ if (err < 0) ++ goto __fail; ++ } + err = 0; + __fail: + if (id != NULL) +@@ -266,6 +331,8 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type) + free(value); + if (info != NULL) + free(info); ++ if (res != NULL) ++ free(res); + + return err; + } +@@ -298,6 +365,7 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr, + break; + case SEQUENCE_ELEMENT_TYPE_CSET: + case SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE: ++ case SEQUENCE_ELEMENT_TYPE_CSET_TLV: + if (cdev == NULL) { + char *playback_ctl = NULL; + char *capture_ctl = NULL; +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index 8405bd2..13f62d7 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -316,6 +316,16 @@ static int parse_sequence(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, + continue; + } + ++ if (strcmp(cmd, "cset-tlv") == 0) { ++ curr->type = SEQUENCE_ELEMENT_TYPE_CSET_TLV; ++ err = parse_string(n, &curr->data.cset); ++ if (err < 0) { ++ uc_error("error: cset-tlv requires a string!"); ++ return err; ++ } ++ continue; ++ } ++ + if (strcmp(cmd, "usleep") == 0) { + curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP; + err = snd_config_get_integer(n, &curr->data.sleep); +diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h +index 3a5d2c2..b89de2a 100644 +--- a/src/ucm/ucm_local.h ++++ b/src/ucm/ucm_local.h +@@ -48,6 +48,7 @@ + #define SEQUENCE_ELEMENT_TYPE_SLEEP 3 + #define SEQUENCE_ELEMENT_TYPE_EXEC 4 + #define SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE 5 ++#define SEQUENCE_ELEMENT_TYPE_CSET_TLV 6 + + struct ucm_value { + struct list_head list; +-- +2.5.5 + +From fdba9e1bad8f769a6137e565471f0227f23a3132 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 14 Apr 2016 17:33:03 +0200 +Subject: [PATCH 11/34] pcm: Fallback open as the first instance for dmix & co + +dmix and other PCM plugins tries to open a secondary stream with +O_APPEND flag when the shmem was already attached by another. +However, when another streams have been already closed after the +shmem check, this open may return the error EBADFD, since the kernel +accepts O_APPEND only for the secondary streams. + +This patch adds a workaround for such a case. It just retries opening +the stream as the first instance (i.e. without O_APPEND flag). +This is basically safe behavior (the kernel takes care of races), even +we may do this even unconditionally. But it's bad from the +performance POV, so we do it only when really needed. + +Reported-by: Lars Lindqvist +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_dmix.c | 8 ++++++++ + src/pcm/pcm_dshare.c | 8 ++++++++ + src/pcm/pcm_dsnoop.c | 8 ++++++++ + 3 files changed, 24 insertions(+) + +diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c +index b26a5c7..007d356 100644 +--- a/src/pcm/pcm_dmix.c ++++ b/src/pcm/pcm_dmix.c +@@ -1020,6 +1020,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, + dmix->max_periods = opts->max_periods; + dmix->sync_ptr = snd_pcm_dmix_sync_ptr; + ++ retry: + if (first_instance) { + /* recursion is already checked in + snd_pcm_direct_get_slave_ipc_offset() */ +@@ -1076,6 +1077,13 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, + SND_PCM_APPEND, + NULL); + if (ret < 0) { ++ /* all other streams have been closed; ++ * retry as the first instance ++ */ ++ if (ret == -EBADFD) { ++ first_instance = 1; ++ goto retry; ++ } + SNDERR("unable to open slave"); + goto _err; + } +diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c +index 58e47bb..adb3587 100644 +--- a/src/pcm/pcm_dshare.c ++++ b/src/pcm/pcm_dshare.c +@@ -690,6 +690,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, + break; + } + ++ retry: + first_instance = ret = snd_pcm_direct_shm_create_or_connect(dshare); + if (ret < 0) { + SNDERR("unable to create IPC shm instance"); +@@ -758,6 +759,13 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, + SND_PCM_APPEND, + NULL); + if (ret < 0) { ++ /* all other streams have been closed; ++ * retry as the first instance ++ */ ++ if (ret == -EBADFD) { ++ first_instance = 1; ++ goto retry; ++ } + SNDERR("unable to open slave"); + goto _err; + } +diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c +index 576c35b..8ff0ba5 100644 +--- a/src/pcm/pcm_dsnoop.c ++++ b/src/pcm/pcm_dsnoop.c +@@ -583,6 +583,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, + break; + } + ++ retry: + first_instance = ret = snd_pcm_direct_shm_create_or_connect(dsnoop); + if (ret < 0) { + SNDERR("unable to create IPC shm instance"); +@@ -651,6 +652,13 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, + SND_PCM_APPEND, + NULL); + if (ret < 0) { ++ /* all other streams have been closed; ++ * retry as the first instance ++ */ ++ if (ret == -EBADFD) { ++ first_instance = 1; ++ goto retry; ++ } + SNDERR("unable to open slave"); + goto _err; + } +-- +2.5.5 + +From f5c313eae5c26d6843a4f860743151f53b2f4041 Mon Sep 17 00:00:00 2001 +From: Shreyas NC +Date: Thu, 28 Apr 2016 11:07:56 +0530 +Subject: [PATCH 12/34] conf: topology: Add Skylake i2s conf + +The Skylake topology configuration for simple topology graph is +provided. This exposes the PCM capabilities of the DSP. + +Signed-off-by: Shreyas NC +Signed-off-by: Subhransu S. Prusty +Signed-off-by: Vinod Koul +Signed-off-by: Takashi Iwai +--- + configure.ac | 1 + + src/conf/topology/Makefile.am | 2 +- + src/conf/topology/sklrt286/Makefile.am | 4 + + src/conf/topology/sklrt286/codec0_in-cpr-1.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/codec0_in-mi.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/codec0_out-cpr-4.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/codec0_out-mo.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/codec1_out-cpr-5.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/codec1_out-mo.bin | Bin 0 -> 4244 bytes + .../topology/sklrt286/dmic01_hifi_in-cpr-3.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/dmic01_hifi_in-mi.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/hdmi1_pt_out-cpr-7.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/hdmi1_pt_out-cpr-8.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/hdmi2_pt_out-cpr-10.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/hdmi2_pt_out-cpr-9.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/hdmi3_pt_out-cpr-11.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/hdmi3_pt_out-cpr-12.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/media0_in-cpr-0.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/media0_in-mi.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/media0_out-cpr-6.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/media0_out-mo.bin | Bin 0 -> 4244 bytes + src/conf/topology/sklrt286/skl_i2s.conf | 342 +++++++++++++++++++++ + 22 files changed, 348 insertions(+), 1 deletion(-) + create mode 100644 src/conf/topology/sklrt286/Makefile.am + create mode 100644 src/conf/topology/sklrt286/codec0_in-cpr-1.bin + create mode 100644 src/conf/topology/sklrt286/codec0_in-mi.bin + create mode 100644 src/conf/topology/sklrt286/codec0_out-cpr-4.bin + create mode 100644 src/conf/topology/sklrt286/codec0_out-mo.bin + create mode 100644 src/conf/topology/sklrt286/codec1_out-cpr-5.bin + create mode 100644 src/conf/topology/sklrt286/codec1_out-mo.bin + create mode 100644 src/conf/topology/sklrt286/dmic01_hifi_in-cpr-3.bin + create mode 100644 src/conf/topology/sklrt286/dmic01_hifi_in-mi.bin + create mode 100644 src/conf/topology/sklrt286/hdmi1_pt_out-cpr-7.bin + create mode 100644 src/conf/topology/sklrt286/hdmi1_pt_out-cpr-8.bin + create mode 100644 src/conf/topology/sklrt286/hdmi2_pt_out-cpr-10.bin + create mode 100644 src/conf/topology/sklrt286/hdmi2_pt_out-cpr-9.bin + create mode 100644 src/conf/topology/sklrt286/hdmi3_pt_out-cpr-11.bin + create mode 100644 src/conf/topology/sklrt286/hdmi3_pt_out-cpr-12.bin + create mode 100644 src/conf/topology/sklrt286/media0_in-cpr-0.bin + create mode 100644 src/conf/topology/sklrt286/media0_in-mi.bin + create mode 100644 src/conf/topology/sklrt286/media0_out-cpr-6.bin + create mode 100644 src/conf/topology/sklrt286/media0_out-mo.bin + create mode 100644 src/conf/topology/sklrt286/skl_i2s.conf + +diff --git a/configure.ac b/configure.ac +index c265ec9..1bf75e6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -661,6 +661,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \ + src/conf/topology/Makefile \ + src/conf/topology/broadwell/Makefile \ + modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \ ++ src/conf/topology/sklrt286/Makefile \ + alsalisp/Makefile aserver/Makefile \ + test/Makefile test/lsb/Makefile \ + utils/Makefile utils/alsa-lib.spec utils/alsa.pc) +diff --git a/src/conf/topology/Makefile.am b/src/conf/topology/Makefile.am +index f56a96c..cbdb7cf 100644 +--- a/src/conf/topology/Makefile.am ++++ b/src/conf/topology/Makefile.am +@@ -1 +1 @@ +-SUBDIRS=broadwell ++SUBDIRS=broadwell sklrt286 +diff --git a/src/conf/topology/sklrt286/Makefile.am b/src/conf/topology/sklrt286/Makefile.am +new file mode 100644 +index 0000000..facc508 +--- /dev/null ++++ b/src/conf/topology/sklrt286/Makefile.am +@@ -0,0 +1,4 @@ ++alsaconfigdir = @ALSA_CONFIG_DIR@ ++sklrt286dir = $(alsaconfigdir)/topology/sklrt286 ++sklrt286_DATA = skl_i2s.conf media0_in-cpr-0.bin media0_in-mi.bin media0_out-mo.bin media0_out-cpr-6.bin codec0_out-mo.bin codec0_out-cpr-4.bin codec1_out-mo.bin codec1_out-cpr-5.bin codec0_in-cpr-1.bin codec0_in-mi.bin dmic01_hifi_in-cpr-3.bin dmic01_hifi_in-mi.bin hdmi1_pt_out-cpr-7.bin hdmi1_pt_out-cpr-8.bin hdmi2_pt_out-cpr-9.bin hdmi2_pt_out-cpr-10.bin hdmi3_pt_out-cpr-11.bin hdmi3_pt_out-cpr-12.bin ++EXTRA_DIST = $(sklrt286_DATA) +diff --git a/src/conf/topology/sklrt286/skl_i2s.conf b/src/conf/topology/sklrt286/skl_i2s.conf +new file mode 100644 +index 0000000..6da224f +--- /dev/null ++++ b/src/conf/topology/sklrt286/skl_i2s.conf +@@ -0,0 +1,342 @@ ++SectionData."media0_in cpr 0" { ++ file "sklrt286/media0_in-cpr-0.bin" ++} ++SectionData."media0_in mi" { ++ file "sklrt286/media0_in-mi.bin" ++} ++SectionData."media0_out mo" { ++ file "sklrt286/media0_out-mo.bin" ++} ++SectionData."media0_out cpr 6" { ++ file "sklrt286/media0_out-cpr-6.bin" ++} ++SectionData."codec0_out mo" { ++ file "sklrt286/codec0_out-mo.bin" ++} ++SectionData."codec0_out cpr 4" { ++ file "sklrt286/codec0_out-cpr-4.bin" ++} ++SectionData."codec1_out mo" { ++ file "sklrt286/codec1_out-mo.bin" ++} ++SectionData."codec1_out cpr 5" { ++ file "sklrt286/codec1_out-cpr-5.bin" ++} ++SectionData."codec0_in cpr 1" { ++ file "sklrt286/codec0_in-cpr-1.bin" ++} ++SectionData."codec0_in mi" { ++ file "sklrt286/codec0_in-mi.bin" ++} ++SectionData."dmic01_hifi_in cpr 3" { ++ file "sklrt286/dmic01_hifi_in-cpr-3.bin" ++} ++SectionData."dmic01_hifi_in mi" { ++ file "sklrt286/dmic01_hifi_in-mi.bin" ++} ++SectionData."hdmi1_pt_out cpr 7" { ++ file "sklrt286/hdmi1_pt_out-cpr-7.bin" ++} ++SectionData."hdmi1_pt_out cpr 8" { ++ file "sklrt286/hdmi1_pt_out-cpr-8.bin" ++} ++SectionData."hdmi2_pt_out cpr 9" { ++ file "sklrt286/hdmi2_pt_out-cpr-9.bin" ++} ++SectionData."hdmi2_pt_out cpr 10" { ++ file "sklrt286/hdmi2_pt_out-cpr-10.bin" ++} ++SectionData."hdmi3_pt_out cpr 11" { ++ file "sklrt286/hdmi3_pt_out-cpr-11.bin" ++} ++SectionData."hdmi3_pt_out cpr 12" { ++ file "sklrt286/hdmi3_pt_out-cpr-12.bin" ++} ++ ++SectionControlMixer."media0_in mi Switch" { ++ index"1" ++ invert "false" ++ max "1" ++ min"0" ++ no_pm "true" ++ channel."fl" { ++ reg "-1" ++ shift "0" ++ } ++ channel."fr" { ++ reg "-1" ++ shift "0" ++ } ++ ops."ctl" { ++ get "64" ++ put "64" ++ info "64" ++ } ++} ++SectionControlMixer."codec0_in mi Switch" { ++ index"1" ++ invert "false" ++ max "1" ++ min"0" ++ no_pm "true" ++ channel."fl" { ++ reg "-1" ++ shift "0" ++ } ++ channel."fr" { ++ reg "-1" ++ shift "0" ++ } ++ ops."ctl" { ++ get "64" ++ put "64" ++ info "64" ++ } ++} ++SectionControlMixer."dmic01_hifi_in mi Switch" { ++ index"1" ++ invert "false" ++ max "1" ++ min"0" ++ no_pm "true" ++ channel."fl" { ++ reg "-1" ++ shift "0" ++ } ++ channel."fr" { ++ reg "-1" ++ shift "0" ++ } ++ ops."ctl" { ++ get "64" ++ put "64" ++ info "64" ++ } ++} ++ ++ ++SectionWidget."media0_in cpr 0" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "3" ++ event_flags "9" ++ data "media0_in cpr 0" ++} ++SectionWidget."media0_in mi" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ event_flags "9" ++ subseq "10" ++ data "media0_in mi" ++} ++SectionWidget."media0_out mo" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "1" ++ event_flags "15" ++ subseq "10" ++ data "media0_out mo" ++ mixer [ ++ "media0_in mi Switch" ++ "codec0_in mi Switch" ++ "dmic01_hifi_in mi Switch" ++ ] ++} ++SectionWidget."media0_out cpr 6" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ data "media0_out cpr 6" ++} ++SectionWidget."codec0_out mo" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "1" ++ event_flags "15" ++ subseq "10" ++ data "codec0_out mo" ++ mixer [ ++ "media0_in mi Switch" ++ "codec0_in mi Switch" ++ "dmic01_hifi_in mi Switch" ++ ] ++} ++SectionWidget."codec0_out cpr 4" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ data "codec0_out cpr 4" ++} ++SectionWidget."codec0_out" { ++ index"1" ++ type"aif_out" ++ no_pm "true" ++} ++SectionWidget."codec1_out mo" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "1" ++ event_flags "15" ++ subseq "10" ++ data "codec1_out mo" ++ mixer [ ++ "media0_in mi Switch" ++ "codec0_in mi Switch" ++ "dmic01_hifi_in mi Switch" ++ ] ++} ++SectionWidget."codec1_out cpr 5" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ data "codec1_out cpr 5" ++} ++SectionWidget."codec1_out" { ++ index"1" ++ type"aif_out" ++ no_pm "true" ++} ++SectionWidget."codec0_in cpr 1" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "3" ++ event_flags "9" ++ data "codec0_in cpr 1" ++} ++SectionWidget."codec0_in mi" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ event_flags "9" ++ subseq "10" ++ data "codec0_in mi" ++} ++SectionWidget."codec0_in" { ++ index"1" ++ type"aif_in" ++ no_pm "true" ++} ++SectionWidget."dmic01_hifi_in cpr 3" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "3" ++ event_flags "9" ++ data "dmic01_hifi_in cpr 3" ++} ++SectionWidget."dmic01_hifi_in mi" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ event_flags "9" ++ subseq "10" ++ data "dmic01_hifi_in mi" ++} ++SectionWidget."dmic01_hifi" { ++ index"1" ++ type"aif_in" ++ no_pm "true" ++} ++SectionWidget."hdmi1_pt_out cpr 7" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "3" ++ event_flags "9" ++ data "hdmi1_pt_out cpr 7" ++} ++SectionWidget."hdmi1_pt_out cpr 8" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ data "hdmi1_pt_out cpr 8" ++} ++SectionWidget."iDisp1_out" { ++ index"1" ++ type"aif_out" ++ no_pm "true" ++} ++SectionWidget."hdmi2_pt_out cpr 9" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "3" ++ event_flags "9" ++ data "hdmi2_pt_out cpr 9" ++} ++SectionWidget."hdmi2_pt_out cpr 10" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ data "hdmi2_pt_out cpr 10" ++} ++SectionWidget."iDisp2_out" { ++ index"1" ++ type"aif_out" ++ no_pm "true" ++} ++SectionWidget."hdmi3_pt_out cpr 11" { ++ index"1" ++ type"mixer" ++ no_pm "true" ++ event_type "3" ++ event_flags "9" ++ data "hdmi3_pt_out cpr 11" ++} ++SectionWidget."hdmi3_pt_out cpr 12" { ++ index"1" ++ type"pga" ++ no_pm "true" ++ event_type "4" ++ data "hdmi3_pt_out cpr 12" ++} ++SectionGraph."Pipeline 1 Graph" { ++ index"1" ++ lines [ ++ "media0_in mi, , media0_in cpr 0" ++ "media0_in cpr 0, , System Playback" ++ "media0_out mo, media0_in mi Switch, media0_in mi" ++ "media0_out mo, codec0_in mi Switch, codec0_in mi" ++ "media0_out mo, dmic01_hifi_in mi Switch, dmic01_hifi_in mi" ++ "media0_out cpr 6, , media0_out mo" ++ "System Capture, , media0_out cpr 6" ++ "codec0_out mo, media0_in mi Switch, media0_in mi" ++ "codec0_out mo, codec0_in mi Switch, codec0_in mi" ++ "codec0_out mo, dmic01_hifi_in mi Switch, dmic01_hifi_in mi" ++ "codec0_out cpr 4, , codec0_out mo" ++ "codec0_out, , codec0_out cpr 4" ++ "codec1_out mo, media0_in mi Switch, media0_in mi" ++ "codec1_out mo, codec0_in mi Switch, codec0_in mi" ++ "codec1_out mo, dmic01_hifi_in mi Switch, dmic01_hifi_in mi" ++ "codec1_out cpr 5, , codec1_out mo" ++ "codec1_out, , codec1_out cpr 5" ++ "codec0_in mi, , codec0_in cpr 1" ++ "codec0_in cpr 1, , codec0_in" ++ "dmic01_hifi_in mi, , dmic01_hifi_in cpr 3" ++ "dmic01_hifi_in cpr 3, , dmic01_hifi" ++ "hdmi1_pt_out cpr 8, , hdmi1_pt_out cpr 7" ++ "hdmi1_pt_out cpr 7, , HDMI1 Playback" ++ "iDisp1_out, , hdmi1_pt_out cpr 8" ++ "hdmi2_pt_out cpr 10, , hdmi2_pt_out cpr 9" ++ "hdmi2_pt_out cpr 9, , HDMI2 Playback" ++ "iDisp2_out, , hdmi2_pt_out cpr 10" ++ "hdmi3_pt_out cpr 12, , hdmi3_pt_out cpr 11" ++ "hdmi3_pt_out cpr 11, , HDMI3 Playback" ++ "iDisp1_out, , hdmi3_pt_out cpr 12" ++ ] ++} ++ +-- +2.5.5 + +From a8ca6d1c4b942616dad43d51d954c31894e3c608 Mon Sep 17 00:00:00 2001 +From: Shreyas NC +Date: Thu, 28 Apr 2016 11:07:57 +0530 +Subject: [PATCH 13/34] Add u8 in type_compat.h + +Skylake headers use u8 data types which were not present in +type_compat so add them. + +Signed-off-by: Shreyas NC +Signed-off-by: Vinod Koul +Signed-off-by: Takashi Iwai +--- + include/sound/type_compat.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/sound/type_compat.h b/include/sound/type_compat.h +index eec86e4..e973ff3 100644 +--- a/include/sound/type_compat.h ++++ b/include/sound/type_compat.h +@@ -32,9 +32,11 @@ typedef int32_t __s32; + #define __le64 __u64 + #define __le32 __u32 + #define __le16 __u16 ++#define __le8 __u8 + #define __be64 __u64 + #define __be32 __u32 + #define __be16 __u16 ++#define __be8 __u8 + #endif /* DOC_HIDDEN */ + + #endif /* __TYPE_COMPAT_H */ +-- +2.5.5 + +From 65b271034a36580badc980b3ff0bd77e7b9837ce Mon Sep 17 00:00:00 2001 +From: Shreyas NC +Date: Thu, 28 Apr 2016 11:07:58 +0530 +Subject: [PATCH 14/34] conf: topology: Generate Private data binary blobs + +The DSP modules need private data and that is provided as binary +blob. These blobs are compiled from C structures which specify module +configuration. + +Signed-off-by: Shreyas NC +Signed-off-by: Vinod Koul +Signed-off-by: Takashi Iwai +--- + configure.ac | 1 + + src/conf/topology/sklrt286/Makefile.am | 1 + + src/conf/topology/sklrt286/data/Makefile.am | 4 + + src/conf/topology/sklrt286/data/pvt.c | 1815 ++++++++++++++++++++ + src/conf/topology/sklrt286/data/pvt_data.c | 90 + + src/conf/topology/sklrt286/data/pvt_local.h | 9 + + .../topology/sklrt286/data/skl-tplg-interface.h | 232 +++ + 7 files changed, 2152 insertions(+) + create mode 100644 src/conf/topology/sklrt286/data/Makefile.am + create mode 100644 src/conf/topology/sklrt286/data/pvt.c + create mode 100644 src/conf/topology/sklrt286/data/pvt_data.c + create mode 100644 src/conf/topology/sklrt286/data/pvt_local.h + create mode 100644 src/conf/topology/sklrt286/data/skl-tplg-interface.h + +diff --git a/configure.ac b/configure.ac +index 1bf75e6..28fcd24 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -661,6 +661,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \ + src/conf/topology/Makefile \ + src/conf/topology/broadwell/Makefile \ + modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \ ++ src/conf/topology/sklrt286/data/Makefile \ + src/conf/topology/sklrt286/Makefile \ + alsalisp/Makefile aserver/Makefile \ + test/Makefile test/lsb/Makefile \ +diff --git a/src/conf/topology/sklrt286/Makefile.am b/src/conf/topology/sklrt286/Makefile.am +index facc508..ed58b77 100644 +--- a/src/conf/topology/sklrt286/Makefile.am ++++ b/src/conf/topology/sklrt286/Makefile.am +@@ -1,4 +1,5 @@ + alsaconfigdir = @ALSA_CONFIG_DIR@ ++SUBDIRS = data + sklrt286dir = $(alsaconfigdir)/topology/sklrt286 + sklrt286_DATA = skl_i2s.conf media0_in-cpr-0.bin media0_in-mi.bin media0_out-mo.bin media0_out-cpr-6.bin codec0_out-mo.bin codec0_out-cpr-4.bin codec1_out-mo.bin codec1_out-cpr-5.bin codec0_in-cpr-1.bin codec0_in-mi.bin dmic01_hifi_in-cpr-3.bin dmic01_hifi_in-mi.bin hdmi1_pt_out-cpr-7.bin hdmi1_pt_out-cpr-8.bin hdmi2_pt_out-cpr-9.bin hdmi2_pt_out-cpr-10.bin hdmi3_pt_out-cpr-11.bin hdmi3_pt_out-cpr-12.bin + EXTRA_DIST = $(sklrt286_DATA) +diff --git a/src/conf/topology/sklrt286/data/Makefile.am b/src/conf/topology/sklrt286/data/Makefile.am +new file mode 100644 +index 0000000..888ce16 +--- /dev/null ++++ b/src/conf/topology/sklrt286/data/Makefile.am +@@ -0,0 +1,4 @@ ++noinst_PROGRAMS = pvt_data ++pvt_data_SOURCES = pvt_data.c ++AM_CPPFLAGS = \ ++ -Wall -I$(top_srcdir)/include +diff --git a/src/conf/topology/sklrt286/data/pvt.c b/src/conf/topology/sklrt286/data/pvt.c +new file mode 100644 +index 0000000..3447e3e +--- /dev/null ++++ b/src/conf/topology/sklrt286/data/pvt.c +@@ -0,0 +1,1815 @@ ++/* ++* Copyright(c) 2014-2016 Intel Corporation ++* All rights reserved. ++* ++* 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 of the License, or (at your option) any later version. ++ ++* This library 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: Shreyas Nc ++* ++*/ ++#include "pvt_local.h" ++ ++struct skl_dfw_module_mod dfw_wrap[] = { ++{ ++.name = "media0_in cpr 0", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 0, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 1, ++ .dev_type = 5, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 1, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "media0_in mi", ++.skl_dfw_mod = { ++ .uuid = {178, 110, 101, 57, 113, 59, 73, 64, 141, 63, 249, 44, 213, 196, 60, 9}, ++ .module_id = 1, ++ .instance_id = 0, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 1, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 0, ++ .conn_type = 0, ++ .dev_type = 6, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 1, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "media0_out mo", ++.skl_dfw_mod = { ++ .uuid = {90, 80, 86, 60, 215, 36, 143, 65, 189, 220, 193, 245, 163, 172, 42, 224}, ++ .module_id = 2, ++ .instance_id = 2, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 8, ++ .max_out_queue = 1, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 0, ++ .conn_type = 0, ++ .dev_type = 6, ++ .hw_conn_type = 2, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 2, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "media0_out cpr 6", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 6, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 0, ++ .dev_type = 5, ++ .hw_conn_type = 2, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 2, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "codec0_out mo", ++.skl_dfw_mod = { ++ .uuid = {90, 80, 86, 60, 215, 36, 143, 65, 189, 220, 193, 245, 163, 172, 42, 224}, ++ .module_id = 2, ++ .instance_id = 0, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 8, ++ .max_out_queue = 1, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 0, ++ .conn_type = 0, ++ .dev_type = 6, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 3, ++ .pipe_priority = 0, ++ .conn_type = 2, ++ .rsvd = 0, ++ .memory_pages = 0x4, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "codec0_out cpr 4", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 4, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = 0, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 2, ++ .dev_type = 2, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 3, ++ .pipe_priority = 0, ++ .conn_type = 2, ++ .rsvd = 0, ++ .memory_pages = 0x4, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "codec1_out mo", ++.skl_dfw_mod = { ++ .uuid = {90, 80, 86, 60, 215, 36, 143, 65, 189, 220, 193, 245, 163, 172, 42, 224}, ++ .module_id = 2, ++ .instance_id = 1, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 8, ++ .max_out_queue = 1, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 0, ++ .conn_type = 0, ++ .dev_type = 6, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 4, ++ .pipe_priority = 0, ++ .conn_type = 2, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "codec1_out cpr 5", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 5, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = 0, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 2, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 2, ++ .dev_type = 2, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 4, ++ .pipe_priority = 0, ++ .conn_type = 2, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "codec0_in cpr 1", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 1, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = 0, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 2, ++ .dev_type = 2, ++ .hw_conn_type = 2, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 5, ++ .pipe_priority = 0, ++ .conn_type = 2, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "codec0_in mi", ++.skl_dfw_mod = { ++ .uuid = {178, 110, 101, 57, 113, 59, 73, 64, 141, 63, 249, 44, 213, 196, 60, 9}, ++ .module_id = 1, ++ .instance_id = 1, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 1, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 0, ++ .conn_type = 0, ++ .dev_type = 6, ++ .hw_conn_type = 2, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 5, ++ .pipe_priority = 0, ++ .conn_type = 2, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "dmic01_hifi_in cpr 3", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 3, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = 0, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 2, ++ .dev_type = 1, ++ .hw_conn_type = 2, ++ .rsvd2 = 0, ++ .params_fixup = 4, ++ .converter = 4, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 6, ++ .pipe_priority = 0, ++ .conn_type = 2, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "dmic01_hifi_in mi", ++.skl_dfw_mod = { ++ .uuid = {178, 110, 101, 57, 113, 59, 73, 64, 141, 63, 249, 44, 213, 196, 60, 9}, ++ .module_id = 1, ++ .instance_id = 3, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 1, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 0, ++ .conn_type = 0, ++ .dev_type = 6, ++ .hw_conn_type = 2, ++ .rsvd2 = 0, ++ .params_fixup = 0, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 6, ++ .pipe_priority = 0, ++ .conn_type = 2, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "hdmi1_pt_out cpr 7", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 7, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 1, ++ .dev_type = 5, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 7, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 7, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "hdmi1_pt_out cpr 8", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 8, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 1, ++ .dev_type = 4, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 7, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 7, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "hdmi2_pt_out cpr 9", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 9, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 1, ++ .dev_type = 5, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 7, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 8, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "hdmi2_pt_out cpr 10", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 10, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 1, ++ .dev_type = 4, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 7, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 8, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "hdmi3_pt_out cpr 11", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 11, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 1, ++ .dev_type = 5, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 7, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 9, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 32, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++{ ++.name = "hdmi3_pt_out cpr 12", ++.skl_dfw_mod = { ++ .uuid = {131, 12, 160, 155, 18, 202, 131, 74, 148, 60, 31, 162, 232, 47, 157, 218}, ++ .module_id = 3, ++ .instance_id = 12, ++ .max_mcps = 0x186a0, ++ .mem_pages = 0x1, ++ .obs = 384, ++ .ibs = 384, ++ .vbus_id = -1, ++ .max_in_queue = 1, ++ .max_out_queue = 2, ++ .time_slot = 0, ++ .core_id = 0, ++ .rsvd1 = 0, ++ .module_type = 1, ++ .conn_type = 1, ++ .dev_type = 4, ++ .hw_conn_type = 1, ++ .rsvd2 = 0, ++ .params_fixup = 7, ++ .converter = 0, ++ .input_pin_type = 0, ++ .output_pin_type = 0, ++ .is_dynamic_in_pin = 1, ++ .is_dynamic_out_pin = 1, ++ .is_loadable = 0, ++ .rsvd3 = 0, ++ .pipe = { ++ .pipe_id = 9, ++ .pipe_priority = 0, ++ .conn_type = 1, ++ .rsvd = 0, ++ .memory_pages = 0x2, ++ }, ++ .in_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .out_fmt = { ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ { ++ .channels = 2, ++ .freq = 48000, ++ .bit_depth = 32, ++ .valid_bit_depth = 24, ++ .ch_cfg = 1, ++ .interleaving_style = 0, ++ .sample_type = 0, ++ .ch_map = 0xffffff10, ++ }, ++ }, ++ .in_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ .out_pin = { ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ { ++ .module_id = 0, ++ .instance_id = 0, ++ }, ++ }, ++ }, ++}, ++ }; +diff --git a/src/conf/topology/sklrt286/data/pvt_data.c b/src/conf/topology/sklrt286/data/pvt_data.c +new file mode 100644 +index 0000000..dd55c3a +--- /dev/null ++++ b/src/conf/topology/sklrt286/data/pvt_data.c +@@ -0,0 +1,90 @@ ++/* ++ * Copyright(c) 2014-2016 Intel Corporation ++ * All rights reserved. ++ * ++ * 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 of the License, or (at your option) any later version. ++ * ++ * This library 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. ++ * ++ * Authors: Shreyas Nc ++ * ++ */ ++#include "pvt.c" ++#include "stdio.h" ++#include "fcntl.h" ++#include ++#include ++#include ++#include ++#include "global.h" ++#include "list.h" ++ ++#include ++#include ++ ++int replace_space(char *path, char *newpath) ++{ ++ char buffer[52]; ++ char *p; ++ ++ strcpy(buffer, path); ++ ++ while ((p = strchr(buffer, ' '))) ++ p[0] = '-'; ++ ++ strcpy(newpath, buffer); ++ return 0; ++} ++ ++/* ++ * The private data structures are written into a ++ * binary blob. These contain module private data ++ * information ++ */ ++int main(void) ++{ ++ unsigned int i; ++ FILE *fd; ++ char path[128]; ++ char new_path[128]; ++ struct snd_soc_tplg_private *priv = NULL; ++ ++ memset(path, 0, sizeof(path)); ++ memset(new_path, 0, sizeof(new_path)); ++ ++ priv = calloc(1, sizeof(dfw_wrap) + sizeof(uint32_t)); ++ ++ for (i = 0; i < ARRAY_SIZE(dfw_wrap); i++) { ++ strcat(path, "../"); ++ strcat(path, dfw_wrap[i].name); ++ strcat(path, ".bin"); ++ ++ replace_space(path, new_path); ++ ++ priv->size = (uint32_t)sizeof(dfw_wrap[i].skl_dfw_mod); ++ ++ memcpy(priv->data, &dfw_wrap[i].skl_dfw_mod, ++ priv->size); ++ ++ fd = fopen(new_path, "wb"); ++ ++ if (fd == NULL) ++ return -ENOENT; ++ ++ if (fwrite(priv->data, priv->size, 1, fd) != 1) { ++ fclose(fd); ++ return -1; ++ } ++ ++ memset(path, 0, sizeof(path)); ++ } ++ ++ free(priv); ++ return 0; ++} +diff --git a/src/conf/topology/sklrt286/data/pvt_local.h b/src/conf/topology/sklrt286/data/pvt_local.h +new file mode 100644 +index 0000000..5edf7bd +--- /dev/null ++++ b/src/conf/topology/sklrt286/data/pvt_local.h +@@ -0,0 +1,9 @@ ++#include ++#include "skl-tplg-interface.h" ++ ++struct skl_dfw_module_mod { ++ char name[100]; ++ struct skl_dfw_module skl_dfw_mod; ++}; ++ ++ +diff --git a/src/conf/topology/sklrt286/data/skl-tplg-interface.h b/src/conf/topology/sklrt286/data/skl-tplg-interface.h +new file mode 100644 +index 0000000..e7389bc +--- /dev/null ++++ b/src/conf/topology/sklrt286/data/skl-tplg-interface.h +@@ -0,0 +1,232 @@ ++/* ++ * skl-tplg-interface.h - Intel DSP FW private data interface ++ * ++ * Copyright (C) 2015 Intel Corp ++ * Author: Jeeja KP ++ * Nilofer, Samreen ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as version 2, 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. ++ */ ++ ++#ifndef __HDA_TPLG_INTERFACE_H__ ++#define __HDA_TPLG_INTERFACE_H__ ++ ++#include ++/* ++ * Default types range from 0~12. type can range from 0 to 0xff ++ * SST types start at higher to avoid any overlapping in future ++ */ ++#define SKL_CONTROL_TYPE_BYTE_TLV 0x100 ++ ++#define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ ++#define MAX_IN_QUEUE 8 ++#define MAX_OUT_QUEUE 8 ++ ++#define SKL_UUID_STR_SZ 40 ++/* Event types goes here */ ++/* Reserve event type 0 for no event handlers */ ++enum skl_event_types { ++ SKL_EVENT_NONE = 0, ++ SKL_MIXER_EVENT, ++ SKL_MUX_EVENT, ++ SKL_VMIXER_EVENT, ++ SKL_PGA_EVENT ++}; ++ ++/** ++ * enum skl_ch_cfg - channel configuration ++ * ++ * @SKL_CH_CFG_MONO: One channel only ++ * @SKL_CH_CFG_STEREO: L & R ++ * @SKL_CH_CFG_2_1: L, R & LFE ++ * @SKL_CH_CFG_3_0: L, C & R ++ * @SKL_CH_CFG_3_1: L, C, R & LFE ++ * @SKL_CH_CFG_QUATRO: L, R, Ls & Rs ++ * @SKL_CH_CFG_4_0: L, C, R & Cs ++ * @SKL_CH_CFG_5_0: L, C, R, Ls & Rs ++ * @SKL_CH_CFG_5_1: L, C, R, Ls, Rs & LFE ++ * @SKL_CH_CFG_DUAL_MONO: One channel replicated in two ++ * @SKL_CH_CFG_I2S_DUAL_STEREO_0: Stereo(L,R) in 4 slots, 1st stream:[ L, R, -, - ] ++ * @SKL_CH_CFG_I2S_DUAL_STEREO_1: Stereo(L,R) in 4 slots, 2nd stream:[ -, -, L, R ] ++ * @SKL_CH_CFG_INVALID: Invalid ++ */ ++enum skl_ch_cfg { ++ SKL_CH_CFG_MONO = 0, ++ SKL_CH_CFG_STEREO = 1, ++ SKL_CH_CFG_2_1 = 2, ++ SKL_CH_CFG_3_0 = 3, ++ SKL_CH_CFG_3_1 = 4, ++ SKL_CH_CFG_QUATRO = 5, ++ SKL_CH_CFG_4_0 = 6, ++ SKL_CH_CFG_5_0 = 7, ++ SKL_CH_CFG_5_1 = 8, ++ SKL_CH_CFG_DUAL_MONO = 9, ++ SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10, ++ SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11, ++ SKL_CH_CFG_4_CHANNEL = 12, ++ SKL_CH_CFG_INVALID ++}; ++ ++enum skl_module_type { ++ SKL_MODULE_TYPE_MIXER = 0, ++ SKL_MODULE_TYPE_COPIER, ++ SKL_MODULE_TYPE_UPDWMIX, ++ SKL_MODULE_TYPE_SRCINT, ++ SKL_MODULE_TYPE_ALGO, ++ SKL_MODULE_TYPE_BASE_OUTFMT ++}; ++ ++enum skl_core_affinity { ++ SKL_AFFINITY_CORE_0 = 0, ++ SKL_AFFINITY_CORE_1, ++ SKL_AFFINITY_CORE_MAX ++}; ++ ++enum skl_pipe_conn_type { ++ SKL_PIPE_CONN_TYPE_NONE = 0, ++ SKL_PIPE_CONN_TYPE_FE, ++ SKL_PIPE_CONN_TYPE_BE ++}; ++ ++enum skl_hw_conn_type { ++ SKL_CONN_NONE = 0, ++ SKL_CONN_SOURCE = 1, ++ SKL_CONN_SINK = 2 ++}; ++ ++enum skl_dev_type { ++ SKL_DEVICE_BT = 0x0, ++ SKL_DEVICE_DMIC = 0x1, ++ SKL_DEVICE_I2S = 0x2, ++ SKL_DEVICE_SLIMBUS = 0x3, ++ SKL_DEVICE_HDALINK = 0x4, ++ SKL_DEVICE_HDAHOST = 0x5, ++ SKL_DEVICE_NONE ++}; ++ ++/** ++ * enum skl_interleaving - interleaving style ++ * ++ * @SKL_INTERLEAVING_PER_CHANNEL: [s1_ch1...s1_chN,...,sM_ch1...sM_chN] ++ * @SKL_INTERLEAVING_PER_SAMPLE: [s1_ch1...sM_ch1,...,s1_chN...sM_chN] ++ */ ++enum skl_interleaving { ++ SKL_INTERLEAVING_PER_CHANNEL = 0, ++ SKL_INTERLEAVING_PER_SAMPLE = 1, ++}; ++ ++enum skl_sample_type { ++ SKL_SAMPLE_TYPE_INT_MSB = 0, ++ SKL_SAMPLE_TYPE_INT_LSB = 1, ++ SKL_SAMPLE_TYPE_INT_SIGNED = 2, ++ SKL_SAMPLE_TYPE_INT_UNSIGNED = 3, ++ SKL_SAMPLE_TYPE_FLOAT = 4 ++}; ++ ++enum module_pin_type { ++ /* All pins of the module takes same PCM inputs or outputs ++ * e.g. mixout ++ */ ++ SKL_PIN_TYPE_HOMOGENEOUS, ++ /* All pins of the module takes different PCM inputs or outputs ++ * e.g mux ++ */ ++ SKL_PIN_TYPE_HETEROGENEOUS, ++}; ++ ++enum skl_module_param_type { ++ SKL_PARAM_DEFAULT = 0, ++ SKL_PARAM_INIT, ++ SKL_PARAM_SET, ++ SKL_PARAM_BIND ++}; ++ ++struct skl_dfw_module_pin { ++ __le16 module_id; ++ __le16 instance_id; ++} __attribute__((packed)); ++ ++struct skl_dfw_module_fmt { ++ __le32 channels; ++ __le32 freq; ++ __le32 bit_depth; ++ __le32 valid_bit_depth; ++ __le32 ch_cfg; ++ __le32 interleaving_style; ++ __le32 sample_type; ++ __le32 ch_map; ++} __attribute__((packed)); ++ ++struct skl_dfw_module_caps { ++ __le32 set_params:2; ++ __le32 rsvd:30; ++ __le32 param_id; ++ __le32 caps_size; ++ __le32 caps[HDA_SST_CFG_MAX]; ++}; ++ ++struct skl_dfw_pipe { ++ __le8 pipe_id; ++ __le8 pipe_priority; ++ __le16 conn_type:4; ++ __le16 rsvd:4; ++ __le16 memory_pages:8; ++} __attribute__((packed)); ++ ++struct skl_dfw_module { ++ __le8 uuid[16]; ++ ++ __le16 module_id; ++ __le16 instance_id; ++ __le32 max_mcps; ++ __le32 mem_pages; ++ __le32 obs; ++ __le32 ibs; ++ __le32 vbus_id; ++ ++ __le32 max_in_queue:8; ++ __le32 max_out_queue:8; ++ __le32 time_slot:8; ++ __le32 core_id:4; ++ __le32 rsvd1:4; ++ ++ __le32 module_type:8; ++ __le32 conn_type:4; ++ __le32 dev_type:4; ++ __le32 hw_conn_type:4; ++ __le32 rsvd2:12; ++ ++ __le32 params_fixup:8; ++ __le32 converter:8; ++ __le32 input_pin_type:1; ++ __le32 output_pin_type:1; ++ __le32 is_dynamic_in_pin:1; ++ __le32 is_dynamic_out_pin:1; ++ __le32 is_loadable:1; ++ __le32 rsvd3:11; ++ ++ struct skl_dfw_pipe pipe; ++ struct skl_dfw_module_fmt in_fmt[MAX_IN_QUEUE]; ++ struct skl_dfw_module_fmt out_fmt[MAX_OUT_QUEUE]; ++ struct skl_dfw_module_pin in_pin[MAX_IN_QUEUE]; ++ struct skl_dfw_module_pin out_pin[MAX_OUT_QUEUE]; ++ struct skl_dfw_module_caps caps; ++} __attribute__((packed)); ++ ++struct skl_dfw_algo_data { ++ __le32 set_params:2; ++ __le32 rsvd:30; ++ __le32 param_id; ++ __le32 max; ++ char params[0]; ++} __attribute__((packed)); ++ ++#endif +-- +2.5.5 + +From e64334df2b2fe6756539178d89133a0b56e83c9d Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Fri, 29 Apr 2016 11:02:57 +0800 +Subject: [PATCH 16/34] topology: Set manifest size for ABI + +The topology kernel driver will check the size of manifest struct, and +will stop loading topology info if size mismatch is detected. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + src/topology/parser.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 30d91f9..84117c3 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -414,6 +414,8 @@ snd_tplg_t *snd_tplg_new(void) + if (!tplg) + return NULL; + ++ tplg->manifest.size = sizeof(struct snd_soc_tplg_manifest); ++ + INIT_LIST_HEAD(&tplg->tlv_list); + INIT_LIST_HEAD(&tplg->widget_list); + INIT_LIST_HEAD(&tplg->pcm_list); +-- +2.5.5 + +From 86ec8b49008fbcfa45756f7ab1803392c3bb464e Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Fri, 29 Apr 2016 11:03:04 +0800 +Subject: [PATCH 17/34] topology: Refactor functions to parse and build streams + +Previously these functions are only used by pcm elements (front-end DAI +& DAI link) to parse stream capablities. Now refactor them to be reused +by back-end DAI elements later. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + src/topology/parser.c | 2 +- + src/topology/pcm.c | 60 +++++++++++++++++++++++++++-------------------- + src/topology/tplg_local.h | 2 +- + 3 files changed, 36 insertions(+), 28 deletions(-) + +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 84117c3..f6fc944 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -119,7 +119,7 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + + if (strcmp(id, "SectionPCMCapabilities") == 0) { + err = tplg_parse_compound(tplg, n, +- tplg_parse_pcm_caps, NULL); ++ tplg_parse_stream_caps, NULL); + if (err < 0) + return err; + continue; +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index d75aad8..1df4f54 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -40,9 +40,9 @@ struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base, const char* id) + 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) ++/* copy referenced caps to the parent (pcm or be dai) */ ++static void copy_stream_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; + +@@ -52,24 +52,19 @@ static void copy_pcm_caps(const char *id, struct snd_soc_tplg_stream_caps *caps, + *caps = *ref_caps; + } + +-/* check referenced config and caps for a pcm */ +-static int tplg_build_pcm_caps(snd_tplg_t *tplg, struct tplg_elem *elem) ++/* find and copy the referenced stream caps */ ++static int tplg_build_stream_caps(snd_tplg_t *tplg, ++ const char *id, struct snd_soc_tplg_stream_caps *caps) + { + struct tplg_elem *ref_elem = NULL; +- struct snd_soc_tplg_pcm *pcm; +- struct snd_soc_tplg_stream_caps *caps; + unsigned int i; + +- pcm = elem->pcm; +- + for (i = 0; i < 2; i++) { +- caps = &pcm->caps[i]; +- + ref_elem = tplg_elem_lookup(&tplg->pcm_caps_list, +- caps->name, SND_TPLG_TYPE_STREAM_CAPS); ++ caps[i].name, SND_TPLG_TYPE_STREAM_CAPS); + + if (ref_elem != NULL) +- copy_pcm_caps(elem->id, caps, ref_elem); ++ copy_stream_caps(id, &caps[i], ref_elem); + } + + return 0; +@@ -91,7 +86,7 @@ int tplg_build_pcm(snd_tplg_t *tplg, unsigned int type) + return -EINVAL; + } + +- err = tplg_build_pcm_caps(tplg, elem); ++ err = tplg_build_stream_caps(tplg, elem->id, elem->pcm->caps); + if (err < 0) + return err; + +@@ -184,8 +179,8 @@ static int split_format(struct snd_soc_tplg_stream_caps *caps, char *str) + return 0; + } + +-/* Parse pcm Capabilities */ +-int tplg_parse_pcm_caps(snd_tplg_t *tplg, ++/* Parse pcm stream capabilities */ ++int tplg_parse_stream_caps(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) + { + struct snd_soc_tplg_stream_caps *sc; +@@ -263,29 +258,40 @@ int tplg_parse_pcm_caps(snd_tplg_t *tplg, + return 0; + } + +-/* Parse the caps of a pcm stream */ +-int tplg_parse_stream_caps(snd_tplg_t *tplg, snd_config_t *cfg, ++/* Parse the caps and config of a pcm stream */ ++static int tplg_parse_streams(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 *pcm; ++ unsigned int *playback, *capture; ++ struct snd_soc_tplg_stream_caps *caps; + const char *id, *value; + int stream; + +- pcm = elem->pcm; +- + snd_config_get_id(cfg, &id); + + tplg_dbg("\t%s:\n", id); + ++ switch (elem->type) { ++ case SND_TPLG_TYPE_PCM: ++ pcm = elem->pcm; ++ playback = &pcm->playback; ++ capture = &pcm->capture; ++ caps = pcm->caps; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + if (strcmp(id, "playback") == 0) { + stream = SND_SOC_TPLG_STREAM_PLAYBACK; +- pcm->playback = 1; ++ *playback = 1; + } else if (strcmp(id, "capture") == 0) { + stream = SND_SOC_TPLG_STREAM_CAPTURE; +- pcm->capture = 1; ++ *capture = 1; + } else + return -EINVAL; + +@@ -300,8 +306,10 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, snd_config_t *cfg, + if (strcmp(id, "capabilities") == 0) { + if (snd_config_get_string(n, &value) < 0) + continue; +- +- elem_copy_text(pcm->caps[stream].name, value, ++ /* store stream caps name, to find and merge ++ * the caps in building phase. ++ */ ++ elem_copy_text(caps[stream].name, value, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + + tplg_dbg("\t\t%s\n\t\t\t%s\n", id, value); +@@ -312,7 +320,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + +-/* Parse pcm */ ++/* Parse pcm (for front end DAI & DAI link) */ + int tplg_parse_pcm(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) + { +@@ -365,7 +373,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, + + if (strcmp(id, "pcm") == 0) { + err = tplg_parse_compound(tplg, n, +- tplg_parse_stream_caps, elem); ++ tplg_parse_streams, elem); + if (err < 0) + return err; + continue; +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 4c601d4..9239aef 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -210,7 +210,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, + int tplg_parse_dapm_widget(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); + +-int tplg_parse_pcm_caps(snd_tplg_t *tplg, ++int tplg_parse_stream_caps(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); + + int tplg_parse_pcm(snd_tplg_t *tplg, +-- +2.5.5 + +From 0935e32d40e065e61255550ac4c5b7c6710dd028 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Fri, 29 Apr 2016 11:03:22 +0800 +Subject: [PATCH 18/34] topology: Use generic pointer to realloc buffer for + private data + +Many element types have private data. So use the generic obj pointer +instead of the type-specific pointer when reallocating the object to +accommodate the private data. + +Empty private data will be overlooked. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + src/topology/data.c | 26 +++++++++----------------- + 1 file changed, 9 insertions(+), 17 deletions(-) + +diff --git a/src/topology/data.c b/src/topology/data.c +index 19c31bf..9f8d5d0 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -822,44 +822,36 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref) + { + struct snd_soc_tplg_private *priv; + int priv_data_size; ++ void *obj; + + if (!ref) + return -EINVAL; + + tplg_dbg("Data '%s' used by '%s'\n", ref->id, elem->id); ++ if (!ref->data || !ref->data->size) /* overlook empty private data */ ++ return 0; ++ + priv_data_size = ref->data->size; ++ obj = realloc(elem->obj, ++ elem->size + priv_data_size); ++ if (!obj) ++ return -ENOMEM; ++ elem->obj = obj; + + switch (elem->type) { + case SND_TPLG_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 SND_TPLG_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 SND_TPLG_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 SND_TPLG_TYPE_DAPM_WIDGET: +- elem->widget = realloc(elem->widget, +- elem->size + priv_data_size); +- if (!elem->widget) +- return -ENOMEM; + priv = &elem->widget->priv; + break; + +-- +2.5.5 + +From 5d23c406d1757d1b65e1d17a71c69620d9af71d7 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Fri, 29 Apr 2016 11:03:30 +0800 +Subject: [PATCH 19/34] topology: Fix pcm ID & name parsing + +The name and ID of SectionPCM should be set to pcm_name and pcm_id, +for a front-end DAI link in the kernel, not for the front-end DAI +of the link. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + include/sound/asoc.h | 2 +- + src/topology/pcm.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/include/sound/asoc.h b/include/sound/asoc.h +index 920c9e0..abe49c5 100644 +--- a/include/sound/asoc.h ++++ b/include/sound/asoc.h +@@ -414,7 +414,7 @@ struct snd_soc_tplg_pcm { + __le32 size; /* in bytes of this structure */ + char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- __le32 pcm_id; /* unique ID - used to match */ ++ __le32 pcm_id; /* unique ID - used to match with DAI link */ + __le32 dai_id; /* unique ID - used to match */ + __le32 playback; /* supports playback mode */ + __le32 capture; /* supports capture mode */ +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 1df4f54..1661821 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -337,7 +337,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, + + pcm = elem->pcm; + pcm->size = elem->size; +- elem_copy_text(pcm->dai_name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); ++ elem_copy_text(pcm->pcm_name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + + tplg_dbg(" PCM: %s\n", elem->id); + +@@ -366,8 +366,8 @@ int tplg_parse_pcm(snd_tplg_t *tplg, + 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); ++ pcm->pcm_id = atoi(val); ++ tplg_dbg("\t%s: %d\n", id, pcm->pcm_id); + continue; + } + +-- +2.5.5 + +From 25d6f8e6a8e162259dcf84600496dc8ebd8196e7 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Fri, 29 Apr 2016 11:03:37 +0800 +Subject: [PATCH 20/34] topology: Parse front-end DAI name and ID for the PCM + +These two fields are necessary to create the front-end DAIs +in kernel but the support is missing in text conf previously. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + include/topology.h | 4 ++++ + src/topology/pcm.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 57 insertions(+) + +diff --git a/include/topology.h b/include/topology.h +index b47f422..9d57ce3 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -533,6 +533,10 @@ extern "C" { + * + * id "0" # used for binding to the PCM + * ++ * dai."name of front-end DAI" { ++ * id "0" # used for binding to the front-end DAI ++ * } ++ * + * pcm."playback" { + * capabilities "capabilities1" # capabilities for playback + * +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 1661821..efee58b 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -320,6 +320,51 @@ static int tplg_parse_streams(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* Parse name and id of a front-end DAI (ie. cpu dai of a FE DAI link) */ ++static int tplg_parse_fe_dai(snd_tplg_t *tplg, snd_config_t *cfg, ++ void *private) ++{ ++ struct tplg_elem *elem = private; ++ struct snd_soc_tplg_pcm *pcm = elem->pcm; ++ snd_config_iterator_t i, next; ++ snd_config_t *n; ++ const char *id, *value = NULL; ++ unsigned long int id_val; ++ int err; ++ ++ snd_config_get_id(cfg, &id); ++ tplg_dbg("\t\tFE DAI %s:\n", id); ++ elem_copy_text(pcm->dai_name, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); ++ ++ 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, "id") == 0) { ++ if (snd_config_get_string(n, &value) < 0) ++ continue; ++ errno = 0; ++ /* no support for negative value */ ++ id_val = strtoul(value, NULL, 0); ++ if ((errno == ERANGE && id_val == ULONG_MAX) ++ || (errno != 0 && id_val == 0) ++ || id_val > UINT_MAX) { ++ SNDERR("error: invalid fe dai ID\n"); ++ return -EINVAL; ++ } ++ ++ pcm->dai_id = (int) id_val; ++ tplg_dbg("\t\t\tindex: %d\n", pcm->dai_id); ++ } ++ } ++ ++ return 0; ++} ++ + /* Parse pcm (for front end DAI & DAI link) */ + int tplg_parse_pcm(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) +@@ -378,6 +423,14 @@ int tplg_parse_pcm(snd_tplg_t *tplg, + return err; + continue; + } ++ ++ if (strcmp(id, "dai") == 0) { ++ err = tplg_parse_compound(tplg, n, ++ tplg_parse_fe_dai, elem); ++ if (err < 0) ++ return err; ++ continue; ++ } + } + + return 0; +-- +2.5.5 + +From 76af5bf833323d8ae1caa23d592a959e74990932 Mon Sep 17 00:00:00 2001 +From: Mengdong Lin +Date: Fri, 29 Apr 2016 11:03:45 +0800 +Subject: [PATCH 21/34] topology: Update PCM configurations in Broadwell text + conf file + +To make this conf file a better example, update the name & ID of PCMs +(front-end DAI link) and their cpu DAI (front-end DAI), same as those +defined by Broadwell upstream driver. + +Signed-off-by: Mengdong Lin +Signed-off-by: Takashi Iwai +--- + src/conf/topology/broadwell/broadwell.conf | 34 ++++++++++++++++++++++-------- + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/src/conf/topology/broadwell/broadwell.conf b/src/conf/topology/broadwell/broadwell.conf +index 05b3889..eb89377 100644 +--- a/src/conf/topology/broadwell/broadwell.conf ++++ b/src/conf/topology/broadwell/broadwell.conf +@@ -272,18 +272,22 @@ SectionPCMCapabilities."Offload0 Playback" { + SectionPCMCapabilities."Offload1 Playback" { + formats "S24_LE,S16_LE" + rate_min "8000" +- rate_max "48000" ++ rate_max "192000" + channels_min "2" + channels_max "2" + } + + # PCM devices exported by Firmware +-SectionPCM."System Pin" { ++SectionPCM."System Playback/Capture" { + + index "1" + + # used for binding to the PCM +- ID "0" ++ id "0" ++ ++ dai."System Pin" { ++ id "0" ++ } + + pcm."playback" { + +@@ -307,12 +311,16 @@ SectionPCM."System Pin" { + } + } + +-SectionPCM."Offload0 Pin" { ++SectionPCM."Offload0 Playback" { + + index "1" + + # used for binding to the PCM +- ID "1" ++ id "1" ++ ++ dai."Offload0 Pin" { ++ id "1" ++ } + + pcm."playback" { + +@@ -325,12 +333,16 @@ SectionPCM."Offload0 Pin" { + } + } + +-SectionPCM."Offload1 Pin" { ++SectionPCM."Offload1 Playback" { + + index "1" + + # used for binding to the PCM +- ID "2" ++ id "2" ++ ++ dai."Offload1 Pin" { ++ id "2" ++ } + + pcm."playback" { + +@@ -343,12 +355,16 @@ SectionPCM."Offload1 Pin" { + } + } + +-SectionPCM."Loopback Pin" { ++SectionPCM."Loopback PCM" { + + index "1" + + # used for binding to the PCM +- ID "3" ++ id "3" ++ ++ dai."Loopback Pin" { ++ id "3" ++ } + + pcm."capture" { + +-- +2.5.5 + +From 85bf9915989e0a338632739684c75192c1753239 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Krause?= +Date: Sun, 8 May 2016 20:48:42 +0200 +Subject: [PATCH 22/34] pcm: softvol: fix conversion of TLVs min_db and max_dB + value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Both, min_dB and max_dB, are floating type whereas the TLV is (always) +unsigned. + +The problem with the conversion of a negative floating-point number into an +unsigned integer is, that the behavior is undefined. This may, depending on +the platform, result in a wrong TLV, i.e. for the default values of min_dB +(-51dB) and max_dB (0dB), alsactl generates the following state on an ARM +cpu build with GCC: + + control.1 { + iface MIXER + name Master + value.0 255 + value.1 255 + comment { + access 'read write user' + type INTEGER + count 2 + range '0 - 255' + tlv '00000001000000080000000000000014' + dbmin 0 + dbmax 5100 + dbvalue.0 5100 + dbvalue.1 5100 + } + } + +With the fix applied, alsactl stores the correct TLV: + + control.1 { + iface MIXER + name Master + value.0 255 + value.1 255 + comment { + access 'read write user' + type INTEGER + count 2 + range '0 - 255' + tlv '0000000100000008ffffec1400000014' + dbmin -5100 + dbmax 0 + dbvalue.0 0 + dbvalue.1 0 + } + } + +Also tested for different combinations of min_dB and max_dB other than the +default values. + +Replaces: +http://mailman.alsa-project.org/pipermail/alsa-devel/2016-May/107733.html + +Fixes: +http://mailman.alsa-project.org/pipermail/alsa-devel/2016-May/107628.html + +Cc: Clemens Ladisch +Signed-off-by: Jörg Krause +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_softvol.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c +index 802aa4b..5492db8 100644 +--- a/src/pcm/pcm_softvol.c ++++ b/src/pcm/pcm_softvol.c +@@ -658,8 +658,8 @@ static int add_tlv_info(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo) + unsigned int tlv[4]; + tlv[0] = SND_CTL_TLVT_DB_SCALE; + tlv[1] = 2 * sizeof(int); +- tlv[2] = svol->min_dB * 100; +- tlv[3] = (svol->max_dB - svol->min_dB) * 100 / svol->max_val; ++ tlv[2] = (int)(svol->min_dB * 100); ++ tlv[3] = (int)((svol->max_dB - svol->min_dB) * 100 / svol->max_val); + return snd_ctl_elem_tlv_write(svol->ctl, &cinfo->id, tlv); + } + +-- +2.5.5 + +From a192f52fc63a86e1fbb9a09adb0bc2a6bbc8dab1 Mon Sep 17 00:00:00 2001 +From: Enric Balletbo i Serra +Date: Thu, 5 May 2016 08:32:06 +0200 +Subject: [PATCH 23/34] conf/ucm: ROCKCHIP-I2S: add Rockchip I2S UCM config. + +Taken from the ChromeOS sources, this configuration was tested on Veyron +Jerry based Chromebook from Google. + +[Added missing Makefile changes by tiwai] + +Signed-off-by: Enric Balletbo i Serra +Signed-off-by: Takashi Iwai +--- + configure.ac | 1 + + src/conf/ucm/Makefile.am | 2 +- + src/conf/ucm/ROCKCHIP-I2S/HiFi.conf | 94 +++++++++++++++++++++++++++++ + src/conf/ucm/ROCKCHIP-I2S/Makefile.am | 4 ++ + src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf | 6 ++ + 5 files changed, 106 insertions(+), 1 deletion(-) + create mode 100644 src/conf/ucm/ROCKCHIP-I2S/HiFi.conf + create mode 100644 src/conf/ucm/ROCKCHIP-I2S/Makefile.am + create mode 100644 src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf + +diff --git a/configure.ac b/configure.ac +index 28fcd24..ff340a8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -658,6 +658,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \ + src/conf/ucm/PAZ00/Makefile \ + src/conf/ucm/GoogleNyan/Makefile \ + src/conf/ucm/broadwell-rt286/Makefile \ ++ src/conf/ucm/ROCKCHIP-I2S/Makefile \ + src/conf/topology/Makefile \ + src/conf/topology/broadwell/Makefile \ + modules/Makefile modules/mixer/Makefile modules/mixer/simple/Makefile \ +diff --git a/src/conf/ucm/Makefile.am b/src/conf/ucm/Makefile.am +index e6a6325..d1d51e5 100644 +--- a/src/conf/ucm/Makefile.am ++++ b/src/conf/ucm/Makefile.am +@@ -1 +1 @@ +-SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 ++SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 ROCKCHIP-I2S +diff --git a/src/conf/ucm/ROCKCHIP-I2S/HiFi.conf b/src/conf/ucm/ROCKCHIP-I2S/HiFi.conf +new file mode 100644 +index 0000000..7bfe995 +--- /dev/null ++++ b/src/conf/ucm/ROCKCHIP-I2S/HiFi.conf +@@ -0,0 +1,94 @@ ++SectionVerb { ++ Value { ++ OutputDspName "speaker_eq" ++ MinBufferLevel "512" ++ } ++ ++ EnableSequence [ ++ cdev "hw:ROCKCHIPI2S" ++ ++ cset "name='Left Speaker Mixer Left DAC Switch' on" ++ cset "name='Right Speaker Mixer Right DAC Switch' on" ++ cset "name='Headphone Left Switch' off" ++ cset "name='Headphone Right Switch' off" ++ cset "name='Digital EQ 3 Band Switch' off" ++ cset "name='Digital EQ 5 Band Switch' off" ++ cset "name='Digital EQ 7 Band Switch' off" ++ cset "name='Biquad Switch' off" ++ cset "name='Filter Mode' Music" ++ cset "name='ADC Oversampling Rate' 0" ++ ++ cset "name='DMIC Mux' DMIC" ++ cset "name='MIC2 Mux' IN34" ++ cset "name='Right ADC Mixer MIC2 Switch' on" ++ cset "name='Left ADC Mixer MIC2 Switch' on" ++ cset "name='MIC2 Volume' 20" ++ cset "name='Headset Mic Switch' off" ++ cset "name='Int Mic Switch' on" ++ ++ cset "name='ADCR Boost Volume' 4" ++ cset "name='ADCL Boost Volume' 4" ++ cset "name='ADCR Volume' 11" ++ cset "name='ADCL Volume' 11" ++ ++ cset "name='Left Speaker Mixer Left DAC Switch' on" ++ cset "name='Right Speaker Mixer Right DAC Switch' on" ++ cset "name='Speaker Left Mixer Volume' 2" ++ cset "name='Speaker Right Mixer Volume' 2" ++ cset "name='Record Path DC Blocking' on" ++ cset "name='Playback Path DC Blocking' on" ++ ++ cset "name='Speaker Left Switch' on" ++ cset "name='Speaker Right Switch' on" ++ cset "name='Speaker Switch' on" ++ ] ++ ++ DisableSequence [ ++ ] ++} ++ ++SectionDevice."Headphone".0 { ++ Value { ++ JackName "ROCKCHIP-I2S Headset Jack" ++ OutputDspName "" ++ } ++ ++ EnableSequence [ ++ cdev "hw:ROCKCHIPI2S" ++ ++ cset "name='Speaker Switch' off" ++ cset "name='Headphone Left Switch' on" ++ cset "name='Headphone Right Switch' on" ++ ] ++ DisableSequence [ ++ cdev "hw:ROCKCHIPI2S" ++ ++ cset "name='Headphone Left Switch' off" ++ cset "name='Headphone Right Switch' off" ++ cset "name='Speaker Switch' on" ++ ] ++} ++ ++SectionDevice."Mic".0 { ++ Value { ++ JackName "ROCKCHIP-I2S Headset Jack" ++ } ++ ++ EnableSequence [ ++ cdev "hw:ROCKCHIPI2S" ++ ++ cset "name='Int Mic Switch' off" ++ cset "name='DMIC Mux' ADC" ++ cset "name='Headset Mic Switch' on" ++ cset "name='Record Path DC Blocking' on" ++ ] ++ ++ DisableSequence [ ++ cdev "hw:ROCKCHIPI2S" ++ ++ cset "name='Headset Mic Switch' off" ++ cset "name='DMIC Mux' DMIC" ++ cset "name='Int Mic Switch' on" ++ cset "name='Record Path DC Blocking' off" ++ ] ++} +diff --git a/src/conf/ucm/ROCKCHIP-I2S/Makefile.am b/src/conf/ucm/ROCKCHIP-I2S/Makefile.am +new file mode 100644 +index 0000000..485a740 +--- /dev/null ++++ b/src/conf/ucm/ROCKCHIP-I2S/Makefile.am +@@ -0,0 +1,4 @@ ++alsaconfigdir = @ALSA_CONFIG_DIR@ ++ucmdir = $(alsaconfigdir)/ucm/ROCKCHIP-I2S ++ucm_DATA = ROCKCHIP-I2S.conf HiFi.conf ++EXTRA_DIST = $(ucm_DATA) +diff --git a/src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf b/src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf +new file mode 100644 +index 0000000..0c399b0 +--- /dev/null ++++ b/src/conf/ucm/ROCKCHIP-I2S/ROCKCHIP-I2S.conf +@@ -0,0 +1,6 @@ ++Comment "Rockchip card" ++ ++SectionUseCase."HiFi" { ++ File "HiFi.conf" ++ Comment "Default" ++} +-- +2.5.5 + +From c14b0a08f0bf58e4f62307c68f8ff0137b4dec19 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 11 May 2016 09:06:47 +0200 +Subject: [PATCH 24/34] pcm: Fix suspend/resume regression with dmix & co + +The recent fix commit [8985742d91db: pcm: dmix: Handle slave PCM xrun +and unexpected states properly] caused a regression in dmix and other +plugins regarding suspend/resume. For example, aplay endlessly prints +"Suspended. Trying resume. Done." message if suspend and resume are +performed in the middle of playback. + +The reason is that the commit above changed the shadow PCM state +(dmix->state) to SUSPENDED when the slave PCM is in suspend, while it +doesn't restore the shadow state upon resume. Thus it appears as if +it's always suspended even after the resume is invoked. + +The fix is just to add the proper update of the shadow state in +snd_pcm_direct_resume(). + +Reported-by: Shengjiu Wang +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_direct.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index 14de734..e28738b 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -848,6 +848,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm) + snd_pcm_start(dmix->spcm); + err = 0; + } ++ dmix->state = snd_pcm_state(dmix->spcm); + snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); + return err; + } +-- +2.5.5 + +From 5610b356b5f110f7f8e586f56e5b74e0f0c2db38 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 11 May 2016 13:06:25 +0200 +Subject: [PATCH 25/34] pcm: dmix: Fix doubly resume of slave PCM + +The dmix plugin and co may trigger the resume for each instance in +snd_pcm_direct_resume(). It means that the slave PCM gets resumed or +re-prepared/started by each opened dmix stream, and this may end up +with the doubly triggers even though the slave PCM has been already +resumed by another dmix stream. + +For avoiding this conflicts, check the slave PCM state and resume only +when it's still in the suspended state. Meanwhile we keep the shadow +state updated no matter whether the slave was triggered or not. + +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_direct.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index e28738b..ac082f1 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -841,6 +841,12 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm) + int err; + + snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); ++ /* resume only when the slave PCM is still in suspended state */ ++ if (snd_pcm_state(dmix->spcm) != SND_PCM_STATE_SUSPENDED) { ++ err = 0; ++ goto out; ++ } ++ + err = snd_pcm_resume(dmix->spcm); + if (err == -ENOSYS) { + /* FIXME: error handling? */ +@@ -848,6 +854,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm) + snd_pcm_start(dmix->spcm); + err = 0; + } ++ out: + dmix->state = snd_pcm_state(dmix->spcm); + snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); + return err; +-- +2.5.5 + +From 8cdbdae73109c901aec4984f6ba65e5b25722f13 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 12 May 2016 16:30:44 +0200 +Subject: [PATCH 26/34] namehint: Don't enumerate as duplex if only a single + direction is defined + +When a hint description has only either device_input or device_output, +we shouldn't handle it as a full duplex but rather a single +direction. In that way, we can avoid to list up a playback stream +like dmix or surround51 as a capture stream in the namehint. + +Reported-by: Trent Reed +Signed-off-by: Takashi Iwai +--- + src/control/namehint.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/control/namehint.c b/src/control/namehint.c +index 856957c..ad8dda3 100644 +--- a/src/control/namehint.c ++++ b/src/control/namehint.c +@@ -28,6 +28,7 @@ + #include "local.h" + + #ifndef DOC_HIDDEN ++#define DEV_SKIP 9999 /* some non-existing device number */ + struct hint_list { + char **list; + unsigned int count; +@@ -90,7 +91,7 @@ static int get_dev_name1(struct hint_list *list, char **res, int device, + int stream) + { + *res = NULL; +- if (device < 0) ++ if (device < 0 || device == DEV_SKIP) + return 0; + switch (list->iface) { + #ifdef BUILD_HWDEP +@@ -317,7 +318,9 @@ static int try_config(snd_config_t *config, + err = -EINVAL; + goto __cleanup; + } +- list->device_output = -1; ++ /* skip the counterpart if only a single direction is defined */ ++ if (list->device_output < 0) ++ list->device_output = DEV_SKIP; + } + if (snd_config_search(cfg, "device_output", &n) >= 0) { + if (snd_config_get_integer(n, &list->device_output) < 0) { +@@ -325,6 +328,9 @@ static int try_config(snd_config_t *config, + err = -EINVAL; + goto __cleanup; + } ++ /* skip the counterpart if only a single direction is defined */ ++ if (list->device_input < 0) ++ list->device_input = DEV_SKIP; + } + } else if (level == 1 && !list->show_all) + goto __skip_add; +-- +2.5.5 + +From 5fb3fe17249c3fffb8b8e15108ff72f27ba5e81c Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 12 May 2016 16:33:19 +0200 +Subject: [PATCH 27/34] pcm: Define namehint for single directional PCM types + +The PCM namehint for some PCM types like dmix, dsnoop and surround51 +should be defined as single directional. + +Reported-by: Trent Reed +Signed-off-by: Takashi Iwai +--- + src/conf/pcm/dmix.conf | 2 +- + src/conf/pcm/dsnoop.conf | 2 +- + src/conf/pcm/surround21.conf | 2 +- + src/conf/pcm/surround40.conf | 2 +- + src/conf/pcm/surround41.conf | 2 +- + src/conf/pcm/surround50.conf | 2 +- + src/conf/pcm/surround51.conf | 2 +- + src/conf/pcm/surround71.conf | 2 +- + 8 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf +index e62cb29..7d0aa01 100644 +--- a/src/conf/pcm/dmix.conf ++++ b/src/conf/pcm/dmix.conf +@@ -110,6 +110,6 @@ pcm.!dmix { + name defaults.namehint.extended + } + description "Direct sample mixing device" +- device $DEV ++ device_output $DEV + } + } +diff --git a/src/conf/pcm/dsnoop.conf b/src/conf/pcm/dsnoop.conf +index 49cfca9..abbd44f 100644 +--- a/src/conf/pcm/dsnoop.conf ++++ b/src/conf/pcm/dsnoop.conf +@@ -110,6 +110,6 @@ pcm.!dsnoop { + name defaults.namehint.extended + } + description "Direct sample snooping device" +- device $DEV ++ device_input $DEV + } + } +diff --git a/src/conf/pcm/surround21.conf b/src/conf/pcm/surround21.conf +index 7f4676b..1cf1b7a 100644 +--- a/src/conf/pcm/surround21.conf ++++ b/src/conf/pcm/surround21.conf +@@ -56,6 +56,6 @@ pcm.!surround21 { + ttable.2.LFE 1 + hint { + description "2.1 Surround output to Front and Subwoofer speakers" +- device $DEV ++ device_output $DEV + } + } +diff --git a/src/conf/pcm/surround40.conf b/src/conf/pcm/surround40.conf +index 361ccaa..9788ad4 100644 +--- a/src/conf/pcm/surround40.conf ++++ b/src/conf/pcm/surround40.conf +@@ -54,6 +54,6 @@ pcm.!surround40 { + } + hint { + description "4.0 Surround output to Front and Rear speakers" +- device $DEV ++ device_output $DEV + } + } +diff --git a/src/conf/pcm/surround41.conf b/src/conf/pcm/surround41.conf +index 2f82381..7b4ef3b 100644 +--- a/src/conf/pcm/surround41.conf ++++ b/src/conf/pcm/surround41.conf +@@ -60,6 +60,6 @@ pcm.!surround41 { + ttable.4.LFE 1 + hint { + description "4.1 Surround output to Front, Rear and Subwoofer speakers" +- device $DEV ++ device_output $DEV + } + } +diff --git a/src/conf/pcm/surround50.conf b/src/conf/pcm/surround50.conf +index dc95c17..7d9a9e7 100644 +--- a/src/conf/pcm/surround50.conf ++++ b/src/conf/pcm/surround50.conf +@@ -60,6 +60,6 @@ pcm.!surround50 { + ttable.4.FC 1 + hint { + description "5.0 Surround output to Front, Center and Rear speakers" +- device $DEV ++ device_output $DEV + } + } +diff --git a/src/conf/pcm/surround51.conf b/src/conf/pcm/surround51.conf +index 3a7543f..e67f007 100644 +--- a/src/conf/pcm/surround51.conf ++++ b/src/conf/pcm/surround51.conf +@@ -56,6 +56,6 @@ pcm.!surround51 { + } + hint { + description "5.1 Surround output to Front, Center, Rear and Subwoofer speakers" +- device $DEV ++ device_output $DEV + } + } +diff --git a/src/conf/pcm/surround71.conf b/src/conf/pcm/surround71.conf +index 076a97d..a26c3f3 100644 +--- a/src/conf/pcm/surround71.conf ++++ b/src/conf/pcm/surround71.conf +@@ -58,6 +58,6 @@ pcm.!surround71 { + } + hint { + description "7.1 Surround output to Front, Center, Side, Rear and Woofer speakers" +- device $DEV ++ device_output $DEV + } + } +-- +2.5.5 + +From c9a0d7d601e8ab069f8745968c03c8470b24d20d Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 17 May 2016 15:39:07 +0200 +Subject: [PATCH 28/34] conf: Add thread-safe global tree reference + +Most of open functions in alsa-lib have the call pattern: + snd_config_update(); + return snd_xxx_open(x, snd_config, ...); + +This means that the toplevel config gets updated, and passed to a +local open function. Although snd_config_update() itself has a +pthread mutex to be thread safe, the whole procedure above isn't +thread safe. Namely, the global snd_config tree may be deleted and +recreated at any time while the open function is being processed. +This may lead to a data corruption and crash of the program. + +For avoiding the corruption, this patch introduces a refcount to +config tree object. A few new helper functions are introduced as +well: +- snd_config_update_ref() does update and take the refcount of the + toplevel tree. The obtained config tree has to be freed via + snd_config_unref() below. +- snd_config_ref() and snd_config_unref() manage the refcount of the + config object. The latter eventually deletes the object when all + references are gone. + +Along with these additions, the caller of snd_config_update() and +snd_config global tree in alsa-lib are replaced with the new helpers. + +Signed-off-by: Takashi Iwai +--- + include/conf.h | 4 +++ + src/conf.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ + src/control/control.c | 8 +++-- + src/hwdep/hwdep.c | 8 +++-- + src/pcm/pcm.c | 8 +++-- + src/rawmidi/rawmidi.c | 8 +++-- + src/seq/seq.c | 8 +++-- + src/timer/timer.c | 8 +++-- + src/timer/timer_query.c | 8 +++-- + 9 files changed, 125 insertions(+), 14 deletions(-) + +diff --git a/include/conf.h b/include/conf.h +index 087c05d..5d293d5 100644 +--- a/include/conf.h ++++ b/include/conf.h +@@ -94,6 +94,10 @@ int snd_config_update_r(snd_config_t **top, snd_config_update_t **update, const + int snd_config_update_free(snd_config_update_t *update); + int snd_config_update_free_global(void); + ++int snd_config_update_ref(snd_config_t **top); ++void snd_config_ref(snd_config_t *top); ++void snd_config_unref(snd_config_t *top); ++ + int snd_config_search(snd_config_t *config, const char *key, + snd_config_t **result); + int snd_config_searchv(snd_config_t *config, +diff --git a/src/conf.c b/src/conf.c +index f8b7a66..a516611 100644 +--- a/src/conf.c ++++ b/src/conf.c +@@ -434,6 +434,7 @@ static pthread_once_t snd_config_update_mutex_once = PTHREAD_ONCE_INIT; + struct _snd_config { + char *id; + snd_config_type_t type; ++ int refcount; /* default = 0 */ + union { + long integer; + long long integer64; +@@ -1825,6 +1826,10 @@ int snd_config_remove(snd_config_t *config) + * If the node is a compound node, its descendants (the whole subtree) + * are deleted recursively. + * ++ * The function is supposed to be called only for locally copied config ++ * trees. For the global tree, take the reference via #snd_config_update_ref ++ * and free it via #snd_config_unref. ++ * + * \par Conforming to: + * LSB 3.2 + * +@@ -1833,6 +1838,10 @@ int snd_config_remove(snd_config_t *config) + int snd_config_delete(snd_config_t *config) + { + assert(config); ++ if (config->refcount > 0) { ++ config->refcount--; ++ return 0; ++ } + switch (config->type) { + case SND_CONFIG_TYPE_COMPOUND: + { +@@ -3833,6 +3842,8 @@ int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, cons + * \warning Whenever #snd_config is updated, all string pointers and + * configuration node handles previously obtained from it may become + * invalid. ++ * For safer operations, use #snd_config_update_ref and release the config ++ * via #snd_config_unref. + * + * \par Errors: + * Any errors encountered when parsing the input or returned by hooks or +@@ -3851,6 +3862,74 @@ int snd_config_update(void) + return err; + } + ++/** ++ * \brief Updates #snd_config and takes its reference. ++ * \return 0 if #snd_config was up to date, 1 if #snd_config was ++ * updated, otherwise a negative error code. ++ * ++ * Unlike #snd_config_update, this function increases a reference counter ++ * so that the obtained tree won't be deleted until unreferenced by ++ * #snd_config_unref. ++ * ++ * This function is supposed to be thread-safe. ++ */ ++int snd_config_update_ref(snd_config_t **top) ++{ ++ int err; ++ ++ if (top) ++ *top = NULL; ++ snd_config_lock(); ++ err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL); ++ if (err >= 0) { ++ if (snd_config) { ++ if (top) { ++ snd_config->refcount++; ++ *top = snd_config; ++ } ++ } else { ++ err = -ENODEV; ++ } ++ } ++ snd_config_unlock(); ++ return err; ++} ++ ++/** ++ * \brief Take the reference of the config tree. ++ * ++ * Increases a reference counter of the given config tree. ++ * ++ * This function is supposed to be thread-safe. ++ */ ++void snd_config_ref(snd_config_t *cfg) ++{ ++ snd_config_lock(); ++ if (cfg) ++ cfg->refcount++; ++ snd_config_unlock(); ++} ++ ++/** ++ * \brief Unreference the config tree. ++ * ++ * Decreases a reference counter of the given config tree, and eventually ++ * deletes the tree if all references are gone. This is the counterpart of ++ * #snd_config_unref. ++ * ++ * Also, the config taken via #snd_config_update_ref must be unreferenced ++ * by this function, too. ++ * ++ * This function is supposed to be thread-safe. ++ */ ++void snd_config_unref(snd_config_t *cfg) ++{ ++ snd_config_lock(); ++ if (cfg) ++ snd_config_delete(cfg); ++ snd_config_unlock(); ++} ++ + /** + * \brief Frees a private update structure. + * \param[in] update The private update structure to free. +diff --git a/src/control/control.c b/src/control/control.c +index 8a5d530..ae78843 100644 +--- a/src/control/control.c ++++ b/src/control/control.c +@@ -968,12 +968,16 @@ static int snd_ctl_open_noupdate(snd_ctl_t **ctlp, snd_config_t *root, const cha + */ + int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode) + { ++ snd_config_t *top; + int err; ++ + assert(ctlp && name); +- err = snd_config_update(); ++ err = snd_config_update_ref(&top); + if (err < 0) + return err; +- return snd_ctl_open_noupdate(ctlp, snd_config, name, mode); ++ err = snd_ctl_open_noupdate(ctlp, top, name, mode); ++ snd_config_unref(top); ++ return err; + } + + /** +diff --git a/src/hwdep/hwdep.c b/src/hwdep/hwdep.c +index 5dc791c..bac634b 100644 +--- a/src/hwdep/hwdep.c ++++ b/src/hwdep/hwdep.c +@@ -168,12 +168,16 @@ static int snd_hwdep_open_noupdate(snd_hwdep_t **hwdep, snd_config_t *root, cons + */ + int snd_hwdep_open(snd_hwdep_t **hwdep, const char *name, int mode) + { ++ snd_config_t *top; + int err; ++ + assert(hwdep && name); +- err = snd_config_update(); ++ err = snd_config_update_ref(&top); + if (err < 0) + return err; +- return snd_hwdep_open_noupdate(hwdep, snd_config, name, mode); ++ err = snd_hwdep_open_noupdate(hwdep, top, name, mode); ++ snd_config_unref(top); ++ return err; + } + + /** +diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c +index 203e7a5..0d0d093 100644 +--- a/src/pcm/pcm.c ++++ b/src/pcm/pcm.c +@@ -2288,12 +2288,16 @@ static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root, + int snd_pcm_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_stream_t stream, int mode) + { ++ snd_config_t *top; + int err; ++ + assert(pcmp && name); +- err = snd_config_update(); ++ err = snd_config_update_ref(&top); + if (err < 0) + return err; +- return snd_pcm_open_noupdate(pcmp, snd_config, name, stream, mode, 0); ++ err = snd_pcm_open_noupdate(pcmp, top, name, stream, mode, 0); ++ snd_config_unref(top); ++ return err; + } + + /** +diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c +index 0c89b8b..4701b43 100644 +--- a/src/rawmidi/rawmidi.c ++++ b/src/rawmidi/rawmidi.c +@@ -305,12 +305,16 @@ static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **out + int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, + const char *name, int mode) + { ++ snd_config_t *top; + int err; ++ + assert((inputp || outputp) && name); +- err = snd_config_update(); ++ err = snd_config_update_ref(&top); + if (err < 0) + return err; +- return snd_rawmidi_open_noupdate(inputp, outputp, snd_config, name, mode); ++ err = snd_rawmidi_open_noupdate(inputp, outputp, top, name, mode); ++ snd_config_unref(top); ++ return err; + } + + /** +diff --git a/src/seq/seq.c b/src/seq/seq.c +index 4405e68..9279830 100644 +--- a/src/seq/seq.c ++++ b/src/seq/seq.c +@@ -974,12 +974,16 @@ static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root, + int snd_seq_open(snd_seq_t **seqp, const char *name, + int streams, int mode) + { ++ snd_config_t *top; + int err; ++ + assert(seqp && name); +- err = snd_config_update(); ++ err = snd_config_update_ref(&top); + if (err < 0) + return err; +- return snd_seq_open_noupdate(seqp, snd_config, name, streams, mode, 0); ++ err = snd_seq_open_noupdate(seqp, top, name, streams, mode, 0); ++ snd_config_unref(top); ++ return err; + } + + /** +diff --git a/src/timer/timer.c b/src/timer/timer.c +index a25e4f7..b253471 100644 +--- a/src/timer/timer.c ++++ b/src/timer/timer.c +@@ -201,12 +201,16 @@ static int snd_timer_open_noupdate(snd_timer_t **timer, snd_config_t *root, cons + */ + int snd_timer_open(snd_timer_t **timer, const char *name, int mode) + { ++ snd_config_t *top; + int err; ++ + assert(timer && name); +- err = snd_config_update(); ++ err = snd_config_update_ref(&top); + if (err < 0) + return err; +- return snd_timer_open_noupdate(timer, snd_config, name, mode); ++ err = snd_timer_open_noupdate(timer, top, name, mode); ++ snd_config_unref(top); ++ return err; + } + + /** +diff --git a/src/timer/timer_query.c b/src/timer/timer_query.c +index 93d2455..2072cea 100644 +--- a/src/timer/timer_query.c ++++ b/src/timer/timer_query.c +@@ -159,12 +159,16 @@ static int snd_timer_query_open_noupdate(snd_timer_query_t **timer, snd_config_t + */ + int snd_timer_query_open(snd_timer_query_t **timer, const char *name, int mode) + { ++ snd_config_t *top; + int err; ++ + assert(timer && name); +- err = snd_config_update(); ++ err = snd_config_update_ref(&top); + if (err < 0) + return err; +- return snd_timer_query_open_noupdate(timer, snd_config, name, mode); ++ err = snd_timer_query_open_noupdate(timer, top, name, mode); ++ snd_config_unref(top); ++ return err; + } + + /** +-- +2.5.5 + +From d942498bfbd315c4c4559ccd573685e09aa03383 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 18 May 2016 10:38:27 +0200 +Subject: [PATCH 29/34] pcm: Remove resume support from dmix & co + +PCM dmix and other plugins inherit the resume behavior from the slave +PCM. However, the resume on dmix can't work reliably even if the +slave PCM may do resume. The running state of each dmix stream is +individual and may be PREPARED or RUN_PENDING while the slave PCM is +already in RUNNING. And, when the slave PCM is resumed, the whole +samples that have been already mapped are also played back, even if +the corresponding dmix stream is still in SUSPENDED. Such +inconsistencies can't be avoided as long as we manage each stream +individually. + +That said, dmix & co can't provide the proper resume support "by +design". For aligning with it, we should drop the whole resume code +and clear the PCM SND_PCM_INFO_RESUME flag. + +Reported-by: Shengjiu Wang +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_direct.c | 24 ++---------------------- + 1 file changed, 2 insertions(+), 22 deletions(-) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index ac082f1..53c4992 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -837,27 +837,7 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm) + + int snd_pcm_direct_resume(snd_pcm_t *pcm) + { +- snd_pcm_direct_t *dmix = pcm->private_data; +- int err; +- +- snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); +- /* resume only when the slave PCM is still in suspended state */ +- if (snd_pcm_state(dmix->spcm) != SND_PCM_STATE_SUSPENDED) { +- err = 0; +- goto out; +- } +- +- err = snd_pcm_resume(dmix->spcm); +- if (err == -ENOSYS) { +- /* FIXME: error handling? */ +- snd_pcm_prepare(dmix->spcm); +- snd_pcm_start(dmix->spcm); +- err = 0; +- } +- out: +- dmix->state = snd_pcm_state(dmix->spcm); +- snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); +- return err; ++ return -ENOSYS; + } + + #define COPY_SLAVE(field) (dmix->shmptr->s.field = spcm->field) +@@ -865,7 +845,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm) + /* copy the slave setting */ + static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) + { +- spcm->info &= ~SND_PCM_INFO_PAUSE; ++ spcm->info &= ~(SND_PCM_INFO_PAUSE | SND_PCM_INFO_RESUME); + + COPY_SLAVE(access); + COPY_SLAVE(format); +-- +2.5.5 + +From 2fa36eb03c000560128f7abce701536546b4a618 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Sat, 28 May 2016 10:37:26 +0200 +Subject: [PATCH 30/34] pcm: Fix secondary retry in dsnoop and dshare + +The commit [fdba9e1bad8f: pcm: Fallback open as the first instance for +dmix & co] introduced a mechanism to retry the open of slave PCM for +the secondary streams, but this also introduced a regression in dsnoop +and dshare plugins: since the retry goto-tag was placed at a wrong +position, it retries to re-fetch the shm unnecessarily and eventually +leads to the fatal error. + +The bug can be easily reproduced by starting arecord and killing it +via SIGKILL, then starting arecord again. The second arecord fails. + +The fix is obviously to move the wrong retry goto-tags to the right +positions. + +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_dshare.c | 2 +- + src/pcm/pcm_dsnoop.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c +index adb3587..05854de 100644 +--- a/src/pcm/pcm_dshare.c ++++ b/src/pcm/pcm_dshare.c +@@ -690,7 +690,6 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, + break; + } + +- retry: + first_instance = ret = snd_pcm_direct_shm_create_or_connect(dshare); + if (ret < 0) { + SNDERR("unable to create IPC shm instance"); +@@ -705,6 +704,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, + dshare->max_periods = opts->max_periods; + dshare->sync_ptr = snd_pcm_dshare_sync_ptr; + ++ retry: + if (first_instance) { + /* recursion is already checked in + snd_pcm_direct_get_slave_ipc_offset() */ +diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c +index 8ff0ba5..2d45171 100644 +--- a/src/pcm/pcm_dsnoop.c ++++ b/src/pcm/pcm_dsnoop.c +@@ -583,7 +583,6 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, + break; + } + +- retry: + first_instance = ret = snd_pcm_direct_shm_create_or_connect(dsnoop); + if (ret < 0) { + SNDERR("unable to create IPC shm instance"); +@@ -598,6 +597,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, + dsnoop->max_periods = opts->max_periods; + dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr; + ++ retry: + if (first_instance) { + /* recursion is already checked in + snd_pcm_direct_get_slave_ipc_offset() */ +-- +2.5.5 + +From 6d1d620eadf32c6d963468ce56ff52cc3a2f32e2 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 25 May 2016 15:03:51 +0200 +Subject: [PATCH 31/34] pcm: dmix: resume workaround for buggy driver + +The previous commit removed the whole handling of resume in dmix, but +this seems causing another regression; some buggy drivers assume that +the device-resume needs to be triggered before transitioning to +PREPARED state. As an ugly workaround, in this patch, when the slave +PCM supports resume, snd_pcm_direct_resume() does resume of the slave +PCM but immediately drop the stream after that. In that way, the +device is brought to the sane active state, then the apps can prepare +and restart the stream properly. + +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_direct.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index 53c4992..343fd3c 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -837,6 +837,27 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm) + + int snd_pcm_direct_resume(snd_pcm_t *pcm) + { ++ snd_pcm_direct_t *dmix = pcm->private_data; ++ snd_pcm_t *spcm = dmix->spcm; ++ ++ snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); ++ /* some buggy drivers require the device resumed before prepared; ++ * when a device has RESUME flag and is in SUSPENDED state, resume ++ * here but immediately drop to bring it to a sane active state. ++ */ ++ if ((spcm->info & SND_PCM_INFO_RESUME) && ++ snd_pcm_state(spcm) == SND_PCM_STATE_SUSPENDED) { ++ snd_pcm_resume(spcm); ++ snd_pcm_drop(spcm); ++ snd_pcm_direct_timer_stop(dmix); ++ snd_pcm_direct_clear_timer_queue(dmix); ++ snd_pcm_areas_silence(snd_pcm_mmap_areas(spcm), 0, ++ spcm->channels, spcm->buffer_size, ++ spcm->format); ++ snd_pcm_prepare(spcm); ++ snd_pcm_start(spcm); ++ } ++ snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); + return -ENOSYS; + } + +@@ -845,7 +866,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm) + /* copy the slave setting */ + static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) + { +- spcm->info &= ~(SND_PCM_INFO_PAUSE | SND_PCM_INFO_RESUME); ++ spcm->info &= ~SND_PCM_INFO_PAUSE; + + COPY_SLAVE(access); + COPY_SLAVE(format); +@@ -874,6 +895,8 @@ static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) + COPY_SLAVE(buffer_time); + COPY_SLAVE(sample_bits); + COPY_SLAVE(frame_bits); ++ ++ dmix->shmptr->s.info &= ~SND_PCM_INFO_RESUME; + } + + #undef COPY_SLAVE +-- +2.5.5 + +From 8feb96ed9b457c2aa62ddea2c48651475b7c3411 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 31 May 2016 12:46:03 +0200 +Subject: [PATCH 32/34] pcm: dmix: Prepare slave when it's in SETUP, too + +SETUP is an unusual state, but it's still possible. + +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_direct.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index 343fd3c..fbf9a59 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -819,6 +819,7 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm) + int err; + + switch (snd_pcm_state(dmix->spcm)) { ++ case SND_PCM_STATE_SETUP: + case SND_PCM_STATE_XRUN: + case SND_PCM_STATE_SUSPENDED: + case SND_PCM_STATE_DISCONNECTED: +-- +2.5.5 + +From 614ce73d3d6eba13946f863bec24981d355902e1 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 31 May 2016 12:48:40 +0200 +Subject: [PATCH 33/34] pcm: dmix: Return error when slave is in OPEN or + DISCONNECTED + +A slave PCM in OPEN or DISCONNECTED state can't be used properly at +all, so the best option is to return -EBADFD error. + +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_direct.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index fbf9a59..21f98e7 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -822,12 +822,14 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm) + case SND_PCM_STATE_SETUP: + case SND_PCM_STATE_XRUN: + case SND_PCM_STATE_SUSPENDED: +- case SND_PCM_STATE_DISCONNECTED: + err = snd_pcm_prepare(dmix->spcm); + if (err < 0) + return err; + snd_pcm_start(dmix->spcm); + break; ++ case SND_PCM_STATE_OPEN: ++ case SND_PCM_STATE_DISCONNECTED: ++ return -EBADFD; + } + snd_pcm_direct_check_interleave(dmix, pcm); + dmix->state = SND_PCM_STATE_PREPARED; +-- +2.5.5 + +From d39e1879b9c72d51fe1ca4aeb5ba742e97b2175a Mon Sep 17 00:00:00 2001 +From: Eliot Miranda +Date: Wed, 1 Jun 2016 08:16:31 +0200 +Subject: [PATCH 34/34] async: Handle previously installed signal handler + +The issue is with the signal handler installed and deinstalled in +alsa-lib async handler. This code makes no attempt to remember any +previously installed signal handlers for SIGIO, if SIGIO is used. +Consequently it does not call any previous handlers from its own +handler once installed, and does not reinstall any previous handler +when deinstalling its handler. Consequently, use of also-lib within +applications that depend on SIGIO will break those applications, +rendering them inoperative once alsa-lib is running because their +signal handlers are no longer called. + +This patch does remember and restore any previous handler, and chains +calls to the handler if it exists. + +Signed-off-by: Takashi Iwai +--- + src/async.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/src/async.c b/src/async.c +index 98aec78..0e133c3 100644 +--- a/src/async.c ++++ b/src/async.c +@@ -28,6 +28,9 @@ + #include "control/control_local.h" + #include + ++static struct sigaction previous_action; ++#define MAX_SIG_FUNCTION_CODE 10 /* i.e. SIG_DFL SIG_IGN SIG_HOLD et al */ ++ + #ifdef SND_ASYNC_RT_SIGNAL + /** async signal number */ + static int snd_async_signo; +@@ -54,6 +57,9 @@ static void snd_async_handler(int signo ATTRIBUTE_UNUSED, siginfo_t *siginfo, vo + int fd; + struct list_head *i; + //assert(siginfo->si_code == SI_SIGIO); ++ if (signo == SIGIO ++ && (unsigned long)(previous_action.sa_sigaction) > MAX_SIG_FUNCTION_CODE) ++ previous_action.sa_sigaction(signo, siginfo, context); + fd = siginfo->si_fd; + list_for_each(i, &snd_async_handlers) { + snd_async_handler_t *h = list_entry(i, snd_async_handler_t, glist); +@@ -114,7 +120,8 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd, + act.sa_flags = SA_RESTART | SA_SIGINFO; + act.sa_sigaction = snd_async_handler; + sigemptyset(&act.sa_mask); +- err = sigaction(snd_async_signo, &act, NULL); ++ assert(!previous_action.sa_sigaction); ++ err = sigaction(snd_async_signo, &act, &previous_action); + if (err < 0) { + SYSERR("sigaction"); + return -errno; +@@ -131,18 +138,17 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd, + int snd_async_del_handler(snd_async_handler_t *handler) + { + int err = 0; ++ int was_empty = list_empty(&snd_async_handlers); + assert(handler); + list_del(&handler->glist); +- if (list_empty(&snd_async_handlers)) { +- struct sigaction act; +- memset(&act, 0, sizeof(act)); +- act.sa_flags = 0; +- act.sa_handler = SIG_DFL; +- err = sigaction(snd_async_signo, &act, NULL); ++ if (!was_empty ++ && list_empty(&snd_async_handlers)) { ++ err = sigaction(snd_async_signo, &previous_action, NULL); + if (err < 0) { + SYSERR("sigaction"); + return -errno; + } ++ memset(&previous_action, 0, sizeof(previous_action)); + } + if (handler->type == SND_ASYNC_HANDLER_GENERIC) + goto _end; +-- +2.5.5 + diff --git a/SPECS/alsa-lib.spec b/SPECS/alsa-lib.spec index 19ac289..a507780 100644 --- a/SPECS/alsa-lib.spec +++ b/SPECS/alsa-lib.spec @@ -4,8 +4,8 @@ Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib -Version: 1.0.28 -Release: 2%{?prever_dot}%{?dist} +Version: 1.1.1 +Release: 1%{?prever_dot}%{?dist} License: LGPLv2+ Group: System Environment/Libraries URL: http://www.alsa-project.org/ @@ -14,10 +14,9 @@ Source: ftp://ftp.alsa-project.org/pub/lib/%{name}-%{version}%{?prever}%{?post Source10: asound.conf Source11: modprobe-dist-alsa.conf Source12: modprobe-dist-oss.conf -Patch0: alsa-lib-1.0.24-config.patch -Patch2: alsa-lib-1.0.14-glibc-open.patch -Patch4: alsa-lib-1.0.16-no-dox-date.patch -Patch5: alsa-lib-1.0.28-post.patch +Patch0: alsa-lib-1.1.1-post.patch +Patch1: alsa-lib-1.1.0-config.patch +Patch2: alsa-lib-1.0.16-no-dox-date.patch BuildRequires: doxygen Requires(post): /sbin/ldconfig, coreutils @@ -45,10 +44,9 @@ against the ALSA libraries and interfaces. %prep %setup -q -n %{name}-%{version}%{?prever}%{?postver} -%patch0 -p1 -b .config -%patch2 -p1 -b .glibc-open -%patch4 -p1 -b .no-dox-date -%patch5 -p1 -b .post +%patch0 -p1 -b .post +%patch1 -p1 -b .config +%patch2 -p1 -b .dox-date %build %configure --disable-aload --with-plugindir=%{_libdir}/alsa-lib --disable-alisp @@ -76,8 +74,8 @@ install -p -m 644 %{SOURCE10} %{buildroot}/etc mkdir -p -m 755 %{buildroot}/lib/modprobe.d/ install -p -m 644 %{SOURCE11} %{buildroot}/lib/modprobe.d/dist-alsa.conf # bug#926973, place this file to the doc directory -mkdir -p -m 755 %{buildroot}%{_defaultdocdir}/%{name}-%{version}/ -install -p -m 644 %{SOURCE12} %{buildroot}%{_defaultdocdir}/%{name}-%{version}/modprobe-dist-oss.conf +mkdir -p -m 755 %{buildroot}%{_defaultdocdir}/%{name}/ +install -p -m 644 %{SOURCE12} %{buildroot}%{_defaultdocdir}/%{name}/modprobe-dist-oss.conf # Create UCM directory mkdir -p %{buildroot}/%{_datadir}/alsa/ucm @@ -96,6 +94,7 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';' %doc COPYING TODO doc/asoundrc.txt # file is as old as 0.2.0 / Red Hat bugzilla #510212 #doc Changelog +%{_defaultdocdir}/%{name}/modprobe-dist-oss.conf %config %{_sysconfdir}/asound.conf /%{_lib}/libasound.so.* %{_bindir}/aserver @@ -113,6 +112,10 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';' %{_datadir}/aclocal/alsa.m4 %changelog +* Mon Jun 6 2016 Jaroslav Kysela - 1.1.1-1 +- Updated to 1.1.1 +- Resolves: rhbz#1297932 + * Tue Sep 16 2014 Jaroslav Kysela - 1.0.28-2 - Fix minor coverity bug @@ -214,7 +217,7 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';' * Tue Jan 20 2009 Jaroslav Kysela - 1.0.19-1 - Updated to 1.0.19 final -* Wed Nov 4 2008 Jaroslav Kysela - 1.0.18-7 +* Tue Nov 4 2008 Jaroslav Kysela - 1.0.18-7 - Updated to 1.0.18 final * Wed Sep 10 2008 Jaroslav Kysela - 1.0.18-6.rc3 @@ -331,7 +334,7 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';' - fix for #169729 - Kernel update makes snd-atiixp-modem & slmodemd fail - new ainit (0.7) should fix some problems with root users -* Tue Jan 12 2006 Martin Stransky 1.0.11-1.rc2 +* Thu Jan 12 2006 Martin Stransky 1.0.11-1.rc2 - new upstream version * Tue Jan 3 2006 Jesse Keating 1.0.10rf-4 @@ -391,7 +394,7 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';' * Mon Mar 7 2005 Martin Stransky 1.0.8-4.devel - gcc4 patch -* Wed Feb 15 2005 Martin Stransky 1.0.8-3.devel +* Tue Feb 15 2005 Martin Stransky 1.0.8-3.devel - add $RPM_OPT_FLAGS to CFLAGS * Fri Feb 11 2005 Martin Stransky 1.0.8-2.devel @@ -459,5 +462,5 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';' * Wed Nov 26 2003 Than Ngo 0.9.8-2 - fixed dependant libraries check on x86_64 -* Mon Nov 4 2003 Bill Nottingham - 0.9.8-1 +* Tue Nov 4 2003 Bill Nottingham - 0.9.8-1 - initial build, modify spec file from Matthias Saou