Hello community,

here is the log from the commit of package alsa for openSUSE:Factory checked in 
at 2020-01-02 14:40:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/alsa (Old)
 and      /work/SRC/openSUSE:Factory/.alsa.new.6675 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "alsa"

Thu Jan  2 14:40:05 2020 rev:195 rq:758568 version:1.2.1.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/alsa/alsa.changes        2019-12-02 
11:34:46.954462026 +0100
+++ /work/SRC/openSUSE:Factory/.alsa.new.6675/alsa.changes      2020-01-02 
14:40:18.252887202 +0100
@@ -1,0 +2,45 @@
+Fri Dec 20 16:54:25 CET 2019 - ti...@suse.de
+
+- Upstream fixes, including the alsa-tools build breakage:
+  0001-ucm-Use-strncmp-to-avoid-access-out-of-boundary.patch
+  0002-ucm-return-always-at-least-NULL-if-no-list-is-availa.patch
+  0003-ucm-add-_identifiers-list.patch
+  0004-namehint-correct-the-args-check.patch
+  0005-namehint-improve-the-previous-patch-check-the-return.patch
+  0006-ucm-docs-allow-spaces-in-device-names-for-JackHWMute.patch
+  0007-use-case-docs-add-PlaybackMixerCopy-and-CaptureMixer.patch
+  0008-ucm-docs-add-JackCTL-rearrange-JackControl-and-JackD.patch
+  0009-ucm-Do-not-fail-to-parse-configs-on-cards-with-an-em.patch
+  0010-src-ucm-main.c-fix-build-without-mixer.patch
+  0011-alsa.m4-another-try-to-fix-the-libatopology-detectio.patch
+  0012-ucm-docs-add-Mic-DigitalMic-and-multiple-devices-com.patch
+  0013-ucm-docs-remove-DigitalMic-it-does-not-have-sense.patch
+  0014-ucm-docs-change-the-Mic-description-to-simple-Microp.patch
+  0015-ucm-docs-add-note-about-the-sequences-and-device-spl.patch
+  0016-ucm-docs-remove-MixerCopy-values-add-Priority-for-ve.patch
+  0017-ucm-setup-conf_format-after-getting-ALSA_CONFIG_UCM_.patch
+  0018-alsa-lib-fix-the-array-parser-unique-compound-keys.patch
+  0019-topology-remove-vendor_fd-name-from-snd_tplg-structu.patch
+  0020-topology-file-position-and-size-cleanups.patch
+  0021-topology-use-an-array-describing-blocks-for-the-main.patch
+  0022-topology-use-size_t-for-calc_block_size.patch
+  0023-topology-merge-write_block-to-tplg_write_data.patch
+  0024-topology-make-vebose-output-more-nice.patch
+  0025-topology-use-list_insert-macro-in-tplg_elem_insert.patch
+  0026-topology-dapm-coding-fixes.patch
+  0027-topology-dapm-merge-identical-index-blocks-like-for-.patch
+  0028-topology-more-coding-fixes.patch
+  0029-Fix-alsa-sound-.h-for-external-programs.patch
+  0030-type_compat-Add-missing-__s64-and-__u64-definitions-.patch
+  0031-uapi-Move-typedefs-from-uapi-to-sound.patch
+
+-------------------------------------------------------------------
+Fri Nov 29 20:41:29 CET 2019 - ti...@suse.de
+
+- Update to alsa-lib 1.2.1.2:
+  More UCM and UCMv2 fixes / enhancements, details are found in
+    https://www.alsa-project.org/wiki/Changes_v1.2.1.1_v1.2.1.2
+- Obsoleted patch:
+  0001-alsa.m4-Fix-the-detection-of-topology-library-availa.patch 
+
+-------------------------------------------------------------------

Old:
----
  0001-alsa.m4-Fix-the-detection-of-topology-library-availa.patch
  alsa-lib-1.2.1.1.tar.bz2

New:
----
  0001-ucm-Use-strncmp-to-avoid-access-out-of-boundary.patch
  0002-ucm-return-always-at-least-NULL-if-no-list-is-availa.patch
  0003-ucm-add-_identifiers-list.patch
  0004-namehint-correct-the-args-check.patch
  0005-namehint-improve-the-previous-patch-check-the-return.patch
  0006-ucm-docs-allow-spaces-in-device-names-for-JackHWMute.patch
  0007-use-case-docs-add-PlaybackMixerCopy-and-CaptureMixer.patch
  0008-ucm-docs-add-JackCTL-rearrange-JackControl-and-JackD.patch
  0009-ucm-Do-not-fail-to-parse-configs-on-cards-with-an-em.patch
  0010-src-ucm-main.c-fix-build-without-mixer.patch
  0011-alsa.m4-another-try-to-fix-the-libatopology-detectio.patch
  0012-ucm-docs-add-Mic-DigitalMic-and-multiple-devices-com.patch
  0013-ucm-docs-remove-DigitalMic-it-does-not-have-sense.patch
  0014-ucm-docs-change-the-Mic-description-to-simple-Microp.patch
  0015-ucm-docs-add-note-about-the-sequences-and-device-spl.patch
  0016-ucm-docs-remove-MixerCopy-values-add-Priority-for-ve.patch
  0017-ucm-setup-conf_format-after-getting-ALSA_CONFIG_UCM_.patch
  0018-alsa-lib-fix-the-array-parser-unique-compound-keys.patch
  0019-topology-remove-vendor_fd-name-from-snd_tplg-structu.patch
  0020-topology-file-position-and-size-cleanups.patch
  0021-topology-use-an-array-describing-blocks-for-the-main.patch
  0022-topology-use-size_t-for-calc_block_size.patch
  0023-topology-merge-write_block-to-tplg_write_data.patch
  0024-topology-make-vebose-output-more-nice.patch
  0025-topology-use-list_insert-macro-in-tplg_elem_insert.patch
  0026-topology-dapm-coding-fixes.patch
  0027-topology-dapm-merge-identical-index-blocks-like-for-.patch
  0028-topology-more-coding-fixes.patch
  0029-Fix-alsa-sound-.h-for-external-programs.patch
  0030-type_compat-Add-missing-__s64-and-__u64-definitions-.patch
  0031-uapi-Move-typedefs-from-uapi-to-sound.patch
  alsa-lib-1.2.1.2.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ alsa.spec ++++++
--- /var/tmp/diff_new_pack.ePl5ni/_old  2020-01-02 14:40:19.388887651 +0100
+++ /var/tmp/diff_new_pack.ePl5ni/_new  2020-01-02 14:40:19.388887651 +0100
@@ -26,7 +26,7 @@
 %endif
 
 Name:           alsa
-Version:        1.2.1.1
+Version:        1.2.1.2
 Release:        0
 Summary:        Advanced Linux Sound Architecture
 License:        LGPL-2.1-or-later
@@ -48,7 +48,37 @@
 Source32:       all_notes_off.mid
 Source34:       alsa-init.sh
 # upstream fixes
-Patch1:         0001-alsa.m4-Fix-the-detection-of-topology-library-availa.patch
+Patch1:         0001-ucm-Use-strncmp-to-avoid-access-out-of-boundary.patch
+Patch2:         0002-ucm-return-always-at-least-NULL-if-no-list-is-availa.patch
+Patch3:         0003-ucm-add-_identifiers-list.patch
+Patch4:         0004-namehint-correct-the-args-check.patch
+Patch5:         0005-namehint-improve-the-previous-patch-check-the-return.patch
+Patch6:         0006-ucm-docs-allow-spaces-in-device-names-for-JackHWMute.patch
+Patch7:         0007-use-case-docs-add-PlaybackMixerCopy-and-CaptureMixer.patch
+Patch8:         0008-ucm-docs-add-JackCTL-rearrange-JackControl-and-JackD.patch
+Patch9:         0009-ucm-Do-not-fail-to-parse-configs-on-cards-with-an-em.patch
+Patch10:        0010-src-ucm-main.c-fix-build-without-mixer.patch
+Patch11:        0011-alsa.m4-another-try-to-fix-the-libatopology-detectio.patch
+Patch12:        0012-ucm-docs-add-Mic-DigitalMic-and-multiple-devices-com.patch
+Patch13:        0013-ucm-docs-remove-DigitalMic-it-does-not-have-sense.patch
+Patch14:        0014-ucm-docs-change-the-Mic-description-to-simple-Microp.patch
+Patch15:        0015-ucm-docs-add-note-about-the-sequences-and-device-spl.patch
+Patch16:        0016-ucm-docs-remove-MixerCopy-values-add-Priority-for-ve.patch
+Patch17:        0017-ucm-setup-conf_format-after-getting-ALSA_CONFIG_UCM_.patch
+Patch18:        0018-alsa-lib-fix-the-array-parser-unique-compound-keys.patch
+Patch19:        0019-topology-remove-vendor_fd-name-from-snd_tplg-structu.patch
+Patch20:        0020-topology-file-position-and-size-cleanups.patch
+Patch21:        0021-topology-use-an-array-describing-blocks-for-the-main.patch
+Patch22:        0022-topology-use-size_t-for-calc_block_size.patch
+Patch23:        0023-topology-merge-write_block-to-tplg_write_data.patch
+Patch24:        0024-topology-make-vebose-output-more-nice.patch
+Patch25:        0025-topology-use-list_insert-macro-in-tplg_elem_insert.patch
+Patch26:        0026-topology-dapm-coding-fixes.patch
+Patch27:        0027-topology-dapm-merge-identical-index-blocks-like-for-.patch
+Patch28:        0028-topology-more-coding-fixes.patch
+Patch29:        0029-Fix-alsa-sound-.h-for-external-programs.patch
+Patch30:        0030-type_compat-Add-missing-__s64-and-__u64-definitions-.patch
+Patch31:        0031-uapi-Move-typedefs-from-uapi-to-sound.patch
 # rest suse fixes
 Patch101:       alsa-lib-ignore-non-accessible-ALSA_CONFIG_PATH.patch
 BuildRequires:  doxygen
@@ -134,6 +164,36 @@
 %prep
 %setup -q -n alsa-lib-%{version}
 %patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
+%patch31 -p1
 %patch101 -p1
 
 %build
@@ -141,7 +201,7 @@
 %define _lto_cflags %{nil}
 export AUTOMAKE_JOBS="%{?_smp_mflags}"
 # build alsa-lib
-# autoreconf -fi
+autoreconf -fi
 %configure \
   --disable-static \
   --enable-symbolic-functions \

++++++ 0001-ucm-Use-strncmp-to-avoid-access-out-of-boundary.patch ++++++
>From c79f09e1f5e8b559b58dacdb00708d995b2e3aa5 Mon Sep 17 00:00:00 2001
From: paulhsia <paulh...@chromium.org>
Date: Sat, 30 Nov 2019 03:35:30 +0800
Subject: [PATCH 01/30] ucm: Use strncmp to avoid access-out-of-boundary

If the length of the identifier is less than the length of the prefix,
access-out-of-boundary will occur in memcmp().

Signed-off-by: paulhsia <paulh...@chromium.org>
Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/ucm/main.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/ucm/main.c b/src/ucm/main.c
index b0b6ffb34be5..252e50d9a387 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -61,11 +61,13 @@ static int check_identifier(const char *identifier, const 
char *prefix)
 {
        int len;
 
-       if (strcmp(identifier, prefix) == 0)
-               return 1;
        len = strlen(prefix);
-       if (memcmp(identifier, prefix, len) == 0 && identifier[len] == '/')
+       if (strncmp(identifier, prefix, len) != 0)
+               return 0;
+
+       if (identifier[len] == 0 || identifier[len] == '/')
                return 1;
+
        return 0;
 }
 
-- 
2.16.4

++++++ 0002-ucm-return-always-at-least-NULL-if-no-list-is-availa.patch ++++++
>From 9baf64da2f26844434ecea4825052937a3abe06c Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 29 Nov 2019 22:28:26 +0100
Subject: [PATCH 02/30] ucm: return always at least NULL if no list is
 available in snd_use_case_get_list()

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/ucm/main.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/ucm/main.c b/src/ucm/main.c
index 252e50d9a387..b80db65fa93b 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -1160,8 +1160,10 @@ static int get_supcon_device_list(snd_use_case_mgr_t 
*uc_mgr,
 
        modifier = find_modifier(uc_mgr, verb, name, 0);
        if (modifier) {
-               if (modifier->dev_list.type != type)
+               if (modifier->dev_list.type != type) {
+                       *list = NULL;
                        return 0;
+               }
                return get_list(&modifier->dev_list.list, list,
                                struct dev_list_node, list,
                                name);
@@ -1169,8 +1171,10 @@ static int get_supcon_device_list(snd_use_case_mgr_t 
*uc_mgr,
 
        device = find_device(uc_mgr, verb, name, 0);
        if (device) {
-               if (device->dev_list.type != type)
+               if (device->dev_list.type != type) {
+                       *list = NULL;
                        return 0;
+               }
                return get_list(&device->dev_list.list, list,
                                struct dev_list_node, list,
                                name);
-- 
2.16.4

++++++ 0003-ucm-add-_identifiers-list.patch ++++++
>From ebdd2b6cdb8119cf75f0dd0a3b283d271b3a547e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Sat, 30 Nov 2019 20:31:55 +0100
Subject: [PATCH 03/30] ucm: add _identifiers list

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h |   1 +
 src/ucm/main.c     | 268 +++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 208 insertions(+), 61 deletions(-)

diff --git a/include/use-case.h b/include/use-case.h
index 8e7e838c9cb9..85c58ac0614a 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -206,6 +206,7 @@ int snd_use_case_free_list(const char *list[], int items);
  *   - _enadevs                        - get list of enabled devices
  *   - _enamods                        - get list of enabled modifiers
  *
+ *   - _identifiers/{modifier}|{device}[/{verb}]     - list of value 
identifiers
  *   - _supporteddevs/{modifier}|{device}[/{verb}]   - list of supported 
devices
  *   - _conflictingdevs/{modifier}|{device}[/{verb}] - list of conflicting 
devices
  *
diff --git a/src/ucm/main.c b/src/ucm/main.c
index b80db65fa93b..d2078a2381d3 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -1072,7 +1072,6 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
 /**
  * \brief Get list of verbs in pair verbname+comment
  * \param list Returned list
- * \param verbname For verb (NULL = current)
  * \return Number of list entries if success, otherwise a negative error code
  */
 static int get_verb_list(snd_use_case_mgr_t *uc_mgr, const char **list[])
@@ -1181,7 +1180,6 @@ static int get_supcon_device_list(snd_use_case_mgr_t 
*uc_mgr,
        }
 
        return -ENOENT;
-
 }
 
 /**
@@ -1210,41 +1208,201 @@ static int 
get_conflicting_device_list(snd_use_case_mgr_t *uc_mgr,
 
 #ifndef DOC_HIDDEN
 struct myvalue {
-        struct list_head list;
-        char *value;
+       struct list_head list;
+       const char *text;
 };
 #endif
 
+/**
+ * \brief Convert myvalue list string list
+ * \param list myvalue list
+ * \param res string list
+ * \retval Number of list entries if success, otherwise a negativer error code
+ */
+static int myvalue_to_str_list(struct list_head *list, char ***res)
+{
+       struct list_head *pos;
+       struct myvalue *value;
+       char **p;
+       int cnt;
+
+       cnt = alloc_str_list(list, 1, res);
+       if (cnt < 0)
+               return cnt;
+       p = *res;
+       list_for_each(pos, list) {
+               value = list_entry(pos, struct myvalue, list);
+               *p = strdup(value->text);
+               if (*p == NULL) {
+                       snd_use_case_free_list((const char **)p, cnt);
+                       return -ENOMEM;
+               }
+               p++;
+       }
+       return cnt;
+}
+
+/**
+ * \brief Free myvalue list
+ * \param list myvalue list
+ */
+static void myvalue_list_free(struct list_head *list)
+{
+       struct list_head *pos, *npos;
+       struct myvalue *value;
+
+       list_for_each_safe(pos, npos, list) {
+               value = list_entry(pos, struct myvalue, list);
+               list_del(&value->list);
+               free(value);
+       }
+}
+
+/**
+ * \brief Merge one value to the myvalue list
+ * \param list The list with values
+ * \param value The value to be merged (without duplicates)
+ * \return 1 if dup, 0 if success, otherwise a negative error code
+ */
+static int merge_value(struct list_head *list, const char *text)
+{
+       struct list_head *pos;
+       struct myvalue *value;
+
+       list_for_each(pos, list) {
+               value = list_entry(pos, struct myvalue, list);
+               if (strcmp(value->text, text) == 0)
+                       return 1;
+       }
+       value = malloc(sizeof(*value));
+       if (value == NULL)
+               return -ENOMEM;
+       value->text = text;
+       list_add_tail(&value->list, list);
+       return 0;
+}
+
+/**
+ * \brief Find all values for given identifier
+ * \param list Returned list
+ * \param source Source list with ucm_value structures
+ * \return Zero if success, otherwise a negative error code
+ */
+static int add_identifiers(struct list_head *list,
+                          struct list_head *source)
+{
+       struct ucm_value *v;
+       struct list_head *pos;
+       int err;
+
+       list_for_each(pos, source) {
+               v = list_entry(pos, struct ucm_value, list);
+               err = merge_value(list, v->name);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+/**
+ * \brief Find all values for given identifier
+ * \param list Returned list
+ * \param identifier Identifier
+ * \param source Source list with ucm_value structures
+ */
 static int add_values(struct list_head *list,
                       const char *identifier,
                       struct list_head *source)
 {
-        struct ucm_value *v;
-        struct myvalue *val;
-        struct list_head *pos, *pos1;
-        int match;
+       struct ucm_value *v;
+       struct list_head *pos;
+       int err;
         
-        list_for_each(pos, source) {
-                v = list_entry(pos, struct ucm_value, list);
-                if (check_identifier(identifier, v->name)) {
-                        match = 0;
-                        list_for_each(pos1, list) {
-                                val = list_entry(pos1, struct myvalue, list);
-                                if (strcmp(val->value, v->data) == 0) {
-                                        match = 1;
-                                        break;
-                                }
-                        }
-                        if (!match) {
-                                val = malloc(sizeof(struct myvalue));
-                                if (val == NULL)
-                                        return -ENOMEM;
-                               val->value = v->data;
-                                list_add_tail(&val->list, list);
-                        }
-                }
-        }
-        return 0;
+       list_for_each(pos, source) {
+               v = list_entry(pos, struct ucm_value, list);
+               if (check_identifier(identifier, v->name)) {
+                       err = merge_value(list, v->data);
+                       if (err < 0)
+                               return err;
+               }
+       }
+       return 0;
+}
+
+/**
+ * \brief compare two identifiers
+ */
+static int identifier_cmp(const void *_a, const void *_b)
+{
+       const char * const *a = _a;
+       const char * const *b = _b;
+       return strcmp(*a, *b);
+}
+
+/**
+ * \brief Get list of available identifiers
+ * \param list Returned list
+ * \param name Name of verb or modifier to query
+ * \return Number of list entries if success, otherwise a negative error code
+ */
+static int get_identifiers_list(snd_use_case_mgr_t *uc_mgr,
+                               const char **list[], char *name)
+{
+       struct use_case_verb *verb;
+       struct use_case_modifier *modifier;
+       struct use_case_device *device;
+       struct list_head mylist;
+       struct list_head *value_list;
+       char *str, **res;
+       int err;
+
+       if (!name)
+               return -ENOENT;
+
+       str = strchr(name, '/');
+       if (str) {
+               *str = '\0';
+               verb = find_verb(uc_mgr, str + 1);
+       }
+       else {
+               verb = uc_mgr->active_verb;
+       }
+       if (!verb)
+               return -ENOENT;
+
+       value_list = NULL;
+       modifier = find_modifier(uc_mgr, verb, name, 0);
+       if (modifier) {
+               value_list = &modifier->value_list;
+       } else {
+               device = find_device(uc_mgr, verb, name, 0);
+               if (device)
+                       value_list = &device->value_list;
+       }
+       if (value_list == NULL)
+               return -ENOENT;
+
+       INIT_LIST_HEAD(&mylist);
+       err = add_identifiers(&mylist, &uc_mgr->value_list);
+       if (err < 0)
+               goto __fail;
+       err = add_identifiers(&mylist, &verb->value_list);
+       if (err < 0)
+               goto __fail;
+       err = add_identifiers(&mylist, value_list);
+       if (err < 0)
+               goto __fail;
+       err = myvalue_to_str_list(&mylist, &res);
+       if (err > 0)
+               *list = (const char **)res;
+       else if (err == 0)
+               *list = NULL;
+__fail:
+       myvalue_list_free(&mylist);
+       if (err <= 0)
+               return err;
+       qsort(*list, err, sizeof(char *), identifier_cmp);
+       return err;
 }
 
 /**
@@ -1258,8 +1416,7 @@ static int get_value_list(snd_use_case_mgr_t *uc_mgr,
                           const char **list[],
                           char *verbname)
 {
-        struct list_head mylist, *pos, *npos;
-        struct myvalue *val;
+       struct list_head mylist, *pos;
         struct use_case_verb *verb;
         struct use_case_device *dev;
         struct use_case_modifier *mod;
@@ -1292,26 +1449,13 @@ static int get_value_list(snd_use_case_mgr_t *uc_mgr,
                 if (err < 0)
                         goto __fail;
         }
-        err = alloc_str_list(&mylist, 1, &res);
-        if (err >= 0) {
+       err = myvalue_to_str_list(&mylist, &res);
+       if (err > 0)
                *list = (const char **)res;
-                list_for_each(pos, &mylist) {
-                        val = list_entry(pos, struct myvalue, list);
-                        *res = strdup(val->value);
-                        if (*res == NULL) {
-                                snd_use_case_free_list((const char **)res, 
err);
-                                err = -ENOMEM;
-                                goto __fail;
-                        }
-                        res++;
-                }
-        }
+       else if (err == 0)
+               *list = NULL;
       __fail:
-        list_for_each_safe(pos, npos, &mylist) {
-                val = list_entry(pos, struct myvalue, list);
-                list_del(&val->list);
-                free(val);
-        }
+       myvalue_list_free(&mylist);
         return err;
 }
 
@@ -1381,21 +1525,23 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
                 } else {
                         str = NULL;
                 }
-               if (check_identifier(identifier, "_devices"))
-                       err = get_device_list(uc_mgr, list, str);
+               if (check_identifier(identifier, "_devices"))
+                       err = get_device_list(uc_mgr, list, str);
                 else if (check_identifier(identifier, "_modifiers"))
-                        err = get_modifier_list(uc_mgr, list, str);
-                else if (check_identifier(identifier, "_supporteddevs"))
-                        err = get_supported_device_list(uc_mgr, list, str);
-                else if (check_identifier(identifier, "_conflictingdevs"))
-                        err = get_conflicting_device_list(uc_mgr, list, str);
+                       err = get_modifier_list(uc_mgr, list, str);
+               else if (check_identifier(identifier, "_identifiers"))
+                       err = get_identifiers_list(uc_mgr, list, str);
+               else if (check_identifier(identifier, "_supporteddevs"))
+                       err = get_supported_device_list(uc_mgr, list, str);
+               else if (check_identifier(identifier, "_conflictingdevs"))
+                       err = get_conflicting_device_list(uc_mgr, list, str);
                else if (identifier[0] == '_')
                        err = -ENOENT;
-                else
-                        err = get_value_list(uc_mgr, identifier, list, str);
-               if (str)
-                       free(str);
-        }
+               else
+                       err = get_value_list(uc_mgr, identifier, list, str);
+               if (str)
+                       free(str);
+       }
       __end:
        pthread_mutex_unlock(&uc_mgr->mutex);
        return err;
-- 
2.16.4

++++++ 0004-namehint-correct-the-args-check.patch ++++++
>From 5ee5ef31b5ff3fb7c904054cb9cac7478a727f7c Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Sun, 1 Dec 2019 14:26:40 +0100
Subject: [PATCH 04/30] namehint: correct the @args check

BugLink: https://github.com/alsa-project/alsa-plugins/issues/3
Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/control/namehint.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/control/namehint.c b/src/control/namehint.c
index 808df6b50733..4927ef973c32 100644
--- a/src/control/namehint.c
+++ b/src/control/namehint.c
@@ -348,6 +348,12 @@ static int try_config(snd_config_t *config,
                goto __cleanup;
        if (snd_config_search(res, "@args", &cfg) >= 0) {
                snd_config_for_each(i, next, cfg) {
+                       /* skip the argument list */
+                       snd_config_get_id(snd_config_iterator_entry(i), &str);
+                       while (*str && *str >= '0' && *str <= '9') str++;
+                       if (*str == '\0')
+                               continue;
+                       /* the argument definition must have the default */
                        if (snd_config_search(snd_config_iterator_entry(i),
                                              "default", NULL) < 0) {
                                err = -EINVAL;
-- 
2.16.4

++++++ 0005-namehint-improve-the-previous-patch-check-the-return.patch ++++++
>From 6055f8a584296abfc0cec0439ceb708f0eddcc9d Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Sun, 1 Dec 2019 14:30:54 +0100
Subject: [PATCH 05/30] namehint: improve the previous patch (check the
 returned value)

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/control/namehint.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/control/namehint.c b/src/control/namehint.c
index 4927ef973c32..60c48ae32877 100644
--- a/src/control/namehint.c
+++ b/src/control/namehint.c
@@ -349,7 +349,8 @@ static int try_config(snd_config_t *config,
        if (snd_config_search(res, "@args", &cfg) >= 0) {
                snd_config_for_each(i, next, cfg) {
                        /* skip the argument list */
-                       snd_config_get_id(snd_config_iterator_entry(i), &str);
+                       if (snd_config_get_id(snd_config_iterator_entry(i), 
&str) < 0)
+                               continue;
                        while (*str && *str >= '0' && *str <= '9') str++;
                        if (*str == '\0')
                                continue;
-- 
2.16.4

++++++ 0006-ucm-docs-allow-spaces-in-device-names-for-JackHWMute.patch ++++++
>From 4dddcf733d56a13f4d042fefa1fb6230c09f1f65 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Mon, 2 Dec 2019 11:56:30 +0100
Subject: [PATCH 06/30] ucm: docs - allow spaces in device names for JackHWMute

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/include/use-case.h b/include/use-case.h
index 85c58ac0614a..e1f5802789ff 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -326,7 +326,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  *      - Valid values: "soft" (software attenuation)
  *   - EDIDFile
  *      - Path to EDID file for HDMI devices
- *   - JackControl, JackDev, JackHWMute
+ *   - JackControl, JackDev
  *      - Jack information for a device. The jack status can be reported via
  *        a kcontrol and/or via an input device. **JackControl** is the
  *        kcontrol name of the jack, and **JackDev** is the input device id of
@@ -334,17 +334,18 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  *        JackDev value should be "foo"). UCM configuration files should
  *        contain both JackControl and JackDev when possible, because
  *        applications are likely to support only one or the other.
- *
- *        If **JackHWMute** is set, it indicates that when the jack is plugged
- *        in, the hardware automatically mutes some other device(s). The
- *        JackHWMute value is a space-separated list of device names (this
- *        isn't compatible with device names with spaces in them, so don't use
- *        such device names!). Note that JackHWMute should be used only when
- *        the hardware enforces the automatic muting. If the hardware doesn't
- *        enforce any muting, it may still be tempting to set JackHWMute to
- *        trick upper software layers to e.g. automatically mute speakers when
- *        headphones are plugged in, but that's application policy
- *        configuration that doesn't belong to UCM configuration files.
+ *   - JackHWMute
+ *       If this value is set, it indicates that when the jack is plugged
+ *       in, the hardware automatically mutes some other device(s). The
+ *       value is a space-separated list of device names. If the device
+ *       name contains space, it must be enclosed to ' or ", e.g.:
+ *             JackHWMute "'Dock Headphone' Headphone"
+ *        Note that JackHWMute should be used only when the hardware enforces
+ *        the automatic muting. If the hardware doesn't enforce any muting, it
+ *        may still be tempting to set JackHWMute to trick upper software 
layers
+ *        to e.g. automatically mute speakers when headphones are plugged in,
+ *        but that's application policy configuration that doesn't belong
+ *        to UCM configuration files.
  *   - MinBufferLevel
  *     - This is used on platform where reported buffer level is not accurate.
  *       E.g. "512", which holds 512 samples in device buffer. Note: this will
-- 
2.16.4

++++++ 0007-use-case-docs-add-PlaybackMixerCopy-and-CaptureMixer.patch ++++++
>From 2a286ca9a8415571181ce58027686ec332a834e9 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Mon, 2 Dec 2019 11:57:18 +0100
Subject: [PATCH 07/30] use-case: docs - add PlaybackMixerCopy and
 CaptureMixerCopy

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/use-case.h b/include/use-case.h
index e1f5802789ff..71fcc949a117 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -309,8 +309,14 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  *   - PlaybackMixerElem
  *      - mixer element playback identifier
  *     - can be parsed using snd_use_case_parse_selem_id()
+ *   - PlaybackMixerCopy
+ *      - additional mixer element playback identifier
+ *     - can be parsed using snd_use_case_parse_selem_id()
+ *      - those elements should copy the volume and switch settings
+ *      - element identifiers are separated using the | character
  *   - PlaybackMasterElem
  *      - mixer element playback identifier for the master control
+ *     - can be parsed using snd_use_case_parse_selem_id()
  *   - PlaybackMasterType
  *      - type of the master volume control
  *      - Valid values: "soft" (software attenuation)
@@ -319,8 +325,14 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  *   - CaptureMixerElem
  *      - mixer element capture identifier
  *     - can be parsed using snd_use_case_parse_selem_id()
+ *   - CaptureMixerCopy
+ *      - additional mixer element capture identifier
+ *     - can be parsed using snd_use_case_parse_selem_id()
+ *      - those elements should copy the volume and switch settings
+ *      - element identifiers are separated using the | character
  *   - CaptureMasterElem
  *      - mixer element playback identifier for the master control
+ *     - can be parsed using snd_use_case_parse_selem_id()
  *   - CaptureMasterType
  *      - type of the master volume control
  *      - Valid values: "soft" (software attenuation)
-- 
2.16.4

++++++ 0008-ucm-docs-add-JackCTL-rearrange-JackControl-and-JackD.patch ++++++
>From a0fc4447bb7c7f9a850a0a85f3a5a32c1509caf4 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Tue, 3 Dec 2019 15:01:04 +0100
Subject: [PATCH 08/30] ucm: docs - add JackCTL, rearrange JackControl and
 JackDev

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/include/use-case.h b/include/use-case.h
index 71fcc949a117..25998cb9bad5 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -338,14 +338,20 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  *      - Valid values: "soft" (software attenuation)
  *   - EDIDFile
  *      - Path to EDID file for HDMI devices
- *   - JackControl, JackDev
- *      - Jack information for a device. The jack status can be reported via
- *        a kcontrol and/or via an input device. **JackControl** is the
- *        kcontrol name of the jack, and **JackDev** is the input device id of
- *        the jack (if the full input device path is /dev/input/by-id/foo, the
- *        JackDev value should be "foo"). UCM configuration files should
- *        contain both JackControl and JackDev when possible, because
- *        applications are likely to support only one or the other.
+ *   - JackCTL
+ *      - jack control device name
+ *   - JackControl
+ *      - jack control identificator
+ *      - can be parsed using snd_use_case_parse_ctl_elem_id()
+ *      - UCM configuration files should contain both JackControl and JackDev
+ *        when possible, because applications are likely to support only one
+ *        or the other
+ *   - JackDev
+ *      - the input device id of the jack (if the full input device path is
+ *        /dev/input/by-id/foo, the JackDev value should be "foo")
+ *      - UCM configuration files should contain both JackControl and JackDev
+ *        when possible, because applications are likely to support only one
+ *        or the other
  *   - JackHWMute
  *       If this value is set, it indicates that when the jack is plugged
  *       in, the hardware automatically mutes some other device(s). The
-- 
2.16.4

++++++ 0009-ucm-Do-not-fail-to-parse-configs-on-cards-with-an-em.patch ++++++
>From e59034a0bec257cc7422a1e9436d936be8696a6f Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdego...@redhat.com>
Date: Tue, 3 Dec 2019 18:27:39 +0100
Subject: [PATCH 09/30] ucm: Do not fail to parse configs on cards with an
 empty CardComponents lists

Since the UCM profiles for all Bay- and Cherry-Trail SST cards have been
moved over to UCM2, parsing them fails with:

ALSA lib ucm_subs.c:220:(uc_mgr_get_substituted_value) variable 
'${CardComponents}' is not defined in this context!

This completely breaks audio support on all Bay- and Cherry-Trail devices.

This is caused by these non-SOF ASoC using cards having an empty
CardComponents list. Which in itself is fine, but is rejected by
the ucm_subs.c code. This commit changes the ucm_subs code to accept
an empty string as a valid value for CardComponents restoring audio
functionality on these boards.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/ucm/ucm_subs.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
index 00afa9e3de0e..90e395f0ab6f 100644
--- a/src/ucm/ucm_subs.c
+++ b/src/ucm/ucm_subs.c
@@ -25,6 +25,7 @@
  */
 
 #include "ucm_local.h"
+#include <stdbool.h>
 #include <sys/stat.h>
 #include <limits.h>
 
@@ -145,10 +146,11 @@ static char *rval_sysfs(snd_use_case_mgr_t *uc_mgr 
ATTRIBUTE_UNUSED, const char
        return strdup(path);
 }
 
-#define MATCH_VARIABLE(name, id, fcn)                                  \
+#define MATCH_VARIABLE(name, id, fcn, empty_ok)                                
\
        if (strncmp((name), (id), sizeof(id) - 1) == 0) {               \
                rval = fcn(uc_mgr);                                     \
                idsize = sizeof(id) - 1;                                \
+               allow_empty = (empty_ok);                               \
                goto __rval;                                            \
        }
 
@@ -189,12 +191,14 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t 
*uc_mgr,
 
        while (*value) {
                if (*value == '$' && *(value+1) == '{') {
-                       MATCH_VARIABLE(value, "${ConfName}", rval_conf_name);
-                       MATCH_VARIABLE(value, "${CardId}", rval_card_id);
-                       MATCH_VARIABLE(value, "${CardDriver}", 
rval_card_driver);
-                       MATCH_VARIABLE(value, "${CardName}", rval_card_name);
-                       MATCH_VARIABLE(value, "${CardLongName}", 
rval_card_longname);
-                       MATCH_VARIABLE(value, "${CardComponents}", 
rval_card_components);
+                       bool allow_empty = false;
+
+                       MATCH_VARIABLE(value, "${ConfName}", rval_conf_name, 
false);
+                       MATCH_VARIABLE(value, "${CardId}", rval_card_id, false);
+                       MATCH_VARIABLE(value, "${CardDriver}", 
rval_card_driver, false);
+                       MATCH_VARIABLE(value, "${CardName}", rval_card_name, 
false);
+                       MATCH_VARIABLE(value, "${CardLongName}", 
rval_card_longname, false);
+                       MATCH_VARIABLE(value, "${CardComponents}", 
rval_card_components, true);
                        MATCH_VARIABLE2(value, "${env:", rval_env);
                        MATCH_VARIABLE2(value, "${sys:", rval_sysfs);
                        err = -EINVAL;
@@ -208,7 +212,7 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr,
                        }
                        goto __error;
 __rval:
-                       if (rval == NULL || rval[0] == '\0') {
+                       if (rval == NULL || (!allow_empty && rval[0] == '\0')) {
                                free(rval);
                                strncpy(r, value, idsize);
                                r[idsize] = '\0';
-- 
2.16.4

++++++ 0010-src-ucm-main.c-fix-build-without-mixer.patch ++++++
>From 8e2c70add782f997f7c269ed3f722888e56ff024 Mon Sep 17 00:00:00 2001
From: Fabrice Fontaine <fontaine.fabr...@gmail.com>
Date: Tue, 3 Dec 2019 18:56:40 +0100
Subject: [PATCH 10/30] src/ucm/main.c: fix build without mixer

Commit 4ce38a5ff466d18039b2606938f866ea3a6c9f3c breaks the build without
mixer on:

  CCLD     libasound.la
/home/buildroot/autobuild/instance-1/output-1/host/lib/gcc/xtensa-buildroot-linux-uclibc/8.3.0/../../../../xtensa-buildroot-linux-uclibc/bin/ld:
 ucm/.libs/libucm.a(main.o): in function `snd_use_case_set':
main.c:(.text+0x185c): undefined reference to `snd_mixer_selem_id_parse'

Fixes: 
http://autobuild.buildroot.org/results/4d91c9f82a2a61c50c457a851073b85cc09ea345

Signed-off-by: Fabrice Fontaine <fontaine.fabr...@gmail.com>
Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/ucm/main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/ucm/main.c b/src/ucm/main.c
index d2078a2381d3..61922f10b7c7 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -2115,8 +2115,10 @@ int snd_use_case_parse_selem_id(snd_mixer_selem_id_t 
*dst,
                                const char *ucm_id,
                                const char *value)
 {
+#ifdef BUILD_MIXER
        if (strcmp(ucm_id, "PlaybackMixerId") == 0 ||
            strcmp(ucm_id, "CaptureMixerId") == 0)
                return snd_mixer_selem_id_parse(dst, value);
+#endif
        return -EINVAL;
 }
-- 
2.16.4

++++++ 0011-alsa.m4-another-try-to-fix-the-libatopology-detectio.patch ++++++
>From ad8527d81b09c4d0edd054b5b1468ce1c50b23cb Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Wed, 4 Dec 2019 09:49:40 +0100
Subject: [PATCH 11/30] alsa.m4: another try to fix the libatopology detection

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 utils/alsa.m4 | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/utils/alsa.m4 b/utils/alsa.m4
index 4c457f0d4e1d..320e4336a925 100644
--- a/utils/alsa.m4
+++ b/utils/alsa.m4
@@ -22,6 +22,7 @@ alsa_save_CFLAGS="$CFLAGS"
 alsa_save_LDFLAGS="$LDFLAGS"
 alsa_save_LIBS="$LIBS"
 alsa_found=yes
+alsa_topology_found=no
 
 dnl
 dnl Get the cflags and libraries for alsa
@@ -158,11 +159,17 @@ AC_CHECK_LIB([asound], [snd_ctl_open],,
         alsa_found=no]
 )
 if test "x$enable_atopology" = "xyes"; then
+alsa_topology_found=yes
 AC_CHECK_LIB([atopology], [snd_tplg_new],,
        [ifelse([$3], , [AC_MSG_ERROR(No linkable libatopology was found.)])
-        alsa_found=no]
+        alsa_topology_found=no,
+]
 )
 fi
+else
+if test "x$enable_atopology" = "xyes"; then
+  alsa_topology_found=yes
+fi
 fi
 
 if test "x$alsa_found" = "xyes" ; then
@@ -183,7 +190,7 @@ fi
 
 dnl add the alsa topology library; must be at the end
 AC_MSG_CHECKING(for ALSA topology LDFLAGS)
-if test "x$enable_atopology" = "xyes"; then
+if test "x$alsa_topology_found" = "xyes"; then
   ALSA_TOPOLOGY_LIBS="$ALSA_TOPOLOGY_LIBS -latopology"
 fi
 AC_MSG_RESULT($ALSA_TOPOLOGY_LIBS)
-- 
2.16.4

++++++ 0012-ucm-docs-add-Mic-DigitalMic-and-multiple-devices-com.patch ++++++
>From 555a5dbdabc5ed3be1ca81865abdb997bc3a6082 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Thu, 5 Dec 2019 16:59:05 +0100
Subject: [PATCH 12/30] ucm: docs - add Mic/DigitalMic and multiple devices
 comments

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/use-case.h b/include/use-case.h
index 25998cb9bad5..1736da25b649 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -114,10 +114,18 @@ extern "C" {
  *
  * Physical system devices the render and capture audio. Devices can be OR'ed
  * together to support audio on simultaneous devices.
+ *
+ * If multiple devices with the same name exists, the number suffixes should
+ * be added to these names like HDMI1,HDMI2,HDMI3 etc. No number gaps are
+ * allowed. The names with numbers must be continuous.
+ *
+ * The preference of the devices is determined by the priority value.
  */
 #define SND_USE_CASE_DEV_NONE          "None"          /**< None Device */
 #define SND_USE_CASE_DEV_SPEAKER       "Speaker"       /**< Speaker Device */
 #define SND_USE_CASE_DEV_LINE          "Line"          /**< Line Device */
+#define SND_USE_CASE_DEV_MIC            "Mic"           /**< Integrated Analog 
Microphone */
+#define SND_USE_CASE_DEV_DIGITAL_MIC    "DigitalMic"    /**< Integrated 
Digital Microphone */
 #define SND_USE_CASE_DEV_HEADPHONES    "Headphones"    /**< Headphones Device 
*/
 #define SND_USE_CASE_DEV_HEADSET       "Headset"       /**< Headset Device */
 #define SND_USE_CASE_DEV_HANDSET       "Handset"       /**< Handset Device */
-- 
2.16.4

++++++ 0013-ucm-docs-remove-DigitalMic-it-does-not-have-sense.patch ++++++
>From 1ad660ddeecb2a364f1ca62aa60f256f7029cfdc Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Thu, 5 Dec 2019 17:01:31 +0100
Subject: [PATCH 13/30] ucm: docs - remove DigitalMic, it does not have sense

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/use-case.h b/include/use-case.h
index 1736da25b649..214a2a4c4691 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -124,8 +124,7 @@ extern "C" {
 #define SND_USE_CASE_DEV_NONE          "None"          /**< None Device */
 #define SND_USE_CASE_DEV_SPEAKER       "Speaker"       /**< Speaker Device */
 #define SND_USE_CASE_DEV_LINE          "Line"          /**< Line Device */
-#define SND_USE_CASE_DEV_MIC            "Mic"           /**< Integrated Analog 
Microphone */
-#define SND_USE_CASE_DEV_DIGITAL_MIC    "DigitalMic"    /**< Integrated 
Digital Microphone */
+#define SND_USE_CASE_DEV_MIC            "Mic"           /**< Integrated 
Microphone */
 #define SND_USE_CASE_DEV_HEADPHONES    "Headphones"    /**< Headphones Device 
*/
 #define SND_USE_CASE_DEV_HEADSET       "Headset"       /**< Headset Device */
 #define SND_USE_CASE_DEV_HANDSET       "Handset"       /**< Handset Device */
-- 
2.16.4

++++++ 0014-ucm-docs-change-the-Mic-description-to-simple-Microp.patch ++++++
>From 5473c5d677915b88d5c93d5bcc6cd16bb6a40342 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Thu, 5 Dec 2019 17:19:06 +0100
Subject: [PATCH 14/30] ucm: docs - change the Mic description to simple
 Microphone Device

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/use-case.h b/include/use-case.h
index 214a2a4c4691..b04f7b9d38de 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -124,7 +124,7 @@ extern "C" {
 #define SND_USE_CASE_DEV_NONE          "None"          /**< None Device */
 #define SND_USE_CASE_DEV_SPEAKER       "Speaker"       /**< Speaker Device */
 #define SND_USE_CASE_DEV_LINE          "Line"          /**< Line Device */
-#define SND_USE_CASE_DEV_MIC            "Mic"           /**< Integrated 
Microphone */
+#define SND_USE_CASE_DEV_MIC            "Mic"           /**< Microphone Device 
*/
 #define SND_USE_CASE_DEV_HEADPHONES    "Headphones"    /**< Headphones Device 
*/
 #define SND_USE_CASE_DEV_HEADSET       "Headset"       /**< Headset Device */
 #define SND_USE_CASE_DEV_HANDSET       "Handset"       /**< Handset Device */
-- 
2.16.4

++++++ 0015-ucm-docs-add-note-about-the-sequences-and-device-spl.patch ++++++
>From ca67e823833213e140a09ce43b6399b7676616df Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 6 Dec 2019 11:11:54 +0100
Subject: [PATCH 15/30] ucm: docs - add note about the sequences and device
 split

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/use-case.h b/include/use-case.h
index b04f7b9d38de..2efcb4d8fdc3 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -119,6 +119,11 @@ extern "C" {
  * be added to these names like HDMI1,HDMI2,HDMI3 etc. No number gaps are
  * allowed. The names with numbers must be continuous.
  *
+ * If EnableSequence/DisableSequence controls independent paths in the hardware
+ * it is also recommended to split playback and capture UCM devices and use
+ * the number suffixes. Example use case: Use the integrated microphone
+ * in the laptop instead the microphone in headphones.
+ *
  * The preference of the devices is determined by the priority value.
  */
 #define SND_USE_CASE_DEV_NONE          "None"          /**< None Device */
-- 
2.16.4

++++++ 0016-ucm-docs-remove-MixerCopy-values-add-Priority-for-ve.patch ++++++
>From f828dfe549fbab0a920768c63ebd3478272954eb Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Tue, 10 Dec 2019 11:48:06 +0100
Subject: [PATCH 16/30] ucm: docs - remove MixerCopy values, add Priority for
 verb, improve priority docs

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 include/use-case.h | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/include/use-case.h b/include/use-case.h
index 2efcb4d8fdc3..134303afaa18 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -274,6 +274,10 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  * Recommended names for values:
  *   - TQ
  *      - Tone Quality
+ *   - Priority
+ *      - priority value (1-10000), higher value means higher priority
+ *      - valid only for verbs
+ *      - for devices - PlaybackPriority and CapturePriority
  *   - PlaybackPCM
  *      - full PCM playback device name
  *   - PlaybackPCMIsDummy
@@ -301,7 +305,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  *      - playback control switch identifier string
  *     - can be parsed using snd_use_case_parse_ctl_elem_id()
  *   - PlaybackPriority
- *      - priority value (1-10000), default value is 100, higher value means 
lower priority
+ *      - priority value (1-10000), higher value means higher priority
  *   - CaptureRate
  *      - capture device sample rate
  *   - CaptureChannels
@@ -315,17 +319,12 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  *      - capture control switch identifier string
  *     - can be parsed using snd_use_case_parse_ctl_elem_id()
  *   - CapturePriority
- *      - priority value (1-10000), default value is 100, higher value means 
lower priority
+ *      - priority value (1-10000), higher value means higher priority
  *   - PlaybackMixer
  *      - name of playback mixer
  *   - PlaybackMixerElem
  *      - mixer element playback identifier
  *     - can be parsed using snd_use_case_parse_selem_id()
- *   - PlaybackMixerCopy
- *      - additional mixer element playback identifier
- *     - can be parsed using snd_use_case_parse_selem_id()
- *      - those elements should copy the volume and switch settings
- *      - element identifiers are separated using the | character
  *   - PlaybackMasterElem
  *      - mixer element playback identifier for the master control
  *     - can be parsed using snd_use_case_parse_selem_id()
@@ -337,11 +336,6 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
  *   - CaptureMixerElem
  *      - mixer element capture identifier
  *     - can be parsed using snd_use_case_parse_selem_id()
- *   - CaptureMixerCopy
- *      - additional mixer element capture identifier
- *     - can be parsed using snd_use_case_parse_selem_id()
- *      - those elements should copy the volume and switch settings
- *      - element identifiers are separated using the | character
  *   - CaptureMasterElem
  *      - mixer element playback identifier for the master control
  *     - can be parsed using snd_use_case_parse_selem_id()
-- 
2.16.4

++++++ 0017-ucm-setup-conf_format-after-getting-ALSA_CONFIG_UCM_.patch ++++++
>From 1744159180ac94a72036d7232e674c58cedee70a Mon Sep 17 00:00:00 2001
From: Libin Yang <libin.y...@linux.intel.com>
Date: Wed, 11 Dec 2019 14:07:19 +0800
Subject: [PATCH 17/30] ucm: setup conf_format after getting
 ALSA_CONFIG_UCM_VAR successfully

Set the conf_format to 1 after getting ALSA_CONFIG_UCM_VAR successfully.
Otherwise, the conf_format is not set in this scenario.

Signed-off-by: Libin Yang <libin.y...@linux.intel.com>
Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/ucm/parser.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index ba5002779f56..d61124a343e1 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -89,6 +89,8 @@ static void configuration_filename(snd_use_case_mgr_t *uc_mgr,
                env = getenv(ALSA_CONFIG_UCM2_VAR);
                if (env == NULL) {
                        env = getenv(ALSA_CONFIG_UCM_VAR);
+                       if (env)
+                               uc_mgr->conf_format = 1;
                } else {
                        uc_mgr->conf_format = 2;
                }
-- 
2.16.4

++++++ 0018-alsa-lib-fix-the-array-parser-unique-compound-keys.patch ++++++
>From 9980e18c3c99da42a90a98b140a0ffe7d0f92cd3 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Thu, 12 Dec 2019 18:42:33 +0100
Subject: [PATCH 18/30] alsa-lib: fix the array parser (unique compound keys)

The code from the old import may merge arrays wrongly and
the result is a compound with same keys like:

Input:

        lines [
                "SSP0.OUT, , BUF1.3"
        ]
        lines [
                "BUF2.0, , SSP0.IN"
        ]

Parsed contents:

        lines {
                0 'SSP0.OUT, , BUF1.3'
                0 'BUF2.0, , SSP0.IN'
        }

Proper parsed contents (create+merge mode):

        lines {
                0 'SSP0.OUT, , BUF1.3'
                1 'BUF2.0, , SSP0.IN'
        }

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/conf.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/conf.c b/src/conf.c
index e430650430d1..3e753b266b8d 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -1226,7 +1226,7 @@ static int parse_value(snd_config_t **_n, snd_config_t 
*parent, input_t *input,
 static int parse_defs(snd_config_t *parent, input_t *input, int skip, int 
override);
 static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, 
int override);
 
-static int parse_array_def(snd_config_t *parent, input_t *input, int idx, int 
skip, int override)
+static int parse_array_def(snd_config_t *parent, input_t *input, int *idx, int 
skip, int override)
 {
        char *id = NULL;
        int c;
@@ -1234,8 +1234,21 @@ static int parse_array_def(snd_config_t *parent, input_t 
*input, int idx, int sk
        snd_config_t *n = NULL;
 
        if (!skip) {
+               snd_config_t *g;
                char static_id[12];
-               snprintf(static_id, sizeof(static_id), "%i", idx);
+               while (1) {
+                       snprintf(static_id, sizeof(static_id), "%i", *idx);
+                       if (_snd_config_search(parent, static_id, -1, &g) == 0) 
{
+                               if (override) {
+                                       snd_config_delete(n);
+                               } else {
+                                       /* merge */
+                                       (*idx)++;
+                                       continue;
+                               }
+                       }
+                       break;
+               }
                id = strdup(static_id);
                if (id == NULL)
                        return -ENOMEM;
@@ -1306,9 +1319,10 @@ static int parse_array_defs(snd_config_t *parent, 
input_t *input, int skip, int
                unget_char(c, input);
                if (c == ']')
                        return 0;
-               err = parse_array_def(parent, input, idx++, skip, override);
+               err = parse_array_def(parent, input, &idx, skip, override);
                if (err < 0)
                        return err;
+               idx++;
        }
        return 0;
 }
-- 
2.16.4

++++++ 0019-topology-remove-vendor_fd-name-from-snd_tplg-structu.patch ++++++
>From 075ee165e647a6b434f63ca578f2f8faff2a55f6 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 16:09:35 +0100
Subject: [PATCH 19/30] topology: remove vendor_fd/name from snd_tplg structure
 - not used

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/tplg_local.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index c32267d29510..22648fa51f9b 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -60,11 +60,6 @@ typedef enum _snd_pcm_rates {
 } snd_pcm_rates_t;
 
 struct snd_tplg {
-
-       /* opaque vendor data */
-       int vendor_fd;
-       char *vendor_name;
-
        /* out file */
        int out_fd;
 
-- 
2.16.4

++++++ 0020-topology-file-position-and-size-cleanups.patch ++++++
>From ce74829db630a49569c79aea4aeb288fdd458dd8 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 17:01:03 +0100
Subject: [PATCH 20/30] topology: file position and size cleanups

- try to use size_t/ssize_t
- track the position in own variable, do not use lseek

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/builder.c    | 121 ++++++++++++++++++++++------------------------
 src/topology/tplg_local.h |   3 +-
 2 files changed, 60 insertions(+), 64 deletions(-)

diff --git a/src/topology/builder.c b/src/topology/builder.c
index 5ae3ae89dac7..4e6cbbb08a1a 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -23,28 +23,41 @@
 /* verbose output detailing each object size and file position */
 static void verbose(snd_tplg_t *tplg, const char *fmt, ...)
 {
-       int offset;
        va_list va;
 
        if (!tplg->verbose)
                return;
 
-       offset = lseek(tplg->out_fd, 0, SEEK_CUR);
-
        va_start(va, fmt);
-       fprintf(stdout, "0x%6.6x/%6.6d -", offset, offset);
+       fprintf(stdout, "0x%6.6zx/%6.6zd -", tplg->out_pos, tplg->out_pos);
        vfprintf(stdout, fmt, va);
        va_end(va);
 }
 
+/* write a block, track the position */
+static ssize_t twrite(snd_tplg_t *tplg, void *data, size_t data_size)
+{
+       ssize_t r = write(tplg->out_fd, data, data_size);
+       if (r != (ssize_t)data_size) {
+               if (r < 0) {
+                       SNDERR("error: unable to write: %s", strerror(errno));
+                       return -errno;
+               }
+               tplg->out_pos += r;
+               SNDERR("error: unable to write (partial)");
+               return -EIO;
+       }
+       tplg->out_pos += r;
+       return r;
+}
+
 /* write out block header to output file */
-static int write_block_header(snd_tplg_t *tplg, unsigned int type,
-       unsigned int vendor_type, unsigned int version, unsigned int index,
-       size_t payload_size, int count)
+static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type,
+                                 unsigned int vendor_type,
+                                 unsigned int version, unsigned int index,
+                                 size_t payload_size, int count)
 {
        struct snd_soc_tplg_hdr hdr;
-       size_t bytes;
-       int offset = lseek(tplg->out_fd, 0, SEEK_CUR);
 
        memset(&hdr, 0, sizeof(hdr));
        hdr.magic = SND_SOC_TPLG_MAGIC;
@@ -58,13 +71,13 @@ static int write_block_header(snd_tplg_t *tplg, unsigned 
int type,
        hdr.count = count;
 
        /* make sure file offset is aligned with the calculated HDR offset */
-       if ((unsigned int)offset != tplg->next_hdr_pos) {
-               SNDERR("error: New header is at offset 0x%x but file"
-                       " offset 0x%x is %s by %d bytes\n",
-                       tplg->next_hdr_pos, offset,
-                       (unsigned int)offset > tplg->next_hdr_pos ? "ahead" : 
"behind",
-                       abs(offset - tplg->next_hdr_pos));
-               exit(-EINVAL);
+       if (tplg->out_pos != tplg->next_hdr_pos) {
+               SNDERR("error: New header is at offset 0x%zx but file"
+                       " offset 0x%zx is %s by %ld bytes\n",
+                       tplg->next_hdr_pos, tplg->out_pos,
+                       tplg->out_pos > tplg->next_hdr_pos ? "ahead" : "behind",
+                       labs(tplg->out_pos - tplg->next_hdr_pos));
+               return -EINVAL;
        }
 
        verbose(tplg, " header index %d type %d count %d size 0x%lx/%ld vendor 
%d "
@@ -74,22 +87,16 @@ static int write_block_header(snd_tplg_t *tplg, unsigned 
int type,
 
        tplg->next_hdr_pos += hdr.payload_size + sizeof(hdr);
 
-       bytes = write(tplg->out_fd, &hdr, sizeof(hdr));
-       if (bytes != sizeof(hdr)) {
-               SNDERR("error: can't write section header %lu\n",
-                       (long unsigned int)bytes);
-               return bytes;
-       }
-
-       return bytes;
+       return twrite(tplg, &hdr, sizeof(hdr));
 }
 
 static int write_elem_block(snd_tplg_t *tplg,
-       struct list_head *base, int size, int tplg_type, const char *obj_name)
+       struct list_head *base, size_t size, int tplg_type, const char 
*obj_name)
 {
        struct list_head *pos, *sub_pos, *sub_base;
        struct tplg_elem *elem, *elem_next;
-       int ret, wsize = 0, total_size = 0, count = 0, block_size = 0;
+       size_t total_size = 0, count = 0, block_size = 0;
+       ssize_t ret, wsize;
 
        sub_base = base;
        list_for_each(pos, base) {
@@ -129,12 +136,9 @@ static int write_elem_block(snd_tplg_t *tplg,
                                                elem->route->control,
                                                elem->route->sink, elem->size);
 
-                               wsize = write(tplg->out_fd, elem->obj, 
elem->size);
-                               if (wsize < 0) {
-                                       SNDERR("error: failed to write %s %d\n",
-                                               obj_name, ret);
-                                       return ret;
-                               }
+                               wsize = twrite(tplg, elem->obj, elem->size);
+                               if (wsize < 0)
+                                       return size;
 
                                total_size += wsize;
                                /* get to the end of sub list */
@@ -151,7 +155,7 @@ static int write_elem_block(snd_tplg_t *tplg,
 
        /* make sure we have written the correct size */
        if (total_size != size) {
-               SNDERR("error: size mismatch. Expected %d wrote %d\n",
+               SNDERR("error: size mismatch. Expected %zu wrote %zu\n",
                        size, total_size);
                return -EIO;
        }
@@ -179,8 +183,7 @@ static int calc_block_size(struct list_head *base)
        return size;
 }
 
-static int write_block(snd_tplg_t *tplg, struct list_head *base,
-       int type)
+static int write_block(snd_tplg_t *tplg, struct list_head *base, int type)
 {
        int size;
 
@@ -231,44 +234,36 @@ static int write_block(snd_tplg_t *tplg, struct list_head 
*base,
 }
 
 /* write the manifest including its private data */
-static int write_manifest_data(snd_tplg_t *tplg)
+static ssize_t write_manifest_data(snd_tplg_t *tplg)
 {
-       int ret;
+       ssize_t ret;
 
        /* write the header for this block */
        ret = write_block_header(tplg, SND_SOC_TPLG_TYPE_MANIFEST, 0,
                tplg->version, 0,
                sizeof(tplg->manifest) + tplg->manifest.priv.size, 1);
        if (ret < 0) {
-               SNDERR("error: failed to write manifest block %d\n", ret);
+               SNDERR("error: failed to write manifest block\n");
                return ret;
        }
 
        verbose(tplg, "manifest : write %d bytes\n", sizeof(tplg->manifest));
-       ret = write(tplg->out_fd, &tplg->manifest, sizeof(tplg->manifest));
-       if (ret < 0) {
-               SNDERR("error: failed to write manifest %d\n", ret);
-               return ret;
+       ret = twrite(tplg, &tplg->manifest, sizeof(tplg->manifest));
+       if (ret >= 0) {
+               verbose(tplg, "manifest : write %d priv bytes\n", 
tplg->manifest.priv.size);
+               ret = twrite(tplg, tplg->manifest_pdata, 
tplg->manifest.priv.size);
        }
-
-       verbose(tplg, "manifest : write %d priv bytes\n", 
tplg->manifest.priv.size);
-       ret = write(tplg->out_fd, tplg->manifest_pdata, 
tplg->manifest.priv.size);
-       if (ret < 0) {
-               SNDERR("error: failed to write manifest priv data %d\n", ret);
-               return ret;
-       }
-
-       return 0;
+       return ret;
 }
 
 int tplg_write_data(snd_tplg_t *tplg)
 {
-       int ret;
+       ssize_t ret;
 
        /* write manifest */
        ret = write_manifest_data(tplg);
        if (ret < 0) {
-               SNDERR("failed to write manifest %d\n", ret);
+               SNDERR("failed to write manifest %zd\n", ret);
                return ret;
        }
 
@@ -276,7 +271,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->mixer_list,
                SND_TPLG_TYPE_MIXER);
        if (ret < 0) {
-               SNDERR("failed to write control elems %d\n", ret);
+               SNDERR("failed to write control elems %zd\n", ret);
                return ret;
        }
 
@@ -284,7 +279,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->enum_list,
                SND_TPLG_TYPE_ENUM);
        if (ret < 0) {
-               SNDERR("failed to write control elems %d\n", ret);
+               SNDERR("failed to write control elems %zd\n", ret);
                return ret;
        }
 
@@ -292,7 +287,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->bytes_ext_list,
                SND_TPLG_TYPE_BYTES);
        if (ret < 0) {
-               SNDERR("failed to write control elems %d\n", ret);
+               SNDERR("failed to write control elems %zd\n", ret);
                return ret;
        }
 
@@ -300,7 +295,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->widget_list,
                SND_TPLG_TYPE_DAPM_WIDGET);
        if (ret < 0) {
-               SNDERR("failed to write widget elems %d\n", ret);
+               SNDERR("failed to write widget elems %zd\n", ret);
                return ret;
        }
 
@@ -308,7 +303,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->pcm_list,
                SND_TPLG_TYPE_PCM);
        if (ret < 0) {
-               SNDERR("failed to write pcm elems %d\n", ret);
+               SNDERR("failed to write pcm elems %zd\n", ret);
                return ret;
        }
 
@@ -316,7 +311,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->dai_list,
                SND_TPLG_TYPE_DAI);
        if (ret < 0) {
-               SNDERR("failed to write physical dai elems %d\n", ret);
+               SNDERR("failed to write physical dai elems %zd\n", ret);
                return ret;
        }
 
@@ -324,7 +319,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->be_list,
                SND_TPLG_TYPE_BE);
        if (ret < 0) {
-               SNDERR("failed to write be elems %d\n", ret);
+               SNDERR("failed to write be elems %zd\n", ret);
                return ret;
        }
 
@@ -332,7 +327,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->cc_list,
                SND_TPLG_TYPE_CC);
        if (ret < 0) {
-               SNDERR("failed to write cc elems %d\n", ret);
+               SNDERR("failed to write cc elems %zd\n", ret);
                return ret;
        }
 
@@ -340,7 +335,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->route_list,
                SND_TPLG_TYPE_DAPM_GRAPH);
        if (ret < 0) {
-               SNDERR("failed to write graph elems %d\n", ret);
+               SNDERR("failed to write graph elems %zd\n", ret);
                return ret;
        }
 
@@ -348,7 +343,7 @@ int tplg_write_data(snd_tplg_t *tplg)
        ret = write_block(tplg, &tplg->pdata_list,
                SND_TPLG_TYPE_DATA);
        if (ret < 0) {
-               SNDERR("failed to write private data %d\n", ret);
+               SNDERR("failed to write private data %zd\n", ret);
                return ret;
        }
 
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 22648fa51f9b..7b8abcdefbcf 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -62,12 +62,13 @@ typedef enum _snd_pcm_rates {
 struct snd_tplg {
        /* out file */
        int out_fd;
+       size_t out_pos;
 
        int verbose;
        unsigned int version;
 
        /* runtime state */
-       unsigned int next_hdr_pos;
+       size_t next_hdr_pos;
        int index;
        int channel_idx;
 
-- 
2.16.4

++++++ 0021-topology-use-an-array-describing-blocks-for-the-main.patch ++++++
>From 012bd3b28c0d2744db482caca630d5b0a19e4dab Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 18:24:55 +0100
Subject: [PATCH 21/30] topology: use an array describing blocks for the main
 build loop

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/builder.c | 146 +++++++++++++++++++++++--------------------------
 1 file changed, 67 insertions(+), 79 deletions(-)

diff --git a/src/topology/builder.c b/src/topology/builder.c
index 4e6cbbb08a1a..ec1af42ddf9b 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -258,93 +258,81 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg)
 
 int tplg_write_data(snd_tplg_t *tplg)
 {
+       struct wtable {
+               const char *name;
+               struct list_head *list;
+               int type;
+       } *wptr, wtable[] = {
+               {
+                       .name = "control mixer elements",
+                       .list = &tplg->mixer_list,
+                       .type = SND_TPLG_TYPE_MIXER,
+               },
+               {
+                       .name = "control enum elements",
+                       .list = &tplg->enum_list,
+                       .type = SND_TPLG_TYPE_ENUM,
+               },
+               {
+                       .name = "control extended (bytes) elements",
+                       .list = &tplg->bytes_ext_list,
+                       .type = SND_TPLG_TYPE_BYTES,
+               },
+               {
+                       .name = "dapm widget elements",
+                       .list = &tplg->widget_list,
+                       .type = SND_TPLG_TYPE_DAPM_WIDGET,
+               },
+               {
+                       .name = "pcm elements",
+                       .list = &tplg->pcm_list,
+                       .type = SND_TPLG_TYPE_PCM,
+               },
+               {
+                       .name = "physical dai elements",
+                       .list = &tplg->dai_list,
+                       .type = SND_TPLG_TYPE_DAI,
+               },
+               {
+                       .name = "be elements",
+                       .list = &tplg->be_list,
+                       .type = SND_TPLG_TYPE_BE,
+               },
+               {
+                       .name = "cc elements",
+                       .list = &tplg->cc_list,
+                       .type = SND_TPLG_TYPE_CC,
+               },
+               {
+                       .name = "route (dapm graph) elements",
+                       .list = &tplg->route_list,
+                       .type = SND_TPLG_TYPE_DAPM_GRAPH,
+               },
+               {
+                       .name = "private data elements",
+                       .list = &tplg->pdata_list,
+                       .type = SND_TPLG_TYPE_DATA,
+               },
+       };
+
        ssize_t ret;
+       unsigned int index;
 
        /* write manifest */
        ret = write_manifest_data(tplg);
        if (ret < 0) {
-               SNDERR("failed to write manifest %zd\n", ret);
-               return ret;
-       }
-
-       /* write mixer elems. */
-       ret = write_block(tplg, &tplg->mixer_list,
-               SND_TPLG_TYPE_MIXER);
-       if (ret < 0) {
-               SNDERR("failed to write control elems %zd\n", ret);
-               return ret;
-       }
-
-       /* write enum control elems. */
-       ret = write_block(tplg, &tplg->enum_list,
-               SND_TPLG_TYPE_ENUM);
-       if (ret < 0) {
-               SNDERR("failed to write control elems %zd\n", ret);
-               return ret;
-       }
-
-       /* write bytes extended control elems. */
-       ret = write_block(tplg, &tplg->bytes_ext_list,
-               SND_TPLG_TYPE_BYTES);
-       if (ret < 0) {
-               SNDERR("failed to write control elems %zd\n", ret);
-               return ret;
-       }
-
-       /* write widget elems */
-       ret = write_block(tplg, &tplg->widget_list,
-               SND_TPLG_TYPE_DAPM_WIDGET);
-       if (ret < 0) {
-               SNDERR("failed to write widget elems %zd\n", ret);
-               return ret;
-       }
-
-       /* write pcm elems */
-       ret = write_block(tplg, &tplg->pcm_list,
-               SND_TPLG_TYPE_PCM);
-       if (ret < 0) {
-               SNDERR("failed to write pcm elems %zd\n", ret);
-               return ret;
-       }
-
-       /* write physical dai elems */
-       ret = write_block(tplg, &tplg->dai_list,
-               SND_TPLG_TYPE_DAI);
-       if (ret < 0) {
-               SNDERR("failed to write physical dai elems %zd\n", ret);
-               return ret;
-       }
-
-       /* write be elems */
-       ret = write_block(tplg, &tplg->be_list,
-               SND_TPLG_TYPE_BE);
-       if (ret < 0) {
-               SNDERR("failed to write be elems %zd\n", ret);
-               return ret;
-       }
-
-       /* write cc elems */
-       ret = write_block(tplg, &tplg->cc_list,
-               SND_TPLG_TYPE_CC);
-       if (ret < 0) {
-               SNDERR("failed to write cc elems %zd\n", ret);
-               return ret;
-       }
-
-       /* write route elems */
-       ret = write_block(tplg, &tplg->route_list,
-               SND_TPLG_TYPE_DAPM_GRAPH);
-       if (ret < 0) {
-               SNDERR("failed to write graph elems %zd\n", ret);
+               SNDERR("failed to write manifest %d\n", ret);
                return ret;
        }
 
-       /* write private data */
-       ret = write_block(tplg, &tplg->pdata_list,
-               SND_TPLG_TYPE_DATA);
-       if (ret < 0) {
-               SNDERR("failed to write private data %zd\n", ret);
-               return ret;
+       /* write all blocks */
+       for (index = 0; index < ARRAY_SIZE(wtable); index++) {
+               wptr = &wtable[index];
+               ret = write_block(tplg, wptr->list, wptr->type);
+               if (ret < 0) {
+                       SNDERR("failed to write %s: %s\n", wptr->name, 
snd_strerror(-ret));
+                       return ret;
+               }
        }
 
        return 0;
-- 
2.16.4

++++++ 0022-topology-use-size_t-for-calc_block_size.patch ++++++
>From f1f5b48d0cfbce0cc6400daba0020d9385d6645e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 18:26:20 +0100
Subject: [PATCH 22/30] topology: use size_t for calc_block_size()

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/builder.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/topology/builder.c b/src/topology/builder.c
index ec1af42ddf9b..bbee71d67e94 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -163,11 +163,11 @@ static int write_elem_block(snd_tplg_t *tplg,
        return 0;
 }
 
-static int calc_block_size(struct list_head *base)
+static size_t calc_block_size(struct list_head *base)
 {
        struct list_head *pos;
        struct tplg_elem *elem;
-       int size = 0;
+       size_t size = 0;
 
        list_for_each(pos, base) {
 
@@ -185,14 +185,14 @@ static int calc_block_size(struct list_head *base)
 
 static int write_block(snd_tplg_t *tplg, struct list_head *base, int type)
 {
-       int size;
+       size_t size;
 
        /* calculate the block size in bytes for all elems in this list */
        size = calc_block_size(base);
-       if (size <= 0)
+       if (size == 0)
                return size;
 
-       verbose(tplg, " block size for type %d is %d\n", type, size);
+       verbose(tplg, " block size for type %d is %zd\n", type, size);
 
        /* write each elem for this block */
        switch (type) {
-- 
2.16.4

++++++ 0023-topology-merge-write_block-to-tplg_write_data.patch ++++++
>From 4dcceb5f866deda09e971b1c31d46403c3bd8e9e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 18:49:29 +0100
Subject: [PATCH 23/30] topology: merge write_block to tplg_write_data

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/builder.c | 95 ++++++++++++++++++--------------------------------
 1 file changed, 33 insertions(+), 62 deletions(-)

diff --git a/src/topology/builder.c b/src/topology/builder.c
index bbee71d67e94..f530fcd853c4 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -183,56 +183,6 @@ static size_t calc_block_size(struct list_head *base)
        return size;
 }
 
-static int write_block(snd_tplg_t *tplg, struct list_head *base, int type)
-{
-       size_t size;
-
-       /* calculate the block size in bytes for all elems in this list */
-       size = calc_block_size(base);
-       if (size == 0)
-               return size;
-
-       verbose(tplg, " block size for type %d is %zd\n", type, size);
-
-       /* write each elem for this block */
-       switch (type) {
-       case SND_TPLG_TYPE_MIXER:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_MIXER, "mixer");
-       case SND_TPLG_TYPE_BYTES:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_BYTES, "bytes");
-       case SND_TPLG_TYPE_ENUM:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_ENUM, "enum");
-       case SND_TPLG_TYPE_DAPM_GRAPH:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_DAPM_GRAPH, "route");
-       case SND_TPLG_TYPE_DAPM_WIDGET:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_DAPM_WIDGET, "widget");
-       case SND_TPLG_TYPE_PCM:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_PCM, "pcm");
-       case SND_TPLG_TYPE_BE:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_BACKEND_LINK, "be");
-       case SND_TPLG_TYPE_CC:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_CODEC_LINK, "cc");
-       case SND_TPLG_TYPE_DATA:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_PDATA, "data");
-       case SND_TPLG_TYPE_DAI:
-               return write_elem_block(tplg, base, size,
-                       SND_SOC_TPLG_TYPE_DAI, "dai");
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 /* write the manifest including its private data */
 static ssize_t write_manifest_data(snd_tplg_t *tplg)
 {
@@ -262,60 +212,72 @@ int tplg_write_data(snd_tplg_t *tplg)
                const char *name;
                struct list_head *list;
                int type;
+               int tsoc;
        } *wptr, wtable[] = {
                {
-                       .name = "control mixer elements",
+                       .name = "control mixer",
                        .list = &tplg->mixer_list,
                        .type = SND_TPLG_TYPE_MIXER,
+                       .tsoc = SND_SOC_TPLG_TYPE_MIXER,
                },
                {
-                       .name = "control enum elements",
+                       .name = "control enum",
                        .list = &tplg->enum_list,
                        .type = SND_TPLG_TYPE_ENUM,
+                       .tsoc = SND_SOC_TPLG_TYPE_ENUM,
                },
                {
-                       .name = "control extended (bytes) elements",
+                       .name = "control extended (bytes)",
                        .list = &tplg->bytes_ext_list,
                        .type = SND_TPLG_TYPE_BYTES,
+                       .tsoc = SND_SOC_TPLG_TYPE_BYTES,
                },
                {
-                       .name = "dapm widget elements",
+                       .name = "dapm widget",
                        .list = &tplg->widget_list,
                        .type = SND_TPLG_TYPE_DAPM_WIDGET,
+                       .tsoc = SND_SOC_TPLG_TYPE_DAPM_WIDGET,
                },
                {
-                       .name = "pcm elements",
+                       .name = "pcm",
                        .list = &tplg->pcm_list,
                        .type = SND_TPLG_TYPE_PCM,
+                       .tsoc = SND_SOC_TPLG_TYPE_PCM,
                },
                {
-                       .name = "physical dai elements",
+                       .name = "physical dai",
                        .list = &tplg->dai_list,
                        .type = SND_TPLG_TYPE_DAI,
+                       .tsoc = SND_SOC_TPLG_TYPE_DAI,
                },
                {
-                       .name = "be elements",
+                       .name = "be",
                        .list = &tplg->be_list,
                        .type = SND_TPLG_TYPE_BE,
+                       .tsoc = SND_SOC_TPLG_TYPE_BACKEND_LINK,
                },
                {
-                       .name = "cc elements",
+                       .name = "cc",
                        .list = &tplg->cc_list,
                        .type = SND_TPLG_TYPE_CC,
+                       .tsoc = SND_SOC_TPLG_TYPE_CODEC_LINK,
                },
                {
-                       .name = "route (dapm graph) elements",
+                       .name = "route (dapm graph)",
                        .list = &tplg->route_list,
                        .type = SND_TPLG_TYPE_DAPM_GRAPH,
+                       .tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH,
                },
                {
-                       .name = "private data elements",
+                       .name = "private data",
                        .list = &tplg->pdata_list,
                        .type = SND_TPLG_TYPE_DATA,
+                       .tsoc = SND_SOC_TPLG_TYPE_PDATA,
                },
        };
 
        ssize_t ret;
+       size_t size;
        unsigned int index;
 
        /* write manifest */
@@ -328,9 +290,18 @@ int tplg_write_data(snd_tplg_t *tplg)
        /* write all blocks */
        for (index = 0; index < ARRAY_SIZE(wtable); index++) {
                wptr = &wtable[index];
-               ret = write_block(tplg, wptr->list, wptr->type);
+               /* calculate the block size in bytes for all elems in this list 
*/
+               size = calc_block_size(wptr->list);
+               if (size == 0)
+                       continue;
+               verbose(tplg, " block size for type %s (%d:%d) is %zd\n",
+                                               wptr->name, wptr->type,
+                                               wptr->tsoc, size);
+               ret = write_elem_block(tplg, wptr->list, size,
+                                      wptr->tsoc, wptr->name);
                if (ret < 0) {
-                       SNDERR("failed to write %s: %s\n", wptr->name, 
snd_strerror(-ret));
+                       SNDERR("failed to write %s elements: %s\n",
+                                               wptr->name, snd_strerror(-ret));
                        return ret;
                }
        }
-- 
2.16.4

++++++ 0024-topology-make-vebose-output-more-nice.patch ++++++
>From c9e9ee3c40e9f50889f2bb4065c4556184998e8f Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 18:53:41 +0100
Subject: [PATCH 24/30] topology: make vebose output more nice

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/builder.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/topology/builder.c b/src/topology/builder.c
index f530fcd853c4..1a22a453695a 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -29,7 +29,7 @@ static void verbose(snd_tplg_t *tplg, const char *fmt, ...)
                return;
 
        va_start(va, fmt);
-       fprintf(stdout, "0x%6.6zx/%6.6zd -", tplg->out_pos, tplg->out_pos);
+       fprintf(stdout, "0x%6.6zx/%6.6zd - ", tplg->out_pos, tplg->out_pos);
        vfprintf(stdout, fmt, va);
        va_end(va);
 }
@@ -80,7 +80,7 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned 
int type,
                return -EINVAL;
        }
 
-       verbose(tplg, " header index %d type %d count %d size 0x%lx/%ld vendor 
%d "
+       verbose(tplg, "header index %d type %d count %d size 0x%lx/%ld vendor 
%d "
                "version %d\n", index, type, count,
                (long unsigned int)payload_size, (long int)payload_size,
                vendor_type, version);
@@ -128,10 +128,10 @@ static int write_elem_block(snd_tplg_t *tplg,
                                        continue;
 
                                if (elem->type != SND_TPLG_TYPE_DAPM_GRAPH)
-                                       verbose(tplg, " %s '%s': write %d 
bytes\n",
+                                       verbose(tplg, "%s '%s': write %d 
bytes\n",
                                                obj_name, elem->id, elem->size);
                                else
-                                       verbose(tplg, " %s '%s -> %s -> %s': 
write %d bytes\n",
+                                       verbose(tplg, "%s '%s -> %s -> %s': 
write %d bytes\n",
                                                obj_name, elem->route->source,
                                                elem->route->control,
                                                elem->route->sink, elem->size);
@@ -197,10 +197,10 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg)
                return ret;
        }
 
-       verbose(tplg, "manifest : write %d bytes\n", sizeof(tplg->manifest));
+       verbose(tplg, "manifest: write %d bytes\n", sizeof(tplg->manifest));
        ret = twrite(tplg, &tplg->manifest, sizeof(tplg->manifest));
        if (ret >= 0) {
-               verbose(tplg, "manifest : write %d priv bytes\n", 
tplg->manifest.priv.size);
+               verbose(tplg, "manifest: write %d priv bytes\n", 
tplg->manifest.priv.size);
                ret = twrite(tplg, tplg->manifest_pdata, 
tplg->manifest.priv.size);
        }
        return ret;
@@ -294,9 +294,9 @@ int tplg_write_data(snd_tplg_t *tplg)
                size = calc_block_size(wptr->list);
                if (size == 0)
                        continue;
-               verbose(tplg, " block size for type %s (%d:%d) is %zd\n",
+               verbose(tplg, "block size for type %s (%d:%d) is 0x%zx/%zd\n",
                                                wptr->name, wptr->type,
-                                               wptr->tsoc, size);
+                                               wptr->tsoc, size, size);
                ret = write_elem_block(tplg, wptr->list, size,
                                       wptr->tsoc, wptr->name);
                if (ret < 0) {
@@ -306,5 +306,7 @@ int tplg_write_data(snd_tplg_t *tplg)
                }
        }
 
+       verbose(tplg, "total size is 0x%zx/%zd\n", tplg->out_pos, 
tplg->out_pos);
+
        return 0;
 }
-- 
2.16.4

++++++ 0025-topology-use-list_insert-macro-in-tplg_elem_insert.patch ++++++
>From 3b9e39dab5ebfb525b4437a644fe54569e419874 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 21:23:52 +0100
Subject: [PATCH 25/30] topology: use list_insert() macro in tplg_elem_insert()

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/elem.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/topology/elem.c b/src/topology/elem.c
index a9d1d8547bd2..2066fad83774 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -131,7 +131,7 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, 
const char* id,
        return NULL;
 }
 
-/* insert a new element into list in the ascending order of index value*/
+/* insert a new element into list in the ascending order of index value */
 static void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
 {
        struct list_head *pos, *p = &(elem_p->list);
@@ -142,10 +142,8 @@ static void tplg_elem_insert(struct tplg_elem *elem_p, 
struct list_head *list)
                if (elem_p->index < elem->index)
                        break;
        }
-       p->prev = pos->prev;
-       pos->prev->next = p;
-       pos->prev = p;
-       p->next = pos;
+       /* insert item before pos */
+       list_insert(p, pos->prev, pos);
 }
 
 /* create a new common element and object */
-- 
2.16.4

++++++ 0026-topology-dapm-coding-fixes.patch ++++++
>From 0d6949b7f1f99bf3fcd5cce78483c10f9ca35264 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 21:52:13 +0100
Subject: [PATCH 26/30] topology: dapm - coding fixes

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/dapm.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index 97c9695b9ebe..cd80a4c03d92 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -152,8 +152,7 @@ static int copy_dapm_control(struct tplg_elem *elem, struct 
tplg_elem *ref)
 }
 
 /* check referenced controls for a widget */
-static int tplg_build_widget(snd_tplg_t *tplg,
-       struct tplg_elem *elem)
+static int tplg_build_widget(snd_tplg_t *tplg, struct tplg_elem *elem)
 {
        struct tplg_ref *ref;
        struct list_head *base, *pos;
@@ -164,7 +163,7 @@ static int tplg_build_widget(snd_tplg_t *tplg,
        /* A widget's private data sits before the embedded controls.
         * So merge the private data blocks at first
         */
-        list_for_each(pos, base) {
+       list_for_each(pos, base) {
                ref = list_entry(pos, struct tplg_ref, list);
 
                if (ref->type != SND_TPLG_TYPE_DATA)
@@ -314,7 +313,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
        return 0;
 }
 
-struct tplg_elem* tplg_elem_new_route(snd_tplg_t *tplg)
+struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg)
 {
        struct tplg_elem *elem;
        struct snd_soc_tplg_dapm_graph_elem *line;
@@ -342,7 +341,7 @@ struct tplg_elem* tplg_elem_new_route(snd_tplg_t *tplg)
 
 /* line is defined as '"source, control, sink"' */
 static int tplg_parse_line(const char *text,
-       struct snd_soc_tplg_dapm_graph_elem *line)
+                          struct snd_soc_tplg_dapm_graph_elem *line)
 {
        char buf[LINE_SIZE];
        unsigned int len, i;
@@ -422,7 +421,7 @@ static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t 
*cfg, int index)
 }
 
 int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
-       void *private ATTRIBUTE_UNUSED)
+                         void *private ATTRIBUTE_UNUSED)
 {
        snd_config_iterator_t i, next;
        snd_config_t *n;
@@ -472,7 +471,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t 
*cfg,
 
 /* DAPM Widget */
 int tplg_parse_dapm_widget(snd_tplg_t *tplg,
-       snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+                          snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
 {
        struct snd_soc_tplg_dapm_widget *widget;
        struct tplg_elem *elem;
@@ -645,7 +644,7 @@ int tplg_add_route(snd_tplg_t *tplg, struct 
snd_tplg_graph_elem *t)
        snd_strlcpy(line->source, t->src, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
        if (t->ctl)
                snd_strlcpy(line->control, t->ctl,
-                       SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+                               SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
        snd_strlcpy(line->sink, t->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
 
        return 0;
-- 
2.16.4

++++++ 0027-topology-dapm-merge-identical-index-blocks-like-for-.patch ++++++
>From 2b50b594dcbf69f8dcc6e8cf673748f7063c3c17 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 21:56:58 +0100
Subject: [PATCH 27/30] topology: dapm - merge identical index blocks like for
 other elems

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/dapm.c       | 14 +++++++-------
 src/topology/elem.c       |  2 +-
 src/topology/tplg_local.h |  1 +
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index cd80a4c03d92..ce46913192df 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -313,7 +313,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
        return 0;
 }
 
-struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg)
+struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg, int index)
 {
        struct tplg_elem *elem;
        struct snd_soc_tplg_dapm_graph_elem *line;
@@ -322,7 +322,8 @@ struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg)
        if (!elem)
                return NULL;
 
-       list_add_tail(&elem->list, &tplg->route_list);
+       elem->index = index;
+       tplg_elem_insert(elem, &tplg->route_list);
        strcpy(elem->id, "line");
        elem->type = SND_TPLG_TYPE_DAPM_GRAPH;
        elem->size = sizeof(*line);
@@ -403,10 +404,9 @@ static int tplg_parse_routes(snd_tplg_t *tplg, 
snd_config_t *cfg, int index)
                if (snd_config_get_string(n, &val) < 0)
                        continue;
 
-               elem = tplg_elem_new_route(tplg);
+               elem = tplg_elem_new_route(tplg, index);
                if (!elem)
                        return -ENOMEM;
-               elem->index = index;
                line = elem->route;
 
                err = tplg_parse_line(val, line);
@@ -628,7 +628,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
        return 0;
 }
 
-int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t)
+int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t, int index)
 {
        struct tplg_elem *elem;
        struct snd_soc_tplg_dapm_graph_elem *line;
@@ -636,7 +636,7 @@ int tplg_add_route(snd_tplg_t *tplg, struct 
snd_tplg_graph_elem *t)
        if (!t->src || !t->sink)
                return -EINVAL;
 
-       elem = tplg_elem_new_route(tplg);
+       elem = tplg_elem_new_route(tplg, index);
        if (!elem)
                return -ENOMEM;
 
@@ -656,7 +656,7 @@ int tplg_add_graph_object(snd_tplg_t *tplg, 
snd_tplg_obj_template_t *t)
        int i, ret;
 
        for (i = 0; i < gt->count; i++) {
-               ret = tplg_add_route(tplg, gt->elem + i);
+               ret = tplg_add_route(tplg, gt->elem + i, t->index);
                if (ret < 0)
                        return ret;
        }
diff --git a/src/topology/elem.c b/src/topology/elem.c
index 2066fad83774..140cdd327994 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -132,7 +132,7 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, 
const char* id,
 }
 
 /* insert a new element into list in the ascending order of index value */
-static void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
+void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
 {
        struct list_head *pos, *p = &(elem_p->list);
        struct tplg_elem *elem;
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 7b8abcdefbcf..11efce6d580c 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -273,6 +273,7 @@ int tplg_ref_add_elem(struct tplg_elem *elem, struct 
tplg_elem *elem_ref);
 struct tplg_elem *tplg_elem_new(void);
 void tplg_elem_free(struct tplg_elem *elem);
 void tplg_elem_free_list(struct list_head *base);
+void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list);
 struct tplg_elem *tplg_elem_lookup(struct list_head *base,
                                const char* id,
                                unsigned int type,
-- 
2.16.4

++++++ 0028-topology-more-coding-fixes.patch ++++++
>From 780f17126aa8d54fc09694cbf652d4135eb731c0 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <pe...@perex.cz>
Date: Fri, 13 Dec 2019 22:07:46 +0100
Subject: [PATCH 28/30] topology: more coding fixes

Signed-off-by: Jaroslav Kysela <pe...@perex.cz>
---
 src/topology/channel.c |  4 ++--
 src/topology/ctl.c     | 15 ++++++++-------
 src/topology/elem.c    |  6 ++++--
 src/topology/ops.c     |  6 +++---
 src/topology/pcm.c     | 20 ++++++++++++--------
 src/topology/text.c    |  2 +-
 6 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/src/topology/channel.c b/src/topology/channel.c
index 8516b23f302d..60f7e219a674 100644
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -74,8 +74,8 @@ static int lookup_channel(const char *c)
 }
 
 /* Parse a channel mapping. */
-int tplg_parse_channel(snd_tplg_t *tplg,
-       snd_config_t *cfg, void *private)
+int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
+                      void *private)
 {
        snd_config_iterator_t i, next;
        snd_config_t *n;
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index a096252263a5..1db0b16eac95 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -46,7 +46,7 @@ static const struct ctl_access_elem ctl_access[] = {
 
 /* find CTL access strings and conver to values */
 static int parse_access_values(snd_config_t *cfg,
-       struct snd_soc_tplg_ctl_hdr *hdr)
+                              struct snd_soc_tplg_ctl_hdr *hdr)
 {
        snd_config_iterator_t i, next;
        snd_config_t *n;
@@ -77,7 +77,7 @@ static int parse_access_values(snd_config_t *cfg,
 
 /* Parse Access */
 int parse_access(snd_config_t *cfg,
-       struct snd_soc_tplg_ctl_hdr *hdr)
+                struct snd_soc_tplg_ctl_hdr *hdr)
 {
        snd_config_iterator_t i, next;
        snd_config_t *n;
@@ -118,7 +118,7 @@ static int copy_tlv(struct tplg_elem *elem, struct 
tplg_elem *ref)
 
 /* check referenced TLV for a mixer control */
 static int tplg_build_mixer_control(snd_tplg_t *tplg,
-                               struct tplg_elem *elem)
+                                   struct tplg_elem *elem)
 {
        struct tplg_ref *ref;
        struct list_head *base, *pos;
@@ -157,7 +157,7 @@ static int tplg_build_mixer_control(snd_tplg_t *tplg,
 }
 
 static void copy_enum_texts(struct tplg_elem *enum_elem,
-       struct tplg_elem *ref_elem)
+                           struct tplg_elem *ref_elem)
 {
        struct snd_soc_tplg_enum_control *ec = enum_elem->enum_ctrl;
        struct tplg_texts *texts = ref_elem->texts;
@@ -169,7 +169,7 @@ static void copy_enum_texts(struct tplg_elem *enum_elem,
 
 /* check referenced text for a enum control */
 static int tplg_build_enum_control(snd_tplg_t *tplg,
-                               struct tplg_elem *elem)
+                                  struct tplg_elem *elem)
 {
        struct tplg_ref *ref;
        struct list_head *base, *pos;
@@ -331,7 +331,7 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct 
tplg_elem *elem)
 
 /* Parse TLV */
 int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
-       void *private ATTRIBUTE_UNUSED)
+                  void *private ATTRIBUTE_UNUSED)
 {
        snd_config_iterator_t i, next;
        snd_config_t *n;
@@ -364,7 +364,8 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
 
 /* Parse Control Bytes */
 int tplg_parse_control_bytes(snd_tplg_t *tplg,
-       snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+                            snd_config_t *cfg,
+                            void *private ATTRIBUTE_UNUSED)
 {
        struct snd_soc_tplg_bytes_control *be;
        struct tplg_elem *elem;
diff --git a/src/topology/elem.c b/src/topology/elem.c
index 140cdd327994..d8618cc9d983 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -107,7 +107,7 @@ void tplg_elem_free_list(struct list_head *base)
 }
 
 struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
-       unsigned int type, int index)
+                                  unsigned int type, int index)
 {
        struct list_head *pos;
        struct tplg_elem *elem;
@@ -148,7 +148,9 @@ void tplg_elem_insert(struct tplg_elem *elem_p, struct 
list_head *list)
 
 /* create a new common element and object */
 struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
-       snd_config_t *cfg, const char *name, enum snd_tplg_type type)
+                                      snd_config_t *cfg,
+                                      const char *name,
+                                      enum snd_tplg_type type)
 {
        struct tplg_elem *elem;
        const char *id, *val = NULL;
diff --git a/src/topology/ops.c b/src/topology/ops.c
index 6f8dc1ff310f..0f4295a2e50c 100644
--- a/src/topology/ops.c
+++ b/src/topology/ops.c
@@ -48,8 +48,8 @@ static int lookup_ops(const char *c)
 /* Parse Control operations. Ops can come from standard names above or
  * bespoke driver controls with numbers >= 256
  */
-int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
-       snd_config_t *cfg, void *private)
+int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
+                  void *private)
 {
        snd_config_iterator_t i, next;
        snd_config_t *n;
@@ -88,7 +88,7 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
  * bespoke driver controls with numbers >= 256
  */
 int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
-       snd_config_t *cfg, void *private)
+                      snd_config_t *cfg, void *private)
 {
        snd_config_iterator_t i, next;
        snd_config_t *n;
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 553fd822031b..98a8df979e24 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -63,7 +63,8 @@ struct tplg_elem *lookup_pcm_dai_stream(struct list_head 
*base, const char* id)
 
 /* copy referenced caps to the parent (pcm or be dai) */
 static void copy_stream_caps(const char *id ATTRIBUTE_UNUSED,
-       struct snd_soc_tplg_stream_caps *caps, struct tplg_elem *ref_elem)
+                            struct snd_soc_tplg_stream_caps *caps,
+                            struct tplg_elem *ref_elem)
 {
        struct snd_soc_tplg_stream_caps *ref_caps = ref_elem->stream_caps;
 
@@ -75,7 +76,8 @@ static void copy_stream_caps(const char *id ATTRIBUTE_UNUSED,
 
 /* find and copy the referenced stream caps */
 static int tplg_build_stream_caps(snd_tplg_t *tplg,
-       const char *id, int index, struct snd_soc_tplg_stream_caps *caps)
+                                 const char *id, int index,
+                                 struct snd_soc_tplg_stream_caps *caps)
 {
        struct tplg_elem *ref_elem = NULL;
        unsigned int i;
@@ -207,7 +209,8 @@ int tplg_build_dais(snd_tplg_t *tplg, unsigned int type)
 }
 
 static int tplg_build_stream_cfg(snd_tplg_t *tplg,
-       struct snd_soc_tplg_stream *stream, int num_streams, int index)
+                                struct snd_soc_tplg_stream *stream,
+                                int num_streams, int index)
 {
        struct snd_soc_tplg_stream *strm;
        struct tplg_elem *ref_elem;
@@ -367,7 +370,8 @@ static int split_rate(struct snd_soc_tplg_stream_caps 
*caps, char *str)
 
 /* Parse pcm stream capabilities */
 int tplg_parse_stream_caps(snd_tplg_t *tplg,
-       snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+                          snd_config_t *cfg,
+                          void *private ATTRIBUTE_UNUSED)
 {
        struct snd_soc_tplg_stream_caps *sc;
        struct tplg_elem *elem;
@@ -637,8 +641,8 @@ static int parse_flag(snd_config_t *n, unsigned int mask_in,
 }
 
 /* Parse PCM (for front end DAI & DAI link) in text conf file */
-int tplg_parse_pcm(snd_tplg_t *tplg,
-       snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
+                  void *private ATTRIBUTE_UNUSED)
 {
        struct snd_soc_tplg_pcm *pcm;
        struct tplg_elem *elem;
@@ -746,8 +750,8 @@ int tplg_parse_pcm(snd_tplg_t *tplg,
 }
 
 /* Parse physical DAI */
-int tplg_parse_dai(snd_tplg_t *tplg,
-       snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
+                  void *private ATTRIBUTE_UNUSED)
 {
        struct snd_soc_tplg_dai *dai;
        struct tplg_elem *elem;
diff --git a/src/topology/text.c b/src/topology/text.c
index 72647fe04955..f301a4ded727 100644
--- a/src/topology/text.c
+++ b/src/topology/text.c
@@ -59,7 +59,7 @@ static int parse_text_values(snd_config_t *cfg, struct 
tplg_elem *elem)
 
 /* Parse Text data */
 int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
-       void *private ATTRIBUTE_UNUSED)
+                   void *private ATTRIBUTE_UNUSED)
 {
        snd_config_iterator_t i, next;
        snd_config_t *n;
-- 
2.16.4

++++++ 0029-Fix-alsa-sound-.h-for-external-programs.patch ++++++
++++ 7099 lines (skipped)

++++++ 0030-type_compat-Add-missing-__s64-and-__u64-definitions-.patch ++++++
>From 75584fe660880b332fbf60dd7968e2ed8b49a38b Mon Sep 17 00:00:00 2001
From: Takashi Iwai <ti...@suse.de>
Date: Fri, 20 Dec 2019 16:12:50 +0100
Subject: [PATCH 30/30] type_compat: Add missing __s64 and __u64 definitions
 for non-Linux

Just for the case without Linux-compatible definitions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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 d4790c1f0e64..5b765f447e2e 100644
--- a/include/sound/type_compat.h
+++ b/include/sound/type_compat.h
@@ -9,9 +9,11 @@
 typedef uint8_t __u8;
 typedef uint16_t __u16;
 typedef uint32_t __u32;
+typedef uint64_t __u64;
 typedef int8_t __s8;
 typedef int16_t __s16;
 typedef int32_t __s32;
+typedef int64_t __s64;
 
 #include <endian.h>
 #include <byteswap.h>
-- 
2.16.4

++++++ 0031-uapi-Move-typedefs-from-uapi-to-sound.patch ++++++
>From 59792f467b38d6a4c4dffdb30528f7fb03d23d96 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <ti...@suse.de>
Date: Fri, 20 Dec 2019 17:12:37 +0100
Subject: [PATCH alsa-lib] uapi: Move typedefs from uapi to sound/*

For keeping uapi/*.h cleaner.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 include/sound/emu10k1.h      |  9 +++++++++
 include/sound/hdsp.h         | 10 ++++++++++
 include/sound/hdspm.h        |  8 ++++++++
 include/sound/sb16_csp.h     |  4 ++++
 include/sound/uapi/emu10k1.h | 10 ----------
 include/sound/uapi/hdsp.h    |  9 ---------
 include/sound/uapi/hdspm.h   |  8 --------
 7 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index f06ecee51c2b..0832f95bd995 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1,2 +1,11 @@
 #include <alsa/sound/type_compat.h>
 #include <alsa/sound/uapi/emu10k1.h>
+#ifndef __emu10k1_type_defined
+#define __emu10k1_type_defined
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
+typedef struct emu10k1_ctl_elem_id emu10k1_ctl_elem_id_t;
+#endif
diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h
index 78fb745b607a..e8f931569548 100644
--- a/include/sound/hdsp.h
+++ b/include/sound/hdsp.h
@@ -1,2 +1,12 @@
 #include <alsa/sound/type_compat.h>
 #include <alsa/sound/uapi/hdsp.h>
+#ifndef __hdsp_type_defined
+#define __hdsp_type_defined
+typedef enum HDSP_IO_Type HDSP_IO_Type;
+typedef struct hdsp_peak_rms hdsp_peak_rms_t;
+typedef struct hdsp_config_info hdsp_config_info_t;
+typedef struct hdsp_firmware hdsp_firmware_t;
+typedef struct hdsp_version hdsp_version_t;
+typedef struct hdsp_mixer hdsp_mixer_t;
+typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
+#endif
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
index af6d19eda87f..d9095d9f10bb 100644
--- a/include/sound/hdspm.h
+++ b/include/sound/hdspm.h
@@ -1,2 +1,10 @@
 #include <alsa/sound/type_compat.h>
 #include <alsa/sound/uapi/hdspm.h>
+#ifndef __hdspm_type_defined
+#define __hdspm_type_defined
+typedef struct hdspm_peak_rms hdspm_peak_rms_t;
+typedef struct hdspm_config_info hdspm_config_info_t;
+typedef struct hdspm_version hdspm_version_t;
+typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
+typedef struct hdspm_mixer hdspm_mixer_t;
+#endif
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
index 24121fcbd888..fd02bc565e21 100644
--- a/include/sound/sb16_csp.h
+++ b/include/sound/sb16_csp.h
@@ -1 +1,5 @@
 #include <alsa/sound/uapi/sb16_csp.h>
+#ifndef __sb16_csp_type_defined
+#define __sb16_csp_type_defined
+typedef struct snd_sb_csp_microcode snd_sb_csp_microcode_t;
+#endif
diff --git a/include/sound/uapi/emu10k1.h b/include/sound/uapi/emu10k1.h
index c1150e4d0231..6bcd76f64c1c 100644
--- a/include/sound/uapi/emu10k1.h
+++ b/include/sound/uapi/emu10k1.h
@@ -382,14 +382,4 @@ struct snd_emu10k1_fx8010_pcm_rec {
 #define SNDRV_EMU10K1_IOCTL_SINGLE_STEP        _IOW ('H', 0x83, int)
 #define SNDRV_EMU10K1_IOCTL_DBG_READ   _IOR ('H', 0x84, int)
 
-#ifndef __KERNEL__
-/* typedefs for compatibility to user-space */
-typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
-typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
-typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
-typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
-typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
-typedef struct emu10k1_ctl_elem_id emu10k1_ctl_elem_id_t;
-#endif
-
 #endif /* _UAPI__SOUND_EMU10K1_H */
diff --git a/include/sound/uapi/hdsp.h b/include/sound/uapi/hdsp.h
index 88c92a3fb477..7ac2d3f2a9b3 100644
--- a/include/sound/uapi/hdsp.h
+++ b/include/sound/uapi/hdsp.h
@@ -97,13 +97,4 @@ struct hdsp_9632_aeb {
 
 #define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
 
-/* typedefs for compatibility to user-space */
-typedef enum HDSP_IO_Type HDSP_IO_Type;
-typedef struct hdsp_peak_rms hdsp_peak_rms_t;
-typedef struct hdsp_config_info hdsp_config_info_t;
-typedef struct hdsp_firmware hdsp_firmware_t;
-typedef struct hdsp_version hdsp_version_t;
-typedef struct hdsp_mixer hdsp_mixer_t;
-typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
-
 #endif /* __SOUND_HDSP_H */
diff --git a/include/sound/uapi/hdspm.h b/include/sound/uapi/hdspm.h
index 2d91f90eb5e1..3fbfd9dc5f51 100644
--- a/include/sound/uapi/hdspm.h
+++ b/include/sound/uapi/hdspm.h
@@ -219,12 +219,4 @@ struct hdspm_mixer_ioctl {
 /* use indirect access due to the limit of ioctl bit size */
 #define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
 
-/* typedefs for compatibility to user-space */
-typedef struct hdspm_peak_rms hdspm_peak_rms_t;
-typedef struct hdspm_config_info hdspm_config_info_t;
-typedef struct hdspm_version hdspm_version_t;
-typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
-typedef struct hdspm_mixer hdspm_mixer_t;
-
-
 #endif
-- 
2.16.4



++++++ alsa-lib-1.2.1.1.tar.bz2 -> alsa-lib-1.2.1.2.tar.bz2 ++++++
++++ 1698 lines of diff (skipped)



Reply via email to