diff --git a/alsa-git.patch b/alsa-git.patch index d59cdc5..cc848a7 100644 --- a/alsa-git.patch +++ b/alsa-git.patch @@ -1,7 +1,7 @@ From c79f09e1f5e8b559b58dacdb00708d995b2e3aa5 Mon Sep 17 00:00:00 2001 From: paulhsia Date: Sat, 30 Nov 2019 03:35:30 +0800 -Subject: [PATCH 01/10] ucm: Use strncmp to avoid access-out-of-boundary +Subject: [PATCH 01/69] 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(). @@ -34,13 +34,13 @@ index b0b6ffb3..252e50d9 100644 } -- -2.20.1 +2.24.1 From 9baf64da2f26844434ecea4825052937a3abe06c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 29 Nov 2019 22:28:26 +0100 -Subject: [PATCH 02/10] ucm: return always at least NULL if no list is +Subject: [PATCH 02/69] ucm: return always at least NULL if no list is available in snd_use_case_get_list() Signed-off-by: Jaroslav Kysela @@ -77,13 +77,13 @@ index 252e50d9..b80db65f 100644 struct dev_list_node, list, name); -- -2.20.1 +2.24.1 From ebdd2b6cdb8119cf75f0dd0a3b283d271b3a547e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sat, 30 Nov 2019 20:31:55 +0100 -Subject: [PATCH 03/10] ucm: add _identifiers list +Subject: [PATCH 03/69] ucm: add _identifiers list Signed-off-by: Jaroslav Kysela --- @@ -431,13 +431,13 @@ index b80db65f..d2078a23 100644 pthread_mutex_unlock(&uc_mgr->mutex); return err; -- -2.20.1 +2.24.1 From 5ee5ef31b5ff3fb7c904054cb9cac7478a727f7c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 1 Dec 2019 14:26:40 +0100 -Subject: [PATCH 04/10] namehint: correct the @args check +Subject: [PATCH 04/69] namehint: correct the @args check BugLink: https://github.com/alsa-project/alsa-plugins/issues/3 Signed-off-by: Jaroslav Kysela @@ -463,13 +463,13 @@ index 808df6b5..4927ef97 100644 "default", NULL) < 0) { err = -EINVAL; -- -2.20.1 +2.24.1 From 6055f8a584296abfc0cec0439ceb708f0eddcc9d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 1 Dec 2019 14:30:54 +0100 -Subject: [PATCH 05/10] namehint: improve the previous patch (check the +Subject: [PATCH 05/69] namehint: improve the previous patch (check the returned value) Signed-off-by: Jaroslav Kysela @@ -492,13 +492,13 @@ index 4927ef97..60c48ae3 100644 if (*str == '\0') continue; -- -2.20.1 +2.24.1 From 4dddcf733d56a13f4d042fefa1fb6230c09f1f65 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 2 Dec 2019 11:56:30 +0100 -Subject: [PATCH 06/10] ucm: docs - allow spaces in device names for JackHWMute +Subject: [PATCH 06/69] ucm: docs - allow spaces in device names for JackHWMute Signed-off-by: Jaroslav Kysela --- @@ -549,13 +549,13 @@ index 85c58ac0..e1f58027 100644 * - 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.20.1 +2.24.1 From 2a286ca9a8415571181ce58027686ec332a834e9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 2 Dec 2019 11:57:18 +0100 -Subject: [PATCH 07/10] use-case: docs - add PlaybackMixerCopy and +Subject: [PATCH 07/69] use-case: docs - add PlaybackMixerCopy and CaptureMixerCopy Signed-off-by: Jaroslav Kysela @@ -598,13 +598,13 @@ index e1f58027..71fcc949 100644 * - type of the master volume control * - Valid values: "soft" (software attenuation) -- -2.20.1 +2.24.1 From a0fc4447bb7c7f9a850a0a85f3a5a32c1509caf4 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 3 Dec 2019 15:01:04 +0100 -Subject: [PATCH 08/10] ucm: docs - add JackCTL, rearrange JackControl and +Subject: [PATCH 08/69] ucm: docs - add JackCTL, rearrange JackControl and JackDev Signed-off-by: Jaroslav Kysela @@ -646,13 +646,13 @@ index 71fcc949..25998cb9 100644 * If this value is set, it indicates that when the jack is plugged * in, the hardware automatically mutes some other device(s). The -- -2.20.1 +2.24.1 From e59034a0bec257cc7422a1e9436d936be8696a6f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 3 Dec 2019 18:27:39 +0100 -Subject: [PATCH 09/10] ucm: Do not fail to parse configs on cards with an +Subject: [PATCH 09/69] 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 @@ -730,13 +730,13 @@ index 00afa9e3..90e395f0 100644 strncpy(r, value, idsize); r[idsize] = '\0'; -- -2.20.1 +2.24.1 From 8e2c70add782f997f7c269ed3f722888e56ff024 Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Tue, 3 Dec 2019 18:56:40 +0100 -Subject: [PATCH 10/10] src/ucm/main.c: fix build without mixer +Subject: [PATCH 10/69] src/ucm/main.c: fix build without mixer Commit 4ce38a5ff466d18039b2606938f866ea3a6c9f3c breaks the build without mixer on: @@ -769,5 +769,21852 @@ index d2078a23..61922f10 100644 return -EINVAL; } -- -2.20.1 +2.24.1 + + +From ad8527d81b09c4d0edd054b5b1468ce1c50b23cb Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 4 Dec 2019 09:49:40 +0100 +Subject: [PATCH 11/69] alsa.m4: another try to fix the libatopology detection + +Signed-off-by: Jaroslav Kysela +--- + utils/alsa.m4 | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/utils/alsa.m4 b/utils/alsa.m4 +index 4c457f0d..320e4336 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.24.1 + + +From 555a5dbdabc5ed3be1ca81865abdb997bc3a6082 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 5 Dec 2019 16:59:05 +0100 +Subject: [PATCH 12/69] ucm: docs - add Mic/DigitalMic and multiple devices + comments + +Signed-off-by: Jaroslav Kysela +--- + include/use-case.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/include/use-case.h b/include/use-case.h +index 25998cb9..1736da25 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.24.1 + + +From 1ad660ddeecb2a364f1ca62aa60f256f7029cfdc Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 5 Dec 2019 17:01:31 +0100 +Subject: [PATCH 13/69] ucm: docs - remove DigitalMic, it does not have sense + +Signed-off-by: Jaroslav Kysela +--- + 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 1736da25..214a2a4c 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.24.1 + + +From 5473c5d677915b88d5c93d5bcc6cd16bb6a40342 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 5 Dec 2019 17:19:06 +0100 +Subject: [PATCH 14/69] ucm: docs - change the Mic description to simple + Microphone Device + +Signed-off-by: Jaroslav Kysela +--- + 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 214a2a4c..b04f7b9d 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.24.1 + + +From ca67e823833213e140a09ce43b6399b7676616df Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 6 Dec 2019 11:11:54 +0100 +Subject: [PATCH 15/69] ucm: docs - add note about the sequences and device + split + +Signed-off-by: Jaroslav Kysela +--- + include/use-case.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/include/use-case.h b/include/use-case.h +index b04f7b9d..2efcb4d8 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.24.1 + + +From f828dfe549fbab0a920768c63ebd3478272954eb Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 10 Dec 2019 11:48:06 +0100 +Subject: [PATCH 16/69] ucm: docs - remove MixerCopy values, add Priority for + verb, improve priority docs + +Signed-off-by: Jaroslav Kysela +--- + 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 2efcb4d8..134303af 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.24.1 + + +From 1744159180ac94a72036d7232e674c58cedee70a Mon Sep 17 00:00:00 2001 +From: Libin Yang +Date: Wed, 11 Dec 2019 14:07:19 +0800 +Subject: [PATCH 17/69] 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 +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index ba500277..d61124a3 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.24.1 + + +From 9980e18c3c99da42a90a98b140a0ffe7d0f92cd3 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 12 Dec 2019 18:42:33 +0100 +Subject: [PATCH 18/69] 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 +--- + src/conf.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +diff --git a/src/conf.c b/src/conf.c +index e4306504..3e753b26 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.24.1 + + +From 075ee165e647a6b434f63ca578f2f8faff2a55f6 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 16:09:35 +0100 +Subject: [PATCH 19/69] topology: remove vendor_fd/name from snd_tplg structure + - not used + +Signed-off-by: Jaroslav Kysela +--- + 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 c32267d2..22648fa5 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.24.1 + + +From ce74829db630a49569c79aea4aeb288fdd458dd8 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 17:01:03 +0100 +Subject: [PATCH 20/69] 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 +--- + 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 5ae3ae89..4e6cbbb0 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 22648fa5..7b8abcde 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.24.1 + + +From 012bd3b28c0d2744db482caca630d5b0a19e4dab Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 18:24:55 +0100 +Subject: [PATCH 21/69] topology: use an array describing blocks for the main + build loop + +Signed-off-by: Jaroslav Kysela +--- + 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 4e6cbbb0..ec1af42d 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.24.1 + + +From f1f5b48d0cfbce0cc6400daba0020d9385d6645e Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 18:26:20 +0100 +Subject: [PATCH 22/69] topology: use size_t for calc_block_size() + +Signed-off-by: Jaroslav Kysela +--- + 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 ec1af42d..bbee71d6 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.24.1 + + +From 4dcceb5f866deda09e971b1c31d46403c3bd8e9e Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 18:49:29 +0100 +Subject: [PATCH 23/69] topology: merge write_block to tplg_write_data + +Signed-off-by: Jaroslav Kysela +--- + 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 bbee71d6..f530fcd8 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.24.1 + + +From c9e9ee3c40e9f50889f2bb4065c4556184998e8f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 18:53:41 +0100 +Subject: [PATCH 24/69] topology: make vebose output more nice + +Signed-off-by: Jaroslav Kysela +--- + 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 f530fcd8..1a22a453 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.24.1 + + +From 3b9e39dab5ebfb525b4437a644fe54569e419874 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 21:23:52 +0100 +Subject: [PATCH 25/69] topology: use list_insert() macro in tplg_elem_insert() + +Signed-off-by: Jaroslav Kysela +--- + 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 a9d1d854..2066fad8 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.24.1 + + +From 0d6949b7f1f99bf3fcd5cce78483c10f9ca35264 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 21:52:13 +0100 +Subject: [PATCH 26/69] topology: dapm - coding fixes + +Signed-off-by: Jaroslav Kysela +--- + 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 97c9695b..cd80a4c0 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.24.1 + + +From 2b50b594dcbf69f8dcc6e8cf673748f7063c3c17 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 21:56:58 +0100 +Subject: [PATCH 27/69] topology: dapm - merge identical index blocks like for + other elems + +Signed-off-by: Jaroslav Kysela +--- + 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 cd80a4c0..ce469131 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 2066fad8..140cdd32 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 7b8abcde..11efce6d 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.24.1 + + +From 780f17126aa8d54fc09694cbf652d4135eb731c0 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 22:07:46 +0100 +Subject: [PATCH 28/69] topology: more coding fixes + +Signed-off-by: Jaroslav Kysela +--- + 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 8516b23f..60f7e219 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 a0962522..1db0b16e 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 140cdd32..d8618cc9 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 6f8dc1ff..0f4295a2 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 553fd822..98a8df97 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 72647fe0..f301a4de 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.24.1 + + +From ae564665ec261cf104de499b1cdda3564070fc65 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 20 Dec 2019 15:46:48 +0100 +Subject: [PATCH 29/69] Fix alsa/sound/*.h for external programs + +The recent update of sound/*.h to sync with the latest Linus uapi +files broke the build of alsa-tools programs. These files used to be +a modified version of Linux sound/* header files, so that they could +be built without Linux headers. The special prefix like __user and +other things were worked around there. + +We may do that again, but a better approach is to fix those things in +Linux kernel uapi side, while we keep the minimal workaround in +alsa-lib such as the __u16 and co type definitions. + +This patch is such an attempt, namely: +- Keep the original $LINUX/uapi/sound/*.h in include/sound/uapi + directory +- The "fixes" are applied to some uapi headers, so that they don't + contain Linux-specific prefix and use of opaque struct like + snd_ctl_elem_id +- The uapi headers are included indirectly from include/sound/*.h +- Some headers have inclusion of type_compat.h for the Linux variable + types and prefixes +- type_compat.h tries to use when __linux__ is + defined, instead of the own conflicting definitions + +The last type might need a bit more adjustment depending on the +compiler, but it can be fixed locally without disturbing else. + +Signed-off-by: Takashi Iwai +--- + configure.ac | 3 +- + include/sound/Makefile.am | 6 +- + include/sound/asequencer.h | 613 +---------------- + include/sound/asoc.h | 634 +----------------- + include/sound/asound.h | 1039 +---------------------------- + include/sound/asound_fm.h | 136 +--- + include/sound/emu10k1.h | 383 +---------- + include/sound/hdsp.h | 113 +--- + include/sound/hdspm.h | 234 +------ + include/sound/sb16_csp.h | 124 +--- + include/sound/sscape_ioctl.h | 22 +- + include/sound/tlv.h | 118 +--- + include/sound/type_compat.h | 13 + + include/sound/uapi/Makefile.am | 6 + + include/sound/uapi/asequencer.h | 612 +++++++++++++++++ + include/sound/uapi/asoc.h | 633 ++++++++++++++++++ + include/sound/uapi/asound.h | 1038 ++++++++++++++++++++++++++++ + include/sound/uapi/asound_fm.h | 135 ++++ + include/sound/uapi/emu10k1.h | 395 +++++++++++ + include/sound/uapi/hdsp.h | 109 +++ + include/sound/uapi/hdspm.h | 230 +++++++ + include/sound/uapi/sb16_csp.h | 123 ++++ + include/sound/uapi/sscape_ioctl.h | 21 + + include/sound/uapi/tlv.h | 117 ++++ + src/topology/tplg_local.h | 3 +- + 25 files changed, 3452 insertions(+), 3408 deletions(-) + create mode 100644 include/sound/uapi/Makefile.am + create mode 100644 include/sound/uapi/asequencer.h + create mode 100644 include/sound/uapi/asoc.h + create mode 100644 include/sound/uapi/asound.h + create mode 100644 include/sound/uapi/asound_fm.h + create mode 100644 include/sound/uapi/emu10k1.h + create mode 100644 include/sound/uapi/hdsp.h + create mode 100644 include/sound/uapi/hdspm.h + create mode 100644 include/sound/uapi/sb16_csp.h + create mode 100644 include/sound/uapi/sscape_ioctl.h + create mode 100644 include/sound/uapi/tlv.h + +diff --git a/configure.ac b/configure.ac +index 119ef600..886f87bc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -707,7 +707,8 @@ if test ! -L "$srcdir"/include/alsa ; then + fi + + AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \ +- include/Makefile include/sound/Makefile src/Versions src/Makefile \ ++ include/Makefile include/sound/Makefile include/sound/uapi/Makefile \ ++ src/Versions src/Makefile \ + src/control/Makefile src/mixer/Makefile \ + src/pcm/Makefile src/pcm/scopes/Makefile \ + src/rawmidi/Makefile src/timer/Makefile \ +diff --git a/include/sound/Makefile.am b/include/sound/Makefile.am +index 99c42211..ccc7d273 100644 +--- a/include/sound/Makefile.am ++++ b/include/sound/Makefile.am +@@ -1,7 +1,9 @@ ++SUBDIRS = uapi ++ + alsasoundincludedir = ${includedir}/alsa/sound + + alsasoundinclude_HEADERS = asound_fm.h hdsp.h hdspm.h sb16_csp.h \ +- sscape_ioctl.h emu10k1.h type_compat.h \ +- asoc.h tlv.h ++ sscape_ioctl.h emu10k1.h asoc.h tlv.h \ ++ type_compat.h + + noinst_HEADERS = asound.h asequencer.h +diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h +index a75e14ed..e539a77e 100644 +--- a/include/sound/asequencer.h ++++ b/include/sound/asequencer.h +@@ -1,612 +1 @@ +-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +-/* +- * Main header file for the ALSA sequencer +- * Copyright (c) 1998-1999 by Frank van de Pol +- * (c) 1998-1999 by Jaroslav Kysela +- * +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- * +- */ +-#ifndef _UAPI__SOUND_ASEQUENCER_H +-#define _UAPI__SOUND_ASEQUENCER_H +- +-#include +- +-/** version of the sequencer */ +-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 2) +- +-/** +- * definition of sequencer event types +- */ +- +-/** system messages +- * event data type = #snd_seq_result +- */ +-#define SNDRV_SEQ_EVENT_SYSTEM 0 +-#define SNDRV_SEQ_EVENT_RESULT 1 +- +-/** note messages (channel specific) +- * event data type = #snd_seq_ev_note +- */ +-#define SNDRV_SEQ_EVENT_NOTE 5 +-#define SNDRV_SEQ_EVENT_NOTEON 6 +-#define SNDRV_SEQ_EVENT_NOTEOFF 7 +-#define SNDRV_SEQ_EVENT_KEYPRESS 8 +- +-/** control messages (channel specific) +- * event data type = #snd_seq_ev_ctrl +- */ +-#define SNDRV_SEQ_EVENT_CONTROLLER 10 +-#define SNDRV_SEQ_EVENT_PGMCHANGE 11 +-#define SNDRV_SEQ_EVENT_CHANPRESS 12 +-#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */ +-#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */ +-#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */ +-#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */ +- +-/** synchronisation messages +- * event data type = #snd_seq_ev_ctrl +- */ +-#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */ +-#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */ +-#define SNDRV_SEQ_EVENT_QFRAME 22 /* midi time code quarter frame */ +-#define SNDRV_SEQ_EVENT_TIMESIGN 23 /* SMF Time Signature event */ +-#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */ +- +-/** timer messages +- * event data type = snd_seq_ev_queue_control +- */ +-#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */ +-#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */ +-#define SNDRV_SEQ_EVENT_STOP 32 /* midi Real Time Stop message */ +-#define SNDRV_SEQ_EVENT_SETPOS_TICK 33 /* set tick queue position */ +-#define SNDRV_SEQ_EVENT_SETPOS_TIME 34 /* set realtime queue position */ +-#define SNDRV_SEQ_EVENT_TEMPO 35 /* (SMF) Tempo event */ +-#define SNDRV_SEQ_EVENT_CLOCK 36 /* midi Real Time Clock message */ +-#define SNDRV_SEQ_EVENT_TICK 37 /* midi Real Time Tick message */ +-#define SNDRV_SEQ_EVENT_QUEUE_SKEW 38 /* skew queue tempo */ +- +-/** others +- * event data type = none +- */ +-#define SNDRV_SEQ_EVENT_TUNE_REQUEST 40 /* tune request */ +-#define SNDRV_SEQ_EVENT_RESET 41 /* reset to power-on state */ +-#define SNDRV_SEQ_EVENT_SENSING 42 /* "active sensing" event */ +- +-/** echo back, kernel private messages +- * event data type = any type +- */ +-#define SNDRV_SEQ_EVENT_ECHO 50 /* echo event */ +-#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */ +- +-/** system status messages (broadcast for subscribers) +- * event data type = snd_seq_addr +- */ +-#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */ +-#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */ +-#define SNDRV_SEQ_EVENT_CLIENT_CHANGE 62 /* client status/info has changed */ +-#define SNDRV_SEQ_EVENT_PORT_START 63 /* new port was created */ +-#define SNDRV_SEQ_EVENT_PORT_EXIT 64 /* port was deleted from system */ +-#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */ +- +-/** port connection changes +- * event data type = snd_seq_connect +- */ +-#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */ +-#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */ +- +-/* 70-89: synthesizer events - obsoleted */ +- +-/** user-defined events with fixed length +- * event data type = any +- */ +-#define SNDRV_SEQ_EVENT_USR0 90 +-#define SNDRV_SEQ_EVENT_USR1 91 +-#define SNDRV_SEQ_EVENT_USR2 92 +-#define SNDRV_SEQ_EVENT_USR3 93 +-#define SNDRV_SEQ_EVENT_USR4 94 +-#define SNDRV_SEQ_EVENT_USR5 95 +-#define SNDRV_SEQ_EVENT_USR6 96 +-#define SNDRV_SEQ_EVENT_USR7 97 +-#define SNDRV_SEQ_EVENT_USR8 98 +-#define SNDRV_SEQ_EVENT_USR9 99 +- +-/* 100-118: instrument layer - obsoleted */ +-/* 119-129: reserved */ +- +-/* 130-139: variable length events +- * event data type = snd_seq_ev_ext +- * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set) +- */ +-#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */ +-#define SNDRV_SEQ_EVENT_BOUNCE 131 /* error event */ +-/* 132-134: reserved */ +-#define SNDRV_SEQ_EVENT_USR_VAR0 135 +-#define SNDRV_SEQ_EVENT_USR_VAR1 136 +-#define SNDRV_SEQ_EVENT_USR_VAR2 137 +-#define SNDRV_SEQ_EVENT_USR_VAR3 138 +-#define SNDRV_SEQ_EVENT_USR_VAR4 139 +- +-/* 150-151: kernel events with quote - DO NOT use in user clients */ +-#define SNDRV_SEQ_EVENT_KERNEL_ERROR 150 +-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE 151 /* obsolete */ +- +-/* 152-191: reserved */ +- +-/* 192-254: hardware specific events */ +- +-/* 255: special event */ +-#define SNDRV_SEQ_EVENT_NONE 255 +- +- +-typedef unsigned char snd_seq_event_type_t; +- +-/** event address */ +-struct snd_seq_addr { +- unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */ +- unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */ +-}; +- +-/** port connection */ +-struct snd_seq_connect { +- struct snd_seq_addr sender; +- struct snd_seq_addr dest; +-}; +- +- +-#define SNDRV_SEQ_ADDRESS_UNKNOWN 253 /* unknown source */ +-#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS 254 /* send event to all subscribed ports */ +-#define SNDRV_SEQ_ADDRESS_BROADCAST 255 /* send event to all queues/clients/ports/channels */ +-#define SNDRV_SEQ_QUEUE_DIRECT 253 /* direct dispatch */ +- +- /* event mode flag - NOTE: only 8 bits available! */ +-#define SNDRV_SEQ_TIME_STAMP_TICK (0<<0) /* timestamp in clock ticks */ +-#define SNDRV_SEQ_TIME_STAMP_REAL (1<<0) /* timestamp in real time */ +-#define SNDRV_SEQ_TIME_STAMP_MASK (1<<0) +- +-#define SNDRV_SEQ_TIME_MODE_ABS (0<<1) /* absolute timestamp */ +-#define SNDRV_SEQ_TIME_MODE_REL (1<<1) /* relative to current time */ +-#define SNDRV_SEQ_TIME_MODE_MASK (1<<1) +- +-#define SNDRV_SEQ_EVENT_LENGTH_FIXED (0<<2) /* fixed event size */ +-#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /* variable event size */ +-#define SNDRV_SEQ_EVENT_LENGTH_VARUSR (2<<2) /* variable event size - user memory space */ +-#define SNDRV_SEQ_EVENT_LENGTH_MASK (3<<2) +- +-#define SNDRV_SEQ_PRIORITY_NORMAL (0<<4) /* normal priority */ +-#define SNDRV_SEQ_PRIORITY_HIGH (1<<4) /* event should be processed before others */ +-#define SNDRV_SEQ_PRIORITY_MASK (1<<4) +- +- +- /* note event */ +-struct snd_seq_ev_note { +- unsigned char channel; +- unsigned char note; +- unsigned char velocity; +- unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */ +- unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */ +-}; +- +- /* controller event */ +-struct snd_seq_ev_ctrl { +- unsigned char channel; +- unsigned char unused1, unused2, unused3; /* pad */ +- unsigned int param; +- signed int value; +-}; +- +- /* generic set of bytes (12x8 bit) */ +-struct snd_seq_ev_raw8 { +- unsigned char d[12]; /* 8 bit value */ +-}; +- +- /* generic set of integers (3x32 bit) */ +-struct snd_seq_ev_raw32 { +- unsigned int d[3]; /* 32 bit value */ +-}; +- +- /* external stored data */ +-struct snd_seq_ev_ext { +- unsigned int len; /* length of data */ +- void *ptr; /* pointer to data (note: maybe 64-bit) */ +-} __attribute__((packed)); +- +-struct snd_seq_result { +- int event; /* processed event type */ +- int result; +-}; +- +- +-struct snd_seq_real_time { +- unsigned int tv_sec; /* seconds */ +- unsigned int tv_nsec; /* nanoseconds */ +-}; +- +-typedef unsigned int snd_seq_tick_time_t; /* midi ticks */ +- +-union snd_seq_timestamp { +- snd_seq_tick_time_t tick; +- struct snd_seq_real_time time; +-}; +- +-struct snd_seq_queue_skew { +- unsigned int value; +- unsigned int base; +-}; +- +- /* queue timer control */ +-struct snd_seq_ev_queue_control { +- unsigned char queue; /* affected queue */ +- unsigned char pad[3]; /* reserved */ +- union { +- signed int value; /* affected value (e.g. tempo) */ +- union snd_seq_timestamp time; /* time */ +- unsigned int position; /* sync position */ +- struct snd_seq_queue_skew skew; +- unsigned int d32[2]; +- unsigned char d8[8]; +- } param; +-}; +- +- /* quoted event - inside the kernel only */ +-struct snd_seq_ev_quote { +- struct snd_seq_addr origin; /* original sender */ +- unsigned short value; /* optional data */ +- struct snd_seq_event *event; /* quoted event */ +-} __attribute__((packed)); +- +- +- /* sequencer event */ +-struct snd_seq_event { +- snd_seq_event_type_t type; /* event type */ +- unsigned char flags; /* event flags */ +- char tag; +- +- unsigned char queue; /* schedule queue */ +- union snd_seq_timestamp time; /* schedule time */ +- +- +- struct snd_seq_addr source; /* source address */ +- struct snd_seq_addr dest; /* destination address */ +- +- union { /* event data... */ +- struct snd_seq_ev_note note; +- struct snd_seq_ev_ctrl control; +- struct snd_seq_ev_raw8 raw8; +- struct snd_seq_ev_raw32 raw32; +- struct snd_seq_ev_ext ext; +- struct snd_seq_ev_queue_control queue; +- union snd_seq_timestamp time; +- struct snd_seq_addr addr; +- struct snd_seq_connect connect; +- struct snd_seq_result result; +- struct snd_seq_ev_quote quote; +- } data; +-}; +- +- +-/* +- * bounce event - stored as variable size data +- */ +-struct snd_seq_event_bounce { +- int err; +- struct snd_seq_event event; +- /* external data follows here. */ +-}; +- +- +- /* system information */ +-struct snd_seq_system_info { +- int queues; /* maximum queues count */ +- int clients; /* maximum clients count */ +- int ports; /* maximum ports per client */ +- int channels; /* maximum channels per port */ +- int cur_clients; /* current clients */ +- int cur_queues; /* current queues */ +- char reserved[24]; +-}; +- +- +- /* system running information */ +-struct snd_seq_running_info { +- unsigned char client; /* client id */ +- unsigned char big_endian; /* 1 = big-endian */ +- unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */ +- unsigned char pad; /* reserved */ +- unsigned char reserved[12]; +-}; +- +- +- /* known client numbers */ +-#define SNDRV_SEQ_CLIENT_SYSTEM 0 +- /* internal client numbers */ +-#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */ +-#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */ +- +- +- /* client types */ +-typedef int __bitwise snd_seq_client_type_t; +-#define NO_CLIENT ((__force snd_seq_client_type_t) 0) +-#define USER_CLIENT ((__force snd_seq_client_type_t) 1) +-#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2) +- +- /* event filter flags */ +-#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */ +-#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */ +-#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */ +-#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */ +- +-struct snd_seq_client_info { +- int client; /* client number to inquire */ +- snd_seq_client_type_t type; /* client type */ +- char name[64]; /* client name */ +- unsigned int filter; /* filter flags */ +- unsigned char multicast_filter[8]; /* multicast filter bitmap */ +- unsigned char event_filter[32]; /* event filter bitmap */ +- int num_ports; /* RO: number of ports */ +- int event_lost; /* number of lost events */ +- int card; /* RO: card number[kernel] */ +- int pid; /* RO: pid[user] */ +- char reserved[56]; /* for future use */ +-}; +- +- +-/* client pool size */ +-struct snd_seq_client_pool { +- int client; /* client number to inquire */ +- int output_pool; /* outgoing (write) pool size */ +- int input_pool; /* incoming (read) pool size */ +- int output_room; /* minimum free pool size for select/blocking mode */ +- int output_free; /* unused size */ +- int input_free; /* unused size */ +- char reserved[64]; +-}; +- +- +-/* Remove events by specified criteria */ +- +-#define SNDRV_SEQ_REMOVE_INPUT (1<<0) /* Flush input queues */ +-#define SNDRV_SEQ_REMOVE_OUTPUT (1<<1) /* Flush output queues */ +-#define SNDRV_SEQ_REMOVE_DEST (1<<2) /* Restrict by destination q:client:port */ +-#define SNDRV_SEQ_REMOVE_DEST_CHANNEL (1<<3) /* Restrict by channel */ +-#define SNDRV_SEQ_REMOVE_TIME_BEFORE (1<<4) /* Restrict to before time */ +-#define SNDRV_SEQ_REMOVE_TIME_AFTER (1<<5) /* Restrict to time or after */ +-#define SNDRV_SEQ_REMOVE_TIME_TICK (1<<6) /* Time is in ticks */ +-#define SNDRV_SEQ_REMOVE_EVENT_TYPE (1<<7) /* Restrict to event type */ +-#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */ +-#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */ +- +-struct snd_seq_remove_events { +- unsigned int remove_mode; /* Flags that determine what gets removed */ +- +- union snd_seq_timestamp time; +- +- unsigned char queue; /* Queue for REMOVE_DEST */ +- struct snd_seq_addr dest; /* Address for REMOVE_DEST */ +- unsigned char channel; /* Channel for REMOVE_DEST */ +- +- int type; /* For REMOVE_EVENT_TYPE */ +- char tag; /* Tag for REMOVE_TAG */ +- +- int reserved[10]; /* To allow for future binary compatibility */ +- +-}; +- +- +- /* known port numbers */ +-#define SNDRV_SEQ_PORT_SYSTEM_TIMER 0 +-#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1 +- +- /* port capabilities (32 bits) */ +-#define SNDRV_SEQ_PORT_CAP_READ (1<<0) /* readable from this port */ +-#define SNDRV_SEQ_PORT_CAP_WRITE (1<<1) /* writable to this port */ +- +-#define SNDRV_SEQ_PORT_CAP_SYNC_READ (1<<2) +-#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE (1<<3) +- +-#define SNDRV_SEQ_PORT_CAP_DUPLEX (1<<4) +- +-#define SNDRV_SEQ_PORT_CAP_SUBS_READ (1<<5) /* allow read subscription */ +-#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */ +-#define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */ +- +- /* port type */ +-#define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */ +-#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /* generic MIDI device */ +-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM (1<<2) /* General MIDI compatible device */ +-#define SNDRV_SEQ_PORT_TYPE_MIDI_GS (1<<3) /* GS compatible device */ +-#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */ +-#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */ +-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */ +- +-/* other standards...*/ +-#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */ +-#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */ +-#define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */ +-/*...*/ +-#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */ +-#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */ +-#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */ +-#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */ +-#define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */ +- +-/* misc. conditioning flags */ +-#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0) +-#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1) +-#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2) +- +-struct snd_seq_port_info { +- struct snd_seq_addr addr; /* client/port numbers */ +- char name[64]; /* port name */ +- +- unsigned int capability; /* port capability bits */ +- unsigned int type; /* port type bits */ +- int midi_channels; /* channels per MIDI port */ +- int midi_voices; /* voices per MIDI port */ +- int synth_voices; /* voices per SYNTH port */ +- +- int read_use; /* R/O: subscribers for output (from this port) */ +- int write_use; /* R/O: subscribers for input (to this port) */ +- +- void *kernel; /* reserved for kernel use (must be NULL) */ +- unsigned int flags; /* misc. conditioning */ +- unsigned char time_queue; /* queue # for timestamping */ +- char reserved[59]; /* for future use */ +-}; +- +- +-/* queue flags */ +-#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */ +- +-/* queue information */ +-struct snd_seq_queue_info { +- int queue; /* queue id */ +- +- /* +- * security settings, only owner of this queue can start/stop timer +- * etc. if the queue is locked for other clients +- */ +- int owner; /* client id for owner of the queue */ +- unsigned locked:1; /* timing queue locked for other queues */ +- char name[64]; /* name of this queue */ +- unsigned int flags; /* flags */ +- char reserved[60]; /* for future use */ +- +-}; +- +-/* queue info/status */ +-struct snd_seq_queue_status { +- int queue; /* queue id */ +- int events; /* read-only - queue size */ +- snd_seq_tick_time_t tick; /* current tick */ +- struct snd_seq_real_time time; /* current time */ +- int running; /* running state of queue */ +- int flags; /* various flags */ +- char reserved[64]; /* for the future */ +-}; +- +- +-/* queue tempo */ +-struct snd_seq_queue_tempo { +- int queue; /* sequencer queue */ +- unsigned int tempo; /* current tempo, us/tick */ +- int ppq; /* time resolution, ticks/quarter */ +- unsigned int skew_value; /* queue skew */ +- unsigned int skew_base; /* queue skew base */ +- char reserved[24]; /* for the future */ +-}; +- +- +-/* sequencer timer sources */ +-#define SNDRV_SEQ_TIMER_ALSA 0 /* ALSA timer */ +-#define SNDRV_SEQ_TIMER_MIDI_CLOCK 1 /* Midi Clock (CLOCK event) */ +-#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */ +- +-/* queue timer info */ +-struct snd_seq_queue_timer { +- int queue; /* sequencer queue */ +- int type; /* source timer type */ +- union { +- struct { +- struct snd_timer_id id; /* ALSA's timer ID */ +- unsigned int resolution; /* resolution in Hz */ +- } alsa; +- } u; +- char reserved[64]; /* for the future use */ +-}; +- +- +-struct snd_seq_queue_client { +- int queue; /* sequencer queue */ +- int client; /* sequencer client */ +- int used; /* queue is used with this client +- (must be set for accepting events) */ +- /* per client watermarks */ +- char reserved[64]; /* for future use */ +-}; +- +- +-#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE (1<<0) /* exclusive connection */ +-#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1) +-#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2) +- +-struct snd_seq_port_subscribe { +- struct snd_seq_addr sender; /* sender address */ +- struct snd_seq_addr dest; /* destination address */ +- unsigned int voices; /* number of voices to be allocated (0 = don't care) */ +- unsigned int flags; /* modes */ +- unsigned char queue; /* input time-stamp queue (optional) */ +- unsigned char pad[3]; /* reserved */ +- char reserved[64]; +-}; +- +-/* type of query subscription */ +-#define SNDRV_SEQ_QUERY_SUBS_READ 0 +-#define SNDRV_SEQ_QUERY_SUBS_WRITE 1 +- +-struct snd_seq_query_subs { +- struct snd_seq_addr root; /* client/port id to be searched */ +- int type; /* READ or WRITE */ +- int index; /* 0..N-1 */ +- int num_subs; /* R/O: number of subscriptions on this port */ +- struct snd_seq_addr addr; /* R/O: result */ +- unsigned char queue; /* R/O: result */ +- unsigned int flags; /* R/O: result */ +- char reserved[64]; /* for future use */ +-}; +- +- +-/* +- * IOCTL commands +- */ +- +-#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int) +-#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int) +-#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info) +-#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info) +- +-#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info) +-#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info) +- +-#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info) +-#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info) +-#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info) +-#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info) +- +-#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe) +-#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe) +- +-#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info) +-#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info) +-#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info) +-#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info) +-#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info) +-#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status) +-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo) +-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo) +-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer) +-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer) +-#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client) +-#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client) +-#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool) +-#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool) +-#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events) +-#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs) +-#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe) +-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info) +-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info) +- +-#endif /* _UAPI__SOUND_ASEQUENCER_H */ ++#include +diff --git a/include/sound/asoc.h b/include/sound/asoc.h +index a74ca232..185bba81 100644 +--- a/include/sound/asoc.h ++++ b/include/sound/asoc.h +@@ -1,633 +1 @@ +-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +-/* +- * uapi/sound/asoc.h -- ALSA SoC Firmware Controls and DAPM +- * +- * Copyright (C) 2012 Texas Instruments Inc. +- * Copyright (C) 2015 Intel Corporation. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- * +- * Simple file API to load FW that includes mixers, coefficients, DAPM graphs, +- * algorithms, equalisers, DAIs, widgets etc. +-*/ +- +-#ifndef __LINUX_UAPI_SND_ASOC_H +-#define __LINUX_UAPI_SND_ASOC_H +- +-#include +-#include +- +-/* +- * Maximum number of channels topology kcontrol can represent. +- */ +-#define SND_SOC_TPLG_MAX_CHAN 8 +- +-/* +- * Maximum number of PCM formats capability +- */ +-#define SND_SOC_TPLG_MAX_FORMATS 16 +- +-/* +- * Maximum number of PCM stream configs +- */ +-#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8 +- +-/* +- * Maximum number of physical link's hardware configs +- */ +-#define SND_SOC_TPLG_HW_CONFIG_MAX 8 +- +-/* individual kcontrol info types - can be mixed with other types */ +-#define SND_SOC_TPLG_CTL_VOLSW 1 +-#define SND_SOC_TPLG_CTL_VOLSW_SX 2 +-#define SND_SOC_TPLG_CTL_VOLSW_XR_SX 3 +-#define SND_SOC_TPLG_CTL_ENUM 4 +-#define SND_SOC_TPLG_CTL_BYTES 5 +-#define SND_SOC_TPLG_CTL_ENUM_VALUE 6 +-#define SND_SOC_TPLG_CTL_RANGE 7 +-#define SND_SOC_TPLG_CTL_STROBE 8 +- +- +-/* individual widget kcontrol info types - can be mixed with other types */ +-#define SND_SOC_TPLG_DAPM_CTL_VOLSW 64 +-#define SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE 65 +-#define SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT 66 +-#define SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE 67 +-#define SND_SOC_TPLG_DAPM_CTL_PIN 68 +- +-/* DAPM widget types - add new items to the end */ +-#define SND_SOC_TPLG_DAPM_INPUT 0 +-#define SND_SOC_TPLG_DAPM_OUTPUT 1 +-#define SND_SOC_TPLG_DAPM_MUX 2 +-#define SND_SOC_TPLG_DAPM_MIXER 3 +-#define SND_SOC_TPLG_DAPM_PGA 4 +-#define SND_SOC_TPLG_DAPM_OUT_DRV 5 +-#define SND_SOC_TPLG_DAPM_ADC 6 +-#define SND_SOC_TPLG_DAPM_DAC 7 +-#define SND_SOC_TPLG_DAPM_SWITCH 8 +-#define SND_SOC_TPLG_DAPM_PRE 9 +-#define SND_SOC_TPLG_DAPM_POST 10 +-#define SND_SOC_TPLG_DAPM_AIF_IN 11 +-#define SND_SOC_TPLG_DAPM_AIF_OUT 12 +-#define SND_SOC_TPLG_DAPM_DAI_IN 13 +-#define SND_SOC_TPLG_DAPM_DAI_OUT 14 +-#define SND_SOC_TPLG_DAPM_DAI_LINK 15 +-#define SND_SOC_TPLG_DAPM_BUFFER 16 +-#define SND_SOC_TPLG_DAPM_SCHEDULER 17 +-#define SND_SOC_TPLG_DAPM_EFFECT 18 +-#define SND_SOC_TPLG_DAPM_SIGGEN 19 +-#define SND_SOC_TPLG_DAPM_SRC 20 +-#define SND_SOC_TPLG_DAPM_ASRC 21 +-#define SND_SOC_TPLG_DAPM_ENCODER 22 +-#define SND_SOC_TPLG_DAPM_DECODER 23 +-#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DECODER +- +-/* Header magic number and string sizes */ +-#define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */ +- +-/* string sizes */ +-#define SND_SOC_TPLG_NUM_TEXTS 16 +- +-/* ABI version */ +-#define SND_SOC_TPLG_ABI_VERSION 0x5 /* current version */ +-#define SND_SOC_TPLG_ABI_VERSION_MIN 0x4 /* oldest version supported */ +- +-/* Max size of TLV data */ +-#define SND_SOC_TPLG_TLV_SIZE 32 +- +-/* +- * File and Block header data types. +- * Add new generic and vendor types to end of list. +- * Generic types are handled by the core whilst vendors types are passed +- * to the component drivers for handling. +- */ +-#define SND_SOC_TPLG_TYPE_MIXER 1 +-#define SND_SOC_TPLG_TYPE_BYTES 2 +-#define SND_SOC_TPLG_TYPE_ENUM 3 +-#define SND_SOC_TPLG_TYPE_DAPM_GRAPH 4 +-#define SND_SOC_TPLG_TYPE_DAPM_WIDGET 5 +-#define SND_SOC_TPLG_TYPE_DAI_LINK 6 +-#define SND_SOC_TPLG_TYPE_PCM 7 +-#define SND_SOC_TPLG_TYPE_MANIFEST 8 +-#define SND_SOC_TPLG_TYPE_CODEC_LINK 9 +-#define SND_SOC_TPLG_TYPE_BACKEND_LINK 10 +-#define SND_SOC_TPLG_TYPE_PDATA 11 +-#define SND_SOC_TPLG_TYPE_DAI 12 +-#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_DAI +- +-/* vendor block IDs - please add new vendor types to end */ +-#define SND_SOC_TPLG_TYPE_VENDOR_FW 1000 +-#define SND_SOC_TPLG_TYPE_VENDOR_CONFIG 1001 +-#define SND_SOC_TPLG_TYPE_VENDOR_COEFF 1002 +-#define SND_SOC_TPLG_TYPEVENDOR_CODEC 1003 +- +-#define SND_SOC_TPLG_STREAM_PLAYBACK 0 +-#define SND_SOC_TPLG_STREAM_CAPTURE 1 +- +-/* vendor tuple types */ +-#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0 +-#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1 +-#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2 +-#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3 +-#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 +-#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5 +- +-/* DAI flags */ +-#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0) +-#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) +-#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2) +- +-/* DAI clock gating */ +-#define SND_SOC_TPLG_DAI_CLK_GATE_UNDEFINED 0 +-#define SND_SOC_TPLG_DAI_CLK_GATE_GATED 1 +-#define SND_SOC_TPLG_DAI_CLK_GATE_CONT 2 +- +-/* DAI mclk_direction */ +-#define SND_SOC_TPLG_MCLK_CO 0 /* for codec, mclk is output */ +-#define SND_SOC_TPLG_MCLK_CI 1 /* for codec, mclk is input */ +- +-/* DAI physical PCM data formats. +- * Add new formats to the end of the list. +- */ +-#define SND_SOC_DAI_FORMAT_I2S 1 /* I2S mode */ +-#define SND_SOC_DAI_FORMAT_RIGHT_J 2 /* Right Justified mode */ +-#define SND_SOC_DAI_FORMAT_LEFT_J 3 /* Left Justified mode */ +-#define SND_SOC_DAI_FORMAT_DSP_A 4 /* L data MSB after FRM LRC */ +-#define SND_SOC_DAI_FORMAT_DSP_B 5 /* L data MSB during FRM LRC */ +-#define SND_SOC_DAI_FORMAT_AC97 6 /* AC97 */ +-#define SND_SOC_DAI_FORMAT_PDM 7 /* Pulse density modulation */ +- +-/* left and right justified also known as MSB and LSB respectively */ +-#define SND_SOC_DAI_FORMAT_MSB SND_SOC_DAI_FORMAT_LEFT_J +-#define SND_SOC_DAI_FORMAT_LSB SND_SOC_DAI_FORMAT_RIGHT_J +- +-/* DAI link flags */ +-#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES (1 << 0) +-#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) +-#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2) +-#define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP (1 << 3) +- +-/* DAI topology BCLK parameter +- * For the backwards capability, by default codec is bclk master +- */ +-#define SND_SOC_TPLG_BCLK_CM 0 /* codec is bclk master */ +-#define SND_SOC_TPLG_BCLK_CS 1 /* codec is bclk slave */ +- +-/* DAI topology FSYNC parameter +- * For the backwards capability, by default codec is fsync master +- */ +-#define SND_SOC_TPLG_FSYNC_CM 0 /* codec is fsync master */ +-#define SND_SOC_TPLG_FSYNC_CS 1 /* codec is fsync slave */ +- +-/* +- * Block Header. +- * This header precedes all object and object arrays below. +- */ +-struct snd_soc_tplg_hdr { +- __le32 magic; /* magic number */ +- __le32 abi; /* ABI version */ +- __le32 version; /* optional vendor specific version details */ +- __le32 type; /* SND_SOC_TPLG_TYPE_ */ +- __le32 size; /* size of this structure */ +- __le32 vendor_type; /* optional vendor specific type info */ +- __le32 payload_size; /* data bytes, excluding this header */ +- __le32 index; /* identifier for block */ +- __le32 count; /* number of elements in block */ +-} __attribute__((packed)); +- +-/* vendor tuple for uuid */ +-struct snd_soc_tplg_vendor_uuid_elem { +- __le32 token; +- char uuid[16]; +-} __attribute__((packed)); +- +-/* vendor tuple for a bool/byte/short/word value */ +-struct snd_soc_tplg_vendor_value_elem { +- __le32 token; +- __le32 value; +-} __attribute__((packed)); +- +-/* vendor tuple for string */ +-struct snd_soc_tplg_vendor_string_elem { +- __le32 token; +- char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +-} __attribute__((packed)); +- +-struct snd_soc_tplg_vendor_array { +- __le32 size; /* size in bytes of the array, including all elements */ +- __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */ +- __le32 num_elems; /* number of elements in array */ +- union { +- struct snd_soc_tplg_vendor_uuid_elem uuid[0]; +- struct snd_soc_tplg_vendor_value_elem value[0]; +- struct snd_soc_tplg_vendor_string_elem string[0]; +- }; +-} __attribute__((packed)); +- +-/* +- * Private data. +- * All topology objects may have private data that can be used by the driver or +- * firmware. Core will ignore this data. +- */ +-struct snd_soc_tplg_private { +- __le32 size; /* in bytes of private data */ +- union { +- char data[0]; +- struct snd_soc_tplg_vendor_array array[0]; +- }; +-} __attribute__((packed)); +- +-/* +- * Kcontrol TLV data. +- */ +-struct snd_soc_tplg_tlv_dbscale { +- __le32 min; +- __le32 step; +- __le32 mute; +-} __attribute__((packed)); +- +-struct snd_soc_tplg_ctl_tlv { +- __le32 size; /* in bytes of this structure */ +- __le32 type; /* SNDRV_CTL_TLVT_*, type of TLV */ +- union { +- __le32 data[SND_SOC_TPLG_TLV_SIZE]; +- struct snd_soc_tplg_tlv_dbscale scale; +- }; +-} __attribute__((packed)); +- +-/* +- * Kcontrol channel data +- */ +-struct snd_soc_tplg_channel { +- __le32 size; /* in bytes of this structure */ +- __le32 reg; +- __le32 shift; +- __le32 id; /* ID maps to Left, Right, LFE etc */ +-} __attribute__((packed)); +- +-/* +- * Genericl Operations IDs, for binding Kcontrol or Bytes ext ops +- * Kcontrol ops need get/put/info. +- * Bytes ext ops need get/put. +- */ +-struct snd_soc_tplg_io_ops { +- __le32 get; +- __le32 put; +- __le32 info; +-} __attribute__((packed)); +- +-/* +- * kcontrol header +- */ +-struct snd_soc_tplg_ctl_hdr { +- __le32 size; /* in bytes of this structure */ +- __le32 type; +- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- __le32 access; +- struct snd_soc_tplg_io_ops ops; +- struct snd_soc_tplg_ctl_tlv tlv; +-} __attribute__((packed)); +- +-/* +- * Stream Capabilities +- */ +-struct snd_soc_tplg_stream_caps { +- __le32 size; /* in bytes of this structure */ +- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */ +- __le32 rates; /* supported rates SNDRV_PCM_RATE_* */ +- __le32 rate_min; /* min rate */ +- __le32 rate_max; /* max rate */ +- __le32 channels_min; /* min channels */ +- __le32 channels_max; /* max channels */ +- __le32 periods_min; /* min number of periods */ +- __le32 periods_max; /* max number of periods */ +- __le32 period_size_min; /* min period size bytes */ +- __le32 period_size_max; /* max period size bytes */ +- __le32 buffer_size_min; /* min buffer size bytes */ +- __le32 buffer_size_max; /* max buffer size bytes */ +- __le32 sig_bits; /* number of bits of content */ +-} __attribute__((packed)); +- +-/* +- * FE or BE Stream configuration supported by SW/FW +- */ +-struct snd_soc_tplg_stream { +- __le32 size; /* in bytes of this structure */ +- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* Name of the stream */ +- __le64 format; /* SNDRV_PCM_FMTBIT_* */ +- __le32 rate; /* SNDRV_PCM_RATE_* */ +- __le32 period_bytes; /* size of period in bytes */ +- __le32 buffer_bytes; /* size of buffer in bytes */ +- __le32 channels; /* channels */ +-} __attribute__((packed)); +- +- +-/* +- * Describes a physical link's runtime supported hardware config, +- * i.e. hardware audio formats. +- */ +-struct snd_soc_tplg_hw_config { +- __le32 size; /* in bytes of this structure */ +- __le32 id; /* unique ID - - used to match */ +- __le32 fmt; /* SND_SOC_DAI_FORMAT_ format value */ +- __u8 clock_gated; /* SND_SOC_TPLG_DAI_CLK_GATE_ value */ +- __u8 invert_bclk; /* 1 for inverted BCLK, 0 for normal */ +- __u8 invert_fsync; /* 1 for inverted frame clock, 0 for normal */ +- __u8 bclk_master; /* SND_SOC_TPLG_BCLK_ value */ +- __u8 fsync_master; /* SND_SOC_TPLG_FSYNC_ value */ +- __u8 mclk_direction; /* SND_SOC_TPLG_MCLK_ value */ +- __le16 reserved; /* for 32bit alignment */ +- __le32 mclk_rate; /* MCLK or SYSCLK freqency in Hz */ +- __le32 bclk_rate; /* BCLK freqency in Hz */ +- __le32 fsync_rate; /* frame clock in Hz */ +- __le32 tdm_slots; /* number of TDM slots in use */ +- __le32 tdm_slot_width; /* width in bits for each slot */ +- __le32 tx_slots; /* bit mask for active Tx slots */ +- __le32 rx_slots; /* bit mask for active Rx slots */ +- __le32 tx_channels; /* number of Tx channels */ +- __le32 tx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */ +- __le32 rx_channels; /* number of Rx channels */ +- __le32 rx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */ +-} __attribute__((packed)); +- +-/* +- * Manifest. List totals for each payload type. Not used in parsing, but will +- * be passed to the component driver before any other objects in order for any +- * global component resource allocations. +- * +- * File block representation for manifest :- +- * +-----------------------------------+----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-----------------------------------+----+ +- * | struct snd_soc_tplg_manifest | 1 | +- * +-----------------------------------+----+ +- */ +-struct snd_soc_tplg_manifest { +- __le32 size; /* in bytes of this structure */ +- __le32 control_elems; /* number of control elements */ +- __le32 widget_elems; /* number of widget elements */ +- __le32 graph_elems; /* number of graph elements */ +- __le32 pcm_elems; /* number of PCM elements */ +- __le32 dai_link_elems; /* number of DAI link elements */ +- __le32 dai_elems; /* number of physical DAI elements */ +- __le32 reserved[20]; /* reserved for new ABI element types */ +- struct snd_soc_tplg_private priv; +-} __attribute__((packed)); +- +-/* +- * Mixer kcontrol. +- * +- * File block representation for mixer kcontrol :- +- * +-----------------------------------+----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-----------------------------------+----+ +- * | struct snd_soc_tplg_mixer_control | N | +- * +-----------------------------------+----+ +- */ +-struct snd_soc_tplg_mixer_control { +- struct snd_soc_tplg_ctl_hdr hdr; +- __le32 size; /* in bytes of this structure */ +- __le32 min; +- __le32 max; +- __le32 platform_max; +- __le32 invert; +- __le32 num_channels; +- struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN]; +- struct snd_soc_tplg_private priv; +-} __attribute__((packed)); +- +-/* +- * Enumerated kcontrol +- * +- * File block representation for enum kcontrol :- +- * +-----------------------------------+----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-----------------------------------+----+ +- * | struct snd_soc_tplg_enum_control | N | +- * +-----------------------------------+----+ +- */ +-struct snd_soc_tplg_enum_control { +- struct snd_soc_tplg_ctl_hdr hdr; +- __le32 size; /* in bytes of this structure */ +- __le32 num_channels; +- struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN]; +- __le32 items; +- __le32 mask; +- __le32 count; +- char texts[SND_SOC_TPLG_NUM_TEXTS][SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- __le32 values[SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN / 4]; +- struct snd_soc_tplg_private priv; +-} __attribute__((packed)); +- +-/* +- * Bytes kcontrol +- * +- * File block representation for bytes kcontrol :- +- * +-----------------------------------+----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-----------------------------------+----+ +- * | struct snd_soc_tplg_bytes_control | N | +- * +-----------------------------------+----+ +- */ +-struct snd_soc_tplg_bytes_control { +- struct snd_soc_tplg_ctl_hdr hdr; +- __le32 size; /* in bytes of this structure */ +- __le32 max; +- __le32 mask; +- __le32 base; +- __le32 num_regs; +- struct snd_soc_tplg_io_ops ext_ops; +- struct snd_soc_tplg_private priv; +-} __attribute__((packed)); +- +-/* +- * DAPM Graph Element +- * +- * File block representation for DAPM graph elements :- +- * +-------------------------------------+----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-------------------------------------+----+ +- * | struct snd_soc_tplg_dapm_graph_elem | N | +- * +-------------------------------------+----+ +- */ +-struct snd_soc_tplg_dapm_graph_elem { +- char sink[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- char control[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- char source[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +-} __attribute__((packed)); +- +-/* +- * DAPM Widget. +- * +- * File block representation for DAPM widget :- +- * +-------------------------------------+-----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-------------------------------------+-----+ +- * | struct snd_soc_tplg_dapm_widget | N | +- * +-------------------------------------+-----+ +- * | struct snd_soc_tplg_enum_control | 0|1 | +- * | struct snd_soc_tplg_mixer_control | 0|N | +- * +-------------------------------------+-----+ +- * +- * Optional enum or mixer control can be appended to the end of each widget +- * in the block. +- */ +-struct snd_soc_tplg_dapm_widget { +- __le32 size; /* in bytes of this structure */ +- __le32 id; /* SND_SOC_DAPM_CTL */ +- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- char sname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- +- __le32 reg; /* negative reg = no direct dapm */ +- __le32 shift; /* bits to shift */ +- __le32 mask; /* non-shifted mask */ +- __le32 subseq; /* sort within widget type */ +- __le32 invert; /* invert the power bit */ +- __le32 ignore_suspend; /* kept enabled over suspend */ +- __le16 event_flags; +- __le16 event_type; +- __le32 num_kcontrols; +- struct snd_soc_tplg_private priv; +- /* +- * kcontrols that relate to this widget +- * follow here after widget private data +- */ +-} __attribute__((packed)); +- +- +-/* +- * Describes SW/FW specific features of PCM (FE DAI & DAI link). +- * +- * File block representation for PCM :- +- * +-----------------------------------+-----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-----------------------------------+-----+ +- * | struct snd_soc_tplg_pcm | N | +- * +-----------------------------------+-----+ +- */ +-struct snd_soc_tplg_pcm { +- __le32 size; /* in bytes of this structure */ +- char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- __le32 pcm_id; /* unique ID - used to match with DAI link */ +- __le32 dai_id; /* unique ID - used to match */ +- __le32 playback; /* supports playback mode */ +- __le32 capture; /* supports capture mode */ +- __le32 compress; /* 1 = compressed; 0 = PCM */ +- struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */ +- __le32 num_streams; /* number of streams */ +- struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */ +- __le32 flag_mask; /* bitmask of flags to configure */ +- __le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */ +- struct snd_soc_tplg_private priv; +-} __attribute__((packed)); +- +- +-/* +- * Describes the physical link runtime supported configs or params +- * +- * File block representation for physical link config :- +- * +-----------------------------------+-----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-----------------------------------+-----+ +- * | struct snd_soc_tplg_link_config | N | +- * +-----------------------------------+-----+ +- */ +-struct snd_soc_tplg_link_config { +- __le32 size; /* in bytes of this structure */ +- __le32 id; /* unique ID - used to match */ +- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */ +- char stream_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* stream name - used to match */ +- struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */ +- __le32 num_streams; /* number of streams */ +- struct snd_soc_tplg_hw_config hw_config[SND_SOC_TPLG_HW_CONFIG_MAX]; /* hw configs */ +- __le32 num_hw_configs; /* number of hw configs */ +- __le32 default_hw_config_id; /* default hw config ID for init */ +- __le32 flag_mask; /* bitmask of flags to configure */ +- __le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */ +- struct snd_soc_tplg_private priv; +-} __attribute__((packed)); +- +-/* +- * Describes SW/FW specific features of physical DAI. +- * It can be used to configure backend DAIs for DPCM. +- * +- * File block representation for physical DAI :- +- * +-----------------------------------+-----+ +- * | struct snd_soc_tplg_hdr | 1 | +- * +-----------------------------------+-----+ +- * | struct snd_soc_tplg_dai | N | +- * +-----------------------------------+-----+ +- */ +-struct snd_soc_tplg_dai { +- __le32 size; /* in bytes of this structure */ +- char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */ +- __le32 dai_id; /* unique ID - used to match */ +- __le32 playback; /* supports playback mode */ +- __le32 capture; /* supports capture mode */ +- struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */ +- __le32 flag_mask; /* bitmask of flags to configure */ +- __le32 flags; /* SND_SOC_TPLG_DAI_FLGBIT_* */ +- struct snd_soc_tplg_private priv; +-} __attribute__((packed)); +- +-/* +- * Old version of ABI structs, supported for backward compatibility. +- */ +- +-/* Manifest v4 */ +-struct snd_soc_tplg_manifest_v4 { +- __le32 size; /* in bytes of this structure */ +- __le32 control_elems; /* number of control elements */ +- __le32 widget_elems; /* number of widget elements */ +- __le32 graph_elems; /* number of graph elements */ +- __le32 pcm_elems; /* number of PCM elements */ +- __le32 dai_link_elems; /* number of DAI link elements */ +- struct snd_soc_tplg_private priv; +-} __packed; +- +-/* Stream Capabilities v4 */ +-struct snd_soc_tplg_stream_caps_v4 { +- __le32 size; /* in bytes of this structure */ +- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */ +- __le32 rates; /* supported rates SNDRV_PCM_RATE_* */ +- __le32 rate_min; /* min rate */ +- __le32 rate_max; /* max rate */ +- __le32 channels_min; /* min channels */ +- __le32 channels_max; /* max channels */ +- __le32 periods_min; /* min number of periods */ +- __le32 periods_max; /* max number of periods */ +- __le32 period_size_min; /* min period size bytes */ +- __le32 period_size_max; /* max period size bytes */ +- __le32 buffer_size_min; /* min buffer size bytes */ +- __le32 buffer_size_max; /* max buffer size bytes */ +-} __packed; +- +-/* PCM v4 */ +-struct snd_soc_tplg_pcm_v4 { +- __le32 size; /* in bytes of this structure */ +- char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- __le32 pcm_id; /* unique ID - used to match with DAI link */ +- __le32 dai_id; /* unique ID - used to match */ +- __le32 playback; /* supports playback mode */ +- __le32 capture; /* supports capture mode */ +- __le32 compress; /* 1 = compressed; 0 = PCM */ +- struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */ +- __le32 num_streams; /* number of streams */ +- struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */ +-} __packed; +- +-/* Physical link config v4 */ +-struct snd_soc_tplg_link_config_v4 { +- __le32 size; /* in bytes of this structure */ +- __le32 id; /* unique ID - used to match */ +- struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */ +- __le32 num_streams; /* number of streams */ +-} __packed; +- +-#endif ++#include +diff --git a/include/sound/asound.h b/include/sound/asound.h +index df1153ce..3be4d850 100644 +--- a/include/sound/asound.h ++++ b/include/sound/asound.h +@@ -1,1038 +1 @@ +-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +-/* +- * Advanced Linux Sound Architecture - ALSA - Driver +- * Copyright (c) 1994-2003 by Jaroslav Kysela , +- * Abramo Bagnara +- * +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- * +- */ +- +-#ifndef _UAPI__SOUND_ASOUND_H +-#define _UAPI__SOUND_ASOUND_H +- +-#if defined(__KERNEL__) || defined(__linux__) +-#include +-#else +-#include +-#endif +- +-#ifndef __KERNEL__ +-#include +-#include +-#endif +- +-/* +- * protocol version +- */ +- +-#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor)) +-#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff) +-#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff) +-#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff) +-#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \ +- (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \ +- (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \ +- SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion))) +- +-/**************************************************************************** +- * * +- * Digital audio interface * +- * * +- ****************************************************************************/ +- +-struct snd_aes_iec958 { +- unsigned char status[24]; /* AES/IEC958 channel status bits */ +- unsigned char subcode[147]; /* AES/IEC958 subcode bits */ +- unsigned char pad; /* nothing */ +- unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ +-}; +- +-/**************************************************************************** +- * * +- * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort * +- * * +- ****************************************************************************/ +- +-struct snd_cea_861_aud_if { +- unsigned char db1_ct_cc; /* coding type and channel count */ +- unsigned char db2_sf_ss; /* sample frequency and size */ +- unsigned char db3; /* not used, all zeros */ +- unsigned char db4_ca; /* channel allocation code */ +- unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */ +-}; +- +-/**************************************************************************** +- * * +- * Section for driver hardware dependent interface - /dev/snd/hw? * +- * * +- ****************************************************************************/ +- +-#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1) +- +-enum { +- SNDRV_HWDEP_IFACE_OPL2 = 0, +- SNDRV_HWDEP_IFACE_OPL3, +- SNDRV_HWDEP_IFACE_OPL4, +- SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */ +- SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */ +- SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */ +- SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */ +- SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */ +- SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */ +- SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */ +- SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */ +- SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */ +- SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */ +- SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ +- SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ +- SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ +- SNDRV_HWDEP_IFACE_HDA, /* HD-audio */ +- SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */ +- SNDRV_HWDEP_IFACE_FW_DICE, /* TC DICE FireWire device */ +- SNDRV_HWDEP_IFACE_FW_FIREWORKS, /* Echo Audio Fireworks based device */ +- SNDRV_HWDEP_IFACE_FW_BEBOB, /* BridgeCo BeBoB based device */ +- SNDRV_HWDEP_IFACE_FW_OXFW, /* Oxford OXFW970/971 based device */ +- SNDRV_HWDEP_IFACE_FW_DIGI00X, /* Digidesign Digi 002/003 family */ +- SNDRV_HWDEP_IFACE_FW_TASCAM, /* TASCAM FireWire series */ +- SNDRV_HWDEP_IFACE_LINE6, /* Line6 USB processors */ +- SNDRV_HWDEP_IFACE_FW_MOTU, /* MOTU FireWire series */ +- SNDRV_HWDEP_IFACE_FW_FIREFACE, /* RME Fireface series */ +- +- /* Don't forget to change the following: */ +- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE +-}; +- +-struct snd_hwdep_info { +- unsigned int device; /* WR: device number */ +- int card; /* R: card number */ +- unsigned char id[64]; /* ID (user selectable) */ +- unsigned char name[80]; /* hwdep name */ +- int iface; /* hwdep interface */ +- unsigned char reserved[64]; /* reserved for future */ +-}; +- +-/* generic DSP loader */ +-struct snd_hwdep_dsp_status { +- unsigned int version; /* R: driver-specific version */ +- unsigned char id[32]; /* R: driver-specific ID string */ +- unsigned int num_dsps; /* R: number of DSP images to transfer */ +- unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */ +- unsigned int chip_ready; /* R: 1 = initialization finished */ +- unsigned char reserved[16]; /* reserved for future use */ +-}; +- +-struct snd_hwdep_dsp_image { +- unsigned int index; /* W: DSP index */ +- unsigned char name[64]; /* W: ID (e.g. file name) */ +- unsigned char __user *image; /* W: binary image */ +- size_t length; /* W: size of image in bytes */ +- unsigned long driver_data; /* W: driver-specific data */ +-}; +- +-#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int) +-#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info) +-#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status) +-#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image) +- +-/***************************************************************************** +- * * +- * Digital Audio (PCM) interface - /dev/snd/pcm?? * +- * * +- *****************************************************************************/ +- +-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14) +- +-typedef unsigned long snd_pcm_uframes_t; +-typedef signed long snd_pcm_sframes_t; +- +-enum { +- SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */ +- SNDRV_PCM_CLASS_MULTI, /* multichannel device */ +- SNDRV_PCM_CLASS_MODEM, /* software modem class */ +- SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */ +- /* Don't forget to change the following: */ +- SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER, +-}; +- +-enum { +- SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */ +- SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */ +- /* Don't forget to change the following: */ +- SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX, +-}; +- +-enum { +- SNDRV_PCM_STREAM_PLAYBACK = 0, +- SNDRV_PCM_STREAM_CAPTURE, +- SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE, +-}; +- +-typedef int __bitwise snd_pcm_access_t; +-#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */ +-#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */ +-#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */ +-#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */ +-#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */ +-#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED +- +-typedef int __bitwise snd_pcm_format_t; +-#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0) +-#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1) +-#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2) +-#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3) +-#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4) +-#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5) +-#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */ +-#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */ +-#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */ +-#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */ +-#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10) +-#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11) +-#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12) +-#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13) +-#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ +-#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ +-#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ +-#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ +-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */ +-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */ +-#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20) +-#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21) +-#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22) +-#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23) +-#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24) +-#define SNDRV_PCM_FORMAT_S20_LE ((__force snd_pcm_format_t) 25) /* in four bytes, LSB justified */ +-#define SNDRV_PCM_FORMAT_S20_BE ((__force snd_pcm_format_t) 26) /* in four bytes, LSB justified */ +-#define SNDRV_PCM_FORMAT_U20_LE ((__force snd_pcm_format_t) 27) /* in four bytes, LSB justified */ +-#define SNDRV_PCM_FORMAT_U20_BE ((__force snd_pcm_format_t) 28) /* in four bytes, LSB justified */ +-/* gap in the numbering for a future standard linear format */ +-#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31) +-#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */ +-#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */ +-#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */ +-#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */ +-#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ +-#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */ +-#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */ +-#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */ +-#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */ +-#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */ +-#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE +-#define SNDRV_PCM_FORMAT_FIRST SNDRV_PCM_FORMAT_S8 +- +-#ifdef SNDRV_LITTLE_ENDIAN +-#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE +-#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE +-#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE +-#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE +-#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE +-#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE +-#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE +-#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE +-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE +-#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_LE +-#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_LE +-#endif +-#ifdef SNDRV_BIG_ENDIAN +-#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE +-#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE +-#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE +-#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE +-#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE +-#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE +-#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE +-#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE +-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE +-#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_BE +-#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_BE +-#endif +- +-typedef int __bitwise snd_pcm_subformat_t; +-#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0) +-#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD +- +-#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */ +-#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */ +-#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */ +-#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */ +-#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */ +-#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */ +-#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */ +-#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */ +-#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */ +-#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */ +-#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */ +-#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */ +-#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */ +-#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ +-#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ +-#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */ +-#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */ +-#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */ +-#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */ +-#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ +-#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ +- +-#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ +-#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ +- +- +- +-typedef int __bitwise snd_pcm_state_t; +-#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */ +-#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */ +-#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */ +-#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */ +-#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */ +-#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */ +-#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */ +-#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */ +-#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */ +-#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED +- +-enum { +- SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000, +- SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000, +- SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000, +-}; +- +-union snd_pcm_sync_id { +- unsigned char id[16]; +- unsigned short id16[8]; +- unsigned int id32[4]; +-}; +- +-struct snd_pcm_info { +- unsigned int device; /* RO/WR (control): device number */ +- unsigned int subdevice; /* RO/WR (control): subdevice number */ +- int stream; /* RO/WR (control): stream direction */ +- int card; /* R: card number */ +- unsigned char id[64]; /* ID (user selectable) */ +- unsigned char name[80]; /* name of this device */ +- unsigned char subname[32]; /* subdevice name */ +- int dev_class; /* SNDRV_PCM_CLASS_* */ +- int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ +- unsigned int subdevices_count; +- unsigned int subdevices_avail; +- union snd_pcm_sync_id sync; /* hardware synchronization ID */ +- unsigned char reserved[64]; /* reserved for future... */ +-}; +- +-typedef int snd_pcm_hw_param_t; +-#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */ +-#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */ +-#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */ +-#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS +-#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT +- +-#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */ +-#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */ +-#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */ +-#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */ +-#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between +- * interrupts in us +- */ +-#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between +- * interrupts +- */ +-#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between +- * interrupts +- */ +-#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per +- * buffer +- */ +-#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer +- * in us +- */ +-#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */ +-#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */ +-#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */ +-#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS +-#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME +- +-#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */ +-#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */ +-#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */ +- +-struct snd_interval { +- unsigned int min, max; +- unsigned int openmin:1, +- openmax:1, +- integer:1, +- empty:1; +-}; +- +-#define SNDRV_MASK_MAX 256 +- +-struct snd_mask { +- __u32 bits[(SNDRV_MASK_MAX+31)/32]; +-}; +- +-struct snd_pcm_hw_params { +- unsigned int flags; +- struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - +- SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; +- struct snd_mask mres[5]; /* reserved masks */ +- struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - +- SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; +- struct snd_interval ires[9]; /* reserved intervals */ +- unsigned int rmask; /* W: requested masks */ +- unsigned int cmask; /* R: changed masks */ +- unsigned int info; /* R: Info flags for returned setup */ +- unsigned int msbits; /* R: used most significant bits */ +- unsigned int rate_num; /* R: rate numerator */ +- unsigned int rate_den; /* R: rate denominator */ +- snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ +- unsigned char reserved[64]; /* reserved for future */ +-}; +- +-enum { +- SNDRV_PCM_TSTAMP_NONE = 0, +- SNDRV_PCM_TSTAMP_ENABLE, +- SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE, +-}; +- +-struct snd_pcm_sw_params { +- int tstamp_mode; /* timestamp mode */ +- unsigned int period_step; +- unsigned int sleep_min; /* min ticks to sleep */ +- snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */ +- snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */ +- snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */ +- snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */ +- snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ +- snd_pcm_uframes_t silence_size; /* silence block size */ +- snd_pcm_uframes_t boundary; /* pointers wrap point */ +- unsigned int proto; /* protocol version */ +- unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */ +- unsigned char reserved[56]; /* reserved for future */ +-}; +- +-struct snd_pcm_channel_info { +- unsigned int channel; +- __kernel_off_t offset; /* mmap offset */ +- unsigned int first; /* offset to first sample in bits */ +- unsigned int step; /* samples distance in bits */ +-}; +- +-enum { +- /* +- * first definition for backwards compatibility only, +- * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else +- */ +- SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0, +- +- /* timestamp definitions */ +- SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */ +- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */ +- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */ +- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */ +- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */ +- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED +-}; +- +-struct snd_pcm_status { +- snd_pcm_state_t state; /* stream state */ +- struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */ +- struct timespec tstamp; /* reference timestamp */ +- snd_pcm_uframes_t appl_ptr; /* appl ptr */ +- snd_pcm_uframes_t hw_ptr; /* hw ptr */ +- snd_pcm_sframes_t delay; /* current delay in frames */ +- snd_pcm_uframes_t avail; /* number of frames available */ +- snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */ +- snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */ +- snd_pcm_state_t suspended_state; /* suspended stream state */ +- __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */ +- struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */ +- struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */ +- __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */ +- unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */ +-}; +- +-struct snd_pcm_mmap_status { +- snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */ +- int pad1; /* Needed for 64 bit alignment */ +- snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */ +- struct timespec tstamp; /* Timestamp */ +- snd_pcm_state_t suspended_state; /* RO: suspended stream state */ +- struct timespec audio_tstamp; /* from sample counter or wall clock */ +-}; +- +-struct snd_pcm_mmap_control { +- snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */ +- snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */ +-}; +- +-#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */ +-#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */ +-#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */ +- +-struct snd_pcm_sync_ptr { +- unsigned int flags; +- union { +- struct snd_pcm_mmap_status status; +- unsigned char reserved[64]; +- } s; +- union { +- struct snd_pcm_mmap_control control; +- unsigned char reserved[64]; +- } c; +-}; +- +-struct snd_xferi { +- snd_pcm_sframes_t result; +- void __user *buf; +- snd_pcm_uframes_t frames; +-}; +- +-struct snd_xfern { +- snd_pcm_sframes_t result; +- void __user * __user *bufs; +- snd_pcm_uframes_t frames; +-}; +- +-enum { +- SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */ +- SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */ +- SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */ +- SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, +-}; +- +-/* channel positions */ +-enum { +- SNDRV_CHMAP_UNKNOWN = 0, +- SNDRV_CHMAP_NA, /* N/A, silent */ +- SNDRV_CHMAP_MONO, /* mono stream */ +- /* this follows the alsa-lib mixer channel value + 3 */ +- SNDRV_CHMAP_FL, /* front left */ +- SNDRV_CHMAP_FR, /* front right */ +- SNDRV_CHMAP_RL, /* rear left */ +- SNDRV_CHMAP_RR, /* rear right */ +- SNDRV_CHMAP_FC, /* front center */ +- SNDRV_CHMAP_LFE, /* LFE */ +- SNDRV_CHMAP_SL, /* side left */ +- SNDRV_CHMAP_SR, /* side right */ +- SNDRV_CHMAP_RC, /* rear center */ +- /* new definitions */ +- SNDRV_CHMAP_FLC, /* front left center */ +- SNDRV_CHMAP_FRC, /* front right center */ +- SNDRV_CHMAP_RLC, /* rear left center */ +- SNDRV_CHMAP_RRC, /* rear right center */ +- SNDRV_CHMAP_FLW, /* front left wide */ +- SNDRV_CHMAP_FRW, /* front right wide */ +- SNDRV_CHMAP_FLH, /* front left high */ +- SNDRV_CHMAP_FCH, /* front center high */ +- SNDRV_CHMAP_FRH, /* front right high */ +- SNDRV_CHMAP_TC, /* top center */ +- SNDRV_CHMAP_TFL, /* top front left */ +- SNDRV_CHMAP_TFR, /* top front right */ +- SNDRV_CHMAP_TFC, /* top front center */ +- SNDRV_CHMAP_TRL, /* top rear left */ +- SNDRV_CHMAP_TRR, /* top rear right */ +- SNDRV_CHMAP_TRC, /* top rear center */ +- /* new definitions for UAC2 */ +- SNDRV_CHMAP_TFLC, /* top front left center */ +- SNDRV_CHMAP_TFRC, /* top front right center */ +- SNDRV_CHMAP_TSL, /* top side left */ +- SNDRV_CHMAP_TSR, /* top side right */ +- SNDRV_CHMAP_LLFE, /* left LFE */ +- SNDRV_CHMAP_RLFE, /* right LFE */ +- SNDRV_CHMAP_BC, /* bottom center */ +- SNDRV_CHMAP_BLC, /* bottom left center */ +- SNDRV_CHMAP_BRC, /* bottom right center */ +- SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC, +-}; +- +-#define SNDRV_CHMAP_POSITION_MASK 0xffff +-#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) +-#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16) +- +-#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) +-#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) +-#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) +-#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) +-#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int) +-#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) +-#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) +-#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) +-#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params) +-#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status) +-#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t) +-#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) +-#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr) +-#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status) +-#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info) +-#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) +-#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) +-#define SNDRV_PCM_IOCTL_START _IO('A', 0x42) +-#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43) +-#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44) +-#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int) +-#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t) +-#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47) +-#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48) +-#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t) +-#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi) +-#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi) +-#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern) +-#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern) +-#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int) +-#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61) +- +-/***************************************************************************** +- * * +- * MIDI v1.0 interface * +- * * +- *****************************************************************************/ +- +-/* +- * Raw MIDI section - /dev/snd/midi?? +- */ +- +-#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0) +- +-enum { +- SNDRV_RAWMIDI_STREAM_OUTPUT = 0, +- SNDRV_RAWMIDI_STREAM_INPUT, +- SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT, +-}; +- +-#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001 +-#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002 +-#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004 +- +-struct snd_rawmidi_info { +- unsigned int device; /* RO/WR (control): device number */ +- unsigned int subdevice; /* RO/WR (control): subdevice number */ +- int stream; /* WR: stream */ +- int card; /* R: card number */ +- unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */ +- unsigned char id[64]; /* ID (user selectable) */ +- unsigned char name[80]; /* name of device */ +- unsigned char subname[32]; /* name of active or selected subdevice */ +- unsigned int subdevices_count; +- unsigned int subdevices_avail; +- unsigned char reserved[64]; /* reserved for future use */ +-}; +- +-struct snd_rawmidi_params { +- int stream; +- size_t buffer_size; /* queue size in bytes */ +- size_t avail_min; /* minimum avail bytes for wakeup */ +- unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ +- unsigned char reserved[16]; /* reserved for future use */ +-}; +- +-struct snd_rawmidi_status { +- int stream; +- struct timespec tstamp; /* Timestamp */ +- size_t avail; /* available bytes */ +- size_t xruns; /* count of overruns since last status (in bytes) */ +- unsigned char reserved[16]; /* reserved for future use */ +-}; +- +-#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) +-#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info) +-#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params) +-#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status) +-#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) +-#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int) +- +-/* +- * Timer section - /dev/snd/timer +- */ +- +-#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6) +- +-enum { +- SNDRV_TIMER_CLASS_NONE = -1, +- SNDRV_TIMER_CLASS_SLAVE = 0, +- SNDRV_TIMER_CLASS_GLOBAL, +- SNDRV_TIMER_CLASS_CARD, +- SNDRV_TIMER_CLASS_PCM, +- SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM, +-}; +- +-/* slave timer classes */ +-enum { +- SNDRV_TIMER_SCLASS_NONE = 0, +- SNDRV_TIMER_SCLASS_APPLICATION, +- SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */ +- SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */ +- SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER, +-}; +- +-/* global timers (device member) */ +-#define SNDRV_TIMER_GLOBAL_SYSTEM 0 +-#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */ +-#define SNDRV_TIMER_GLOBAL_HPET 2 +-#define SNDRV_TIMER_GLOBAL_HRTIMER 3 +- +-/* info flags */ +-#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */ +- +-struct snd_timer_id { +- int dev_class; +- int dev_sclass; +- int card; +- int device; +- int subdevice; +-}; +- +-struct snd_timer_ginfo { +- struct snd_timer_id tid; /* requested timer ID */ +- unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ +- int card; /* card number */ +- unsigned char id[64]; /* timer identification */ +- unsigned char name[80]; /* timer name */ +- unsigned long reserved0; /* reserved for future use */ +- unsigned long resolution; /* average period resolution in ns */ +- unsigned long resolution_min; /* minimal period resolution in ns */ +- unsigned long resolution_max; /* maximal period resolution in ns */ +- unsigned int clients; /* active timer clients */ +- unsigned char reserved[32]; +-}; +- +-struct snd_timer_gparams { +- struct snd_timer_id tid; /* requested timer ID */ +- unsigned long period_num; /* requested precise period duration (in seconds) - numerator */ +- unsigned long period_den; /* requested precise period duration (in seconds) - denominator */ +- unsigned char reserved[32]; +-}; +- +-struct snd_timer_gstatus { +- struct snd_timer_id tid; /* requested timer ID */ +- unsigned long resolution; /* current period resolution in ns */ +- unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */ +- unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */ +- unsigned char reserved[32]; +-}; +- +-struct snd_timer_select { +- struct snd_timer_id id; /* bind to timer ID */ +- unsigned char reserved[32]; /* reserved */ +-}; +- +-struct snd_timer_info { +- unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ +- int card; /* card number */ +- unsigned char id[64]; /* timer identificator */ +- unsigned char name[80]; /* timer name */ +- unsigned long reserved0; /* reserved for future use */ +- unsigned long resolution; /* average period resolution in ns */ +- unsigned char reserved[64]; /* reserved */ +-}; +- +-#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */ +-#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */ +-#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */ +- +-struct snd_timer_params { +- unsigned int flags; /* flags - SNDRV_TIMER_PSFLG_* */ +- unsigned int ticks; /* requested resolution in ticks */ +- unsigned int queue_size; /* total size of queue (32-1024) */ +- unsigned int reserved0; /* reserved, was: failure locations */ +- unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */ +- unsigned char reserved[60]; /* reserved */ +-}; +- +-struct snd_timer_status { +- struct timespec tstamp; /* Timestamp - last update */ +- unsigned int resolution; /* current period resolution in ns */ +- unsigned int lost; /* counter of master tick lost */ +- unsigned int overrun; /* count of read queue overruns */ +- unsigned int queue; /* used queue size */ +- unsigned char reserved[64]; /* reserved */ +-}; +- +-#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) +-#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id) +-#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int) +-#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo) +-#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams) +-#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus) +-#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select) +-#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info) +-#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params) +-#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status) +-/* The following four ioctls are changed since 1.0.9 due to confliction */ +-#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0) +-#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1) +-#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) +-#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3) +- +-struct snd_timer_read { +- unsigned int resolution; +- unsigned int ticks; +-}; +- +-enum { +- SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */ +- SNDRV_TIMER_EVENT_TICK, /* val = ticks */ +- SNDRV_TIMER_EVENT_START, /* val = resolution in ns */ +- SNDRV_TIMER_EVENT_STOP, /* val = 0 */ +- SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */ +- SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */ +- SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */ +- SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */ +- SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */ +- /* master timer events for slave timer instances */ +- SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10, +- SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10, +- SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10, +- SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10, +- SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10, +- SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10, +-}; +- +-struct snd_timer_tread { +- int event; +- struct timespec tstamp; +- unsigned int val; +-}; +- +-/**************************************************************************** +- * * +- * Section for driver control interface - /dev/snd/control? * +- * * +- ****************************************************************************/ +- +-#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7) +- +-struct snd_ctl_card_info { +- int card; /* card number */ +- int pad; /* reserved for future (was type) */ +- unsigned char id[16]; /* ID of card (user selectable) */ +- unsigned char driver[16]; /* Driver name */ +- unsigned char name[32]; /* Short name of soundcard */ +- unsigned char longname[80]; /* name + info text about soundcard */ +- unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */ +- unsigned char mixername[80]; /* visual mixer identification */ +- unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */ +-}; +- +-typedef int __bitwise snd_ctl_elem_type_t; +-#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */ +-#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */ +-#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */ +-#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */ +-#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */ +-#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */ +-#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */ +-#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64 +- +-typedef int __bitwise snd_ctl_elem_iface_t; +-#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */ +-#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */ +-#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */ +-#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */ +-#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */ +-#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */ +-#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */ +-#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER +- +-#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0) +-#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1) +-#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE) +-#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */ +-#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */ +-#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */ +-#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */ +-#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) +-#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */ +-#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */ +-#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */ +-#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */ +-#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */ +-#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */ +-/* bits 30 and 31 are obsoleted (for indirect access) */ +- +-/* for further details see the ACPI and PCI power management specification */ +-#define SNDRV_CTL_POWER_D0 0x0000 /* full On */ +-#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */ +-#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */ +-#define SNDRV_CTL_POWER_D3 0x0300 /* Off */ +-#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */ +-#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */ +- +-#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 +- +-struct snd_ctl_elem_id { +- unsigned int numid; /* numeric identifier, zero = invalid */ +- snd_ctl_elem_iface_t iface; /* interface identifier */ +- unsigned int device; /* device/client number */ +- unsigned int subdevice; /* subdevice (substream) number */ +- unsigned char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* ASCII name of item */ +- unsigned int index; /* index of item */ +-}; +- +-struct snd_ctl_elem_list { +- unsigned int offset; /* W: first element ID to get */ +- unsigned int space; /* W: count of element IDs to get */ +- unsigned int used; /* R: count of element IDs set */ +- unsigned int count; /* R: count of all elements */ +- struct snd_ctl_elem_id __user *pids; /* R: IDs */ +- unsigned char reserved[50]; +-}; +- +-struct snd_ctl_elem_info { +- struct snd_ctl_elem_id id; /* W: element ID */ +- snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ +- unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ +- unsigned int count; /* count of values */ +- __kernel_pid_t owner; /* owner's PID of this control */ +- union { +- struct { +- long min; /* R: minimum value */ +- long max; /* R: maximum value */ +- long step; /* R: step (0 variable) */ +- } integer; +- struct { +- long long min; /* R: minimum value */ +- long long max; /* R: maximum value */ +- long long step; /* R: step (0 variable) */ +- } integer64; +- struct { +- unsigned int items; /* R: number of items */ +- unsigned int item; /* W: item number */ +- char name[64]; /* R: value name */ +- __u64 names_ptr; /* W: names list (ELEM_ADD only) */ +- unsigned int names_length; +- } enumerated; +- unsigned char reserved[128]; +- } value; +- union { +- unsigned short d[4]; /* dimensions */ +- unsigned short *d_ptr; /* indirect - obsoleted */ +- } dimen; +- unsigned char reserved[64-4*sizeof(unsigned short)]; +-}; +- +-struct snd_ctl_elem_value { +- struct snd_ctl_elem_id id; /* W: element ID */ +- unsigned int indirect: 1; /* W: indirect access - obsoleted */ +- union { +- union { +- long value[128]; +- long *value_ptr; /* obsoleted */ +- } integer; +- union { +- long long value[64]; +- long long *value_ptr; /* obsoleted */ +- } integer64; +- union { +- unsigned int item[128]; +- unsigned int *item_ptr; /* obsoleted */ +- } enumerated; +- union { +- unsigned char data[512]; +- unsigned char *data_ptr; /* obsoleted */ +- } bytes; +- struct snd_aes_iec958 iec958; +- } value; /* RO */ +- struct timespec tstamp; +- unsigned char reserved[128-sizeof(struct timespec)]; +-}; +- +-struct snd_ctl_tlv { +- unsigned int numid; /* control element numeric identification */ +- unsigned int length; /* in bytes aligned to 4 */ +- unsigned int tlv[0]; /* first TLV */ +-}; +- +-#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) +-#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info) +-#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list) +-#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info) +-#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value) +-#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value) +-#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id) +-#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id) +-#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int) +-#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info) +-#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info) +-#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id) +-#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv) +-#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv) +-#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv) +-#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int) +-#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info) +-#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int) +-#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info) +-#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int) +-#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int) +-#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info) +-#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int) +-#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int) +-#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int) +- +-/* +- * Read interface. +- */ +- +-enum sndrv_ctl_event_type { +- SNDRV_CTL_EVENT_ELEM = 0, +- SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM, +-}; +- +-#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */ +-#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */ +-#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */ +-#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */ +-#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */ +- +-struct snd_ctl_event { +- int type; /* event type - SNDRV_CTL_EVENT_* */ +- union { +- struct { +- unsigned int mask; +- struct snd_ctl_elem_id id; +- } elem; +- unsigned char data8[60]; +- } data; +-}; +- +-/* +- * Control names +- */ +- +-#define SNDRV_CTL_NAME_NONE "" +-#define SNDRV_CTL_NAME_PLAYBACK "Playback " +-#define SNDRV_CTL_NAME_CAPTURE "Capture " +- +-#define SNDRV_CTL_NAME_IEC958_NONE "" +-#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch" +-#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume" +-#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default" +-#define SNDRV_CTL_NAME_IEC958_MASK "Mask" +-#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask" +-#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask" +-#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream" +-#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what +- +-#endif /* _UAPI__SOUND_ASOUND_H */ ++#include +diff --git a/include/sound/asound_fm.h b/include/sound/asound_fm.h +index 8471f404..3e5da4d0 100644 +--- a/include/sound/asound_fm.h ++++ b/include/sound/asound_fm.h +@@ -1,135 +1 @@ +-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +-#ifndef __SOUND_ASOUND_FM_H +-#define __SOUND_ASOUND_FM_H +- +-/* +- * Advanced Linux Sound Architecture - ALSA +- * +- * Interface file between ALSA driver & user space +- * Copyright (c) 1994-98 by Jaroslav Kysela , +- * 4Front Technologies +- * +- * Direct FM control +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- * +- */ +- +-#define SNDRV_DM_FM_MODE_OPL2 0x00 +-#define SNDRV_DM_FM_MODE_OPL3 0x01 +- +-struct snd_dm_fm_info { +- unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */ +- unsigned char rhythm; /* percussion mode flag */ +-}; +- +-/* +- * Data structure composing an FM "note" or sound event. +- */ +- +-struct snd_dm_fm_voice { +- unsigned char op; /* operator cell (0 or 1) */ +- unsigned char voice; /* FM voice (0 to 17) */ +- +- unsigned char am; /* amplitude modulation */ +- unsigned char vibrato; /* vibrato effect */ +- unsigned char do_sustain; /* sustain phase */ +- unsigned char kbd_scale; /* keyboard scaling */ +- unsigned char harmonic; /* 4 bits: harmonic and multiplier */ +- unsigned char scale_level; /* 2 bits: decrease output freq rises */ +- unsigned char volume; /* 6 bits: volume */ +- +- unsigned char attack; /* 4 bits: attack rate */ +- unsigned char decay; /* 4 bits: decay rate */ +- unsigned char sustain; /* 4 bits: sustain level */ +- unsigned char release; /* 4 bits: release rate */ +- +- unsigned char feedback; /* 3 bits: feedback for op0 */ +- unsigned char connection; /* 0 for serial, 1 for parallel */ +- unsigned char left; /* stereo left */ +- unsigned char right; /* stereo right */ +- unsigned char waveform; /* 3 bits: waveform shape */ +-}; +- +-/* +- * This describes an FM note by its voice, octave, frequency number (10bit) +- * and key on/off. +- */ +- +-struct snd_dm_fm_note { +- unsigned char voice; /* 0-17 voice channel */ +- unsigned char octave; /* 3 bits: what octave to play */ +- unsigned int fnum; /* 10 bits: frequency number */ +- unsigned char key_on; /* set for active, clear for silent */ +-}; +- +-/* +- * FM parameters that apply globally to all voices, and thus are not "notes" +- */ +- +-struct snd_dm_fm_params { +- unsigned char am_depth; /* amplitude modulation depth (1=hi) */ +- unsigned char vib_depth; /* vibrato depth (1=hi) */ +- unsigned char kbd_split; /* keyboard split */ +- unsigned char rhythm; /* percussion mode select */ +- +- /* This block is the percussion instrument data */ +- unsigned char bass; +- unsigned char snare; +- unsigned char tomtom; +- unsigned char cymbal; +- unsigned char hihat; +-}; +- +-/* +- * FM mode ioctl settings +- */ +- +-#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, struct snd_dm_fm_info) +-#define SNDRV_DM_FM_IOCTL_RESET _IO ('H', 0x21) +-#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, struct snd_dm_fm_note) +-#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, struct snd_dm_fm_voice) +-#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, struct snd_dm_fm_params) +-#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int) +-/* for OPL3 only */ +-#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int) +-/* SBI patch management */ +-#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES _IO ('H', 0x40) +- +-#define SNDRV_DM_FM_OSS_IOCTL_RESET 0x20 +-#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21 +-#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22 +-#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23 +-#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24 +-#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25 +- +-/* +- * Patch Record - fixed size for write +- */ +- +-#define FM_KEY_SBI "SBI\032" +-#define FM_KEY_2OP "2OP\032" +-#define FM_KEY_4OP "4OP\032" +- +-struct sbi_patch { +- unsigned char prog; +- unsigned char bank; +- char key[4]; +- char name[25]; +- char extension[7]; +- unsigned char data[32]; +-}; +- +-#endif /* __SOUND_ASOUND_FM_H */ ++#include +diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h +index 042c5a6f..f06ecee5 100644 +--- a/include/sound/emu10k1.h ++++ b/include/sound/emu10k1.h +@@ -1,381 +1,2 @@ +-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +-/* +- * Copyright (c) by Jaroslav Kysela , +- * Creative Labs, Inc. +- * Definitions for EMU10K1 (SB Live!) chips +- * +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- * +- */ +-#ifndef _UAPI__SOUND_EMU10K1_H +-#define _UAPI__SOUND_EMU10K1_H +- +-#include +-#include +- +-/* +- * ---- FX8010 ---- +- */ +- +-#define EMU10K1_CARD_CREATIVE 0x00000000 +-#define EMU10K1_CARD_EMUAPS 0x00000001 +- +-#define EMU10K1_FX8010_PCM_COUNT 8 +- +-/* +- * Following definition is copied from linux/types.h to support compiling +- * this header file in userspace since they are not generally available for +- * uapi headers. +- */ +-#define __EMU10K1_DECLARE_BITMAP(name,bits) \ +- unsigned long name[(bits) / (sizeof(unsigned long) * 8)] +- +-/* instruction set */ +-#define iMAC0 0x00 /* R = A + (X * Y >> 31) ; saturation */ +-#define iMAC1 0x01 /* R = A + (-X * Y >> 31) ; saturation */ +-#define iMAC2 0x02 /* R = A + (X * Y >> 31) ; wraparound */ +-#define iMAC3 0x03 /* R = A + (-X * Y >> 31) ; wraparound */ +-#define iMACINT0 0x04 /* R = A + X * Y ; saturation */ +-#define iMACINT1 0x05 /* R = A + X * Y ; wraparound (31-bit) */ +-#define iACC3 0x06 /* R = A + X + Y ; saturation */ +-#define iMACMV 0x07 /* R = A, acc += X * Y >> 31 */ +-#define iANDXOR 0x08 /* R = (A & X) ^ Y */ +-#define iTSTNEG 0x09 /* R = (A >= Y) ? X : ~X */ +-#define iLIMITGE 0x0a /* R = (A >= Y) ? X : Y */ +-#define iLIMITLT 0x0b /* R = (A < Y) ? X : Y */ +-#define iLOG 0x0c /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */ +-#define iEXP 0x0d /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */ +-#define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */ +-#define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */ +- +-/* GPRs */ +-#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */ +-#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */ +-#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */ +-#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */ +- /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */ +- +-#define C_00000000 0x40 +-#define C_00000001 0x41 +-#define C_00000002 0x42 +-#define C_00000003 0x43 +-#define C_00000004 0x44 +-#define C_00000008 0x45 +-#define C_00000010 0x46 +-#define C_00000020 0x47 +-#define C_00000100 0x48 +-#define C_00010000 0x49 +-#define C_00080000 0x4a +-#define C_10000000 0x4b +-#define C_20000000 0x4c +-#define C_40000000 0x4d +-#define C_80000000 0x4e +-#define C_7fffffff 0x4f +-#define C_ffffffff 0x50 +-#define C_fffffffe 0x51 +-#define C_c0000000 0x52 +-#define C_4f1bbcdc 0x53 +-#define C_5a7ef9db 0x54 +-#define C_00100000 0x55 /* ?? */ +-#define GPR_ACCU 0x56 /* ACCUM, accumulator */ +-#define GPR_COND 0x57 /* CCR, condition register */ +-#define GPR_NOISE0 0x58 /* noise source */ +-#define GPR_NOISE1 0x59 /* noise source */ +-#define GPR_IRQ 0x5a /* IRQ register */ +-#define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */ +-#define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */ +-#define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ +-#define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ +-#define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ +-#define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ +- +-#define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ +-#define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ +-#define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ +-#define A_ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ +-#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ +-#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ +- +-#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */ +-#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */ +-#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */ +-#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */ +-#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */ +-#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */ +-#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */ +-#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */ +-#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */ +-#define A_GPR(x) (A_FXGPREGBASE + (x)) +- +-/* cc_reg constants */ +-#define CC_REG_NORMALIZED C_00000001 +-#define CC_REG_BORROW C_00000002 +-#define CC_REG_MINUS C_00000004 +-#define CC_REG_ZERO C_00000008 +-#define CC_REG_SATURATE C_00000010 +-#define CC_REG_NONZERO C_00000100 +- +-/* FX buses */ +-#define FXBUS_PCM_LEFT 0x00 +-#define FXBUS_PCM_RIGHT 0x01 +-#define FXBUS_PCM_LEFT_REAR 0x02 +-#define FXBUS_PCM_RIGHT_REAR 0x03 +-#define FXBUS_MIDI_LEFT 0x04 +-#define FXBUS_MIDI_RIGHT 0x05 +-#define FXBUS_PCM_CENTER 0x06 +-#define FXBUS_PCM_LFE 0x07 +-#define FXBUS_PCM_LEFT_FRONT 0x08 +-#define FXBUS_PCM_RIGHT_FRONT 0x09 +-#define FXBUS_MIDI_REVERB 0x0c +-#define FXBUS_MIDI_CHORUS 0x0d +-#define FXBUS_PCM_LEFT_SIDE 0x0e +-#define FXBUS_PCM_RIGHT_SIDE 0x0f +-#define FXBUS_PT_LEFT 0x14 +-#define FXBUS_PT_RIGHT 0x15 +- +-/* Inputs */ +-#define EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */ +-#define EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */ +-#define EXTIN_SPDIF_CD_L 0x02 /* internal S/PDIF CD - onboard - left */ +-#define EXTIN_SPDIF_CD_R 0x03 /* internal S/PDIF CD - onboard - right */ +-#define EXTIN_ZOOM_L 0x04 /* Zoom Video I2S - left */ +-#define EXTIN_ZOOM_R 0x05 /* Zoom Video I2S - right */ +-#define EXTIN_TOSLINK_L 0x06 /* LiveDrive - TOSLink Optical - left */ +-#define EXTIN_TOSLINK_R 0x07 /* LiveDrive - TOSLink Optical - right */ +-#define EXTIN_LINE1_L 0x08 /* LiveDrive - Line/Mic 1 - left */ +-#define EXTIN_LINE1_R 0x09 /* LiveDrive - Line/Mic 1 - right */ +-#define EXTIN_COAX_SPDIF_L 0x0a /* LiveDrive - Coaxial S/PDIF - left */ +-#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */ +-#define EXTIN_LINE2_L 0x0c /* LiveDrive - Line/Mic 2 - left */ +-#define EXTIN_LINE2_R 0x0d /* LiveDrive - Line/Mic 2 - right */ +- +-/* Outputs */ +-#define EXTOUT_AC97_L 0x00 /* AC'97 playback channel - left */ +-#define EXTOUT_AC97_R 0x01 /* AC'97 playback channel - right */ +-#define EXTOUT_TOSLINK_L 0x02 /* LiveDrive - TOSLink Optical - left */ +-#define EXTOUT_TOSLINK_R 0x03 /* LiveDrive - TOSLink Optical - right */ +-#define EXTOUT_AC97_CENTER 0x04 /* SB Live 5.1 - center */ +-#define EXTOUT_AC97_LFE 0x05 /* SB Live 5.1 - LFE */ +-#define EXTOUT_HEADPHONE_L 0x06 /* LiveDrive - Headphone - left */ +-#define EXTOUT_HEADPHONE_R 0x07 /* LiveDrive - Headphone - right */ +-#define EXTOUT_REAR_L 0x08 /* Rear channel - left */ +-#define EXTOUT_REAR_R 0x09 /* Rear channel - right */ +-#define EXTOUT_ADC_CAP_L 0x0a /* ADC Capture buffer - left */ +-#define EXTOUT_ADC_CAP_R 0x0b /* ADC Capture buffer - right */ +-#define EXTOUT_MIC_CAP 0x0c /* MIC Capture buffer */ +-#define EXTOUT_AC97_REAR_L 0x0d /* SB Live 5.1 (c) 2003 - Rear Left */ +-#define EXTOUT_AC97_REAR_R 0x0e /* SB Live 5.1 (c) 2003 - Rear Right */ +-#define EXTOUT_ACENTER 0x11 /* Analog Center */ +-#define EXTOUT_ALFE 0x12 /* Analog LFE */ +- +-/* Audigy Inputs */ +-#define A_EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */ +-#define A_EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */ +-#define A_EXTIN_SPDIF_CD_L 0x02 /* digital CD left */ +-#define A_EXTIN_SPDIF_CD_R 0x03 /* digital CD left */ +-#define A_EXTIN_OPT_SPDIF_L 0x04 /* audigy drive Optical SPDIF - left */ +-#define A_EXTIN_OPT_SPDIF_R 0x05 /* right */ +-#define A_EXTIN_LINE2_L 0x08 /* audigy drive line2/mic2 - left */ +-#define A_EXTIN_LINE2_R 0x09 /* right */ +-#define A_EXTIN_ADC_L 0x0a /* Philips ADC - left */ +-#define A_EXTIN_ADC_R 0x0b /* right */ +-#define A_EXTIN_AUX2_L 0x0c /* audigy drive aux2 - left */ +-#define A_EXTIN_AUX2_R 0x0d /* - right */ +- +-/* Audigiy Outputs */ +-#define A_EXTOUT_FRONT_L 0x00 /* digital front left */ +-#define A_EXTOUT_FRONT_R 0x01 /* right */ +-#define A_EXTOUT_CENTER 0x02 /* digital front center */ +-#define A_EXTOUT_LFE 0x03 /* digital front lfe */ +-#define A_EXTOUT_HEADPHONE_L 0x04 /* headphone audigy drive left */ +-#define A_EXTOUT_HEADPHONE_R 0x05 /* right */ +-#define A_EXTOUT_REAR_L 0x06 /* digital rear left */ +-#define A_EXTOUT_REAR_R 0x07 /* right */ +-#define A_EXTOUT_AFRONT_L 0x08 /* analog front left */ +-#define A_EXTOUT_AFRONT_R 0x09 /* right */ +-#define A_EXTOUT_ACENTER 0x0a /* analog center */ +-#define A_EXTOUT_ALFE 0x0b /* analog LFE */ +-#define A_EXTOUT_ASIDE_L 0x0c /* analog side left - Audigy 2 ZS */ +-#define A_EXTOUT_ASIDE_R 0x0d /* right - Audigy 2 ZS */ +-#define A_EXTOUT_AREAR_L 0x0e /* analog rear left */ +-#define A_EXTOUT_AREAR_R 0x0f /* right */ +-#define A_EXTOUT_AC97_L 0x10 /* AC97 left (front) */ +-#define A_EXTOUT_AC97_R 0x11 /* right */ +-#define A_EXTOUT_ADC_CAP_L 0x16 /* ADC capture buffer left */ +-#define A_EXTOUT_ADC_CAP_R 0x17 /* right */ +-#define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */ +- +-/* Audigy constants */ +-#define A_C_00000000 0xc0 +-#define A_C_00000001 0xc1 +-#define A_C_00000002 0xc2 +-#define A_C_00000003 0xc3 +-#define A_C_00000004 0xc4 +-#define A_C_00000008 0xc5 +-#define A_C_00000010 0xc6 +-#define A_C_00000020 0xc7 +-#define A_C_00000100 0xc8 +-#define A_C_00010000 0xc9 +-#define A_C_00000800 0xca +-#define A_C_10000000 0xcb +-#define A_C_20000000 0xcc +-#define A_C_40000000 0xcd +-#define A_C_80000000 0xce +-#define A_C_7fffffff 0xcf +-#define A_C_ffffffff 0xd0 +-#define A_C_fffffffe 0xd1 +-#define A_C_c0000000 0xd2 +-#define A_C_4f1bbcdc 0xd3 +-#define A_C_5a7ef9db 0xd4 +-#define A_C_00100000 0xd5 +-#define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */ +-#define A_GPR_COND 0xd7 /* CCR, condition register */ +-#define A_GPR_NOISE0 0xd8 /* noise source */ +-#define A_GPR_NOISE1 0xd9 /* noise source */ +-#define A_GPR_IRQ 0xda /* IRQ register */ +-#define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */ +-#define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */ +- +-/* definitions for debug register */ +-#define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */ +-#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */ +-#define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */ +-#define EMU10K1_DBG_SINGLE_STEP 0x00008000 /* single step mode */ +-#define EMU10K1_DBG_STEP 0x00004000 /* start single step */ +-#define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */ +-#define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */ +- +-/* tank memory address line */ +-#ifndef __KERNEL__ +-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ +-#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ +-#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ +-#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ +-#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ +-#endif +- +-struct snd_emu10k1_fx8010_info { +- unsigned int internal_tram_size; /* in samples */ +- unsigned int external_tram_size; /* in samples */ +- char fxbus_names[16][32]; /* names of FXBUSes */ +- char extin_names[16][32]; /* names of external inputs */ +- char extout_names[32][32]; /* names of external outputs */ +- unsigned int gpr_controls; /* count of GPR controls */ +-}; +- +-#define EMU10K1_GPR_TRANSLATION_NONE 0 +-#define EMU10K1_GPR_TRANSLATION_TABLE100 1 +-#define EMU10K1_GPR_TRANSLATION_BASS 2 +-#define EMU10K1_GPR_TRANSLATION_TREBLE 3 +-#define EMU10K1_GPR_TRANSLATION_ONOFF 4 +- +-struct snd_emu10k1_fx8010_control_gpr { +- struct snd_ctl_elem_id id; /* full control ID definition */ +- unsigned int vcount; /* visible count */ +- unsigned int count; /* count of GPR (1..16) */ +- unsigned short gpr[32]; /* GPR number(s) */ +- unsigned int value[32]; /* initial values */ +- unsigned int min; /* minimum range */ +- unsigned int max; /* maximum range */ +- unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ +- const unsigned int *tlv; +-}; +- +-/* old ABI without TLV support */ +-struct snd_emu10k1_fx8010_control_old_gpr { +- struct snd_ctl_elem_id id; +- unsigned int vcount; +- unsigned int count; +- unsigned short gpr[32]; +- unsigned int value[32]; +- unsigned int min; +- unsigned int max; +- unsigned int translation; +-}; +- +-struct snd_emu10k1_fx8010_code { +- char name[128]; +- +- __EMU10K1_DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */ +- __u32 __user *gpr_map; /* initializers */ +- +- unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */ +- struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */ +- +- unsigned int gpr_del_control_count; /* count of GPR controls to remove */ +- struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */ +- +- unsigned int gpr_list_control_count; /* count of GPR controls to list */ +- unsigned int gpr_list_control_total; /* total count of GPR controls */ +- struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */ +- +- __EMU10K1_DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */ +- __u32 __user *tram_data_map; /* data initializers */ +- __u32 __user *tram_addr_map; /* map initializers */ +- +- __EMU10K1_DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */ +- __u32 __user *code; /* one instruction - 64 bits */ +-}; +- +-struct snd_emu10k1_fx8010_tram { +- unsigned int address; /* 31.bit == 1 -> external TRAM */ +- unsigned int size; /* size in samples (4 bytes) */ +- unsigned int *samples; /* pointer to samples (20-bit) */ +- /* NULL->clear memory */ +-}; +- +-struct snd_emu10k1_fx8010_pcm_rec { +- unsigned int substream; /* substream number */ +- unsigned int res1; /* reserved */ +- unsigned int channels; /* 16-bit channels count, zero = remove this substream */ +- unsigned int tram_start; /* ring buffer position in TRAM (in samples) */ +- unsigned int buffer_size; /* count of buffered samples */ +- unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */ +- unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */ +- unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */ +- unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */ +- unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */ +- unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */ +- unsigned char pad; /* reserved */ +- unsigned char etram[32]; /* external TRAM address & data (one per channel) */ +- unsigned int res2; /* reserved */ +-}; +- +-#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1) +- +-#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info) +-#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code) +-#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code) +-#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int) +-#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram) +-#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram) +-#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec) +-#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec) +-#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int) +-#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80) +-#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81) +-#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82) +-#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int) +-#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int) +- +-/* 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; +- +-#endif /* _UAPI__SOUND_EMU10K1_H */ ++#include ++#include +diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h +index 5dc0c3db..78fb745b 100644 +--- a/include/sound/hdsp.h ++++ b/include/sound/hdsp.h +@@ -1,111 +1,2 @@ +-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +-#ifndef __SOUND_HDSP_H +-#define __SOUND_HDSP_H +- +-/* +- * Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org) +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +- */ +- +-#include +- +-#define HDSP_MATRIX_MIXER_SIZE 2048 +- +-enum HDSP_IO_Type { +- Digiface, +- Multiface, +- H9652, +- H9632, +- RPM, +- Undefined, +-}; +- +-struct hdsp_peak_rms { +- __u32 input_peaks[26]; +- __u32 playback_peaks[26]; +- __u32 output_peaks[28]; +- __u64 input_rms[26]; +- __u64 playback_rms[26]; +- /* These are only used for H96xx cards */ +- __u64 output_rms[26]; +-}; +- +-#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms) +- +-struct hdsp_config_info { +- unsigned char pref_sync_ref; +- unsigned char wordclock_sync_check; +- unsigned char spdif_sync_check; +- unsigned char adatsync_sync_check; +- unsigned char adat_sync_check[3]; +- unsigned char spdif_in; +- unsigned char spdif_out; +- unsigned char spdif_professional; +- unsigned char spdif_emphasis; +- unsigned char spdif_nonaudio; +- unsigned int spdif_sample_rate; +- unsigned int system_sample_rate; +- unsigned int autosync_sample_rate; +- unsigned char system_clock_mode; +- unsigned char clock_source; +- unsigned char autosync_ref; +- unsigned char line_out; +- unsigned char passthru; +- unsigned char da_gain; +- unsigned char ad_gain; +- unsigned char phone_gain; +- unsigned char xlr_breakout_cable; +- unsigned char analog_extension_board; +-}; +- +-#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info) +- +-struct hdsp_firmware { +- void __user *firmware_data; /* 24413 x 4 bytes */ +-}; +- +-#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware) +- +-struct hdsp_version { +- enum HDSP_IO_Type io_type; +- unsigned short firmware_rev; +-}; +- +-#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version) +- +-struct hdsp_mixer { +- unsigned short matrix[HDSP_MATRIX_MIXER_SIZE]; +-}; +- +-#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer) +- +-struct hdsp_9632_aeb { +- int aebi; +- int aebo; +-}; +- +-#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 */ ++#include ++#include +diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h +index a38f3f79..af6d19ed 100644 +--- a/include/sound/hdspm.h ++++ b/include/sound/hdspm.h +@@ -1,232 +1,2 @@ +-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +-#ifndef __SOUND_HDSPM_H +-#define __SOUND_HDSPM_H +-/* +- * Copyright (C) 2003 Winfried Ritsch (IEM) +- * based on hdsp.h from Thomas Charbonnel (thomas@undata.org) +- * +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +- */ +- +-#include +- +-/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */ +-#define HDSPM_MAX_CHANNELS 64 +- +-enum hdspm_io_type { +- MADI, +- MADIface, +- AIO, +- AES32, +- RayDAT +-}; +- +-enum hdspm_speed { +- ss, +- ds, +- qs +-}; +- +-/* -------------------- IOCTL Peak/RMS Meters -------------------- */ +- +-struct hdspm_peak_rms { +- __u32 input_peaks[64]; +- __u32 playback_peaks[64]; +- __u32 output_peaks[64]; +- +- __u64 input_rms[64]; +- __u64 playback_rms[64]; +- __u64 output_rms[64]; +- +- __u8 speed; /* enum {ss, ds, qs} */ +- int status2; +-}; +- +-#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \ +- _IOR('H', 0x42, struct hdspm_peak_rms) +- +-/* ------------ CONFIG block IOCTL ---------------------- */ +- +-struct hdspm_config { +- unsigned char pref_sync_ref; +- unsigned char wordclock_sync_check; +- unsigned char madi_sync_check; +- unsigned int system_sample_rate; +- unsigned int autosync_sample_rate; +- unsigned char system_clock_mode; +- unsigned char clock_source; +- unsigned char autosync_ref; +- unsigned char line_out; +- unsigned int passthru; +- unsigned int analog_out; +-}; +- +-#define SNDRV_HDSPM_IOCTL_GET_CONFIG \ +- _IOR('H', 0x41, struct hdspm_config) +- +-/* +- * If there's a TCO (TimeCode Option) board installed, +- * there are further options and status data available. +- * The hdspm_ltc structure contains the current SMPTE +- * timecode and some status information and can be +- * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the +- * hdspm_status struct. +- */ +- +-enum hdspm_ltc_format { +- format_invalid, +- fps_24, +- fps_25, +- fps_2997, +- fps_30 +-}; +- +-enum hdspm_ltc_frame { +- frame_invalid, +- drop_frame, +- full_frame +-}; +- +-enum hdspm_ltc_input_format { +- ntsc, +- pal, +- no_video +-}; +- +-struct hdspm_ltc { +- unsigned int ltc; +- +- enum hdspm_ltc_format format; +- enum hdspm_ltc_frame frame; +- enum hdspm_ltc_input_format input_format; +-}; +- +-#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_ltc) +- +-/* +- * The status data reflects the device's current state +- * as determined by the card's configuration and +- * connection status. +- */ +- +-enum hdspm_sync { +- hdspm_sync_no_lock = 0, +- hdspm_sync_lock = 1, +- hdspm_sync_sync = 2 +-}; +- +-enum hdspm_madi_input { +- hdspm_input_optical = 0, +- hdspm_input_coax = 1 +-}; +- +-enum hdspm_madi_channel_format { +- hdspm_format_ch_64 = 0, +- hdspm_format_ch_56 = 1 +-}; +- +-enum hdspm_madi_frame_format { +- hdspm_frame_48 = 0, +- hdspm_frame_96 = 1 +-}; +- +-enum hdspm_syncsource { +- syncsource_wc = 0, +- syncsource_madi = 1, +- syncsource_tco = 2, +- syncsource_sync = 3, +- syncsource_none = 4 +-}; +- +-struct hdspm_status { +- __u8 card_type; /* enum hdspm_io_type */ +- enum hdspm_syncsource autosync_source; +- +- __u64 card_clock; +- __u32 master_period; +- +- union { +- struct { +- __u8 sync_wc; /* enum hdspm_sync */ +- __u8 sync_madi; /* enum hdspm_sync */ +- __u8 sync_tco; /* enum hdspm_sync */ +- __u8 sync_in; /* enum hdspm_sync */ +- __u8 madi_input; /* enum hdspm_madi_input */ +- __u8 channel_format; /* enum hdspm_madi_channel_format */ +- __u8 frame_format; /* enum hdspm_madi_frame_format */ +- } madi; +- } card_specific; +-}; +- +-#define SNDRV_HDSPM_IOCTL_GET_STATUS \ +- _IOR('H', 0x47, struct hdspm_status) +- +-/* +- * Get information about the card and its add-ons. +- */ +- +-#define HDSPM_ADDON_TCO 1 +- +-struct hdspm_version { +- __u8 card_type; /* enum hdspm_io_type */ +- char cardname[20]; +- unsigned int serial; +- unsigned short firmware_rev; +- int addons; +-}; +- +-#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version) +- +-/* ------------- get Matrix Mixer IOCTL --------------- */ +- +-/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte = +- * 32768 Bytes +- */ +- +-/* organisation is 64 channelfader in a continuous memory block */ +-/* equivalent to hardware definition, maybe for future feature of mmap of +- * them +- */ +-/* each of 64 outputs has 64 infader and 64 outfader: +- Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */ +- +-#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS +- +-struct hdspm_channelfader { +- unsigned int in[HDSPM_MIXER_CHANNELS]; +- unsigned int pb[HDSPM_MIXER_CHANNELS]; +-}; +- +-struct hdspm_mixer { +- struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS]; +-}; +- +-struct hdspm_mixer_ioctl { +- struct hdspm_mixer *mixer; +-}; +- +-/* 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 ++#include ++#include +diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h +index e6485148..24121fcb 100644 +--- a/include/sound/sb16_csp.h ++++ b/include/sound/sb16_csp.h +@@ -1,123 +1 @@ +-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +-/* +- * Copyright (c) 1999 by Uros Bizjak +- * Takashi Iwai +- * +- * SB16ASP/AWE32 CSP control +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- * +- */ +-#ifndef _UAPI__SOUND_SB16_CSP_H +-#define _UAPI__SOUND_SB16_CSP_H +- +- +-/* CSP modes */ +-#define SNDRV_SB_CSP_MODE_NONE 0x00 +-#define SNDRV_SB_CSP_MODE_DSP_READ 0x01 /* Record from DSP */ +-#define SNDRV_SB_CSP_MODE_DSP_WRITE 0x02 /* Play to DSP */ +-#define SNDRV_SB_CSP_MODE_QSOUND 0x04 /* QSound */ +- +-/* CSP load flags */ +-#define SNDRV_SB_CSP_LOAD_FROMUSER 0x01 +-#define SNDRV_SB_CSP_LOAD_INITBLOCK 0x02 +- +-/* CSP sample width */ +-#define SNDRV_SB_CSP_SAMPLE_8BIT 0x01 +-#define SNDRV_SB_CSP_SAMPLE_16BIT 0x02 +- +-/* CSP channels */ +-#define SNDRV_SB_CSP_MONO 0x01 +-#define SNDRV_SB_CSP_STEREO 0x02 +- +-/* CSP rates */ +-#define SNDRV_SB_CSP_RATE_8000 0x01 +-#define SNDRV_SB_CSP_RATE_11025 0x02 +-#define SNDRV_SB_CSP_RATE_22050 0x04 +-#define SNDRV_SB_CSP_RATE_44100 0x08 +-#define SNDRV_SB_CSP_RATE_ALL 0x0f +- +-/* CSP running state */ +-#define SNDRV_SB_CSP_ST_IDLE 0x00 +-#define SNDRV_SB_CSP_ST_LOADED 0x01 +-#define SNDRV_SB_CSP_ST_RUNNING 0x02 +-#define SNDRV_SB_CSP_ST_PAUSED 0x04 +-#define SNDRV_SB_CSP_ST_AUTO 0x08 +-#define SNDRV_SB_CSP_ST_QSOUND 0x10 +- +-/* maximum QSound value (180 degrees right) */ +-#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT 0x20 +- +-/* maximum microcode RIFF file size */ +-#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000 +- +-/* microcode header */ +-struct snd_sb_csp_mc_header { +- char codec_name[16]; /* id name of codec */ +- unsigned short func_req; /* requested function */ +-}; +- +-/* microcode to be loaded */ +-struct snd_sb_csp_microcode { +- struct snd_sb_csp_mc_header info; +- unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE]; +-}; +- +-/* start CSP with sample_width in mono/stereo */ +-struct snd_sb_csp_start { +- int sample_width; /* sample width, look above */ +- int channels; /* channels, look above */ +-}; +- +-/* CSP information */ +-struct snd_sb_csp_info { +- char codec_name[16]; /* id name of codec */ +- unsigned short func_nr; /* function number */ +- unsigned int acc_format; /* accepted PCM formats */ +- unsigned short acc_channels; /* accepted channels */ +- unsigned short acc_width; /* accepted sample width */ +- unsigned short acc_rates; /* accepted sample rates */ +- unsigned short csp_mode; /* CSP mode, see above */ +- unsigned short run_channels; /* current channels */ +- unsigned short run_width; /* current sample width */ +- unsigned short version; /* version id: 0x10 - 0x1f */ +- unsigned short state; /* state bits */ +-}; +- +-/* HWDEP controls */ +-/* get CSP information */ +-#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info) +-/* load microcode to CSP */ +-/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits) +- * defined for some architectures like MIPS, and it leads to build errors. +- * (x86 and co have 14-bit size, thus it's valid, though.) +- * As a workaround for skipping the size-limit check, here we don't use the +- * normal _IOW() macro but _IOC() with the manual argument. +- */ +-#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \ +- _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode)) +-/* unload microcode from CSP */ +-#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12) +-/* start CSP */ +-#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start) +-/* stop CSP */ +-#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14) +-/* pause CSP and DMA transfer */ +-#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15) +-/* restart CSP and DMA transfer */ +-#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16) +- +- +-#endif /* _UAPI__SOUND_SB16_CSP_H */ ++#include +diff --git a/include/sound/sscape_ioctl.h b/include/sound/sscape_ioctl.h +index c6653ebf..23b48d33 100644 +--- a/include/sound/sscape_ioctl.h ++++ b/include/sound/sscape_ioctl.h +@@ -1,21 +1 @@ +-#ifndef SSCAPE_IOCTL_H +-#define SSCAPE_IOCTL_H +- +- +-struct sscape_bootblock +-{ +- unsigned char code[256]; +- unsigned version; +-}; +- +-#define SSCAPE_MICROCODE_SIZE 65536 +- +-struct sscape_microcode +-{ +- unsigned char *code; +-}; +- +-#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock) +-#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode) +- +-#endif ++#include +diff --git a/include/sound/tlv.h b/include/sound/tlv.h +index 7d6d65f6..e435a5fc 100644 +--- a/include/sound/tlv.h ++++ b/include/sound/tlv.h +@@ -1,117 +1 @@ +-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +-/* +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef __UAPI_SOUND_TLV_H +-#define __UAPI_SOUND_TLV_H +- +-#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */ +-#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */ +-#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */ +-#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */ +-#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */ +-#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */ +- +-/* +- * channel-mapping TLV items +- * TLV length must match with num_channels +- */ +-#define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */ +-#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */ +-#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */ +- +-/* +- * TLV structure is right behind the struct snd_ctl_tlv: +- * unsigned int type - see SNDRV_CTL_TLVT_* +- * unsigned int length +- * .... data aligned to sizeof(unsigned int), use +- * block_length = (length + (sizeof(unsigned int) - 1)) & +- * ~(sizeof(unsigned int) - 1)) .... +- */ +-#define SNDRV_CTL_TLVD_ITEM(type, ...) \ +- (type), SNDRV_CTL_TLVD_LENGTH(__VA_ARGS__), __VA_ARGS__ +-#define SNDRV_CTL_TLVD_LENGTH(...) \ +- ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ })) +- +-/* Accessor offsets for TLV data items */ +-#define SNDRV_CTL_TLVO_TYPE 0 +-#define SNDRV_CTL_TLVO_LEN 1 +- +-#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \ +- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__) +-#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \ +- unsigned int name[] = { \ +- SNDRV_CTL_TLVD_CONTAINER_ITEM(__VA_ARGS__) \ +- } +- +-#define SNDRV_CTL_TLVD_DB_SCALE_MASK 0xffff +-#define SNDRV_CTL_TLVD_DB_SCALE_MUTE 0x10000 +-#define SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \ +- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \ +- (min), \ +- ((step) & SNDRV_CTL_TLVD_DB_SCALE_MASK) | \ +- ((mute) ? SNDRV_CTL_TLVD_DB_SCALE_MUTE : 0)) +-#define SNDRV_CTL_TLVD_DECLARE_DB_SCALE(name, min, step, mute) \ +- unsigned int name[] = { \ +- SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \ +- } +- +-/* Accessor offsets for min, mute and step items in dB scale type TLV */ +-#define SNDRV_CTL_TLVO_DB_SCALE_MIN 2 +-#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 3 +- +-/* dB scale specified with min/max values instead of step */ +-#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \ +- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB)) +-#define SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ +- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB)) +-#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(name, min_dB, max_dB) \ +- unsigned int name[] = { \ +- SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \ +- } +-#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE(name, min_dB, max_dB) \ +- unsigned int name[] = { \ +- SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ +- } +- +-/* Accessor offsets for min, max items in db-minmax types of TLV. */ +-#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 2 +-#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 3 +- +-/* linear volume between min_dB and max_dB (.01dB unit) */ +-#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \ +- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB)) +-#define SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(name, min_dB, max_dB) \ +- unsigned int name[] = { \ +- SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \ +- } +- +-/* Accessor offsets for min, max items in db-linear type of TLV. */ +-#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 2 +-#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 3 +- +-/* dB range container: +- * Items in dB range container must be ordered by their values and by their +- * dB values. This implies that larger values must correspond with larger +- * dB values (which is also required for all other mixer controls). +- */ +-/* Each item is: */ +-#define SNDRV_CTL_TLVD_DB_RANGE_ITEM(...) \ +- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__) +-#define SNDRV_CTL_TLVD_DECLARE_DB_RANGE(name, ...) \ +- unsigned int name[] = { \ +- SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) \ +- } +- +-#define SNDRV_CTL_TLVD_DB_GAIN_MUTE -9999999 +- +-#endif ++#include +diff --git a/include/sound/type_compat.h b/include/sound/type_compat.h +index e973ff31..d4790c1f 100644 +--- a/include/sound/type_compat.h ++++ b/include/sound/type_compat.h +@@ -3,6 +3,9 @@ + + #ifndef DOC_HIDDEN + #include ++#ifdef __linux__ ++#include ++#else + typedef uint8_t __u8; + typedef uint16_t __u16; + typedef uint32_t __u32; +@@ -37,6 +40,16 @@ typedef int32_t __s32; + #define __be32 __u32 + #define __be16 __u16 + #define __be8 __u8 ++#endif ++ ++#ifndef __user ++#define __user ++#endif ++ ++#ifndef __packed ++#define __packed __attribute__((__packed__)) ++#endif ++ + #endif /* DOC_HIDDEN */ + + #endif /* __TYPE_COMPAT_H */ +diff --git a/include/sound/uapi/Makefile.am b/include/sound/uapi/Makefile.am +new file mode 100644 +index 00000000..99197108 +--- /dev/null ++++ b/include/sound/uapi/Makefile.am +@@ -0,0 +1,6 @@ ++alsasounduapiincludedir = ${includedir}/alsa/sound/uapi ++ ++alsasounduapiinclude_HEADERS = asound_fm.h hdsp.h hdspm.h sb16_csp.h \ ++ sscape_ioctl.h emu10k1.h asoc.h tlv.h ++ ++noinst_HEADERS = asound.h asequencer.h +diff --git a/include/sound/uapi/asequencer.h b/include/sound/uapi/asequencer.h +new file mode 100644 +index 00000000..a75e14ed +--- /dev/null ++++ b/include/sound/uapi/asequencer.h +@@ -0,0 +1,612 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * Main header file for the ALSA sequencer ++ * Copyright (c) 1998-1999 by Frank van de Pol ++ * (c) 1998-1999 by Jaroslav Kysela ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++#ifndef _UAPI__SOUND_ASEQUENCER_H ++#define _UAPI__SOUND_ASEQUENCER_H ++ ++#include ++ ++/** version of the sequencer */ ++#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 2) ++ ++/** ++ * definition of sequencer event types ++ */ ++ ++/** system messages ++ * event data type = #snd_seq_result ++ */ ++#define SNDRV_SEQ_EVENT_SYSTEM 0 ++#define SNDRV_SEQ_EVENT_RESULT 1 ++ ++/** note messages (channel specific) ++ * event data type = #snd_seq_ev_note ++ */ ++#define SNDRV_SEQ_EVENT_NOTE 5 ++#define SNDRV_SEQ_EVENT_NOTEON 6 ++#define SNDRV_SEQ_EVENT_NOTEOFF 7 ++#define SNDRV_SEQ_EVENT_KEYPRESS 8 ++ ++/** control messages (channel specific) ++ * event data type = #snd_seq_ev_ctrl ++ */ ++#define SNDRV_SEQ_EVENT_CONTROLLER 10 ++#define SNDRV_SEQ_EVENT_PGMCHANGE 11 ++#define SNDRV_SEQ_EVENT_CHANPRESS 12 ++#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */ ++#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */ ++#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */ ++#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */ ++ ++/** synchronisation messages ++ * event data type = #snd_seq_ev_ctrl ++ */ ++#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */ ++#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */ ++#define SNDRV_SEQ_EVENT_QFRAME 22 /* midi time code quarter frame */ ++#define SNDRV_SEQ_EVENT_TIMESIGN 23 /* SMF Time Signature event */ ++#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */ ++ ++/** timer messages ++ * event data type = snd_seq_ev_queue_control ++ */ ++#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */ ++#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */ ++#define SNDRV_SEQ_EVENT_STOP 32 /* midi Real Time Stop message */ ++#define SNDRV_SEQ_EVENT_SETPOS_TICK 33 /* set tick queue position */ ++#define SNDRV_SEQ_EVENT_SETPOS_TIME 34 /* set realtime queue position */ ++#define SNDRV_SEQ_EVENT_TEMPO 35 /* (SMF) Tempo event */ ++#define SNDRV_SEQ_EVENT_CLOCK 36 /* midi Real Time Clock message */ ++#define SNDRV_SEQ_EVENT_TICK 37 /* midi Real Time Tick message */ ++#define SNDRV_SEQ_EVENT_QUEUE_SKEW 38 /* skew queue tempo */ ++ ++/** others ++ * event data type = none ++ */ ++#define SNDRV_SEQ_EVENT_TUNE_REQUEST 40 /* tune request */ ++#define SNDRV_SEQ_EVENT_RESET 41 /* reset to power-on state */ ++#define SNDRV_SEQ_EVENT_SENSING 42 /* "active sensing" event */ ++ ++/** echo back, kernel private messages ++ * event data type = any type ++ */ ++#define SNDRV_SEQ_EVENT_ECHO 50 /* echo event */ ++#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */ ++ ++/** system status messages (broadcast for subscribers) ++ * event data type = snd_seq_addr ++ */ ++#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */ ++#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */ ++#define SNDRV_SEQ_EVENT_CLIENT_CHANGE 62 /* client status/info has changed */ ++#define SNDRV_SEQ_EVENT_PORT_START 63 /* new port was created */ ++#define SNDRV_SEQ_EVENT_PORT_EXIT 64 /* port was deleted from system */ ++#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */ ++ ++/** port connection changes ++ * event data type = snd_seq_connect ++ */ ++#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */ ++#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */ ++ ++/* 70-89: synthesizer events - obsoleted */ ++ ++/** user-defined events with fixed length ++ * event data type = any ++ */ ++#define SNDRV_SEQ_EVENT_USR0 90 ++#define SNDRV_SEQ_EVENT_USR1 91 ++#define SNDRV_SEQ_EVENT_USR2 92 ++#define SNDRV_SEQ_EVENT_USR3 93 ++#define SNDRV_SEQ_EVENT_USR4 94 ++#define SNDRV_SEQ_EVENT_USR5 95 ++#define SNDRV_SEQ_EVENT_USR6 96 ++#define SNDRV_SEQ_EVENT_USR7 97 ++#define SNDRV_SEQ_EVENT_USR8 98 ++#define SNDRV_SEQ_EVENT_USR9 99 ++ ++/* 100-118: instrument layer - obsoleted */ ++/* 119-129: reserved */ ++ ++/* 130-139: variable length events ++ * event data type = snd_seq_ev_ext ++ * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set) ++ */ ++#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */ ++#define SNDRV_SEQ_EVENT_BOUNCE 131 /* error event */ ++/* 132-134: reserved */ ++#define SNDRV_SEQ_EVENT_USR_VAR0 135 ++#define SNDRV_SEQ_EVENT_USR_VAR1 136 ++#define SNDRV_SEQ_EVENT_USR_VAR2 137 ++#define SNDRV_SEQ_EVENT_USR_VAR3 138 ++#define SNDRV_SEQ_EVENT_USR_VAR4 139 ++ ++/* 150-151: kernel events with quote - DO NOT use in user clients */ ++#define SNDRV_SEQ_EVENT_KERNEL_ERROR 150 ++#define SNDRV_SEQ_EVENT_KERNEL_QUOTE 151 /* obsolete */ ++ ++/* 152-191: reserved */ ++ ++/* 192-254: hardware specific events */ ++ ++/* 255: special event */ ++#define SNDRV_SEQ_EVENT_NONE 255 ++ ++ ++typedef unsigned char snd_seq_event_type_t; ++ ++/** event address */ ++struct snd_seq_addr { ++ unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */ ++ unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */ ++}; ++ ++/** port connection */ ++struct snd_seq_connect { ++ struct snd_seq_addr sender; ++ struct snd_seq_addr dest; ++}; ++ ++ ++#define SNDRV_SEQ_ADDRESS_UNKNOWN 253 /* unknown source */ ++#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS 254 /* send event to all subscribed ports */ ++#define SNDRV_SEQ_ADDRESS_BROADCAST 255 /* send event to all queues/clients/ports/channels */ ++#define SNDRV_SEQ_QUEUE_DIRECT 253 /* direct dispatch */ ++ ++ /* event mode flag - NOTE: only 8 bits available! */ ++#define SNDRV_SEQ_TIME_STAMP_TICK (0<<0) /* timestamp in clock ticks */ ++#define SNDRV_SEQ_TIME_STAMP_REAL (1<<0) /* timestamp in real time */ ++#define SNDRV_SEQ_TIME_STAMP_MASK (1<<0) ++ ++#define SNDRV_SEQ_TIME_MODE_ABS (0<<1) /* absolute timestamp */ ++#define SNDRV_SEQ_TIME_MODE_REL (1<<1) /* relative to current time */ ++#define SNDRV_SEQ_TIME_MODE_MASK (1<<1) ++ ++#define SNDRV_SEQ_EVENT_LENGTH_FIXED (0<<2) /* fixed event size */ ++#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /* variable event size */ ++#define SNDRV_SEQ_EVENT_LENGTH_VARUSR (2<<2) /* variable event size - user memory space */ ++#define SNDRV_SEQ_EVENT_LENGTH_MASK (3<<2) ++ ++#define SNDRV_SEQ_PRIORITY_NORMAL (0<<4) /* normal priority */ ++#define SNDRV_SEQ_PRIORITY_HIGH (1<<4) /* event should be processed before others */ ++#define SNDRV_SEQ_PRIORITY_MASK (1<<4) ++ ++ ++ /* note event */ ++struct snd_seq_ev_note { ++ unsigned char channel; ++ unsigned char note; ++ unsigned char velocity; ++ unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */ ++ unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */ ++}; ++ ++ /* controller event */ ++struct snd_seq_ev_ctrl { ++ unsigned char channel; ++ unsigned char unused1, unused2, unused3; /* pad */ ++ unsigned int param; ++ signed int value; ++}; ++ ++ /* generic set of bytes (12x8 bit) */ ++struct snd_seq_ev_raw8 { ++ unsigned char d[12]; /* 8 bit value */ ++}; ++ ++ /* generic set of integers (3x32 bit) */ ++struct snd_seq_ev_raw32 { ++ unsigned int d[3]; /* 32 bit value */ ++}; ++ ++ /* external stored data */ ++struct snd_seq_ev_ext { ++ unsigned int len; /* length of data */ ++ void *ptr; /* pointer to data (note: maybe 64-bit) */ ++} __attribute__((packed)); ++ ++struct snd_seq_result { ++ int event; /* processed event type */ ++ int result; ++}; ++ ++ ++struct snd_seq_real_time { ++ unsigned int tv_sec; /* seconds */ ++ unsigned int tv_nsec; /* nanoseconds */ ++}; ++ ++typedef unsigned int snd_seq_tick_time_t; /* midi ticks */ ++ ++union snd_seq_timestamp { ++ snd_seq_tick_time_t tick; ++ struct snd_seq_real_time time; ++}; ++ ++struct snd_seq_queue_skew { ++ unsigned int value; ++ unsigned int base; ++}; ++ ++ /* queue timer control */ ++struct snd_seq_ev_queue_control { ++ unsigned char queue; /* affected queue */ ++ unsigned char pad[3]; /* reserved */ ++ union { ++ signed int value; /* affected value (e.g. tempo) */ ++ union snd_seq_timestamp time; /* time */ ++ unsigned int position; /* sync position */ ++ struct snd_seq_queue_skew skew; ++ unsigned int d32[2]; ++ unsigned char d8[8]; ++ } param; ++}; ++ ++ /* quoted event - inside the kernel only */ ++struct snd_seq_ev_quote { ++ struct snd_seq_addr origin; /* original sender */ ++ unsigned short value; /* optional data */ ++ struct snd_seq_event *event; /* quoted event */ ++} __attribute__((packed)); ++ ++ ++ /* sequencer event */ ++struct snd_seq_event { ++ snd_seq_event_type_t type; /* event type */ ++ unsigned char flags; /* event flags */ ++ char tag; ++ ++ unsigned char queue; /* schedule queue */ ++ union snd_seq_timestamp time; /* schedule time */ ++ ++ ++ struct snd_seq_addr source; /* source address */ ++ struct snd_seq_addr dest; /* destination address */ ++ ++ union { /* event data... */ ++ struct snd_seq_ev_note note; ++ struct snd_seq_ev_ctrl control; ++ struct snd_seq_ev_raw8 raw8; ++ struct snd_seq_ev_raw32 raw32; ++ struct snd_seq_ev_ext ext; ++ struct snd_seq_ev_queue_control queue; ++ union snd_seq_timestamp time; ++ struct snd_seq_addr addr; ++ struct snd_seq_connect connect; ++ struct snd_seq_result result; ++ struct snd_seq_ev_quote quote; ++ } data; ++}; ++ ++ ++/* ++ * bounce event - stored as variable size data ++ */ ++struct snd_seq_event_bounce { ++ int err; ++ struct snd_seq_event event; ++ /* external data follows here. */ ++}; ++ ++ ++ /* system information */ ++struct snd_seq_system_info { ++ int queues; /* maximum queues count */ ++ int clients; /* maximum clients count */ ++ int ports; /* maximum ports per client */ ++ int channels; /* maximum channels per port */ ++ int cur_clients; /* current clients */ ++ int cur_queues; /* current queues */ ++ char reserved[24]; ++}; ++ ++ ++ /* system running information */ ++struct snd_seq_running_info { ++ unsigned char client; /* client id */ ++ unsigned char big_endian; /* 1 = big-endian */ ++ unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */ ++ unsigned char pad; /* reserved */ ++ unsigned char reserved[12]; ++}; ++ ++ ++ /* known client numbers */ ++#define SNDRV_SEQ_CLIENT_SYSTEM 0 ++ /* internal client numbers */ ++#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */ ++#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */ ++ ++ ++ /* client types */ ++typedef int __bitwise snd_seq_client_type_t; ++#define NO_CLIENT ((__force snd_seq_client_type_t) 0) ++#define USER_CLIENT ((__force snd_seq_client_type_t) 1) ++#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2) ++ ++ /* event filter flags */ ++#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */ ++#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */ ++#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */ ++#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */ ++ ++struct snd_seq_client_info { ++ int client; /* client number to inquire */ ++ snd_seq_client_type_t type; /* client type */ ++ char name[64]; /* client name */ ++ unsigned int filter; /* filter flags */ ++ unsigned char multicast_filter[8]; /* multicast filter bitmap */ ++ unsigned char event_filter[32]; /* event filter bitmap */ ++ int num_ports; /* RO: number of ports */ ++ int event_lost; /* number of lost events */ ++ int card; /* RO: card number[kernel] */ ++ int pid; /* RO: pid[user] */ ++ char reserved[56]; /* for future use */ ++}; ++ ++ ++/* client pool size */ ++struct snd_seq_client_pool { ++ int client; /* client number to inquire */ ++ int output_pool; /* outgoing (write) pool size */ ++ int input_pool; /* incoming (read) pool size */ ++ int output_room; /* minimum free pool size for select/blocking mode */ ++ int output_free; /* unused size */ ++ int input_free; /* unused size */ ++ char reserved[64]; ++}; ++ ++ ++/* Remove events by specified criteria */ ++ ++#define SNDRV_SEQ_REMOVE_INPUT (1<<0) /* Flush input queues */ ++#define SNDRV_SEQ_REMOVE_OUTPUT (1<<1) /* Flush output queues */ ++#define SNDRV_SEQ_REMOVE_DEST (1<<2) /* Restrict by destination q:client:port */ ++#define SNDRV_SEQ_REMOVE_DEST_CHANNEL (1<<3) /* Restrict by channel */ ++#define SNDRV_SEQ_REMOVE_TIME_BEFORE (1<<4) /* Restrict to before time */ ++#define SNDRV_SEQ_REMOVE_TIME_AFTER (1<<5) /* Restrict to time or after */ ++#define SNDRV_SEQ_REMOVE_TIME_TICK (1<<6) /* Time is in ticks */ ++#define SNDRV_SEQ_REMOVE_EVENT_TYPE (1<<7) /* Restrict to event type */ ++#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */ ++#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */ ++ ++struct snd_seq_remove_events { ++ unsigned int remove_mode; /* Flags that determine what gets removed */ ++ ++ union snd_seq_timestamp time; ++ ++ unsigned char queue; /* Queue for REMOVE_DEST */ ++ struct snd_seq_addr dest; /* Address for REMOVE_DEST */ ++ unsigned char channel; /* Channel for REMOVE_DEST */ ++ ++ int type; /* For REMOVE_EVENT_TYPE */ ++ char tag; /* Tag for REMOVE_TAG */ ++ ++ int reserved[10]; /* To allow for future binary compatibility */ ++ ++}; ++ ++ ++ /* known port numbers */ ++#define SNDRV_SEQ_PORT_SYSTEM_TIMER 0 ++#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1 ++ ++ /* port capabilities (32 bits) */ ++#define SNDRV_SEQ_PORT_CAP_READ (1<<0) /* readable from this port */ ++#define SNDRV_SEQ_PORT_CAP_WRITE (1<<1) /* writable to this port */ ++ ++#define SNDRV_SEQ_PORT_CAP_SYNC_READ (1<<2) ++#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE (1<<3) ++ ++#define SNDRV_SEQ_PORT_CAP_DUPLEX (1<<4) ++ ++#define SNDRV_SEQ_PORT_CAP_SUBS_READ (1<<5) /* allow read subscription */ ++#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */ ++#define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */ ++ ++ /* port type */ ++#define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */ ++#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /* generic MIDI device */ ++#define SNDRV_SEQ_PORT_TYPE_MIDI_GM (1<<2) /* General MIDI compatible device */ ++#define SNDRV_SEQ_PORT_TYPE_MIDI_GS (1<<3) /* GS compatible device */ ++#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */ ++#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */ ++#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */ ++ ++/* other standards...*/ ++#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */ ++#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */ ++#define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */ ++/*...*/ ++#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */ ++#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */ ++#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */ ++#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */ ++#define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */ ++ ++/* misc. conditioning flags */ ++#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0) ++#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1) ++#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2) ++ ++struct snd_seq_port_info { ++ struct snd_seq_addr addr; /* client/port numbers */ ++ char name[64]; /* port name */ ++ ++ unsigned int capability; /* port capability bits */ ++ unsigned int type; /* port type bits */ ++ int midi_channels; /* channels per MIDI port */ ++ int midi_voices; /* voices per MIDI port */ ++ int synth_voices; /* voices per SYNTH port */ ++ ++ int read_use; /* R/O: subscribers for output (from this port) */ ++ int write_use; /* R/O: subscribers for input (to this port) */ ++ ++ void *kernel; /* reserved for kernel use (must be NULL) */ ++ unsigned int flags; /* misc. conditioning */ ++ unsigned char time_queue; /* queue # for timestamping */ ++ char reserved[59]; /* for future use */ ++}; ++ ++ ++/* queue flags */ ++#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */ ++ ++/* queue information */ ++struct snd_seq_queue_info { ++ int queue; /* queue id */ ++ ++ /* ++ * security settings, only owner of this queue can start/stop timer ++ * etc. if the queue is locked for other clients ++ */ ++ int owner; /* client id for owner of the queue */ ++ unsigned locked:1; /* timing queue locked for other queues */ ++ char name[64]; /* name of this queue */ ++ unsigned int flags; /* flags */ ++ char reserved[60]; /* for future use */ ++ ++}; ++ ++/* queue info/status */ ++struct snd_seq_queue_status { ++ int queue; /* queue id */ ++ int events; /* read-only - queue size */ ++ snd_seq_tick_time_t tick; /* current tick */ ++ struct snd_seq_real_time time; /* current time */ ++ int running; /* running state of queue */ ++ int flags; /* various flags */ ++ char reserved[64]; /* for the future */ ++}; ++ ++ ++/* queue tempo */ ++struct snd_seq_queue_tempo { ++ int queue; /* sequencer queue */ ++ unsigned int tempo; /* current tempo, us/tick */ ++ int ppq; /* time resolution, ticks/quarter */ ++ unsigned int skew_value; /* queue skew */ ++ unsigned int skew_base; /* queue skew base */ ++ char reserved[24]; /* for the future */ ++}; ++ ++ ++/* sequencer timer sources */ ++#define SNDRV_SEQ_TIMER_ALSA 0 /* ALSA timer */ ++#define SNDRV_SEQ_TIMER_MIDI_CLOCK 1 /* Midi Clock (CLOCK event) */ ++#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */ ++ ++/* queue timer info */ ++struct snd_seq_queue_timer { ++ int queue; /* sequencer queue */ ++ int type; /* source timer type */ ++ union { ++ struct { ++ struct snd_timer_id id; /* ALSA's timer ID */ ++ unsigned int resolution; /* resolution in Hz */ ++ } alsa; ++ } u; ++ char reserved[64]; /* for the future use */ ++}; ++ ++ ++struct snd_seq_queue_client { ++ int queue; /* sequencer queue */ ++ int client; /* sequencer client */ ++ int used; /* queue is used with this client ++ (must be set for accepting events) */ ++ /* per client watermarks */ ++ char reserved[64]; /* for future use */ ++}; ++ ++ ++#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE (1<<0) /* exclusive connection */ ++#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1) ++#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2) ++ ++struct snd_seq_port_subscribe { ++ struct snd_seq_addr sender; /* sender address */ ++ struct snd_seq_addr dest; /* destination address */ ++ unsigned int voices; /* number of voices to be allocated (0 = don't care) */ ++ unsigned int flags; /* modes */ ++ unsigned char queue; /* input time-stamp queue (optional) */ ++ unsigned char pad[3]; /* reserved */ ++ char reserved[64]; ++}; ++ ++/* type of query subscription */ ++#define SNDRV_SEQ_QUERY_SUBS_READ 0 ++#define SNDRV_SEQ_QUERY_SUBS_WRITE 1 ++ ++struct snd_seq_query_subs { ++ struct snd_seq_addr root; /* client/port id to be searched */ ++ int type; /* READ or WRITE */ ++ int index; /* 0..N-1 */ ++ int num_subs; /* R/O: number of subscriptions on this port */ ++ struct snd_seq_addr addr; /* R/O: result */ ++ unsigned char queue; /* R/O: result */ ++ unsigned int flags; /* R/O: result */ ++ char reserved[64]; /* for future use */ ++}; ++ ++ ++/* ++ * IOCTL commands ++ */ ++ ++#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int) ++#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int) ++#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info) ++#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info) ++ ++#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info) ++#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info) ++ ++#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info) ++#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info) ++#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info) ++#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info) ++ ++#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe) ++#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe) ++ ++#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client) ++#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool) ++#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool) ++#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events) ++#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs) ++#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe) ++#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info) ++#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info) ++ ++#endif /* _UAPI__SOUND_ASEQUENCER_H */ +diff --git a/include/sound/uapi/asoc.h b/include/sound/uapi/asoc.h +new file mode 100644 +index 00000000..a74ca232 +--- /dev/null ++++ b/include/sound/uapi/asoc.h +@@ -0,0 +1,633 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * uapi/sound/asoc.h -- ALSA SoC Firmware Controls and DAPM ++ * ++ * Copyright (C) 2012 Texas Instruments Inc. ++ * Copyright (C) 2015 Intel Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Simple file API to load FW that includes mixers, coefficients, DAPM graphs, ++ * algorithms, equalisers, DAIs, widgets etc. ++*/ ++ ++#ifndef __LINUX_UAPI_SND_ASOC_H ++#define __LINUX_UAPI_SND_ASOC_H ++ ++#include ++#include ++ ++/* ++ * Maximum number of channels topology kcontrol can represent. ++ */ ++#define SND_SOC_TPLG_MAX_CHAN 8 ++ ++/* ++ * Maximum number of PCM formats capability ++ */ ++#define SND_SOC_TPLG_MAX_FORMATS 16 ++ ++/* ++ * Maximum number of PCM stream configs ++ */ ++#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8 ++ ++/* ++ * Maximum number of physical link's hardware configs ++ */ ++#define SND_SOC_TPLG_HW_CONFIG_MAX 8 ++ ++/* individual kcontrol info types - can be mixed with other types */ ++#define SND_SOC_TPLG_CTL_VOLSW 1 ++#define SND_SOC_TPLG_CTL_VOLSW_SX 2 ++#define SND_SOC_TPLG_CTL_VOLSW_XR_SX 3 ++#define SND_SOC_TPLG_CTL_ENUM 4 ++#define SND_SOC_TPLG_CTL_BYTES 5 ++#define SND_SOC_TPLG_CTL_ENUM_VALUE 6 ++#define SND_SOC_TPLG_CTL_RANGE 7 ++#define SND_SOC_TPLG_CTL_STROBE 8 ++ ++ ++/* individual widget kcontrol info types - can be mixed with other types */ ++#define SND_SOC_TPLG_DAPM_CTL_VOLSW 64 ++#define SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE 65 ++#define SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT 66 ++#define SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE 67 ++#define SND_SOC_TPLG_DAPM_CTL_PIN 68 ++ ++/* DAPM widget types - add new items to the end */ ++#define SND_SOC_TPLG_DAPM_INPUT 0 ++#define SND_SOC_TPLG_DAPM_OUTPUT 1 ++#define SND_SOC_TPLG_DAPM_MUX 2 ++#define SND_SOC_TPLG_DAPM_MIXER 3 ++#define SND_SOC_TPLG_DAPM_PGA 4 ++#define SND_SOC_TPLG_DAPM_OUT_DRV 5 ++#define SND_SOC_TPLG_DAPM_ADC 6 ++#define SND_SOC_TPLG_DAPM_DAC 7 ++#define SND_SOC_TPLG_DAPM_SWITCH 8 ++#define SND_SOC_TPLG_DAPM_PRE 9 ++#define SND_SOC_TPLG_DAPM_POST 10 ++#define SND_SOC_TPLG_DAPM_AIF_IN 11 ++#define SND_SOC_TPLG_DAPM_AIF_OUT 12 ++#define SND_SOC_TPLG_DAPM_DAI_IN 13 ++#define SND_SOC_TPLG_DAPM_DAI_OUT 14 ++#define SND_SOC_TPLG_DAPM_DAI_LINK 15 ++#define SND_SOC_TPLG_DAPM_BUFFER 16 ++#define SND_SOC_TPLG_DAPM_SCHEDULER 17 ++#define SND_SOC_TPLG_DAPM_EFFECT 18 ++#define SND_SOC_TPLG_DAPM_SIGGEN 19 ++#define SND_SOC_TPLG_DAPM_SRC 20 ++#define SND_SOC_TPLG_DAPM_ASRC 21 ++#define SND_SOC_TPLG_DAPM_ENCODER 22 ++#define SND_SOC_TPLG_DAPM_DECODER 23 ++#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DECODER ++ ++/* Header magic number and string sizes */ ++#define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */ ++ ++/* string sizes */ ++#define SND_SOC_TPLG_NUM_TEXTS 16 ++ ++/* ABI version */ ++#define SND_SOC_TPLG_ABI_VERSION 0x5 /* current version */ ++#define SND_SOC_TPLG_ABI_VERSION_MIN 0x4 /* oldest version supported */ ++ ++/* Max size of TLV data */ ++#define SND_SOC_TPLG_TLV_SIZE 32 ++ ++/* ++ * File and Block header data types. ++ * Add new generic and vendor types to end of list. ++ * Generic types are handled by the core whilst vendors types are passed ++ * to the component drivers for handling. ++ */ ++#define SND_SOC_TPLG_TYPE_MIXER 1 ++#define SND_SOC_TPLG_TYPE_BYTES 2 ++#define SND_SOC_TPLG_TYPE_ENUM 3 ++#define SND_SOC_TPLG_TYPE_DAPM_GRAPH 4 ++#define SND_SOC_TPLG_TYPE_DAPM_WIDGET 5 ++#define SND_SOC_TPLG_TYPE_DAI_LINK 6 ++#define SND_SOC_TPLG_TYPE_PCM 7 ++#define SND_SOC_TPLG_TYPE_MANIFEST 8 ++#define SND_SOC_TPLG_TYPE_CODEC_LINK 9 ++#define SND_SOC_TPLG_TYPE_BACKEND_LINK 10 ++#define SND_SOC_TPLG_TYPE_PDATA 11 ++#define SND_SOC_TPLG_TYPE_DAI 12 ++#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_DAI ++ ++/* vendor block IDs - please add new vendor types to end */ ++#define SND_SOC_TPLG_TYPE_VENDOR_FW 1000 ++#define SND_SOC_TPLG_TYPE_VENDOR_CONFIG 1001 ++#define SND_SOC_TPLG_TYPE_VENDOR_COEFF 1002 ++#define SND_SOC_TPLG_TYPEVENDOR_CODEC 1003 ++ ++#define SND_SOC_TPLG_STREAM_PLAYBACK 0 ++#define SND_SOC_TPLG_STREAM_CAPTURE 1 ++ ++/* vendor tuple types */ ++#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0 ++#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1 ++#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2 ++#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3 ++#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 ++#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5 ++ ++/* DAI flags */ ++#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0) ++#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) ++#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2) ++ ++/* DAI clock gating */ ++#define SND_SOC_TPLG_DAI_CLK_GATE_UNDEFINED 0 ++#define SND_SOC_TPLG_DAI_CLK_GATE_GATED 1 ++#define SND_SOC_TPLG_DAI_CLK_GATE_CONT 2 ++ ++/* DAI mclk_direction */ ++#define SND_SOC_TPLG_MCLK_CO 0 /* for codec, mclk is output */ ++#define SND_SOC_TPLG_MCLK_CI 1 /* for codec, mclk is input */ ++ ++/* DAI physical PCM data formats. ++ * Add new formats to the end of the list. ++ */ ++#define SND_SOC_DAI_FORMAT_I2S 1 /* I2S mode */ ++#define SND_SOC_DAI_FORMAT_RIGHT_J 2 /* Right Justified mode */ ++#define SND_SOC_DAI_FORMAT_LEFT_J 3 /* Left Justified mode */ ++#define SND_SOC_DAI_FORMAT_DSP_A 4 /* L data MSB after FRM LRC */ ++#define SND_SOC_DAI_FORMAT_DSP_B 5 /* L data MSB during FRM LRC */ ++#define SND_SOC_DAI_FORMAT_AC97 6 /* AC97 */ ++#define SND_SOC_DAI_FORMAT_PDM 7 /* Pulse density modulation */ ++ ++/* left and right justified also known as MSB and LSB respectively */ ++#define SND_SOC_DAI_FORMAT_MSB SND_SOC_DAI_FORMAT_LEFT_J ++#define SND_SOC_DAI_FORMAT_LSB SND_SOC_DAI_FORMAT_RIGHT_J ++ ++/* DAI link flags */ ++#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES (1 << 0) ++#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) ++#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2) ++#define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP (1 << 3) ++ ++/* DAI topology BCLK parameter ++ * For the backwards capability, by default codec is bclk master ++ */ ++#define SND_SOC_TPLG_BCLK_CM 0 /* codec is bclk master */ ++#define SND_SOC_TPLG_BCLK_CS 1 /* codec is bclk slave */ ++ ++/* DAI topology FSYNC parameter ++ * For the backwards capability, by default codec is fsync master ++ */ ++#define SND_SOC_TPLG_FSYNC_CM 0 /* codec is fsync master */ ++#define SND_SOC_TPLG_FSYNC_CS 1 /* codec is fsync slave */ ++ ++/* ++ * Block Header. ++ * This header precedes all object and object arrays below. ++ */ ++struct snd_soc_tplg_hdr { ++ __le32 magic; /* magic number */ ++ __le32 abi; /* ABI version */ ++ __le32 version; /* optional vendor specific version details */ ++ __le32 type; /* SND_SOC_TPLG_TYPE_ */ ++ __le32 size; /* size of this structure */ ++ __le32 vendor_type; /* optional vendor specific type info */ ++ __le32 payload_size; /* data bytes, excluding this header */ ++ __le32 index; /* identifier for block */ ++ __le32 count; /* number of elements in block */ ++} __attribute__((packed)); ++ ++/* vendor tuple for uuid */ ++struct snd_soc_tplg_vendor_uuid_elem { ++ __le32 token; ++ char uuid[16]; ++} __attribute__((packed)); ++ ++/* vendor tuple for a bool/byte/short/word value */ ++struct snd_soc_tplg_vendor_value_elem { ++ __le32 token; ++ __le32 value; ++} __attribute__((packed)); ++ ++/* vendor tuple for string */ ++struct snd_soc_tplg_vendor_string_elem { ++ __le32 token; ++ char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++} __attribute__((packed)); ++ ++struct snd_soc_tplg_vendor_array { ++ __le32 size; /* size in bytes of the array, including all elements */ ++ __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */ ++ __le32 num_elems; /* number of elements in array */ ++ union { ++ struct snd_soc_tplg_vendor_uuid_elem uuid[0]; ++ struct snd_soc_tplg_vendor_value_elem value[0]; ++ struct snd_soc_tplg_vendor_string_elem string[0]; ++ }; ++} __attribute__((packed)); ++ ++/* ++ * Private data. ++ * All topology objects may have private data that can be used by the driver or ++ * firmware. Core will ignore this data. ++ */ ++struct snd_soc_tplg_private { ++ __le32 size; /* in bytes of private data */ ++ union { ++ char data[0]; ++ struct snd_soc_tplg_vendor_array array[0]; ++ }; ++} __attribute__((packed)); ++ ++/* ++ * Kcontrol TLV data. ++ */ ++struct snd_soc_tplg_tlv_dbscale { ++ __le32 min; ++ __le32 step; ++ __le32 mute; ++} __attribute__((packed)); ++ ++struct snd_soc_tplg_ctl_tlv { ++ __le32 size; /* in bytes of this structure */ ++ __le32 type; /* SNDRV_CTL_TLVT_*, type of TLV */ ++ union { ++ __le32 data[SND_SOC_TPLG_TLV_SIZE]; ++ struct snd_soc_tplg_tlv_dbscale scale; ++ }; ++} __attribute__((packed)); ++ ++/* ++ * Kcontrol channel data ++ */ ++struct snd_soc_tplg_channel { ++ __le32 size; /* in bytes of this structure */ ++ __le32 reg; ++ __le32 shift; ++ __le32 id; /* ID maps to Left, Right, LFE etc */ ++} __attribute__((packed)); ++ ++/* ++ * Genericl Operations IDs, for binding Kcontrol or Bytes ext ops ++ * Kcontrol ops need get/put/info. ++ * Bytes ext ops need get/put. ++ */ ++struct snd_soc_tplg_io_ops { ++ __le32 get; ++ __le32 put; ++ __le32 info; ++} __attribute__((packed)); ++ ++/* ++ * kcontrol header ++ */ ++struct snd_soc_tplg_ctl_hdr { ++ __le32 size; /* in bytes of this structure */ ++ __le32 type; ++ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ __le32 access; ++ struct snd_soc_tplg_io_ops ops; ++ struct snd_soc_tplg_ctl_tlv tlv; ++} __attribute__((packed)); ++ ++/* ++ * Stream Capabilities ++ */ ++struct snd_soc_tplg_stream_caps { ++ __le32 size; /* in bytes of this structure */ ++ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */ ++ __le32 rates; /* supported rates SNDRV_PCM_RATE_* */ ++ __le32 rate_min; /* min rate */ ++ __le32 rate_max; /* max rate */ ++ __le32 channels_min; /* min channels */ ++ __le32 channels_max; /* max channels */ ++ __le32 periods_min; /* min number of periods */ ++ __le32 periods_max; /* max number of periods */ ++ __le32 period_size_min; /* min period size bytes */ ++ __le32 period_size_max; /* max period size bytes */ ++ __le32 buffer_size_min; /* min buffer size bytes */ ++ __le32 buffer_size_max; /* max buffer size bytes */ ++ __le32 sig_bits; /* number of bits of content */ ++} __attribute__((packed)); ++ ++/* ++ * FE or BE Stream configuration supported by SW/FW ++ */ ++struct snd_soc_tplg_stream { ++ __le32 size; /* in bytes of this structure */ ++ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* Name of the stream */ ++ __le64 format; /* SNDRV_PCM_FMTBIT_* */ ++ __le32 rate; /* SNDRV_PCM_RATE_* */ ++ __le32 period_bytes; /* size of period in bytes */ ++ __le32 buffer_bytes; /* size of buffer in bytes */ ++ __le32 channels; /* channels */ ++} __attribute__((packed)); ++ ++ ++/* ++ * Describes a physical link's runtime supported hardware config, ++ * i.e. hardware audio formats. ++ */ ++struct snd_soc_tplg_hw_config { ++ __le32 size; /* in bytes of this structure */ ++ __le32 id; /* unique ID - - used to match */ ++ __le32 fmt; /* SND_SOC_DAI_FORMAT_ format value */ ++ __u8 clock_gated; /* SND_SOC_TPLG_DAI_CLK_GATE_ value */ ++ __u8 invert_bclk; /* 1 for inverted BCLK, 0 for normal */ ++ __u8 invert_fsync; /* 1 for inverted frame clock, 0 for normal */ ++ __u8 bclk_master; /* SND_SOC_TPLG_BCLK_ value */ ++ __u8 fsync_master; /* SND_SOC_TPLG_FSYNC_ value */ ++ __u8 mclk_direction; /* SND_SOC_TPLG_MCLK_ value */ ++ __le16 reserved; /* for 32bit alignment */ ++ __le32 mclk_rate; /* MCLK or SYSCLK freqency in Hz */ ++ __le32 bclk_rate; /* BCLK freqency in Hz */ ++ __le32 fsync_rate; /* frame clock in Hz */ ++ __le32 tdm_slots; /* number of TDM slots in use */ ++ __le32 tdm_slot_width; /* width in bits for each slot */ ++ __le32 tx_slots; /* bit mask for active Tx slots */ ++ __le32 rx_slots; /* bit mask for active Rx slots */ ++ __le32 tx_channels; /* number of Tx channels */ ++ __le32 tx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */ ++ __le32 rx_channels; /* number of Rx channels */ ++ __le32 rx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */ ++} __attribute__((packed)); ++ ++/* ++ * Manifest. List totals for each payload type. Not used in parsing, but will ++ * be passed to the component driver before any other objects in order for any ++ * global component resource allocations. ++ * ++ * File block representation for manifest :- ++ * +-----------------------------------+----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-----------------------------------+----+ ++ * | struct snd_soc_tplg_manifest | 1 | ++ * +-----------------------------------+----+ ++ */ ++struct snd_soc_tplg_manifest { ++ __le32 size; /* in bytes of this structure */ ++ __le32 control_elems; /* number of control elements */ ++ __le32 widget_elems; /* number of widget elements */ ++ __le32 graph_elems; /* number of graph elements */ ++ __le32 pcm_elems; /* number of PCM elements */ ++ __le32 dai_link_elems; /* number of DAI link elements */ ++ __le32 dai_elems; /* number of physical DAI elements */ ++ __le32 reserved[20]; /* reserved for new ABI element types */ ++ struct snd_soc_tplg_private priv; ++} __attribute__((packed)); ++ ++/* ++ * Mixer kcontrol. ++ * ++ * File block representation for mixer kcontrol :- ++ * +-----------------------------------+----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-----------------------------------+----+ ++ * | struct snd_soc_tplg_mixer_control | N | ++ * +-----------------------------------+----+ ++ */ ++struct snd_soc_tplg_mixer_control { ++ struct snd_soc_tplg_ctl_hdr hdr; ++ __le32 size; /* in bytes of this structure */ ++ __le32 min; ++ __le32 max; ++ __le32 platform_max; ++ __le32 invert; ++ __le32 num_channels; ++ struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN]; ++ struct snd_soc_tplg_private priv; ++} __attribute__((packed)); ++ ++/* ++ * Enumerated kcontrol ++ * ++ * File block representation for enum kcontrol :- ++ * +-----------------------------------+----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-----------------------------------+----+ ++ * | struct snd_soc_tplg_enum_control | N | ++ * +-----------------------------------+----+ ++ */ ++struct snd_soc_tplg_enum_control { ++ struct snd_soc_tplg_ctl_hdr hdr; ++ __le32 size; /* in bytes of this structure */ ++ __le32 num_channels; ++ struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN]; ++ __le32 items; ++ __le32 mask; ++ __le32 count; ++ char texts[SND_SOC_TPLG_NUM_TEXTS][SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ __le32 values[SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN / 4]; ++ struct snd_soc_tplg_private priv; ++} __attribute__((packed)); ++ ++/* ++ * Bytes kcontrol ++ * ++ * File block representation for bytes kcontrol :- ++ * +-----------------------------------+----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-----------------------------------+----+ ++ * | struct snd_soc_tplg_bytes_control | N | ++ * +-----------------------------------+----+ ++ */ ++struct snd_soc_tplg_bytes_control { ++ struct snd_soc_tplg_ctl_hdr hdr; ++ __le32 size; /* in bytes of this structure */ ++ __le32 max; ++ __le32 mask; ++ __le32 base; ++ __le32 num_regs; ++ struct snd_soc_tplg_io_ops ext_ops; ++ struct snd_soc_tplg_private priv; ++} __attribute__((packed)); ++ ++/* ++ * DAPM Graph Element ++ * ++ * File block representation for DAPM graph elements :- ++ * +-------------------------------------+----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-------------------------------------+----+ ++ * | struct snd_soc_tplg_dapm_graph_elem | N | ++ * +-------------------------------------+----+ ++ */ ++struct snd_soc_tplg_dapm_graph_elem { ++ char sink[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ char control[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ char source[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++} __attribute__((packed)); ++ ++/* ++ * DAPM Widget. ++ * ++ * File block representation for DAPM widget :- ++ * +-------------------------------------+-----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-------------------------------------+-----+ ++ * | struct snd_soc_tplg_dapm_widget | N | ++ * +-------------------------------------+-----+ ++ * | struct snd_soc_tplg_enum_control | 0|1 | ++ * | struct snd_soc_tplg_mixer_control | 0|N | ++ * +-------------------------------------+-----+ ++ * ++ * Optional enum or mixer control can be appended to the end of each widget ++ * in the block. ++ */ ++struct snd_soc_tplg_dapm_widget { ++ __le32 size; /* in bytes of this structure */ ++ __le32 id; /* SND_SOC_DAPM_CTL */ ++ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ char sname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ ++ __le32 reg; /* negative reg = no direct dapm */ ++ __le32 shift; /* bits to shift */ ++ __le32 mask; /* non-shifted mask */ ++ __le32 subseq; /* sort within widget type */ ++ __le32 invert; /* invert the power bit */ ++ __le32 ignore_suspend; /* kept enabled over suspend */ ++ __le16 event_flags; ++ __le16 event_type; ++ __le32 num_kcontrols; ++ struct snd_soc_tplg_private priv; ++ /* ++ * kcontrols that relate to this widget ++ * follow here after widget private data ++ */ ++} __attribute__((packed)); ++ ++ ++/* ++ * Describes SW/FW specific features of PCM (FE DAI & DAI link). ++ * ++ * File block representation for PCM :- ++ * +-----------------------------------+-----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-----------------------------------+-----+ ++ * | struct snd_soc_tplg_pcm | N | ++ * +-----------------------------------+-----+ ++ */ ++struct snd_soc_tplg_pcm { ++ __le32 size; /* in bytes of this structure */ ++ char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ __le32 pcm_id; /* unique ID - used to match with DAI link */ ++ __le32 dai_id; /* unique ID - used to match */ ++ __le32 playback; /* supports playback mode */ ++ __le32 capture; /* supports capture mode */ ++ __le32 compress; /* 1 = compressed; 0 = PCM */ ++ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */ ++ __le32 num_streams; /* number of streams */ ++ struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */ ++ __le32 flag_mask; /* bitmask of flags to configure */ ++ __le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */ ++ struct snd_soc_tplg_private priv; ++} __attribute__((packed)); ++ ++ ++/* ++ * Describes the physical link runtime supported configs or params ++ * ++ * File block representation for physical link config :- ++ * +-----------------------------------+-----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-----------------------------------+-----+ ++ * | struct snd_soc_tplg_link_config | N | ++ * +-----------------------------------+-----+ ++ */ ++struct snd_soc_tplg_link_config { ++ __le32 size; /* in bytes of this structure */ ++ __le32 id; /* unique ID - used to match */ ++ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */ ++ char stream_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* stream name - used to match */ ++ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */ ++ __le32 num_streams; /* number of streams */ ++ struct snd_soc_tplg_hw_config hw_config[SND_SOC_TPLG_HW_CONFIG_MAX]; /* hw configs */ ++ __le32 num_hw_configs; /* number of hw configs */ ++ __le32 default_hw_config_id; /* default hw config ID for init */ ++ __le32 flag_mask; /* bitmask of flags to configure */ ++ __le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */ ++ struct snd_soc_tplg_private priv; ++} __attribute__((packed)); ++ ++/* ++ * Describes SW/FW specific features of physical DAI. ++ * It can be used to configure backend DAIs for DPCM. ++ * ++ * File block representation for physical DAI :- ++ * +-----------------------------------+-----+ ++ * | struct snd_soc_tplg_hdr | 1 | ++ * +-----------------------------------+-----+ ++ * | struct snd_soc_tplg_dai | N | ++ * +-----------------------------------+-----+ ++ */ ++struct snd_soc_tplg_dai { ++ __le32 size; /* in bytes of this structure */ ++ char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */ ++ __le32 dai_id; /* unique ID - used to match */ ++ __le32 playback; /* supports playback mode */ ++ __le32 capture; /* supports capture mode */ ++ struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */ ++ __le32 flag_mask; /* bitmask of flags to configure */ ++ __le32 flags; /* SND_SOC_TPLG_DAI_FLGBIT_* */ ++ struct snd_soc_tplg_private priv; ++} __attribute__((packed)); ++ ++/* ++ * Old version of ABI structs, supported for backward compatibility. ++ */ ++ ++/* Manifest v4 */ ++struct snd_soc_tplg_manifest_v4 { ++ __le32 size; /* in bytes of this structure */ ++ __le32 control_elems; /* number of control elements */ ++ __le32 widget_elems; /* number of widget elements */ ++ __le32 graph_elems; /* number of graph elements */ ++ __le32 pcm_elems; /* number of PCM elements */ ++ __le32 dai_link_elems; /* number of DAI link elements */ ++ struct snd_soc_tplg_private priv; ++} __packed; ++ ++/* Stream Capabilities v4 */ ++struct snd_soc_tplg_stream_caps_v4 { ++ __le32 size; /* in bytes of this structure */ ++ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */ ++ __le32 rates; /* supported rates SNDRV_PCM_RATE_* */ ++ __le32 rate_min; /* min rate */ ++ __le32 rate_max; /* max rate */ ++ __le32 channels_min; /* min channels */ ++ __le32 channels_max; /* max channels */ ++ __le32 periods_min; /* min number of periods */ ++ __le32 periods_max; /* max number of periods */ ++ __le32 period_size_min; /* min period size bytes */ ++ __le32 period_size_max; /* max period size bytes */ ++ __le32 buffer_size_min; /* min buffer size bytes */ ++ __le32 buffer_size_max; /* max buffer size bytes */ ++} __packed; ++ ++/* PCM v4 */ ++struct snd_soc_tplg_pcm_v4 { ++ __le32 size; /* in bytes of this structure */ ++ char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ __le32 pcm_id; /* unique ID - used to match with DAI link */ ++ __le32 dai_id; /* unique ID - used to match */ ++ __le32 playback; /* supports playback mode */ ++ __le32 capture; /* supports capture mode */ ++ __le32 compress; /* 1 = compressed; 0 = PCM */ ++ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */ ++ __le32 num_streams; /* number of streams */ ++ struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */ ++} __packed; ++ ++/* Physical link config v4 */ ++struct snd_soc_tplg_link_config_v4 { ++ __le32 size; /* in bytes of this structure */ ++ __le32 id; /* unique ID - used to match */ ++ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */ ++ __le32 num_streams; /* number of streams */ ++} __packed; ++ ++#endif +diff --git a/include/sound/uapi/asound.h b/include/sound/uapi/asound.h +new file mode 100644 +index 00000000..df1153ce +--- /dev/null ++++ b/include/sound/uapi/asound.h +@@ -0,0 +1,1038 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * Advanced Linux Sound Architecture - ALSA - Driver ++ * Copyright (c) 1994-2003 by Jaroslav Kysela , ++ * Abramo Bagnara ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#ifndef _UAPI__SOUND_ASOUND_H ++#define _UAPI__SOUND_ASOUND_H ++ ++#if defined(__KERNEL__) || defined(__linux__) ++#include ++#else ++#include ++#endif ++ ++#ifndef __KERNEL__ ++#include ++#include ++#endif ++ ++/* ++ * protocol version ++ */ ++ ++#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor)) ++#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff) ++#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff) ++#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff) ++#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \ ++ (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \ ++ (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \ ++ SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion))) ++ ++/**************************************************************************** ++ * * ++ * Digital audio interface * ++ * * ++ ****************************************************************************/ ++ ++struct snd_aes_iec958 { ++ unsigned char status[24]; /* AES/IEC958 channel status bits */ ++ unsigned char subcode[147]; /* AES/IEC958 subcode bits */ ++ unsigned char pad; /* nothing */ ++ unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ ++}; ++ ++/**************************************************************************** ++ * * ++ * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort * ++ * * ++ ****************************************************************************/ ++ ++struct snd_cea_861_aud_if { ++ unsigned char db1_ct_cc; /* coding type and channel count */ ++ unsigned char db2_sf_ss; /* sample frequency and size */ ++ unsigned char db3; /* not used, all zeros */ ++ unsigned char db4_ca; /* channel allocation code */ ++ unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */ ++}; ++ ++/**************************************************************************** ++ * * ++ * Section for driver hardware dependent interface - /dev/snd/hw? * ++ * * ++ ****************************************************************************/ ++ ++#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1) ++ ++enum { ++ SNDRV_HWDEP_IFACE_OPL2 = 0, ++ SNDRV_HWDEP_IFACE_OPL3, ++ SNDRV_HWDEP_IFACE_OPL4, ++ SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */ ++ SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */ ++ SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */ ++ SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */ ++ SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */ ++ SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */ ++ SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */ ++ SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */ ++ SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */ ++ SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */ ++ SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ ++ SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ ++ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ ++ SNDRV_HWDEP_IFACE_HDA, /* HD-audio */ ++ SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */ ++ SNDRV_HWDEP_IFACE_FW_DICE, /* TC DICE FireWire device */ ++ SNDRV_HWDEP_IFACE_FW_FIREWORKS, /* Echo Audio Fireworks based device */ ++ SNDRV_HWDEP_IFACE_FW_BEBOB, /* BridgeCo BeBoB based device */ ++ SNDRV_HWDEP_IFACE_FW_OXFW, /* Oxford OXFW970/971 based device */ ++ SNDRV_HWDEP_IFACE_FW_DIGI00X, /* Digidesign Digi 002/003 family */ ++ SNDRV_HWDEP_IFACE_FW_TASCAM, /* TASCAM FireWire series */ ++ SNDRV_HWDEP_IFACE_LINE6, /* Line6 USB processors */ ++ SNDRV_HWDEP_IFACE_FW_MOTU, /* MOTU FireWire series */ ++ SNDRV_HWDEP_IFACE_FW_FIREFACE, /* RME Fireface series */ ++ ++ /* Don't forget to change the following: */ ++ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE ++}; ++ ++struct snd_hwdep_info { ++ unsigned int device; /* WR: device number */ ++ int card; /* R: card number */ ++ unsigned char id[64]; /* ID (user selectable) */ ++ unsigned char name[80]; /* hwdep name */ ++ int iface; /* hwdep interface */ ++ unsigned char reserved[64]; /* reserved for future */ ++}; ++ ++/* generic DSP loader */ ++struct snd_hwdep_dsp_status { ++ unsigned int version; /* R: driver-specific version */ ++ unsigned char id[32]; /* R: driver-specific ID string */ ++ unsigned int num_dsps; /* R: number of DSP images to transfer */ ++ unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */ ++ unsigned int chip_ready; /* R: 1 = initialization finished */ ++ unsigned char reserved[16]; /* reserved for future use */ ++}; ++ ++struct snd_hwdep_dsp_image { ++ unsigned int index; /* W: DSP index */ ++ unsigned char name[64]; /* W: ID (e.g. file name) */ ++ unsigned char __user *image; /* W: binary image */ ++ size_t length; /* W: size of image in bytes */ ++ unsigned long driver_data; /* W: driver-specific data */ ++}; ++ ++#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int) ++#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info) ++#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status) ++#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image) ++ ++/***************************************************************************** ++ * * ++ * Digital Audio (PCM) interface - /dev/snd/pcm?? * ++ * * ++ *****************************************************************************/ ++ ++#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14) ++ ++typedef unsigned long snd_pcm_uframes_t; ++typedef signed long snd_pcm_sframes_t; ++ ++enum { ++ SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */ ++ SNDRV_PCM_CLASS_MULTI, /* multichannel device */ ++ SNDRV_PCM_CLASS_MODEM, /* software modem class */ ++ SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */ ++ /* Don't forget to change the following: */ ++ SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER, ++}; ++ ++enum { ++ SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */ ++ SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */ ++ /* Don't forget to change the following: */ ++ SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX, ++}; ++ ++enum { ++ SNDRV_PCM_STREAM_PLAYBACK = 0, ++ SNDRV_PCM_STREAM_CAPTURE, ++ SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE, ++}; ++ ++typedef int __bitwise snd_pcm_access_t; ++#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */ ++#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */ ++#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */ ++#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */ ++#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */ ++#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ++ ++typedef int __bitwise snd_pcm_format_t; ++#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0) ++#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1) ++#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2) ++#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3) ++#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4) ++#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5) ++#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */ ++#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */ ++#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */ ++#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */ ++#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10) ++#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11) ++#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12) ++#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13) ++#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ ++#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ ++#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ ++#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ ++#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */ ++#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */ ++#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20) ++#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21) ++#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22) ++#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23) ++#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24) ++#define SNDRV_PCM_FORMAT_S20_LE ((__force snd_pcm_format_t) 25) /* in four bytes, LSB justified */ ++#define SNDRV_PCM_FORMAT_S20_BE ((__force snd_pcm_format_t) 26) /* in four bytes, LSB justified */ ++#define SNDRV_PCM_FORMAT_U20_LE ((__force snd_pcm_format_t) 27) /* in four bytes, LSB justified */ ++#define SNDRV_PCM_FORMAT_U20_BE ((__force snd_pcm_format_t) 28) /* in four bytes, LSB justified */ ++/* gap in the numbering for a future standard linear format */ ++#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31) ++#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */ ++#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */ ++#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */ ++#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */ ++#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ ++#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */ ++#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */ ++#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */ ++#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */ ++#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */ ++#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE ++#define SNDRV_PCM_FORMAT_FIRST SNDRV_PCM_FORMAT_S8 ++ ++#ifdef SNDRV_LITTLE_ENDIAN ++#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE ++#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE ++#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE ++#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE ++#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE ++#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE ++#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE ++#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE ++#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ++#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_LE ++#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_LE ++#endif ++#ifdef SNDRV_BIG_ENDIAN ++#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE ++#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE ++#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE ++#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE ++#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE ++#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE ++#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE ++#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE ++#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ++#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_BE ++#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_BE ++#endif ++ ++typedef int __bitwise snd_pcm_subformat_t; ++#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0) ++#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD ++ ++#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */ ++#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */ ++#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */ ++#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */ ++#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */ ++#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */ ++#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */ ++#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */ ++#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */ ++#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */ ++#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */ ++#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */ ++#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */ ++#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ ++#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ ++#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */ ++#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */ ++#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */ ++#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */ ++#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ ++#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ ++ ++#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ ++#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ ++ ++ ++ ++typedef int __bitwise snd_pcm_state_t; ++#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */ ++#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */ ++#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */ ++#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */ ++#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */ ++#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */ ++#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */ ++#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */ ++#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */ ++#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED ++ ++enum { ++ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000, ++ SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000, ++ SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000, ++}; ++ ++union snd_pcm_sync_id { ++ unsigned char id[16]; ++ unsigned short id16[8]; ++ unsigned int id32[4]; ++}; ++ ++struct snd_pcm_info { ++ unsigned int device; /* RO/WR (control): device number */ ++ unsigned int subdevice; /* RO/WR (control): subdevice number */ ++ int stream; /* RO/WR (control): stream direction */ ++ int card; /* R: card number */ ++ unsigned char id[64]; /* ID (user selectable) */ ++ unsigned char name[80]; /* name of this device */ ++ unsigned char subname[32]; /* subdevice name */ ++ int dev_class; /* SNDRV_PCM_CLASS_* */ ++ int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ ++ unsigned int subdevices_count; ++ unsigned int subdevices_avail; ++ union snd_pcm_sync_id sync; /* hardware synchronization ID */ ++ unsigned char reserved[64]; /* reserved for future... */ ++}; ++ ++typedef int snd_pcm_hw_param_t; ++#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */ ++#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */ ++#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */ ++#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS ++#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT ++ ++#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */ ++#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */ ++#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */ ++#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */ ++#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between ++ * interrupts in us ++ */ ++#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between ++ * interrupts ++ */ ++#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between ++ * interrupts ++ */ ++#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per ++ * buffer ++ */ ++#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer ++ * in us ++ */ ++#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */ ++#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */ ++#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */ ++#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS ++#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME ++ ++#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */ ++#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */ ++#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */ ++ ++struct snd_interval { ++ unsigned int min, max; ++ unsigned int openmin:1, ++ openmax:1, ++ integer:1, ++ empty:1; ++}; ++ ++#define SNDRV_MASK_MAX 256 ++ ++struct snd_mask { ++ __u32 bits[(SNDRV_MASK_MAX+31)/32]; ++}; ++ ++struct snd_pcm_hw_params { ++ unsigned int flags; ++ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - ++ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; ++ struct snd_mask mres[5]; /* reserved masks */ ++ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - ++ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; ++ struct snd_interval ires[9]; /* reserved intervals */ ++ unsigned int rmask; /* W: requested masks */ ++ unsigned int cmask; /* R: changed masks */ ++ unsigned int info; /* R: Info flags for returned setup */ ++ unsigned int msbits; /* R: used most significant bits */ ++ unsigned int rate_num; /* R: rate numerator */ ++ unsigned int rate_den; /* R: rate denominator */ ++ snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ ++ unsigned char reserved[64]; /* reserved for future */ ++}; ++ ++enum { ++ SNDRV_PCM_TSTAMP_NONE = 0, ++ SNDRV_PCM_TSTAMP_ENABLE, ++ SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE, ++}; ++ ++struct snd_pcm_sw_params { ++ int tstamp_mode; /* timestamp mode */ ++ unsigned int period_step; ++ unsigned int sleep_min; /* min ticks to sleep */ ++ snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */ ++ snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */ ++ snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */ ++ snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */ ++ snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ ++ snd_pcm_uframes_t silence_size; /* silence block size */ ++ snd_pcm_uframes_t boundary; /* pointers wrap point */ ++ unsigned int proto; /* protocol version */ ++ unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */ ++ unsigned char reserved[56]; /* reserved for future */ ++}; ++ ++struct snd_pcm_channel_info { ++ unsigned int channel; ++ __kernel_off_t offset; /* mmap offset */ ++ unsigned int first; /* offset to first sample in bits */ ++ unsigned int step; /* samples distance in bits */ ++}; ++ ++enum { ++ /* ++ * first definition for backwards compatibility only, ++ * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else ++ */ ++ SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0, ++ ++ /* timestamp definitions */ ++ SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */ ++ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */ ++ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */ ++ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */ ++ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */ ++ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED ++}; ++ ++struct snd_pcm_status { ++ snd_pcm_state_t state; /* stream state */ ++ struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */ ++ struct timespec tstamp; /* reference timestamp */ ++ snd_pcm_uframes_t appl_ptr; /* appl ptr */ ++ snd_pcm_uframes_t hw_ptr; /* hw ptr */ ++ snd_pcm_sframes_t delay; /* current delay in frames */ ++ snd_pcm_uframes_t avail; /* number of frames available */ ++ snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */ ++ snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */ ++ snd_pcm_state_t suspended_state; /* suspended stream state */ ++ __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */ ++ struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */ ++ struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */ ++ __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */ ++ unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */ ++}; ++ ++struct snd_pcm_mmap_status { ++ snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */ ++ int pad1; /* Needed for 64 bit alignment */ ++ snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */ ++ struct timespec tstamp; /* Timestamp */ ++ snd_pcm_state_t suspended_state; /* RO: suspended stream state */ ++ struct timespec audio_tstamp; /* from sample counter or wall clock */ ++}; ++ ++struct snd_pcm_mmap_control { ++ snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */ ++ snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */ ++}; ++ ++#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */ ++#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */ ++#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */ ++ ++struct snd_pcm_sync_ptr { ++ unsigned int flags; ++ union { ++ struct snd_pcm_mmap_status status; ++ unsigned char reserved[64]; ++ } s; ++ union { ++ struct snd_pcm_mmap_control control; ++ unsigned char reserved[64]; ++ } c; ++}; ++ ++struct snd_xferi { ++ snd_pcm_sframes_t result; ++ void __user *buf; ++ snd_pcm_uframes_t frames; ++}; ++ ++struct snd_xfern { ++ snd_pcm_sframes_t result; ++ void __user * __user *bufs; ++ snd_pcm_uframes_t frames; ++}; ++ ++enum { ++ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */ ++ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */ ++ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */ ++ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, ++}; ++ ++/* channel positions */ ++enum { ++ SNDRV_CHMAP_UNKNOWN = 0, ++ SNDRV_CHMAP_NA, /* N/A, silent */ ++ SNDRV_CHMAP_MONO, /* mono stream */ ++ /* this follows the alsa-lib mixer channel value + 3 */ ++ SNDRV_CHMAP_FL, /* front left */ ++ SNDRV_CHMAP_FR, /* front right */ ++ SNDRV_CHMAP_RL, /* rear left */ ++ SNDRV_CHMAP_RR, /* rear right */ ++ SNDRV_CHMAP_FC, /* front center */ ++ SNDRV_CHMAP_LFE, /* LFE */ ++ SNDRV_CHMAP_SL, /* side left */ ++ SNDRV_CHMAP_SR, /* side right */ ++ SNDRV_CHMAP_RC, /* rear center */ ++ /* new definitions */ ++ SNDRV_CHMAP_FLC, /* front left center */ ++ SNDRV_CHMAP_FRC, /* front right center */ ++ SNDRV_CHMAP_RLC, /* rear left center */ ++ SNDRV_CHMAP_RRC, /* rear right center */ ++ SNDRV_CHMAP_FLW, /* front left wide */ ++ SNDRV_CHMAP_FRW, /* front right wide */ ++ SNDRV_CHMAP_FLH, /* front left high */ ++ SNDRV_CHMAP_FCH, /* front center high */ ++ SNDRV_CHMAP_FRH, /* front right high */ ++ SNDRV_CHMAP_TC, /* top center */ ++ SNDRV_CHMAP_TFL, /* top front left */ ++ SNDRV_CHMAP_TFR, /* top front right */ ++ SNDRV_CHMAP_TFC, /* top front center */ ++ SNDRV_CHMAP_TRL, /* top rear left */ ++ SNDRV_CHMAP_TRR, /* top rear right */ ++ SNDRV_CHMAP_TRC, /* top rear center */ ++ /* new definitions for UAC2 */ ++ SNDRV_CHMAP_TFLC, /* top front left center */ ++ SNDRV_CHMAP_TFRC, /* top front right center */ ++ SNDRV_CHMAP_TSL, /* top side left */ ++ SNDRV_CHMAP_TSR, /* top side right */ ++ SNDRV_CHMAP_LLFE, /* left LFE */ ++ SNDRV_CHMAP_RLFE, /* right LFE */ ++ SNDRV_CHMAP_BC, /* bottom center */ ++ SNDRV_CHMAP_BLC, /* bottom left center */ ++ SNDRV_CHMAP_BRC, /* bottom right center */ ++ SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC, ++}; ++ ++#define SNDRV_CHMAP_POSITION_MASK 0xffff ++#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) ++#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16) ++ ++#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) ++#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) ++#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) ++#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) ++#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int) ++#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) ++#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) ++#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) ++#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params) ++#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status) ++#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t) ++#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) ++#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr) ++#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status) ++#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info) ++#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) ++#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) ++#define SNDRV_PCM_IOCTL_START _IO('A', 0x42) ++#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43) ++#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44) ++#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int) ++#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t) ++#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47) ++#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48) ++#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t) ++#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi) ++#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi) ++#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern) ++#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern) ++#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int) ++#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61) ++ ++/***************************************************************************** ++ * * ++ * MIDI v1.0 interface * ++ * * ++ *****************************************************************************/ ++ ++/* ++ * Raw MIDI section - /dev/snd/midi?? ++ */ ++ ++#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0) ++ ++enum { ++ SNDRV_RAWMIDI_STREAM_OUTPUT = 0, ++ SNDRV_RAWMIDI_STREAM_INPUT, ++ SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT, ++}; ++ ++#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001 ++#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002 ++#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004 ++ ++struct snd_rawmidi_info { ++ unsigned int device; /* RO/WR (control): device number */ ++ unsigned int subdevice; /* RO/WR (control): subdevice number */ ++ int stream; /* WR: stream */ ++ int card; /* R: card number */ ++ unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */ ++ unsigned char id[64]; /* ID (user selectable) */ ++ unsigned char name[80]; /* name of device */ ++ unsigned char subname[32]; /* name of active or selected subdevice */ ++ unsigned int subdevices_count; ++ unsigned int subdevices_avail; ++ unsigned char reserved[64]; /* reserved for future use */ ++}; ++ ++struct snd_rawmidi_params { ++ int stream; ++ size_t buffer_size; /* queue size in bytes */ ++ size_t avail_min; /* minimum avail bytes for wakeup */ ++ unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ ++ unsigned char reserved[16]; /* reserved for future use */ ++}; ++ ++struct snd_rawmidi_status { ++ int stream; ++ struct timespec tstamp; /* Timestamp */ ++ size_t avail; /* available bytes */ ++ size_t xruns; /* count of overruns since last status (in bytes) */ ++ unsigned char reserved[16]; /* reserved for future use */ ++}; ++ ++#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) ++#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info) ++#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params) ++#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status) ++#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) ++#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int) ++ ++/* ++ * Timer section - /dev/snd/timer ++ */ ++ ++#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6) ++ ++enum { ++ SNDRV_TIMER_CLASS_NONE = -1, ++ SNDRV_TIMER_CLASS_SLAVE = 0, ++ SNDRV_TIMER_CLASS_GLOBAL, ++ SNDRV_TIMER_CLASS_CARD, ++ SNDRV_TIMER_CLASS_PCM, ++ SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM, ++}; ++ ++/* slave timer classes */ ++enum { ++ SNDRV_TIMER_SCLASS_NONE = 0, ++ SNDRV_TIMER_SCLASS_APPLICATION, ++ SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */ ++ SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */ ++ SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER, ++}; ++ ++/* global timers (device member) */ ++#define SNDRV_TIMER_GLOBAL_SYSTEM 0 ++#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */ ++#define SNDRV_TIMER_GLOBAL_HPET 2 ++#define SNDRV_TIMER_GLOBAL_HRTIMER 3 ++ ++/* info flags */ ++#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */ ++ ++struct snd_timer_id { ++ int dev_class; ++ int dev_sclass; ++ int card; ++ int device; ++ int subdevice; ++}; ++ ++struct snd_timer_ginfo { ++ struct snd_timer_id tid; /* requested timer ID */ ++ unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ ++ int card; /* card number */ ++ unsigned char id[64]; /* timer identification */ ++ unsigned char name[80]; /* timer name */ ++ unsigned long reserved0; /* reserved for future use */ ++ unsigned long resolution; /* average period resolution in ns */ ++ unsigned long resolution_min; /* minimal period resolution in ns */ ++ unsigned long resolution_max; /* maximal period resolution in ns */ ++ unsigned int clients; /* active timer clients */ ++ unsigned char reserved[32]; ++}; ++ ++struct snd_timer_gparams { ++ struct snd_timer_id tid; /* requested timer ID */ ++ unsigned long period_num; /* requested precise period duration (in seconds) - numerator */ ++ unsigned long period_den; /* requested precise period duration (in seconds) - denominator */ ++ unsigned char reserved[32]; ++}; ++ ++struct snd_timer_gstatus { ++ struct snd_timer_id tid; /* requested timer ID */ ++ unsigned long resolution; /* current period resolution in ns */ ++ unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */ ++ unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */ ++ unsigned char reserved[32]; ++}; ++ ++struct snd_timer_select { ++ struct snd_timer_id id; /* bind to timer ID */ ++ unsigned char reserved[32]; /* reserved */ ++}; ++ ++struct snd_timer_info { ++ unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ ++ int card; /* card number */ ++ unsigned char id[64]; /* timer identificator */ ++ unsigned char name[80]; /* timer name */ ++ unsigned long reserved0; /* reserved for future use */ ++ unsigned long resolution; /* average period resolution in ns */ ++ unsigned char reserved[64]; /* reserved */ ++}; ++ ++#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */ ++#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */ ++#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */ ++ ++struct snd_timer_params { ++ unsigned int flags; /* flags - SNDRV_TIMER_PSFLG_* */ ++ unsigned int ticks; /* requested resolution in ticks */ ++ unsigned int queue_size; /* total size of queue (32-1024) */ ++ unsigned int reserved0; /* reserved, was: failure locations */ ++ unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */ ++ unsigned char reserved[60]; /* reserved */ ++}; ++ ++struct snd_timer_status { ++ struct timespec tstamp; /* Timestamp - last update */ ++ unsigned int resolution; /* current period resolution in ns */ ++ unsigned int lost; /* counter of master tick lost */ ++ unsigned int overrun; /* count of read queue overruns */ ++ unsigned int queue; /* used queue size */ ++ unsigned char reserved[64]; /* reserved */ ++}; ++ ++#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) ++#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id) ++#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int) ++#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo) ++#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams) ++#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus) ++#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select) ++#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info) ++#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params) ++#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status) ++/* The following four ioctls are changed since 1.0.9 due to confliction */ ++#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0) ++#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1) ++#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) ++#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3) ++ ++struct snd_timer_read { ++ unsigned int resolution; ++ unsigned int ticks; ++}; ++ ++enum { ++ SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */ ++ SNDRV_TIMER_EVENT_TICK, /* val = ticks */ ++ SNDRV_TIMER_EVENT_START, /* val = resolution in ns */ ++ SNDRV_TIMER_EVENT_STOP, /* val = 0 */ ++ SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */ ++ SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */ ++ SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */ ++ SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */ ++ SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */ ++ /* master timer events for slave timer instances */ ++ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10, ++ SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10, ++ SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10, ++ SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10, ++ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10, ++ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10, ++}; ++ ++struct snd_timer_tread { ++ int event; ++ struct timespec tstamp; ++ unsigned int val; ++}; ++ ++/**************************************************************************** ++ * * ++ * Section for driver control interface - /dev/snd/control? * ++ * * ++ ****************************************************************************/ ++ ++#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7) ++ ++struct snd_ctl_card_info { ++ int card; /* card number */ ++ int pad; /* reserved for future (was type) */ ++ unsigned char id[16]; /* ID of card (user selectable) */ ++ unsigned char driver[16]; /* Driver name */ ++ unsigned char name[32]; /* Short name of soundcard */ ++ unsigned char longname[80]; /* name + info text about soundcard */ ++ unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */ ++ unsigned char mixername[80]; /* visual mixer identification */ ++ unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */ ++}; ++ ++typedef int __bitwise snd_ctl_elem_type_t; ++#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */ ++#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */ ++#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */ ++#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */ ++#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */ ++#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */ ++#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */ ++#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64 ++ ++typedef int __bitwise snd_ctl_elem_iface_t; ++#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */ ++#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */ ++#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */ ++#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */ ++#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */ ++#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */ ++#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */ ++#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER ++ ++#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0) ++#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1) ++#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE) ++#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */ ++#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */ ++#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */ ++#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */ ++#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) ++#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */ ++#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */ ++#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */ ++#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */ ++#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */ ++#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */ ++/* bits 30 and 31 are obsoleted (for indirect access) */ ++ ++/* for further details see the ACPI and PCI power management specification */ ++#define SNDRV_CTL_POWER_D0 0x0000 /* full On */ ++#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */ ++#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */ ++#define SNDRV_CTL_POWER_D3 0x0300 /* Off */ ++#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */ ++#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */ ++ ++#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 ++ ++struct snd_ctl_elem_id { ++ unsigned int numid; /* numeric identifier, zero = invalid */ ++ snd_ctl_elem_iface_t iface; /* interface identifier */ ++ unsigned int device; /* device/client number */ ++ unsigned int subdevice; /* subdevice (substream) number */ ++ unsigned char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* ASCII name of item */ ++ unsigned int index; /* index of item */ ++}; ++ ++struct snd_ctl_elem_list { ++ unsigned int offset; /* W: first element ID to get */ ++ unsigned int space; /* W: count of element IDs to get */ ++ unsigned int used; /* R: count of element IDs set */ ++ unsigned int count; /* R: count of all elements */ ++ struct snd_ctl_elem_id __user *pids; /* R: IDs */ ++ unsigned char reserved[50]; ++}; ++ ++struct snd_ctl_elem_info { ++ struct snd_ctl_elem_id id; /* W: element ID */ ++ snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ ++ unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ ++ unsigned int count; /* count of values */ ++ __kernel_pid_t owner; /* owner's PID of this control */ ++ union { ++ struct { ++ long min; /* R: minimum value */ ++ long max; /* R: maximum value */ ++ long step; /* R: step (0 variable) */ ++ } integer; ++ struct { ++ long long min; /* R: minimum value */ ++ long long max; /* R: maximum value */ ++ long long step; /* R: step (0 variable) */ ++ } integer64; ++ struct { ++ unsigned int items; /* R: number of items */ ++ unsigned int item; /* W: item number */ ++ char name[64]; /* R: value name */ ++ __u64 names_ptr; /* W: names list (ELEM_ADD only) */ ++ unsigned int names_length; ++ } enumerated; ++ unsigned char reserved[128]; ++ } value; ++ union { ++ unsigned short d[4]; /* dimensions */ ++ unsigned short *d_ptr; /* indirect - obsoleted */ ++ } dimen; ++ unsigned char reserved[64-4*sizeof(unsigned short)]; ++}; ++ ++struct snd_ctl_elem_value { ++ struct snd_ctl_elem_id id; /* W: element ID */ ++ unsigned int indirect: 1; /* W: indirect access - obsoleted */ ++ union { ++ union { ++ long value[128]; ++ long *value_ptr; /* obsoleted */ ++ } integer; ++ union { ++ long long value[64]; ++ long long *value_ptr; /* obsoleted */ ++ } integer64; ++ union { ++ unsigned int item[128]; ++ unsigned int *item_ptr; /* obsoleted */ ++ } enumerated; ++ union { ++ unsigned char data[512]; ++ unsigned char *data_ptr; /* obsoleted */ ++ } bytes; ++ struct snd_aes_iec958 iec958; ++ } value; /* RO */ ++ struct timespec tstamp; ++ unsigned char reserved[128-sizeof(struct timespec)]; ++}; ++ ++struct snd_ctl_tlv { ++ unsigned int numid; /* control element numeric identification */ ++ unsigned int length; /* in bytes aligned to 4 */ ++ unsigned int tlv[0]; /* first TLV */ ++}; ++ ++#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) ++#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info) ++#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list) ++#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info) ++#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value) ++#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value) ++#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id) ++#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id) ++#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int) ++#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info) ++#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info) ++#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id) ++#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv) ++#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv) ++#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv) ++#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int) ++#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info) ++#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int) ++#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info) ++#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int) ++#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int) ++#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info) ++#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int) ++#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int) ++#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int) ++ ++/* ++ * Read interface. ++ */ ++ ++enum sndrv_ctl_event_type { ++ SNDRV_CTL_EVENT_ELEM = 0, ++ SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM, ++}; ++ ++#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */ ++#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */ ++#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */ ++#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */ ++#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */ ++ ++struct snd_ctl_event { ++ int type; /* event type - SNDRV_CTL_EVENT_* */ ++ union { ++ struct { ++ unsigned int mask; ++ struct snd_ctl_elem_id id; ++ } elem; ++ unsigned char data8[60]; ++ } data; ++}; ++ ++/* ++ * Control names ++ */ ++ ++#define SNDRV_CTL_NAME_NONE "" ++#define SNDRV_CTL_NAME_PLAYBACK "Playback " ++#define SNDRV_CTL_NAME_CAPTURE "Capture " ++ ++#define SNDRV_CTL_NAME_IEC958_NONE "" ++#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch" ++#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume" ++#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default" ++#define SNDRV_CTL_NAME_IEC958_MASK "Mask" ++#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask" ++#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask" ++#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream" ++#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what ++ ++#endif /* _UAPI__SOUND_ASOUND_H */ +diff --git a/include/sound/uapi/asound_fm.h b/include/sound/uapi/asound_fm.h +new file mode 100644 +index 00000000..8471f404 +--- /dev/null ++++ b/include/sound/uapi/asound_fm.h +@@ -0,0 +1,135 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++#ifndef __SOUND_ASOUND_FM_H ++#define __SOUND_ASOUND_FM_H ++ ++/* ++ * Advanced Linux Sound Architecture - ALSA ++ * ++ * Interface file between ALSA driver & user space ++ * Copyright (c) 1994-98 by Jaroslav Kysela , ++ * 4Front Technologies ++ * ++ * Direct FM control ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#define SNDRV_DM_FM_MODE_OPL2 0x00 ++#define SNDRV_DM_FM_MODE_OPL3 0x01 ++ ++struct snd_dm_fm_info { ++ unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */ ++ unsigned char rhythm; /* percussion mode flag */ ++}; ++ ++/* ++ * Data structure composing an FM "note" or sound event. ++ */ ++ ++struct snd_dm_fm_voice { ++ unsigned char op; /* operator cell (0 or 1) */ ++ unsigned char voice; /* FM voice (0 to 17) */ ++ ++ unsigned char am; /* amplitude modulation */ ++ unsigned char vibrato; /* vibrato effect */ ++ unsigned char do_sustain; /* sustain phase */ ++ unsigned char kbd_scale; /* keyboard scaling */ ++ unsigned char harmonic; /* 4 bits: harmonic and multiplier */ ++ unsigned char scale_level; /* 2 bits: decrease output freq rises */ ++ unsigned char volume; /* 6 bits: volume */ ++ ++ unsigned char attack; /* 4 bits: attack rate */ ++ unsigned char decay; /* 4 bits: decay rate */ ++ unsigned char sustain; /* 4 bits: sustain level */ ++ unsigned char release; /* 4 bits: release rate */ ++ ++ unsigned char feedback; /* 3 bits: feedback for op0 */ ++ unsigned char connection; /* 0 for serial, 1 for parallel */ ++ unsigned char left; /* stereo left */ ++ unsigned char right; /* stereo right */ ++ unsigned char waveform; /* 3 bits: waveform shape */ ++}; ++ ++/* ++ * This describes an FM note by its voice, octave, frequency number (10bit) ++ * and key on/off. ++ */ ++ ++struct snd_dm_fm_note { ++ unsigned char voice; /* 0-17 voice channel */ ++ unsigned char octave; /* 3 bits: what octave to play */ ++ unsigned int fnum; /* 10 bits: frequency number */ ++ unsigned char key_on; /* set for active, clear for silent */ ++}; ++ ++/* ++ * FM parameters that apply globally to all voices, and thus are not "notes" ++ */ ++ ++struct snd_dm_fm_params { ++ unsigned char am_depth; /* amplitude modulation depth (1=hi) */ ++ unsigned char vib_depth; /* vibrato depth (1=hi) */ ++ unsigned char kbd_split; /* keyboard split */ ++ unsigned char rhythm; /* percussion mode select */ ++ ++ /* This block is the percussion instrument data */ ++ unsigned char bass; ++ unsigned char snare; ++ unsigned char tomtom; ++ unsigned char cymbal; ++ unsigned char hihat; ++}; ++ ++/* ++ * FM mode ioctl settings ++ */ ++ ++#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, struct snd_dm_fm_info) ++#define SNDRV_DM_FM_IOCTL_RESET _IO ('H', 0x21) ++#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, struct snd_dm_fm_note) ++#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, struct snd_dm_fm_voice) ++#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, struct snd_dm_fm_params) ++#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int) ++/* for OPL3 only */ ++#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int) ++/* SBI patch management */ ++#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES _IO ('H', 0x40) ++ ++#define SNDRV_DM_FM_OSS_IOCTL_RESET 0x20 ++#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21 ++#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22 ++#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23 ++#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24 ++#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25 ++ ++/* ++ * Patch Record - fixed size for write ++ */ ++ ++#define FM_KEY_SBI "SBI\032" ++#define FM_KEY_2OP "2OP\032" ++#define FM_KEY_4OP "4OP\032" ++ ++struct sbi_patch { ++ unsigned char prog; ++ unsigned char bank; ++ char key[4]; ++ char name[25]; ++ char extension[7]; ++ unsigned char data[32]; ++}; ++ ++#endif /* __SOUND_ASOUND_FM_H */ +diff --git a/include/sound/uapi/emu10k1.h b/include/sound/uapi/emu10k1.h +new file mode 100644 +index 00000000..c1150e4d +--- /dev/null ++++ b/include/sound/uapi/emu10k1.h +@@ -0,0 +1,395 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * Copyright (c) by Jaroslav Kysela , ++ * Creative Labs, Inc. ++ * Definitions for EMU10K1 (SB Live!) chips ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++#ifndef _UAPI__SOUND_EMU10K1_H ++#define _UAPI__SOUND_EMU10K1_H ++ ++/* ++ * ---- FX8010 ---- ++ */ ++ ++#define EMU10K1_CARD_CREATIVE 0x00000000 ++#define EMU10K1_CARD_EMUAPS 0x00000001 ++ ++#define EMU10K1_FX8010_PCM_COUNT 8 ++ ++/* ++ * Following definition is copied from linux/types.h to support compiling ++ * this header file in userspace since they are not generally available for ++ * uapi headers. ++ */ ++#define __EMU10K1_DECLARE_BITMAP(name,bits) \ ++ unsigned long name[(bits) / (sizeof(unsigned long) * 8)] ++ ++/* instruction set */ ++#define iMAC0 0x00 /* R = A + (X * Y >> 31) ; saturation */ ++#define iMAC1 0x01 /* R = A + (-X * Y >> 31) ; saturation */ ++#define iMAC2 0x02 /* R = A + (X * Y >> 31) ; wraparound */ ++#define iMAC3 0x03 /* R = A + (-X * Y >> 31) ; wraparound */ ++#define iMACINT0 0x04 /* R = A + X * Y ; saturation */ ++#define iMACINT1 0x05 /* R = A + X * Y ; wraparound (31-bit) */ ++#define iACC3 0x06 /* R = A + X + Y ; saturation */ ++#define iMACMV 0x07 /* R = A, acc += X * Y >> 31 */ ++#define iANDXOR 0x08 /* R = (A & X) ^ Y */ ++#define iTSTNEG 0x09 /* R = (A >= Y) ? X : ~X */ ++#define iLIMITGE 0x0a /* R = (A >= Y) ? X : Y */ ++#define iLIMITLT 0x0b /* R = (A < Y) ? X : Y */ ++#define iLOG 0x0c /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */ ++#define iEXP 0x0d /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */ ++#define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */ ++#define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */ ++ ++/* GPRs */ ++#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */ ++#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */ ++#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */ ++#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */ ++ /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */ ++ ++#define C_00000000 0x40 ++#define C_00000001 0x41 ++#define C_00000002 0x42 ++#define C_00000003 0x43 ++#define C_00000004 0x44 ++#define C_00000008 0x45 ++#define C_00000010 0x46 ++#define C_00000020 0x47 ++#define C_00000100 0x48 ++#define C_00010000 0x49 ++#define C_00080000 0x4a ++#define C_10000000 0x4b ++#define C_20000000 0x4c ++#define C_40000000 0x4d ++#define C_80000000 0x4e ++#define C_7fffffff 0x4f ++#define C_ffffffff 0x50 ++#define C_fffffffe 0x51 ++#define C_c0000000 0x52 ++#define C_4f1bbcdc 0x53 ++#define C_5a7ef9db 0x54 ++#define C_00100000 0x55 /* ?? */ ++#define GPR_ACCU 0x56 /* ACCUM, accumulator */ ++#define GPR_COND 0x57 /* CCR, condition register */ ++#define GPR_NOISE0 0x58 /* noise source */ ++#define GPR_NOISE1 0x59 /* noise source */ ++#define GPR_IRQ 0x5a /* IRQ register */ ++#define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */ ++#define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */ ++#define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ ++#define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ ++#define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ ++#define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ ++ ++#define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ ++#define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ ++#define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ ++#define A_ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ ++#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ ++#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ ++ ++#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */ ++#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */ ++#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */ ++#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */ ++#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */ ++#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */ ++#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */ ++#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */ ++#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */ ++#define A_GPR(x) (A_FXGPREGBASE + (x)) ++ ++/* cc_reg constants */ ++#define CC_REG_NORMALIZED C_00000001 ++#define CC_REG_BORROW C_00000002 ++#define CC_REG_MINUS C_00000004 ++#define CC_REG_ZERO C_00000008 ++#define CC_REG_SATURATE C_00000010 ++#define CC_REG_NONZERO C_00000100 ++ ++/* FX buses */ ++#define FXBUS_PCM_LEFT 0x00 ++#define FXBUS_PCM_RIGHT 0x01 ++#define FXBUS_PCM_LEFT_REAR 0x02 ++#define FXBUS_PCM_RIGHT_REAR 0x03 ++#define FXBUS_MIDI_LEFT 0x04 ++#define FXBUS_MIDI_RIGHT 0x05 ++#define FXBUS_PCM_CENTER 0x06 ++#define FXBUS_PCM_LFE 0x07 ++#define FXBUS_PCM_LEFT_FRONT 0x08 ++#define FXBUS_PCM_RIGHT_FRONT 0x09 ++#define FXBUS_MIDI_REVERB 0x0c ++#define FXBUS_MIDI_CHORUS 0x0d ++#define FXBUS_PCM_LEFT_SIDE 0x0e ++#define FXBUS_PCM_RIGHT_SIDE 0x0f ++#define FXBUS_PT_LEFT 0x14 ++#define FXBUS_PT_RIGHT 0x15 ++ ++/* Inputs */ ++#define EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */ ++#define EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */ ++#define EXTIN_SPDIF_CD_L 0x02 /* internal S/PDIF CD - onboard - left */ ++#define EXTIN_SPDIF_CD_R 0x03 /* internal S/PDIF CD - onboard - right */ ++#define EXTIN_ZOOM_L 0x04 /* Zoom Video I2S - left */ ++#define EXTIN_ZOOM_R 0x05 /* Zoom Video I2S - right */ ++#define EXTIN_TOSLINK_L 0x06 /* LiveDrive - TOSLink Optical - left */ ++#define EXTIN_TOSLINK_R 0x07 /* LiveDrive - TOSLink Optical - right */ ++#define EXTIN_LINE1_L 0x08 /* LiveDrive - Line/Mic 1 - left */ ++#define EXTIN_LINE1_R 0x09 /* LiveDrive - Line/Mic 1 - right */ ++#define EXTIN_COAX_SPDIF_L 0x0a /* LiveDrive - Coaxial S/PDIF - left */ ++#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */ ++#define EXTIN_LINE2_L 0x0c /* LiveDrive - Line/Mic 2 - left */ ++#define EXTIN_LINE2_R 0x0d /* LiveDrive - Line/Mic 2 - right */ ++ ++/* Outputs */ ++#define EXTOUT_AC97_L 0x00 /* AC'97 playback channel - left */ ++#define EXTOUT_AC97_R 0x01 /* AC'97 playback channel - right */ ++#define EXTOUT_TOSLINK_L 0x02 /* LiveDrive - TOSLink Optical - left */ ++#define EXTOUT_TOSLINK_R 0x03 /* LiveDrive - TOSLink Optical - right */ ++#define EXTOUT_AC97_CENTER 0x04 /* SB Live 5.1 - center */ ++#define EXTOUT_AC97_LFE 0x05 /* SB Live 5.1 - LFE */ ++#define EXTOUT_HEADPHONE_L 0x06 /* LiveDrive - Headphone - left */ ++#define EXTOUT_HEADPHONE_R 0x07 /* LiveDrive - Headphone - right */ ++#define EXTOUT_REAR_L 0x08 /* Rear channel - left */ ++#define EXTOUT_REAR_R 0x09 /* Rear channel - right */ ++#define EXTOUT_ADC_CAP_L 0x0a /* ADC Capture buffer - left */ ++#define EXTOUT_ADC_CAP_R 0x0b /* ADC Capture buffer - right */ ++#define EXTOUT_MIC_CAP 0x0c /* MIC Capture buffer */ ++#define EXTOUT_AC97_REAR_L 0x0d /* SB Live 5.1 (c) 2003 - Rear Left */ ++#define EXTOUT_AC97_REAR_R 0x0e /* SB Live 5.1 (c) 2003 - Rear Right */ ++#define EXTOUT_ACENTER 0x11 /* Analog Center */ ++#define EXTOUT_ALFE 0x12 /* Analog LFE */ ++ ++/* Audigy Inputs */ ++#define A_EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */ ++#define A_EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */ ++#define A_EXTIN_SPDIF_CD_L 0x02 /* digital CD left */ ++#define A_EXTIN_SPDIF_CD_R 0x03 /* digital CD left */ ++#define A_EXTIN_OPT_SPDIF_L 0x04 /* audigy drive Optical SPDIF - left */ ++#define A_EXTIN_OPT_SPDIF_R 0x05 /* right */ ++#define A_EXTIN_LINE2_L 0x08 /* audigy drive line2/mic2 - left */ ++#define A_EXTIN_LINE2_R 0x09 /* right */ ++#define A_EXTIN_ADC_L 0x0a /* Philips ADC - left */ ++#define A_EXTIN_ADC_R 0x0b /* right */ ++#define A_EXTIN_AUX2_L 0x0c /* audigy drive aux2 - left */ ++#define A_EXTIN_AUX2_R 0x0d /* - right */ ++ ++/* Audigiy Outputs */ ++#define A_EXTOUT_FRONT_L 0x00 /* digital front left */ ++#define A_EXTOUT_FRONT_R 0x01 /* right */ ++#define A_EXTOUT_CENTER 0x02 /* digital front center */ ++#define A_EXTOUT_LFE 0x03 /* digital front lfe */ ++#define A_EXTOUT_HEADPHONE_L 0x04 /* headphone audigy drive left */ ++#define A_EXTOUT_HEADPHONE_R 0x05 /* right */ ++#define A_EXTOUT_REAR_L 0x06 /* digital rear left */ ++#define A_EXTOUT_REAR_R 0x07 /* right */ ++#define A_EXTOUT_AFRONT_L 0x08 /* analog front left */ ++#define A_EXTOUT_AFRONT_R 0x09 /* right */ ++#define A_EXTOUT_ACENTER 0x0a /* analog center */ ++#define A_EXTOUT_ALFE 0x0b /* analog LFE */ ++#define A_EXTOUT_ASIDE_L 0x0c /* analog side left - Audigy 2 ZS */ ++#define A_EXTOUT_ASIDE_R 0x0d /* right - Audigy 2 ZS */ ++#define A_EXTOUT_AREAR_L 0x0e /* analog rear left */ ++#define A_EXTOUT_AREAR_R 0x0f /* right */ ++#define A_EXTOUT_AC97_L 0x10 /* AC97 left (front) */ ++#define A_EXTOUT_AC97_R 0x11 /* right */ ++#define A_EXTOUT_ADC_CAP_L 0x16 /* ADC capture buffer left */ ++#define A_EXTOUT_ADC_CAP_R 0x17 /* right */ ++#define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */ ++ ++/* Audigy constants */ ++#define A_C_00000000 0xc0 ++#define A_C_00000001 0xc1 ++#define A_C_00000002 0xc2 ++#define A_C_00000003 0xc3 ++#define A_C_00000004 0xc4 ++#define A_C_00000008 0xc5 ++#define A_C_00000010 0xc6 ++#define A_C_00000020 0xc7 ++#define A_C_00000100 0xc8 ++#define A_C_00010000 0xc9 ++#define A_C_00000800 0xca ++#define A_C_10000000 0xcb ++#define A_C_20000000 0xcc ++#define A_C_40000000 0xcd ++#define A_C_80000000 0xce ++#define A_C_7fffffff 0xcf ++#define A_C_ffffffff 0xd0 ++#define A_C_fffffffe 0xd1 ++#define A_C_c0000000 0xd2 ++#define A_C_4f1bbcdc 0xd3 ++#define A_C_5a7ef9db 0xd4 ++#define A_C_00100000 0xd5 ++#define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */ ++#define A_GPR_COND 0xd7 /* CCR, condition register */ ++#define A_GPR_NOISE0 0xd8 /* noise source */ ++#define A_GPR_NOISE1 0xd9 /* noise source */ ++#define A_GPR_IRQ 0xda /* IRQ register */ ++#define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */ ++#define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */ ++ ++/* definitions for debug register */ ++#define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */ ++#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */ ++#define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */ ++#define EMU10K1_DBG_SINGLE_STEP 0x00008000 /* single step mode */ ++#define EMU10K1_DBG_STEP 0x00004000 /* start single step */ ++#define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */ ++#define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */ ++ ++/* tank memory address line */ ++#ifndef __KERNEL__ ++#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ ++#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ ++#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ ++#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ ++#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ ++#endif ++ ++struct snd_emu10k1_fx8010_info { ++ unsigned int internal_tram_size; /* in samples */ ++ unsigned int external_tram_size; /* in samples */ ++ char fxbus_names[16][32]; /* names of FXBUSes */ ++ char extin_names[16][32]; /* names of external inputs */ ++ char extout_names[32][32]; /* names of external outputs */ ++ unsigned int gpr_controls; /* count of GPR controls */ ++}; ++ ++#define EMU10K1_GPR_TRANSLATION_NONE 0 ++#define EMU10K1_GPR_TRANSLATION_TABLE100 1 ++#define EMU10K1_GPR_TRANSLATION_BASS 2 ++#define EMU10K1_GPR_TRANSLATION_TREBLE 3 ++#define EMU10K1_GPR_TRANSLATION_ONOFF 4 ++ ++enum emu10k1_ctl_elem_iface { ++ EMU10K1_CTL_ELEM_IFACE_MIXER = 2, /* virtual mixer device */ ++ EMU10K1_CTL_ELEM_IFACE_PCM = 3, /* PCM device */ ++}; ++ ++struct emu10k1_ctl_elem_id { ++ unsigned int pad; /* don't use */ ++ int iface; /* interface identifier */ ++ unsigned int device; /* device/client number */ ++ unsigned int subdevice; /* subdevice (substream) number */ ++ unsigned char name[44]; /* ASCII name of item */ ++ unsigned int index; /* index of item */ ++}; ++ ++struct snd_emu10k1_fx8010_control_gpr { ++ struct emu10k1_ctl_elem_id id; /* full control ID definition */ ++ unsigned int vcount; /* visible count */ ++ unsigned int count; /* count of GPR (1..16) */ ++ unsigned short gpr[32]; /* GPR number(s) */ ++ unsigned int value[32]; /* initial values */ ++ unsigned int min; /* minimum range */ ++ unsigned int max; /* maximum range */ ++ unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ ++ const unsigned int *tlv; ++}; ++ ++/* old ABI without TLV support */ ++struct snd_emu10k1_fx8010_control_old_gpr { ++ struct emu10k1_ctl_elem_id id; ++ unsigned int vcount; ++ unsigned int count; ++ unsigned short gpr[32]; ++ unsigned int value[32]; ++ unsigned int min; ++ unsigned int max; ++ unsigned int translation; ++}; ++ ++struct snd_emu10k1_fx8010_code { ++ char name[128]; ++ ++ __EMU10K1_DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */ ++ __u32 *gpr_map; /* initializers */ ++ ++ unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */ ++ struct snd_emu10k1_fx8010_control_gpr *gpr_add_controls; /* GPR controls to add/replace */ ++ ++ unsigned int gpr_del_control_count; /* count of GPR controls to remove */ ++ struct emu10k1_ctl_elem_id *gpr_del_controls; /* IDs of GPR controls to remove */ ++ ++ unsigned int gpr_list_control_count; /* count of GPR controls to list */ ++ unsigned int gpr_list_control_total; /* total count of GPR controls */ ++ struct snd_emu10k1_fx8010_control_gpr *gpr_list_controls; /* listed GPR controls */ ++ ++ __EMU10K1_DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */ ++ __u32 *tram_data_map; /* data initializers */ ++ __u32 *tram_addr_map; /* map initializers */ ++ ++ __EMU10K1_DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */ ++ __u32 *code; /* one instruction - 64 bits */ ++}; ++ ++struct snd_emu10k1_fx8010_tram { ++ unsigned int address; /* 31.bit == 1 -> external TRAM */ ++ unsigned int size; /* size in samples (4 bytes) */ ++ unsigned int *samples; /* pointer to samples (20-bit) */ ++ /* NULL->clear memory */ ++}; ++ ++struct snd_emu10k1_fx8010_pcm_rec { ++ unsigned int substream; /* substream number */ ++ unsigned int res1; /* reserved */ ++ unsigned int channels; /* 16-bit channels count, zero = remove this substream */ ++ unsigned int tram_start; /* ring buffer position in TRAM (in samples) */ ++ unsigned int buffer_size; /* count of buffered samples */ ++ unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */ ++ unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */ ++ unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */ ++ unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */ ++ unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */ ++ unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */ ++ unsigned char pad; /* reserved */ ++ unsigned char etram[32]; /* external TRAM address & data (one per channel) */ ++ unsigned int res2; /* reserved */ ++}; ++ ++#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1) ++ ++#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info) ++#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code) ++#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code) ++#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int) ++#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram) ++#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram) ++#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec) ++#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec) ++#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int) ++#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80) ++#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81) ++#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82) ++#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 +new file mode 100644 +index 00000000..88c92a3f +--- /dev/null ++++ b/include/sound/uapi/hdsp.h +@@ -0,0 +1,109 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++#ifndef __SOUND_HDSP_H ++#define __SOUND_HDSP_H ++ ++/* ++ * Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#define HDSP_MATRIX_MIXER_SIZE 2048 ++ ++enum HDSP_IO_Type { ++ Digiface, ++ Multiface, ++ H9652, ++ H9632, ++ RPM, ++ Undefined, ++}; ++ ++struct hdsp_peak_rms { ++ __u32 input_peaks[26]; ++ __u32 playback_peaks[26]; ++ __u32 output_peaks[28]; ++ __u64 input_rms[26]; ++ __u64 playback_rms[26]; ++ /* These are only used for H96xx cards */ ++ __u64 output_rms[26]; ++}; ++ ++#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms) ++ ++struct hdsp_config_info { ++ unsigned char pref_sync_ref; ++ unsigned char wordclock_sync_check; ++ unsigned char spdif_sync_check; ++ unsigned char adatsync_sync_check; ++ unsigned char adat_sync_check[3]; ++ unsigned char spdif_in; ++ unsigned char spdif_out; ++ unsigned char spdif_professional; ++ unsigned char spdif_emphasis; ++ unsigned char spdif_nonaudio; ++ unsigned int spdif_sample_rate; ++ unsigned int system_sample_rate; ++ unsigned int autosync_sample_rate; ++ unsigned char system_clock_mode; ++ unsigned char clock_source; ++ unsigned char autosync_ref; ++ unsigned char line_out; ++ unsigned char passthru; ++ unsigned char da_gain; ++ unsigned char ad_gain; ++ unsigned char phone_gain; ++ unsigned char xlr_breakout_cable; ++ unsigned char analog_extension_board; ++}; ++ ++#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info) ++ ++struct hdsp_firmware { ++ void *firmware_data; /* 24413 x 4 bytes */ ++}; ++ ++#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware) ++ ++struct hdsp_version { ++ enum HDSP_IO_Type io_type; ++ unsigned short firmware_rev; ++}; ++ ++#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version) ++ ++struct hdsp_mixer { ++ unsigned short matrix[HDSP_MATRIX_MIXER_SIZE]; ++}; ++ ++#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer) ++ ++struct hdsp_9632_aeb { ++ int aebi; ++ int aebo; ++}; ++ ++#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 +new file mode 100644 +index 00000000..2d91f90e +--- /dev/null ++++ b/include/sound/uapi/hdspm.h +@@ -0,0 +1,230 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++#ifndef __SOUND_HDSPM_H ++#define __SOUND_HDSPM_H ++/* ++ * Copyright (C) 2003 Winfried Ritsch (IEM) ++ * based on hdsp.h from Thomas Charbonnel (thomas@undata.org) ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */ ++#define HDSPM_MAX_CHANNELS 64 ++ ++enum hdspm_io_type { ++ MADI, ++ MADIface, ++ AIO, ++ AES32, ++ RayDAT ++}; ++ ++enum hdspm_speed { ++ ss, ++ ds, ++ qs ++}; ++ ++/* -------------------- IOCTL Peak/RMS Meters -------------------- */ ++ ++struct hdspm_peak_rms { ++ __u32 input_peaks[64]; ++ __u32 playback_peaks[64]; ++ __u32 output_peaks[64]; ++ ++ __u64 input_rms[64]; ++ __u64 playback_rms[64]; ++ __u64 output_rms[64]; ++ ++ __u8 speed; /* enum {ss, ds, qs} */ ++ int status2; ++}; ++ ++#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \ ++ _IOR('H', 0x42, struct hdspm_peak_rms) ++ ++/* ------------ CONFIG block IOCTL ---------------------- */ ++ ++struct hdspm_config { ++ unsigned char pref_sync_ref; ++ unsigned char wordclock_sync_check; ++ unsigned char madi_sync_check; ++ unsigned int system_sample_rate; ++ unsigned int autosync_sample_rate; ++ unsigned char system_clock_mode; ++ unsigned char clock_source; ++ unsigned char autosync_ref; ++ unsigned char line_out; ++ unsigned int passthru; ++ unsigned int analog_out; ++}; ++ ++#define SNDRV_HDSPM_IOCTL_GET_CONFIG \ ++ _IOR('H', 0x41, struct hdspm_config) ++ ++/* ++ * If there's a TCO (TimeCode Option) board installed, ++ * there are further options and status data available. ++ * The hdspm_ltc structure contains the current SMPTE ++ * timecode and some status information and can be ++ * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the ++ * hdspm_status struct. ++ */ ++ ++enum hdspm_ltc_format { ++ format_invalid, ++ fps_24, ++ fps_25, ++ fps_2997, ++ fps_30 ++}; ++ ++enum hdspm_ltc_frame { ++ frame_invalid, ++ drop_frame, ++ full_frame ++}; ++ ++enum hdspm_ltc_input_format { ++ ntsc, ++ pal, ++ no_video ++}; ++ ++struct hdspm_ltc { ++ unsigned int ltc; ++ ++ enum hdspm_ltc_format format; ++ enum hdspm_ltc_frame frame; ++ enum hdspm_ltc_input_format input_format; ++}; ++ ++#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_ltc) ++ ++/* ++ * The status data reflects the device's current state ++ * as determined by the card's configuration and ++ * connection status. ++ */ ++ ++enum hdspm_sync { ++ hdspm_sync_no_lock = 0, ++ hdspm_sync_lock = 1, ++ hdspm_sync_sync = 2 ++}; ++ ++enum hdspm_madi_input { ++ hdspm_input_optical = 0, ++ hdspm_input_coax = 1 ++}; ++ ++enum hdspm_madi_channel_format { ++ hdspm_format_ch_64 = 0, ++ hdspm_format_ch_56 = 1 ++}; ++ ++enum hdspm_madi_frame_format { ++ hdspm_frame_48 = 0, ++ hdspm_frame_96 = 1 ++}; ++ ++enum hdspm_syncsource { ++ syncsource_wc = 0, ++ syncsource_madi = 1, ++ syncsource_tco = 2, ++ syncsource_sync = 3, ++ syncsource_none = 4 ++}; ++ ++struct hdspm_status { ++ __u8 card_type; /* enum hdspm_io_type */ ++ enum hdspm_syncsource autosync_source; ++ ++ __u64 card_clock; ++ __u32 master_period; ++ ++ union { ++ struct { ++ __u8 sync_wc; /* enum hdspm_sync */ ++ __u8 sync_madi; /* enum hdspm_sync */ ++ __u8 sync_tco; /* enum hdspm_sync */ ++ __u8 sync_in; /* enum hdspm_sync */ ++ __u8 madi_input; /* enum hdspm_madi_input */ ++ __u8 channel_format; /* enum hdspm_madi_channel_format */ ++ __u8 frame_format; /* enum hdspm_madi_frame_format */ ++ } madi; ++ } card_specific; ++}; ++ ++#define SNDRV_HDSPM_IOCTL_GET_STATUS \ ++ _IOR('H', 0x47, struct hdspm_status) ++ ++/* ++ * Get information about the card and its add-ons. ++ */ ++ ++#define HDSPM_ADDON_TCO 1 ++ ++struct hdspm_version { ++ __u8 card_type; /* enum hdspm_io_type */ ++ char cardname[20]; ++ unsigned int serial; ++ unsigned short firmware_rev; ++ int addons; ++}; ++ ++#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version) ++ ++/* ------------- get Matrix Mixer IOCTL --------------- */ ++ ++/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte = ++ * 32768 Bytes ++ */ ++ ++/* organisation is 64 channelfader in a continuous memory block */ ++/* equivalent to hardware definition, maybe for future feature of mmap of ++ * them ++ */ ++/* each of 64 outputs has 64 infader and 64 outfader: ++ Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */ ++ ++#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS ++ ++struct hdspm_channelfader { ++ unsigned int in[HDSPM_MIXER_CHANNELS]; ++ unsigned int pb[HDSPM_MIXER_CHANNELS]; ++}; ++ ++struct hdspm_mixer { ++ struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS]; ++}; ++ ++struct hdspm_mixer_ioctl { ++ struct hdspm_mixer *mixer; ++}; ++ ++/* 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 +diff --git a/include/sound/uapi/sb16_csp.h b/include/sound/uapi/sb16_csp.h +new file mode 100644 +index 00000000..e6485148 +--- /dev/null ++++ b/include/sound/uapi/sb16_csp.h +@@ -0,0 +1,123 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * Copyright (c) 1999 by Uros Bizjak ++ * Takashi Iwai ++ * ++ * SB16ASP/AWE32 CSP control ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++#ifndef _UAPI__SOUND_SB16_CSP_H ++#define _UAPI__SOUND_SB16_CSP_H ++ ++ ++/* CSP modes */ ++#define SNDRV_SB_CSP_MODE_NONE 0x00 ++#define SNDRV_SB_CSP_MODE_DSP_READ 0x01 /* Record from DSP */ ++#define SNDRV_SB_CSP_MODE_DSP_WRITE 0x02 /* Play to DSP */ ++#define SNDRV_SB_CSP_MODE_QSOUND 0x04 /* QSound */ ++ ++/* CSP load flags */ ++#define SNDRV_SB_CSP_LOAD_FROMUSER 0x01 ++#define SNDRV_SB_CSP_LOAD_INITBLOCK 0x02 ++ ++/* CSP sample width */ ++#define SNDRV_SB_CSP_SAMPLE_8BIT 0x01 ++#define SNDRV_SB_CSP_SAMPLE_16BIT 0x02 ++ ++/* CSP channels */ ++#define SNDRV_SB_CSP_MONO 0x01 ++#define SNDRV_SB_CSP_STEREO 0x02 ++ ++/* CSP rates */ ++#define SNDRV_SB_CSP_RATE_8000 0x01 ++#define SNDRV_SB_CSP_RATE_11025 0x02 ++#define SNDRV_SB_CSP_RATE_22050 0x04 ++#define SNDRV_SB_CSP_RATE_44100 0x08 ++#define SNDRV_SB_CSP_RATE_ALL 0x0f ++ ++/* CSP running state */ ++#define SNDRV_SB_CSP_ST_IDLE 0x00 ++#define SNDRV_SB_CSP_ST_LOADED 0x01 ++#define SNDRV_SB_CSP_ST_RUNNING 0x02 ++#define SNDRV_SB_CSP_ST_PAUSED 0x04 ++#define SNDRV_SB_CSP_ST_AUTO 0x08 ++#define SNDRV_SB_CSP_ST_QSOUND 0x10 ++ ++/* maximum QSound value (180 degrees right) */ ++#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT 0x20 ++ ++/* maximum microcode RIFF file size */ ++#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000 ++ ++/* microcode header */ ++struct snd_sb_csp_mc_header { ++ char codec_name[16]; /* id name of codec */ ++ unsigned short func_req; /* requested function */ ++}; ++ ++/* microcode to be loaded */ ++struct snd_sb_csp_microcode { ++ struct snd_sb_csp_mc_header info; ++ unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE]; ++}; ++ ++/* start CSP with sample_width in mono/stereo */ ++struct snd_sb_csp_start { ++ int sample_width; /* sample width, look above */ ++ int channels; /* channels, look above */ ++}; ++ ++/* CSP information */ ++struct snd_sb_csp_info { ++ char codec_name[16]; /* id name of codec */ ++ unsigned short func_nr; /* function number */ ++ unsigned int acc_format; /* accepted PCM formats */ ++ unsigned short acc_channels; /* accepted channels */ ++ unsigned short acc_width; /* accepted sample width */ ++ unsigned short acc_rates; /* accepted sample rates */ ++ unsigned short csp_mode; /* CSP mode, see above */ ++ unsigned short run_channels; /* current channels */ ++ unsigned short run_width; /* current sample width */ ++ unsigned short version; /* version id: 0x10 - 0x1f */ ++ unsigned short state; /* state bits */ ++}; ++ ++/* HWDEP controls */ ++/* get CSP information */ ++#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info) ++/* load microcode to CSP */ ++/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits) ++ * defined for some architectures like MIPS, and it leads to build errors. ++ * (x86 and co have 14-bit size, thus it's valid, though.) ++ * As a workaround for skipping the size-limit check, here we don't use the ++ * normal _IOW() macro but _IOC() with the manual argument. ++ */ ++#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \ ++ _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode)) ++/* unload microcode from CSP */ ++#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12) ++/* start CSP */ ++#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start) ++/* stop CSP */ ++#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14) ++/* pause CSP and DMA transfer */ ++#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15) ++/* restart CSP and DMA transfer */ ++#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16) ++ ++ ++#endif /* _UAPI__SOUND_SB16_CSP_H */ +diff --git a/include/sound/uapi/sscape_ioctl.h b/include/sound/uapi/sscape_ioctl.h +new file mode 100644 +index 00000000..c6653ebf +--- /dev/null ++++ b/include/sound/uapi/sscape_ioctl.h +@@ -0,0 +1,21 @@ ++#ifndef SSCAPE_IOCTL_H ++#define SSCAPE_IOCTL_H ++ ++ ++struct sscape_bootblock ++{ ++ unsigned char code[256]; ++ unsigned version; ++}; ++ ++#define SSCAPE_MICROCODE_SIZE 65536 ++ ++struct sscape_microcode ++{ ++ unsigned char *code; ++}; ++ ++#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock) ++#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode) ++ ++#endif +diff --git a/include/sound/uapi/tlv.h b/include/sound/uapi/tlv.h +new file mode 100644 +index 00000000..7d6d65f6 +--- /dev/null ++++ b/include/sound/uapi/tlv.h +@@ -0,0 +1,117 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __UAPI_SOUND_TLV_H ++#define __UAPI_SOUND_TLV_H ++ ++#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */ ++#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */ ++#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */ ++#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */ ++#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */ ++#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */ ++ ++/* ++ * channel-mapping TLV items ++ * TLV length must match with num_channels ++ */ ++#define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */ ++#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */ ++#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */ ++ ++/* ++ * TLV structure is right behind the struct snd_ctl_tlv: ++ * unsigned int type - see SNDRV_CTL_TLVT_* ++ * unsigned int length ++ * .... data aligned to sizeof(unsigned int), use ++ * block_length = (length + (sizeof(unsigned int) - 1)) & ++ * ~(sizeof(unsigned int) - 1)) .... ++ */ ++#define SNDRV_CTL_TLVD_ITEM(type, ...) \ ++ (type), SNDRV_CTL_TLVD_LENGTH(__VA_ARGS__), __VA_ARGS__ ++#define SNDRV_CTL_TLVD_LENGTH(...) \ ++ ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ })) ++ ++/* Accessor offsets for TLV data items */ ++#define SNDRV_CTL_TLVO_TYPE 0 ++#define SNDRV_CTL_TLVO_LEN 1 ++ ++#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \ ++ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__) ++#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \ ++ unsigned int name[] = { \ ++ SNDRV_CTL_TLVD_CONTAINER_ITEM(__VA_ARGS__) \ ++ } ++ ++#define SNDRV_CTL_TLVD_DB_SCALE_MASK 0xffff ++#define SNDRV_CTL_TLVD_DB_SCALE_MUTE 0x10000 ++#define SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \ ++ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \ ++ (min), \ ++ ((step) & SNDRV_CTL_TLVD_DB_SCALE_MASK) | \ ++ ((mute) ? SNDRV_CTL_TLVD_DB_SCALE_MUTE : 0)) ++#define SNDRV_CTL_TLVD_DECLARE_DB_SCALE(name, min, step, mute) \ ++ unsigned int name[] = { \ ++ SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \ ++ } ++ ++/* Accessor offsets for min, mute and step items in dB scale type TLV */ ++#define SNDRV_CTL_TLVO_DB_SCALE_MIN 2 ++#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 3 ++ ++/* dB scale specified with min/max values instead of step */ ++#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \ ++ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB)) ++#define SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ ++ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB)) ++#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(name, min_dB, max_dB) \ ++ unsigned int name[] = { \ ++ SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \ ++ } ++#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE(name, min_dB, max_dB) \ ++ unsigned int name[] = { \ ++ SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ ++ } ++ ++/* Accessor offsets for min, max items in db-minmax types of TLV. */ ++#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 2 ++#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 3 ++ ++/* linear volume between min_dB and max_dB (.01dB unit) */ ++#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \ ++ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB)) ++#define SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(name, min_dB, max_dB) \ ++ unsigned int name[] = { \ ++ SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \ ++ } ++ ++/* Accessor offsets for min, max items in db-linear type of TLV. */ ++#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 2 ++#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 3 ++ ++/* dB range container: ++ * Items in dB range container must be ordered by their values and by their ++ * dB values. This implies that larger values must correspond with larger ++ * dB values (which is also required for all other mixer controls). ++ */ ++/* Each item is: */ ++#define SNDRV_CTL_TLVD_DB_RANGE_ITEM(...) \ ++ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__) ++#define SNDRV_CTL_TLVD_DECLARE_DB_RANGE(name, ...) \ ++ unsigned int name[] = { \ ++ SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) \ ++ } ++ ++#define SNDRV_CTL_TLVD_DB_GAIN_MUTE -9999999 ++ ++#endif +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 11efce6d..101491a4 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -18,8 +18,7 @@ + #include "list.h" + #include "topology.h" + +-#define __packed __attribute__((__packed__)) +- ++#include + #include + #include + #include +-- +2.24.1 + + +From 75584fe660880b332fbf60dd7968e2ed8b49a38b Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 20 Dec 2019 16:12:50 +0100 +Subject: [PATCH 30/69] type_compat: Add missing __s64 and __u64 definitions + for non-Linux + +Just for the case without Linux-compatible definitions. + +Signed-off-by: Takashi Iwai +--- + include/sound/type_compat.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/sound/type_compat.h b/include/sound/type_compat.h +index d4790c1f..5b765f44 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 + #include +-- +2.24.1 + + +From 59792f467b38d6a4c4dffdb30528f7fb03d23d96 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 20 Dec 2019 17:12:37 +0100 +Subject: [PATCH 31/69] uapi: Move typedefs from uapi to sound/* + +For keeping uapi/*.h cleaner. + +Signed-off-by: Takashi Iwai +--- + 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 f06ecee5..0832f95b 100644 +--- a/include/sound/emu10k1.h ++++ b/include/sound/emu10k1.h +@@ -1,2 +1,11 @@ + #include + #include ++#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 78fb745b..e8f93156 100644 +--- a/include/sound/hdsp.h ++++ b/include/sound/hdsp.h +@@ -1,2 +1,12 @@ + #include + #include ++#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 af6d19ed..d9095d9f 100644 +--- a/include/sound/hdspm.h ++++ b/include/sound/hdspm.h +@@ -1,2 +1,10 @@ + #include + #include ++#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 24121fcb..fd02bc56 100644 +--- a/include/sound/sb16_csp.h ++++ b/include/sound/sb16_csp.h +@@ -1 +1,5 @@ + #include ++#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 c1150e4d..6bcd76f6 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 88c92a3f..7ac2d3f2 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 2d91f90e..3fbfd9dc 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.24.1 + + +From 9e2bbccfcc8069a676519149a280f20c1e05f0ac Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Fri, 3 Jan 2020 13:05:51 -0500 +Subject: [PATCH 32/69] Update the attributes.m4 macro file from xine +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This file was imported from the xine project. Update it to the current +revision, which resolves the "no AC_LANG_SOURCE call detected in body" +warnings with Autoconf 2.68 or later. + +Cc: Diego Pettenò +Signed-off-by: David Ward +Signed-off-by: Jaroslav Kysela +--- + m4/attributes.m4 | 33 ++++++++++++++++++++------------- + 1 file changed, 20 insertions(+), 13 deletions(-) + +diff --git a/m4/attributes.m4 b/m4/attributes.m4 +index e86456a4..3d9c256a 100644 +--- a/m4/attributes.m4 ++++ b/m4/attributes.m4 +@@ -1,6 +1,6 @@ + dnl Macros to check the presence of generic (non-typed) symbols. +-dnl Copyright (c) 2006-2007 Diego Pettenò +-dnl Copyright (c) 2006-2007 xine project ++dnl Copyright (c) 2006-2008 Diego Pettenò ++dnl Copyright (c) 2006-2008 xine project + dnl + dnl This program is free software; you can redistribute it and/or modify + dnl it under the terms of the GNU General Public License as published by +@@ -25,7 +25,7 @@ dnl License when using or distributing such scripts, even though portions + dnl of the text of the Macro appear in them. The GNU General Public + dnl License (GPL) does govern all other use of the material that + dnl constitutes the Autoconf Macro. +-dnl ++dnl + dnl This special exception to the GPL applies to versions of the + dnl Autoconf Macro released by this project. When you make and + dnl distribute a modified version of the Autoconf Macro, you may extend +@@ -39,7 +39,7 @@ AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [ + AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" +- AC_COMPILE_IFELSE([int a;], ++ AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])], + [eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_cflags_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" +@@ -71,7 +71,7 @@ AC_DEFUN([CC_CHECK_CFLAG_APPEND], [ + ) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], +- [CFLAGS="$CFLAGS $1"; $2], [$3]) ++ [CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3]) + ]) + + dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not]) +@@ -89,7 +89,7 @@ AC_DEFUN([CC_CHECK_LDFLAGS], [ + AS_TR_SH([cc_cv_ldflags_$1]), + [ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $1" +- AC_LINK_IFELSE([int main() { return 1; }], ++ AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])], + [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_ldflags_$1])="]) + LDFLAGS="$ac_save_LDFLAGS" +@@ -109,14 +109,21 @@ AC_DEFUN([CC_NOUNDEFINED], [ + dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads + dnl are requested, as different implementations are present; to avoid problems + dnl use -Wl,-z,defs only for those platform not behaving this way. +- *-freebsd*) ;; ++ dnl ++ dnl MinGW platforms: for libraries required -no-undefined, ++ dnl use it only for libraries in mingw32-w64 ++ ++ *-freebsd* | *-openbsd*) ;; ++ *-mingw*) ++ LDFLAGS_NOUNDEFINED="-no-undefined" ++ ;; + *) + dnl First of all check for the --no-undefined variant of GNU ld. This allows + dnl for a much more readable commandline, so that people can understand what + dnl it does without going to look for what the heck -z defs does. +- for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do ++ for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do + CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"]) +- break ++ if test "x$LDFLAGS_NOUNDEFINED" = "x"; then break; fi + done + ;; + esac +@@ -147,7 +154,7 @@ AC_DEFUN([CC_CHECK_ATTRIBUTE], [ + AS_TR_SH([cc_cv_attribute_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" +- AC_COMPILE_IFELSE([$3], ++ AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])], + [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" +@@ -257,7 +264,7 @@ AC_DEFUN([CC_FLAG_VISIBILITY], [ + cc_cv_flag_visibility='yes', + cc_cv_flag_visibility='no') + CFLAGS="$cc_flag_visibility_save_CFLAGS"]) +- ++ + AS_IF([test "x$cc_cv_flag_visibility" = "xyes"], + [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1, + [Define this if the compiler supports the -fvisibility flag]) +@@ -295,11 +302,11 @@ AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + for cc_attribute_align_try in 64 32 16 8 4 2; do +- AC_COMPILE_IFELSE([ ++ AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + int main() { + static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0; + return c; +- }], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) ++ }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) + done + CFLAGS="$ac_save_CFLAGS" + ]) +-- +2.24.1 + + +From f373bf1f6eea0f2037a7714e9b55aa65fa00b889 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 14 Dec 2019 13:36:09 +0100 +Subject: [PATCH 33/69] topology: avoid to use the atoi() directly when + expected + +Signed-off-by: Jaroslav Kysela +--- + src/topology/channel.c | 10 +-- + src/topology/ctl.c | 37 +++++----- + src/topology/dapm.c | 32 +++++---- + src/topology/data.c | 14 ++-- + src/topology/elem.c | 9 ++- + src/topology/ops.c | 2 +- + src/topology/parser.c | 29 ++++++++ + src/topology/pcm.c | 148 +++++++++++++++++--------------------- + src/topology/tplg_local.h | 2 + + 9 files changed, 150 insertions(+), 133 deletions(-) + +diff --git a/src/topology/channel.c b/src/topology/channel.c +index 60f7e219..4569eb31 100644 +--- a/src/topology/channel.c ++++ b/src/topology/channel.c +@@ -80,8 +80,8 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + snd_config_iterator_t i, next; + snd_config_t *n; + struct snd_soc_tplg_channel *channel = private; +- const char *id, *value; +- int channel_id; ++ const char *id; ++ int channel_id, value; + + if (tplg->channel_idx >= SND_SOC_TPLG_MAX_CHAN) + return -EINVAL; +@@ -109,13 +109,13 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + continue; + + /* get value */ +- if (snd_config_get_string(n, &value) < 0) ++ if (tplg_get_integer(n, &value, 0) < 0) + continue; + + if (strcmp(id, "reg") == 0) +- channel->reg = atoi(value); ++ channel->reg = value; + else if (strcmp(id, "shift") == 0) +- channel->shift = atoi(value); ++ channel->shift = value; + + tplg_dbg("\t\t%s = %s\n", id, value); + } +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index 1db0b16e..e1896f46 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -286,7 +286,8 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem) + snd_config_t *n; + struct snd_soc_tplg_ctl_tlv *tplg_tlv; + struct snd_soc_tplg_tlv_dbscale *scale; +- const char *id = NULL, *value = NULL; ++ const char *id = NULL; ++ int val; + + tplg_dbg(" scale: %s\n", elem->id); + +@@ -310,18 +311,18 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem) + } + + /* get value */ +- if (snd_config_get_string(n, &value) < 0) ++ if (tplg_get_integer(n, &val, 0)) + continue; + +- tplg_dbg("\t%s = %s\n", id, value); ++ tplg_dbg("\t%s = %i\n", id, val); + + /* get TLV data */ + if (strcmp(id, "min") == 0) +- scale->min = atoi(value); ++ scale->min = val; + else if (strcmp(id, "step") == 0) +- scale->step = atoi(value); ++ scale->step = val; + else if (strcmp(id, "mute") == 0) +- scale->mute = atoi(value); ++ scale->mute = val; + else + SNDERR("error: unknown key %s\n", id); + } +@@ -372,7 +373,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + snd_config_iterator_t i, next; + snd_config_t *n; + const char *id, *val = NULL; +- int err; ++ int err, ival; + bool access_set = false, tlv_set = false; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES); +@@ -398,37 +399,37 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + continue; + + if (strcmp(id, "base") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- be->base = atoi(val); ++ be->base = ival; + tplg_dbg("\t%s: %d\n", id, be->base); + continue; + } + + if (strcmp(id, "num_regs") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- be->num_regs = atoi(val); ++ be->num_regs = ival; + tplg_dbg("\t%s: %d\n", id, be->num_regs); + continue; + } + + if (strcmp(id, "max") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- be->max = atoi(val); ++ be->max = ival; + tplg_dbg("\t%s: %d\n", id, be->max); + continue; + } + + if (strcmp(id, "mask") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 16)) + return -EINVAL; + +- be->mask = strtol(val, NULL, 16); ++ be->mask = ival; + tplg_dbg("\t%s: %d\n", id, be->mask); + continue; + } +@@ -598,7 +599,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + snd_config_iterator_t i, next; + snd_config_t *n; + const char *id, *val = NULL; +- int err, j; ++ int err, j, ival; + bool access_set = false, tlv_set = false; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER); +@@ -647,10 +648,10 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + } + + if (strcmp(id, "max") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- mc->max = atoi(val); ++ mc->max = ival; + tplg_dbg("\t%s: %d\n", id, mc->max); + continue; + } +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index ce469131..c6fd793d 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -426,7 +426,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, + snd_config_iterator_t i, next; + snd_config_t *n; + int err; +- const char *graph_id, *val = NULL; ++ const char *graph_id; + int index = -1; + + if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { +@@ -445,9 +445,10 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, + } + + if (strcmp(id, "index") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &index, 0)) ++ return -EINVAL; ++ if (index < 0) + return -EINVAL; +- index = atoi(val); + } + + if (strcmp(id, "lines") == 0) { +@@ -479,6 +480,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + snd_config_t *n; + const char *id, *val = NULL; + int widget_type, err; ++ int ival; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DAPM_WIDGET); + if (!elem) +@@ -540,55 +542,55 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + } + + if (strcmp(id, "shift") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- widget->shift = atoi(val); ++ widget->shift = ival; + tplg_dbg("\t%s: %d\n", id, widget->shift); + continue; + } + + if (strcmp(id, "reg") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- widget->reg = atoi(val); ++ widget->reg = ival; + tplg_dbg("\t%s: %d\n", id, widget->reg); + continue; + } + + if (strcmp(id, "invert") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- widget->invert = atoi(val); ++ widget->invert = ival; + tplg_dbg("\t%s: %d\n", id, widget->invert); + continue; + } + + if (strcmp(id, "subseq") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- widget->subseq= atoi(val); ++ widget->subseq = ival; + tplg_dbg("\t%s: %d\n", id, widget->subseq); + continue; + } + + if (strcmp(id, "event_type") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- widget->event_type = atoi(val); ++ widget->event_type = ival; + tplg_dbg("\t%s: %d\n", id, widget->event_type); + continue; + } + + if (strcmp(id, "event_flags") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- widget->event_flags = atoi(val); ++ widget->event_flags = ival; + tplg_dbg("\t%s: %d\n", id, widget->event_flags); + continue; + } +diff --git a/src/topology/data.c b/src/topology/data.c +index 729ce1f4..0edfe54f 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -800,10 +800,10 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, + { + snd_config_iterator_t i, next; + snd_config_t *n; +- const char *id, *value; ++ const char *id; + struct tplg_elem *elem; + struct tplg_vendor_tokens *tokens; +- int num_tokens = 0; ++ int num_tokens = 0, value; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TOKEN); + if (!elem) +@@ -830,12 +830,12 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, + if (snd_config_get_id(n, &id) < 0) + continue; + +- if (snd_config_get_string(n, &value) < 0) ++ if (tplg_get_integer(n, &value, 0)) + continue; + + snd_strlcpy(tokens->token[tokens->num_tokens].id, id, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); +- tokens->token[tokens->num_tokens].value = atoi(value); ++ tokens->token[tokens->num_tokens].value = value; + tplg_dbg("\t\t %s : %d\n", tokens->token[tokens->num_tokens].id, + tokens->token[tokens->num_tokens].value); + tokens->num_tokens++; +@@ -1013,7 +1013,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + snd_config_iterator_t i, next; + snd_config_t *n; + const char *id, *val = NULL; +- int err = 0; ++ int err = 0, ival; + struct tplg_elem *elem; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DATA); +@@ -1071,10 +1071,10 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + } + + if (strcmp(id, "type") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (tplg_get_integer(n, &ival, 0)) + return -EINVAL; + +- elem->vendor_type = atoi(val); ++ elem->vendor_type = ival; + tplg_dbg("\t%s: %d\n", id, elem->index); + continue; + } +diff --git a/src/topology/elem.c b/src/topology/elem.c +index d8618cc9..f2076f79 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -153,7 +153,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + enum snd_tplg_type type) + { + struct tplg_elem *elem; +- const char *id, *val = NULL; ++ const char *id; + int obj_size = 0; + void *obj; + snd_config_iterator_t i, next; +@@ -178,11 +178,14 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + if (snd_config_get_id(n, &id)) + continue; + if (strcmp(id, "index") == 0) { +- if (snd_config_get_string(n, &val) < 0) { ++ if (tplg_get_integer(n, &elem->index, 0)) { ++ free(elem); ++ return NULL; ++ } ++ if (elem->index < 0) { + free(elem); + return NULL; + } +- elem->index = atoi(val); + } + } + } else if (name != NULL) +diff --git a/src/topology/ops.c b/src/topology/ops.c +index 0f4295a2..073acdcb 100644 +--- a/src/topology/ops.c ++++ b/src/topology/ops.c +@@ -42,7 +42,7 @@ static int lookup_ops(const char *c) + } + + /* cant find string name in our table so we use its ID number */ +- return atoi(c); ++ return strtol(c, NULL, 0); + } + + /* Parse Control operations. Ops can come from standard names above or +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 5940692d..7e657809 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -21,6 +21,35 @@ + #include "list.h" + #include "tplg_local.h" + ++/* ++ * Get integer value ++ */ ++int tplg_get_integer(snd_config_t *n, int *val, int base) ++{ ++ const char *str; ++ long lval; ++ int err; ++ ++ switch (snd_config_get_type(n)) { ++ case SND_CONFIG_TYPE_INTEGER: ++ err = snd_config_get_integer(n, &lval); ++ if (err < 0) ++ return err; ++ if (lval < INT_MIN || lval > INT_MAX) ++ return -EINVAL; ++ *val = lval; ++ return err; ++ case SND_CONFIG_TYPE_STRING: ++ err = snd_config_get_string(n, &str); ++ if (err < 0) ++ return err; ++ *val = strtol(str, NULL, base); ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ + /* + * Parse compound + */ +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 98a8df97..d6c52b47 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -368,6 +368,24 @@ static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str) + return 0; + } + ++static int parse_unsigned(snd_config_t *n, unsigned int *dst) ++{ ++ int ival; ++ ++ if (tplg_get_integer(n, &ival, 0) < 0) ++ return -EINVAL; ++ ++ *dst = ival; ++#if TPLG_DEBUG ++ { ++ const char *id; ++ if (snd_config_get_id(n, &id) >= 0) ++ tplg_dbg("\t\t%s: %d\n", id, *dst); ++ } ++#endif ++ return 0; ++} ++ + /* Parse pcm stream capabilities */ + int tplg_parse_stream_caps(snd_tplg_t *tplg, + snd_config_t *cfg, +@@ -402,10 +420,10 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + if (id[0] == '#') + continue; + +- if (snd_config_get_string(n, &val) < 0) +- return -EINVAL; +- + if (strcmp(id, "formats") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ + s = strdup(val); + if (s == NULL) + return -ENOMEM; +@@ -421,6 +439,9 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + } + + if (strcmp(id, "rates") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ + s = strdup(val); + if (!s) + return -ENOMEM; +@@ -436,68 +457,68 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + } + + if (strcmp(id, "rate_min") == 0) { +- sc->rate_min = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->rate_min); ++ if (parse_unsigned(n, &sc->rate_min)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "rate_max") == 0) { +- sc->rate_max = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->rate_max); ++ if (parse_unsigned(n, &sc->rate_max)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "channels_min") == 0) { +- sc->channels_min = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->channels_min); ++ if (parse_unsigned(n, &sc->channels_min)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "channels_max") == 0) { +- sc->channels_max = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->channels_max); ++ if (parse_unsigned(n, &sc->channels_max)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "periods_min") == 0) { +- sc->periods_min = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->periods_min); ++ if (parse_unsigned(n, &sc->periods_min)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "periods_max") == 0) { +- sc->periods_max = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->periods_max); ++ if (parse_unsigned(n, &sc->periods_max)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "period_size_min") == 0) { +- sc->period_size_min = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->period_size_min); ++ if (parse_unsigned(n, &sc->period_size_min)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "period_size_max") == 0) { +- sc->period_size_max = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->period_size_max); ++ if (parse_unsigned(n, &sc->period_size_max)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "buffer_size_min") == 0) { +- sc->buffer_size_min = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->buffer_size_min); ++ if (parse_unsigned(n, &sc->buffer_size_min)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "buffer_size_max") == 0) { +- sc->buffer_size_max = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->buffer_size_max); ++ if (parse_unsigned(n, &sc->buffer_size_max)) ++ return -EINVAL; + continue; + } + + if (strcmp(id, "sig_bits") == 0) { +- sc->sig_bits = atoi(val); +- tplg_dbg("\t\t%s: %d\n", id, sc->sig_bits); ++ if (parse_unsigned(n, &sc->sig_bits)) ++ return -EINVAL; + continue; + } + +@@ -674,11 +695,8 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, + continue; + + if (strcmp(id, "id") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &pcm->pcm_id)) + return -EINVAL; +- +- pcm->pcm_id = atoi(val); +- tplg_dbg("\t%s: %d\n", id, pcm->pcm_id); + continue; + } + +@@ -784,30 +802,21 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, + continue; + + if (strcmp(id, "id") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &dai->dai_id)) + return -EINVAL; +- +- dai->dai_id = atoi(val); +- tplg_dbg("\t%s: %d\n", id, dai->dai_id); + continue; + } + + if (strcmp(id, "playback") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &dai->playback)) + return -EINVAL; +- +- dai->playback = atoi(val); +- tplg_dbg("\t%s: %d\n", id, dai->playback); + continue; + } + + + if (strcmp(id, "capture") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &dai->capture)) + return -EINVAL; +- +- dai->capture = atoi(val); +- tplg_dbg("\t%s: %d\n", id, dai->capture); + continue; + } + +@@ -949,11 +958,8 @@ int tplg_parse_link(snd_tplg_t *tplg, + continue; + + if (strcmp(id, "id") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &link->id)) + return -EINVAL; +- +- link->id = atoi(val); +- tplg_dbg("\t%s: %d\n", id, link->id); + continue; + } + +@@ -975,10 +981,8 @@ int tplg_parse_link(snd_tplg_t *tplg, + } + + if (strcmp(id, "default_hw_conf_id") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &link->default_hw_config_id)) + return -EINVAL; +- +- link->default_hw_config_id = atoi(val); + continue; + } + +@@ -1030,7 +1034,7 @@ int tplg_parse_cc(snd_tplg_t *tplg, + struct tplg_elem *elem; + snd_config_iterator_t i, next; + snd_config_t *n; +- const char *id, *val = NULL; ++ const char *id; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_CC); + if (!elem) +@@ -1054,11 +1058,8 @@ int tplg_parse_cc(snd_tplg_t *tplg, + continue; + + if (strcmp(id, "id") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &link->id)) + return -EINVAL; +- +- link->id = atoi(val); +- tplg_dbg("\t%s: %d\n", id, link->id); + continue; + } + +@@ -1130,11 +1131,8 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + continue; + + if (strcmp(id, "id") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->id)) + return -EINVAL; +- +- hw_cfg->id = atoi(val); +- tplg_dbg("\t%s: %d\n", id, hw_cfg->id); + continue; + } + +@@ -1173,10 +1171,8 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + + if (strcmp(id, "bclk_freq") == 0 || + strcmp(id, "bclk_rate") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->bclk_rate)) + return -EINVAL; +- +- hw_cfg->bclk_rate = atoi(val); + continue; + } + +@@ -1223,19 +1219,15 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + + if (strcmp(id, "fsync_freq") == 0 || + strcmp(id, "fsync_rate") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->fsync_rate)) + return -EINVAL; +- +- hw_cfg->fsync_rate = atoi(val); + continue; + } + + if (strcmp(id, "mclk_freq") == 0 || + strcmp(id, "mclk_rate") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->mclk_rate)) + return -EINVAL; +- +- hw_cfg->mclk_rate = atoi(val); + continue; + } + +@@ -1275,50 +1267,38 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + } + + if (strcmp(id, "tdm_slots") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->tdm_slots)) + return -EINVAL; +- +- hw_cfg->tdm_slots = atoi(val); + continue; + } + + if (strcmp(id, "tdm_slot_width") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->tdm_slot_width)) + return -EINVAL; +- +- hw_cfg->tdm_slot_width = atoi(val); + continue; + } + + if (strcmp(id, "tx_slots") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->tx_slots)) + return -EINVAL; +- +- hw_cfg->tx_slots = atoi(val); + continue; + } + + if (strcmp(id, "rx_slots") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->rx_slots)) + return -EINVAL; +- +- hw_cfg->rx_slots = atoi(val); + continue; + } + + if (strcmp(id, "tx_channels") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->tx_channels)) + return -EINVAL; +- +- hw_cfg->tx_channels = atoi(val); + continue; + } + + if (strcmp(id, "rx_channels") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (parse_unsigned(n, &hw_cfg->rx_channels)) + return -EINVAL; +- +- hw_cfg->rx_channels = atoi(val); + continue; + } + +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 101491a4..991e0b41 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -280,6 +280,8 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, + struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + snd_config_t *cfg, const char *name, enum snd_tplg_type type); + ++int tplg_get_integer(snd_config_t *n, int *val, int base); ++ + int tplg_parse_channel(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_config_t *cfg, void *private); + +-- +2.24.1 + + +From 5925a6d870331c631f85ed4e18a8c5e6459b3c36 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 14 Dec 2019 13:50:04 +0100 +Subject: [PATCH 34/69] topology: use snd_config_get_bool() instead own + implementation + +Signed-off-by: Jaroslav Kysela +--- + src/topology/ctl.c | 9 +++------ + src/topology/dapm.c | 9 ++++----- + src/topology/data.c | 15 ++++++++++++--- + src/topology/pcm.c | 29 +++++++++++++++-------------- + 4 files changed, 34 insertions(+), 28 deletions(-) + +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index e1896f46..9190efef 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -657,13 +657,10 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + } + + if (strcmp(id, "invert") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ ival = snd_config_get_bool(n); ++ if (ival < 0) + return -EINVAL; +- +- if (strcmp(val, "true") == 0) +- mc->invert = 1; +- else if (strcmp(val, "false") == 0) +- mc->invert = 0; ++ mc->invert = ival; + + tplg_dbg("\t%s: %d\n", id, mc->invert); + continue; +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index c6fd793d..ad709210 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -479,8 +479,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + snd_config_iterator_t i, next; + snd_config_t *n; + const char *id, *val = NULL; +- int widget_type, err; +- int ival; ++ int widget_type, err, ival; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DAPM_WIDGET); + if (!elem) +@@ -531,11 +530,11 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + } + + if (strcmp(id, "no_pm") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ ival = snd_config_get_bool(n); ++ if (ival < 0) + return -EINVAL; + +- if (strcmp(val, "true") == 0) +- widget->reg = -1; ++ widget->reg = ival ? -1 : 0; + + tplg_dbg("\t%s: %s\n", id, val); + continue; +diff --git a/src/topology/data.c b/src/topology/data.c +index 0edfe54f..6b1337b3 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -557,6 +557,7 @@ static int parse_tuple_set(snd_config_t *cfg, + unsigned int type, num_tuples = 0; + struct tplg_tuple *tuple; + unsigned long int tuple_val; ++ int ival; + + snd_config_get_id(cfg, &id); + +@@ -607,25 +608,33 @@ static int parse_tuple_set(snd_config_t *cfg, + + switch (type) { + case SND_SOC_TPLG_TUPLE_TYPE_UUID: ++ if (snd_config_get_string(n, &value) < 0) ++ continue; + if (get_uuid(value, tuple->uuid) < 0) + goto err; + break; + + case SND_SOC_TPLG_TUPLE_TYPE_STRING: ++ if (snd_config_get_string(n, &value) < 0) ++ continue; + snd_strlcpy(tuple->string, value, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + tplg_dbg("\t\t%s = %s\n", tuple->token, tuple->string); + break; + + case SND_SOC_TPLG_TUPLE_TYPE_BOOL: +- if (strcmp(value, "true") == 0) +- tuple->value = 1; ++ ival = snd_config_get_bool(n); ++ if (ival < 0) ++ continue; ++ tuple->value = ival; + tplg_dbg("\t\t%s = %d\n", tuple->token, tuple->value); + break; + + case SND_SOC_TPLG_TUPLE_TYPE_BYTE: + case SND_SOC_TPLG_TUPLE_TYPE_SHORT: + case SND_SOC_TPLG_TUPLE_TYPE_WORD: ++ if (snd_config_get_string(n, &value) < 0) ++ continue; + errno = 0; + /* no support for negative value */ + tuple_val = strtoul(value, NULL, 0); +@@ -1012,7 +1021,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + { + snd_config_iterator_t i, next; + snd_config_t *n; +- const char *id, *val = NULL; ++ const char *id; + int err = 0, ival; + struct tplg_elem *elem; + +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index d6c52b47..6364e24f 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -669,8 +669,8 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, + struct tplg_elem *elem; + snd_config_iterator_t i, next; + snd_config_t *n; +- const char *id, *val = NULL; +- int err; ++ const char *id; ++ int err, ival; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_PCM); + if (!elem) +@@ -709,11 +709,11 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, + } + + if (strcmp(id, "compress") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ ival = snd_config_get_bool(n); ++ if (ival < 0) + return -EINVAL; + +- if (strcmp(val, "true") == 0) +- pcm->compress = 1; ++ pcm->compress = ival; + + tplg_dbg("\t%s: %s\n", id, val); + continue; +@@ -1107,7 +1107,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + snd_config_iterator_t i, next; + snd_config_t *n; + const char *id, *val = NULL; +- int ret; ++ int ret, ival; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_HW_CONFIG); + if (!elem) +@@ -1178,11 +1178,11 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + + if (strcmp(id, "bclk_invert") == 0 || + strcmp(id, "invert_bclk") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ ival = snd_config_get_bool(n); ++ if (ival < 0) + return -EINVAL; + +- if (!strcmp(val, "true")) +- hw_cfg->invert_bclk = true; ++ hw_cfg->invert_bclk = ival; + continue; + } + +@@ -1209,11 +1209,11 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + + if (strcmp(id, "fsync_invert") == 0 || + strcmp(id, "invert_fsync") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ ival = snd_config_get_bool(n); ++ if (ival < 0) + return -EINVAL; + +- if (!strcmp(val, "true")) +- hw_cfg->invert_fsync = true; ++ hw_cfg->invert_fsync = ival; + continue; + } + +@@ -1254,10 +1254,11 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + + if (strcmp(id, "pm_gate_clocks") == 0 || + strcmp(id, "clock_gated") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ ival = snd_config_get_bool(n); ++ if (ival < 0) + return -EINVAL; + +- if (!strcmp(val, "true")) ++ if (ival) + hw_cfg->clock_gated = + SND_SOC_TPLG_DAI_CLK_GATE_GATED; + else +-- +2.24.1 + + +From 1047a5f3c0d39a3b0579db027f52d7facdf44077 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 14 Dec 2019 13:52:18 +0100 +Subject: [PATCH 35/69] topology: fix tplg_get_integer() - handle errno == + ERANGE + +Signed-off-by: Jaroslav Kysela +--- + src/topology/parser.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 7e657809..667c8d45 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -36,14 +36,19 @@ int tplg_get_integer(snd_config_t *n, int *val, int base) + if (err < 0) + return err; + if (lval < INT_MIN || lval > INT_MAX) +- return -EINVAL; ++ return -ERANGE; + *val = lval; + return err; + case SND_CONFIG_TYPE_STRING: + err = snd_config_get_string(n, &str); + if (err < 0) + return err; ++ errno = 0; + *val = strtol(str, NULL, base); ++ if (errno == ERANGE) ++ return -ERANGE; ++ if (errno && *val == 0) ++ return -EINVAL; + return 0; + default: + return -EINVAL; +-- +2.24.1 + + +From 14e43a11873d14ec6f16967c83629237ef44ac38 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 14 Dec 2019 14:05:49 +0100 +Subject: [PATCH 36/69] topology: add tplg_get_unsigned() function + +Signed-off-by: Jaroslav Kysela +--- + src/topology/data.c | 19 +++++----------- + src/topology/parser.c | 47 +++++++++++++++++++++++++++++++++++++++ + src/topology/pcm.c | 13 ++--------- + src/topology/tplg_local.h | 1 + + 4 files changed, 55 insertions(+), 25 deletions(-) + +diff --git a/src/topology/data.c b/src/topology/data.c +index 6b1337b3..9807445e 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -556,7 +556,7 @@ static int parse_tuple_set(snd_config_t *cfg, + struct tplg_tuple_set *set; + unsigned int type, num_tuples = 0; + struct tplg_tuple *tuple; +- unsigned long int tuple_val; ++ unsigned int tuple_val; + int ival; + + snd_config_get_id(cfg, &id); +@@ -598,10 +598,6 @@ static int parse_tuple_set(snd_config_t *cfg, + if (snd_config_get_id(n, &id) < 0) + continue; + +- /* get value */ +- if (snd_config_get_string(n, &value) < 0) +- continue; +- + tuple = &set->tuple[set->num_tuples]; + snd_strlcpy(tuple->token, id, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); +@@ -633,14 +629,9 @@ static int parse_tuple_set(snd_config_t *cfg, + case SND_SOC_TPLG_TUPLE_TYPE_BYTE: + case SND_SOC_TPLG_TUPLE_TYPE_SHORT: + case SND_SOC_TPLG_TUPLE_TYPE_WORD: +- if (snd_config_get_string(n, &value) < 0) +- continue; +- errno = 0; +- /* no support for negative value */ +- tuple_val = strtoul(value, NULL, 0); +- if ((errno == ERANGE && tuple_val == ULONG_MAX) +- || (errno != 0 && tuple_val == 0)) { +- SNDERR("error: tuple %s:strtoul fail\n", id); ++ ival = tplg_get_unsigned(n, &tuple_val, 0); ++ if (ival < 0) { ++ SNDERR("error: tuple %s: %s\n", id, snd_strerror(ival)); + goto err; + } + +@@ -654,7 +645,7 @@ static int parse_tuple_set(snd_config_t *cfg, + goto err; + } + +- tuple->value = (unsigned int) tuple_val; ++ tuple->value = tuple_val; + tplg_dbg("\t\t%s = 0x%x\n", tuple->token, tuple->value); + break; + +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 667c8d45..f56ad97e 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -55,6 +55,53 @@ int tplg_get_integer(snd_config_t *n, int *val, int base) + } + } + ++/* ++ * Get unsigned integer value ++ */ ++int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base) ++{ ++ const char *str; ++ long lval; ++ long long llval; ++ unsigned long uval; ++ int err; ++ ++ switch (snd_config_get_type(n)) { ++ case SND_CONFIG_TYPE_INTEGER: ++ err = snd_config_get_integer(n, &lval); ++ if (err < 0) ++ return err; ++ if (lval < 0 || lval > UINT_MAX) ++ return -ERANGE; ++ *val = lval; ++ return err; ++ case SND_CONFIG_TYPE_INTEGER64: ++ err = snd_config_get_integer64(n, &llval); ++ if (err < 0) ++ return err; ++ if (llval < 0 || llval > UINT_MAX) ++ return -ERANGE; ++ *val = llval; ++ return err; ++ case SND_CONFIG_TYPE_STRING: ++ err = snd_config_get_string(n, &str); ++ if (err < 0) ++ return err; ++ errno = 0; ++ uval = strtoul(str, NULL, base); ++ if (errno == ERANGE && uval == ULONG_MAX) ++ return -ERANGE; ++ if (errno && uval == 0) ++ return -EINVAL; ++ if (uval > UINT_MAX) ++ return -ERANGE; ++ *val = uval; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ + /* + * Parse compound + */ +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 6364e24f..9b87549c 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -606,8 +606,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + struct snd_soc_tplg_pcm *pcm = elem->pcm; + snd_config_iterator_t i, next; + snd_config_t *n; +- const char *id, *value = NULL; +- unsigned long int id_val; ++ const char *id; + + snd_config_get_id(cfg, &id); + tplg_dbg("\t\tFE DAI %s:\n", id); +@@ -622,19 +621,11 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + continue; + + if (strcmp(id, "id") == 0) { +- if (snd_config_get_string(n, &value) < 0) +- continue; +- errno = 0; +- /* no support for negative value */ +- id_val = strtoul(value, NULL, 0); +- if ((errno == ERANGE && id_val == ULONG_MAX) +- || (errno != 0 && id_val == 0) +- || id_val > UINT_MAX) { ++ if (tplg_get_unsigned(n, &pcm->dai_id, 0)) { + SNDERR("error: invalid fe dai ID\n"); + return -EINVAL; + } + +- pcm->dai_id = (int) id_val; + tplg_dbg("\t\t\tindex: %d\n", pcm->dai_id); + } + } +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 991e0b41..e16c78d4 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -281,6 +281,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + snd_config_t *cfg, const char *name, enum snd_tplg_type type); + + int tplg_get_integer(snd_config_t *n, int *val, int base); ++int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base); + + int tplg_parse_channel(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_config_t *cfg, void *private); +-- +2.24.1 + + +From 39fb37fef5bd3b3fa7a63e06a5f0a147197fddb9 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 14 Dec 2019 19:13:53 +0100 +Subject: [PATCH 37/69] topology: convert builder to use the mallocated memory + +Signed-off-by: Jaroslav Kysela +--- + src/topology/builder.c | 88 +++++++++++++++++++++++++++++++-------- + src/topology/parser.c | 74 +++++++++++++------------------- + src/topology/tplg_local.h | 5 ++- + 3 files changed, 103 insertions(+), 64 deletions(-) + +diff --git a/src/topology/builder.c b/src/topology/builder.c +index 1a22a453..40943b56 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->bin_pos, tplg->bin_pos); + vfprintf(stdout, fmt, va); + va_end(va); + } +@@ -37,18 +37,11 @@ static void verbose(snd_tplg_t *tplg, const char *fmt, ...) + /* 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)"); ++ if (tplg->bin_pos + data_size > tplg->bin_size) + return -EIO; +- } +- tplg->out_pos += r; +- return r; ++ memcpy(tplg->bin + tplg->bin_pos, data, data_size); ++ tplg->bin_pos += data_size; ++ return data_size; + } + + /* write out block header to output file */ +@@ -71,12 +64,12 @@ static ssize_t 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 (tplg->out_pos != tplg->next_hdr_pos) { ++ if (tplg->bin_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)); ++ tplg->next_hdr_pos, tplg->bin_pos, ++ tplg->bin_pos > tplg->next_hdr_pos ? "ahead" : "behind", ++ labs(tplg->bin_pos - tplg->next_hdr_pos)); + return -EINVAL; + } + +@@ -163,6 +156,41 @@ static int write_elem_block(snd_tplg_t *tplg, + return 0; + } + ++static size_t calc_manifest_size(snd_tplg_t *tplg) ++{ ++ return sizeof(struct snd_soc_tplg_hdr) + ++ sizeof(tplg->manifest) + ++ tplg->manifest.priv.size; ++} ++ ++static size_t calc_real_size(struct list_head *base) ++{ ++ struct list_head *pos; ++ struct tplg_elem *elem, *elem_next; ++ size_t size = 0; ++ ++ list_for_each(pos, base) { ++ ++ elem = list_entry(pos, struct tplg_elem, list); ++ ++ /* compound elems have already been copied to other elems */ ++ if (elem->compound_elem) ++ continue; ++ ++ if (elem->size <= 0) ++ continue; ++ ++ size += elem->size; ++ ++ elem_next = list_entry(pos->next, struct tplg_elem, list); ++ ++ if ((pos->next == base) || (elem_next->index != elem->index)) ++ size += sizeof(struct snd_soc_tplg_hdr); ++ } ++ ++ return size; ++} ++ + static size_t calc_block_size(struct list_head *base) + { + struct list_head *pos; +@@ -277,9 +305,27 @@ int tplg_write_data(snd_tplg_t *tplg) + }; + + ssize_t ret; +- size_t size; ++ size_t total_size, size; + unsigned int index; + ++ /* calculate total size */ ++ total_size = calc_manifest_size(tplg); ++ for (index = 0; index < ARRAY_SIZE(wtable); index++) { ++ wptr = &wtable[index]; ++ size = calc_real_size(wptr->list); ++ total_size += size; ++ } ++ ++ /* allocate new binary output */ ++ free(tplg->bin); ++ tplg->bin = malloc(total_size); ++ tplg->bin_pos = 0; ++ tplg->bin_size = total_size; ++ if (tplg->bin == NULL) { ++ tplg->bin_size = 0; ++ return -ENOMEM; ++ } ++ + /* write manifest */ + ret = write_manifest_data(tplg); + if (ret < 0) { +@@ -306,7 +352,13 @@ int tplg_write_data(snd_tplg_t *tplg) + } + } + +- verbose(tplg, "total size is 0x%zx/%zd\n", tplg->out_pos, tplg->out_pos); ++ verbose(tplg, "total size is 0x%zx/%zd\n", tplg->bin_pos, tplg->bin_pos); ++ ++ if (total_size != tplg->bin_pos) { ++ SNDERR("total size mismatch (%zd != %zd)\n", ++ total_size, tplg->bin_pos); ++ return -EINVAL; ++ } + + return 0; + } +diff --git a/src/topology/parser.c b/src/topology/parser.c +index f56ad97e..98a9f9e9 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -393,50 +393,29 @@ static int tplg_build_integ(snd_tplg_t *tplg) + return err; + } + +-int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile, +- const char *outfile) ++int snd_tplg_build_file(snd_tplg_t *tplg, ++ const char *infile, ++ const char *outfile) + { + snd_config_t *cfg = NULL; + int err = 0; + +- tplg->out_fd = +- open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); +- if (tplg->out_fd < 0) { +- SNDERR("error: failed to open %s err %d\n", +- outfile, -errno); +- return -errno; +- } +- + err = tplg_load_config(infile, &cfg); + if (err < 0) { + SNDERR("error: failed to load topology file %s\n", + infile); +- goto out_close; ++ return err; + } + + err = tplg_parse_config(tplg, cfg); + if (err < 0) { + SNDERR("error: failed to parse topology\n"); +- goto out; +- } +- +- err = tplg_build_integ(tplg); +- if (err < 0) { +- SNDERR("error: failed to check topology integrity\n"); +- goto out; +- } +- +- err = tplg_write_data(tplg); +- if (err < 0) { +- SNDERR("error: failed to write data %d\n", err); +- goto out; ++ return err; + } + +-out: + snd_config_delete(cfg); +-out_close: +- close(tplg->out_fd); +- return err; ++ ++ return snd_tplg_build(tplg, outfile); + } + + int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) +@@ -468,31 +447,38 @@ int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + + int snd_tplg_build(snd_tplg_t *tplg, const char *outfile) + { +- int err; +- +- tplg->out_fd = +- open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); +- if (tplg->out_fd < 0) { +- SNDERR("error: failed to open %s err %d\n", +- outfile, -errno); +- return -errno; +- } ++ int fd, err; ++ ssize_t r; + + err = tplg_build_integ(tplg); + if (err < 0) { + SNDERR("error: failed to check topology integrity\n"); +- goto out; ++ return err; + } + + err = tplg_write_data(tplg); + if (err < 0) { + SNDERR("error: failed to write data %d\n", err); +- goto out; ++ return err; + } + +-out: +- close(tplg->out_fd); +- return err; ++ fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); ++ if (fd < 0) { ++ SNDERR("error: failed to open %s err %d\n", outfile, -errno); ++ return -errno; ++ } ++ r = write(fd, tplg->bin, tplg->bin_size); ++ close(fd); ++ if (r < 0) { ++ err = -errno; ++ SNDERR("error: write error: %s\n", strerror(errno)); ++ return err; ++ } ++ if ((size_t)r != tplg->bin_size) { ++ SNDERR("error: partial write (%zd != %zd)\n", r, tplg->bin_size); ++ return -EIO; ++ } ++ return 0; + } + + int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len) +@@ -571,8 +557,8 @@ snd_tplg_t *snd_tplg_new(void) + + void snd_tplg_free(snd_tplg_t *tplg) + { +- if (tplg->manifest_pdata) +- free(tplg->manifest_pdata); ++ free(tplg->bin); ++ free(tplg->manifest_pdata); + + tplg_elem_free_list(&tplg->tlv_list); + tplg_elem_free_list(&tplg->widget_list); +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index e16c78d4..87e6c9a5 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -60,8 +60,9 @@ typedef enum _snd_pcm_rates { + + struct snd_tplg { + /* out file */ +- int out_fd; +- size_t out_pos; ++ unsigned char *bin; ++ size_t bin_pos; ++ size_t bin_size; + + int verbose; + unsigned int version; +-- +2.24.1 + + +From bee8d4fcaa52d00950d035ec561513c2b9e7cac7 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 14 Dec 2019 19:20:02 +0100 +Subject: [PATCH 38/69] topology: add binary output from the builder + +- snd_tplg_build_bin() +- snd_tplg_build_bin_file() + +Signed-off-by: Jaroslav Kysela +--- + include/topology.h | 22 +++++++++++- + src/topology/parser.c | 79 ++++++++++++++++++++++++++++++++++++------- + 2 files changed, 87 insertions(+), 14 deletions(-) + +diff --git a/include/topology.h b/include/topology.h +index 27da7308..c9ef554a 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -791,7 +791,18 @@ void snd_tplg_free(snd_tplg_t *tplg); + * \return Zero on success, otherwise a negative error code + */ + int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile, +- const char *outfile); ++ const char *outfile); ++ ++/** ++ * \brief Parse and build topology text file into binary file. ++ * \param tplg Topology instance. ++ * \param infile Topology text input file to be parsed ++ * \param bin Binary topology output buffer (malloc). ++ * \param size Binary topology output buffer size in bytes. ++ * \return Zero on success, otherwise a negative error code ++ */ ++int snd_tplg_build_bin_file(snd_tplg_t *tplg, const char *infile, ++ void **bin, size_t *size); + + /** + * \brief Enable verbose reporting of binary file output +@@ -1089,6 +1100,15 @@ int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); + */ + int snd_tplg_build(snd_tplg_t *tplg, const char *outfile); + ++/** ++ * \brief Build all registered topology data into memory. ++ * \param tplg Topology instance. ++ * \param bin Binary topology output buffer (malloc). ++ * \param size Binary topology output buffer size in bytes. ++ * \return Zero on success, otherwise a negative error code ++ */ ++int snd_tplg_build_bin(snd_tplg_t *tplg, void **bin, size_t *size); ++ + /** + * \brief Attach private data to topology manifest. + * \param tplg Topology instance. +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 98a9f9e9..861565b7 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -393,9 +393,7 @@ static int tplg_build_integ(snd_tplg_t *tplg) + return err; + } + +-int snd_tplg_build_file(snd_tplg_t *tplg, +- const char *infile, +- const char *outfile) ++static int tplg_load(snd_tplg_t *tplg, const char *infile) + { + snd_config_t *cfg = NULL; + int err = 0; +@@ -414,10 +412,53 @@ int snd_tplg_build_file(snd_tplg_t *tplg, + } + + snd_config_delete(cfg); ++ return 0; ++} ++ ++static int tplg_build(snd_tplg_t *tplg) ++{ ++ int err; ++ ++ err = tplg_build_integ(tplg); ++ if (err < 0) { ++ SNDERR("error: failed to check topology integrity\n"); ++ return err; ++ } ++ ++ err = tplg_write_data(tplg); ++ if (err < 0) { ++ SNDERR("error: failed to write data %d\n", err); ++ return err; ++ } ++ return 0; ++} ++ ++int snd_tplg_build_file(snd_tplg_t *tplg, ++ const char *infile, ++ const char *outfile) ++{ ++ int err; ++ ++ err = tplg_load(tplg, infile); ++ if (err < 0) ++ return err; + + return snd_tplg_build(tplg, outfile); + } + ++int snd_tplg_build_bin_file(snd_tplg_t *tplg, ++ const char *infile, ++ void **bin, size_t *size) ++{ ++ int err; ++ ++ err = tplg_load(tplg, infile); ++ if (err < 0) ++ return err; ++ ++ return snd_tplg_build_bin(tplg, bin, size); ++} ++ + int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + { + switch (t->type) { +@@ -450,17 +491,9 @@ int snd_tplg_build(snd_tplg_t *tplg, const char *outfile) + int fd, err; + ssize_t r; + +- err = tplg_build_integ(tplg); +- if (err < 0) { +- SNDERR("error: failed to check topology integrity\n"); +- return err; +- } +- +- err = tplg_write_data(tplg); +- if (err < 0) { +- SNDERR("error: failed to write data %d\n", err); ++ err = tplg_build(tplg); ++ if (err < 0) + return err; +- } + + fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd < 0) { +@@ -481,6 +514,26 @@ int snd_tplg_build(snd_tplg_t *tplg, const char *outfile) + return 0; + } + ++int snd_tplg_build_bin(snd_tplg_t *tplg, ++ void **bin, size_t *size) ++{ ++ int err; ++ ++ err = tplg_build(tplg); ++ if (err < 0) ++ return err; ++ ++ err = tplg_build(tplg); ++ if (err < 0) ++ return err; ++ ++ *bin = tplg->bin; ++ *size = tplg->bin_size; ++ tplg->bin = NULL; ++ tplg->bin_size = tplg->bin_pos = 0; ++ return 0; ++} ++ + int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len) + { + if (len <= 0) +-- +2.24.1 + + +From 22b66731f3dc0eb5149a99ff547eeb84eaf8d54b Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 14 Dec 2019 20:32:24 +0100 +Subject: [PATCH 39/69] topology: parser - recode tplg_parse_config() + +Signed-off-by: Jaroslav Kysela +--- + src/topology/parser.c | 225 +++++++++++++++----------------------- + src/topology/tplg_local.h | 67 +++--------- + 2 files changed, 108 insertions(+), 184 deletions(-) + +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 861565b7..82af7cc5 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -142,9 +142,88 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, + + static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + { ++ static struct _parser { ++ const char *id; ++ int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++ } *p, parsers[] = { ++ { ++ .id = "SectionTLV", ++ .parser = tplg_parse_tlv ++ }, ++ { ++ .id = "SectionControlMixer", ++ .parser = tplg_parse_control_mixer ++ }, ++ { ++ .id = "SectionControlEnum", ++ .parser = tplg_parse_control_enum ++ }, ++ { ++ .id = "SectionControlBytes", ++ .parser = tplg_parse_control_bytes ++ }, ++ { ++ .id = "SectionWidget", ++ .parser = tplg_parse_dapm_widget ++ }, ++ { ++ .id = "SectionPCMCapabilities", ++ .parser = tplg_parse_stream_caps ++ }, ++ { ++ .id = "SectionPCM", ++ .parser = tplg_parse_pcm ++ }, ++ { ++ .id = "SectionDAI", ++ .parser = tplg_parse_dai ++ }, ++ { ++ .id = "SectionHWConfig", ++ .parser = tplg_parse_hw_config ++ }, ++ { ++ .id = "SectionLink", ++ .parser = tplg_parse_link ++ }, ++ { ++ .id = "SectionBE", ++ .parser = tplg_parse_link ++ }, ++ { ++ .id = "SectionCC", ++ .parser = tplg_parse_cc ++ }, ++ { ++ .id = "SectionGraph", ++ .parser = tplg_parse_dapm_graph ++ }, ++ { ++ .id = "SectionText", ++ .parser = tplg_parse_text ++ }, ++ { ++ .id = "SectionData", ++ .parser = tplg_parse_data ++ }, ++ { ++ .id = "SectionVendorTokens", ++ .parser = tplg_parse_tokens ++ }, ++ { ++ .id = "SectionVendorTuples", ++ .parser = tplg_parse_tuples ++ }, ++ { ++ .id = "SectionManifest", ++ .parser = tplg_parse_manifest_data ++ }, ++ }; ++ int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); + snd_config_iterator_t i, next; + snd_config_t *n; + const char *id; ++ unsigned int idx; + int err; + + if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { +@@ -159,145 +238,23 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + if (snd_config_get_id(n, &id) < 0) + continue; + +- if (strcmp(id, "SectionTLV") == 0) { +- err = tplg_parse_compound(tplg, n, tplg_parse_tlv, +- NULL); +- if (err < 0) +- return err; +- continue; ++ parser = NULL; ++ for (idx = 0; idx < ARRAY_SIZE(parsers); idx++) { ++ p = &parsers[idx]; ++ if (strcmp(id, p->id) == 0) { ++ parser = p->parser; ++ break; ++ } + } + +- if (strcmp(id, "SectionControlMixer") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_control_mixer, NULL); +- if (err < 0) +- return err; ++ if (parser == NULL) { ++ SNDERR("error: unknown section %s\n", id); + continue; + } + +- if (strcmp(id, "SectionControlEnum") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_control_enum, NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionControlBytes") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_control_bytes, NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionWidget") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_dapm_widget, NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionPCMCapabilities") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_stream_caps, NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionPCM") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_pcm, NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionDAI") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_dai, NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionHWConfig") == 0) { +- err = tplg_parse_compound(tplg, n, tplg_parse_hw_config, +- NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionLink") == 0 +- || strcmp(id, "SectionBE") == 0) { +- err = tplg_parse_compound(tplg, n, tplg_parse_link, +- NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionCC") == 0) { +- err = tplg_parse_compound(tplg, n, tplg_parse_cc, +- NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionGraph") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_dapm_graph, NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionText") == 0) { +- err = tplg_parse_compound(tplg, n, tplg_parse_text, +- NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionData") == 0) { +- err = tplg_parse_compound(tplg, n, tplg_parse_data, +- NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionVendorTokens") == 0) { +- err = tplg_parse_compound(tplg, n, tplg_parse_tokens, +- NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionVendorTuples") == 0) { +- err = tplg_parse_compound(tplg, n, tplg_parse_tuples, +- NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- if (strcmp(id, "SectionManifest") == 0) { +- err = tplg_parse_compound(tplg, n, +- tplg_parse_manifest_data, +- NULL); +- if (err < 0) +- return err; +- continue; +- } +- +- SNDERR("error: unknown section %s\n", id); ++ err = tplg_parse_compound(tplg, n, parser, NULL); ++ if (err < 0) ++ return err; + } + return 0; + } +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 87e6c9a5..77a68189 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -202,59 +202,26 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, + + int tplg_write_data(snd_tplg_t *tplg); + +-int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); ++int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_control_bytes(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_control_mixer(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_dapm_widget(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_stream_caps(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_link(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_cc(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); + + void tplg_free_tuples(void *obj); + +-int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_control_bytes(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_control_mixer(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_dapm_widget(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_stream_caps(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_pcm(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_link(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_cc(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +- +-int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED); +- + int tplg_build_data(snd_tplg_t *tplg); + int tplg_build_manifest_data(snd_tplg_t *tplg); + int tplg_build_controls(snd_tplg_t *tplg); +-- +2.24.1 + + +From d52eaba63dfe1d845663a4cd1bf676fafc43874a Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 15 Dec 2019 16:03:29 +0100 +Subject: [PATCH 40/69] topology: add snd_tplg_load() remove + snd_tplg_build_bin_file() + +Signed-off-by: Jaroslav Kysela +--- + include/topology.h | 16 ++++---- + src/topology/parser.c | 96 +++++++++++++++---------------------------- + 2 files changed, 41 insertions(+), 71 deletions(-) + +diff --git a/include/topology.h b/include/topology.h +index c9ef554a..c9f4ffea 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -784,25 +784,23 @@ snd_tplg_t *snd_tplg_new(void); + void snd_tplg_free(snd_tplg_t *tplg); + + /** +- * \brief Parse and build topology text file into binary file. ++ * \brief Load topology from the text buffer. + * \param tplg Topology instance. +- * \param infile Topology text input file to be parsed +- * \param outfile Binary topology output file. ++ * \param buf Text buffer. ++ * \param size Text buffer size in bytes. + * \return Zero on success, otherwise a negative error code + */ +-int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile, +- const char *outfile); ++int snd_tplg_load(snd_tplg_t *tplg, const char *buf, size_t size); + + /** + * \brief Parse and build topology text file into binary file. + * \param tplg Topology instance. + * \param infile Topology text input file to be parsed +- * \param bin Binary topology output buffer (malloc). +- * \param size Binary topology output buffer size in bytes. ++ * \param outfile Binary topology output file. + * \return Zero on success, otherwise a negative error code + */ +-int snd_tplg_build_bin_file(snd_tplg_t *tplg, const char *infile, +- void **bin, size_t *size); ++int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile, ++ const char *outfile); + + /** + * \brief Enable verbose reporting of binary file output +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 82af7cc5..ed864d32 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -259,52 +259,30 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + return 0; + } + +-static int tplg_load_config(const char *file, snd_config_t **cfg) ++static int tplg_load_config(snd_tplg_t *tplg, snd_input_t *in) + { +- FILE *fp; +- snd_input_t *in; + snd_config_t *top; + int ret; + +- fp = fopen(file, "r"); +- if (fp == NULL) { +- SNDERR("error: could not open configuration file %s", +- file); +- return -errno; +- } +- +- ret = snd_input_stdio_attach(&in, fp, 1); +- if (ret < 0) { +- fclose(fp); +- SNDERR("error: could not attach stdio %s", file); +- return ret; +- } + ret = snd_config_top(&top); + if (ret < 0) +- goto err; ++ return ret; + + ret = snd_config_load(top, in); + if (ret < 0) { +- SNDERR("error: could not load configuration file %s", +- file); +- goto err_load; ++ SNDERR("error: could not load configuration"); ++ snd_config_delete(top); ++ return ret; + } + +- ret = snd_input_close(in); ++ ret = tplg_parse_config(tplg, top); ++ snd_config_delete(top); + if (ret < 0) { +- in = NULL; +- goto err_load; ++ SNDERR("error: failed to parse topology"); ++ return ret; + } + +- *cfg = top; + return 0; +- +-err_load: +- snd_config_delete(top); +-err: +- if (in) +- snd_input_close(in); +- return ret; + } + + static int tplg_build_integ(snd_tplg_t *tplg) +@@ -350,26 +328,20 @@ static int tplg_build_integ(snd_tplg_t *tplg) + return err; + } + +-static int tplg_load(snd_tplg_t *tplg, const char *infile) ++int snd_tplg_load(snd_tplg_t *tplg, const char *buf, size_t size) + { +- snd_config_t *cfg = NULL; +- int err = 0; +- +- err = tplg_load_config(infile, &cfg); +- if (err < 0) { +- SNDERR("error: failed to load topology file %s\n", +- infile); +- return err; +- } ++ snd_input_t *in; ++ int err; + +- err = tplg_parse_config(tplg, cfg); ++ err = snd_input_buffer_open(&in, buf, size); + if (err < 0) { +- SNDERR("error: failed to parse topology\n"); ++ SNDERR("error: could not create input buffer"); + return err; + } + +- snd_config_delete(cfg); +- return 0; ++ err = tplg_load_config(tplg, in); ++ snd_input_close(in); ++ return err; + } + + static int tplg_build(snd_tplg_t *tplg) +@@ -394,26 +366,30 @@ int snd_tplg_build_file(snd_tplg_t *tplg, + const char *infile, + const char *outfile) + { ++ FILE *fp; ++ snd_input_t *in; + int err; + +- err = tplg_load(tplg, infile); +- if (err < 0) +- return err; +- +- return snd_tplg_build(tplg, outfile); +-} ++ fp = fopen(infile, "r"); ++ if (fp == NULL) { ++ SNDERR("error: could not open configuration file %s", ++ infile); ++ return -errno; ++ } + +-int snd_tplg_build_bin_file(snd_tplg_t *tplg, +- const char *infile, +- void **bin, size_t *size) +-{ +- int err; ++ err = snd_input_stdio_attach(&in, fp, 1); ++ if (err < 0) { ++ fclose(fp); ++ SNDERR("error: could not attach stdio %s", infile); ++ return err; ++ } + +- err = tplg_load(tplg, infile); ++ err = tplg_load_config(tplg, in); ++ snd_input_close(in); + if (err < 0) + return err; + +- return snd_tplg_build_bin(tplg, bin, size); ++ return snd_tplg_build(tplg, outfile); + } + + int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) +@@ -476,10 +452,6 @@ int snd_tplg_build_bin(snd_tplg_t *tplg, + { + int err; + +- err = tplg_build(tplg); +- if (err < 0) +- return err; +- + err = tplg_build(tplg); + if (err < 0) + return err; +-- +2.24.1 + + +From 4f076f5b69a873418ecb826a4198e4d95a3a2a6f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 15 Dec 2019 16:15:29 +0100 +Subject: [PATCH 41/69] topology: move the topology element table from builder + to elem + +- use offsetof() for the lists +- add other info to describe the elements +- use the table in the element constructor + +Signed-off-by: Jaroslav Kysela +--- + src/topology/builder.c | 98 ++++------------ + src/topology/ctl.c | 7 +- + src/topology/elem.c | 232 +++++++++++++++++++++++++++----------- + src/topology/tplg_local.h | 15 +++ + 4 files changed, 199 insertions(+), 153 deletions(-) + +diff --git a/src/topology/builder.c b/src/topology/builder.c +index 40943b56..cadb5583 100644 +--- a/src/topology/builder.c ++++ b/src/topology/builder.c +@@ -236,83 +236,20 @@ 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; +- int tsoc; +- } *wptr, wtable[] = { +- { +- .name = "control mixer", +- .list = &tplg->mixer_list, +- .type = SND_TPLG_TYPE_MIXER, +- .tsoc = SND_SOC_TPLG_TYPE_MIXER, +- }, +- { +- .name = "control enum", +- .list = &tplg->enum_list, +- .type = SND_TPLG_TYPE_ENUM, +- .tsoc = SND_SOC_TPLG_TYPE_ENUM, +- }, +- { +- .name = "control extended (bytes)", +- .list = &tplg->bytes_ext_list, +- .type = SND_TPLG_TYPE_BYTES, +- .tsoc = SND_SOC_TPLG_TYPE_BYTES, +- }, +- { +- .name = "dapm widget", +- .list = &tplg->widget_list, +- .type = SND_TPLG_TYPE_DAPM_WIDGET, +- .tsoc = SND_SOC_TPLG_TYPE_DAPM_WIDGET, +- }, +- { +- .name = "pcm", +- .list = &tplg->pcm_list, +- .type = SND_TPLG_TYPE_PCM, +- .tsoc = SND_SOC_TPLG_TYPE_PCM, +- }, +- { +- .name = "physical dai", +- .list = &tplg->dai_list, +- .type = SND_TPLG_TYPE_DAI, +- .tsoc = SND_SOC_TPLG_TYPE_DAI, +- }, +- { +- .name = "be", +- .list = &tplg->be_list, +- .type = SND_TPLG_TYPE_BE, +- .tsoc = SND_SOC_TPLG_TYPE_BACKEND_LINK, +- }, +- { +- .name = "cc", +- .list = &tplg->cc_list, +- .type = SND_TPLG_TYPE_CC, +- .tsoc = SND_SOC_TPLG_TYPE_CODEC_LINK, +- }, +- { +- .name = "route (dapm graph)", +- .list = &tplg->route_list, +- .type = SND_TPLG_TYPE_DAPM_GRAPH, +- .tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH, +- }, +- { +- .name = "private data", +- .list = &tplg->pdata_list, +- .type = SND_TPLG_TYPE_DATA, +- .tsoc = SND_SOC_TPLG_TYPE_PDATA, +- }, +- }; +- ++ struct tplg_table *tptr; ++ struct list_head *list; + ssize_t ret; + size_t total_size, size; + unsigned int index; + + /* calculate total size */ + total_size = calc_manifest_size(tplg); +- for (index = 0; index < ARRAY_SIZE(wtable); index++) { +- wptr = &wtable[index]; +- size = calc_real_size(wptr->list); ++ for (index = 0; index < tplg_table_items; index++) { ++ tptr = &tplg_table[index]; ++ if (!tptr->build) ++ continue; ++ list = (struct list_head *)((void *)tplg + tptr->loff); ++ size = calc_real_size(list); + total_size += size; + } + +@@ -334,20 +271,23 @@ int tplg_write_data(snd_tplg_t *tplg) + } + + /* write all blocks */ +- for (index = 0; index < ARRAY_SIZE(wtable); index++) { +- wptr = &wtable[index]; ++ for (index = 0; index < tplg_table_items; index++) { ++ tptr = &tplg_table[index]; ++ if (!tptr->build) ++ continue; ++ list = (struct list_head *)((void *)tplg + tptr->loff); + /* calculate the block size in bytes for all elems in this list */ +- size = calc_block_size(wptr->list); ++ size = calc_block_size(list); + if (size == 0) + continue; + verbose(tplg, "block size for type %s (%d:%d) is 0x%zx/%zd\n", +- wptr->name, wptr->type, +- wptr->tsoc, size, size); +- ret = write_elem_block(tplg, wptr->list, size, +- wptr->tsoc, wptr->name); ++ tptr->name, tptr->type, ++ tptr->tsoc, size, size); ++ ret = write_elem_block(tplg, list, size, ++ tptr->tsoc, tptr->name); + if (ret < 0) { + SNDERR("failed to write %s elements: %s\n", +- wptr->name, snd_strerror(-ret)); ++ tptr->name, snd_strerror(-ret)); + return ret; + } + } +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index 9190efef..539329cd 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -284,18 +284,13 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem) + { + snd_config_iterator_t i, next; + snd_config_t *n; +- struct snd_soc_tplg_ctl_tlv *tplg_tlv; ++ struct snd_soc_tplg_ctl_tlv *tplg_tlv = elem->tlv; + struct snd_soc_tplg_tlv_dbscale *scale; + const char *id = NULL; + int val; + + tplg_dbg(" scale: %s\n", elem->id); + +- tplg_tlv = calloc(1, sizeof(*tplg_tlv)); +- if (!tplg_tlv) +- return -ENOMEM; +- +- elem->tlv = tplg_tlv; + tplg_tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv); + tplg_tlv->type = SNDRV_CTL_TLVT_DB_SCALE; + scale = &tplg_tlv->scale; +diff --git a/src/topology/elem.c b/src/topology/elem.c +index f2076f79..92ca7da4 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -20,6 +20,154 @@ + #include "list.h" + #include "tplg_local.h" + ++struct tplg_table tplg_table[] = { ++ { ++ .name = "manifest", ++ .loff = offsetof(snd_tplg_t, manifest_list), ++ .type = SND_TPLG_TYPE_MANIFEST, ++ .tsoc = SND_SOC_TPLG_TYPE_MANIFEST, ++ .size = sizeof(struct snd_soc_tplg_manifest), ++ .enew = 1, ++ }, ++ { ++ .name = "control mixer", ++ .loff = offsetof(snd_tplg_t, mixer_list), ++ .type = SND_TPLG_TYPE_MIXER, ++ .tsoc = SND_SOC_TPLG_TYPE_MIXER, ++ .size = sizeof(struct snd_soc_tplg_mixer_control), ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "control enum", ++ .loff = offsetof(snd_tplg_t, enum_list), ++ .type = SND_TPLG_TYPE_ENUM, ++ .tsoc = SND_SOC_TPLG_TYPE_ENUM, ++ .size = sizeof(struct snd_soc_tplg_enum_control), ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "control extended (bytes)", ++ .loff = offsetof(snd_tplg_t, bytes_ext_list), ++ .type = SND_TPLG_TYPE_BYTES, ++ .tsoc = SND_SOC_TPLG_TYPE_BYTES, ++ .size = sizeof(struct snd_soc_tplg_bytes_control), ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "dapm widget", ++ .loff = offsetof(snd_tplg_t, widget_list), ++ .type = SND_TPLG_TYPE_DAPM_WIDGET, ++ .tsoc = SND_SOC_TPLG_TYPE_DAPM_WIDGET, ++ .size = sizeof(struct snd_soc_tplg_dapm_widget), ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "pcm", ++ .loff = offsetof(snd_tplg_t, pcm_list), ++ .type = SND_TPLG_TYPE_PCM, ++ .tsoc = SND_SOC_TPLG_TYPE_PCM, ++ .size = sizeof(struct snd_soc_tplg_pcm), ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "physical dai", ++ .loff = offsetof(snd_tplg_t, dai_list), ++ .type = SND_TPLG_TYPE_DAI, ++ .tsoc = SND_SOC_TPLG_TYPE_DAI, ++ .size = sizeof(struct snd_soc_tplg_dai), ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "be", ++ .loff = offsetof(snd_tplg_t, be_list), ++ .type = SND_TPLG_TYPE_BE, ++ .tsoc = SND_SOC_TPLG_TYPE_BACKEND_LINK, ++ .size = sizeof(struct snd_soc_tplg_link_config), ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "cc", ++ .loff = offsetof(snd_tplg_t, cc_list), ++ .type = SND_TPLG_TYPE_CC, ++ .tsoc = SND_SOC_TPLG_TYPE_CODEC_LINK, ++ .size = sizeof(struct snd_soc_tplg_link_config), ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "route (dapm graph)", ++ .loff = offsetof(snd_tplg_t, route_list), ++ .type = SND_TPLG_TYPE_DAPM_GRAPH, ++ .tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH, ++ .build = 1, ++ }, ++ { ++ .name = "private data", ++ .loff = offsetof(snd_tplg_t, pdata_list), ++ .type = SND_TPLG_TYPE_DATA, ++ .tsoc = SND_SOC_TPLG_TYPE_PDATA, ++ .build = 1, ++ .enew = 1, ++ }, ++ { ++ .name = "text", ++ .loff = offsetof(snd_tplg_t, text_list), ++ .type = SND_TPLG_TYPE_TEXT, ++ .size = sizeof(struct tplg_texts), ++ .enew = 1, ++ }, ++ { ++ .name = "tlv", ++ .loff = offsetof(snd_tplg_t, tlv_list), ++ .type = SND_TPLG_TYPE_TLV, ++ .size = sizeof(struct snd_soc_tplg_ctl_tlv), ++ .enew = 1, ++ }, ++ { ++ .name = "stream config", ++ .loff = offsetof(snd_tplg_t, pcm_config_list), ++ .type = SND_TPLG_TYPE_STREAM_CONFIG, ++ .size = sizeof(struct snd_soc_tplg_stream), ++ .enew = 1, ++ }, ++ { ++ .name = "stream capabilities", ++ .loff = offsetof(snd_tplg_t, pcm_caps_list), ++ .type = SND_TPLG_TYPE_STREAM_CAPS, ++ .size = sizeof(struct snd_soc_tplg_stream_caps), ++ .enew = 1, ++ }, ++ { ++ .name = "token", ++ .loff = offsetof(snd_tplg_t, token_list), ++ .type = SND_TPLG_TYPE_TOKEN, ++ .enew = 1, ++ }, ++ { ++ .name = "tuple", ++ .loff = offsetof(snd_tplg_t, tuple_list), ++ .type = SND_TPLG_TYPE_TUPLE, ++ .free = tplg_free_tuples, ++ .enew = 1, ++ }, ++ { ++ .name = "hw config", ++ .loff = offsetof(snd_tplg_t, hw_cfg_list), ++ .type = SND_TPLG_TYPE_HW_CONFIG, ++ .size = sizeof(struct snd_soc_tplg_hw_config), ++ .enew = 1, ++ } ++}; ++ ++unsigned int tplg_table_items = ARRAY_SIZE(tplg_table); ++ + int tplg_ref_add(struct tplg_elem *elem, int type, const char* id) + { + struct tplg_ref *ref; +@@ -152,9 +300,12 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + const char *name, + enum snd_tplg_type type) + { ++ struct tplg_table *tptr; + struct tplg_elem *elem; ++ struct list_head *list; + const char *id; + int obj_size = 0; ++ unsigned index; + void *obj; + snd_config_iterator_t i, next; + snd_config_t *n; +@@ -191,79 +342,24 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + } else if (name != NULL) + snd_strlcpy(elem->id, name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + +- switch (type) { +- case SND_TPLG_TYPE_DATA: +- tplg_elem_insert(elem, &tplg->pdata_list); +- break; +- case SND_TPLG_TYPE_MANIFEST: +- tplg_elem_insert(elem, &tplg->manifest_list); +- obj_size = sizeof(struct snd_soc_tplg_manifest); +- break; +- case SND_TPLG_TYPE_TEXT: +- tplg_elem_insert(elem, &tplg->text_list); +- obj_size = sizeof(struct tplg_texts); +- break; +- case SND_TPLG_TYPE_TLV: +- tplg_elem_insert(elem, &tplg->tlv_list); +- elem->size = sizeof(struct snd_soc_tplg_ctl_tlv); +- break; +- case SND_TPLG_TYPE_BYTES: +- tplg_elem_insert(elem, &tplg->bytes_ext_list); +- obj_size = sizeof(struct snd_soc_tplg_bytes_control); +- break; +- case SND_TPLG_TYPE_ENUM: +- tplg_elem_insert(elem, &tplg->enum_list); +- obj_size = sizeof(struct snd_soc_tplg_enum_control); +- break; +- case SND_TPLG_TYPE_MIXER: +- tplg_elem_insert(elem, &tplg->mixer_list); +- obj_size = sizeof(struct snd_soc_tplg_mixer_control); +- break; +- case SND_TPLG_TYPE_DAPM_WIDGET: +- tplg_elem_insert(elem, &tplg->widget_list); +- obj_size = sizeof(struct snd_soc_tplg_dapm_widget); +- break; +- case SND_TPLG_TYPE_STREAM_CONFIG: +- tplg_elem_insert(elem, &tplg->pcm_config_list); +- obj_size = sizeof(struct snd_soc_tplg_stream); ++ for (index = 0; index < tplg_table_items; index++) { ++ tptr = &tplg_table[index]; ++ if (!tptr->enew) ++ continue; ++ if ((int)type != tptr->type) ++ continue; + break; +- case SND_TPLG_TYPE_STREAM_CAPS: +- tplg_elem_insert(elem, &tplg->pcm_caps_list); +- obj_size = sizeof(struct snd_soc_tplg_stream_caps); +- break; +- case SND_TPLG_TYPE_PCM: +- tplg_elem_insert(elem, &tplg->pcm_list); +- obj_size = sizeof(struct snd_soc_tplg_pcm); +- break; +- case SND_TPLG_TYPE_DAI: +- tplg_elem_insert(elem, &tplg->dai_list); +- obj_size = sizeof(struct snd_soc_tplg_dai); +- break; +- case SND_TPLG_TYPE_BE: +- case SND_TPLG_TYPE_LINK: +- tplg_elem_insert(elem, &tplg->be_list); +- obj_size = sizeof(struct snd_soc_tplg_link_config); +- break; +- case SND_TPLG_TYPE_CC: +- tplg_elem_insert(elem, &tplg->cc_list); +- obj_size = sizeof(struct snd_soc_tplg_link_config); +- break; +- case SND_TPLG_TYPE_TOKEN: +- tplg_elem_insert(elem, &tplg->token_list); +- break; +- case SND_TPLG_TYPE_TUPLE: +- tplg_elem_insert(elem, &tplg->tuple_list); +- elem->free = tplg_free_tuples; +- break; +- case SND_TPLG_TYPE_HW_CONFIG: +- tplg_elem_insert(elem, &tplg->hw_cfg_list); +- obj_size = sizeof(struct snd_soc_tplg_hw_config); +- break; +- default: ++ } ++ if (index >= tplg_table_items) { + free(elem); + return NULL; + } + ++ list = (struct list_head *)((void *)tplg + tptr->loff); ++ tplg_elem_insert(elem, list); ++ obj_size = tptr->size; ++ elem->free = tptr->free; ++ + /* create new object too if required */ + if (obj_size > 0) { + obj = calloc(1, obj_size); +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 77a68189..0987898f 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -196,6 +196,21 @@ struct map_elem { + int id; + }; + ++/* mapping table */ ++struct tplg_table { ++ const char *name; ++ off_t loff; ++ size_t size; ++ int type; ++ int tsoc; ++ unsigned build: 1; ++ unsigned enew: 1; ++ void (*free)(void *); ++}; ++ ++extern struct tplg_table tplg_table[]; ++extern unsigned int tplg_table_items; ++ + int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, + int (*fcn)(snd_tplg_t *, snd_config_t *, void *), + void *private); +-- +2.24.1 + + +From 4a0efdc87355d5789876e20b9530dc85224ad281 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 15 Dec 2019 17:24:50 +0100 +Subject: [PATCH 42/69] topology: add parser to the tplg_table + +Signed-off-by: Jaroslav Kysela +--- + src/topology/elem.c | 35 +++++++++++++++ + src/topology/parser.c | 90 ++++----------------------------------- + src/topology/tplg_local.h | 3 ++ + 3 files changed, 47 insertions(+), 81 deletions(-) + +diff --git a/src/topology/elem.c b/src/topology/elem.c +index 92ca7da4..e79a68b7 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -23,112 +23,139 @@ + struct tplg_table tplg_table[] = { + { + .name = "manifest", ++ .id = "SectionManifest", + .loff = offsetof(snd_tplg_t, manifest_list), + .type = SND_TPLG_TYPE_MANIFEST, + .tsoc = SND_SOC_TPLG_TYPE_MANIFEST, + .size = sizeof(struct snd_soc_tplg_manifest), + .enew = 1, ++ .parse = tplg_parse_manifest_data, + }, + { + .name = "control mixer", ++ .id = "SectionControlMixer", + .loff = offsetof(snd_tplg_t, mixer_list), + .type = SND_TPLG_TYPE_MIXER, + .tsoc = SND_SOC_TPLG_TYPE_MIXER, + .size = sizeof(struct snd_soc_tplg_mixer_control), + .build = 1, + .enew = 1, ++ .parse = tplg_parse_control_mixer, + }, + { + .name = "control enum", ++ .id = "SectionControlEnum", + .loff = offsetof(snd_tplg_t, enum_list), + .type = SND_TPLG_TYPE_ENUM, + .tsoc = SND_SOC_TPLG_TYPE_ENUM, + .size = sizeof(struct snd_soc_tplg_enum_control), + .build = 1, + .enew = 1, ++ .parse = tplg_parse_control_enum, + }, + { + .name = "control extended (bytes)", ++ .id = "SectionControlBytes", + .loff = offsetof(snd_tplg_t, bytes_ext_list), + .type = SND_TPLG_TYPE_BYTES, + .tsoc = SND_SOC_TPLG_TYPE_BYTES, + .size = sizeof(struct snd_soc_tplg_bytes_control), + .build = 1, + .enew = 1, ++ .parse = tplg_parse_control_bytes, + }, + { + .name = "dapm widget", ++ .id = "SectionWidget", + .loff = offsetof(snd_tplg_t, widget_list), + .type = SND_TPLG_TYPE_DAPM_WIDGET, + .tsoc = SND_SOC_TPLG_TYPE_DAPM_WIDGET, + .size = sizeof(struct snd_soc_tplg_dapm_widget), + .build = 1, + .enew = 1, ++ .parse = tplg_parse_dapm_widget, + }, + { + .name = "pcm", ++ .id = "SectionPCM", + .loff = offsetof(snd_tplg_t, pcm_list), + .type = SND_TPLG_TYPE_PCM, + .tsoc = SND_SOC_TPLG_TYPE_PCM, + .size = sizeof(struct snd_soc_tplg_pcm), + .build = 1, + .enew = 1, ++ .parse = tplg_parse_pcm, + }, + { + .name = "physical dai", ++ .id = "SectionDAI", + .loff = offsetof(snd_tplg_t, dai_list), + .type = SND_TPLG_TYPE_DAI, + .tsoc = SND_SOC_TPLG_TYPE_DAI, + .size = sizeof(struct snd_soc_tplg_dai), + .build = 1, + .enew = 1, ++ .parse = tplg_parse_dai, + }, + { + .name = "be", ++ .id = "SectionBE", ++ .id2 = "SectionLink", + .loff = offsetof(snd_tplg_t, be_list), + .type = SND_TPLG_TYPE_BE, + .tsoc = SND_SOC_TPLG_TYPE_BACKEND_LINK, + .size = sizeof(struct snd_soc_tplg_link_config), + .build = 1, + .enew = 1, ++ .parse = tplg_parse_link, + }, + { + .name = "cc", ++ .id = "SectionCC", + .loff = offsetof(snd_tplg_t, cc_list), + .type = SND_TPLG_TYPE_CC, + .tsoc = SND_SOC_TPLG_TYPE_CODEC_LINK, + .size = sizeof(struct snd_soc_tplg_link_config), + .build = 1, + .enew = 1, ++ .parse = tplg_parse_cc, + }, + { + .name = "route (dapm graph)", ++ .id = "SectionGraph", + .loff = offsetof(snd_tplg_t, route_list), + .type = SND_TPLG_TYPE_DAPM_GRAPH, + .tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH, + .build = 1, ++ .parse = tplg_parse_dapm_graph, + }, + { + .name = "private data", ++ .id = "SectionData", + .loff = offsetof(snd_tplg_t, pdata_list), + .type = SND_TPLG_TYPE_DATA, + .tsoc = SND_SOC_TPLG_TYPE_PDATA, + .build = 1, + .enew = 1, ++ .parse = tplg_parse_data, + }, + { + .name = "text", ++ .id = "SectionText", + .loff = offsetof(snd_tplg_t, text_list), + .type = SND_TPLG_TYPE_TEXT, + .size = sizeof(struct tplg_texts), + .enew = 1, ++ .parse = tplg_parse_text, + }, + { + .name = "tlv", ++ .id = "SectionTLV", + .loff = offsetof(snd_tplg_t, tlv_list), + .type = SND_TPLG_TYPE_TLV, + .size = sizeof(struct snd_soc_tplg_ctl_tlv), + .enew = 1, ++ .parse = tplg_parse_tlv, + }, + { + .name = "stream config", +@@ -139,30 +166,38 @@ struct tplg_table tplg_table[] = { + }, + { + .name = "stream capabilities", ++ .id = "SectionPCMCapabilities", + .loff = offsetof(snd_tplg_t, pcm_caps_list), + .type = SND_TPLG_TYPE_STREAM_CAPS, + .size = sizeof(struct snd_soc_tplg_stream_caps), + .enew = 1, ++ .parse = tplg_parse_stream_caps, + }, + { + .name = "token", ++ .id = "SectionVendorTokens", + .loff = offsetof(snd_tplg_t, token_list), + .type = SND_TPLG_TYPE_TOKEN, + .enew = 1, ++ .parse = tplg_parse_tokens, + }, + { + .name = "tuple", ++ .id = "SectionVendorTuples", + .loff = offsetof(snd_tplg_t, tuple_list), + .type = SND_TPLG_TYPE_TUPLE, + .free = tplg_free_tuples, + .enew = 1, ++ .parse = tplg_parse_tuples, + }, + { + .name = "hw config", ++ .id = "SectionHWConfig", + .loff = offsetof(snd_tplg_t, hw_cfg_list), + .type = SND_TPLG_TYPE_HW_CONFIG, + .size = sizeof(struct snd_soc_tplg_hw_config), + .enew = 1, ++ .parse = tplg_parse_hw_config, + } + }; + +diff --git a/src/topology/parser.c b/src/topology/parser.c +index ed864d32..11202769 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -142,87 +142,11 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, + + static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + { +- static struct _parser { +- const char *id; +- int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); +- } *p, parsers[] = { +- { +- .id = "SectionTLV", +- .parser = tplg_parse_tlv +- }, +- { +- .id = "SectionControlMixer", +- .parser = tplg_parse_control_mixer +- }, +- { +- .id = "SectionControlEnum", +- .parser = tplg_parse_control_enum +- }, +- { +- .id = "SectionControlBytes", +- .parser = tplg_parse_control_bytes +- }, +- { +- .id = "SectionWidget", +- .parser = tplg_parse_dapm_widget +- }, +- { +- .id = "SectionPCMCapabilities", +- .parser = tplg_parse_stream_caps +- }, +- { +- .id = "SectionPCM", +- .parser = tplg_parse_pcm +- }, +- { +- .id = "SectionDAI", +- .parser = tplg_parse_dai +- }, +- { +- .id = "SectionHWConfig", +- .parser = tplg_parse_hw_config +- }, +- { +- .id = "SectionLink", +- .parser = tplg_parse_link +- }, +- { +- .id = "SectionBE", +- .parser = tplg_parse_link +- }, +- { +- .id = "SectionCC", +- .parser = tplg_parse_cc +- }, +- { +- .id = "SectionGraph", +- .parser = tplg_parse_dapm_graph +- }, +- { +- .id = "SectionText", +- .parser = tplg_parse_text +- }, +- { +- .id = "SectionData", +- .parser = tplg_parse_data +- }, +- { +- .id = "SectionVendorTokens", +- .parser = tplg_parse_tokens +- }, +- { +- .id = "SectionVendorTuples", +- .parser = tplg_parse_tuples +- }, +- { +- .id = "SectionManifest", +- .parser = tplg_parse_manifest_data +- }, +- }; + int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); + snd_config_iterator_t i, next; + snd_config_t *n; + const char *id; ++ struct tplg_table *p; + unsigned int idx; + int err; + +@@ -239,10 +163,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + continue; + + parser = NULL; +- for (idx = 0; idx < ARRAY_SIZE(parsers); idx++) { +- p = &parsers[idx]; +- if (strcmp(id, p->id) == 0) { +- parser = p->parser; ++ for (idx = 0; idx < tplg_table_items; idx++) { ++ p = &tplg_table[idx]; ++ if (p->id && strcmp(id, p->id) == 0) { ++ parser = p->parse; ++ break; ++ } ++ if (p->id2 && strcmp(id, p->id2) == 0) { ++ parser = p->parse; + break; + } + } +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 0987898f..bea88ba3 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -199,6 +199,8 @@ struct map_elem { + /* mapping table */ + struct tplg_table { + const char *name; ++ const char *id; ++ const char *id2; + off_t loff; + size_t size; + int type; +@@ -206,6 +208,7 @@ struct tplg_table { + unsigned build: 1; + unsigned enew: 1; + void (*free)(void *); ++ int (*parse)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); + }; + + extern struct tplg_table tplg_table[]; +-- +2.24.1 + + +From aa1bac2d04bd1fb4ccae96a1136e60454298a710 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 16 Dec 2019 14:26:31 +0100 +Subject: [PATCH 43/69] topology: add snd_tplg_save() + +Signed-off-by: Jaroslav Kysela +--- + include/topology.h | 15 + + src/conf.c | 17 + + src/topology/Makefile.am | 3 +- + src/topology/channel.c | 45 +++ + src/topology/ctl.c | 201 +++++++++++- + src/topology/dapm.c | 209 +++++++++---- + src/topology/data.c | 601 +++++++++++++++++++++++++++++------- + src/topology/elem.c | 18 ++ + src/topology/ops.c | 92 ++++++ + src/topology/parser.c | 4 + + src/topology/pcm.c | 505 ++++++++++++++++++++++++++---- + src/topology/save.c | 632 ++++++++++++++++++++++++++++++++++++++ + src/topology/text.c | 19 ++ + src/topology/tplg_local.h | 58 +++- + 14 files changed, 2162 insertions(+), 257 deletions(-) + create mode 100644 src/topology/save.c + +diff --git a/include/topology.h b/include/topology.h +index c9f4ffea..69aa5ed7 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -1124,6 +1124,21 @@ int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len); + */ + int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version); + ++/* ++ * Flags for the snd_tplg_save() ++ */ ++#define SND_TPLG_SAVE_SORT (1<<0) /*!< sort identifiers */ ++#define SND_TPLG_SAVE_GROUPS (1<<1) /*!< create the structure by group index */ ++#define SND_TPLG_SAVE_NOCHECK (1<<16) /*!< unchecked output for debugging */ ++ ++/** ++ * \brief Save the topology to the text configuration string. ++ * \param tplg Topology instance. ++ * \param dst A pointer to string with result (malloc). ++ * \return Zero on success, otherwise a negative error code ++ */ ++int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags); ++ + /* \} */ + + #ifdef __cplusplus +diff --git a/src/conf.c b/src/conf.c +index 3e753b26..c4db9f21 100644 +--- a/src/conf.c ++++ b/src/conf.c +@@ -874,6 +874,21 @@ static int get_nonwhite(input_t *input) + } + } + ++static inline int get_hexachar(input_t *input) ++{ ++ int c, num = 0; ++ ++ c = get_char(input); ++ if (c >= '0' && c <= '9') num |= (c - '0') << 4; ++ else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 4; ++ else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 4; ++ c = get_char(input); ++ if (c >= '0' && c <= '9') num |= (c - '0') << 0; ++ else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 0; ++ else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 0; ++ return c; ++} ++ + static int get_quotedchar(input_t *input) + { + int c; +@@ -891,6 +906,8 @@ static int get_quotedchar(input_t *input) + return '\r'; + case 'f': + return '\f'; ++ case 'x': ++ return get_hexachar(input); + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + { +diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am +index 9dc472d6..a850ec4c 100644 +--- a/src/topology/Makefile.am ++++ b/src/topology/Makefile.am +@@ -27,7 +27,8 @@ libatopology_la_SOURCES =\ + text.c \ + channel.c \ + ops.c \ +- elem.c ++ elem.c \ ++ save.c + + noinst_HEADERS = tplg_local.h + +diff --git a/src/topology/channel.c b/src/topology/channel.c +index 4569eb31..b54a10c8 100644 +--- a/src/topology/channel.c ++++ b/src/topology/channel.c +@@ -73,6 +73,18 @@ static int lookup_channel(const char *c) + return -EINVAL; + } + ++const char *tplg_channel_name(int type) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(channel_map); i++) { ++ if (channel_map[i].id == type) ++ return channel_map[i].name; ++ } ++ ++ return NULL; ++} ++ + /* Parse a channel mapping. */ + int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + void *private) +@@ -123,3 +135,36 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + tplg->channel_idx++; + return 0; + } ++ ++int tplg_save_channels(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct snd_soc_tplg_channel *channel, ++ unsigned int count, char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_channel *c; ++ const char *s; ++ unsigned int index; ++ int err; ++ ++ if (count == 0) ++ return 0; ++ err = tplg_save_printf(dst, pfx, "channel {\n"); ++ for (index = 0; err >= 0 && index < count; index++) { ++ c = channel + index; ++ s = tplg_channel_name(c->id); ++ if (s == NULL) ++ err = tplg_save_printf(dst, pfx, "\t%u", c->id); ++ else ++ err = tplg_save_printf(dst, pfx, "\t%s", s); ++ if (err >= 0) ++ err = tplg_save_printf(dst, NULL, " {\n"); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "\t\treg %d\n", c->reg); ++ if (err >= 0 && c->shift > 0) ++ err = tplg_save_printf(dst, pfx, "\t\tshift %u\n", c->shift); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "\t}\n"); ++ } ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index 539329cd..979cc1b0 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -28,15 +28,16 @@ struct ctl_access_elem { + }; + + /* CTL access strings and codes */ ++/* place the multi-bit values on top - like read_write - for save */ + static const struct ctl_access_elem ctl_access[] = { ++ {"read_write", SNDRV_CTL_ELEM_ACCESS_READWRITE}, ++ {"tlv_read_write", SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE}, + {"read", SNDRV_CTL_ELEM_ACCESS_READ}, + {"write", SNDRV_CTL_ELEM_ACCESS_WRITE}, +- {"read_write", SNDRV_CTL_ELEM_ACCESS_READWRITE}, + {"volatile", SNDRV_CTL_ELEM_ACCESS_VOLATILE}, + {"timestamp", SNDRV_CTL_ELEM_ACCESS_TIMESTAMP}, + {"tlv_read", SNDRV_CTL_ELEM_ACCESS_TLV_READ}, + {"tlv_write", SNDRV_CTL_ELEM_ACCESS_TLV_WRITE}, +- {"tlv_read_write", SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE}, + {"tlv_command", SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND}, + {"inactive", SNDRV_CTL_ELEM_ACCESS_INACTIVE}, + {"lock", SNDRV_CTL_ELEM_ACCESS_LOCK}, +@@ -103,6 +104,46 @@ int parse_access(snd_config_t *cfg, + return err; + } + ++/* Save Access */ ++static int tplg_save_access(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct snd_soc_tplg_ctl_hdr *hdr, char **dst, ++ const char *pfx) ++{ ++ const char *last; ++ unsigned int j, count, access, cval; ++ int err; ++ ++ if (hdr->access == 0) ++ return 0; ++ ++ access = hdr->access; ++ for (j = 0, count = 0, last = NULL; j < ARRAY_SIZE(ctl_access); j++) { ++ cval = ctl_access[j].value; ++ if ((access & cval) == cval) { ++ access &= ~cval; ++ last = ctl_access[j].name; ++ count++; ++ } ++ } ++ if (count == 1) ++ return tplg_save_printf(dst, pfx, "access.0 %s\n", last); ++ err = tplg_save_printf(dst, pfx, "access [\n"); ++ if (err < 0) ++ return err; ++ access = hdr->access; ++ for (j = 0; j < ARRAY_SIZE(ctl_access); j++) { ++ cval = ctl_access[j].value; ++ if ((access & cval) == cval) { ++ err = tplg_save_printf(dst, pfx, "\t%s\n", ++ ctl_access[j].name); ++ if (err < 0) ++ return err; ++ access &= ~cval; ++ } ++ } ++ return tplg_save_printf(dst, pfx, "]\n"); ++} ++ + /* copy referenced TLV to the mixer control */ + static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref) + { +@@ -358,6 +399,37 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg, + return err; + } + ++/* save TLV data */ ++int tplg_save_tlv(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_ctl_tlv *tlv = elem->tlv; ++ struct snd_soc_tplg_tlv_dbscale *scale; ++ int err; ++ ++ if (tlv->type != SNDRV_CTL_TLVT_DB_SCALE) { ++ SNDERR("unknown TLV type"); ++ return -EINVAL; ++ } ++ ++ scale = &tlv->scale; ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "\tscale {\n"); ++ if (err >= 0 && scale->min) ++ err = tplg_save_printf(dst, pfx, "\t\tmin %i\n", scale->min); ++ if (err >= 0 && scale->step > 0) ++ err = tplg_save_printf(dst, pfx, "\t\tstep %i\n", scale->step); ++ if (err >= 0 && scale->mute > 0) ++ err = tplg_save_printf(dst, pfx, "\t\tmute %i\n", scale->mute); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "\t}\n"); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* Parse Control Bytes */ + int tplg_parse_control_bytes(snd_tplg_t *tplg, + snd_config_t *cfg, +@@ -430,7 +502,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + } + + if (strcmp(id, "data") == 0) { +- err = tplg_parse_data_refs(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA); + if (err < 0) + return err; + continue; +@@ -485,6 +557,49 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + return 0; + } + ++/* save control bytes */ ++int tplg_save_control_bytes(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_bytes_control *be = elem->bytes_ext; ++ char pfx2[16]; ++ int err; ++ ++ if (!be) ++ return 0; ++ ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err < 0) ++ return err; ++ if (err >= 0 && elem->index > 0) ++ err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index); ++ if (err >= 0 && be->base > 0) ++ err = tplg_save_printf(dst, pfx, "\tbase %u\n", be->base); ++ if (err >= 0 && be->num_regs > 0) ++ err = tplg_save_printf(dst, pfx, "\tnum_regs %u\n", be->num_regs); ++ if (err >= 0 && be->max > 0) ++ err = tplg_save_printf(dst, pfx, "\tmax %u\n", be->max); ++ if (err >= 0 && be->mask > 0) ++ err = tplg_save_printf(dst, pfx, "\tmask %u\n", be->mask); ++ if (err >= 0) ++ err = tplg_save_ops(tplg, &be->hdr, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_ext_ops(tplg, be, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_access(tplg, &be->hdr, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TLV, ++ "tlv", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA, ++ "data", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* Parse Control Enums. */ + int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, + void *private ATTRIBUTE_UNUSED) +@@ -559,7 +674,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, + } + + if (strcmp(id, "data") == 0) { +- err = tplg_parse_data_refs(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA); + if (err < 0) + return err; + continue; +@@ -582,6 +697,42 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* save control eunm */ ++int tplg_save_control_enum(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_enum_control *ec = elem->enum_ctrl; ++ char pfx2[16]; ++ int err; ++ ++ if (!ec) ++ return 0; ++ ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err < 0) ++ return err; ++ if (err >= 0 && elem->index > 0) ++ err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TEXT, ++ "texts", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_channels(tplg, ec->channel, ec->num_channels, ++ dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_ops(tplg, &ec->hdr, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_access(tplg, &ec->hdr, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA, ++ "data", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* Parse Controls. + * + * Mixer control. Supports multiple channels. +@@ -683,7 +834,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + } + + if (strcmp(id, "data") == 0) { +- err = tplg_parse_data_refs(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA); + if (err < 0) + return err; + continue; +@@ -709,6 +860,46 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + return 0; + } + ++int tplg_save_control_mixer(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, char **dst, ++ const char *pfx) ++{ ++ struct snd_soc_tplg_mixer_control *mc = elem->mixer_ctrl; ++ char pfx2[16]; ++ int err; ++ ++ if (!mc) ++ return 0; ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err < 0) ++ return err; ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ if (err >= 0 && elem->index > 0) ++ err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index); ++ if (err >= 0) ++ err = tplg_save_channels(tplg, mc->channel, mc->num_channels, ++ dst, pfx2); ++ if (err >= 0 && mc->max > 0) ++ err = tplg_save_printf(dst, pfx, "\tmax %u\n", mc->max); ++ if (err >= 0 && mc->invert > 0) ++ err = tplg_save_printf(dst, pfx, "\tinvert 1\n", mc->max); ++ if (err >= 0 && mc->invert > 0) ++ err = tplg_save_printf(dst, pfx, "\tinvert 1\n", mc->max); ++ if (err >= 0) ++ err = tplg_save_ops(tplg, &mc->hdr, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_access(tplg, &mc->hdr, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TLV, ++ "tlv", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA, ++ "data", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr, + struct snd_tplg_ctl_template *t) + { +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index ad709210..2bdacedc 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -43,7 +43,6 @@ static const struct map_elem widget_map[] = { + {"effect", SND_SOC_TPLG_DAPM_EFFECT}, + {"siggen", SND_SOC_TPLG_DAPM_SIGGEN}, + {"src", SND_SOC_TPLG_DAPM_SRC}, +- {"asrc", SND_SOC_TPLG_DAPM_ASRC}, + {"encoder", SND_SOC_TPLG_DAPM_ENCODER}, + {"decoder", SND_SOC_TPLG_DAPM_DECODER}, + }; +@@ -60,70 +59,16 @@ static int lookup_widget(const char *w) + return -EINVAL; + } + +-static int tplg_parse_dapm_mixers(snd_config_t *cfg, struct tplg_elem *elem) ++static const char *get_widget_name(unsigned int type) + { +- snd_config_iterator_t i, next; +- snd_config_t *n; +- const char *value = NULL; +- +- tplg_dbg(" DAPM Mixer Controls: %s\n", elem->id); +- +- snd_config_for_each(i, next, cfg) { +- n = snd_config_iterator_entry(i); +- +- /* get value */ +- if (snd_config_get_string(n, &value) < 0) +- continue; +- +- tplg_ref_add(elem, SND_TPLG_TYPE_MIXER, value); +- tplg_dbg("\t\t %s\n", value); +- } +- +- return 0; +-} +- +-static int tplg_parse_dapm_enums(snd_config_t *cfg, struct tplg_elem *elem) +-{ +- snd_config_iterator_t i, next; +- snd_config_t *n; +- const char *value = NULL; +- +- tplg_dbg(" DAPM Enum Controls: %s\n", elem->id); +- +- snd_config_for_each(i, next, cfg) { +- n = snd_config_iterator_entry(i); +- +- /* get value */ +- if (snd_config_get_string(n, &value) < 0) +- continue; +- +- tplg_ref_add(elem, SND_TPLG_TYPE_ENUM, value); +- tplg_dbg("\t\t %s\n", value); +- } +- +- return 0; +-} +- +-static int tplg_parse_dapm_bytes(snd_config_t *cfg, struct tplg_elem *elem) +-{ +- snd_config_iterator_t i, next; +- snd_config_t *n; +- const char *value = NULL; +- +- tplg_dbg(" DAPM Bytes Controls: %s\n", elem->id); +- +- snd_config_for_each(i, next, cfg) { +- n = snd_config_iterator_entry(i); +- +- /* get value */ +- if (snd_config_get_string(n, &value) < 0) +- continue; ++ unsigned int i; + +- tplg_ref_add(elem, SND_TPLG_TYPE_BYTES, value); +- tplg_dbg("\t\t %s\n", value); ++ for (i = 0; i < ARRAY_SIZE(widget_map); i++) { ++ if ((unsigned int)widget_map[i].id == type) ++ return widget_map[i].name; + } + +- return 0; ++ return NULL; + } + + /* move referenced controls to the widget */ +@@ -340,7 +285,7 @@ struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg, int index) + + #define LINE_SIZE 1024 + +-/* line is defined as '"source, control, sink"' */ ++/* line is defined as '"sink, control, source"' */ + static int tplg_parse_line(const char *text, + struct snd_soc_tplg_dapm_graph_elem *line) + { +@@ -470,6 +415,77 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* save DAPM graph */ ++int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_dapm_graph_elem *route; ++ struct list_head *pos; ++ struct tplg_elem *elem; ++ int err, first = 1, old_index = -1; ++ unsigned block = -1, count = 0; ++ ++ list_for_each(pos, &tplg->route_list) { ++ elem = list_entry(pos, struct tplg_elem, list); ++ if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH) ++ continue; ++ if (index >= 0 && elem->index != index) ++ continue; ++ count++; ++ } ++ if (count == 0) ++ return 0; ++ err = tplg_save_printf(dst, pfx, "SectionGraph {\n"); ++ list_for_each(pos, &tplg->route_list) { ++ elem = list_entry(pos, struct tplg_elem, list); ++ if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH) ++ continue; ++ if (index >= 0 && elem->index != index) ++ continue; ++ if (old_index != elem->index) { ++ if (old_index >= 0) { ++ err = tplg_save_printf(dst, pfx, "\t\t]\n"); ++ if (err < 0) ++ return err; ++ err = tplg_save_printf(dst, pfx, "\t}\n"); ++ if (err < 0) ++ return err; ++ } ++ old_index = elem->index; ++ block++; ++ first = 1; ++ err = tplg_save_printf(dst, pfx, "\tset%u {\n", block); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "\t\tindex %u\n", ++ elem->index); ++ if (err < 0) ++ return err; ++ } ++ if (first) { ++ first = 0; ++ err = tplg_save_printf(dst, pfx, "\t\tlines [\n", elem->index); ++ if (err < 0) ++ return err; ++ } ++ route = elem->route; ++ err = tplg_save_printf(dst, pfx, "\t\t\t'%s, %s, %s'\n", ++ route->sink, route->control, ++ route->source); ++ if (err < 0) ++ return err; ++ } ++ ++ if (!first) { ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "\t\t]\n"); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "\t}\n"); ++ } ++ ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* DAPM Widget */ + int tplg_parse_dapm_widget(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) +@@ -595,7 +611,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + } + + if (strcmp(id, "enum") == 0) { +- err = tplg_parse_dapm_enums(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_ENUM); + if (err < 0) + return err; + +@@ -603,7 +619,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + } + + if (strcmp(id, "mixer") == 0) { +- err = tplg_parse_dapm_mixers(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_MIXER); + if (err < 0) + return err; + +@@ -611,7 +627,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + } + + if (strcmp(id, "bytes") == 0) { +- err = tplg_parse_dapm_bytes(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_BYTES); + if (err < 0) + return err; + +@@ -619,7 +635,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + } + + if (strcmp(id, "data") == 0) { +- err = tplg_parse_data_refs(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA); + if (err < 0) + return err; + continue; +@@ -629,6 +645,66 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + return 0; + } + ++/* save DAPM widget */ ++int tplg_save_dapm_widget(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_dapm_widget *widget = elem->widget; ++ const char *s; ++ char pfx2[16]; ++ int err; ++ ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0 && elem->index) ++ err = tplg_save_printf(dst, pfx, "\tindex %u\n", ++ elem->index); ++ if (err >= 0) { ++ s = get_widget_name(widget->id); ++ if (s) ++ err = tplg_save_printf(dst, pfx, "\ttype %s\n", s); ++ else ++ err = tplg_save_printf(dst, pfx, "\ttype %u\n", ++ widget->id); ++ } ++ if (err >= 0 && widget->sname[0]) ++ err = tplg_save_printf(dst, pfx, "\tstream_name '%s'\n", ++ widget->sname); ++ if (err >= 0 && widget->reg) ++ err = tplg_save_printf(dst, pfx, "\tno_pm 1\n"); ++ if (err >= 0 && widget->shift) ++ err = tplg_save_printf(dst, pfx, "\tshift %u\n", ++ widget->shift); ++ if (err >= 0 && widget->invert) ++ err = tplg_save_printf(dst, pfx, "\tinvert %u\n", ++ widget->invert); ++ if (err >= 0 && widget->subseq) ++ err = tplg_save_printf(dst, pfx, "\tsubseq %u\n", ++ widget->subseq); ++ if (err >= 0 && widget->event_type) ++ err = tplg_save_printf(dst, pfx, "\tevent_type %u\n", ++ widget->event_type); ++ if (err >= 0 && widget->event_flags) ++ err = tplg_save_printf(dst, pfx, "\tevent_flags %u\n", ++ widget->event_flags); ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_ENUM, ++ "enum", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_MIXER, ++ "mixer", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_BYTES, ++ "bytes", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA, ++ "data", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t, int index) + { + struct tplg_elem *elem; +@@ -744,7 +820,6 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + default: + SNDERR("error: widget %s: invalid type %d for ctl %d\n", + wt->name, ct->type, i); +- ret = -EINVAL; + break; + } + +diff --git a/src/topology/data.c b/src/topology/data.c +index 9807445e..11cd73f5 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -21,6 +21,10 @@ + #include "tplg_local.h" + #include + ++#define UUID_FORMAT "\ ++0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, \ ++0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x" ++ + /* Get private data buffer of an element */ + struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem) + { +@@ -64,6 +68,96 @@ struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem) + return priv; + } + ++/* Parse references for the element, either a single data section ++ * or a list of data sections. ++ */ ++int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem, ++ unsigned int type) ++{ ++ snd_config_type_t cfg_type; ++ snd_config_iterator_t i, next; ++ snd_config_t *n; ++ const char *val = NULL; ++ int err, count; ++ ++ cfg_type = snd_config_get_type(cfg); ++ ++ /* refer to a single data section */ ++ if (cfg_type == SND_CONFIG_TYPE_STRING) { ++ if (snd_config_get_string(cfg, &val) < 0) ++ return -EINVAL; ++ ++ tplg_dbg("\tref data: %s\n", val); ++ err = tplg_ref_add(elem, type, val); ++ if (err < 0) ++ return err; ++ return 1; ++ } ++ ++ if (cfg_type != SND_CONFIG_TYPE_COMPOUND) { ++ SNDERR("error: compound type expected for %s", elem->id); ++ return -EINVAL; ++ } ++ ++ /* refer to a list of data sections */ ++ count = 0; ++ snd_config_for_each(i, next, cfg) { ++ const char *val; ++ ++ n = snd_config_iterator_entry(i); ++ if (snd_config_get_string(n, &val) < 0) ++ continue; ++ ++ tplg_dbg("\tref data: %s\n", val); ++ err = tplg_ref_add(elem, type, val); ++ if (err < 0) ++ return err; ++ count++; ++ } ++ ++ return count; ++} ++ ++/* save references */ ++int tplg_save_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, unsigned int type, ++ const char *id, char **dst, const char *pfx) ++{ ++ struct tplg_ref *ref, *last; ++ struct list_head *pos; ++ int err, count; ++ ++ count = 0; ++ last = NULL; ++ list_for_each(pos, &elem->ref_list) { ++ ref = list_entry(pos, struct tplg_ref, list); ++ if (ref->type == type) { ++ last = ref; ++ count++; ++ } ++ } ++ ++ if (count == 0) ++ return 0; ++ ++ if (count == 1) ++ return tplg_save_printf(dst, pfx, "%s '%s'\n", id, last->id); ++ ++ err = tplg_save_printf(dst, pfx, "%s [\n", id); ++ if (err < 0) ++ return err; ++ list_for_each(pos, &elem->ref_list) { ++ ref = list_entry(pos, struct tplg_ref, list); ++ if (ref->type == type) { ++ err = tplg_save_printf(dst, pfx, "\t'%s'\n", ref->id); ++ if (err < 0) ++ return err; ++ } ++ } ++ ++ return tplg_save_printf(dst, pfx, "]\n"); ++} ++ + /* Get Private data from a file. */ + static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem) + { +@@ -140,58 +234,98 @@ err: + static void dump_priv_data(struct tplg_elem *elem) + { + struct snd_soc_tplg_private *priv = elem->data; +- unsigned int i, j = 0; ++ unsigned int i; + + tplg_dbg(" elem size = %d, priv data size = %d\n", + elem->size, priv->size); + + for (i = 0; i < priv->size; i++) { +- if (j++ % 8 == 0) ++ if (i > 0 && (i % 16) == 0) + tplg_dbg("\n"); + +- tplg_dbg(" 0x%x", *p++); ++ tplg_dbg(" %02x:", *p++); + } + + tplg_dbg("\n\n"); + } + ++static inline int check_nibble(unsigned char c) ++{ ++ return (c >= '0' && c <= '9') || ++ (c >= 'a' && c <= 'f') || ++ (c >= 'A' && c <= 'F'); ++} ++ + /* get number of hex value elements in CSV list */ + static int get_hex_num(const char *str) + { +- int commas = 0, values = 0, len = strlen(str); +- const char *end = str + len; ++ int delims, values, len = strlen(str); ++ const char *s, *end = str + len; ++ ++ /* check "aa:bb:00" syntax */ ++ s = str; ++ delims = values = 0; ++ while (s < end) { ++ /* skip white space */ ++ if (isspace(*s)) { ++ s++; ++ continue; ++ } ++ /* find delimeters */ ++ if (*s == ':') { ++ delims++; ++ s++; ++ continue; ++ } ++ /* check 00 hexadecimal value */ ++ if (s + 1 <= end) { ++ if (check_nibble(s[0]) && check_nibble(s[1])) { ++ values++; ++ } else { ++ goto format2; ++ } ++ s++; ++ } ++ s++; ++ } ++ goto end; + ++format2: + /* we expect "0x0, 0x0, 0x0" */ +- while (str < end) { ++ s = str; ++ delims = values = 0; ++ while (s < end) { + + /* skip white space */ +- if (isspace(*str)) { +- str++; ++ if (isspace(*s)) { ++ s++; + continue; + } + + /* find delimeters */ +- if (*str == ',') { +- commas++; +- str++; ++ if (*s == ',') { ++ delims++; ++ s++; + continue; + } + + /* find 0x[0-9] values */ +- if (*str == '0' && str + 2 <= end) { +- if (str[1] == 'x' && str[2] >= '0' && str[2] <= 'f') { ++ if (*s == '0' && s + 2 <= end) { ++ if (s[1] == 'x' && check_nibble(s[2])) { ++ if (check_nibble(s[3])) ++ s++; + values++; +- str += 3; +- } else { +- str++; ++ s += 2; + } ++ s++; + } + +- str++; ++ s++; + } + ++end: + /* there should always be one less comma than value */ +- if (values -1 != commas) ++ if (values - 1 != delims) + return -EINVAL; + + return values; +@@ -547,6 +681,71 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem) + return 0; + } + ++struct tuple_type { ++ unsigned int type; ++ const char *name; ++ unsigned int size; ++}; ++ ++static struct tuple_type tuple_types[] = { ++ { ++ .type = SND_SOC_TPLG_TUPLE_TYPE_UUID, ++ .name = "uuid", ++ .size = 4, ++ }, ++ { ++ .type = SND_SOC_TPLG_TUPLE_TYPE_STRING, ++ .name = "string", ++ .size = 6, ++ }, ++ { ++ .type = SND_SOC_TPLG_TUPLE_TYPE_BOOL, ++ .name = "bool", ++ .size = 4, ++ }, ++ { ++ .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, ++ .name = "byte", ++ .size = 4, ++ }, ++ { ++ .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT, ++ .name = "short", ++ .size = 5, ++ }, ++ { ++ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, ++ .name = "word", ++ .size = 4 ++ }, ++}; ++ ++static int get_tuple_type(const char *name) ++{ ++ struct tuple_type *t; ++ unsigned int i; ++ ++ /* skip initial index for sorting */ ++ while ((*name >= '0' && *name <= '9') || *name == '_') ++ name++; ++ for (i = 0; i < ARRAY_SIZE(tuple_types); i++) { ++ t = &tuple_types[i]; ++ if (strncasecmp(t->name, name, t->size) == 0) ++ return t->type; ++ } ++ return -EINVAL; ++} ++ ++static const char *get_tuple_type_name(unsigned int type) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(tuple_types); i++) ++ if (tuple_types[i].type == type) ++ return tuple_types[i].name; ++ return NULL; ++} ++ + static int parse_tuple_set(snd_config_t *cfg, + struct tplg_tuple_set **s) + { +@@ -554,28 +753,17 @@ static int parse_tuple_set(snd_config_t *cfg, + snd_config_t *n; + const char *id, *value; + struct tplg_tuple_set *set; +- unsigned int type, num_tuples = 0; ++ unsigned int num_tuples = 0; + struct tplg_tuple *tuple; + unsigned int tuple_val; +- int ival; ++ int type, ival; + + snd_config_get_id(cfg, &id); + +- if (strncmp(id, "uuid", 4) == 0) +- type = SND_SOC_TPLG_TUPLE_TYPE_UUID; +- else if (strncmp(id, "string", 5) == 0) +- type = SND_SOC_TPLG_TUPLE_TYPE_STRING; +- else if (strncmp(id, "bool", 4) == 0) +- type = SND_SOC_TPLG_TUPLE_TYPE_BOOL; +- else if (strncmp(id, "byte", 4) == 0) +- type = SND_SOC_TPLG_TUPLE_TYPE_BYTE; +- else if (strncmp(id, "short", 5) == 0) +- type = SND_SOC_TPLG_TUPLE_TYPE_SHORT; +- else if (strncmp(id, "word", 4) == 0) +- type = SND_SOC_TPLG_TUPLE_TYPE_WORD; +- else { +- SNDERR("error: invalid tuple type '%s'\n", id); +- return -EINVAL; ++ type = get_tuple_type(id); ++ if (type < 0) { ++ SNDERR("error: invalid tuple type '%s'", id); ++ return type; + } + + snd_config_for_each(i, next, cfg) +@@ -664,6 +852,84 @@ err: + return -EINVAL; + } + ++/* save tuple set */ ++static int tplg_save_tuple_set(struct tplg_vendor_tuples *tuples, ++ unsigned int set_index, ++ char **dst, const char *pfx) ++{ ++ struct tplg_tuple_set *set; ++ struct tplg_tuple *tuple; ++ const char *s, *fmt; ++ char buf[32]; ++ unsigned int i; ++ int err; ++ ++ set = tuples->set[set_index]; ++ if (set->num_tuples == 0) ++ return 0; ++ s = get_tuple_type_name(set->type); ++ if (s == NULL) ++ return -EINVAL; ++ if (tuples->num_sets < 10) ++ fmt = "%u_"; ++ else if (tuples->num_sets < 100) ++ fmt = "%02u_"; ++ else if (tuples->num_sets < 1000) ++ fmt = "%03u_"; ++ else ++ return -EINVAL; ++ if (set->num_tuples > 1) { ++ snprintf(buf, sizeof(buf), "tuples.%s%%s {\n", fmt); ++ err = tplg_save_printf(dst, NULL, buf, set_index, s); ++ if (err < 0) ++ return err; ++ } ++ for (i = 0; i < set->num_tuples; i++) { ++ tuple = &set->tuple[i]; ++ if (set->num_tuples == 1) { ++ snprintf(buf, sizeof(buf), "tuples.%s%%s.'%%s' ", fmt); ++ err = tplg_save_printf(dst, NULL, buf, ++ set_index, s, tuple->token); ++ } else { ++ err = tplg_save_printf(dst, pfx, "\t'%s' ", ++ tuple->token); ++ } ++ switch (set->type) { ++ case SND_SOC_TPLG_TUPLE_TYPE_UUID: ++ err = tplg_save_printf(dst, NULL, "'" UUID_FORMAT "'\n", ++ tuple->uuid[0], tuple->uuid[1], ++ tuple->uuid[2], tuple->uuid[3], ++ tuple->uuid[4], tuple->uuid[5], ++ tuple->uuid[6], tuple->uuid[7], ++ tuple->uuid[8], tuple->uuid[9], ++ tuple->uuid[10], tuple->uuid[11], ++ tuple->uuid[12], tuple->uuid[13], ++ tuple->uuid[14], tuple->uuid[15]); ++ break; ++ case SND_SOC_TPLG_TUPLE_TYPE_STRING: ++ err = tplg_save_printf(dst, NULL, "'%s'\n", ++ tuple->string); ++ break; ++ case SND_SOC_TPLG_TUPLE_TYPE_BOOL: ++ case SND_SOC_TPLG_TUPLE_TYPE_BYTE: ++ case SND_SOC_TPLG_TUPLE_TYPE_SHORT: ++ err = tplg_save_printf(dst, NULL, "%u\n", tuple->value); ++ break; ++ case SND_SOC_TPLG_TUPLE_TYPE_WORD: ++ tplg_nice_value_format(buf, sizeof(buf), tuple->value); ++ err = tplg_save_printf(dst, NULL, "%s\n", buf); ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (err < 0) ++ return err; ++ } ++ if (set->num_tuples > 1) ++ return tplg_save_printf(dst, pfx, "}\n"); ++ return 0; ++} ++ + static int parse_tuple_sets(snd_config_t *cfg, + struct tplg_vendor_tuples *tuples) + { +@@ -710,87 +976,24 @@ static int parse_tuple_sets(snd_config_t *cfg, + return 0; + } + +-/* Parse tuples references for a data element, either a single tuples section +- * or a list of tuples sections. +- */ +-static int parse_tuples_refs(snd_config_t *cfg, +- struct tplg_elem *elem) +-{ +- snd_config_type_t type; +- snd_config_iterator_t i, next; +- snd_config_t *n; +- const char *val = NULL; +- +- type = snd_config_get_type(cfg); +- +- /* refer to a single tuples section */ +- if (type == SND_CONFIG_TYPE_STRING) { +- if (snd_config_get_string(cfg, &val) < 0) +- return -EINVAL; +- tplg_dbg("\ttuples: %s\n", val); +- return tplg_ref_add(elem, SND_TPLG_TYPE_TUPLE, val); +- } +- +- if (type != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound type expected for %s", elem->id); +- return -EINVAL; +- } +- +- /* refer to a list of data sections */ +- snd_config_for_each(i, next, cfg) { +- const char *val; +- +- n = snd_config_iterator_entry(i); +- if (snd_config_get_string(n, &val) < 0) +- continue; +- +- tplg_dbg("\ttuples: %s\n", val); +- tplg_ref_add(elem, SND_TPLG_TYPE_TUPLE, val); +- } +- +- return 0; +-} +- +-/* Parse private data references for the element, either a single data section +- * or a list of data sections. +- */ +-int tplg_parse_data_refs(snd_config_t *cfg, +- struct tplg_elem *elem) ++/* save tuple sets */ ++int tplg_save_tuple_sets(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) + { +- snd_config_type_t type; +- snd_config_iterator_t i, next; +- snd_config_t *n; +- const char *val = NULL; +- +- type = snd_config_get_type(cfg); +- +- /* refer to a single data section */ +- if (type == SND_CONFIG_TYPE_STRING) { +- if (snd_config_get_string(cfg, &val) < 0) +- return -EINVAL; +- +- tplg_dbg("\tdata: %s\n", val); +- return tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val); +- } +- +- if (type != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound type expected for %s", elem->id); +- return -EINVAL; +- } +- +- /* refer to a list of data sections */ +- snd_config_for_each(i, next, cfg) { +- const char *val; +- +- n = snd_config_iterator_entry(i); +- if (snd_config_get_string(n, &val) < 0) +- continue; ++ struct tplg_vendor_tuples *tuples = elem->tuples; ++ unsigned int i; ++ int err = 0; + +- tplg_dbg("\tdata: %s\n", val); +- tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val); ++ for (i = 0; i < tuples->num_sets; i++) { ++ err = tplg_save_printf(dst, pfx, ""); ++ if (err < 0) ++ break; ++ err = tplg_save_tuple_set(tuples, i, dst, pfx); ++ if (err < 0) ++ break; + } +- +- return 0; ++ return err; + } + + /* Parse vendor tokens +@@ -844,6 +1047,31 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* save vendor tokens */ ++int tplg_save_tokens(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct tplg_vendor_tokens *tokens = elem->tokens; ++ unsigned int i; ++ int err; ++ ++ if (!tokens || tokens->num_tokens == 0) ++ return 0; ++ ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err < 0) ++ return err; ++ for (i = 0; err >= 0 && i < tokens->num_tokens; i++) ++ err = tplg_save_printf(dst, pfx, "\t'%s' %u\n", ++ tokens->token[i].id, ++ tokens->token[i].value); ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ if (err < 0) ++ return err; ++ return 0; ++} ++ + /* Parse vendor tuples. + */ + int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, +@@ -890,6 +1118,29 @@ int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* save vendor tuples */ ++int tplg_save_tuples(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ char pfx2[16]; ++ int err; ++ ++ if (!elem->tuples) ++ return 0; ++ ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TOKEN, ++ "tokens", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_tuple_sets(tplg, elem, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return 0; ++} ++ + /* Free handler of tuples */ + void tplg_free_tuples(void *obj) + { +@@ -944,7 +1195,7 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, + + + if (strcmp(id, "data") == 0) { +- err = tplg_parse_data_refs(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA); + if (err < 0) + return err; + continue; +@@ -954,6 +1205,51 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* save manifest data */ ++int tplg_save_manifest_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, char **dst, ++ const char *pfx) ++{ ++ struct list_head *pos; ++ struct tplg_ref *ref; ++ int err, index, count; ++ ++ /* for each ref in this manifest elem */ ++ count = 0; ++ list_for_each(pos, &elem->ref_list) { ++ ref = list_entry(pos, struct tplg_ref, list); ++ if (ref->type != SND_TPLG_TYPE_DATA) ++ continue; ++ count++; ++ } ++ if (count > 1) { ++ err = tplg_save_printf(dst, NULL, "'%s'.data [\n", elem->id); ++ if (err < 0) ++ return err; ++ } ++ index = 0; ++ list_for_each(pos, &elem->ref_list) { ++ ref = list_entry(pos, struct tplg_ref, list); ++ if (ref->type != SND_TPLG_TYPE_DATA) ++ continue; ++ if (count == 1) { ++ err = tplg_save_printf(dst, NULL, "'%s'.data.%u '%s'\n", ++ elem->id, index, ref->id); ++ } else { ++ err = tplg_save_printf(dst, pfx, "\t'%s'\n", ref->id); ++ if (err < 0) ++ return err; ++ } ++ index++; ++ } ++ if (count > 1) { ++ err = tplg_save_printf(dst, pfx, "]\n"); ++ if (err < 0) ++ return err; ++ } ++ return 0; ++} ++ + /* merge private data of manifest */ + int tplg_build_manifest_data(snd_tplg_t *tplg) + { +@@ -1064,7 +1360,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + } + + if (strcmp(id, "tuples") == 0) { +- err = parse_tuples_refs(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_TUPLE); + if (err < 0) + return err; + continue; +@@ -1083,6 +1379,81 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + return err; + } + ++/* save data element */ ++int tplg_save_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_private *priv = elem->data; ++ struct list_head *pos; ++ struct tplg_ref *ref; ++ char pfx2[16]; ++ unsigned int i, count; ++ int err; ++ ++ count = 0; ++ if (priv && priv->size > 0) ++ count++; ++ list_for_each(pos, &elem->ref_list) { ++ ref = list_entry(pos, struct tplg_ref, list); ++ if (ref->type == SND_TPLG_TYPE_TUPLE) ++ count++; ++ } ++ if (elem->vendor_type > 0) ++ count++; ++ ++ if (count > 1) { ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0) ++ err = tplg_save_printf(dst, NULL, ""); ++ } else { ++ err = tplg_save_printf(dst, NULL, "'%s'.", elem->id); ++ } ++ if (err >= 0 && priv && priv->size > 0) { ++ if (count > 1) { ++ err = tplg_save_printf(dst, pfx, ""); ++ if (err < 0) ++ return err; ++ } ++ if (priv->size > 8) { ++ err = tplg_save_printf(dst, NULL, "bytes\n"); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "\t'"); ++ } else { ++ err = tplg_save_printf(dst, NULL, "bytes '"); ++ } ++ if (err < 0) ++ return err; ++ for (i = 0; i < priv->size; i++) { ++ if (i > 0 && (i % 8) == 0) { ++ err = tplg_save_printf(dst, NULL, ":\n"); ++ if (err < 0) ++ return err; ++ err = tplg_save_printf(dst, pfx, "\t "); ++ if (err < 0) ++ return err; ++ } ++ err = tplg_save_printf(dst, NULL, "%s%02x", ++ (i % 8) == 0 ? "" : ":", ++ (unsigned char)priv->data[i]); ++ if (err < 0) ++ return err; ++ } ++ err = tplg_save_printf(dst, NULL, "'\n"); ++ } ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TUPLE, ++ "tuples", dst, ++ count > 1 ? pfx2 : NULL); ++ if (err >= 0 && elem->vendor_type > 0) ++ err = tplg_save_printf(dst, pfx, "type %u", ++ elem->vendor_type); ++ if (err >= 0 && count > 1) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* Find a referenced data element and copy its data to the parent + * element's private data buffer. + * An element can refer to multiple data sections. Data of these sections +diff --git a/src/topology/elem.c b/src/topology/elem.c +index e79a68b7..89aed1fc 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -30,6 +30,7 @@ struct tplg_table tplg_table[] = { + .size = sizeof(struct snd_soc_tplg_manifest), + .enew = 1, + .parse = tplg_parse_manifest_data, ++ .save = tplg_save_manifest_data, + }, + { + .name = "control mixer", +@@ -41,6 +42,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_control_mixer, ++ .save = tplg_save_control_mixer, + }, + { + .name = "control enum", +@@ -52,6 +54,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_control_enum, ++ .save = tplg_save_control_enum, + }, + { + .name = "control extended (bytes)", +@@ -63,6 +66,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_control_bytes, ++ .save = tplg_save_control_bytes, + }, + { + .name = "dapm widget", +@@ -74,6 +78,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_dapm_widget, ++ .save = tplg_save_dapm_widget, + }, + { + .name = "pcm", +@@ -85,6 +90,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_pcm, ++ .save = tplg_save_pcm, + }, + { + .name = "physical dai", +@@ -96,6 +102,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_dai, ++ .save = tplg_save_dai, + }, + { + .name = "be", +@@ -108,6 +115,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_link, ++ .save = tplg_save_link, + }, + { + .name = "cc", +@@ -119,6 +127,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_cc, ++ .save = tplg_save_cc, + }, + { + .name = "route (dapm graph)", +@@ -128,6 +137,7 @@ struct tplg_table tplg_table[] = { + .tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH, + .build = 1, + .parse = tplg_parse_dapm_graph, ++ .gsave = tplg_save_dapm_graph, + }, + { + .name = "private data", +@@ -138,6 +148,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .enew = 1, + .parse = tplg_parse_data, ++ .save = tplg_save_data, + }, + { + .name = "text", +@@ -147,6 +158,7 @@ struct tplg_table tplg_table[] = { + .size = sizeof(struct tplg_texts), + .enew = 1, + .parse = tplg_parse_text, ++ .save = tplg_save_text, + }, + { + .name = "tlv", +@@ -156,6 +168,7 @@ struct tplg_table tplg_table[] = { + .size = sizeof(struct snd_soc_tplg_ctl_tlv), + .enew = 1, + .parse = tplg_parse_tlv, ++ .save = tplg_save_tlv, + }, + { + .name = "stream config", +@@ -172,6 +185,7 @@ struct tplg_table tplg_table[] = { + .size = sizeof(struct snd_soc_tplg_stream_caps), + .enew = 1, + .parse = tplg_parse_stream_caps, ++ .save = tplg_save_stream_caps, + }, + { + .name = "token", +@@ -180,6 +194,7 @@ struct tplg_table tplg_table[] = { + .type = SND_TPLG_TYPE_TOKEN, + .enew = 1, + .parse = tplg_parse_tokens, ++ .save = tplg_save_tokens, + }, + { + .name = "tuple", +@@ -189,6 +204,7 @@ struct tplg_table tplg_table[] = { + .free = tplg_free_tuples, + .enew = 1, + .parse = tplg_parse_tuples, ++ .save = tplg_save_tuples, + }, + { + .name = "hw config", +@@ -198,6 +214,7 @@ struct tplg_table tplg_table[] = { + .size = sizeof(struct snd_soc_tplg_hw_config), + .enew = 1, + .parse = tplg_parse_hw_config, ++ .save = tplg_save_hw_config, + } + }; + +@@ -394,6 +411,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + tplg_elem_insert(elem, list); + obj_size = tptr->size; + elem->free = tptr->free; ++ elem->table = tptr; + + /* create new object too if required */ + if (obj_size > 0) { +diff --git a/src/topology/ops.c b/src/topology/ops.c +index 073acdcb..ad72ef1b 100644 +--- a/src/topology/ops.c ++++ b/src/topology/ops.c +@@ -45,6 +45,18 @@ static int lookup_ops(const char *c) + return strtol(c, NULL, 0); + } + ++const char *tplg_ops_name(int type) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(control_map); i++) { ++ if (control_map[i].id == type) ++ return control_map[i].name; ++ } ++ ++ return NULL; ++} ++ + /* Parse Control operations. Ops can come from standard names above or + * bespoke driver controls with numbers >= 256 + */ +@@ -84,6 +96,46 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg, + return 0; + } + ++/* save control operations */ ++int tplg_save_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct snd_soc_tplg_ctl_hdr *hdr, char **dst, ++ const char *pfx) ++{ ++ const char *s; ++ int err; ++ ++ if (hdr->ops.info + hdr->ops.get + hdr->ops.put == 0) ++ return 0; ++ err = tplg_save_printf(dst, pfx, "ops.0 {\n"); ++ if (err >= 0 && hdr->ops.info > 0) { ++ s = tplg_ops_name(hdr->ops.info); ++ if (s == NULL) ++ err = tplg_save_printf(dst, pfx, "\tinfo %u\n", ++ hdr->ops.info); ++ else ++ err = tplg_save_printf(dst, pfx, "\tinfo %s\n", s); ++ } ++ if (err >= 0 && hdr->ops.get > 0) { ++ s = tplg_ops_name(hdr->ops.get); ++ if (s == NULL) ++ err = tplg_save_printf(dst, pfx, "\tget %u\n", ++ hdr->ops.get); ++ else ++ err = tplg_save_printf(dst, pfx, "\tget %s\n", s); ++ } ++ if (err >= 0 && hdr->ops.put > 0) { ++ s = tplg_ops_name(hdr->ops.put); ++ if (s == NULL) ++ err = tplg_save_printf(dst, pfx, "\tput %u\n", ++ hdr->ops.put); ++ else ++ err = tplg_save_printf(dst, pfx, "\tput %s\n", s); ++ } ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* Parse External Control operations. Ops can come from standard names above or + * bespoke driver controls with numbers >= 256 + */ +@@ -121,3 +173,43 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + + return 0; + } ++ ++/* save external control operations */ ++int tplg_save_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct snd_soc_tplg_bytes_control *be, ++ char **dst, const char *pfx) ++{ ++ const char *s; ++ int err; ++ ++ if (be->ext_ops.info + be->ext_ops.get + be->ext_ops.put == 0) ++ return 0; ++ err = tplg_save_printf(dst, pfx, "extops.0 {\n"); ++ if (err >= 0 && be->ext_ops.info > 0) { ++ s = tplg_ops_name(be->ext_ops.info); ++ if (s == NULL) ++ err = tplg_save_printf(dst, pfx, "\tinfo %u\n", ++ be->ext_ops.info); ++ else ++ err = tplg_save_printf(dst, pfx, "\tinfo %s\n", s); ++ } ++ if (err >= 0 && be->ext_ops.get > 0) { ++ s = tplg_ops_name(be->ext_ops.get); ++ if (s == NULL) ++ err = tplg_save_printf(dst, pfx, "\tget %u\n", ++ be->ext_ops.get); ++ else ++ err = tplg_save_printf(dst, pfx, "\tget %s\n", s); ++ } ++ if (err >= 0 && be->ext_ops.put > 0) { ++ s = tplg_ops_name(be->ext_ops.put); ++ if (s == NULL) ++ err = tplg_save_printf(dst, pfx, "\tput %u\n", ++ be->ext_ops.put); ++ else ++ err = tplg_save_printf(dst, pfx, "\tput %s\n", s); ++ } ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 11202769..de5edd1b 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -71,6 +71,8 @@ int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base) + err = snd_config_get_integer(n, &lval); + if (err < 0) + return err; ++ if (lval < 0 && lval >= INT_MIN) ++ lval = UINT_MAX + lval + 1; + if (lval < 0 || lval > UINT_MAX) + return -ERANGE; + *val = lval; +@@ -79,6 +81,8 @@ int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base) + err = snd_config_get_integer64(n, &llval); + if (err < 0) + return err; ++ if (llval < 0 && llval >= INT_MIN) ++ llval = UINT_MAX + llval + 1; + if (llval < 0 || llval > UINT_MAX) + return -ERANGE; + *val = llval; +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 9b87549c..d09fbe42 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -345,6 +345,13 @@ static int get_rate_value(const char* name) + return SND_PCM_RATE_UNKNOWN; + } + ++static const char *get_rate_name(int rate) ++{ ++ if (rate >= 0 && rate <= SND_PCM_RATE_LAST) ++ return snd_pcm_rate_names[rate]; ++ return NULL; ++} ++ + static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str) + { + char *s = NULL; +@@ -527,6 +534,80 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + return 0; + } + ++/* save stream caps */ ++int tplg_save_stream_caps(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_stream_caps *sc = elem->stream_caps; ++ const char *s; ++ unsigned int i; ++ int err, first; ++ ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0 && sc->formats) { ++ err = tplg_save_printf(dst, pfx, "\tformats '"); ++ first = 1; ++ for (i = 0; err >= 0 && i < SND_PCM_FORMAT_LAST; i++) { ++ if (sc->formats & (1ULL << i)) { ++ s = snd_pcm_format_name(i); ++ err = tplg_save_printf(dst, NULL, "%s%s", ++ !first ? ", " : "", s); ++ first = 0; ++ } ++ } ++ if (err >= 0) ++ err = tplg_save_printf(dst, NULL, "'\n"); ++ } ++ if (err >= 0 && sc->rates) { ++ err = tplg_save_printf(dst, pfx, "\trates '"); ++ first = 1; ++ for (i = 0; err >= 0 && i < SND_PCM_RATE_LAST; i++) { ++ if (sc->rates & (1ULL << i)) { ++ s = get_rate_name(i); ++ err = tplg_save_printf(dst, NULL, "%s%s", ++ !first ? ", " : "", s); ++ first = 0; ++ } ++ } ++ if (err >= 0) ++ err = tplg_save_printf(dst, NULL, "'\n"); ++ } ++ if (err >= 0 && sc->rate_min) ++ err = tplg_save_printf(dst, pfx, "\trate_min %u\n", ++ sc->rate_min); ++ if (err >= 0 && sc->rate_max) ++ err = tplg_save_printf(dst, pfx, "\trate_max %u\n", ++ sc->rate_max); ++ if (err >= 0 && sc->channels_min) ++ err = tplg_save_printf(dst, pfx, "\tchannels_min %u\n", ++ sc->channels_min); ++ if (err >= 0 && sc->channels_max) ++ err = tplg_save_printf(dst, pfx, "\tchannels_max %u\n", ++ sc->channels_max); ++ if (err >= 0 && sc->periods_min) ++ err = tplg_save_printf(dst, pfx, "\tperiods_min %u\n", ++ sc->periods_min); ++ if (err >= 0 && sc->periods_max) ++ err = tplg_save_printf(dst, pfx, "\tperiods_max %u\n", ++ sc->periods_max); ++ if (err >= 0 && sc->period_size_min) ++ err = tplg_save_printf(dst, pfx, "\tperiod_size_min %u\n", ++ sc->period_size_min); ++ if (err >= 0 && sc->period_size_max) ++ err = tplg_save_printf(dst, pfx, "\tperiod_size_max %u\n", ++ sc->period_size_max); ++ if (err >= 0 && sc->buffer_size_min) ++ err = tplg_save_printf(dst, pfx, "\tbuffer_size_min %u\n", ++ sc->buffer_size_min); ++ if (err >= 0 && sc->buffer_size_max) ++ err = tplg_save_printf(dst, pfx, "\tbuffer_size_max %u\n", ++ sc->buffer_size_max); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* Parse the caps and config of a pcm stream */ + static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_config_t *cfg, void *private) +@@ -598,6 +679,61 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + return 0; + } + ++/* Save the caps and config of a pcm stream */ ++int tplg_save_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ static const char *stream_ids[2] = { ++ "playback", ++ "capture" ++ }; ++ static unsigned int stream_types[2] = { ++ SND_SOC_TPLG_STREAM_PLAYBACK, ++ SND_SOC_TPLG_STREAM_CAPTURE ++ }; ++ struct snd_soc_tplg_stream_caps *caps; ++ unsigned int streams[2], stream; ++ const char *s; ++ int err; ++ ++ switch (elem->type) { ++ case SND_TPLG_TYPE_PCM: ++ streams[0] = elem->pcm->playback; ++ streams[1] = elem->pcm->capture; ++ caps = elem->pcm->caps; ++ break; ++ case SND_TPLG_TYPE_DAI: ++ streams[0] = elem->dai->playback; ++ streams[1] = elem->dai->capture; ++ caps = elem->dai->caps; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ for (stream = 0; stream < 2; stream++) { ++ if (streams[stream] == 0) ++ continue; ++ if (!caps) ++ continue; ++ s = caps[stream_types[stream]].name; ++ if (s[0] == '\0') ++ continue; ++ err = tplg_save_printf(dst, pfx, "pcm.%s {\n", stream_ids[stream]); ++ if (err < 0) ++ return err; ++ err = tplg_save_printf(dst, pfx, "\tcapabilities '%s'\n", s); ++ if (err < 0) ++ return err; ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ + /* Parse name and id of a front-end DAI (ie. cpu dai of a FE DAI link) */ + static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_config_t *cfg, void *private) +@@ -633,6 +769,19 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + return 0; + } + ++/* Save the caps and config of a pcm stream */ ++int tplg_save_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_pcm *pcm = elem->pcm; ++ int err = 0; ++ ++ if (pcm->dai_id > 0) ++ err = tplg_save_printf(dst, pfx, "dai.0.id %u\n", pcm->dai_id); ++ return err; ++} ++ + /* parse a flag bit of the given mask */ + static int parse_flag(snd_config_t *n, unsigned int mask_in, + unsigned int *mask, unsigned int *flags) +@@ -652,6 +801,32 @@ static int parse_flag(snd_config_t *n, unsigned int mask_in, + return 0; + } + ++static int save_flags(unsigned int flags, unsigned int mask, ++ char **dst, const char *pfx) ++{ ++ static unsigned int flag_masks[3] = { ++ SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES, ++ SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS, ++ SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS, ++ }; ++ static const char *flag_ids[3] = { ++ "symmetric_rates", ++ "symmetric_channels", ++ "symmetric_sample_bits", ++ }; ++ unsigned int i; ++ int err = 0; ++ ++ for (i = 0; err >= 0 && i < ARRAY_SIZE(flag_masks); i++) { ++ if (mask & flag_masks[i]) { ++ unsigned int v = (flags & flag_masks[i]) ? 1 : 0; ++ err = tplg_save_printf(dst, pfx, "%s %u\n", ++ flag_ids[i], v); ++ } ++ } ++ return err; ++} ++ + /* 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) +@@ -748,7 +923,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, + + /* private data */ + if (strcmp(id, "data") == 0) { +- err = tplg_parse_data_refs(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA); + if (err < 0) + return err; + continue; +@@ -758,6 +933,40 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* save PCM */ ++int tplg_save_pcm(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_pcm *pcm = elem->pcm; ++ char pfx2[16]; ++ int err; ++ ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0 && elem->index) ++ err = tplg_save_printf(dst, pfx, "\tindex %u\n", ++ elem->index); ++ if (err >= 0 && pcm->pcm_id) ++ err = tplg_save_printf(dst, pfx, "\tid %u\n", ++ pcm->pcm_id); ++ if (err >= 0 && pcm->compress) ++ err = tplg_save_printf(dst, pfx, "\tcompress 1\n"); ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ if (err >= 0) ++ err = tplg_save_fe_dai(tplg, elem, dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_streams(tplg, elem, dst, pfx2); ++ if (err >= 0) ++ err = save_flags(pcm->flags, pcm->flag_mask, dst, pfx); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA, ++ "data", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* Parse physical DAI */ + int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, + void *private ATTRIBUTE_UNUSED) +@@ -766,7 +975,7 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, + struct tplg_elem *elem; + snd_config_iterator_t i, next; + snd_config_t *n; +- const char *id, *val = NULL; ++ const char *id; + int err; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DAI); +@@ -851,11 +1060,9 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, + + /* private data */ + if (strcmp(id, "data") == 0) { +- if (snd_config_get_string(n, &val) < 0) +- return -EINVAL; +- +- tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val); +- tplg_dbg("\t%s: %s\n", id, val); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA); ++ if (err < 0) ++ return err; + continue; + } + } +@@ -863,55 +1070,55 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* save DAI */ ++int tplg_save_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_dai *dai = elem->dai; ++ char pfx2[16]; ++ int err; ++ ++ if (!dai) ++ return 0; ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0 && elem->index) ++ err = tplg_save_printf(dst, pfx, "\tindex %u\n", ++ elem->index); ++ if (err >= 0 && dai->dai_id) ++ err = tplg_save_printf(dst, pfx, "\tid %u\n", ++ dai->dai_id); ++ if (err >= 0 && dai->playback) ++ err = tplg_save_printf(dst, pfx, "\tplayback %u\n", ++ dai->playback); ++ if (err >= 0 && dai->capture) ++ err = tplg_save_printf(dst, pfx, "\tcapture %u\n", ++ dai->capture); ++ if (err >= 0) ++ err = tplg_save_streams(tplg, elem, dst, pfx2); ++ if (err >= 0) ++ err = save_flags(dai->flags, dai->flag_mask, dst, pfx); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA, ++ "data", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* parse physical link runtime supported HW configs in text conf file */ + static int parse_hw_config_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_config_t *cfg, + struct tplg_elem *elem) + { + struct snd_soc_tplg_link_config *link = elem->link; +- snd_config_type_t type; +- snd_config_iterator_t i, next; +- snd_config_t *n; +- const char *id, *val = NULL; +- +- if (snd_config_get_id(cfg, &id) < 0) +- return -EINVAL; +- type = snd_config_get_type(cfg); +- +- /* refer to a single HW config */ +- if (type == SND_CONFIG_TYPE_STRING) { +- if (snd_config_get_string(cfg, &val) < 0) +- return -EINVAL; +- +- link->num_hw_configs = 1; +- return tplg_ref_add(elem, SND_TPLG_TYPE_HW_CONFIG, val); +- } +- +- if (type != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound type expected for %s", id); +- return -EINVAL; +- } +- +- /* refer to a list of HW configs */ +- snd_config_for_each(i, next, cfg) { +- const char *val; +- int err; +- +- n = snd_config_iterator_entry(i); +- if (snd_config_get_string(n, &val) < 0) +- continue; +- +- if (link->num_hw_configs >= SND_SOC_TPLG_HW_CONFIG_MAX) { +- SNDERR("error: exceed max hw configs for link %s", id); +- return -EINVAL; +- } +- +- link->num_hw_configs++; +- err = tplg_ref_add(elem, SND_TPLG_TYPE_HW_CONFIG, val); +- if (err < 0) +- return err; +- } ++ int err; + ++ err = tplg_parse_refs(cfg, elem, SND_TPLG_TYPE_HW_CONFIG); ++ if (err < 0) ++ return err; ++ link->num_hw_configs = err; + return 0; + } + +@@ -1007,7 +1214,7 @@ int tplg_parse_link(snd_tplg_t *tplg, + + /* private data */ + if (strcmp(id, "data") == 0) { +- err = tplg_parse_data_refs(n, elem); ++ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA); + if (err < 0) + return err; + continue; +@@ -1017,6 +1224,44 @@ int tplg_parse_link(snd_tplg_t *tplg, + return 0; + } + ++/* save physical link */ ++int tplg_save_link(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_link_config *link = elem->link; ++ char pfx2[16]; ++ int err; ++ ++ if (!link) ++ return 0; ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0 && elem->index) ++ err = tplg_save_printf(dst, pfx, "\tindex %u\n", ++ elem->index); ++ if (err >= 0 && link->id) ++ err = tplg_save_printf(dst, pfx, "\tid %u\n", ++ link->id); ++ if (err >= 0 && link->stream_name[0]) ++ err = tplg_save_printf(dst, pfx, "\tstream_name '%s'\n", ++ link->stream_name); ++ if (err >= 0 && link->default_hw_config_id) ++ err = tplg_save_printf(dst, pfx, "\tdefault_hw_conf_id %u\n", ++ link->default_hw_config_id); ++ if (err >= 0) ++ err = save_flags(link->flags, link->flag_mask, dst, pfx); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_HW_CONFIG, ++ "hw_configs", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA, ++ "data", dst, pfx2); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* Parse cc */ + int tplg_parse_cc(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) +@@ -1059,36 +1304,95 @@ int tplg_parse_cc(snd_tplg_t *tplg, + return 0; + } + +-static int get_audio_hw_format(const char *val) ++/* save CC */ ++int tplg_save_cc(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) + { +- if (!strlen(val)) +- return -EINVAL; +- +- if (!strcmp(val, "I2S")) +- return SND_SOC_DAI_FORMAT_I2S; ++ struct snd_soc_tplg_link_config *link = elem->link; ++ char pfx2[16]; ++ int err; + +- if (!strcmp(val, "RIGHT_J")) +- return SND_SOC_DAI_FORMAT_RIGHT_J; ++ if (!link) ++ return 0; ++ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: ""); ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0 && elem->index) ++ err = tplg_save_printf(dst, pfx, "\tindex %u\n", ++ elem->index); ++ if (err >= 0 && link->id) ++ err = tplg_save_printf(dst, pfx, "\tid %u\n", ++ link->id); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} + +- if (!strcmp(val, "LEFT_J")) +- return SND_SOC_DAI_FORMAT_LEFT_J; ++struct audio_hw_format { ++ unsigned int type; ++ const char *name; ++}; + +- if (!strcmp(val, "DSP_A")) +- return SND_SOC_DAI_FORMAT_DSP_A; ++static struct audio_hw_format audio_hw_formats[] = { ++ { ++ .type = SND_SOC_DAI_FORMAT_I2S, ++ .name = "I2S", ++ }, ++ { ++ .type = SND_SOC_DAI_FORMAT_RIGHT_J, ++ .name = "RIGHT_J", ++ }, ++ { ++ .type = SND_SOC_DAI_FORMAT_LEFT_J, ++ .name = "LEFT_J", ++ }, ++ { ++ .type = SND_SOC_DAI_FORMAT_DSP_A, ++ .name = "DSP_A", ++ }, ++ { ++ .type = SND_SOC_DAI_FORMAT_DSP_B, ++ .name = "DSP_B", ++ }, ++ { ++ .type = SND_SOC_DAI_FORMAT_AC97, ++ .name = "AC97", ++ }, ++ { ++ .type = SND_SOC_DAI_FORMAT_AC97, ++ .name = "AC97", ++ }, ++ { ++ .type = SND_SOC_DAI_FORMAT_PDM, ++ .name = "PDM", ++ }, ++}; + +- if (!strcmp(val, "DSP_B")) +- return SND_SOC_DAI_FORMAT_DSP_B; ++static int get_audio_hw_format(const char *val) ++{ ++ unsigned int i; + +- if (!strcmp(val, "AC97")) +- return SND_SOC_DAI_FORMAT_AC97; ++ if (val[0] == '\0') ++ return -EINVAL; + +- if (!strcmp(val, "PDM")) +- return SND_SOC_DAI_FORMAT_PDM; ++ for (i = 0; i < ARRAY_SIZE(audio_hw_formats); i++) ++ if (strcasecmp(audio_hw_formats[i].name, val) == 0) ++ return audio_hw_formats[i].type; + + SNDERR("error: invalid audio HW format %s\n", val); + return -EINVAL; + } + ++static const char *get_audio_hw_format_name(unsigned int type) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(audio_hw_formats); i++) ++ if (audio_hw_formats[i].type == type) ++ return audio_hw_formats[i].name; ++ return NULL; ++} ++ + int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + void *private ATTRIBUTE_UNUSED) + { +@@ -1299,6 +1603,71 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + return 0; + } + ++/* save hw config */ ++int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct snd_soc_tplg_hw_config *hc = elem->hw_cfg; ++ int err; ++ ++ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id); ++ if (err >= 0 && hc->id) ++ err = tplg_save_printf(dst, pfx, "\tid %u\n", ++ hc->id); ++ if (err >= 0 && hc->fmt) ++ err = tplg_save_printf(dst, pfx, "\tformat '%s'\n", ++ get_audio_hw_format_name(hc->fmt)); ++ if (err >= 0 && hc->bclk_master) ++ err = tplg_save_printf(dst, pfx, "\tbclk '%s'\n", ++ hc->bclk_master == SND_SOC_TPLG_BCLK_CS ? ++ "codec_slave" : "codec_master"); ++ if (err >= 0 && hc->bclk_rate) ++ err = tplg_save_printf(dst, pfx, "\tbclk_freq %u\n", ++ hc->bclk_rate); ++ if (err >= 0 && hc->invert_bclk) ++ err = tplg_save_printf(dst, pfx, "\tbclk_invert 1\n"); ++ if (err >= 0 && hc->fsync_master) ++ err = tplg_save_printf(dst, pfx, "\tfsync_master '%s'\n", ++ hc->fsync_master == SND_SOC_TPLG_FSYNC_CS ? ++ "codec_slave" : "codec_master"); ++ if (err >= 0 && hc->fsync_rate) ++ err = tplg_save_printf(dst, pfx, "\tfsync_freq %u\n", ++ hc->fsync_rate); ++ if (err >= 0 && hc->invert_fsync) ++ err = tplg_save_printf(dst, pfx, "\tfsync_invert 1\n"); ++ if (err >= 0 && hc->mclk_rate) ++ err = tplg_save_printf(dst, pfx, "\tmclk_freq %u\n", ++ hc->mclk_rate); ++ if (err >= 0 && hc->mclk_direction) ++ err = tplg_save_printf(dst, pfx, "\tmclk '%s'\n", ++ hc->mclk_direction == SND_SOC_TPLG_MCLK_CI ? ++ "codec_mclk_in" : "codec_mclk_out"); ++ if (err >= 0 && hc->clock_gated) ++ err = tplg_save_printf(dst, pfx, "\tpm_gate_clocks 1\n"); ++ if (err >= 0 && hc->tdm_slots) ++ err = tplg_save_printf(dst, pfx, "\ttdm_slots %u\n", ++ hc->tdm_slots); ++ if (err >= 0 && hc->tdm_slot_width) ++ err = tplg_save_printf(dst, pfx, "\ttdm_slot_width %u\n", ++ hc->tdm_slot_width); ++ if (err >= 0 && hc->tx_slots) ++ err = tplg_save_printf(dst, pfx, "\ttx_slots %u\n", ++ hc->tx_slots); ++ if (err >= 0 && hc->rx_slots) ++ err = tplg_save_printf(dst, pfx, "\trx_slots %u\n", ++ hc->rx_slots); ++ if (err >= 0 && hc->tx_channels) ++ err = tplg_save_printf(dst, pfx, "\ttx_channels %u\n", ++ hc->tx_channels); ++ if (err >= 0 && hc->rx_channels) ++ err = tplg_save_printf(dst, pfx, "\trx_channels %u\n", ++ hc->rx_channels); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "}\n"); ++ return err; ++} ++ + /* copy stream object */ + static void tplg_add_stream_object(struct snd_soc_tplg_stream *strm, + struct snd_tplg_stream_template *strm_tpl) +diff --git a/src/topology/save.c b/src/topology/save.c +new file mode 100644 +index 00000000..0498911f +--- /dev/null ++++ b/src/topology/save.c +@@ -0,0 +1,632 @@ ++/* ++ Copyright(c) 2019 Red Hat Inc. ++ All rights reserved. ++ ++ This library is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of ++ the License, or (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ Authors: Jaroslav Kysela ++*/ ++ ++#include "list.h" ++#include "tplg_local.h" ++ ++#define SAVE_ALLOC_SHIFT (13) /* 8192 bytes */ ++ ++int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...) ++{ ++ va_list va; ++ char buf[1024], *s; ++ size_t n, l, t, pl; ++ ++ if (pfx == NULL) ++ pfx = ""; ++ ++ va_start(va, fmt); ++ n = vsnprintf(buf, sizeof(buf), fmt, va); ++ va_end(va); ++ ++ if (n >= sizeof(buf)) ++ return -EOVERFLOW; ++ ++ pl = strlen(pfx); ++ l = *dst ? strlen(*dst) : 0; ++ t = l + pl + n + 1; ++ /* allocate chunks */ ++ if (*dst == NULL || ++ (l >> SAVE_ALLOC_SHIFT) != (t >> SAVE_ALLOC_SHIFT)) { ++ s = realloc(*dst, ((t >> SAVE_ALLOC_SHIFT) + 1) << ++ SAVE_ALLOC_SHIFT); ++ if (s == NULL) { ++ free(*dst); ++ *dst = NULL; ++ return -ENOMEM; ++ } ++ } else { ++ s = *dst; ++ } ++ ++ if (pl > 0) ++ strcpy(s + l, pfx); ++ strcpy(s + l + pl, buf); ++ *dst = s; ++ return 0; ++} ++ ++int tplg_nice_value_format(char *dst, size_t dst_size, unsigned int value) ++{ ++ if ((value % 1000) != 0) { ++ if (value > 0xfffffff0) ++ return snprintf(dst, dst_size, "%d", (int)value); ++ if (value >= 0xffff0000) ++ return snprintf(dst, dst_size, "0x%x", value); ++ } ++ return snprintf(dst, dst_size, "%u", value); ++} ++ ++static int tplg_pprint_integer(snd_config_t *n, char **ret) ++{ ++ long lval; ++ int err, type; ++ char buf[16]; ++ ++ type = snd_config_get_type(n); ++ if (type == SND_CONFIG_TYPE_INTEGER) { ++ err = snd_config_get_integer(n, &lval); ++ if (err < 0) ++ return err; ++ if (lval < INT_MIN || lval > UINT_MAX) ++ return snd_config_get_ascii(n, ret); ++ } else if (type == SND_CONFIG_TYPE_INTEGER64) { ++ long long llval; ++ err = snd_config_get_integer64(n, &llval); ++ if (err < 0) ++ return err; ++ if (llval < INT_MIN || llval > UINT_MAX) ++ return snd_config_get_ascii(n, ret); ++ lval = llval; ++ } ++ err = tplg_nice_value_format(buf, sizeof(buf), (unsigned int)lval); ++ if (err < 0) ++ return err; ++ *ret = strdup(buf); ++ if (*ret == NULL) ++ return -ENOMEM; ++ return 0; ++} ++ ++static int tplg_check_array_item(const char *id, int index) ++{ ++ const char *p; ++ long int val; ++ ++ for (p = id; *p; p++) { ++ if (*p < '0' || *p > '9') ++ return 0; ++ } ++ ++ errno = 0; ++ val = strtol(id, NULL, 10); ++ return errno == 0 && val == index; ++} ++ ++static int _compar(const void *a, const void *b) ++{ ++ const snd_config_t *c1 = *(snd_config_t **)a; ++ const snd_config_t *c2 = *(snd_config_t **)b; ++ const char *id1, *id2; ++ if (snd_config_get_id(c1, &id1)) return 0; ++ if (snd_config_get_id(c2, &id2)) return 0; ++ return strcmp(id1, id2); ++} ++ ++static snd_config_t *sort_config(const char *id, snd_config_t *src) ++{ ++ snd_config_t *dst, **a; ++ snd_config_iterator_t i, next; ++ int index, array, count; ++ ++ if (snd_config_get_type(src) != SND_CONFIG_TYPE_COMPOUND) { ++ ++ if (snd_config_copy(&dst, src) >= 0) ++ return dst; ++ return NULL; ++ } ++ count = 0; ++ snd_config_for_each(i, next, src) ++ count++; ++ a = malloc(sizeof(dst) * count); ++ if (a == NULL) ++ return NULL; ++ index = array = 0; ++ snd_config_for_each(i, next, src) { ++ snd_config_t *s = snd_config_iterator_entry(i); ++ const char *id2; ++ a[index++] = s; ++ if (array < 0) ++ continue; ++ if (snd_config_get_id(s, &id2)) { ++ free(a); ++ return NULL; ++ } ++ if (array >= 0 && tplg_check_array_item(id2, array)) ++ array++; ++ else ++ array = -1; ++ } ++ if (array < 0) ++ qsort(a, count, sizeof(a[0]), _compar); ++ if (snd_config_make_compound(&dst, id, count == 1)) { ++ free(a); ++ return NULL; ++ } ++ for (index = 0; index < count; index++) { ++ snd_config_t *s = a[index]; ++ const char *id2; ++ if (snd_config_get_id(s, &id2)) { ++ snd_config_delete(dst); ++ free(a); ++ return NULL; ++ } ++ s = sort_config(id2, s); ++ if (s == NULL || snd_config_add(dst, s)) { ++ if (s) ++ snd_config_delete(s); ++ snd_config_delete(dst); ++ free(a); ++ return NULL; ++ } ++ } ++ free(a); ++ return dst; ++} ++ ++static int tplg_check_quoted(const unsigned char *p) ++{ ++ for ( ; *p != '\0'; p++) { ++ switch (*p) { ++ case ' ': ++ case '=': ++ case ';': ++ case ',': ++ case '.': ++ case '{': ++ case '}': ++ case '\'': ++ case '"': ++ return 1; ++ default: ++ if (*p <= 31 || *p >= 127) ++ return 1; ++ ++ } ++ } ++ return 0; ++} ++ ++static int tplg_save_quoted(char **dst, const char *str) ++{ ++ static const char nibble[16] = "0123456789abcdef"; ++ unsigned char *p, *d, *t; ++ int c; ++ ++ d = t = alloca(strlen(str) * 5 + 1 + 1); ++ for (p = (unsigned char *)str; *p != '\0'; p++) { ++ c = *p; ++ switch (c) { ++ case '\n': ++ *t++ = '\\'; ++ *t++ = 'n'; ++ break; ++ case '\t': ++ *t++ = '\\'; ++ *t++ = 't'; ++ break; ++ case '\v': ++ *t++ = '\\'; ++ *t++ = 'v'; ++ break; ++ case '\b': ++ *t++ = '\\'; ++ *t++ = 'b'; ++ break; ++ case '\r': ++ *t++ = '\\'; ++ *t++ = 'r'; ++ break; ++ case '\f': ++ *t++ = '\\'; ++ *t++ = 'f'; ++ break; ++ case '\'': ++ *t++ = '\\'; ++ *t++ = c; ++ break; ++ default: ++ if (c >= 32 && c <= 126) { ++ *t++ = c; ++ } else { ++ *t++ = '\\'; ++ *t++ = 'x'; ++ *t++ = nibble[(c >> 4) & 0x0f]; ++ *t++ = nibble[(c >> 0) & 0x0f]; ++ } ++ break; ++ } ++ } ++ *t = '\0'; ++ return tplg_save_printf(dst, NULL, "'%s'", d); ++} ++ ++static int tplg_save_string(char **dst, const char *str, int id) ++{ ++ const unsigned char *p = (const unsigned char *)str; ++ ++ if (!p || !*p) ++ return tplg_save_printf(dst, NULL, "''"); ++ ++ if (!id && ((*p >= '0' && *p <= '9') || *p == '-')) ++ return tplg_save_quoted(dst, str); ++ ++ if (tplg_check_quoted(p)) ++ return tplg_save_quoted(dst, str); ++ ++ return tplg_save_printf(dst, NULL, "%s", str); ++} ++ ++static int save_config(char **dst, int level, const char *delim, snd_config_t *src) ++{ ++ snd_config_iterator_t i, next; ++ snd_config_t *s; ++ const char *id; ++ char *pfx; ++ unsigned int count; ++ int type, err, quoted, array; ++ ++ if (delim == NULL) ++ delim = ""; ++ ++ type = snd_config_get_type(src); ++ if (type != SND_CONFIG_TYPE_COMPOUND) { ++ char *val; ++ if (type == SND_CONFIG_TYPE_INTEGER || ++ type == SND_CONFIG_TYPE_INTEGER64) { ++ err = tplg_pprint_integer(src, &val); ++ } else { ++ err = snd_config_get_ascii(src, &val); ++ } ++ if (err < 0) ++ return err; ++ if (type == SND_CONFIG_TYPE_STRING) { ++ /* hexa array pretty print */ ++ id = strchr(val, '\n'); ++ if (id) { ++ err = tplg_save_printf(dst, NULL, "\n"); ++ if (err < 0) ++ goto retval; ++ for (id++; *id == '\t'; id++) { ++ err = tplg_save_printf(dst, NULL, "\t"); ++ if (err < 0) ++ goto retval; ++ } ++ delim = ""; ++ } ++ err = tplg_save_printf(dst, NULL, "%s'%s'\n", delim, val); ++ } else { ++ err = tplg_save_printf(dst, NULL, "%s%s\n", delim, val); ++ } ++retval: ++ free(val); ++ return err; ++ } ++ ++ count = 0; ++ quoted = 0; ++ array = 0; ++ s = NULL; ++ snd_config_for_each(i, next, src) { ++ s = snd_config_iterator_entry(i); ++ err = snd_config_get_id(s, &id); ++ if (err < 0) ++ return err; ++ if (!quoted && tplg_check_quoted((unsigned char *)id)) ++ quoted = 1; ++ if (array >= 0 && tplg_check_array_item(id, array)) ++ array++; ++ else ++ array = -1; ++ count++; ++ } ++ if (count == 0) ++ return 0; ++ ++ if (count == 1) { ++ err = snd_config_get_id(s, &id); ++ if (err >= 0 && level > 0) ++ err = tplg_save_printf(dst, NULL, "."); ++ if (err >= 0) ++ err = tplg_save_string(dst, id, 1); ++ if (err >= 0) ++ err = save_config(dst, level, " ", s); ++ return err; ++ } ++ ++ pfx = alloca(level + 1); ++ memset(pfx, '\t', level); ++ pfx[level] = '\0'; ++ ++ if (level > 0) { ++ err = tplg_save_printf(dst, NULL, "%s%s\n", delim, ++ array >= 0 ? "[" : "{"); ++ if (err < 0) ++ return err; ++ } ++ ++ snd_config_for_each(i, next, src) { ++ s = snd_config_iterator_entry(i); ++ const char *id; ++ err = snd_config_get_id(s, &id); ++ if (err < 0) ++ return err; ++ err = tplg_save_printf(dst, pfx, ""); ++ if (err < 0) ++ return err; ++ if (array < 0) { ++ delim = " "; ++ if (quoted) { ++ err = tplg_save_quoted(dst, id); ++ } else { ++ err = tplg_save_string(dst, id, 1); ++ if (err < 0) ++ return err; ++ } ++ } else { ++ delim = ""; ++ } ++ err = save_config(dst, level + 1, delim, s); ++ if (err < 0) ++ return err; ++ } ++ ++ if (level > 0) { ++ pfx[level - 1] = '\0'; ++ err = tplg_save_printf(dst, pfx, "%s\n", ++ array >= 0 ? "]" : "}"); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int tplg_save(snd_tplg_t *tplg, char **dst, int gindex, const char *prefix) ++{ ++ struct tplg_table *tptr; ++ struct tplg_elem *elem; ++ struct list_head *list, *pos; ++ char pfx2[16]; ++ unsigned int index; ++ int err, count; ++ ++ snprintf(pfx2, sizeof(pfx2), "%s\t", prefix ?: ""); ++ ++ /* write all blocks */ ++ for (index = 0; index < tplg_table_items; index++) { ++ tptr = &tplg_table[index]; ++ list = (struct list_head *)((void *)tplg + tptr->loff); ++ ++ /* count elements */ ++ count = 0; ++ list_for_each(pos, list) { ++ elem = list_entry(pos, struct tplg_elem, list); ++ if (gindex >= 0 && elem->index != gindex) ++ continue; ++ if (tptr->save == NULL && tptr->gsave == NULL) { ++ SNDERR("unable to create %s block (no callback)", ++ tptr->id); ++ err = -ENXIO; ++ goto _err; ++ } ++ if (tptr->save) ++ count++; ++ } ++ ++ if (count == 0) ++ continue; ++ ++ if (count > 1) { ++ err = tplg_save_printf(dst, prefix, "%s {\n", ++ elem->table ? ++ elem->table->id : "_NOID_"); ++ } else { ++ err = tplg_save_printf(dst, prefix, "%s.", ++ elem->table ? ++ elem->table->id : "_NOID_"); ++ } ++ ++ if (err < 0) ++ goto _err; ++ ++ list_for_each(pos, list) { ++ elem = list_entry(pos, struct tplg_elem, list); ++ if (gindex >= 0 && elem->index != gindex) ++ continue; ++ if (count > 1) { ++ err = tplg_save_printf(dst, pfx2, ""); ++ if (err < 0) ++ goto _err; ++ } ++ err = tptr->save(tplg, elem, dst, count > 1 ? pfx2 : prefix); ++ if (err < 0) { ++ SNDERR("failed to save %s elements: %s", ++ tptr->id, snd_strerror(-err)); ++ goto _err; ++ } ++ } ++ if (count > 1) { ++ err = tplg_save_printf(dst, prefix, "}\n"); ++ if (err < 0) ++ goto _err; ++ } ++ } ++ ++ /* save globals */ ++ for (index = 0; index < tplg_table_items; index++) { ++ tptr = &tplg_table[index]; ++ if (tptr->gsave) { ++ err = tptr->gsave(tplg, gindex, dst, prefix); ++ if (err < 0) ++ goto _err; ++ } ++ } ++ ++ return 0; ++ ++_err: ++ free(*dst); ++ *dst = NULL; ++ return err; ++} ++ ++static int tplg_index_compar(const void *a, const void *b) ++{ ++ const int *a1 = a, *b1 = b; ++ return *a1 - *b1; ++} ++ ++static int tplg_index_groups(snd_tplg_t *tplg, int **indexes) ++{ ++ struct tplg_table *tptr; ++ struct tplg_elem *elem; ++ struct list_head *list, *pos; ++ unsigned int index, j, count, size; ++ int *a, *b; ++ ++ count = 0; ++ size = 16; ++ a = malloc(size * sizeof(a[0])); ++ ++ for (index = 0; index < tplg_table_items; index++) { ++ tptr = &tplg_table[index]; ++ list = (struct list_head *)((void *)tplg + tptr->loff); ++ list_for_each(pos, list) { ++ elem = list_entry(pos, struct tplg_elem, list); ++ for (j = 0; j < count; j++) { ++ if (a[j] == elem->index) ++ break; ++ } ++ if (j < count) ++ continue; ++ if (count + 1 >= size) { ++ size += 8; ++ b = realloc(a, size * sizeof(a[0])); ++ if (b == NULL) { ++ free(a); ++ return -ENOMEM; ++ } ++ a = b; ++ } ++ a[count++] = elem->index; ++ } ++ } ++ a[count] = -1; ++ ++ qsort(a, count, sizeof(a[0]), tplg_index_compar); ++ ++ *indexes = a; ++ return 0; ++} ++ ++int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags) ++{ ++ snd_input_t *in; ++ snd_config_t *top, *top2; ++ char *dst2; ++ int *indexes, *a; ++ int err; ++ ++ assert(tplg); ++ assert(dst); ++ *dst = NULL; ++ ++ if (flags & SND_TPLG_SAVE_GROUPS) { ++ err = tplg_index_groups(tplg, &indexes); ++ if (err < 0) ++ return err; ++ for (a = indexes; err >= 0 && *a >= 0; a++) { ++ err = tplg_save_printf(dst, NULL, ++ "IndexGroup.%d {\n", ++ *a); ++ if (err >= 0) ++ err = tplg_save(tplg, dst, *a, "\t"); ++ if (err >= 0) ++ err = tplg_save_printf(dst, NULL, "}\n"); ++ } ++ free(indexes); ++ } else { ++ err = tplg_save(tplg, dst, -1, NULL); ++ } ++ ++ if (err < 0) ++ goto _err; ++ ++ if (flags & SND_TPLG_SAVE_NOCHECK) ++ return 0; ++ ++ /* always load configuration - check */ ++ err = snd_input_buffer_open(&in, *dst, strlen(*dst)); ++ if (err < 0) { ++ SNDERR("could not create input buffer"); ++ goto _err; ++ } ++ ++ err = snd_config_top(&top); ++ if (err < 0) { ++ snd_input_close(in); ++ goto _err; ++ } ++ ++ err = snd_config_load(top, in); ++ snd_input_close(in); ++ if (err < 0) { ++ SNDERR("could not load configuration"); ++ snd_config_delete(top); ++ goto _err; ++ } ++ ++ if (flags & SND_TPLG_SAVE_SORT) { ++ top2 = sort_config(NULL, top); ++ if (top2 == NULL) { ++ SNDERR("could not sort configuration"); ++ snd_config_delete(top); ++ err = -EINVAL; ++ goto _err; ++ } ++ snd_config_delete(top); ++ top = top2; ++ } ++ ++ dst2 = NULL; ++ err = save_config(&dst2, 0, NULL, top); ++ snd_config_delete(top); ++ if (err < 0) { ++ SNDERR("could not save configuration"); ++ goto _err; ++ } ++ ++ free(*dst); ++ *dst = dst2; ++ return 0; ++ ++_err: ++ free(*dst); ++ *dst = NULL; ++ return err; ++} +diff --git a/src/topology/text.c b/src/topology/text.c +index f301a4de..e9386e7d 100644 +--- a/src/topology/text.c ++++ b/src/topology/text.c +@@ -89,3 +89,22 @@ int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg, + + return err; + } ++ ++/* save text data */ ++int tplg_save_text(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) ++{ ++ struct tplg_texts *texts = elem->texts; ++ unsigned int i; ++ int err; ++ ++ if (!texts || texts->num_items == 0) ++ return 0; ++ err = tplg_save_printf(dst, pfx, "'%s'.values [\n", elem->id); ++ for (i = 0; err >= 0 && i < texts->num_items; i++) ++ err = tplg_save_printf(dst, pfx, "\t'%s'\n", texts->items[i][0]); ++ if (err >= 0) ++ err = tplg_save_printf(dst, pfx, "]\n"); ++ return err; ++} +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index bea88ba3..42a3aa96 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -37,6 +37,7 @@ + + struct tplg_ref; + struct tplg_elem; ++struct tplg_table; + + typedef enum _snd_pcm_rates { + SND_PCM_RATE_UNKNOWN = -1, +@@ -147,6 +148,8 @@ struct tplg_vendor_tuples { + /* topology element */ + struct tplg_elem { + ++ struct tplg_table *table; ++ + char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + + int index; +@@ -209,6 +212,10 @@ struct tplg_table { + unsigned enew: 1; + void (*free)(void *); + int (*parse)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); ++ int (*save)(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *prefix); ++ int (*gsave)(snd_tplg_t *tplg, int index, ++ char **dst, const char *prefix); + }; + + extern struct tplg_table tplg_table[]; +@@ -250,7 +257,8 @@ int tplg_build_pcm_dai(snd_tplg_t *tplg, unsigned int type); + int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem, + struct tplg_ref *ref); + +-int tplg_parse_data_refs(snd_config_t *cfg, struct tplg_elem *elem); ++int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem, ++ unsigned int type); + + int tplg_ref_add(struct tplg_elem *elem, int type, const char* id); + int tplg_ref_add_elem(struct tplg_elem *elem, struct tplg_elem *elem_ref); +@@ -269,9 +277,11 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + int tplg_get_integer(snd_config_t *n, int *val, int base); + int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base); + ++const char *tplg_channel_name(int type); + int tplg_parse_channel(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_config_t *cfg, void *private); + ++const char *tplg_ops_name(int type); + int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_config_t *cfg, void *private); + int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, +@@ -299,3 +309,49 @@ int tplg_build_links(snd_tplg_t *tplg, unsigned int type); + int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); + int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); + int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); ++ ++int tplg_nice_value_format(char *dst, size_t dst_size, unsigned int value); ++ ++int tplg_save_printf(char **dst, const char *prefix, const char *fmt, ...); ++int tplg_save_refs(snd_tplg_t *tplg, struct tplg_elem *elem, unsigned int type, ++ const char *id, char **dst, const char *pfx); ++int tplg_save_channels(snd_tplg_t *tplg, struct snd_soc_tplg_channel *channel, ++ unsigned int channel_count, char **dst, const char *pfx); ++int tplg_save_ops(snd_tplg_t *tplg, struct snd_soc_tplg_ctl_hdr *hdr, ++ char **dst, const char *pfx); ++int tplg_save_ext_ops(snd_tplg_t *tplg, struct snd_soc_tplg_bytes_control *be, ++ char **dst, const char *pfx); ++int tplg_save_manifest_data(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_control_mixer(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_control_enum(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_control_bytes(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_tlv(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_data(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_text(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_tokens(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_tuples(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, ++ char **dst, const char *pfx); ++int tplg_save_dapm_widget(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_link(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_cc(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_pcm(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_hw_config(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_stream_caps(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); ++int tplg_save_dai(snd_tplg_t *tplg, struct tplg_elem *elem, ++ char **dst, const char *pfx); +-- +2.24.1 + + +From b336aea507b80493cdae439f09f710eec4bcd4ae Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 20 Dec 2019 14:59:00 +0100 +Subject: [PATCH 44/69] topology: add snd_tplg_create() with flags + +Add SND_TPLG_CREATE_VERBOSE and SND_TPLG_CREATE_DAPM_NOSORT +flags for the special operations. + +Signed-off-by: Jaroslav Kysela +--- + include/topology.h | 10 ++++++++++ + src/topology/dapm.c | 5 ++++- + src/topology/parser.c | 10 +++++++++- + src/topology/tplg_local.h | 1 + + 4 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/include/topology.h b/include/topology.h +index 69aa5ed7..63c13a98 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -771,12 +771,22 @@ enum snd_tplg_type { + /** Fit for all user cases */ + #define SND_TPLG_INDEX_ALL 0 + ++/** Flags for the snd_tplg_create */ ++#define SND_TPLG_CREATE_VERBOSE (1<<0) /*!< Verbose output */ ++#define SND_TPLG_CREATE_DAPM_NOSORT (1<<1) /*!< Do not sort DAPM objects by index */ ++ + /** + * \brief Create a new topology parser instance. + * \return New topology parser instance + */ + snd_tplg_t *snd_tplg_new(void); + ++/** ++ * \brief Create a new topology parser instance. ++ * \return New topology parser instance ++ */ ++snd_tplg_t *snd_tplg_create(int flags); ++ + /** + * \brief Free a topology parser instance. + * \param tplg Topology parser instance +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index 2bdacedc..d6c15fc1 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -268,7 +268,10 @@ struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg, int index) + return NULL; + + elem->index = index; +- tplg_elem_insert(elem, &tplg->route_list); ++ if (tplg->dapm_sort) ++ tplg_elem_insert(elem, &tplg->route_list); ++ else ++ list_add_tail(&elem->list, &tplg->route_list); + strcpy(elem->id, "line"); + elem->type = SND_TPLG_TYPE_DAPM_GRAPH; + elem->size = sizeof(*line); +diff --git a/src/topology/parser.c b/src/topology/parser.c +index de5edd1b..8f810f75 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -432,7 +432,7 @@ static bool is_little_endian(void) + return false; + } + +-snd_tplg_t *snd_tplg_new(void) ++snd_tplg_t *snd_tplg_create(int flags) + { + snd_tplg_t *tplg; + +@@ -445,6 +445,9 @@ snd_tplg_t *snd_tplg_new(void) + if (!tplg) + return NULL; + ++ tplg->verbose = !!(flags & SND_TPLG_CREATE_VERBOSE); ++ tplg->dapm_sort = (flags & SND_TPLG_CREATE_DAPM_NOSORT) == 0; ++ + tplg->manifest.size = sizeof(struct snd_soc_tplg_manifest); + + INIT_LIST_HEAD(&tplg->tlv_list); +@@ -469,6 +472,11 @@ snd_tplg_t *snd_tplg_new(void) + return tplg; + } + ++snd_tplg_t *snd_tplg_new(void) ++{ ++ return snd_tplg_create(0); ++} ++ + void snd_tplg_free(snd_tplg_t *tplg) + { + free(tplg->bin); +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 42a3aa96..74b3a55c 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -66,6 +66,7 @@ struct snd_tplg { + size_t bin_size; + + int verbose; ++ unsigned int dapm_sort: 1; + unsigned int version; + + /* runtime state */ +-- +2.24.1 + + +From 0793ef064a97afd0b1335af0d187ede227b90582 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 20 Dec 2019 21:28:30 +0100 +Subject: [PATCH 45/69] topology: add snd_tplg_version() function + +Signed-off-by: Jaroslav Kysela +--- + include/topology.h | 6 ++++++ + src/topology/parser.c | 5 +++++ + 2 files changed, 11 insertions(+) + +diff --git a/include/topology.h b/include/topology.h +index 63c13a98..37bced1a 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -775,6 +775,12 @@ enum snd_tplg_type { + #define SND_TPLG_CREATE_VERBOSE (1<<0) /*!< Verbose output */ + #define SND_TPLG_CREATE_DAPM_NOSORT (1<<1) /*!< Do not sort DAPM objects by index */ + ++/** ++ * \brief Return the version of the topology library. ++ * \return A static string with the version number. ++ */ ++const char *snd_tplg_version(void); ++ + /** + * \brief Create a new topology parser instance. + * \return New topology parser instance +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 8f810f75..1eaa24bd 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -503,3 +503,8 @@ void snd_tplg_free(snd_tplg_t *tplg) + + free(tplg); + } ++ ++const char *snd_tplg_version(void) ++{ ++ return SND_LIB_VERSION_STR; ++} +-- +2.24.1 + + +From f42b2c088a23e1c6156c0d5710efd7689b8c15be Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 20 Dec 2019 23:48:40 +0100 +Subject: [PATCH 46/69] topology: cleanup the SNDERR() calls + +- remove the wrong new lines +- remove error/warning prefixes (error is error) + +Signed-off-by: Jaroslav Kysela +--- + src/topology/builder.c | 16 ++++++------- + src/topology/channel.c | 2 +- + src/topology/ctl.c | 36 +++++++++++++--------------- + src/topology/dapm.c | 40 ++++++++++++++----------------- + src/topology/data.c | 53 +++++++++++++++++++++--------------------- + src/topology/parser.c | 33 +++++++++++++------------- + src/topology/pcm.c | 29 +++++++++++------------ + src/topology/text.c | 2 +- + 8 files changed, 99 insertions(+), 112 deletions(-) + +diff --git a/src/topology/builder.c b/src/topology/builder.c +index cadb5583..74c44405 100644 +--- a/src/topology/builder.c ++++ b/src/topology/builder.c +@@ -65,8 +65,8 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type, + + /* make sure file offset is aligned with the calculated HDR offset */ + if (tplg->bin_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", ++ SNDERR("New header is at offset 0x%zx but file" ++ " offset 0x%zx is %s by %ld bytes", + tplg->next_hdr_pos, tplg->bin_pos, + tplg->bin_pos > tplg->next_hdr_pos ? "ahead" : "behind", + labs(tplg->bin_pos - tplg->next_hdr_pos)); +@@ -108,7 +108,7 @@ static int write_elem_block(snd_tplg_t *tplg, + ret = write_block_header(tplg, tplg_type, elem->vendor_type, + tplg->version, elem->index, block_size, count); + if (ret < 0) { +- SNDERR("error: failed to write %s block %d\n", ++ SNDERR("failed to write %s block %d", + obj_name, ret); + return ret; + } +@@ -148,7 +148,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 %zu wrote %zu\n", ++ SNDERR("size mismatch. Expected %zu wrote %zu", + size, total_size); + return -EIO; + } +@@ -221,7 +221,7 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg) + tplg->version, 0, + sizeof(tplg->manifest) + tplg->manifest.priv.size, 1); + if (ret < 0) { +- SNDERR("error: failed to write manifest block\n"); ++ SNDERR("failed to write manifest block"); + return ret; + } + +@@ -266,7 +266,7 @@ int tplg_write_data(snd_tplg_t *tplg) + /* write manifest */ + ret = write_manifest_data(tplg); + if (ret < 0) { +- SNDERR("failed to write manifest %d\n", ret); ++ SNDERR("failed to write manifest %d", ret); + return ret; + } + +@@ -286,7 +286,7 @@ int tplg_write_data(snd_tplg_t *tplg) + ret = write_elem_block(tplg, list, size, + tptr->tsoc, tptr->name); + if (ret < 0) { +- SNDERR("failed to write %s elements: %s\n", ++ SNDERR("failed to write %s elements: %s", + tptr->name, snd_strerror(-ret)); + return ret; + } +@@ -295,7 +295,7 @@ int tplg_write_data(snd_tplg_t *tplg) + verbose(tplg, "total size is 0x%zx/%zd\n", tplg->bin_pos, tplg->bin_pos); + + if (total_size != tplg->bin_pos) { +- SNDERR("total size mismatch (%zd != %zd)\n", ++ SNDERR("total size mismatch (%zd != %zd)", + total_size, tplg->bin_pos); + return -EINVAL; + } +diff --git a/src/topology/channel.c b/src/topology/channel.c +index b54a10c8..110775a8 100644 +--- a/src/topology/channel.c ++++ b/src/topology/channel.c +@@ -104,7 +104,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + + channel_id = lookup_channel(id); + if (channel_id < 0) { +- SNDERR("error: invalid channel %s\n", id); ++ SNDERR("invalid channel %s", id); + return -EINVAL; + } + +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index 979cc1b0..03874b27 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -94,7 +94,7 @@ int parse_access(snd_config_t *cfg, + if (strcmp(id, "access") == 0) { + err = parse_access_values(n, hdr); + if (err < 0) { +- SNDERR("error: failed to parse access"); ++ SNDERR("failed to parse access"); + return err; + } + continue; +@@ -187,8 +187,8 @@ static int tplg_build_mixer_control(snd_tplg_t *tplg, + } + + if (!ref->elem) { +- SNDERR("error: cannot find '%s' referenced by" +- " control '%s'\n", ref->id, elem->id); ++ SNDERR("cannot find '%s' referenced by" ++ " control '%s'", ref->id, elem->id); + return -EINVAL; + } else if (err < 0) + return err; +@@ -236,8 +236,8 @@ static int tplg_build_enum_control(snd_tplg_t *tplg, + return err; + } + if (!ref->elem) { +- SNDERR("error: cannot find '%s' referenced by" +- " control '%s'\n", ref->id, elem->id); ++ SNDERR("cannot find '%s' referenced by" ++ " control '%s'", ref->id, elem->id); + return -EINVAL; + } + } +@@ -341,10 +341,8 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem) + n = snd_config_iterator_entry(i); + + /* get ID */ +- if (snd_config_get_id(n, &id) < 0) { +- SNDERR("error: cant get ID\n"); ++ if (snd_config_get_id(n, &id) < 0) + return -EINVAL; +- } + + /* get value */ + if (tplg_get_integer(n, &val, 0)) +@@ -360,7 +358,7 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem) + else if (strcmp(id, "mute") == 0) + scale->mute = val; + else +- SNDERR("error: unknown key %s\n", id); ++ SNDERR("unknown id '%s'", id); + } + + return 0; +@@ -389,7 +387,7 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg, + if (strcmp(id, "scale") == 0) { + err = tplg_parse_tlv_dbscale(n, elem); + if (err < 0) { +- SNDERR("error: failed to DBScale"); ++ SNDERR("failed to DBScale"); + return err; + } + continue; +@@ -651,8 +649,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, + + if (strcmp(id, "channel") == 0) { + if (ec->num_channels >= SND_SOC_TPLG_MAX_CHAN) { +- SNDERR("error: too many channels %s\n", +- elem->id); ++ SNDERR("too many channels %s", elem->id); + return -EINVAL; + } + +@@ -779,8 +776,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + + if (strcmp(id, "channel") == 0) { + if (mc->num_channels >= SND_SOC_TPLG_MAX_CHAN) { +- SNDERR("error: too many channels %s\n", +- elem->id); ++ SNDERR("too many channels %s", elem->id); + return -EINVAL; + } + +@@ -933,7 +929,7 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr, + struct snd_soc_tplg_tlv_dbscale *scale; + + if (!tlvt) { +- SNDERR("error: missing TLV data\n"); ++ SNDERR("missing TLV data"); + return -EINVAL; + } + +@@ -952,7 +948,7 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr, + + /* TODO: add support for other TLV types */ + default: +- SNDERR("error: unsupported TLV type %d\n", tlv->type); ++ SNDERR("unsupported TLV type %d", tlv->type); + break; + } + } +@@ -971,7 +967,7 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer, + tplg_dbg(" Control Mixer: %s\n", mixer->hdr.name); + + if (mixer->hdr.type != SND_SOC_TPLG_TYPE_MIXER) { +- SNDERR("error: invalid mixer type %d\n", mixer->hdr.type); ++ SNDERR("invalid mixer type %d", mixer->hdr.type); + return -EINVAL; + } + +@@ -1039,7 +1035,7 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, + tplg_dbg(" Control Enum: %s\n", enum_ctl->hdr.name); + + if (enum_ctl->hdr.type != SND_SOC_TPLG_TYPE_ENUM) { +- SNDERR("error: invalid enum type %d\n", enum_ctl->hdr.type); ++ SNDERR("invalid enum type %d", enum_ctl->hdr.type); + return -EINVAL; + } + +@@ -1113,7 +1109,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl, + tplg_dbg(" Control Bytes: %s\n", bytes_ctl->hdr.name); + + if (bytes_ctl->hdr.type != SND_SOC_TPLG_TYPE_BYTES) { +- SNDERR("error: invalid bytes type %d\n", bytes_ctl->hdr.type); ++ SNDERR("invalid bytes type %d", bytes_ctl->hdr.type); + return -EINVAL; + } + +@@ -1157,7 +1153,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl, + if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { + if ((be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) + != SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) { +- SNDERR("error: Invalid TLV bytes control access 0x%x\n", ++ SNDERR("Invalid TLV bytes control access 0x%x", + be->hdr.access); + tplg_elem_free(elem); + return -EINVAL; +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index d6c15fc1..f61fe071 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -154,8 +154,7 @@ static int tplg_build_widget(snd_tplg_t *tplg, struct tplg_elem *elem) + } + + if (!ref->elem) { +- SNDERR("error: cannot find '%s'" +- " referenced by widget '%s'\n", ++ SNDERR("cannot find '%s' referenced by widget '%s'", + ref->id, elem->id); + return -EINVAL; + } +@@ -179,8 +178,7 @@ int tplg_build_widgets(snd_tplg_t *tplg) + + elem = list_entry(pos, struct tplg_elem, list); + if (!elem->widget || elem->type != SND_TPLG_TYPE_DAPM_WIDGET) { +- SNDERR("error: invalid widget '%s'\n", +- elem->id); ++ SNDERR("invalid widget '%s'", elem->id); + return -EINVAL; + } + +@@ -207,8 +205,7 @@ int tplg_build_routes(snd_tplg_t *tplg) + elem = list_entry(pos, struct tplg_elem, list); + + if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH) { +- SNDERR("error: invalid route '%s'\n", +- elem->id); ++ SNDERR("invalid route '%s'", elem->id); + return -EINVAL; + } + +@@ -218,14 +215,13 @@ int tplg_build_routes(snd_tplg_t *tplg) + + /* validate sink */ + if (strlen(route->sink) <= 0) { +- SNDERR("error: no sink\n"); ++ SNDERR("no sink"); + return -EINVAL; + + } + if (!tplg_elem_lookup(&tplg->widget_list, route->sink, + SND_TPLG_TYPE_DAPM_WIDGET, SND_TPLG_INDEX_ALL)) { +- SNDERR("warning: undefined sink widget/stream '%s'\n", +- route->sink); ++ SNDERR("undefined sink widget/stream '%s'", route->sink); + } + + /* validate control name */ +@@ -234,21 +230,21 @@ int tplg_build_routes(snd_tplg_t *tplg) + SND_TPLG_TYPE_MIXER, elem->index) && + !tplg_elem_lookup(&tplg->enum_list, route->control, + SND_TPLG_TYPE_ENUM, elem->index)) { +- SNDERR("warning: Undefined mixer/enum control '%s'\n", +- route->control); ++ SNDERR("Undefined mixer/enum control '%s'", ++ route->control); + } + } + + /* validate source */ + if (strlen(route->source) <= 0) { +- SNDERR("error: no source\n"); ++ SNDERR("no source"); + return -EINVAL; + + } + if (!tplg_elem_lookup(&tplg->widget_list, route->source, + SND_TPLG_TYPE_DAPM_WIDGET, SND_TPLG_INDEX_ALL)) { +- SNDERR("warning: Undefined source widget/stream '%s'\n", +- route->source); ++ SNDERR("Undefined source widget/stream '%s'", ++ route->source); + } + + /* add graph to manifest */ +@@ -300,7 +296,7 @@ static int tplg_parse_line(const char *text, + + len = strlen(buf); + if (len <= 2) { +- SNDERR("error: invalid route \"%s\"\n", buf); ++ SNDERR("invalid route \"%s\"", buf); + return -EINVAL; + } + +@@ -309,7 +305,7 @@ static int tplg_parse_line(const char *text, + if (buf[i] == ',') + goto second; + } +- SNDERR("error: invalid route \"%s\"\n", buf); ++ SNDERR("invalid route \"%s\"", buf); + return -EINVAL; + + second: +@@ -323,7 +319,7 @@ second: + goto done; + } + +- SNDERR("error: invalid route \"%s\"\n", buf); ++ SNDERR("invalid route \"%s\"", buf); + return -EINVAL; + + done: +@@ -378,7 +374,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, + int index = -1; + + if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound is expected for dapm graph definition\n"); ++ SNDERR("compound is expected for dapm graph definition"); + return -EINVAL; + } + +@@ -401,13 +397,13 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, + + if (strcmp(id, "lines") == 0) { + if (index < 0) { +- SNDERR("error: failed to parse dapm graph %s, missing index\n", ++ SNDERR("failed to parse dapm graph %s, missing index", + graph_id); + return -EINVAL; + } + err = tplg_parse_routes(tplg, n, index); + if (err < 0) { +- SNDERR("error: failed to parse dapm graph %s\n", ++ SNDERR("failed to parse dapm graph %s", + graph_id); + return err; + } +@@ -528,7 +524,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + + widget_type = lookup_widget(val); + if (widget_type < 0){ +- SNDERR("Widget '%s': Unsupported widget type %s\n", ++ SNDERR("widget '%s': Unsupported widget type %s", + elem->id, val); + return -EINVAL; + } +@@ -821,7 +817,7 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + break; + + default: +- SNDERR("error: widget %s: invalid type %d for ctl %d\n", ++ SNDERR("widget %s: invalid type %d for ctl %d", + wt->name, ct->type, i); + break; + } +diff --git a/src/topology/data.c b/src/topology/data.c +index 11cd73f5..f00ed301 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -61,7 +61,7 @@ struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem) + priv = &elem->pcm->priv; + break; + default: +- SNDERR("error: '%s': no support for private data for type %d\n", ++ SNDERR("'%s': no support for private data for type %d", + elem->id, elem->type); + } + +@@ -95,7 +95,7 @@ int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem, + } + + if (cfg_type != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound type expected for %s", elem->id); ++ SNDERR("compound type expected for %s", elem->id); + return -EINVAL; + } + +@@ -183,8 +183,7 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem) + + fp = fopen(filename, "r"); + if (fp == NULL) { +- SNDERR("error: invalid data file path '%s'\n", +- filename); ++ SNDERR("invalid data file path '%s'", filename); + return -errno; + } + +@@ -192,12 +191,12 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem) + size = ftell(fp); + fseek(fp, 0L, SEEK_SET); + if (size <= 0) { +- SNDERR("error: invalid data file size %zu\n", size); ++ SNDERR("invalid data file size %zu", size); + ret = -EINVAL; + goto err; + } + if (size > TPLG_MAX_PRIV_SIZE) { +- SNDERR("error: data file too big %zu\n", size); ++ SNDERR("data file too big %zu", size); + ret = -EINVAL; + goto err; + } +@@ -350,7 +349,7 @@ static int get_uuid(const char *str, unsigned char *uuid_le) + if ((errno == ERANGE && val == ULONG_MAX) + || (errno != 0 && val == 0) + || (val > UCHAR_MAX)) { +- SNDERR("error: invalid value for uuid\n"); ++ SNDERR("invalid value for uuid"); + ret = -EINVAL; + goto out; + } +@@ -365,7 +364,7 @@ static int get_uuid(const char *str, unsigned char *uuid_le) + } + + if (values < 16) { +- SNDERR("error: less than 16 integers for uuid\n"); ++ SNDERR("less than 16 integers for uuid"); + ret = -EINVAL; + } + +@@ -446,7 +445,7 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, + + num = get_hex_num(value); + if (num <= 0) { +- SNDERR("error: malformed hex variable list %s\n", value); ++ SNDERR("malformed hex variable list %s", value); + return -EINVAL; + } + +@@ -454,7 +453,7 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, + priv = elem->data; + + if (size > TPLG_MAX_PRIV_SIZE) { +- SNDERR("error: data too big %d\n", size); ++ SNDERR("data too big %d", size); + return -EINVAL; + } + +@@ -492,7 +491,7 @@ static int get_token_value(const char *token_id, + return tokens->token[i].value; + } + +- SNDERR("error: cannot find token id '%s'\n", token_id); ++ SNDERR("cannot find token id '%s'", token_id); + return -1; + } + +@@ -579,7 +578,7 @@ static int copy_tuples(struct tplg_elem *elem, + * tuple_set->num_tuples; + size += set_size; + if (size > TPLG_MAX_PRIV_SIZE) { +- SNDERR("error: data too big %d\n", size); ++ SNDERR("data too big %d", size); + return -EINVAL; + } + +@@ -662,13 +661,13 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem) + ref->id, SND_TPLG_TYPE_TUPLE, elem->index); + tuples = ref->elem; + if (!tuples) { +- SNDERR("error: cannot find tuples %s\n", ref->id); ++ SNDERR("cannot find tuples %s", ref->id); + return -EINVAL; + } + + tokens = get_tokens(tplg, tuples); + if (!tokens) { +- SNDERR("error: cannot find token for %s\n", ref->id); ++ SNDERR("cannot find token for %s", ref->id); + return -EINVAL; + } + +@@ -762,7 +761,7 @@ static int parse_tuple_set(snd_config_t *cfg, + + type = get_tuple_type(id); + if (type < 0) { +- SNDERR("error: invalid tuple type '%s'", id); ++ SNDERR("invalid tuple type '%s'", id); + return type; + } + +@@ -819,7 +818,7 @@ static int parse_tuple_set(snd_config_t *cfg, + case SND_SOC_TPLG_TUPLE_TYPE_WORD: + ival = tplg_get_unsigned(n, &tuple_val, 0); + if (ival < 0) { +- SNDERR("error: tuple %s: %s\n", id, snd_strerror(ival)); ++ SNDERR("tuple %s: %s", id, snd_strerror(ival)); + goto err; + } + +@@ -829,7 +828,7 @@ static int parse_tuple_set(snd_config_t *cfg, + && tuple_val > USHRT_MAX) + || (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE + && tuple_val > UCHAR_MAX)) { +- SNDERR("error: tuple %s: invalid value\n", id); ++ SNDERR("tuple %s: invalid value", id); + goto err; + } + +@@ -941,7 +940,7 @@ static int parse_tuple_sets(snd_config_t *cfg, + + if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { + if (snd_config_get_id(cfg, &id) >= 0) +- SNDERR("error: compound type expected for %s", id); ++ SNDERR("compound type expected for %s", id); + return -EINVAL; + } + +@@ -959,8 +958,8 @@ static int parse_tuple_sets(snd_config_t *cfg, + snd_config_for_each(i, next, cfg) { + n = snd_config_iterator_entry(i); + if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound type expected for %s, is %d", +- id, snd_config_get_type(n)); ++ SNDERR("compound type expected for %s, is %d", ++ id, snd_config_get_type(n)); + return -EINVAL; + } + +@@ -1169,7 +1168,7 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, + int err; + + if (!list_empty(&tplg->manifest_list)) { +- SNDERR("error: already has manifest data\n"); ++ SNDERR("already has manifest data"); + return -EINVAL; + } + +@@ -1326,7 +1325,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + if (strcmp(id, "file") == 0) { + err = tplg_parse_data_file(n, elem); + if (err < 0) { +- SNDERR("error: failed to parse data file\n"); ++ SNDERR("failed to parse data file"); + return err; + } + continue; +@@ -1335,7 +1334,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + if (strcmp(id, "bytes") == 0) { + err = tplg_parse_data_hex(n, elem, 1); + if (err < 0) { +- SNDERR("error: failed to parse data bytes\n"); ++ SNDERR("failed to parse data bytes"); + return err; + } + continue; +@@ -1344,7 +1343,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + if (strcmp(id, "shorts") == 0) { + err = tplg_parse_data_hex(n, elem, 2); + if (err < 0) { +- SNDERR("error: failed to parse data shorts\n"); ++ SNDERR("failed to parse data shorts"); + return err; + } + continue; +@@ -1353,7 +1352,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + if (strcmp(id, "words") == 0) { + err = tplg_parse_data_hex(n, elem, 4); + if (err < 0) { +- SNDERR("error: failed to parse data words\n"); ++ SNDERR("failed to parse data words"); + return err; + } + continue; +@@ -1470,8 +1469,8 @@ int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem, + ref_elem = tplg_elem_lookup(&tplg->pdata_list, + ref->id, SND_TPLG_TYPE_DATA, elem->index); + if (!ref_elem) { +- SNDERR("error: cannot find data '%s' referenced by" +- " element '%s'\n", ref->id, elem->id); ++ SNDERR("cannot find data '%s' referenced by" ++ " element '%s'", ref->id, elem->id); + return -EINVAL; + } + +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 1eaa24bd..5a5dd14f 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -122,7 +122,7 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, + return -EINVAL; + + if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound type expected for %s", id); ++ SNDERR("compound type expected for %s", id); + return -EINVAL; + } + +@@ -131,7 +131,7 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, + n = snd_config_iterator_entry(i); + + if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound type expected for %s, is %d", ++ SNDERR("compound type expected for %s, is %d", + id, snd_config_get_type(cfg)); + return -EINVAL; + } +@@ -155,7 +155,7 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + int err; + + if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { +- SNDERR("error: compound type expected at top level"); ++ SNDERR("compound type expected at top level"); + return -EINVAL; + } + +@@ -180,7 +180,7 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) + } + + if (parser == NULL) { +- SNDERR("error: unknown section %s\n", id); ++ SNDERR("unknown section %s", id); + continue; + } + +@@ -202,7 +202,7 @@ static int tplg_load_config(snd_tplg_t *tplg, snd_input_t *in) + + ret = snd_config_load(top, in); + if (ret < 0) { +- SNDERR("error: could not load configuration"); ++ SNDERR("could not load configuration"); + snd_config_delete(top); + return ret; + } +@@ -210,7 +210,7 @@ static int tplg_load_config(snd_tplg_t *tplg, snd_input_t *in) + ret = tplg_parse_config(tplg, top); + snd_config_delete(top); + if (ret < 0) { +- SNDERR("error: failed to parse topology"); ++ SNDERR("failed to parse topology"); + return ret; + } + +@@ -267,7 +267,7 @@ int snd_tplg_load(snd_tplg_t *tplg, const char *buf, size_t size) + + err = snd_input_buffer_open(&in, buf, size); + if (err < 0) { +- SNDERR("error: could not create input buffer"); ++ SNDERR("could not create input buffer"); + return err; + } + +@@ -282,13 +282,13 @@ static int tplg_build(snd_tplg_t *tplg) + + err = tplg_build_integ(tplg); + if (err < 0) { +- SNDERR("error: failed to check topology integrity\n"); ++ SNDERR("failed to check topology integrity"); + return err; + } + + err = tplg_write_data(tplg); + if (err < 0) { +- SNDERR("error: failed to write data %d\n", err); ++ SNDERR("failed to write data %d", err); + return err; + } + return 0; +@@ -304,15 +304,14 @@ int snd_tplg_build_file(snd_tplg_t *tplg, + + fp = fopen(infile, "r"); + if (fp == NULL) { +- SNDERR("error: could not open configuration file %s", +- infile); ++ SNDERR("could not open configuration file %s", infile); + return -errno; + } + + err = snd_input_stdio_attach(&in, fp, 1); + if (err < 0) { + fclose(fp); +- SNDERR("error: could not attach stdio %s", infile); ++ SNDERR("could not attach stdio %s", infile); + return err; + } + +@@ -346,7 +345,7 @@ int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + case SND_TPLG_TYPE_CC: + return tplg_add_link_object(tplg, t); + default: +- SNDERR("error: invalid object type %d\n", t->type); ++ SNDERR("invalid object type %d", t->type); + return -EINVAL; + }; + } +@@ -362,18 +361,18 @@ int snd_tplg_build(snd_tplg_t *tplg, const char *outfile) + + fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd < 0) { +- SNDERR("error: failed to open %s err %d\n", outfile, -errno); ++ SNDERR("failed to open %s err %d", outfile, -errno); + return -errno; + } + r = write(fd, tplg->bin, tplg->bin_size); + close(fd); + if (r < 0) { + err = -errno; +- SNDERR("error: write error: %s\n", strerror(errno)); ++ SNDERR("write error: %s", strerror(errno)); + return err; + } + if ((size_t)r != tplg->bin_size) { +- SNDERR("error: partial write (%zd != %zd)\n", r, tplg->bin_size); ++ SNDERR("partial write (%zd != %zd)", r, tplg->bin_size); + return -EIO; + } + return 0; +@@ -437,7 +436,7 @@ snd_tplg_t *snd_tplg_create(int flags) + snd_tplg_t *tplg; + + if (!is_little_endian()) { +- SNDERR("error: cannot support big-endian machines\n"); ++ SNDERR("cannot support big-endian machines"); + return NULL; + } + +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index d09fbe42..bc307081 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -116,8 +116,8 @@ static int build_pcm(snd_tplg_t *tplg, struct tplg_elem *elem) + return err; + } + if (!ref->elem) { +- SNDERR("error: cannot find '%s' referenced by" +- " PCM '%s'\n", ref->id, elem->id); ++ SNDERR("cannot find '%s' referenced by" ++ " PCM '%s'", ref->id, elem->id); + return -EINVAL; + } + } +@@ -137,7 +137,7 @@ int tplg_build_pcms(snd_tplg_t *tplg, unsigned int type) + + elem = list_entry(pos, struct tplg_elem, list); + if (elem->type != type) { +- SNDERR("error: invalid elem '%s'\n", elem->id); ++ SNDERR("invalid elem '%s'", elem->id); + return -EINVAL; + } + +@@ -196,7 +196,7 @@ int tplg_build_dais(snd_tplg_t *tplg, unsigned int type) + + elem = list_entry(pos, struct tplg_elem, list); + if (elem->type != type) { +- SNDERR("error: invalid elem '%s'\n", elem->id); ++ SNDERR("invalid elem '%s'", elem->id); + return -EINVAL; + } + +@@ -251,8 +251,8 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem) + ref->elem = tplg_elem_lookup(&tplg->hw_cfg_list, + ref->id, SND_TPLG_TYPE_HW_CONFIG, elem->index); + if (!ref->elem) { +- SNDERR("error: cannot find HW config '%s'" +- " referenced by link '%s'\n", ++ SNDERR("cannot find HW config '%s'" ++ " referenced by link '%s'", + ref->id, elem->id); + return -EINVAL; + } +@@ -320,7 +320,7 @@ static int split_format(struct snd_soc_tplg_stream_caps *caps, char *str) + while ((s != NULL) && (i < SND_SOC_TPLG_MAX_FORMATS)) { + format = snd_pcm_format_value(s); + if (format == SND_PCM_FORMAT_UNKNOWN) { +- SNDERR("error: unsupported stream format %s\n", s); ++ SNDERR("unsupported stream format %s", s); + return -EINVAL; + } + +@@ -363,7 +363,7 @@ static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str) + rate = get_rate_value(s); + + if (rate == SND_PCM_RATE_UNKNOWN) { +- SNDERR("error: unsupported stream rate %s\n", s); ++ SNDERR("unsupported stream rate %s", s); + return -EINVAL; + } + +@@ -758,7 +758,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + + if (strcmp(id, "id") == 0) { + if (tplg_get_unsigned(n, &pcm->dai_id, 0)) { +- SNDERR("error: invalid fe dai ID\n"); ++ SNDERR("invalid fe dai ID"); + return -EINVAL; + } + +@@ -1379,7 +1379,7 @@ static int get_audio_hw_format(const char *val) + if (strcasecmp(audio_hw_formats[i].name, val) == 0) + return audio_hw_formats[i].type; + +- SNDERR("error: invalid audio HW format %s\n", val); ++ SNDERR("invalid audio HW format %s", val); + return -EINVAL; + } + +@@ -1452,8 +1452,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + /* For backwards capability, + * "master" == "codec is slave" + */ +- SNDERR("warning: deprecated bclk value '%s'\n", +- val); ++ SNDERR("deprecated bclk value '%s'", val); + + hw_cfg->bclk_master = SND_SOC_TPLG_BCLK_CS; + } else if (!strcmp(val, "codec_slave")) { +@@ -1490,8 +1489,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + /* For backwards capability, + * "master" == "codec is slave" + */ +- SNDERR("warning: deprecated fsync value '%s'\n", +- val); ++ SNDERR("deprecated fsync value '%s'", val); + + hw_cfg->fsync_master = SND_SOC_TPLG_FSYNC_CS; + } else if (!strcmp(val, "codec_slave")) { +@@ -1535,8 +1533,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + /* For backwards capability, + * "master" == "for codec, mclk is input" + */ +- SNDERR("warning: deprecated mclk value '%s'\n", +- val); ++ SNDERR("deprecated mclk value '%s'", val); + + hw_cfg->mclk_direction = SND_SOC_TPLG_MCLK_CI; + } else if (!strcmp(val, "codec_mclk_in")) { +diff --git a/src/topology/text.c b/src/topology/text.c +index e9386e7d..6dbf2230 100644 +--- a/src/topology/text.c ++++ b/src/topology/text.c +@@ -38,7 +38,7 @@ static int parse_text_values(snd_config_t *cfg, struct tplg_elem *elem) + n = snd_config_iterator_entry(i); + + if (j == SND_SOC_TPLG_NUM_TEXTS) { +- tplg_dbg("error: text string number exceeds %d\n", j); ++ tplg_dbg("text string number exceeds %d\n", j); + return -ENOMEM; + } + +-- +2.24.1 + + +From 712fbacf160f899582a9adc3f30f297211b063bb Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 27 Dec 2019 19:32:03 +0100 +Subject: [PATCH 47/69] topology: dapm - fix the SNDERR() - Undefined + +Signed-off-by: Jaroslav Kysela +--- + src/topology/dapm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index f61fe071..88bddca3 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -230,7 +230,7 @@ int tplg_build_routes(snd_tplg_t *tplg) + SND_TPLG_TYPE_MIXER, elem->index) && + !tplg_elem_lookup(&tplg->enum_list, route->control, + SND_TPLG_TYPE_ENUM, elem->index)) { +- SNDERR("Undefined mixer/enum control '%s'", ++ SNDERR("undefined mixer/enum control '%s'", + route->control); + } + } +@@ -243,7 +243,7 @@ int tplg_build_routes(snd_tplg_t *tplg) + } + if (!tplg_elem_lookup(&tplg->widget_list, route->source, + SND_TPLG_TYPE_DAPM_WIDGET, SND_TPLG_INDEX_ALL)) { +- SNDERR("Undefined source widget/stream '%s'", ++ SNDERR("undefined source widget/stream '%s'", + route->source); + } + +-- +2.24.1 + + +From 07d779143bfd24448034cd55945b46c46407247c Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 28 Dec 2019 10:18:34 +0100 +Subject: [PATCH 48/69] topology: fix the unitialized tuples + +Signed-off-by: Jaroslav Kysela +--- + src/topology/data.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/topology/data.c b/src/topology/data.c +index f00ed301..4e43fcc9 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -601,6 +601,7 @@ static int copy_tuples(struct tplg_elem *elem, + elem->data = priv; + + array = (struct snd_soc_tplg_vendor_array *)(priv->data + off); ++ memset(array, 0, set_size); + array->size = set_size; + array->type = tuple_set->type; + array->num_elems = tuple_set->num_tuples; +-- +2.24.1 + + +From 2947d83c1322bcdb31c1da180acb0f779a63dcdd Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 28 Dec 2019 21:44:03 +0100 +Subject: [PATCH 49/69] topology: implement shorter hexa uuid 00:00 parser + +Signed-off-by: Jaroslav Kysela +--- + src/topology/data.c | 37 +++++++++++++++++++++++++++++++------ + 1 file changed, 31 insertions(+), 6 deletions(-) + +diff --git a/src/topology/data.c b/src/topology/data.c +index 4e43fcc9..1ddd3c50 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -22,8 +22,8 @@ + #include + + #define UUID_FORMAT "\ +-0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, \ +-0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x" ++%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:\ ++%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" + + /* Get private data buffer of an element */ + struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem) +@@ -316,7 +316,6 @@ format2: + values++; + s += 2; + } +- s++; + } + + s++; +@@ -341,6 +340,32 @@ static int get_uuid(const char *str, unsigned char *uuid_le) + if (tmp == NULL) + return -ENOMEM; + ++ if (strchr(tmp, ':') == NULL) ++ goto data2; ++ ++ s = strtok(tmp, ":"); ++ while (s != NULL) { ++ errno = 0; ++ val = strtoul(s, NULL, 16); ++ if ((errno == ERANGE && val == ULONG_MAX) ++ || (errno != 0 && val == 0) ++ || (val > UCHAR_MAX)) { ++ SNDERR("invalid value for uuid"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ *(uuid_le + values) = (unsigned char)val; ++ ++ values++; ++ if (values >= 16) ++ break; ++ ++ s = strtok(NULL, ":"); ++ } ++ goto out; ++ ++data2: + s = strtok(tmp, ","); + + while (s != NULL) { +@@ -354,7 +379,7 @@ static int get_uuid(const char *str, unsigned char *uuid_le) + goto out; + } + +- *(uuid_le + values) = (unsigned char)val; ++ *(uuid_le + values) = (unsigned char)val; + + values++; + if (values >= 16) +@@ -413,7 +438,7 @@ static int copy_data_hex(char *data, int off, const char *str, int width) + return -ENOMEM; + + p += off; +- s = strtok(tmp, ","); ++ s = strtok(tmp, ",:"); + + while (s != NULL) { + ret = write_hex(p, s, width); +@@ -422,7 +447,7 @@ static int copy_data_hex(char *data, int off, const char *str, int width) + return ret; + } + +- s = strtok(NULL, ","); ++ s = strtok(NULL, ",:"); + p += width; + } + +-- +2.24.1 + + +From 1482d1f254fe42d83d904e52c911df8693b62653 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 29 Dec 2019 20:05:14 +0100 +Subject: [PATCH 50/69] topology: fix the TPLG_DEBUG compilation + +Signed-off-by: Jaroslav Kysela +--- + src/topology/channel.c | 2 +- + src/topology/data.c | 5 ++++- + src/topology/pcm.c | 2 +- + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/src/topology/channel.c b/src/topology/channel.c +index 110775a8..390c3f16 100644 +--- a/src/topology/channel.c ++++ b/src/topology/channel.c +@@ -129,7 +129,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + else if (strcmp(id, "shift") == 0) + channel->shift = value; + +- tplg_dbg("\t\t%s = %s\n", id, value); ++ tplg_dbg("\t\t%s = %d\n", id, value); + } + + tplg->channel_idx++; +diff --git a/src/topology/data.c b/src/topology/data.c +index 1ddd3c50..7b4bdccd 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -230,9 +230,11 @@ err: + return ret; + } + +-static void dump_priv_data(struct tplg_elem *elem) ++static void dump_priv_data(struct tplg_elem *elem ATTRIBUTE_UNUSED) + { ++#ifdef TPLG_DEBUG + struct snd_soc_tplg_private *priv = elem->data; ++ unsigned char *p = (unsigned char *)priv->data; + unsigned int i; + + tplg_dbg(" elem size = %d, priv data size = %d\n", +@@ -246,6 +248,7 @@ static void dump_priv_data(struct tplg_elem *elem) + } + + tplg_dbg("\n\n"); ++#endif + } + + static inline int check_nibble(unsigned char c) +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index bc307081..8e5afbe6 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -881,7 +881,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, + + pcm->compress = ival; + +- tplg_dbg("\t%s: %s\n", id, val); ++ tplg_dbg("\t%s: %d\n", id, ival); + continue; + } + +-- +2.24.1 + + +From c765615bce7903a0f3e3d5e7826483708398c184 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 31 Dec 2019 15:27:58 +0100 +Subject: [PATCH 51/69] topology: fix the ops parser (accept integer/hexa + values) + +Signed-off-by: Jaroslav Kysela +--- + src/topology/ops.c | 36 +++++++++++++++++++++++++----------- + 1 file changed, 25 insertions(+), 11 deletions(-) + +diff --git a/src/topology/ops.c b/src/topology/ops.c +index ad72ef1b..2885c781 100644 +--- a/src/topology/ops.c ++++ b/src/topology/ops.c +@@ -67,6 +67,7 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg, + snd_config_t *n; + struct snd_soc_tplg_ctl_hdr *hdr = private; + const char *id, *value; ++ int ival; + + tplg_dbg("\tOps\n"); + hdr->size = sizeof(*hdr); +@@ -80,17 +81,23 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg, + continue; + + /* get value - try strings then ints */ +- if (snd_config_get_string(n, &value) < 0) +- continue; ++ if (snd_config_get_type(n) == SND_CONFIG_TYPE_STRING) { ++ if (snd_config_get_string(n, &value) < 0) ++ continue; ++ ival = lookup_ops(value); ++ } else { ++ if (tplg_get_integer(n, &ival, 0)) ++ continue; ++ } + + if (strcmp(id, "info") == 0) +- hdr->ops.info = lookup_ops(value); ++ hdr->ops.info = ival; + else if (strcmp(id, "put") == 0) +- hdr->ops.put = lookup_ops(value); ++ hdr->ops.put = ival; + else if (strcmp(id, "get") == 0) +- hdr->ops.get = lookup_ops(value); ++ hdr->ops.get = ival; + +- tplg_dbg("\t\t%s = %s\n", id, value); ++ tplg_dbg("\t\t%s = %d\n", id, ival); + } + + return 0; +@@ -146,6 +153,7 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_config_t *n; + struct snd_soc_tplg_bytes_control *be = private; + const char *id, *value; ++ int ival; + + tplg_dbg("\tExt Ops\n"); + +@@ -158,15 +166,21 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + continue; + + /* get value - try strings then ints */ +- if (snd_config_get_string(n, &value) < 0) +- continue; ++ if (snd_config_get_type(n) == SND_CONFIG_TYPE_STRING) { ++ if (snd_config_get_string(n, &value) < 0) ++ continue; ++ ival = lookup_ops(value); ++ } else { ++ if (tplg_get_integer(n, &ival, 0)) ++ continue; ++ } + + if (strcmp(id, "info") == 0) +- be->ext_ops.info = lookup_ops(value); ++ be->ext_ops.info = ival; + else if (strcmp(id, "put") == 0) +- be->ext_ops.put = lookup_ops(value); ++ be->ext_ops.put = ival; + else if (strcmp(id, "get") == 0) +- be->ext_ops.get = lookup_ops(value); ++ be->ext_ops.get = ival; + + tplg_dbg("\t\t%s = %s\n", id, value); + } +-- +2.24.1 + + +From 0ba4d6d9c0ae4576f35724d2a5735990f09ceeb0 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 1 Jan 2020 19:10:20 +0100 +Subject: [PATCH 52/69] topology: fix the wrong memory access (object realloc) + +Signed-off-by: Jaroslav Kysela +--- + src/topology/pcm.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 8e5afbe6..bd728959 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -252,8 +252,8 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem) + ref->id, SND_TPLG_TYPE_HW_CONFIG, elem->index); + if (!ref->elem) { + SNDERR("cannot find HW config '%s'" +- " referenced by link '%s'", +- ref->id, elem->id); ++ " referenced by link '%s'", ++ ref->id, elem->id); + return -EINVAL; + } + +@@ -267,6 +267,7 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem) + err = tplg_copy_data(tplg, elem, ref); + if (err < 0) + return err; ++ link = elem->link; /* realloc */ + break; + + default: +-- +2.24.1 + + +From b6c9afb4f59bb678dc834028680d579f47dc273b Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 15 Dec 2019 15:24:57 +0100 +Subject: [PATCH 53/69] topology: implement snd_tplg_decode + +Signed-off-by: Jaroslav Kysela +--- + include/topology.h | 14 +- + src/topology/Makefile.am | 3 +- + src/topology/ctl.c | 450 +++++++++++++++++++++++++++++++++----- + src/topology/dapm.c | 253 +++++++++++++++++++-- + src/topology/data.c | 440 ++++++++++++++++++++++++++++++++++++- + src/topology/decoder.c | 136 ++++++++++++ + src/topology/elem.c | 80 +++++++ + src/topology/parser.c | 20 +- + src/topology/pcm.c | 396 ++++++++++++++++++++++++++++----- + src/topology/save.c | 3 + + src/topology/tplg_local.h | 71 +++++- + 11 files changed, 1727 insertions(+), 139 deletions(-) + create mode 100644 src/topology/decoder.c + +diff --git a/include/topology.h b/include/topology.h +index 37bced1a..1f52e66e 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -885,7 +885,10 @@ struct snd_tplg_ctl_template { + const char *name; /*!< Control name */ + int access; /*!< Control access */ + struct snd_tplg_io_ops_template ops; /*!< operations */ +- struct snd_tplg_tlv_template *tlv; /*!< non NULL means we have TLV data */ ++ union { ++ struct snd_tplg_tlv_template *tlv; /*!< non NULL means we have TLV data */ ++ struct snd_tplg_tlv_dbscale_template *tlv_scale; /*!< scale TLV data */ ++ }; + }; + + /** \struct snd_tplg_mixer_template +@@ -1155,6 +1158,15 @@ int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version); + */ + int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags); + ++/** ++ * \brief Decode the binary topology contents. ++ * \param tplg Topology instance. ++ * \param bin Binary topology input buffer. ++ * \param size Binary topology input buffer size. ++ * \return Zero on success, otherwise a negative error code ++ */ ++int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags); ++ + /* \} */ + + #ifdef __cplusplus +diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am +index a850ec4c..12d1d445 100644 +--- a/src/topology/Makefile.am ++++ b/src/topology/Makefile.am +@@ -28,7 +28,8 @@ libatopology_la_SOURCES =\ + channel.c \ + ops.c \ + elem.c \ +- save.c ++ save.c \ ++ decoder.c + + noinst_HEADERS = tplg_local.h + +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index 03874b27..24d437aa 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -621,8 +621,9 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, + tplg->channel_idx = 0; + + /* set channel reg to default state */ +- for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++) ++ for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++) { + ec->channel[j].reg = -1; ++ } + + tplg_dbg(" Control Enum: %s\n", elem->id); + +@@ -896,9 +897,14 @@ int tplg_save_control_mixer(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + return err; + } + +-static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr, +- struct snd_tplg_ctl_template *t) ++static int init_ctl_hdr(snd_tplg_t *tplg, ++ struct tplg_elem *parent, ++ struct snd_soc_tplg_ctl_hdr *hdr, ++ struct snd_tplg_ctl_template *t) + { ++ struct tplg_elem *elem; ++ int err; ++ + hdr->size = sizeof(struct snd_soc_tplg_ctl_hdr); + hdr->type = t->type; + +@@ -924,7 +930,7 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr, + && !(hdr->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) { + + struct snd_tplg_tlv_template *tlvt = t->tlv; +- struct snd_soc_tplg_ctl_tlv *tlv = &hdr->tlv; ++ struct snd_soc_tplg_ctl_tlv *tlv; + struct snd_tplg_tlv_dbscale_template *scalet; + struct snd_soc_tplg_tlv_dbscale *scale; + +@@ -933,6 +939,17 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr, + return -EINVAL; + } + ++ elem = tplg_elem_new_common(tplg, NULL, parent->id, ++ SND_TPLG_TYPE_TLV); ++ if (!elem) ++ return -ENOMEM; ++ ++ tlv = elem->tlv; ++ ++ err = tplg_ref_add(parent, SND_TPLG_TYPE_TLV, parent->id); ++ if (err < 0) ++ return err; ++ + tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv); + tlv->type = tlvt->type; + +@@ -957,10 +974,10 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr, + } + + int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer, +- struct tplg_elem **e) ++ struct tplg_elem **e) + { +- struct snd_soc_tplg_private *priv = mixer->priv; + struct snd_soc_tplg_mixer_control *mc; ++ struct snd_soc_tplg_private *priv; + struct tplg_elem *elem; + int ret, i, num_channels; + +@@ -979,7 +996,7 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer, + /* init new mixer */ + mc = elem->mixer_ctrl; + mc->size = elem->size; +- ret = init_ctl_hdr(&mc->hdr, &mixer->hdr); ++ ret = init_ctl_hdr(tplg, elem, &mc->hdr, &mixer->hdr); + if (ret < 0) { + tplg_elem_free(elem); + return ret; +@@ -1000,25 +1017,20 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer, + for (i = 0; i < num_channels; i++) { + struct snd_tplg_channel_elem *channel = &mixer->map->channel[i]; + +- mc->channel[i].size = channel->size; ++ mc->channel[i].size = sizeof(mc->channel[0]); + mc->channel[i].reg = channel->reg; + mc->channel[i].shift = channel->shift; + mc->channel[i].id = channel->id; + } + + /* priv data */ +- if (priv) { +- mc = realloc(mc, elem->size + priv->size); +- if (!mc) { +- tplg_elem_free(elem); +- return -ENOMEM; +- } +- +- elem->mixer_ctrl = mc; +- elem->size += priv->size; +- mc->priv.size = priv->size; +- memcpy(mc->priv.data, priv->data, priv->size); +- } ++ priv = mixer->priv; ++ if (priv && priv->size > 0) { ++ ret = tplg_add_data(tplg, elem, priv, ++ sizeof(*priv) + priv->size); ++ if (ret < 0) ++ return ret; ++ } + + if (e) + *e = elem; +@@ -1026,11 +1038,12 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer, + } + + int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, +- struct tplg_elem **e) ++ struct tplg_elem **e) + { + struct snd_soc_tplg_enum_control *ec; ++ struct snd_soc_tplg_private *priv; + struct tplg_elem *elem; +- int ret, i, num_items; ++ int ret, i, num_items, num_channels; + + tplg_dbg(" Control Enum: %s\n", enum_ctl->hdr.name); + +@@ -1046,7 +1059,7 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, + + ec = elem->enum_ctrl; + ec->size = elem->size; +- ret = init_ctl_hdr(&ec->hdr, &enum_ctl->hdr); ++ ret = init_ctl_hdr(tplg, elem, &ec->hdr, &enum_ctl->hdr); + if (ret < 0) { + tplg_elem_free(elem); + return ret; +@@ -1058,6 +1071,22 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, + ec->mask = enum_ctl->mask; + ec->count = enum_ctl->items; + ++ /* set channel reg to default state */ ++ for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) ++ ec->channel[i].reg = -1; ++ ++ num_channels = enum_ctl->map ? enum_ctl->map->num_channels : 0; ++ ec->num_channels = num_channels; ++ ++ for (i = 0; i < num_channels; i++) { ++ struct snd_tplg_channel_elem *channel = &enum_ctl->map->channel[i]; ++ ++ ec->channel[i].size = sizeof(ec->channel[0]); ++ ec->channel[i].reg = channel->reg; ++ ec->channel[i].shift = channel->shift; ++ ec->channel[i].id = channel->id; ++ } ++ + if (enum_ctl->texts != NULL) { + for (i = 0; i < num_items; i++) { + if (enum_ctl->texts[i] != NULL) +@@ -1077,21 +1106,13 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, + } + } + +- if (enum_ctl->priv != NULL) { +- ec = realloc(ec, +- elem->size + enum_ctl->priv->size); +- if (!ec) { +- tplg_elem_free(elem); +- return -ENOMEM; +- } +- +- elem->enum_ctrl = ec; +- elem->size += enum_ctl->priv->size; +- +- memcpy(ec->priv.data, enum_ctl->priv->data, +- enum_ctl->priv->size); +- +- ec->priv.size = enum_ctl->priv->size; ++ /* priv data */ ++ priv = enum_ctl->priv; ++ if (priv && priv->size > 0) { ++ ret = tplg_add_data(tplg, elem, priv, ++ sizeof(*priv) + priv->size); ++ if (ret < 0) ++ return ret; + } + + if (e) +@@ -1100,9 +1121,10 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, + } + + int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl, +- struct tplg_elem **e) ++ struct tplg_elem **e) + { + struct snd_soc_tplg_bytes_control *be; ++ struct snd_soc_tplg_private *priv; + struct tplg_elem *elem; + int ret; + +@@ -1120,7 +1142,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl, + + be = elem->bytes_ext; + be->size = elem->size; +- ret = init_ctl_hdr(&be->hdr, &bytes_ctl->hdr); ++ ret = init_ctl_hdr(tplg, elem, &be->hdr, &bytes_ctl->hdr); + if (ret < 0) { + tplg_elem_free(elem); + return ret; +@@ -1133,20 +1155,13 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl, + be->ext_ops.put = bytes_ctl->ext_ops.put; + be->ext_ops.get = bytes_ctl->ext_ops.get; + +- if (bytes_ctl->priv != NULL) { +- be = realloc(be, +- elem->size + bytes_ctl->priv->size); +- if (!be) { +- tplg_elem_free(elem); +- return -ENOMEM; +- } +- elem->bytes_ext = be; +- elem->size += bytes_ctl->priv->size; +- +- memcpy(be->priv.data, bytes_ctl->priv->data, +- bytes_ctl->priv->size); +- +- be->priv.size = bytes_ctl->priv->size; ++ /* priv data */ ++ priv = bytes_ctl->priv; ++ if (priv && priv->size > 0) { ++ ret = tplg_add_data(tplg, elem, priv, ++ sizeof(*priv) + priv->size); ++ if (ret < 0) ++ return ret; + } + + /* check on TLV bytes control */ +@@ -1184,3 +1199,330 @@ int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + { + return tplg_add_bytes(tplg, t->bytes_ctl, NULL); + } ++ ++int tplg_decode_control_mixer1(snd_tplg_t *tplg, ++ struct list_head *heap, ++ struct snd_tplg_mixer_template *mt, ++ size_t pos, ++ void *bin, size_t size) ++{ ++ struct snd_soc_tplg_mixer_control *mc = bin; ++ struct snd_tplg_channel_map_template *map; ++ struct snd_tplg_tlv_dbscale_template *db; ++ int i; ++ ++ if (size < sizeof(*mc)) { ++ SNDERR("mixer: small size %d", size); ++ return -EINVAL; ++ } ++ ++ tplg_dv(tplg, pos, "mixer: size %d TLV size %d private size %d", ++ mc->size, mc->hdr.tlv.size, mc->priv.size); ++ if (size != mc->size + mc->priv.size) { ++ SNDERR("mixer: unexpected element size %d", size); ++ return -EINVAL; ++ } ++ ++ memset(mt, 0, sizeof(*mt)); ++ mt->hdr.type = mc->hdr.type; ++ mt->hdr.name = mc->hdr.name; ++ mt->hdr.access = mc->hdr.access; ++ mt->hdr.ops.get = mc->hdr.ops.get; ++ mt->hdr.ops.put = mc->hdr.ops.put; ++ mt->hdr.ops.info = mc->hdr.ops.info; ++ mt->min = mc->min; ++ mt->max = mc->max; ++ mt->platform_max = mc->platform_max; ++ tplg_dv(tplg, pos, "mixer: name '%s' access 0x%x", ++ mt->hdr.name, mt->hdr.access); ++ if (mc->num_channels > 0) { ++ map = tplg_calloc(heap, sizeof(*map)); ++ map->num_channels = mc->num_channels; ++ for (i = 0; i < map->num_channels; i++) { ++ map->channel[i].reg = mc->channel[i].reg; ++ map->channel[i].shift = mc->channel[i].shift; ++ map->channel[i].id = mc->channel[i].id; ++ } ++ mt->map = map; ++ } ++ if (mc->hdr.tlv.size == 0) { ++ /* nothing */ ++ } else if (mc->hdr.tlv.size == sizeof(struct snd_soc_tplg_ctl_tlv)) { ++ if (mc->hdr.tlv.type != SNDRV_CTL_TLVT_DB_SCALE) { ++ SNDERR("mixer: unknown TLV type %d", ++ mc->hdr.tlv.type); ++ return -EINVAL; ++ } ++ db = tplg_calloc(heap, sizeof(*db)); ++ if (db == NULL) ++ return -ENOMEM; ++ mt->hdr.tlv_scale = db; ++ db->hdr.type = mc->hdr.tlv.type; ++ db->min = mc->hdr.tlv.scale.min; ++ db->step = mc->hdr.tlv.scale.step; ++ db->mute = mc->hdr.tlv.scale.mute; ++ tplg_dv(tplg, pos, "mixer: dB scale TLV: min %d step %d mute %d", ++ db->min, db->step, db->mute); ++ } else { ++ SNDERR("mixer: wrong TLV size %d", mc->hdr.tlv.size); ++ return -EINVAL; ++ } ++ ++ mt->priv = &mc->priv; ++ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_mixer_control, priv), ++ "mixer: private start"); ++ return 0; ++} ++ ++int tplg_decode_control_mixer(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ struct list_head heap; ++ snd_tplg_obj_template_t t; ++ struct snd_tplg_mixer_template mt; ++ struct snd_soc_tplg_mixer_control *mc; ++ size_t size2; ++ int err; ++ ++ err = tplg_decode_template(tplg, pos, hdr, &t); ++ if (err < 0) ++ return err; ++ ++next: ++ if (size < sizeof(*mc)) { ++ SNDERR("mixer: small size %d", size); ++ return -EINVAL; ++ } ++ INIT_LIST_HEAD(&heap); ++ mc = bin; ++ size2 = mc->size + mc->priv.size; ++ if (size2 > size) { ++ SNDERR("mixer: wrong element size (%d, priv %d)", ++ mc->size, mc->priv.size); ++ return -EINVAL; ++ } ++ ++ err = tplg_decode_control_mixer1(tplg, &heap, &mt, pos, bin, size2); ++ if (err >= 0) { ++ t.mixer = &mt; ++ err = snd_tplg_add_object(tplg, &t); ++ } ++ tplg_free(&heap); ++ if (err < 0) ++ return err; ++ ++ bin += size2; ++ size -= size2; ++ pos += size2; ++ ++ if (size > 0) ++ goto next; ++ ++ return 0; ++} ++ ++int tplg_decode_control_enum1(snd_tplg_t *tplg, ++ struct list_head *heap, ++ struct snd_tplg_enum_template *et, ++ size_t pos, ++ void *bin, size_t size) ++{ ++ struct snd_soc_tplg_enum_control *ec = bin; ++ struct snd_tplg_channel_map_template cmt; ++ int i; ++ ++ if (size < sizeof(*ec)) { ++ SNDERR("enum: small size %d", size); ++ return -EINVAL; ++ } ++ ++ tplg_dv(tplg, pos, "enum: size %d private size %d", ++ ec->size, ec->priv.size); ++ if (size != ec->size + ec->priv.size) { ++ SNDERR("enum: unexpected element size %d", size); ++ return -EINVAL; ++ } ++ if (ec->num_channels > SND_TPLG_MAX_CHAN || ++ ec->num_channels > SND_SOC_TPLG_MAX_CHAN) { ++ SNDERR("enum: unexpected channel count %d", ec->num_channels); ++ return -EINVAL; ++ } ++ if (ec->items > SND_SOC_TPLG_NUM_TEXTS) { ++ SNDERR("enum: unexpected texts count %d", ec->items); ++ return -EINVAL; ++ } ++ ++ memset(et, 0, sizeof(*et)); ++ et->hdr.type = ec->hdr.type; ++ et->hdr.name = ec->hdr.name; ++ et->hdr.access = ec->hdr.access; ++ et->hdr.ops.get = ec->hdr.ops.get; ++ et->hdr.ops.put = ec->hdr.ops.put; ++ et->hdr.ops.info = ec->hdr.ops.info; ++ et->mask = ec->mask; ++ ++ if (ec->items > 0) { ++ et->items = ec->items; ++ et->texts = tplg_calloc(heap, sizeof(char *) * ec->items); ++ if (!et->texts) ++ return -ENOMEM; ++ for (i = 0; ec->items; i++) { ++ unsigned int j = i * sizeof(int) * ENUM_VAL_SIZE; ++ et->texts[i] = ec->texts[i]; ++ et->values[i] = (int *)&ec->values[j]; ++ } ++ } ++ ++ et->map = &cmt; ++ memset(&cmt, 0, sizeof(cmt)); ++ cmt.num_channels = ec->num_channels; ++ for (i = 0; i < cmt.num_channels; i++) { ++ struct snd_tplg_channel_elem *channel = &cmt.channel[i]; ++ tplg_dv(tplg, pos + ((void *)&ec->channel[i] - (void *)ec), ++ "enum: channel size %d", ec->channel[i].size); ++ channel->reg = ec->channel[i].reg; ++ channel->shift = ec->channel[i].shift; ++ channel->id = ec->channel[i].id; ++ } ++ ++ et->priv = &ec->priv; ++ return 0; ++} ++ ++int tplg_decode_control_enum(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ struct list_head heap; ++ snd_tplg_obj_template_t t; ++ struct snd_tplg_enum_template et; ++ struct snd_soc_tplg_enum_control *ec; ++ size_t size2; ++ int err; ++ ++ err = tplg_decode_template(tplg, pos, hdr, &t); ++ if (err < 0) ++ return err; ++ ++next: ++ if (size < sizeof(*ec)) { ++ SNDERR("enum: small size %d", size); ++ return -EINVAL; ++ } ++ INIT_LIST_HEAD(&heap); ++ ec = bin; ++ size2 = ec->size + ec->priv.size; ++ if (size2 > size) { ++ SNDERR("enum: wrong element size (%d, priv %d)", ++ ec->size, ec->priv.size); ++ return -EINVAL; ++ } ++ ++ err = tplg_decode_control_enum1(tplg, &heap, &et, pos, bin, size); ++ if (err >= 0) { ++ t.enum_ctl = &et; ++ err = snd_tplg_add_object(tplg, &t); ++ } ++ tplg_free(&heap); ++ if (err < 0) ++ return err; ++ ++ bin += size2; ++ size -= size2; ++ pos += size2; ++ ++ if (size > 0) ++ goto next; ++ ++ return 0; ++} ++ ++int tplg_decode_control_bytes1(snd_tplg_t *tplg, ++ struct snd_tplg_bytes_template *bt, ++ size_t pos, ++ void *bin, size_t size) ++{ ++ struct snd_soc_tplg_bytes_control *bc = bin; ++ ++ if (size < sizeof(*bc)) { ++ SNDERR("bytes: small size %d", size); ++ return -EINVAL; ++ } ++ ++ tplg_dv(tplg, pos, "control bytes: size %d private size %d", ++ bc->size, bc->priv.size); ++ if (size != bc->size + bc->priv.size) { ++ SNDERR("bytes: unexpected element size %d", size); ++ return -EINVAL; ++ } ++ ++ memset(bt, 0, sizeof(*bt)); ++ bt->hdr.type = bc->hdr.type; ++ bt->hdr.name = bc->hdr.name; ++ bt->hdr.access = bc->hdr.access; ++ bt->hdr.ops.get = bc->hdr.ops.get; ++ bt->hdr.ops.put = bc->hdr.ops.put; ++ bt->hdr.ops.info = bc->hdr.ops.info; ++ bt->max = bc->max; ++ bt->mask = bc->mask; ++ bt->base = bc->base; ++ bt->num_regs = bc->num_regs; ++ bt->ext_ops.get = bc->ext_ops.get; ++ bt->ext_ops.put = bc->ext_ops.put; ++ bt->ext_ops.info = bc->ext_ops.info; ++ tplg_dv(tplg, pos, "control bytes: name '%s' access 0x%x", ++ bt->hdr.name, bt->hdr.access); ++ ++ bt->priv = &bc->priv; ++ return 0; ++} ++ ++int tplg_decode_control_bytes(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ snd_tplg_obj_template_t t; ++ struct snd_tplg_bytes_template bt; ++ struct snd_soc_tplg_bytes_control *bc; ++ size_t size2; ++ int err; ++ ++ err = tplg_decode_template(tplg, pos, hdr, &t); ++ if (err < 0) ++ return err; ++ ++next: ++ if (size < sizeof(*bc)) { ++ SNDERR("bytes: small size %d", size); ++ return -EINVAL; ++ } ++ bc = bin; ++ size2 = bc->size + bc->priv.size; ++ if (size2 > size) { ++ SNDERR("bytes: wrong element size (%d, priv %d)", ++ bc->size, bc->priv.size); ++ return -EINVAL; ++ } ++ ++ err = tplg_decode_control_bytes1(tplg, &bt, pos, bin, size); ++ if (err < 0) ++ return err; ++ ++ t.bytes_ctl = &bt; ++ err = snd_tplg_add_object(tplg, &t); ++ if (err < 0) ++ return err; ++ ++ bin += size2; ++ size -= size2; ++ pos += size2; ++ ++ if (size > 0) ++ goto next; ++ ++ return 0; ++} +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index 88bddca3..9fab2d92 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -420,19 +420,39 @@ int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, char **dst, const char *pf + struct snd_soc_tplg_dapm_graph_elem *route; + struct list_head *pos; + struct tplg_elem *elem; +- int err, first = 1, old_index = -1; +- unsigned block = -1, count = 0; ++ int err, first, old_index; ++ unsigned block, count; ++ const char *fmt; + ++ old_index = -1; ++ block = 0; ++ count = 0; + list_for_each(pos, &tplg->route_list) { + elem = list_entry(pos, struct tplg_elem, list); + if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH) + continue; + if (index >= 0 && elem->index != index) + continue; ++ if (old_index != elem->index) { ++ block++; ++ old_index = elem->index; ++ } + count++; + } + if (count == 0) + return 0; ++ if (block < 10) { ++ fmt = "\tset%u {\n"; ++ } else if (block < 100) { ++ fmt = "\tset%02u {\n"; ++ } else if (block < 1000) { ++ fmt = "\tset%03u {\n"; ++ } else { ++ return -EINVAL; ++ } ++ old_index = -1; ++ block = -1; ++ first = 1; + err = tplg_save_printf(dst, pfx, "SectionGraph {\n"); + list_for_each(pos, &tplg->route_list) { + elem = list_entry(pos, struct tplg_elem, list); +@@ -452,7 +472,7 @@ int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, char **dst, const char *pf + old_index = elem->index; + block++; + first = 1; +- err = tplg_save_printf(dst, pfx, "\tset%u {\n", block); ++ err = tplg_save_printf(dst, pfx, fmt, block); + if (err >= 0) + err = tplg_save_printf(dst, pfx, "\t\tindex %u\n", + elem->index); +@@ -771,20 +791,14 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + w->event_flags = wt->event_flags; + w->event_type = wt->event_type; + +- if (wt->priv != NULL) { +- w = realloc(w, +- elem->size + wt->priv->size); +- if (!w) { ++ /* add private data */ ++ if (wt->priv != NULL && wt->priv->size > 0) { ++ ret = tplg_add_data(tplg, elem, wt->priv, ++ sizeof(*wt->priv) + wt->priv->size); ++ if (ret < 0) { + tplg_elem_free(elem); +- return -ENOMEM; ++ return ret; + } +- +- elem->widget = w; +- elem->size += wt->priv->size; +- +- memcpy(w->priv.data, wt->priv->data, +- wt->priv->size); +- w->priv.size = wt->priv->size; + } + + /* add controls to the widget's reference list */ +@@ -836,3 +850,212 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + + return 0; + } ++ ++/* decode dapm widget from the binary input */ ++int tplg_decode_dapm_widget(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ struct list_head heap; ++ struct snd_soc_tplg_dapm_widget *w; ++ snd_tplg_obj_template_t t; ++ struct snd_tplg_widget_template *wt; ++ struct snd_tplg_mixer_template *mt; ++ struct snd_tplg_enum_template *et; ++ struct snd_tplg_bytes_template *bt; ++ struct snd_soc_tplg_ctl_hdr *chdr; ++ struct snd_soc_tplg_mixer_control *mc; ++ struct snd_soc_tplg_enum_control *ec; ++ struct snd_soc_tplg_bytes_control *bc; ++ size_t size2; ++ unsigned int index; ++ int err; ++ ++ err = tplg_decode_template(tplg, pos, hdr, &t); ++ if (err < 0) ++ return err; ++ ++next: ++ INIT_LIST_HEAD(&heap); ++ w = bin; ++ ++ if (size < sizeof(*w)) { ++ SNDERR("dapm widget: small size %d", size); ++ return -EINVAL; ++ } ++ if (sizeof(*w) != w->size) { ++ SNDERR("dapm widget: unknown element size %d (expected %zd)", ++ w->size, sizeof(*w)); ++ return -EINVAL; ++ } ++ if (w->num_kcontrols > 16) { ++ SNDERR("dapm widget: too many kcontrols %d", ++ w->num_kcontrols); ++ return -EINVAL; ++ } ++ ++ tplg_dv(tplg, pos, "dapm widget: size %d private size %d kcontrols %d", ++ w->size, w->priv.size, w->num_kcontrols); ++ ++ wt = tplg_calloc(&heap, sizeof(*wt) + sizeof(void *) * w->num_kcontrols); ++ if (wt == NULL) ++ return -ENOMEM; ++ wt->id = w->id; ++ wt->name = w->name; ++ wt->sname = w->sname; ++ wt->reg = w->reg; ++ wt->shift = w->shift; ++ wt->mask = w->mask; ++ wt->subseq = w->subseq; ++ wt->invert = w->invert; ++ wt->ignore_suspend = w->ignore_suspend; ++ wt->event_flags = w->event_flags; ++ wt->event_type = w->event_type; ++ ++ tplg_dv(tplg, pos, "dapm widget: name '%s' sname '%s'", wt->name, wt->sname); ++ ++ if (sizeof(*w) + w->priv.size > size) { ++ SNDERR("dapm widget: wrong private data size %d", ++ w->priv.size); ++ return -EINVAL; ++ } ++ ++ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_dapm_widget, priv), ++ "dapm widget: private start"); ++ ++ wt->priv = &w->priv; ++ bin += sizeof(*w) + w->priv.size; ++ size -= sizeof(*w) + w->priv.size; ++ pos += sizeof(*w) + w->priv.size; ++ ++ for (index = 0; index < w->num_kcontrols; index++) { ++ chdr = bin; ++ switch (chdr->type) { ++ case SND_SOC_TPLG_TYPE_MIXER: ++ mt = tplg_calloc(&heap, sizeof(*mt)); ++ if (mt == NULL) { ++ err = -ENOMEM; ++ goto retval; ++ } ++ wt->ctl[index] = (void *)mt; ++ wt->num_ctls++; ++ mc = bin; ++ size2 = mc->size + mc->priv.size; ++ tplg_dv(tplg, pos, "kcontrol mixer size %zd", size2); ++ if (size2 > size) { ++ SNDERR("dapm widget: small mixer size %d", ++ size2); ++ err = -EINVAL; ++ goto retval; ++ } ++ err = tplg_decode_control_mixer1(tplg, &heap, mt, pos, ++ bin, size2); ++ break; ++ case SND_SOC_TPLG_TYPE_ENUM: ++ et = tplg_calloc(&heap, sizeof(*mt)); ++ if (et == NULL) { ++ err = -ENOMEM; ++ goto retval; ++ } ++ wt->ctl[index] = (void *)et; ++ wt->num_ctls++; ++ ec = bin; ++ size2 = ec->size + ec->priv.size; ++ tplg_dv(tplg, pos, "kcontrol enum size %zd", size2); ++ if (size2 > size) { ++ SNDERR("dapm widget: small enum size %d", ++ size2); ++ err = -EINVAL; ++ goto retval; ++ } ++ err = tplg_decode_control_enum1(tplg, &heap, et, pos, ++ bin, size2); ++ break; ++ case SND_SOC_TPLG_TYPE_BYTES: ++ bt = tplg_calloc(&heap, sizeof(*bt)); ++ if (bt == NULL) { ++ err = -ENOMEM; ++ goto retval; ++ } ++ wt->ctl[index] = (void *)bt; ++ wt->num_ctls++; ++ bc = bin; ++ size2 = bc->size + bc->priv.size; ++ tplg_dv(tplg, pos, "kcontrol bytes size %zd", size2); ++ if (size2 > size) { ++ SNDERR("dapm widget: small bytes size %d", ++ size2); ++ err = -EINVAL; ++ goto retval; ++ } ++ err = tplg_decode_control_bytes1(tplg, bt, pos, ++ bin, size2); ++ break; ++ default: ++ SNDERR("dapm widget: wrong control type %d", ++ chdr->type); ++ err = -EINVAL; ++ goto retval; ++ } ++ if (err < 0) ++ goto retval; ++ bin += size2; ++ size -= size2; ++ pos += size2; ++ } ++ ++ t.widget = wt; ++ err = snd_tplg_add_object(tplg, &t); ++ tplg_free(&heap); ++ if (err < 0) ++ return err; ++ if (size > 0) ++ goto next; ++ return 0; ++ ++retval: ++ tplg_free(&heap); ++ return err; ++} ++ ++/* decode dapm link from the binary input */ ++int tplg_decode_dapm_graph(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ struct snd_soc_tplg_dapm_graph_elem *g; ++ snd_tplg_obj_template_t t; ++ struct snd_tplg_graph_template *gt; ++ struct snd_tplg_graph_elem *ge; ++ size_t asize; ++ int err; ++ ++ err = tplg_decode_template(tplg, pos, hdr, &t); ++ if (err < 0) ++ return err; ++ ++ asize = sizeof(*gt) + (size / sizeof(*g)) * sizeof(*ge); ++ gt = alloca(asize); ++ memset(gt, 0, asize); ++ for (ge = gt->elem; size > 0; ge++) { ++ g = bin; ++ if (size < sizeof(*g)) { ++ SNDERR("dapm graph: small size %d", size); ++ return -EINVAL; ++ } ++ ge->src = g->source; ++ ge->ctl = g->control; ++ ge->sink = g->sink; ++ gt->count++; ++ tplg_dv(tplg, pos, "dapm graph: src='%s' ctl='%s' sink='%s'", ++ ge->src, ge->ctl, ge->sink); ++ bin += sizeof(*g); ++ size -= sizeof(*g); ++ pos += sizeof(*g); ++ } ++ ++ t.graph = gt; ++ return snd_tplg_add_object(tplg, &t); ++} +diff --git a/src/topology/data.c b/src/topology/data.c +index 7b4bdccd..64563920 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -566,7 +566,7 @@ static bool has_tuples(struct tplg_elem *elem) + } + + /* get size of a tuple element from its type */ +-static unsigned int get_tuple_size(int type) ++unsigned int tplg_get_tuple_size(int type) + { + switch (type) { + +@@ -602,7 +602,7 @@ static int copy_tuples(struct tplg_elem *elem, + for (i = 0; i < tuples->num_sets ; i++) { + tuple_set = tuples->set[i]; + set_size = sizeof(struct snd_soc_tplg_vendor_array) +- + get_tuple_size(tuple_set->type) ++ + tplg_get_tuple_size(tuple_set->type) + * tuple_set->num_tuples; + size += set_size; + if (size > TPLG_MAX_PRIV_SIZE) { +@@ -1250,6 +1250,9 @@ int tplg_save_manifest_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + continue; + count++; + } ++ if (count == 0) ++ return tplg_save_printf(dst, NULL, ++ "'%s'.comment 'empty'\n", elem->id); + if (count > 1) { + err = tplg_save_printf(dst, NULL, "'%s'.data [\n", elem->id); + if (err < 0) +@@ -1557,3 +1560,436 @@ int tplg_build_data(snd_tplg_t *tplg) + + return 0; + } ++ ++/* decode manifest data */ ++int tplg_decode_manifest_data(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ struct snd_soc_tplg_manifest *m = bin; ++ struct tplg_elem *elem; ++ size_t off; ++ ++ if (hdr->index != 0) { ++ SNDERR("manifest - wrong index %d", hdr->index); ++ return -EINVAL; ++ } ++ ++ if (sizeof(*m) > size) { ++ SNDERR("manifest - wrong size %zd (minimal %zd)", ++ size, sizeof(*m)); ++ return -EINVAL; ++ } ++ ++ if (m->size != sizeof(*m)) { ++ SNDERR("manifest - wrong sructure size %d", m->size); ++ return -EINVAL; ++ } ++ ++ off = offsetof(struct snd_soc_tplg_manifest, priv); ++ if (off + m->priv.size > size) { ++ SNDERR("manifest - wrong private size %d", m->priv.size); ++ return -EINVAL; ++ } ++ ++ tplg->manifest = *m; ++ ++ bin += off; ++ size -= off; ++ pos += off; ++ ++ elem = tplg_elem_new_common(tplg, NULL, "manifest", ++ SND_TPLG_TYPE_MANIFEST); ++ if (!elem) ++ return -ENOMEM; ++ ++ tplg_dv(tplg, pos, "manifest: private size %d", size); ++ return tplg_add_data(tplg, elem, bin, size); ++} ++ ++int tplg_add_token(snd_tplg_t *tplg, struct tplg_elem *parent, ++ unsigned int token, ++ char str_ref[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]) ++{ ++ struct tplg_elem *elem; ++ struct tplg_token *t; ++ struct tplg_vendor_tokens *tokens; ++ unsigned int i; ++ size_t size; ++ ++ elem = tplg_elem_lookup(&tplg->token_list, parent->id, ++ SND_TPLG_TYPE_TOKEN, parent->index); ++ if (elem == NULL) { ++ elem = tplg_elem_new_common(tplg, NULL, parent->id, ++ SND_TPLG_TYPE_TOKEN); ++ if (!elem) ++ return -ENOMEM; ++ } ++ ++ tokens = elem->tokens; ++ if (tokens) { ++ for (i = 0; i < tokens->num_tokens; i++) { ++ t = &tokens->token[i]; ++ if (t->value == token) ++ goto found; ++ } ++ size = sizeof(*tokens) + ++ (tokens->num_tokens + 1) * sizeof(struct tplg_token); ++ tokens = realloc(tokens, size); ++ } else { ++ size = sizeof(*tokens) + 1 * sizeof(struct tplg_token); ++ tokens = calloc(1, size); ++ } ++ ++ if (!tokens) ++ return -ENOMEM; ++ ++ memset(&tokens->token[tokens->num_tokens], 0, sizeof(struct tplg_token)); ++ elem->tokens = tokens; ++ t = &tokens->token[tokens->num_tokens]; ++ tokens->num_tokens++; ++ snprintf(t->id, sizeof(t->id), "token%u", token); ++ t->value = token; ++found: ++ snd_strlcpy(str_ref, t->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); ++ return 0; ++} ++ ++static int tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos, ++ const void *bin, size_t size) ++{ ++ const struct snd_soc_tplg_vendor_array *va; ++ unsigned int j; ++ ++ va = bin; ++ if (size < sizeof(*va) || size < va->size) { ++ tplg_dv(tplg, pos, "tuple set verify: wrong size %d", size); ++ return -EINVAL; ++ } ++ ++ switch (va->type) { ++ case SND_SOC_TPLG_TUPLE_TYPE_UUID: ++ case SND_SOC_TPLG_TUPLE_TYPE_STRING: ++ case SND_SOC_TPLG_TUPLE_TYPE_BOOL: ++ case SND_SOC_TPLG_TUPLE_TYPE_BYTE: ++ case SND_SOC_TPLG_TUPLE_TYPE_WORD: ++ case SND_SOC_TPLG_TUPLE_TYPE_SHORT: ++ break; ++ default: ++ tplg_dv(tplg, pos, "tuple set verify: unknown array type %d", va->type); ++ return -EINVAL; ++ } ++ ++ j = tplg_get_tuple_size(va->type) * va->num_elems; ++ if (j + sizeof(*va) != va->size) { ++ tplg_dv(tplg, pos, "tuple set verify: wrong vendor array size %d " ++ "(expected %d for %d count %d)", ++ va->size, j + sizeof(*va), va->type, va->num_elems); ++ return -EINVAL; ++ } ++ ++ if (va->num_elems > 4096) { ++ tplg_dv(tplg, pos, "tuple set verify: tuples overflow %d", va->num_elems); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int tplg_decode_tuple_set(snd_tplg_t *tplg, ++ size_t pos, ++ struct tplg_elem *parent, ++ struct tplg_tuple_set **_set, ++ const void *bin, size_t size) ++{ ++ const struct snd_soc_tplg_vendor_array *va; ++ struct tplg_tuple_set *set; ++ struct tplg_tuple *tuple; ++ unsigned int j; ++ int err; ++ ++ va = bin; ++ if (size < sizeof(*va) || size < va->size) { ++ SNDERR("tuples: wrong size %d", size); ++ return -EINVAL; ++ } ++ ++ switch (va->type) { ++ case SND_SOC_TPLG_TUPLE_TYPE_UUID: ++ case SND_SOC_TPLG_TUPLE_TYPE_STRING: ++ case SND_SOC_TPLG_TUPLE_TYPE_BOOL: ++ case SND_SOC_TPLG_TUPLE_TYPE_BYTE: ++ case SND_SOC_TPLG_TUPLE_TYPE_WORD: ++ case SND_SOC_TPLG_TUPLE_TYPE_SHORT: ++ break; ++ default: ++ SNDERR("tuples: unknown array type %d", va->type); ++ return -EINVAL; ++ } ++ ++ j = tplg_get_tuple_size(va->type) * va->num_elems; ++ if (j + sizeof(*va) != va->size) { ++ SNDERR("tuples: wrong vendor array size %d " ++ "(expected %d for %d count %d)", ++ va->size, j + sizeof(*va), va->type, va->num_elems); ++ return -EINVAL; ++ } ++ ++ if (va->num_elems > 4096) { ++ SNDERR("tuples: tuples overflow %d", va->num_elems); ++ return -EINVAL; ++ } ++ ++ set = calloc(1, sizeof(*set) + va->num_elems * sizeof(struct tplg_tuple)); ++ if (!set) ++ return -ENOMEM; ++ ++ set->type = va->type; ++ set->num_tuples = va->num_elems; ++ ++ tplg_dv(tplg, pos, "tuple set: type %d (%s) tuples %d size %d", set->type, ++ get_tuple_type_name(set->type), set->num_tuples, va->size); ++ for (j = 0; j < set->num_tuples; j++) { ++ tuple = &set->tuple[j]; ++ switch (va->type) { ++ case SND_SOC_TPLG_TUPLE_TYPE_UUID: ++ err = tplg_add_token(tplg, parent, va->uuid[j].token, ++ tuple->token); ++ if (err < 0) ++ goto retval; ++ memcpy(tuple->uuid, va->uuid[j].uuid, ++ sizeof(va->uuid[j].uuid)); ++ break; ++ case SND_SOC_TPLG_TUPLE_TYPE_STRING: ++ err = tplg_add_token(tplg, parent, va->string[j].token, ++ tuple->token); ++ if (err < 0) ++ goto retval; ++ snd_strlcpy(tuple->string, va->string[j].string, ++ sizeof(tuple->string)); ++ break; ++ case SND_SOC_TPLG_TUPLE_TYPE_BOOL: ++ case SND_SOC_TPLG_TUPLE_TYPE_BYTE: ++ case SND_SOC_TPLG_TUPLE_TYPE_WORD: ++ case SND_SOC_TPLG_TUPLE_TYPE_SHORT: ++ err = tplg_add_token(tplg, parent, va->value[j].token, ++ tuple->token); ++ if (err < 0) ++ goto retval; ++ tuple->value = va->value[j].value; ++ break; ++ } ++ } ++ ++ *_set = set; ++ return 0; ++ ++retval: ++ free(set); ++ return err; ++} ++ ++/* verify tuples from the binary input */ ++static int tplg_verify_tuples(snd_tplg_t *tplg, size_t pos, ++ const void *bin, size_t size) ++{ ++ const struct snd_soc_tplg_vendor_array *va; ++ int err; ++ ++ if (size < sizeof(*va)) { ++ tplg_dv(tplg, pos, "tuples: small size %d", size); ++ return -EINVAL; ++ } ++ ++next: ++ va = bin; ++ if (size < sizeof(*va)) { ++ tplg_dv(tplg, pos, "tuples: unexpected vendor arry size %d", size); ++ return -EINVAL; ++ } ++ ++ err = tplg_verify_tuple_set(tplg, pos, va, va->size); ++ if (err < 0) ++ return err; ++ ++ bin += va->size; ++ size -= va->size; ++ pos += va->size; ++ if (size > 0) ++ goto next; ++ ++ return 0; ++} ++ ++/* add tuples from the binary input */ ++static int tplg_decode_tuples(snd_tplg_t *tplg, ++ size_t pos, ++ struct tplg_elem *parent, ++ struct tplg_vendor_tuples *tuples, ++ const void *bin, size_t size) ++{ ++ const struct snd_soc_tplg_vendor_array *va; ++ struct tplg_tuple_set *set; ++ int err; ++ ++ if (size < sizeof(*va)) { ++ SNDERR("tuples: small size %d", size); ++ return -EINVAL; ++ } ++ ++next: ++ va = bin; ++ if (size < sizeof(*va)) { ++ SNDERR("tuples: unexpected vendor arry size %d", size); ++ return -EINVAL; ++ } ++ ++ if (tuples->num_sets >= tuples->alloc_sets) { ++ SNDERR("tuples: index overflow (%d)", tuples->num_sets); ++ return -EINVAL; ++ } ++ ++ err = tplg_decode_tuple_set(tplg, pos, parent, &set, va, va->size); ++ if (err < 0) ++ return err; ++ tuples->set[tuples->num_sets++] = set; ++ ++ bin += va->size; ++ size -= va->size; ++ pos += va->size; ++ if (size > 0) ++ goto next; ++ ++ return 0; ++} ++ ++/* decode private data */ ++int tplg_add_data(snd_tplg_t *tplg, ++ struct tplg_elem *parent, ++ const void *bin, size_t size) ++{ ++ const struct snd_soc_tplg_private *tp; ++ const struct snd_soc_tplg_vendor_array *va; ++ struct tplg_elem *elem = NULL, *elem2 = NULL; ++ struct tplg_vendor_tuples *tuples = NULL; ++ char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ char suffix[16]; ++ size_t pos = 0, off; ++ int err, num_tuples = 0, block = 0; ++ ++ if (size == 0) ++ return 0; ++ ++ off = offsetof(struct snd_soc_tplg_private, array); ++ ++next: ++ tp = bin; ++ if (off + size < tp->size) { ++ SNDERR("data: unexpected element size %d", size); ++ return -EINVAL; ++ } ++ ++ if (tplg_verify_tuples(tplg, pos, tp->array, tp->size) < 0) { ++ if (tuples) { ++ err = tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, parent->id); ++ if (err < 0) ++ return err; ++ err = tplg_ref_add(elem2, SND_TPLG_TYPE_TUPLE, id); ++ if (err < 0) ++ return err; ++ err = tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id); ++ if (err < 0) ++ return err; ++ tuples = NULL; ++ } ++ tplg_dv(tplg, pos, "add bytes: size %d", tp->size); ++ snprintf(suffix, sizeof(suffix), "data%u", block++); ++ err = tplg_add_data_bytes(tplg, parent, suffix, tp->array, tp->size); ++ } else { ++ if (!tuples) { ++ snprintf(id, sizeof(id), "%.30s:tuple%d", parent->id, (block++) & 0xffff); ++ elem = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_TUPLE); ++ if (!elem) ++ return -ENOMEM; ++ ++ elem2 = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_DATA); ++ if (!elem2) ++ return -ENOMEM; ++ ++ tuples = calloc(1, sizeof(*tuples)); ++ if (!tuples) ++ return -ENOMEM; ++ elem->tuples = tuples; ++ ++ tuples->alloc_sets = (size / sizeof(*va)) + 1; ++ tuples->set = calloc(1, tuples->alloc_sets * sizeof(void *)); ++ if (!tuples->set) { ++ tuples->alloc_sets = 0; ++ return -ENOMEM; ++ } ++ } ++ tplg_dv(tplg, pos, "decode tuples: size %d", tp->size); ++ err = tplg_decode_tuples(tplg, pos, parent, tuples, tp->array, tp->size); ++ num_tuples++; ++ } ++ if (err < 0) ++ return err; ++ ++ bin += off + tp->size; ++ size -= off + tp->size; ++ pos += off + tp->size; ++ if (size > 0) ++ goto next; ++ ++ if (tuples && elem && elem2) { ++ err = tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, parent->id); ++ if (err < 0) ++ return err; ++ err = tplg_ref_add(elem2, SND_TPLG_TYPE_TUPLE, id); ++ if (err < 0) ++ return err; ++ err = tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++/* add private data - bytes */ ++int tplg_add_data_bytes(snd_tplg_t *tplg, struct tplg_elem *parent, ++ const char *suffix, const void *bin, size_t size) ++{ ++ struct snd_soc_tplg_private *priv; ++ struct tplg_elem *elem; ++ char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; ++ ++ if (suffix) ++ snprintf(id, sizeof(id), "%.30s:%.12s", parent->id, suffix); ++ else ++ snd_strlcpy(id, parent->id, sizeof(id)); ++ elem = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_DATA); ++ if (!elem) ++ return -ENOMEM; ++ ++ priv = malloc(sizeof(*priv) + size); ++ if (!priv) ++ return -ENOMEM; ++ memcpy(priv->data, bin, size); ++ priv->size = size; ++ elem->data = priv; ++ ++ return tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id); ++} ++ ++/* decode data from the binary input */ ++int tplg_decode_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, ++ size_t pos ATTRIBUTE_UNUSED, ++ struct snd_soc_tplg_hdr *hdr ATTRIBUTE_UNUSED, ++ void *bin ATTRIBUTE_UNUSED, ++ size_t size ATTRIBUTE_UNUSED) ++{ ++ SNDERR("data type not expected"); ++ return -EINVAL; ++} +diff --git a/src/topology/decoder.c b/src/topology/decoder.c +new file mode 100644 +index 00000000..2d6a8969 +--- /dev/null ++++ b/src/topology/decoder.c +@@ -0,0 +1,136 @@ ++/* ++ Copyright (c) 2019 Red Hat Inc. ++ All rights reserved. ++ ++ This library is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of ++ the License, or (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ Authors: Jaroslav Kysela ++*/ ++ ++#include "list.h" ++#include "tplg_local.h" ++ ++/* verbose output detailing each object size and file position */ ++void tplg_dv(snd_tplg_t *tplg, size_t pos, const char *fmt, ...) ++{ ++ va_list va; ++ ++ if (!tplg->verbose) ++ return; ++ ++ va_start(va, fmt); ++ fprintf(stdout, "D0x%6.6zx/%6.6zd - ", pos, pos); ++ vfprintf(stdout, fmt, va); ++ va_end(va); ++ putc('\n', stdout); ++} ++ ++int tplg_decode_template(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ snd_tplg_obj_template_t *t) ++{ ++ int type; ++ ++ type = tplg_get_type(hdr->type); ++ tplg_dv(tplg, pos, "template: asoc type %d library type %d", hdr->type, type); ++ if (type < 0) ++ return type; ++ ++ memset(t, 0, sizeof(*t)); ++ t->type = type; ++ t->index = hdr->index; ++ t->version = hdr->version; ++ t->vendor_type = hdr->vendor_type; ++ tplg_dv(tplg, pos, "template: index %d version %d vendor_type %d", ++ hdr->index, hdr->version, hdr->vendor_type); ++ return 0; ++} ++ ++int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags) ++{ ++ struct snd_soc_tplg_hdr *hdr; ++ struct tplg_table *tptr; ++ size_t pos; ++ void *b = bin; ++ unsigned int index; ++ int err; ++ ++ if (dflags != 0) ++ return -EINVAL; ++ if (tplg == NULL || bin == NULL) ++ return -EINVAL; ++ while (1) { ++ pos = b - bin; ++ if (size == pos) { ++ tplg_dv(tplg, pos, "block: success (total %zd)", size); ++ return 0; ++ } ++ if (size - pos < sizeof(*hdr)) { ++ tplg_dv(tplg, pos, "block: small size"); ++ SNDERR("incomplete header data to decode"); ++ return -EINVAL; ++ } ++ hdr = b; ++ if (hdr->magic != SND_SOC_TPLG_MAGIC) { ++ SNDERR("bad block magic %08x", hdr->magic); ++ return -EINVAL; ++ } ++ ++ tplg_dv(tplg, pos, "block: abi %d size %d payload size %d", ++ hdr->abi, hdr->size, hdr->payload_size); ++ if (hdr->abi != SND_SOC_TPLG_ABI_VERSION) { ++ SNDERR("unsupported ABI version %d", hdr->abi); ++ return -EINVAL; ++ } ++ if (hdr->size != sizeof(*hdr)) { ++ SNDERR("header size mismatch"); ++ return -EINVAL; ++ } ++ ++ if (size - pos < hdr->size + hdr->payload_size) { ++ SNDERR("incomplete payload data to decode"); ++ return -EINVAL; ++ } ++ ++ if (hdr->payload_size < 8) { ++ SNDERR("wrong payload size %d", hdr->payload_size); ++ return -EINVAL; ++ } ++ ++ /* first block must be manifest */ ++ if (b == bin) { ++ if (hdr->type != SND_SOC_TPLG_TYPE_MANIFEST) { ++ SNDERR("first block must be manifest (value %d)", hdr->type); ++ return -EINVAL; ++ } ++ err = snd_tplg_set_version(tplg, hdr->version); ++ if (err < 0) ++ return err; ++ } ++ ++ pos += hdr->size; ++ for (index = 0; index < tplg_table_items; index++) { ++ tptr = &tplg_table[index]; ++ if (tptr->tsoc == (int)hdr->type) ++ break; ++ } ++ if (index >= tplg_table_items || tptr->decod == NULL) { ++ SNDERR("unknown block type %d", hdr->type); ++ return -EINVAL; ++ } ++ tplg_dv(tplg, pos, "block: type %d - %s", hdr->type, tptr->name); ++ err = tptr->decod(tplg, pos, hdr, b + hdr->size, hdr->payload_size); ++ if (err < 0) ++ return err; ++ b += hdr->size + hdr->payload_size; ++ } ++} +diff --git a/src/topology/elem.c b/src/topology/elem.c +index 89aed1fc..ed5b5f13 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -31,6 +31,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_manifest_data, + .save = tplg_save_manifest_data, ++ .decod = tplg_decode_manifest_data, + }, + { + .name = "control mixer", +@@ -43,6 +44,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_control_mixer, + .save = tplg_save_control_mixer, ++ .decod = tplg_decode_control_mixer, + }, + { + .name = "control enum", +@@ -55,6 +57,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_control_enum, + .save = tplg_save_control_enum, ++ .decod = tplg_decode_control_enum, + }, + { + .name = "control extended (bytes)", +@@ -67,6 +70,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_control_bytes, + .save = tplg_save_control_bytes, ++ .decod = tplg_decode_control_bytes, + }, + { + .name = "dapm widget", +@@ -79,6 +83,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_dapm_widget, + .save = tplg_save_dapm_widget, ++ .decod = tplg_decode_dapm_widget, + }, + { + .name = "pcm", +@@ -91,6 +96,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_pcm, + .save = tplg_save_pcm, ++ .decod = tplg_decode_pcm, + }, + { + .name = "physical dai", +@@ -103,6 +109,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_dai, + .save = tplg_save_dai, ++ .decod = tplg_decode_dai, + }, + { + .name = "be", +@@ -116,6 +123,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_link, + .save = tplg_save_link, ++ .decod = tplg_decode_link, + }, + { + .name = "cc", +@@ -128,6 +136,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_cc, + .save = tplg_save_cc, ++ .decod = tplg_decode_cc, + }, + { + .name = "route (dapm graph)", +@@ -138,6 +147,7 @@ struct tplg_table tplg_table[] = { + .build = 1, + .parse = tplg_parse_dapm_graph, + .gsave = tplg_save_dapm_graph, ++ .decod = tplg_decode_dapm_graph, + }, + { + .name = "private data", +@@ -149,6 +159,7 @@ struct tplg_table tplg_table[] = { + .enew = 1, + .parse = tplg_parse_data, + .save = tplg_save_data, ++ .decod = tplg_decode_data, + }, + { + .name = "text", +@@ -220,6 +231,17 @@ struct tplg_table tplg_table[] = { + + unsigned int tplg_table_items = ARRAY_SIZE(tplg_table); + ++int tplg_get_type(int asoc_type) ++{ ++ unsigned int index; ++ ++ for (index = 0; index < tplg_table_items; index++) ++ if (tplg_table[index].tsoc == asoc_type) ++ return tplg_table[index].type; ++ SNDERR("uknown asoc type %d", asoc_type); ++ return -EINVAL; ++} ++ + int tplg_ref_add(struct tplg_elem *elem, int type, const char* id) + { + struct tplg_ref *ref; +@@ -331,6 +353,36 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id, + return NULL; + } + ++/* find an element by type */ ++struct tplg_elem *tplg_elem_type_lookup(snd_tplg_t *tplg, ++ enum snd_tplg_type type) ++{ ++ struct tplg_table *tptr; ++ struct list_head *pos, *list; ++ struct tplg_elem *elem; ++ unsigned int index; ++ ++ for (index = 0; index < tplg_table_items; index++) { ++ tptr = &tplg_table[index]; ++ if (!tptr->enew) ++ continue; ++ if ((int)type != tptr->type) ++ continue; ++ break; ++ } ++ if (index >= tplg_table_items) ++ return NULL; ++ ++ list = (struct list_head *)((void *)tplg + tptr->loff); ++ ++ /* return only first element */ ++ list_for_each(pos, list) { ++ elem = list_entry(pos, struct tplg_elem, list); ++ return elem; ++ } ++ return NULL; ++} ++ + /* insert a new element into list in the ascending order of index value */ + void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list) + { +@@ -428,3 +480,31 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + elem->type = type; + return elem; + } ++ ++struct tplg_alloc { ++ struct list_head list; ++ void *data[0]; ++}; ++ ++void *tplg_calloc(struct list_head *heap, size_t size) ++{ ++ struct tplg_alloc *a; ++ ++ a = calloc(1, sizeof(*a) + size); ++ if (a == NULL) ++ return NULL; ++ list_add_tail(&a->list, heap); ++ return a->data; ++} ++ ++void tplg_free(struct list_head *heap) ++{ ++ struct list_head *pos, *npos; ++ struct tplg_alloc *a; ++ ++ list_for_each_safe(pos, npos, heap) { ++ a = list_entry(pos, struct tplg_alloc, list); ++ list_del(&a->list); ++ free(a); ++ } ++} +diff --git a/src/topology/parser.c b/src/topology/parser.c +index 5a5dd14f..d7783a93 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -396,17 +396,21 @@ int snd_tplg_build_bin(snd_tplg_t *tplg, + + int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len) + { ++ struct tplg_elem *elem; ++ ++ elem = tplg_elem_type_lookup(tplg, SND_TPLG_TYPE_MANIFEST); ++ if (elem == NULL) { ++ elem = tplg_elem_new_common(tplg, NULL, "manifest", ++ SND_TPLG_TYPE_MANIFEST); ++ if (!elem) ++ return -ENOMEM; ++ tplg->manifest.size = elem->size; ++ } ++ + if (len <= 0) + return 0; + +- tplg->manifest.priv.size = len; +- +- tplg->manifest_pdata = malloc(len); +- if (!tplg->manifest_pdata) +- return -ENOMEM; +- +- memcpy(tplg->manifest_pdata, data, len); +- return 0; ++ return tplg_add_data_bytes(tplg, elem, NULL, data, len); + } + + int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version) +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index bd728959..4e04a6bc 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -1679,11 +1679,20 @@ static void tplg_add_stream_object(struct snd_soc_tplg_stream *strm, + strm->channels = strm_tpl->channels; + } + +-static void tplg_add_stream_caps(struct snd_soc_tplg_stream_caps *caps, +- struct snd_tplg_stream_caps_template *caps_tpl) ++static int tplg_add_stream_caps(snd_tplg_t *tplg, ++ struct snd_tplg_stream_caps_template *caps_tpl) + { +- snd_strlcpy(caps->name, caps_tpl->name, +- SNDRV_CTL_ELEM_ID_NAME_MAXLEN); ++ struct snd_soc_tplg_stream_caps *caps; ++ struct tplg_elem *elem; ++ ++ elem = tplg_elem_new_common(tplg, NULL, caps_tpl->name, ++ SND_TPLG_TYPE_STREAM_CAPS); ++ if (!elem) ++ return -ENOMEM; ++ ++ caps = elem->stream_caps; ++ ++ snd_strlcpy(caps->name, caps_tpl->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + + caps->formats = caps_tpl->formats; + caps->rates = caps_tpl->rates; +@@ -1698,15 +1707,17 @@ static void tplg_add_stream_caps(struct snd_soc_tplg_stream_caps *caps, + caps->buffer_size_min = caps_tpl->buffer_size_min; + caps->buffer_size_max = caps_tpl->buffer_size_max; + caps->sig_bits = caps_tpl->sig_bits; ++ return 0; + } + + /* Add a PCM element (FE DAI & DAI link) from C API */ + int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + { + struct snd_tplg_pcm_template *pcm_tpl = t->pcm; +- struct snd_soc_tplg_pcm *pcm, *_pcm; ++ struct snd_soc_tplg_private *priv; ++ struct snd_soc_tplg_pcm *pcm; + struct tplg_elem *elem; +- int i; ++ int ret, i; + + tplg_dbg("PCM: %s, DAI %s\n", pcm_tpl->pcm_name, pcm_tpl->dai_name); + +@@ -1732,8 +1743,13 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + pcm->compress = pcm_tpl->compress; + + for (i = 0; i < 2; i++) { +- if (pcm_tpl->caps[i]) +- tplg_add_stream_caps(&pcm->caps[i], pcm_tpl->caps[i]); ++ if (!pcm_tpl->caps[i] || !pcm_tpl->caps[i]->name) ++ continue; ++ ret = tplg_add_stream_caps(tplg, pcm_tpl->caps[i]); ++ if (ret < 0) ++ return ret; ++ snd_strlcpy(pcm->caps[i].name, pcm_tpl->caps[i]->name, ++ sizeof(pcm->caps[i].name)); + } + + pcm->flag_mask = pcm_tpl->flag_mask; +@@ -1744,22 +1760,12 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + tplg_add_stream_object(&pcm->stream[i], &pcm_tpl->stream[i]); + + /* private data */ +- if (pcm_tpl->priv != NULL && pcm_tpl->priv->size) { +- tplg_dbg("\t priv data size %d\n", pcm_tpl->priv->size); +- _pcm = realloc(pcm, +- elem->size + pcm_tpl->priv->size); +- if (!_pcm) { +- tplg_elem_free(elem); +- return -ENOMEM; +- } +- +- pcm = _pcm; +- elem->pcm = pcm; +- elem->size += pcm_tpl->priv->size; +- +- memcpy(pcm->priv.data, pcm_tpl->priv->data, +- pcm_tpl->priv->size); +- pcm->priv.size = pcm_tpl->priv->size; ++ priv = pcm_tpl->priv; ++ if (priv && priv->size > 0) { ++ ret = tplg_add_data(tplg, elem, priv, ++ sizeof(*priv) + priv->size); ++ if (ret < 0) ++ return ret; + } + + return 0; +@@ -1810,9 +1816,11 @@ static int set_link_hw_config(struct snd_soc_tplg_hw_config *cfg, + int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + { + struct snd_tplg_link_template *link_tpl = t->link; +- struct snd_soc_tplg_link_config *link, *_link; ++ struct snd_soc_tplg_link_config *link; ++ struct snd_soc_tplg_private *priv; + struct tplg_elem *elem; + unsigned int i; ++ int ret; + + if (t->type != SND_TPLG_TYPE_LINK && t->type != SND_TPLG_TYPE_BE + && t->type != SND_TPLG_TYPE_CC) +@@ -1854,21 +1862,12 @@ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + link->flags = link_tpl->flags; + + /* private data */ +- if (link_tpl->priv != NULL && link_tpl->priv->size) { +- _link = realloc(link, +- elem->size + link_tpl->priv->size); +- if (!_link) { +- tplg_elem_free(elem); +- return -ENOMEM; +- } +- +- link = _link; +- elem->link = link; +- elem->size += link_tpl->priv->size; +- +- memcpy(link->priv.data, link_tpl->priv->data, +- link_tpl->priv->size); +- link->priv.size = link_tpl->priv->size; ++ priv = link_tpl->priv; ++ if (priv && priv->size > 0) { ++ ret = tplg_add_data(tplg, elem, priv, ++ sizeof(*priv) + priv->size); ++ if (ret < 0) ++ return ret; + } + + return 0; +@@ -1877,14 +1876,15 @@ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + { + struct snd_tplg_dai_template *dai_tpl = t->dai; +- struct snd_soc_tplg_dai *dai, *_dai; ++ struct snd_soc_tplg_dai *dai; ++ struct snd_soc_tplg_private *priv; + struct tplg_elem *elem; +- int i; ++ int ret, i; + + tplg_dbg("DAI %s\n", dai_tpl->dai_name); + + elem = tplg_elem_new_common(tplg, NULL, dai_tpl->dai_name, +- SND_TPLG_TYPE_DAI); ++ SND_TPLG_TYPE_DAI); + if (!elem) + return -ENOMEM; + +@@ -1900,8 +1900,13 @@ int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + dai->capture = dai_tpl->capture; + + for (i = 0; i < 2; i++) { +- if (dai_tpl->caps[i]) +- tplg_add_stream_caps(&dai->caps[i], dai_tpl->caps[i]); ++ if (!dai_tpl->caps[i] || !dai_tpl->caps[i]->name) ++ continue; ++ ret = tplg_add_stream_caps(tplg, dai_tpl->caps[i]); ++ if (ret < 0) ++ return ret; ++ snd_strlcpy(dai->caps[i].name, dai_tpl->caps[i]->name, ++ sizeof(dai->caps[i].name)); + } + + /* flags */ +@@ -1909,22 +1914,299 @@ int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + dai->flags = dai_tpl->flags; + + /* private data */ +- if (dai_tpl->priv != NULL) { +- _dai = realloc(dai, +- elem->size + dai_tpl->priv->size); +- if (!_dai) { +- tplg_elem_free(elem); +- return -ENOMEM; ++ priv = dai_tpl->priv; ++ if (priv && priv->size > 0) { ++ ret = tplg_add_data(tplg, elem, priv, ++ sizeof(*priv) + priv->size); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/* decode pcm from the binary input */ ++int tplg_decode_pcm(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ struct snd_soc_tplg_pcm *pcm; ++ snd_tplg_obj_template_t t; ++ struct snd_tplg_pcm_template *pt; ++ struct snd_tplg_stream_caps_template caps[2], *cap; ++ struct snd_tplg_stream_template *stream; ++ unsigned int i; ++ size_t asize; ++ int err; ++ ++ err = tplg_decode_template(tplg, pos, hdr, &t); ++ if (err < 0) ++ return err; ++ ++ asize = sizeof(*pt) + SND_SOC_TPLG_STREAM_CONFIG_MAX * sizeof(*stream); ++ pt = alloca(asize); ++ ++next: ++ memset(pt, 0, asize); ++ pcm = bin; ++ ++ if (size < sizeof(*pcm)) { ++ SNDERR("pcm: small size %d", size); ++ return -EINVAL; ++ } ++ if (sizeof(*pcm) != pcm->size) { ++ SNDERR("pcm: unknown element size %d (expected %zd)", ++ pcm->size, sizeof(*pcm)); ++ return -EINVAL; ++ } ++ if (pcm->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX) { ++ SNDERR("pcm: wrong number of streams %d", pcm->num_streams); ++ return -EINVAL; ++ } ++ if (sizeof(*pcm) + pcm->priv.size > size) { ++ SNDERR("pcm: wrong private data size %d", pcm->priv.size); ++ return -EINVAL; ++ } ++ ++ tplg_dv(tplg, pos, "pcm: size %d private size %d streams %d", ++ pcm->size, pcm->priv.size, pcm->num_streams); ++ ++ pt->pcm_name = pcm->pcm_name; ++ tplg_dv(tplg, pos, "pcm: pcm_name '%s'", pt->pcm_name); ++ pt->dai_name = pcm->dai_name; ++ tplg_dv(tplg, pos, "pcm: dai_name '%s'", pt->dai_name); ++ pt->pcm_id = pcm->pcm_id; ++ pt->dai_id = pcm->dai_id; ++ tplg_dv(tplg, pos, "pcm: pcm_id %d dai_id %d", pt->pcm_id, pt->dai_id); ++ pt->playback = pcm->playback; ++ pt->capture = pcm->capture; ++ pt->compress = pcm->compress; ++ tplg_dv(tplg, pos, "pcm: playback %d capture %d compress", ++ pt->playback, pt->capture, pt->compress); ++ pt->num_streams = pcm->num_streams; ++ pt->flag_mask = pcm->flag_mask; ++ pt->flags = pcm->flags; ++ for (i = 0; i < pcm->num_streams; i++) { ++ stream = &pt->stream[i]; ++ if (pcm->stream[i].size != sizeof(pcm->stream[0])) { ++ SNDERR("pcm: unknown stream structure size %d", ++ pcm->stream[i].size); ++ return -EINVAL; ++ } ++ stream->name = pcm->stream[i].name; ++ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, stream[i]), ++ "stream %d: '%s'", i, stream->name); ++ stream->format = pcm->stream[i].format; ++ stream->rate = pcm->stream[i].rate; ++ stream->period_bytes = pcm->stream[i].period_bytes; ++ stream->buffer_bytes = pcm->stream[i].buffer_bytes; ++ stream->channels = pcm->stream[i].channels; ++ } ++ for (i = 0; i < 2; i++) { ++ if (i == 0 && !pcm->playback) ++ continue; ++ if (i == 1 && !pcm->capture) ++ continue; ++ cap = &caps[i]; ++ pt->caps[i] = cap; ++ if (pcm->caps[i].size != sizeof(pcm->caps[0])) { ++ SNDERR("pcm: unknown caps structure size %d", ++ pcm->caps[i].size); ++ return -EINVAL; + } ++ cap->name = pcm->caps[i].name; ++ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, caps[i]), ++ "caps %d: '%s'", i, cap->name); ++ cap->formats = pcm->caps[i].formats; ++ cap->rates = pcm->caps[i].rates; ++ cap->rate_min = pcm->caps[i].rate_min; ++ cap->rate_max = pcm->caps[i].rate_max; ++ cap->channels_min = pcm->caps[i].channels_min; ++ cap->channels_max = pcm->caps[i].channels_max; ++ cap->periods_min = pcm->caps[i].periods_min; ++ cap->periods_max = pcm->caps[i].periods_max; ++ cap->period_size_min = pcm->caps[i].period_size_min; ++ cap->period_size_max = pcm->caps[i].period_size_max; ++ cap->buffer_size_min = pcm->caps[i].buffer_size_min; ++ cap->buffer_size_max = pcm->caps[i].buffer_size_max; ++ cap->sig_bits = pcm->caps[i].sig_bits; ++ } ++ ++ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, priv), ++ "pcm: private start"); ++ pt->priv = &pcm->priv; ++ ++ bin += sizeof(*pcm) + pcm->priv.size; ++ size -= sizeof(*pcm) + pcm->priv.size; ++ pos += sizeof(*pcm) + pcm->priv.size; ++ ++ t.pcm = pt; ++ err = snd_tplg_add_object(tplg, &t); ++ if (err < 0) ++ return err; ++ ++ if (size > 0) ++ goto next; ++ ++ return 0; ++} ++ ++/* decode dai from the binary input */ ++int tplg_decode_dai(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ SNDERR("not implemented"); ++ return -ENXIO; ++} ++ ++/* decode cc from the binary input */ ++int tplg_decode_cc(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ SNDERR("not implemented"); ++ return -ENXIO; ++} ++ ++/* decode link from the binary input */ ++int tplg_decode_link(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size) ++{ ++ struct snd_soc_tplg_link_config *link; ++ snd_tplg_obj_template_t t; ++ struct snd_tplg_link_template lt; ++ struct snd_tplg_stream_template streams[SND_SOC_TPLG_STREAM_CONFIG_MAX]; ++ struct snd_tplg_stream_template *stream; ++ struct snd_tplg_hw_config_template hws[SND_SOC_TPLG_HW_CONFIG_MAX]; ++ struct snd_tplg_hw_config_template *hw; ++ unsigned int i, j; ++ int err; ++ ++ err = tplg_decode_template(tplg, pos, hdr, &t); ++ if (err < 0) ++ return err; ++ ++next: ++ memset(<, 0, sizeof(lt)); ++ memset(streams, 0, sizeof(streams)); ++ memset(hws, 0, sizeof(hws)); ++ link = bin; + +- dai = _dai; +- dai->priv.size = dai_tpl->priv->size; ++ if (size < sizeof(*link)) { ++ SNDERR("link: small size %d", size); ++ return -EINVAL; ++ } ++ if (sizeof(*link) != link->size) { ++ SNDERR("link: unknown element size %d (expected %zd)", ++ link->size, sizeof(*link)); ++ return -EINVAL; ++ } ++ if (link->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX) { ++ SNDERR("link: wrong number of streams %d", link->num_streams); ++ return -EINVAL; ++ } ++ if (link->num_hw_configs > SND_SOC_TPLG_HW_CONFIG_MAX) { ++ SNDERR("link: wrong number of streams %d", link->num_streams); ++ return -EINVAL; ++ } ++ if (sizeof(*link) + link->priv.size > size) { ++ SNDERR("link: wrong private data size %d", link->priv.size); ++ return -EINVAL; ++ } + +- elem->dai = dai; +- elem->size += dai->priv.size; +- memcpy(dai->priv.data, dai_tpl->priv->data, +- dai->priv.size); ++ tplg_dv(tplg, pos, "link: size %d private size %d streams %d " ++ "hw_configs %d", ++ link->size, link->priv.size, link->num_streams, ++ link->num_hw_configs); ++ ++ lt.id = link->id; ++ lt.name = link->name; ++ tplg_dv(tplg, pos, "link: name '%s'", lt.name); ++ lt.stream_name = link->stream_name; ++ tplg_dv(tplg, pos, "link: stream_name '%s'", lt.stream_name); ++ lt.num_streams = link->num_streams; ++ lt.num_hw_configs = link->num_hw_configs; ++ lt.default_hw_config_id = link->default_hw_config_id; ++ lt.flag_mask = link->flag_mask; ++ lt.flags = link->flags; ++ for (i = 0; i < link->num_streams; i++) { ++ stream = &streams[i]; ++ if (link->stream[i].size != sizeof(link->stream[0])) { ++ SNDERR("link: unknown stream structure size %d", ++ link->stream[i].size); ++ return -EINVAL; ++ } ++ stream->name = link->stream[i].name; ++ tplg_dv(tplg, ++ pos + offsetof(struct snd_soc_tplg_link_config, stream[i]), ++ "stream %d: '%s'", i, stream->name); ++ stream->format = link->stream[i].format; ++ stream->rate = link->stream[i].rate; ++ stream->period_bytes = link->stream[i].period_bytes; ++ stream->buffer_bytes = link->stream[i].buffer_bytes; ++ stream->channels = link->stream[i].channels; + } ++ lt.stream = streams; ++ for (i = 0; i < link->num_hw_configs; i++) { ++ hw = &hws[i]; ++ if (link->hw_config[i].size != sizeof(link->hw_config[0])) { ++ SNDERR("link: unknown hw_config structure size %d", ++ link->hw_config[i].size); ++ return -EINVAL; ++ } ++ hw->id = link->hw_config[i].id; ++ hw->fmt = link->hw_config[i].fmt; ++ hw->clock_gated = link->hw_config[i].clock_gated; ++ hw->invert_bclk = link->hw_config[i].invert_bclk; ++ hw->invert_fsync = link->hw_config[i].invert_fsync; ++ hw->bclk_master = link->hw_config[i].bclk_master; ++ hw->fsync_master = link->hw_config[i].fsync_master; ++ hw->mclk_direction = link->hw_config[i].mclk_direction; ++ hw->mclk_rate = link->hw_config[i].mclk_rate; ++ hw->bclk_rate = link->hw_config[i].bclk_rate; ++ hw->fsync_rate = link->hw_config[i].fsync_rate; ++ hw->tdm_slots = link->hw_config[i].tdm_slots; ++ hw->tdm_slot_width = link->hw_config[i].tdm_slot_width; ++ hw->tx_slots = link->hw_config[i].tx_slots; ++ hw->rx_slots = link->hw_config[i].rx_slots; ++ hw->tx_channels = link->hw_config[i].tx_channels; ++ if (hw->tx_channels > SND_SOC_TPLG_MAX_CHAN) { ++ SNDERR("link: wrong tx channels %d", hw->tx_channels); ++ return -EINVAL; ++ } ++ for (j = 0; j < hw->tx_channels; j++) ++ hw->tx_chanmap[j] = link->hw_config[i].tx_chanmap[j]; ++ hw->rx_channels = link->hw_config[i].rx_channels; ++ if (hw->rx_channels > SND_SOC_TPLG_MAX_CHAN) { ++ SNDERR("link: wrong rx channels %d", hw->tx_channels); ++ return -EINVAL; ++ } ++ for (j = 0; j < hw->rx_channels; j++) ++ hw->rx_chanmap[j] = link->hw_config[i].rx_chanmap[j]; ++ } ++ lt.hw_config = hws; ++ ++ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, priv), ++ "link: private start"); ++ lt.priv = &link->priv; ++ ++ bin += sizeof(*link) + link->priv.size; ++ size -= sizeof(*link) + link->priv.size; ++ pos += sizeof(*link) + link->priv.size; ++ ++ t.link = < ++ err = snd_tplg_add_object(tplg, &t); ++ if (err < 0) ++ return err; ++ ++ if (size > 0) ++ goto next; + + return 0; + } +diff --git a/src/topology/save.c b/src/topology/save.c +index 0498911f..c6eabc49 100644 +--- a/src/topology/save.c ++++ b/src/topology/save.c +@@ -577,6 +577,9 @@ int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags) + if (err < 0) + goto _err; + ++ if (*dst == NULL) ++ return -EINVAL; ++ + if (flags & SND_TPLG_SAVE_NOCHECK) + return 0; + +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 74b3a55c..22fc5fba 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -142,7 +142,8 @@ struct tplg_tuple_set { + }; + + struct tplg_vendor_tuples { +- unsigned int num_sets; ++ unsigned int num_sets; ++ unsigned int alloc_sets; + struct tplg_tuple_set **set; + }; + +@@ -217,11 +218,19 @@ struct tplg_table { + char **dst, const char *prefix); + int (*gsave)(snd_tplg_t *tplg, int index, + char **dst, const char *prefix); ++ int (*decod)(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); + }; + + extern struct tplg_table tplg_table[]; + extern unsigned int tplg_table_items; + ++void *tplg_calloc(struct list_head *heap, size_t size); ++void tplg_free(struct list_head *heap); ++ ++int tplg_get_type(int asoc_type); ++ + int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, + int (*fcn)(snd_tplg_t *, snd_config_t *, void *), + void *private); +@@ -246,6 +255,7 @@ int tplg_parse_link(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); + int tplg_parse_cc(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); + int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); + ++unsigned int tplg_get_tuple_size(int type); + void tplg_free_tuples(void *obj); + + int tplg_build_data(snd_tplg_t *tplg); +@@ -272,6 +282,8 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, + const char* id, + unsigned int type, + int index); ++struct tplg_elem *tplg_elem_type_lookup(snd_tplg_t *tplg, ++ enum snd_tplg_type type); + struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + snd_config_t *cfg, const char *name, enum snd_tplg_type type); + +@@ -291,6 +303,10 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base, + const char* id); + ++int tplg_add_data(snd_tplg_t *tplg, struct tplg_elem *parent, ++ const void *bin, size_t size); ++int tplg_add_data_bytes(snd_tplg_t *tplg, struct tplg_elem *parent, ++ const char *suffix, const void *bin, size_t size); + int tplg_add_mixer_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); + int tplg_add_enum_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); + int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); +@@ -356,3 +372,56 @@ int tplg_save_stream_caps(snd_tplg_t *tplg, struct tplg_elem *elem, + char **dst, const char *pfx); + int tplg_save_dai(snd_tplg_t *tplg, struct tplg_elem *elem, + char **dst, const char *pfx); ++ ++void tplg_dv(snd_tplg_t *tplg, size_t pos, const char *fmt, ...); ++int tplg_decode_template(snd_tplg_t *tplg, ++ size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ snd_tplg_obj_template_t *t); ++int tplg_decode_manifest_data(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_control_mixer1(snd_tplg_t *tplg, ++ struct list_head *heap, ++ struct snd_tplg_mixer_template *mt, ++ size_t pos, ++ void *bin, size_t size); ++int tplg_decode_control_mixer(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_control_enum1(snd_tplg_t *tplg, ++ struct list_head *heap, ++ struct snd_tplg_enum_template *et, ++ size_t pos, ++ void *bin, size_t size); ++int tplg_decode_control_enum(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_control_bytes1(snd_tplg_t *tplg, ++ struct snd_tplg_bytes_template *bt, ++ size_t pos, ++ void *bin, size_t size); ++int tplg_decode_control_bytes(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_data(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_dapm_graph(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_dapm_widget(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_link(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_cc(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_pcm(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); ++int tplg_decode_dai(snd_tplg_t *tplg, size_t pos, ++ struct snd_soc_tplg_hdr *hdr, ++ void *bin, size_t size); +-- +2.24.1 + + +From cb88813ff71226af5d16f8853d186ff7c572dbe0 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 3 Jan 2020 22:07:11 +0100 +Subject: [PATCH 54/69] topology: move the elem->list delete to + tplg_elem_free() + +The tplg_elem_free() is called in the error path from many places +and it is expected that the element object will be unregistered +from the tplg structure, too. + +Signed-off-by: Jaroslav Kysela +--- + src/topology/elem.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/topology/elem.c b/src/topology/elem.c +index ed5b5f13..cbd7f4b6 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -301,6 +301,8 @@ struct tplg_elem *tplg_elem_new(void) + + void tplg_elem_free(struct tplg_elem *elem) + { ++ list_del(&elem->list); ++ + tplg_ref_free_list(&elem->ref_list); + + /* free struct snd_tplg_ object, +@@ -323,7 +325,6 @@ void tplg_elem_free_list(struct list_head *base) + + list_for_each_safe(pos, npos, base) { + elem = list_entry(pos, struct tplg_elem, list); +- list_del(&elem->list); + tplg_elem_free(elem); + } + } +-- +2.24.1 + + +From ae6522e10621839a15f5a439091af7542d84d3e5 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 3 Jan 2020 22:31:27 +0100 +Subject: [PATCH 55/69] topology: unify the log mechanism + +Signed-off-by: Jaroslav Kysela +--- + src/topology/Makefile.am | 3 ++- + src/topology/builder.c | 54 +++++++++++++++++---------------------- + src/topology/ctl.c | 30 +++++++++++----------- + src/topology/dapm.c | 19 +++++++------- + src/topology/data.c | 26 +++++++++---------- + src/topology/decoder.c | 32 +++++++---------------- + src/topology/log.c | 34 ++++++++++++++++++++++++ + src/topology/pcm.c | 48 +++++++++++++++++----------------- + src/topology/tplg_local.h | 8 +++++- + 9 files changed, 138 insertions(+), 116 deletions(-) + create mode 100644 src/topology/log.c + +diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am +index 12d1d445..9f48891f 100644 +--- a/src/topology/Makefile.am ++++ b/src/topology/Makefile.am +@@ -29,7 +29,8 @@ libatopology_la_SOURCES =\ + ops.c \ + elem.c \ + save.c \ +- decoder.c ++ decoder.c \ ++ log.c + + noinst_HEADERS = tplg_local.h + +diff --git a/src/topology/builder.c b/src/topology/builder.c +index 74c44405..7af5de08 100644 +--- a/src/topology/builder.c ++++ b/src/topology/builder.c +@@ -20,20 +20,6 @@ + #include "list.h" + #include "tplg_local.h" + +-/* verbose output detailing each object size and file position */ +-static void verbose(snd_tplg_t *tplg, const char *fmt, ...) +-{ +- va_list va; +- +- if (!tplg->verbose) +- return; +- +- va_start(va, fmt); +- fprintf(stdout, "0x%6.6zx/%6.6zd - ", tplg->bin_pos, tplg->bin_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) + { +@@ -73,10 +59,11 @@ 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 " +- "version %d\n", index, type, count, +- (long unsigned int)payload_size, (long int)payload_size, +- vendor_type, version); ++ tplg_log(tplg, 'B', tplg->bin_pos, ++ "header index %d type %d count %d size 0x%lx/%ld vendor %d " ++ "version %d", index, type, count, ++ (long unsigned int)payload_size, (long int)payload_size, ++ vendor_type, version); + + tplg->next_hdr_pos += hdr.payload_size + sizeof(hdr); + +@@ -121,13 +108,15 @@ 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", +- obj_name, elem->id, elem->size); ++ tplg_log(tplg, 'B', tplg->bin_pos, ++ "%s '%s': write %d bytes", ++ obj_name, elem->id, elem->size); + else +- verbose(tplg, "%s '%s -> %s -> %s': write %d bytes\n", +- obj_name, elem->route->source, +- elem->route->control, +- elem->route->sink, elem->size); ++ tplg_log(tplg, 'B', tplg->bin_pos, ++ "%s '%s -> %s -> %s': write %d bytes", ++ obj_name, elem->route->source, ++ elem->route->control, ++ elem->route->sink, elem->size); + + wsize = twrite(tplg, elem->obj, elem->size); + if (wsize < 0) +@@ -225,10 +214,13 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg) + return ret; + } + +- verbose(tplg, "manifest: write %d bytes\n", sizeof(tplg->manifest)); ++ tplg_log(tplg, 'B', tplg->bin_pos, "manifest: write %d bytes", ++ 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); ++ tplg_log(tplg, 'B', tplg->bin_pos, ++ "manifest: write %d priv bytes", ++ tplg->manifest.priv.size); + ret = twrite(tplg, tplg->manifest_pdata, tplg->manifest.priv.size); + } + return ret; +@@ -280,9 +272,10 @@ int tplg_write_data(snd_tplg_t *tplg) + size = calc_block_size(list); + if (size == 0) + continue; +- verbose(tplg, "block size for type %s (%d:%d) is 0x%zx/%zd\n", +- tptr->name, tptr->type, +- tptr->tsoc, size, size); ++ tplg_log(tplg, 'B', tplg->bin_pos, ++ "block size for type %s (%d:%d) is 0x%zx/%zd", ++ tptr->name, tptr->type, ++ tptr->tsoc, size, size); + ret = write_elem_block(tplg, list, size, + tptr->tsoc, tptr->name); + if (ret < 0) { +@@ -292,7 +285,8 @@ int tplg_write_data(snd_tplg_t *tplg) + } + } + +- verbose(tplg, "total size is 0x%zx/%zd\n", tplg->bin_pos, tplg->bin_pos); ++ tplg_log(tplg, 'B', tplg->bin_pos, "total size is 0x%zx/%zd", ++ tplg->bin_pos, tplg->bin_pos); + + if (total_size != tplg->bin_pos) { + SNDERR("total size mismatch (%zd != %zd)", +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index 24d437aa..a5a81148 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -1216,8 +1216,8 @@ int tplg_decode_control_mixer1(snd_tplg_t *tplg, + return -EINVAL; + } + +- tplg_dv(tplg, pos, "mixer: size %d TLV size %d private size %d", +- mc->size, mc->hdr.tlv.size, mc->priv.size); ++ tplg_log(tplg, 'D', pos, "mixer: size %d TLV size %d private size %d", ++ mc->size, mc->hdr.tlv.size, mc->priv.size); + if (size != mc->size + mc->priv.size) { + SNDERR("mixer: unexpected element size %d", size); + return -EINVAL; +@@ -1233,7 +1233,7 @@ int tplg_decode_control_mixer1(snd_tplg_t *tplg, + mt->min = mc->min; + mt->max = mc->max; + mt->platform_max = mc->platform_max; +- tplg_dv(tplg, pos, "mixer: name '%s' access 0x%x", ++ tplg_log(tplg, 'D', pos, "mixer: name '%s' access 0x%x", + mt->hdr.name, mt->hdr.access); + if (mc->num_channels > 0) { + map = tplg_calloc(heap, sizeof(*map)); +@@ -1261,16 +1261,16 @@ int tplg_decode_control_mixer1(snd_tplg_t *tplg, + db->min = mc->hdr.tlv.scale.min; + db->step = mc->hdr.tlv.scale.step; + db->mute = mc->hdr.tlv.scale.mute; +- tplg_dv(tplg, pos, "mixer: dB scale TLV: min %d step %d mute %d", +- db->min, db->step, db->mute); ++ tplg_log(tplg, 'D', pos, "mixer: dB scale TLV: min %d step %d mute %d", ++ db->min, db->step, db->mute); + } else { + SNDERR("mixer: wrong TLV size %d", mc->hdr.tlv.size); + return -EINVAL; + } + + mt->priv = &mc->priv; +- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_mixer_control, priv), +- "mixer: private start"); ++ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_mixer_control, priv), ++ "mixer: private start"); + return 0; + } + +@@ -1338,8 +1338,8 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg, + return -EINVAL; + } + +- tplg_dv(tplg, pos, "enum: size %d private size %d", +- ec->size, ec->priv.size); ++ tplg_log(tplg, 'D', pos, "enum: size %d private size %d", ++ ec->size, ec->priv.size); + if (size != ec->size + ec->priv.size) { + SNDERR("enum: unexpected element size %d", size); + return -EINVAL; +@@ -1380,8 +1380,8 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg, + cmt.num_channels = ec->num_channels; + for (i = 0; i < cmt.num_channels; i++) { + struct snd_tplg_channel_elem *channel = &cmt.channel[i]; +- tplg_dv(tplg, pos + ((void *)&ec->channel[i] - (void *)ec), +- "enum: channel size %d", ec->channel[i].size); ++ tplg_log(tplg, 'D', pos + ((void *)&ec->channel[i] - (void *)ec), ++ "enum: channel size %d", ec->channel[i].size); + channel->reg = ec->channel[i].reg; + channel->shift = ec->channel[i].shift; + channel->id = ec->channel[i].id; +@@ -1452,8 +1452,8 @@ int tplg_decode_control_bytes1(snd_tplg_t *tplg, + return -EINVAL; + } + +- tplg_dv(tplg, pos, "control bytes: size %d private size %d", +- bc->size, bc->priv.size); ++ tplg_log(tplg, 'D', pos, "control bytes: size %d private size %d", ++ bc->size, bc->priv.size); + if (size != bc->size + bc->priv.size) { + SNDERR("bytes: unexpected element size %d", size); + return -EINVAL; +@@ -1473,8 +1473,8 @@ int tplg_decode_control_bytes1(snd_tplg_t *tplg, + bt->ext_ops.get = bc->ext_ops.get; + bt->ext_ops.put = bc->ext_ops.put; + bt->ext_ops.info = bc->ext_ops.info; +- tplg_dv(tplg, pos, "control bytes: name '%s' access 0x%x", +- bt->hdr.name, bt->hdr.access); ++ tplg_log(tplg, 'D', pos, "control bytes: name '%s' access 0x%x", ++ bt->hdr.name, bt->hdr.access); + + bt->priv = &bc->priv; + return 0; +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index 9fab2d92..0bf64833 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -895,8 +895,8 @@ next: + return -EINVAL; + } + +- tplg_dv(tplg, pos, "dapm widget: size %d private size %d kcontrols %d", +- w->size, w->priv.size, w->num_kcontrols); ++ tplg_log(tplg, 'D', pos, "dapm widget: size %d private size %d kcontrols %d", ++ w->size, w->priv.size, w->num_kcontrols); + + wt = tplg_calloc(&heap, sizeof(*wt) + sizeof(void *) * w->num_kcontrols); + if (wt == NULL) +@@ -913,7 +913,8 @@ next: + wt->event_flags = w->event_flags; + wt->event_type = w->event_type; + +- tplg_dv(tplg, pos, "dapm widget: name '%s' sname '%s'", wt->name, wt->sname); ++ tplg_log(tplg, 'D', pos, "dapm widget: name '%s' sname '%s'", ++ wt->name, wt->sname); + + if (sizeof(*w) + w->priv.size > size) { + SNDERR("dapm widget: wrong private data size %d", +@@ -921,8 +922,8 @@ next: + return -EINVAL; + } + +- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_dapm_widget, priv), +- "dapm widget: private start"); ++ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_dapm_widget, priv), ++ "dapm widget: private start"); + + wt->priv = &w->priv; + bin += sizeof(*w) + w->priv.size; +@@ -942,7 +943,7 @@ next: + wt->num_ctls++; + mc = bin; + size2 = mc->size + mc->priv.size; +- tplg_dv(tplg, pos, "kcontrol mixer size %zd", size2); ++ tplg_log(tplg, 'D', pos, "kcontrol mixer size %zd", size2); + if (size2 > size) { + SNDERR("dapm widget: small mixer size %d", + size2); +@@ -962,7 +963,7 @@ next: + wt->num_ctls++; + ec = bin; + size2 = ec->size + ec->priv.size; +- tplg_dv(tplg, pos, "kcontrol enum size %zd", size2); ++ tplg_log(tplg, 'D', pos, "kcontrol enum size %zd", size2); + if (size2 > size) { + SNDERR("dapm widget: small enum size %d", + size2); +@@ -982,7 +983,7 @@ next: + wt->num_ctls++; + bc = bin; + size2 = bc->size + bc->priv.size; +- tplg_dv(tplg, pos, "kcontrol bytes size %zd", size2); ++ tplg_log(tplg, 'D', pos, "kcontrol bytes size %zd", size2); + if (size2 > size) { + SNDERR("dapm widget: small bytes size %d", + size2); +@@ -1049,7 +1050,7 @@ int tplg_decode_dapm_graph(snd_tplg_t *tplg, + ge->ctl = g->control; + ge->sink = g->sink; + gt->count++; +- tplg_dv(tplg, pos, "dapm graph: src='%s' ctl='%s' sink='%s'", ++ tplg_log(tplg, 'D', pos, "dapm graph: src='%s' ctl='%s' sink='%s'", + ge->src, ge->ctl, ge->sink); + bin += sizeof(*g); + size -= sizeof(*g); +diff --git a/src/topology/data.c b/src/topology/data.c +index 64563920..0b513428 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -1604,7 +1604,7 @@ int tplg_decode_manifest_data(snd_tplg_t *tplg, + if (!elem) + return -ENOMEM; + +- tplg_dv(tplg, pos, "manifest: private size %d", size); ++ tplg_log(tplg, 'D', pos, "manifest: private size %d", size); + return tplg_add_data(tplg, elem, bin, size); + } + +@@ -1664,7 +1664,7 @@ static int tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos, + + va = bin; + if (size < sizeof(*va) || size < va->size) { +- tplg_dv(tplg, pos, "tuple set verify: wrong size %d", size); ++ tplg_log(tplg, 'A', pos, "tuple set verify: wrong size %d", size); + return -EINVAL; + } + +@@ -1677,20 +1677,20 @@ static int tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos, + case SND_SOC_TPLG_TUPLE_TYPE_SHORT: + break; + default: +- tplg_dv(tplg, pos, "tuple set verify: unknown array type %d", va->type); ++ tplg_log(tplg, 'A', pos, "tuple set verify: unknown array type %d", va->type); + return -EINVAL; + } + + j = tplg_get_tuple_size(va->type) * va->num_elems; + if (j + sizeof(*va) != va->size) { +- tplg_dv(tplg, pos, "tuple set verify: wrong vendor array size %d " +- "(expected %d for %d count %d)", +- va->size, j + sizeof(*va), va->type, va->num_elems); ++ tplg_log(tplg, 'A', pos, "tuple set verify: wrong vendor array size %d " ++ "(expected %d for %d count %d)", ++ va->size, j + sizeof(*va), va->type, va->num_elems); + return -EINVAL; + } + + if (va->num_elems > 4096) { +- tplg_dv(tplg, pos, "tuple set verify: tuples overflow %d", va->num_elems); ++ tplg_log(tplg, 'A', pos, "tuple set verify: tuples overflow %d", va->num_elems); + return -EINVAL; + } + +@@ -1748,8 +1748,8 @@ static int tplg_decode_tuple_set(snd_tplg_t *tplg, + set->type = va->type; + set->num_tuples = va->num_elems; + +- tplg_dv(tplg, pos, "tuple set: type %d (%s) tuples %d size %d", set->type, +- get_tuple_type_name(set->type), set->num_tuples, va->size); ++ tplg_log(tplg, 'A', pos, "tuple set: type %d (%s) tuples %d size %d", set->type, ++ get_tuple_type_name(set->type), set->num_tuples, va->size); + for (j = 0; j < set->num_tuples; j++) { + tuple = &set->tuple[j]; + switch (va->type) { +@@ -1798,14 +1798,14 @@ static int tplg_verify_tuples(snd_tplg_t *tplg, size_t pos, + int err; + + if (size < sizeof(*va)) { +- tplg_dv(tplg, pos, "tuples: small size %d", size); ++ tplg_log(tplg, 'A', pos, "tuples: small size %d", size); + return -EINVAL; + } + + next: + va = bin; + if (size < sizeof(*va)) { +- tplg_dv(tplg, pos, "tuples: unexpected vendor arry size %d", size); ++ tplg_log(tplg, 'A', pos, "tuples: unexpected vendor arry size %d", size); + return -EINVAL; + } + +@@ -1903,7 +1903,7 @@ next: + return err; + tuples = NULL; + } +- tplg_dv(tplg, pos, "add bytes: size %d", tp->size); ++ tplg_log(tplg, 'A', pos, "add bytes: size %d", tp->size); + snprintf(suffix, sizeof(suffix), "data%u", block++); + err = tplg_add_data_bytes(tplg, parent, suffix, tp->array, tp->size); + } else { +@@ -1929,7 +1929,7 @@ next: + return -ENOMEM; + } + } +- tplg_dv(tplg, pos, "decode tuples: size %d", tp->size); ++ tplg_log(tplg, 'A', pos, "decode tuples: size %d", tp->size); + err = tplg_decode_tuples(tplg, pos, parent, tuples, tp->array, tp->size); + num_tuples++; + } +diff --git a/src/topology/decoder.c b/src/topology/decoder.c +index 2d6a8969..66ebe5d8 100644 +--- a/src/topology/decoder.c ++++ b/src/topology/decoder.c +@@ -18,21 +18,6 @@ + #include "list.h" + #include "tplg_local.h" + +-/* verbose output detailing each object size and file position */ +-void tplg_dv(snd_tplg_t *tplg, size_t pos, const char *fmt, ...) +-{ +- va_list va; +- +- if (!tplg->verbose) +- return; +- +- va_start(va, fmt); +- fprintf(stdout, "D0x%6.6zx/%6.6zd - ", pos, pos); +- vfprintf(stdout, fmt, va); +- va_end(va); +- putc('\n', stdout); +-} +- + int tplg_decode_template(snd_tplg_t *tplg, + size_t pos, + struct snd_soc_tplg_hdr *hdr, +@@ -41,7 +26,8 @@ int tplg_decode_template(snd_tplg_t *tplg, + int type; + + type = tplg_get_type(hdr->type); +- tplg_dv(tplg, pos, "template: asoc type %d library type %d", hdr->type, type); ++ tplg_log(tplg, 'D', pos, "template: asoc type %d library type %d", ++ hdr->type, type); + if (type < 0) + return type; + +@@ -50,8 +36,8 @@ int tplg_decode_template(snd_tplg_t *tplg, + t->index = hdr->index; + t->version = hdr->version; + t->vendor_type = hdr->vendor_type; +- tplg_dv(tplg, pos, "template: index %d version %d vendor_type %d", +- hdr->index, hdr->version, hdr->vendor_type); ++ tplg_log(tplg, 'D', pos, "template: index %d version %d vendor_type %d", ++ hdr->index, hdr->version, hdr->vendor_type); + return 0; + } + +@@ -71,11 +57,11 @@ int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags) + while (1) { + pos = b - bin; + if (size == pos) { +- tplg_dv(tplg, pos, "block: success (total %zd)", size); ++ tplg_log(tplg, 'D', pos, "block: success (total %zd)", size); + return 0; + } + if (size - pos < sizeof(*hdr)) { +- tplg_dv(tplg, pos, "block: small size"); ++ tplg_log(tplg, 'D', pos, "block: small size"); + SNDERR("incomplete header data to decode"); + return -EINVAL; + } +@@ -85,8 +71,8 @@ int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags) + return -EINVAL; + } + +- tplg_dv(tplg, pos, "block: abi %d size %d payload size %d", +- hdr->abi, hdr->size, hdr->payload_size); ++ tplg_log(tplg, 'D', pos, "block: abi %d size %d payload size %d", ++ hdr->abi, hdr->size, hdr->payload_size); + if (hdr->abi != SND_SOC_TPLG_ABI_VERSION) { + SNDERR("unsupported ABI version %d", hdr->abi); + return -EINVAL; +@@ -127,7 +113,7 @@ int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags) + SNDERR("unknown block type %d", hdr->type); + return -EINVAL; + } +- tplg_dv(tplg, pos, "block: type %d - %s", hdr->type, tptr->name); ++ tplg_log(tplg, 'D', pos, "block: type %d - %s", hdr->type, tptr->name); + err = tptr->decod(tplg, pos, hdr, b + hdr->size, hdr->payload_size); + if (err < 0) + return err; +diff --git a/src/topology/log.c b/src/topology/log.c +new file mode 100644 +index 00000000..1ca36528 +--- /dev/null ++++ b/src/topology/log.c +@@ -0,0 +1,34 @@ ++/* ++ Copyright (c) 2019 Red Hat Inc. ++ All rights reserved. ++ ++ This library is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of ++ the License, or (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ Authors: Jaroslav Kysela ++*/ ++ ++#include "list.h" ++#include "tplg_local.h" ++ ++/* verbose output detailing each object size and file position */ ++void tplg_log_(snd_tplg_t *tplg, char type, size_t pos, const char *fmt, ...) ++{ ++ va_list va; ++ ++ if (!tplg->verbose) ++ return; ++ ++ va_start(va, fmt); ++ fprintf(stdout, "%c0x%6.6zx/%6.6zd - ", type, pos, pos); ++ vfprintf(stdout, fmt, va); ++ va_end(va); ++ putc('\n', stdout); ++} +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 4e04a6bc..918e3e9a 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -1969,21 +1969,21 @@ next: + return -EINVAL; + } + +- tplg_dv(tplg, pos, "pcm: size %d private size %d streams %d", +- pcm->size, pcm->priv.size, pcm->num_streams); ++ tplg_log(tplg, 'D', pos, "pcm: size %d private size %d streams %d", ++ pcm->size, pcm->priv.size, pcm->num_streams); + + pt->pcm_name = pcm->pcm_name; +- tplg_dv(tplg, pos, "pcm: pcm_name '%s'", pt->pcm_name); ++ tplg_log(tplg, 'D', pos, "pcm: pcm_name '%s'", pt->pcm_name); + pt->dai_name = pcm->dai_name; +- tplg_dv(tplg, pos, "pcm: dai_name '%s'", pt->dai_name); ++ tplg_log(tplg, 'D', pos, "pcm: dai_name '%s'", pt->dai_name); + pt->pcm_id = pcm->pcm_id; + pt->dai_id = pcm->dai_id; +- tplg_dv(tplg, pos, "pcm: pcm_id %d dai_id %d", pt->pcm_id, pt->dai_id); ++ tplg_log(tplg, 'D', pos, "pcm: pcm_id %d dai_id %d", pt->pcm_id, pt->dai_id); + pt->playback = pcm->playback; + pt->capture = pcm->capture; + pt->compress = pcm->compress; +- tplg_dv(tplg, pos, "pcm: playback %d capture %d compress", +- pt->playback, pt->capture, pt->compress); ++ tplg_log(tplg, 'D', pos, "pcm: playback %d capture %d compress", ++ pt->playback, pt->capture, pt->compress); + pt->num_streams = pcm->num_streams; + pt->flag_mask = pcm->flag_mask; + pt->flags = pcm->flags; +@@ -1995,8 +1995,8 @@ next: + return -EINVAL; + } + stream->name = pcm->stream[i].name; +- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, stream[i]), +- "stream %d: '%s'", i, stream->name); ++ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_pcm, stream[i]), ++ "stream %d: '%s'", i, stream->name); + stream->format = pcm->stream[i].format; + stream->rate = pcm->stream[i].rate; + stream->period_bytes = pcm->stream[i].period_bytes; +@@ -2016,8 +2016,8 @@ next: + return -EINVAL; + } + cap->name = pcm->caps[i].name; +- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, caps[i]), +- "caps %d: '%s'", i, cap->name); ++ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_pcm, caps[i]), ++ "caps %d: '%s'", i, cap->name); + cap->formats = pcm->caps[i].formats; + cap->rates = pcm->caps[i].rates; + cap->rate_min = pcm->caps[i].rate_min; +@@ -2033,8 +2033,8 @@ next: + cap->sig_bits = pcm->caps[i].sig_bits; + } + +- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, priv), +- "pcm: private start"); ++ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_pcm, priv), ++ "pcm: private start"); + pt->priv = &pcm->priv; + + bin += sizeof(*pcm) + pcm->priv.size; +@@ -2120,16 +2120,16 @@ next: + return -EINVAL; + } + +- tplg_dv(tplg, pos, "link: size %d private size %d streams %d " +- "hw_configs %d", +- link->size, link->priv.size, link->num_streams, +- link->num_hw_configs); ++ tplg_log(tplg, 'D', pos, "link: size %d private size %d streams %d " ++ "hw_configs %d", ++ link->size, link->priv.size, link->num_streams, ++ link->num_hw_configs); + + lt.id = link->id; + lt.name = link->name; +- tplg_dv(tplg, pos, "link: name '%s'", lt.name); ++ tplg_log(tplg, 'D', pos, "link: name '%s'", lt.name); + lt.stream_name = link->stream_name; +- tplg_dv(tplg, pos, "link: stream_name '%s'", lt.stream_name); ++ tplg_log(tplg, 'D', pos, "link: stream_name '%s'", lt.stream_name); + lt.num_streams = link->num_streams; + lt.num_hw_configs = link->num_hw_configs; + lt.default_hw_config_id = link->default_hw_config_id; +@@ -2143,9 +2143,9 @@ next: + return -EINVAL; + } + stream->name = link->stream[i].name; +- tplg_dv(tplg, +- pos + offsetof(struct snd_soc_tplg_link_config, stream[i]), +- "stream %d: '%s'", i, stream->name); ++ tplg_log(tplg, 'D', ++ pos + offsetof(struct snd_soc_tplg_link_config, stream[i]), ++ "stream %d: '%s'", i, stream->name); + stream->format = link->stream[i].format; + stream->rate = link->stream[i].rate; + stream->period_bytes = link->stream[i].period_bytes; +@@ -2192,8 +2192,8 @@ next: + } + lt.hw_config = hws; + +- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, priv), +- "link: private start"); ++ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_pcm, priv), ++ "link: private start"); + lt.priv = &link->priv; + + bin += sizeof(*link) + link->priv.size; +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 22fc5fba..e061db75 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -226,6 +226,13 @@ struct tplg_table { + extern struct tplg_table tplg_table[]; + extern unsigned int tplg_table_items; + ++#define tplg_log(tplg, type, pos, fmt, args...) do { \ ++ if ((tplg)->verbose) \ ++ tplg_log_((tplg), (type), (pos), (fmt), ##args); \ ++} while (0) ++ ++void tplg_log_(snd_tplg_t *tplg, char type, size_t pos, const char *fmt, ...); ++ + void *tplg_calloc(struct list_head *heap, size_t size); + void tplg_free(struct list_head *heap); + +@@ -373,7 +380,6 @@ int tplg_save_stream_caps(snd_tplg_t *tplg, struct tplg_elem *elem, + int tplg_save_dai(snd_tplg_t *tplg, struct tplg_elem *elem, + char **dst, const char *pfx); + +-void tplg_dv(snd_tplg_t *tplg, size_t pos, const char *fmt, ...); + int tplg_decode_template(snd_tplg_t *tplg, + size_t pos, + struct snd_soc_tplg_hdr *hdr, +-- +2.24.1 + + +From d768da27e7f9f56328c61ed5d37c17ce075cbc6e Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 3 Jan 2020 22:44:15 +0100 +Subject: [PATCH 56/69] topology: tplg_dbg() cleanups + +- remove newline at the end + +Signed-off-by: Jaroslav Kysela +--- + src/topology/channel.c | 6 +++--- + src/topology/ctl.c | 40 +++++++++++++++++------------------ + src/topology/dapm.c | 32 ++++++++++++++-------------- + src/topology/data.c | 48 ++++++++++++++++++++++++------------------ + src/topology/ops.c | 8 +++---- + src/topology/pcm.c | 36 +++++++++++++++---------------- + src/topology/text.c | 6 +++--- + 7 files changed, 91 insertions(+), 85 deletions(-) + +diff --git a/src/topology/channel.c b/src/topology/channel.c +index 390c3f16..47d5ea4c 100644 +--- a/src/topology/channel.c ++++ b/src/topology/channel.c +@@ -100,7 +100,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + + channel += tplg->channel_idx; + snd_config_get_id(cfg, &id); +- tplg_dbg("\tChannel %s at index %d\n", id, tplg->channel_idx); ++ tplg_dbg("\tChannel %s at index %d", id, tplg->channel_idx); + + channel_id = lookup_channel(id); + if (channel_id < 0) { +@@ -110,7 +110,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + + channel->id = channel_id; + channel->size = sizeof(*channel); +- tplg_dbg("\tChan %s = %d\n", id, channel->id); ++ tplg_dbg("\tChan %s = %d", id, channel->id); + + snd_config_for_each(i, next, cfg) { + +@@ -129,7 +129,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, + else if (strcmp(id, "shift") == 0) + channel->shift = value; + +- tplg_dbg("\t\t%s = %d\n", id, value); ++ tplg_dbg("\t\t%s = %d", id, value); + } + + tplg->channel_idx++; +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index a5a81148..41dc2ddb 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -54,7 +54,7 @@ static int parse_access_values(snd_config_t *cfg, + const char *value = NULL; + unsigned int j; + +- tplg_dbg(" Access:\n"); ++ tplg_dbg(" Access:"); + + snd_config_for_each(i, next, cfg) { + n = snd_config_iterator_entry(i); +@@ -67,7 +67,7 @@ static int parse_access_values(snd_config_t *cfg, + for (j = 0; j < ARRAY_SIZE(ctl_access); j++) { + if (strcmp(value, ctl_access[j].name) == 0) { + hdr->access |= ctl_access[j].value; +- tplg_dbg("\t%s\n", value); ++ tplg_dbg("\t%s", value); + break; + } + } +@@ -150,7 +150,7 @@ static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref) + struct snd_soc_tplg_mixer_control *mixer_ctrl = elem->mixer_ctrl; + struct snd_soc_tplg_ctl_tlv *tlv = ref->tlv; + +- tplg_dbg("TLV '%s' used by '%s\n", ref->id, elem->id); ++ tplg_dbg("TLV '%s' used by '%s", ref->id, elem->id); + + /* TLV has a fixed size */ + mixer_ctrl->hdr.tlv = *tlv; +@@ -330,7 +330,7 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem) + const char *id = NULL; + int val; + +- tplg_dbg(" scale: %s\n", elem->id); ++ tplg_dbg(" scale: %s", elem->id); + + tplg_tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv); + tplg_tlv->type = SNDRV_CTL_TLVT_DB_SCALE; +@@ -348,7 +348,7 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem) + if (tplg_get_integer(n, &val, 0)) + continue; + +- tplg_dbg("\t%s = %i\n", id, val); ++ tplg_dbg("\t%s = %i", id, val); + + /* get TLV data */ + if (strcmp(id, "min") == 0) +@@ -450,7 +450,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + snd_strlcpy(be->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + be->hdr.type = SND_SOC_TPLG_TYPE_BYTES; + +- tplg_dbg(" Control Bytes: %s\n", elem->id); ++ tplg_dbg(" Control Bytes: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + n = snd_config_iterator_entry(i); +@@ -468,7 +468,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + return -EINVAL; + + be->base = ival; +- tplg_dbg("\t%s: %d\n", id, be->base); ++ tplg_dbg("\t%s: %d", id, be->base); + continue; + } + +@@ -477,7 +477,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + return -EINVAL; + + be->num_regs = ival; +- tplg_dbg("\t%s: %d\n", id, be->num_regs); ++ tplg_dbg("\t%s: %d", id, be->num_regs); + continue; + } + +@@ -486,7 +486,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + return -EINVAL; + + be->max = ival; +- tplg_dbg("\t%s: %d\n", id, be->max); ++ tplg_dbg("\t%s: %d", id, be->max); + continue; + } + +@@ -495,7 +495,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + return -EINVAL; + + be->mask = ival; +- tplg_dbg("\t%s: %d\n", id, be->mask); ++ tplg_dbg("\t%s: %d", id, be->mask); + continue; + } + +@@ -515,7 +515,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, + return err; + + tlv_set = true; +- tplg_dbg("\t%s: %s\n", id, val); ++ tplg_dbg("\t%s: %s", id, val); + continue; + } + +@@ -625,7 +625,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, + ec->channel[j].reg = -1; + } + +- tplg_dbg(" Control Enum: %s\n", elem->id); ++ tplg_dbg(" Control Enum: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + +@@ -644,7 +644,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, + return -EINVAL; + + tplg_ref_add(elem, SND_TPLG_TYPE_TEXT, val); +- tplg_dbg("\t%s: %s\n", id, val); ++ tplg_dbg("\t%s: %s", id, val); + continue; + } + +@@ -761,7 +761,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++) + mc->channel[j].reg = -1; + +- tplg_dbg(" Control Mixer: %s\n", elem->id); ++ tplg_dbg(" Control Mixer: %s", elem->id); + + /* giterate trough each mixer elment */ + snd_config_for_each(i, next, cfg) { +@@ -795,7 +795,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + return -EINVAL; + + mc->max = ival; +- tplg_dbg("\t%s: %d\n", id, mc->max); ++ tplg_dbg("\t%s: %d", id, mc->max); + continue; + } + +@@ -805,7 +805,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + return -EINVAL; + mc->invert = ival; + +- tplg_dbg("\t%s: %d\n", id, mc->invert); ++ tplg_dbg("\t%s: %d", id, mc->invert); + continue; + } + +@@ -826,7 +826,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, + return err; + + tlv_set = true; +- tplg_dbg("\t%s: %s\n", id, val); ++ tplg_dbg("\t%s: %s", id, val); + continue; + } + +@@ -981,7 +981,7 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer, + struct tplg_elem *elem; + int ret, i, num_channels; + +- tplg_dbg(" Control Mixer: %s\n", mixer->hdr.name); ++ tplg_dbg(" Control Mixer: %s", mixer->hdr.name); + + if (mixer->hdr.type != SND_SOC_TPLG_TYPE_MIXER) { + SNDERR("invalid mixer type %d", mixer->hdr.type); +@@ -1045,7 +1045,7 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, + struct tplg_elem *elem; + int ret, i, num_items, num_channels; + +- tplg_dbg(" Control Enum: %s\n", enum_ctl->hdr.name); ++ tplg_dbg(" Control Enum: %s", enum_ctl->hdr.name); + + if (enum_ctl->hdr.type != SND_SOC_TPLG_TYPE_ENUM) { + SNDERR("invalid enum type %d", enum_ctl->hdr.type); +@@ -1128,7 +1128,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl, + struct tplg_elem *elem; + int ret; + +- tplg_dbg(" Control Bytes: %s\n", bytes_ctl->hdr.name); ++ tplg_dbg(" Control Bytes: %s", bytes_ctl->hdr.name); + + if (bytes_ctl->hdr.type != SND_SOC_TPLG_TYPE_BYTES) { + SNDERR("invalid bytes type %d", bytes_ctl->hdr.type); +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index 0bf64833..cb85e667 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -76,8 +76,8 @@ static int copy_dapm_control(struct tplg_elem *elem, struct tplg_elem *ref) + { + struct snd_soc_tplg_dapm_widget *widget = elem->widget; + +- tplg_dbg("Control '%s' used by '%s'\n", ref->id, elem->id); +- tplg_dbg("\tparent size: %d + %d -> %d, priv size -> %d\n", ++ tplg_dbg("Control '%s' used by '%s'", ref->id, elem->id); ++ tplg_dbg("\tparent size: %d + %d -> %d, priv size -> %d", + elem->size, ref->size, elem->size + ref->size, + widget->priv.size); + +@@ -210,8 +210,8 @@ int tplg_build_routes(snd_tplg_t *tplg) + } + + route = elem->route; +- tplg_dbg("\nCheck route: sink '%s', control '%s', source '%s'\n", +- route->sink, route->control, route->source); ++ tplg_dbg("Check route: sink '%s', control '%s', source '%s'", ++ route->sink, route->control, route->source); + + /* validate sink */ + if (strlen(route->sink) <= 0) { +@@ -357,7 +357,7 @@ static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t *cfg, int index) + if (err < 0) + return err; + +- tplg_dbg("route: sink '%s', control '%s', source '%s'\n", ++ tplg_dbg("route: sink '%s', control '%s', source '%s'", + line->sink, line->control, line->source); + } + +@@ -520,7 +520,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + if (!elem) + return -ENOMEM; + +- tplg_dbg(" Widget: %s\n", elem->id); ++ tplg_dbg(" Widget: %s", elem->id); + + widget = elem->widget; + snd_strlcpy(widget->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); +@@ -550,7 +550,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + } + + widget->id = widget_type; +- tplg_dbg("\t%s: %s\n", id, val); ++ tplg_dbg("\t%s: %s", id, val); + continue; + } + +@@ -560,7 +560,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + + snd_strlcpy(widget->sname, val, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); +- tplg_dbg("\t%s: %s\n", id, val); ++ tplg_dbg("\t%s: %s", id, val); + continue; + } + +@@ -571,7 +571,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + + widget->reg = ival ? -1 : 0; + +- tplg_dbg("\t%s: %s\n", id, val); ++ tplg_dbg("\t%s: %s", id, val); + continue; + } + +@@ -580,7 +580,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + return -EINVAL; + + widget->shift = ival; +- tplg_dbg("\t%s: %d\n", id, widget->shift); ++ tplg_dbg("\t%s: %d", id, widget->shift); + continue; + } + +@@ -589,7 +589,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + return -EINVAL; + + widget->reg = ival; +- tplg_dbg("\t%s: %d\n", id, widget->reg); ++ tplg_dbg("\t%s: %d", id, widget->reg); + continue; + } + +@@ -598,7 +598,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + return -EINVAL; + + widget->invert = ival; +- tplg_dbg("\t%s: %d\n", id, widget->invert); ++ tplg_dbg("\t%s: %d", id, widget->invert); + continue; + } + +@@ -607,7 +607,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + return -EINVAL; + + widget->subseq = ival; +- tplg_dbg("\t%s: %d\n", id, widget->subseq); ++ tplg_dbg("\t%s: %d", id, widget->subseq); + continue; + } + +@@ -616,7 +616,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + return -EINVAL; + + widget->event_type = ival; +- tplg_dbg("\t%s: %d\n", id, widget->event_type); ++ tplg_dbg("\t%s: %d", id, widget->event_type); + continue; + } + +@@ -625,7 +625,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, + return -EINVAL; + + widget->event_flags = ival; +- tplg_dbg("\t%s: %d\n", id, widget->event_flags); ++ tplg_dbg("\t%s: %d", id, widget->event_flags); + continue; + } + +@@ -767,7 +767,7 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + struct tplg_elem *elem; + int i, ret = 0; + +- tplg_dbg("Widget: %s\n", wt->name); ++ tplg_dbg("Widget: %s", wt->name); + + elem = tplg_elem_new_common(tplg, NULL, wt->name, + SND_TPLG_TYPE_DAPM_WIDGET); +diff --git a/src/topology/data.c b/src/topology/data.c +index 0b513428..37c45919 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -87,7 +87,7 @@ int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem, + if (snd_config_get_string(cfg, &val) < 0) + return -EINVAL; + +- tplg_dbg("\tref data: %s\n", val); ++ tplg_dbg("\tref data: %s", val); + err = tplg_ref_add(elem, type, val); + if (err < 0) + return err; +@@ -108,7 +108,7 @@ int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem, + if (snd_config_get_string(n, &val) < 0) + continue; + +- tplg_dbg("\tref data: %s\n", val); ++ tplg_dbg("\tref data: %s", val); + err = tplg_ref_add(elem, type, val); + if (err < 0) + return err; +@@ -169,7 +169,7 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem) + size_t size, bytes_read; + int ret = 0; + +- tplg_dbg("data DataFile: %s\n", elem->id); ++ tplg_dbg("data DataFile: %s", elem->id); + + if (snd_config_get_string(cfg, &value) < 0) + return -EINVAL; +@@ -235,19 +235,25 @@ static void dump_priv_data(struct tplg_elem *elem ATTRIBUTE_UNUSED) + #ifdef TPLG_DEBUG + struct snd_soc_tplg_private *priv = elem->data; + unsigned char *p = (unsigned char *)priv->data; ++ char buf[128], buf2[8]; + unsigned int i; + +- tplg_dbg(" elem size = %d, priv data size = %d\n", ++ tplg_dbg(" elem size = %d, priv data size = %d", + elem->size, priv->size); + ++ buf[0] = '\0'; + for (i = 0; i < priv->size; i++) { +- if (i > 0 && (i % 16) == 0) +- tplg_dbg("\n"); ++ if (i > 0 && (i % 16) == 0) { ++ tplg_dbg("%s", buf); ++ buf[0] = '\0'; ++ } + +- tplg_dbg(" %02x:", *p++); ++ snprintf(buf2, sizeof(buf2), " %02x", *p++); ++ strcat(buf, buf2); + } + +- tplg_dbg("\n\n"); ++ if (buf[0]) ++ tplg_dbg("%s", buf); + #endif + } + +@@ -466,7 +472,7 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, + int size, esize, off, num; + int ret; + +- tplg_dbg(" data: %s\n", elem->id); ++ tplg_dbg(" data: %s", elem->id); + + if (snd_config_get_string(cfg, &value) < 0) + return -EINVAL; +@@ -683,7 +689,7 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem) + if (ref->type != SND_TPLG_TYPE_TUPLE) + continue; + +- tplg_dbg("tuples '%s' used by data '%s'\n", ref->id, elem->id); ++ tplg_dbg("tuples '%s' used by data '%s'", ref->id, elem->id); + + if (!ref->elem) + ref->elem = tplg_elem_lookup(&tplg->tuple_list, +@@ -799,7 +805,7 @@ static int parse_tuple_set(snd_config_t *cfg, + if (!num_tuples) + return 0; + +- tplg_dbg("\t %d %s tuples:\n", num_tuples, id); ++ tplg_dbg("\t %d %s tuples:", num_tuples, id); + set = calloc(1, sizeof(*set) + num_tuples * sizeof(struct tplg_tuple)); + if (!set) + return -ENOMEM; +@@ -831,7 +837,7 @@ static int parse_tuple_set(snd_config_t *cfg, + continue; + snd_strlcpy(tuple->string, value, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); +- tplg_dbg("\t\t%s = %s\n", tuple->token, tuple->string); ++ tplg_dbg("\t\t%s = %s", tuple->token, tuple->string); + break; + + case SND_SOC_TPLG_TUPLE_TYPE_BOOL: +@@ -839,7 +845,7 @@ static int parse_tuple_set(snd_config_t *cfg, + if (ival < 0) + continue; + tuple->value = ival; +- tplg_dbg("\t\t%s = %d\n", tuple->token, tuple->value); ++ tplg_dbg("\t\t%s = %d", tuple->token, tuple->value); + break; + + case SND_SOC_TPLG_TUPLE_TYPE_BYTE: +@@ -862,7 +868,7 @@ static int parse_tuple_set(snd_config_t *cfg, + } + + tuple->value = tuple_val; +- tplg_dbg("\t\t%s = 0x%x\n", tuple->token, tuple->value); ++ tplg_dbg("\t\t%s = 0x%x", tuple->token, tuple->value); + break; + + default: +@@ -1047,7 +1053,7 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, + if (!num_tokens) + return 0; + +- tplg_dbg(" Vendor tokens: %s, %d tokens\n", elem->id, num_tokens); ++ tplg_dbg(" Vendor tokens: %s, %d tokens", elem->id, num_tokens); + + tokens = calloc(1, sizeof(*tokens) + + num_tokens * sizeof(struct tplg_token)); +@@ -1067,7 +1073,7 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, + snd_strlcpy(tokens->token[tokens->num_tokens].id, id, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + tokens->token[tokens->num_tokens].value = value; +- tplg_dbg("\t\t %s : %d\n", tokens->token[tokens->num_tokens].id, ++ tplg_dbg("\t\t %s : %d", tokens->token[tokens->num_tokens].id, + tokens->token[tokens->num_tokens].value); + tokens->num_tokens++; + } +@@ -1116,7 +1122,7 @@ int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, + if (!elem) + return -ENOMEM; + +- tplg_dbg(" Vendor Tuples: %s\n", elem->id); ++ tplg_dbg(" Vendor Tuples: %s", elem->id); + + tuples = calloc(1, sizeof(*tuples)); + if (!tuples) +@@ -1133,7 +1139,7 @@ int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, + if (snd_config_get_string(n, &value) < 0) + return -EINVAL; + tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, value); +- tplg_dbg("\t refer to vendor tokens: %s\n", value); ++ tplg_dbg("\t refer to vendor tokens: %s", value); + } + + if (strcmp(id, "tuples") == 0) { +@@ -1208,7 +1214,7 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, + manifest = elem->manifest; + manifest->size = elem->size; + +- tplg_dbg(" Manifest: %s\n", elem->id); ++ tplg_dbg(" Manifest: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + n = snd_config_iterator_entry(i); +@@ -1402,7 +1408,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, + return -EINVAL; + + elem->vendor_type = ival; +- tplg_dbg("\t%s: %d\n", id, elem->index); ++ tplg_dbg("\t%s: %d", id, elem->index); + continue; + } + } +@@ -1506,7 +1512,7 @@ int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem, + return -EINVAL; + } + +- tplg_dbg("Data '%s' used by '%s'\n", ref->id, elem->id); ++ tplg_dbg("Data '%s' used by '%s'", ref->id, elem->id); + /* overlook empty private data */ + if (!ref_elem->data || !ref_elem->data->size) { + ref->elem = ref_elem; +diff --git a/src/topology/ops.c b/src/topology/ops.c +index 2885c781..110eef58 100644 +--- a/src/topology/ops.c ++++ b/src/topology/ops.c +@@ -69,7 +69,7 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg, + const char *id, *value; + int ival; + +- tplg_dbg("\tOps\n"); ++ tplg_dbg("\tOps"); + hdr->size = sizeof(*hdr); + + snd_config_for_each(i, next, cfg) { +@@ -97,7 +97,7 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg, + else if (strcmp(id, "get") == 0) + hdr->ops.get = ival; + +- tplg_dbg("\t\t%s = %d\n", id, ival); ++ tplg_dbg("\t\t%s = %d", id, ival); + } + + return 0; +@@ -155,7 +155,7 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + const char *id, *value; + int ival; + +- tplg_dbg("\tExt Ops\n"); ++ tplg_dbg("\tExt Ops"); + + snd_config_for_each(i, next, cfg) { + +@@ -182,7 +182,7 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + else if (strcmp(id, "get") == 0) + be->ext_ops.get = ival; + +- tplg_dbg("\t\t%s = %s\n", id, value); ++ tplg_dbg("\t\t%s = %s", id, value); + } + + return 0; +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 918e3e9a..da88783f 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -68,7 +68,7 @@ static void copy_stream_caps(const char *id ATTRIBUTE_UNUSED, + { + struct snd_soc_tplg_stream_caps *ref_caps = ref_elem->stream_caps; + +- tplg_dbg("Copy pcm caps (%ld bytes) from '%s' to '%s' \n", ++ tplg_dbg("Copy pcm caps (%ld bytes) from '%s' to '%s'", + sizeof(*caps), ref_elem->id, id); + + *caps = *ref_caps; +@@ -388,7 +388,7 @@ static int parse_unsigned(snd_config_t *n, unsigned int *dst) + { + const char *id; + if (snd_config_get_id(n, &id) >= 0) +- tplg_dbg("\t\t%s: %d\n", id, *dst); ++ tplg_dbg("\t\t%s: %d", id, *dst); + } + #endif + return 0; +@@ -415,7 +415,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + sc->size = elem->size; + snd_strlcpy(sc->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + +- tplg_dbg(" PCM Capabilities: %s\n", elem->id); ++ tplg_dbg(" PCM Capabilities: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + n = snd_config_iterator_entry(i); +@@ -442,7 +442,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + if (err < 0) + return err; + +- tplg_dbg("\t\t%s: %s\n", id, val); ++ tplg_dbg("\t\t%s: %s", id, val); + continue; + } + +@@ -460,7 +460,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + if (err < 0) + return err; + +- tplg_dbg("\t\t%s: %s\n", id, val); ++ tplg_dbg("\t\t%s: %s", id, val); + continue; + } + +@@ -625,7 +625,7 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + + snd_config_get_id(cfg, &id); + +- tplg_dbg("\t%s:\n", id); ++ tplg_dbg("\t%s:", id); + + switch (elem->type) { + case SND_TPLG_TYPE_PCM: +@@ -672,7 +672,7 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + snd_strlcpy(caps[stream].name, value, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + +- tplg_dbg("\t\t%s\n\t\t\t%s\n", id, value); ++ tplg_dbg("\t\t%s\n\t\t\t%s", id, value); + continue; + } + } +@@ -746,7 +746,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + const char *id; + + snd_config_get_id(cfg, &id); +- tplg_dbg("\t\tFE DAI %s:\n", id); ++ tplg_dbg("\t\tFE DAI %s:", id); + snd_strlcpy(pcm->dai_name, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + + snd_config_for_each(i, next, cfg) { +@@ -763,7 +763,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + return -EINVAL; + } + +- tplg_dbg("\t\t\tindex: %d\n", pcm->dai_id); ++ tplg_dbg("\t\t\tindex: %d", pcm->dai_id); + } + } + +@@ -847,7 +847,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, + pcm->size = elem->size; + snd_strlcpy(pcm->pcm_name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + +- tplg_dbg(" PCM: %s\n", elem->id); ++ tplg_dbg(" PCM: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + +@@ -882,7 +882,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, + + pcm->compress = ival; + +- tplg_dbg("\t%s: %d\n", id, ival); ++ tplg_dbg("\t%s: %d", id, ival); + continue; + } + +@@ -988,7 +988,7 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, + snd_strlcpy(dai->dai_name, elem->id, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + +- tplg_dbg(" DAI: %s\n", elem->id); ++ tplg_dbg(" DAI: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + +@@ -1142,7 +1142,7 @@ int tplg_parse_link(snd_tplg_t *tplg, + link->size = elem->size; + snd_strlcpy(link->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + +- tplg_dbg(" Link: %s\n", elem->id); ++ tplg_dbg(" Link: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + +@@ -1168,7 +1168,7 @@ int tplg_parse_link(snd_tplg_t *tplg, + + snd_strlcpy(link->stream_name, val, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); +- tplg_dbg("\t%s: %s\n", id, val); ++ tplg_dbg("\t%s: %s", id, val); + continue; + } + +@@ -1280,7 +1280,7 @@ int tplg_parse_cc(snd_tplg_t *tplg, + link = elem->link; + link->size = elem->size; + +- tplg_dbg(" CC: %s\n", elem->id); ++ tplg_dbg(" CC: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + +@@ -1412,7 +1412,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + hw_cfg = elem->hw_cfg; + hw_cfg->size = elem->size; + +- tplg_dbg(" Link HW config: %s\n", elem->id); ++ tplg_dbg(" Link HW config: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + +@@ -1719,7 +1719,7 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + struct tplg_elem *elem; + int ret, i; + +- tplg_dbg("PCM: %s, DAI %s\n", pcm_tpl->pcm_name, pcm_tpl->dai_name); ++ tplg_dbg("PCM: %s, DAI %s", pcm_tpl->pcm_name, pcm_tpl->dai_name); + + if (pcm_tpl->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX) + return -EINVAL; +@@ -1881,7 +1881,7 @@ int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + struct tplg_elem *elem; + int ret, i; + +- tplg_dbg("DAI %s\n", dai_tpl->dai_name); ++ tplg_dbg("DAI %s", dai_tpl->dai_name); + + elem = tplg_elem_new_common(tplg, NULL, dai_tpl->dai_name, + SND_TPLG_TYPE_DAI); +diff --git a/src/topology/text.c b/src/topology/text.c +index 6dbf2230..507c5450 100644 +--- a/src/topology/text.c ++++ b/src/topology/text.c +@@ -32,13 +32,13 @@ static int parse_text_values(snd_config_t *cfg, struct tplg_elem *elem) + const char *value = NULL; + int j = 0; + +- tplg_dbg(" Text Values: %s\n", elem->id); ++ tplg_dbg(" Text Values: %s", elem->id); + + snd_config_for_each(i, next, cfg) { + n = snd_config_iterator_entry(i); + + if (j == SND_SOC_TPLG_NUM_TEXTS) { +- tplg_dbg("text string number exceeds %d\n", j); ++ tplg_dbg("text string number exceeds %d", j); + return -ENOMEM; + } + +@@ -48,7 +48,7 @@ static int parse_text_values(snd_config_t *cfg, struct tplg_elem *elem) + + snd_strlcpy(&texts->items[j][0], value, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); +- tplg_dbg("\t%s\n", &texts->items[j][0]); ++ tplg_dbg("\t%s", &texts->items[j][0]); + + j++; + } +-- +2.24.1 + + +From b20b400e2f598c86abaf697d66396cecd49b3e14 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 3 Jan 2020 22:56:48 +0100 +Subject: [PATCH 57/69] topology: cosmetic changes (functions) + +Signed-off-by: Jaroslav Kysela +--- + src/topology/builder.c | 3 ++- + src/topology/ctl.c | 5 +++-- + src/topology/data.c | 17 +++++++++-------- + src/topology/parser.c | 4 ++-- + src/topology/pcm.c | 16 ++++++++-------- + 5 files changed, 24 insertions(+), 21 deletions(-) + +diff --git a/src/topology/builder.c b/src/topology/builder.c +index 7af5de08..15757668 100644 +--- a/src/topology/builder.c ++++ b/src/topology/builder.c +@@ -71,7 +71,8 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type, + } + + static int write_elem_block(snd_tplg_t *tplg, +- struct list_head *base, size_t 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; +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index 41dc2ddb..b78f1c54 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -600,7 +600,7 @@ int tplg_save_control_bytes(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + + /* Parse Control Enums. */ + int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED) ++ void *private ATTRIBUTE_UNUSED) + { + struct snd_soc_tplg_enum_control *ec; + struct tplg_elem *elem; +@@ -736,7 +736,8 @@ int tplg_save_control_enum(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + * Mixer control. Supports multiple channels. + */ + int tplg_parse_control_mixer(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) ++ snd_config_t *cfg, ++ void *private ATTRIBUTE_UNUSED) + { + struct snd_soc_tplg_mixer_control *mc; + struct tplg_elem *elem; +diff --git a/src/topology/data.c b/src/topology/data.c +index 37c45919..b63e98cd 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -516,7 +516,7 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, + + /* get the token integer value from its id */ + static int get_token_value(const char *token_id, +- struct tplg_vendor_tokens *tokens) ++ struct tplg_vendor_tokens *tokens) + { + unsigned int i; + +@@ -589,7 +589,8 @@ unsigned int tplg_get_tuple_size(int type) + + /* Add a tuples object to the private buffer of its parent data element */ + static int copy_tuples(struct tplg_elem *elem, +- struct tplg_vendor_tuples *tuples, struct tplg_vendor_tokens *tokens) ++ struct tplg_vendor_tuples *tuples, ++ struct tplg_vendor_tokens *tokens) + { + struct snd_soc_tplg_private *priv = elem->data, *priv2; + struct tplg_tuple_set *tuple_set; +@@ -781,7 +782,7 @@ static const char *get_tuple_type_name(unsigned int type) + } + + static int parse_tuple_set(snd_config_t *cfg, +- struct tplg_tuple_set **s) ++ struct tplg_tuple_set **s) + { + snd_config_iterator_t i, next; + snd_config_t *n; +@@ -965,7 +966,7 @@ static int tplg_save_tuple_set(struct tplg_vendor_tuples *tuples, + } + + static int parse_tuple_sets(snd_config_t *cfg, +- struct tplg_vendor_tuples *tuples) ++ struct tplg_vendor_tuples *tuples) + { + snd_config_iterator_t i, next; + snd_config_t *n; +@@ -1033,7 +1034,7 @@ int tplg_save_tuple_sets(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + /* Parse vendor tokens + */ + int tplg_parse_tokens(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; +@@ -1109,7 +1110,7 @@ int tplg_save_tokens(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + /* Parse vendor tuples. + */ + int tplg_parse_tuples(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; +@@ -1193,7 +1194,7 @@ void tplg_free_tuples(void *obj) + /* Parse manifest's data references + */ + int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, +- void *private ATTRIBUTE_UNUSED) ++ void *private ATTRIBUTE_UNUSED) + { + struct snd_soc_tplg_manifest *manifest; + struct tplg_elem *elem; +@@ -1341,7 +1342,7 @@ int tplg_build_manifest_data(snd_tplg_t *tplg) + * words, tuples. + */ + int tplg_parse_data(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; +diff --git a/src/topology/parser.c b/src/topology/parser.c +index d7783a93..436e4841 100644 +--- a/src/topology/parser.c ++++ b/src/topology/parser.c +@@ -110,8 +110,8 @@ int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base) + * Parse compound + */ + int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, +- int (*fcn)(snd_tplg_t *, snd_config_t *, void *), +- void *private) ++ int (*fcn)(snd_tplg_t *, snd_config_t *, void *), ++ void *private) + { + const char *id; + snd_config_iterator_t i, next; +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index da88783f..61159d33 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -1124,8 +1124,8 @@ static int parse_hw_config_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + } + + /* Parse a physical link element in text conf file */ +-int tplg_parse_link(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) ++int tplg_parse_link(snd_tplg_t *tplg, snd_config_t *cfg, ++ void *private ATTRIBUTE_UNUSED) + { + struct snd_soc_tplg_link_config *link; + struct tplg_elem *elem; +@@ -1264,8 +1264,8 @@ int tplg_save_link(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + } + + /* Parse cc */ +-int tplg_parse_cc(snd_tplg_t *tplg, +- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) ++int tplg_parse_cc(snd_tplg_t *tplg, snd_config_t *cfg, ++ void *private ATTRIBUTE_UNUSED) + { + struct snd_soc_tplg_link_config *link; + struct tplg_elem *elem; +@@ -1307,8 +1307,8 @@ int tplg_parse_cc(snd_tplg_t *tplg, + + /* save CC */ + int tplg_save_cc(snd_tplg_t *tplg ATTRIBUTE_UNUSED, +- struct tplg_elem *elem, +- char **dst, const char *pfx) ++ struct tplg_elem *elem, ++ char **dst, const char *pfx) + { + struct snd_soc_tplg_link_config *link = elem->link; + char pfx2[16]; +@@ -1668,7 +1668,7 @@ int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED, + + /* copy stream object */ + static void tplg_add_stream_object(struct snd_soc_tplg_stream *strm, +- struct snd_tplg_stream_template *strm_tpl) ++ struct snd_tplg_stream_template *strm_tpl) + { + snd_strlcpy(strm->name, strm_tpl->name, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); +@@ -1773,7 +1773,7 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) + + /* Set link HW config from C API template */ + static int set_link_hw_config(struct snd_soc_tplg_hw_config *cfg, +- struct snd_tplg_hw_config_template *tpl) ++ struct snd_tplg_hw_config_template *tpl) + { + unsigned int i; + +-- +2.24.1 + + +From 14ad963e192f101246e9b559d3b3fd41268330fb Mon Sep 17 00:00:00 2001 +From: David Fries +Date: Tue, 7 Jan 2020 09:18:10 -0600 +Subject: [PATCH 58/69] mixer: Fix memory leak for more than 16 file descriptor + case + +Signed-off-by: David Fries +Reviewed-by: Takashi Iwai +Signed-off-by: Takashi Iwai +--- + src/mixer/mixer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c +index 82056474..b1af9945 100644 +--- a/src/mixer/mixer.c ++++ b/src/mixer/mixer.c +@@ -767,7 +767,7 @@ int snd_mixer_wait(snd_mixer_t *mixer, int timeout) + if (count < 0) + return count; + if ((unsigned int) count > sizeof(spfds) / sizeof(spfds[0])) { +- pfds = malloc(count * sizeof(*pfds)); ++ pfds = alloca(count * sizeof(*pfds)); + if (!pfds) + return -ENOMEM; + err = snd_mixer_poll_descriptors(mixer, pfds, +-- +2.24.1 + + +From a78dd1bd1e9b47c2aee9b1e066de515b6854695a Mon Sep 17 00:00:00 2001 +From: Bertware +Date: Mon, 13 Jan 2020 10:21:33 +0100 +Subject: [PATCH 59/69] Quote strings containing [ or ] when saving an alsa + config + +Signed-off-by: Bert Marcelis +Signed-off-by: Jaroslav Kysela +--- + src/conf.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/conf.c b/src/conf.c +index c4db9f21..50d04034 100644 +--- a/src/conf.c ++++ b/src/conf.c +@@ -1531,6 +1531,8 @@ static void string_print(char *str, int id, snd_output_t *out) + case '.': + case '{': + case '}': ++ case '[': ++ case ']': + case '\'': + case '"': + goto quoted; +-- +2.24.1 + + +From b34715004f4a1aabb85c5b9f03ba9f200638ee97 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 15 Jan 2020 09:41:05 +0100 +Subject: [PATCH 60/69] ucm: fix the configuration directory (longname) for + ucm2 + +The new ucm2 expects that the longname directory is shared with +the driver directory. Fix that for 'Syntax 2'. + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index d61124a3..b3970a13 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -1649,7 +1649,9 @@ __longname: + + if (err == 0) { + /* got device-specific file that matches the card long name */ +- snd_strlcpy(uc_mgr->conf_file_name, longname, sizeof(uc_mgr->conf_file_name)); ++ if (uc_mgr->conf_format < 2) ++ snd_strlcpy(uc_mgr->conf_file_name, longname, ++ sizeof(uc_mgr->conf_file_name)); + goto __parse; + } + } +-- +2.24.1 + + +From fe6425af751a768a2ba6cf7d430a85553d3b84f6 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 15 Jan 2020 10:31:56 +0100 +Subject: [PATCH 61/69] ucm: split conf_file_name and conf_dir_name + +With ucm2, the file name might differ from the directory +name. Also, allocate those fields. + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/main.c | 7 ++++--- + src/ucm/parser.c | 37 ++++++++++++++++++++++++++----------- + src/ucm/ucm_local.h | 4 ++-- + src/ucm/ucm_subs.c | 2 +- + src/ucm/utils.c | 4 ++++ + 5 files changed, 37 insertions(+), 17 deletions(-) + +diff --git a/src/ucm/main.c b/src/ucm/main.c +index 61922f10..23e15bd8 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -1700,12 +1700,13 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr, + err = 0; + } else if (strcmp(identifier, "_file") == 0) { + /* get the conf file name of the opened card */ +- if ((uc_mgr->card_name == NULL) +- || (uc_mgr->conf_file_name[0] == '\0')) { ++ if ((uc_mgr->card_name == NULL) || ++ (uc_mgr->conf_file_name == NULL) || ++ (uc_mgr->conf_file_name[0] == '\0')) { + err = -ENOENT; + goto __end; + } +- *value = strndup(uc_mgr->conf_file_name, MAX_FILE); ++ *value = strdup(uc_mgr->conf_file_name); + if (*value == NULL) { + err = -ENOMEM; + goto __end; +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index b3970a13..1bfde0be 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -124,6 +124,16 @@ static void configuration_filename(snd_use_case_mgr_t *uc_mgr, + configuration_filename2(fn, fn_len, 2, dir, file, suffix); + } + ++/* ++ * Replace mallocated string ++ */ ++static char *replace_string(char **dst, const char *value) ++{ ++ free(*dst); ++ *dst = strdup(value); ++ return *dst; ++} ++ + /* + * Parse string + */ +@@ -1186,7 +1196,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr, + + /* open Verb file for reading */ + configuration_filename(uc_mgr, filename, sizeof(filename), +- uc_mgr->conf_file_name, file, ""); ++ uc_mgr->conf_dir_name, file, ""); + err = uc_mgr_config_load(uc_mgr->conf_format, filename, &cfg); + if (err < 0) { + uc_error("error: failed to open verb file %s : %d", +@@ -1404,16 +1414,16 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) + if (uc_mgr->conf_format >= 2) { + err = snd_config_search(cfg, "Syntax", &n); + if (err < 0) { +- uc_error("Syntax field not found in %s", uc_mgr->conf_file_name); ++ uc_error("Syntax field not found in %s", uc_mgr->conf_dir_name); + return -EINVAL; + } + err = snd_config_get_integer(n, &l); + if (err < 0) { +- uc_error("Syntax field is invalid in %s", uc_mgr->conf_file_name); ++ uc_error("Syntax field is invalid in %s", uc_mgr->conf_dir_name); + return err; + } + if (l < 2 || l > SYNTAX_VERSION_MAX) { +- uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_file_name); ++ uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_dir_name); + return -EINVAL; + } + /* delete this field to avoid strcmp() call in the loop */ +@@ -1561,8 +1571,9 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name, char *long + return err; + + _name = snd_ctl_card_info_get_name(info); ++ if (replace_string(&mgr->conf_dir_name, _name) == NULL) ++ return -ENOMEM; + _long_name = snd_ctl_card_info_get_longname(info); +- snd_strlcpy(mgr->conf_file_name, _name, sizeof(mgr->conf_file_name)); + snd_strlcpy(longname, _long_name, MAX_CARD_LONG_NAME); + + return 0; +@@ -1585,7 +1596,7 @@ static int load_master_config(snd_use_case_mgr_t *uc_mgr, + if (getenv(ALSA_CONFIG_UCM2_VAR) || !getenv(ALSA_CONFIG_UCM_VAR)) { + uc_mgr->conf_format = 2; + configuration_filename(uc_mgr, filename, sizeof(filename), +- uc_mgr->conf_file_name, card_name, ".conf"); ++ uc_mgr->conf_dir_name, card_name, ".conf"); + if (access(filename, R_OK) == 0) + goto __load; + } +@@ -1608,6 +1619,9 @@ __load: + return err; + } + ++ if (replace_string(&uc_mgr->conf_file_name, card_name) == NULL) ++ return -ENOMEM; ++ + return 0; + } + +@@ -1632,7 +1646,8 @@ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr) + char longname[MAX_CARD_LONG_NAME]; + int err; + +- snd_strlcpy(uc_mgr->conf_file_name, uc_mgr->card_name, sizeof(uc_mgr->conf_file_name)); ++ if (replace_string(&uc_mgr->conf_dir_name, uc_mgr->card_name) == NULL) ++ return -ENOMEM; + + if (strncmp(name, "hw:", 3) == 0) { + err = get_by_card(uc_mgr, name, longname); +@@ -1650,14 +1665,14 @@ __longname: + if (err == 0) { + /* got device-specific file that matches the card long name */ + if (uc_mgr->conf_format < 2) +- snd_strlcpy(uc_mgr->conf_file_name, longname, +- sizeof(uc_mgr->conf_file_name)); ++ snd_strlcpy(uc_mgr->conf_dir_name, longname, ++ sizeof(uc_mgr->conf_dir_name)); + goto __parse; + } + } + + /* standard path */ +- err = load_master_config(uc_mgr, uc_mgr->conf_file_name, &cfg, 0); ++ err = load_master_config(uc_mgr, uc_mgr->conf_dir_name, &cfg, 0); + if (err < 0) + goto __error; + +@@ -1673,7 +1688,7 @@ __parse: + + __error: + uc_mgr_free_ctl_list(uc_mgr); +- uc_mgr->conf_file_name[0] = '\0'; ++ uc_mgr->conf_dir_name[0] = '\0'; + return err; + } + +diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h +index ba961507..63e0f3bf 100644 +--- a/src/ucm/ucm_local.h ++++ b/src/ucm/ucm_local.h +@@ -187,7 +187,6 @@ struct use_case_verb { + /* verb transition list */ + struct list_head transition_list; + +- /* hardware devices that can be used with this use case */ + struct list_head device_list; + + /* component device list */ +@@ -205,7 +204,8 @@ struct use_case_verb { + */ + struct snd_use_case_mgr { + char *card_name; +- char conf_file_name[MAX_CARD_LONG_NAME]; ++ char *conf_file_name; ++ char *conf_dir_name; + char *comment; + int conf_format; + +diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c +index 90e395f0..d931f603 100644 +--- a/src/ucm/ucm_subs.c ++++ b/src/ucm/ucm_subs.c +@@ -31,7 +31,7 @@ + + static char *rval_conf_name(snd_use_case_mgr_t *uc_mgr) + { +- if (uc_mgr->conf_file_name[0]) ++ if (uc_mgr->conf_file_name && uc_mgr->conf_file_name[0]) + return strdup(uc_mgr->conf_file_name); + return NULL; + } +diff --git a/src/ucm/utils.c b/src/ucm/utils.c +index cde1d672..daa568c1 100644 +--- a/src/ucm/utils.c ++++ b/src/ucm/utils.c +@@ -441,7 +441,11 @@ void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr) + uc_mgr_free_sequence(&uc_mgr->default_list); + uc_mgr_free_value(&uc_mgr->value_list); + free(uc_mgr->comment); ++ free(uc_mgr->conf_dir_name); ++ free(uc_mgr->conf_file_name); + uc_mgr->comment = NULL; ++ uc_mgr->conf_dir_name = NULL; ++ uc_mgr->conf_file_name = NULL; + uc_mgr->active_verb = NULL; + INIT_LIST_HEAD(&uc_mgr->active_devices); + INIT_LIST_HEAD(&uc_mgr->active_modifiers); +-- +2.24.1 + + +From ebf5213cd61824b10bcaf67c570919e2a9ea0e1f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 15 Jan 2020 10:40:01 +0100 +Subject: [PATCH 62/69] ucm: remove MAX_FILE definition and use correct + PATH_MAX + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 6 +++--- + src/ucm/ucm_local.h | 1 - + 2 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index 1bfde0be..6c13fafd 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -1167,7 +1167,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr, + snd_config_t *n; + struct use_case_verb *verb; + snd_config_t *cfg; +- char filename[MAX_FILE]; ++ char filename[PATH_MAX]; + int err; + + /* allocate verb */ +@@ -1582,7 +1582,7 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name, char *long + static int load_master_config(snd_use_case_mgr_t *uc_mgr, + const char *card_name, snd_config_t **cfg, int longname) + { +- char filename[MAX_FILE]; ++ char filename[PATH_MAX]; + int err; + + if (strnlen(card_name, MAX_CARD_LONG_NAME) == MAX_CARD_LONG_NAME) { +@@ -1733,7 +1733,7 @@ static int is_component_directory(const char *dir) + */ + int uc_mgr_scan_master_configs(const char **_list[]) + { +- char filename[MAX_FILE], dfl[MAX_FILE]; ++ char filename[PATH_MAX], dfl[PATH_MAX]; + char *env = getenv(ALSA_CONFIG_UCM2_VAR); + const char **list, *d_name; + snd_config_t *cfg, *c; +diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h +index 63e0f3bf..fa9fc166 100644 +--- a/src/ucm/ucm_local.h ++++ b/src/ucm/ucm_local.h +@@ -42,7 +42,6 @@ + + #define SYNTAX_VERSION_MAX 2 + +-#define MAX_FILE 256 + #define MAX_CARD_SHORT_NAME 32 + #define MAX_CARD_LONG_NAME 80 + +-- +2.24.1 + + +From fbe1ac4a09933f527aff860aad035586367f21b4 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 15 Jan 2020 10:41:35 +0100 +Subject: [PATCH 63/69] topology: remove MAX_FILE definition and use correct + PATH_MAX + +Signed-off-by: Jaroslav Kysela +--- + src/topology/data.c | 2 +- + src/topology/tplg_local.h | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/topology/data.c b/src/topology/data.c +index b63e98cd..5742b357 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -163,7 +163,7 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem) + { + struct snd_soc_tplg_private *priv = NULL; + const char *value = NULL; +- char filename[MAX_FILE]; ++ char filename[PATH_MAX]; + char *env = getenv(ALSA_CONFIG_TPLG_VAR); + FILE *fp; + size_t size, bytes_read; +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index e061db75..5ace0d19 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -29,7 +29,6 @@ + #define tplg_dbg(fmt, arg...) do { } while (0) + #endif + +-#define MAX_FILE 256 + #define TPLG_MAX_PRIV_SIZE (1024 * 128) + + /** The name of the environment variable containing the tplg directory */ +-- +2.24.1 + + +From 7d3fec6ac68de0244621ae0aca7474d159336639 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 17 Jan 2020 18:21:08 +0100 +Subject: [PATCH 64/69] ucm: parser - cosmetic fixes in the comments + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 63 ++++++++++++++++++++++++------------------------ + 1 file changed, 31 insertions(+), 32 deletions(-) + +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index 6c13fafd..6c5d2902 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -676,42 +676,41 @@ static int parse_value(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, + /* + * Parse Modifier Use cases + * +- * # Each modifier is described in new section. N modifiers are allowed +- * SectionModifier."Capture Voice" { ++ * # Each modifier is described in new section. N modifiers are allowed ++ * SectionModifier."Capture Voice" { + * +- * Comment "Record voice call" ++ * Comment "Record voice call" + * +- * SupportedDevice [ +- * "x" +- * "y" +- * ] +- * +- * ConflictingDevice [ +- * "x" +- * "y" +- * ] ++ * SupportedDevice [ ++ * "x" ++ * "y" ++ * ] + * +- * EnableSequence [ +- * .... +- * ] ++ * ConflictingDevice [ ++ * "x" ++ * "y" ++ * ] + * +- * DisableSequence [ +- * ... +- * ] ++ * EnableSequence [ ++ * .... ++ * ] + * +- * TransitionSequence."ToModifierName" [ +- * ... +- * ] ++ * DisableSequence [ ++ * ... ++ * ] + * +- * # Optional TQ and ALSA PCMs +- * Value { +- * TQ Voice +- * CapturePCM "hw:1" +- * PlaybackVolume "name='Master Playback Volume',index=2" +- * PlaybackSwitch "name='Master Playback Switch',index=2" +- * } ++ * TransitionSequence."ToModifierName" [ ++ * ... ++ * ] + * +- * } ++ * # Optional TQ and ALSA PCMs ++ * Value { ++ * TQ Voice ++ * CapturePCM "hw:1" ++ * PlaybackVolume "name='Master Playback Volume',index=2" ++ * PlaybackSwitch "name='Master Playback Switch',index=2" ++ * } ++ * } + * + * SupportedDevice and ConflictingDevice cannot be specified together. + * Both are optional. +@@ -836,11 +835,11 @@ static int parse_modifier(snd_use_case_mgr_t *uc_mgr, + /* + * Parse Device Use Cases + * +- *# Each device is described in new section. N devices are allowed +- *SectionDevice."Headphones" { ++ * # Each device is described in new section. N devices are allowed ++ * SectionDevice."Headphones" { + * Comment "Headphones connected to 3.5mm jack" + * +- * upportedDevice [ ++ * SupportedDevice [ + * "x" + * "y" + * ] +-- +2.24.1 + + +From b2fe99277a73ec80eac0bd221672dd4aa02defa7 Mon Sep 17 00:00:00 2001 +From: Tanu Kaskinen +Date: Fri, 20 Dec 2019 09:26:12 +0200 +Subject: [PATCH 65/69] configure.ac: remove an unnecessary libtool fix + +This code was added in commit 75d393a563efb578c79364a277087c6326267f52 +without explaining why. I assume it was a mistake, since it looks like +the libtool problem should have gone away a long time ago. The referenced +wiki page https://wiki.debian.org/RpathIssue says: + + Since libtool 1.5.2 (released 2004-01-25), on Linux libtool no + longer sets RPATH for any directories in the dynamic linker search + path, so this should no longer be an issue unless upstream used a + really old version of libtool when creating their distribution + tarball. + +This code caused problems in OpenEmbedded, where the libtool script is +named "x86_64-oe-linux-libtool" or similar rather than just "libtool", +so the sed command failed with a file not found error. Rather than +adapting the code to OpenEmbedded's peculiarities, it seems best to just +remove the unnecessary code altogether. + +Note: The rpath is set (hardcoded) for 'make' but it is corrected +for 'make install' by libtool. + +Signed-off-by: Tanu Kaskinen +Signed-off-by: Jaroslav Kysela +--- + configure.ac | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 886f87bc..fb60c030 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -765,14 +765,3 @@ test "$build_seq" = "yes" && echo "#include " >> include/asoundlib.h + test "$build_seq" = "yes" && echo "#include " >> include/asoundlib.h + test "$build_seq" = "yes" && echo "#include " >> include/asoundlib.h + cat "$srcdir"/include/asoundlib-tail.h >> include/asoundlib.h +- +-dnl Taken from https://wiki.debian.org/RpathIssue +-case $host in +- *-*-linux-gnu) +- AC_MSG_RESULT([Fixing libtool for -rpath problems.]) +- sed < libtool > libtool-2 \ +- 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_IS_A_FOOL__ "/' +- mv libtool-2 libtool +- chmod 755 libtool +- ;; +-esac +-- +2.24.1 + + +From c5a09b0feaf759957dfac2c797b652781a0d41fe Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 3 Feb 2020 14:44:13 +0100 +Subject: [PATCH 66/69] ucm: parser - use correct filename in + parser_master_file() + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index 6c5d2902..dbbd3817 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -1413,16 +1413,16 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) + if (uc_mgr->conf_format >= 2) { + err = snd_config_search(cfg, "Syntax", &n); + if (err < 0) { +- uc_error("Syntax field not found in %s", uc_mgr->conf_dir_name); ++ uc_error("Syntax field not found in %s", uc_mgr->conf_file_name); + return -EINVAL; + } + err = snd_config_get_integer(n, &l); + if (err < 0) { +- uc_error("Syntax field is invalid in %s", uc_mgr->conf_dir_name); ++ uc_error("Syntax field is invalid in %s", uc_mgr->conf_file_name); + return err; + } + if (l < 2 || l > SYNTAX_VERSION_MAX) { +- uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_dir_name); ++ uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_file_name); + return -EINVAL; + } + /* delete this field to avoid strcmp() call in the loop */ +-- +2.24.1 + + +From 71a1367bcabc50f99302d8c76395f1cb84975775 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 3 Feb 2020 15:24:19 +0100 +Subject: [PATCH 67/69] ucm: the ucm2/ subdirectory is driver name based + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index dbbd3817..f576fde4 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -1515,7 +1515,7 @@ static int get_card_long_name(snd_use_case_mgr_t *mgr, char *longname) + int card, err; + snd_ctl_t *ctl; + snd_ctl_card_info_t *info; +- const char *_name, *_long_name; ++ const char *_driver, *_name, *_long_name; + + snd_ctl_card_info_alloca(&info); + +@@ -1535,9 +1535,11 @@ static int get_card_long_name(snd_use_case_mgr_t *mgr, char *longname) + err = get_card_info(mgr, name, &ctl, info); + + if (err == 0) { ++ _driver = snd_ctl_card_info_get_driver(info); + _name = snd_ctl_card_info_get_name(info); + _long_name = snd_ctl_card_info_get_longname(info); +- if (!strcmp(card_name, _name) || ++ if (!strcmp(card_name, _driver) || ++ !strcmp(card_name, _name) || + !strcmp(card_name, _long_name)) { + snd_strlcpy(longname, _long_name, MAX_CARD_LONG_NAME); + return 0; +@@ -1560,7 +1562,7 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name, char *long + { + snd_ctl_t *ctl; + snd_ctl_card_info_t *info; +- const char *_name, *_long_name; ++ const char *_driver, *_long_name; + int err; + + snd_ctl_card_info_alloca(&info); +@@ -1569,8 +1571,8 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name, char *long + if (err) + return err; + +- _name = snd_ctl_card_info_get_name(info); +- if (replace_string(&mgr->conf_dir_name, _name) == NULL) ++ _driver = snd_ctl_card_info_get_driver(info); ++ if (replace_string(&mgr->conf_dir_name, _driver) == NULL) + return -ENOMEM; + _long_name = snd_ctl_card_info_get_longname(info); + snd_strlcpy(longname, _long_name, MAX_CARD_LONG_NAME); +-- +2.24.1 + + +From 251bc204a1e7f1bf1d12b452f2b62e15543bba94 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 7 Feb 2020 10:09:07 +0100 +Subject: [PATCH 68/69] ucm: implement RenameDevice and RemoveDevice verb + management + +With the conditionals, it may be useful to define the devices +in the included configuration files. To satisfy the specification +requirements (device naming) those device names might require +to be renamed or deleted wrong references from the conflicting +or supported lists. + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 129 +++++++++++++++++++++++++++++++++++++++++++- + src/ucm/ucm_local.h | 15 ++++++ + src/ucm/utils.c | 123 +++++++++++++++++++++++++++++++++++++----- + 3 files changed, 254 insertions(+), 13 deletions(-) + +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index f576fde4..f9a8f628 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -985,6 +985,71 @@ static int parse_device(snd_use_case_mgr_t *uc_mgr, + return 0; + } + ++/* ++ * Parse Device Rename/Delete Command ++ * ++ * # The devices might be renamed to allow the better conditional runtime ++ * # evaluation. Bellow example renames Speaker1 device to Speaker and ++ * # removes Speaker2 device. ++ * RenameDevice."Speaker1" "Speaker" ++ * RemoveDevice."Speaker2" "Speaker2" ++ */ ++static int parse_dev_name_list(snd_config_t *cfg, ++ struct list_head *list) ++{ ++ snd_config_t *n; ++ snd_config_iterator_t i, next; ++ const char *id, *name1; ++ char *name2; ++ struct ucm_dev_name *dev; ++ snd_config_iterator_t pos; ++ int err; ++ ++ if (snd_config_get_id(cfg, &id) < 0) ++ return -EINVAL; ++ ++ if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { ++ uc_error("compound type expected for %s", id); ++ return -EINVAL; ++ } ++ ++ snd_config_for_each(i, next, cfg) { ++ n = snd_config_iterator_entry(i); ++ ++ if (snd_config_get_id(n, &name1) < 0) ++ return -EINVAL; ++ ++ err = parse_string(n, &name2); ++ if (err < 0) { ++ uc_error("error: failed to get target device name for '%s'", name1); ++ return err; ++ } ++ ++ /* skip duplicates */ ++ list_for_each(pos, list) { ++ dev = list_entry(pos, struct ucm_dev_name, list); ++ if (strcmp(dev->name1, name1) == 0) { ++ free(name2); ++ return 0; ++ } ++ } ++ ++ dev = calloc(1, sizeof(*dev)); ++ if (dev == NULL) ++ return -ENOMEM; ++ dev->name1 = strdup(name1); ++ if (dev->name1 == NULL) { ++ free(dev); ++ free(name2); ++ return -ENOMEM; ++ } ++ dev->name2 = name2; ++ list_add_tail(&dev->list, list); ++ } ++ ++ return 0; ++} ++ + static int parse_compound_check_legacy(snd_use_case_mgr_t *uc_mgr, + snd_config_t *cfg, + int (*fcn)(snd_use_case_mgr_t *, snd_config_t *, void *, void *), +@@ -1044,7 +1109,39 @@ static int parse_modifier_name(snd_use_case_mgr_t *uc_mgr, + void *data1, + void *data2 ATTRIBUTE_UNUSED) + { +- return parse_compound_check_legacy(uc_mgr, cfg, parse_modifier, data1); ++ return parse_compound(uc_mgr, cfg, parse_modifier, data1, data2); ++} ++ ++static int verb_device_management(struct use_case_verb *verb) ++{ ++ struct list_head *pos; ++ struct ucm_dev_name *dev; ++ int err; ++ ++ /* rename devices */ ++ list_for_each(pos, &verb->rename_list) { ++ dev = list_entry(pos, struct ucm_dev_name, list); ++ err = uc_mgr_rename_device(verb, dev->name1, dev->name2); ++ if (err < 0) { ++ uc_error("error: cannot rename device '%s' to '%s'", dev->name1, dev->name2); ++ return err; ++ } ++ } ++ ++ /* remove devices */ ++ list_for_each(pos, &verb->rename_list) { ++ dev = list_entry(pos, struct ucm_dev_name, list); ++ err = uc_mgr_remove_device(verb, dev->name2); ++ if (err < 0) { ++ uc_error("error: cannot remove device '%s'", dev->name2); ++ return err; ++ } ++ } ++ ++ /* those lists are no longer used */ ++ uc_mgr_free_dev_name_list(&verb->rename_list); ++ uc_mgr_free_dev_name_list(&verb->remove_list); ++ return 0; + } + + /* +@@ -1180,6 +1277,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr, + INIT_LIST_HEAD(&verb->cmpt_device_list); + INIT_LIST_HEAD(&verb->modifier_list); + INIT_LIST_HEAD(&verb->value_list); ++ INIT_LIST_HEAD(&verb->rename_list); ++ INIT_LIST_HEAD(&verb->remove_list); + list_add_tail(&verb->list, &uc_mgr->verb_list); + if (use_case_name == NULL) + return -EINVAL; +@@ -1249,6 +1348,26 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr, + } + continue; + } ++ ++ /* device renames */ ++ if (strcmp(id, "RenameDevice") == 0) { ++ err = parse_dev_name_list(n, &verb->rename_list); ++ if (err < 0) { ++ uc_error("error: %s failed to parse device rename", ++ file); ++ goto _err; ++ } ++ } ++ ++ /* device remove */ ++ if (strcmp(id, "RemoveDevice") == 0) { ++ err = parse_dev_name_list(n, &verb->remove_list); ++ if (err < 0) { ++ uc_error("error: %s failed to parse device remove", ++ file); ++ goto _err; ++ } ++ } + } + + snd_config_delete(cfg); +@@ -1258,6 +1377,14 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr, + uc_error("error: no use case device defined", file); + return -EINVAL; + } ++ ++ /* do device rename and delete */ ++ err = verb_device_management(verb); ++ if (err < 0) { ++ uc_error("error: device management error in verb '%s'", verb->name); ++ return err; ++ } ++ + return 0; + + _err: +diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h +index fa9fc166..ba8d2acb 100644 +--- a/src/ucm/ucm_local.h ++++ b/src/ucm/ucm_local.h +@@ -117,6 +117,12 @@ struct ctl_list { + snd_ctl_card_info_t *ctl_info; + }; + ++struct ucm_dev_name { ++ struct list_head list; ++ char *name1; ++ char *name2; ++}; ++ + /* + * Describes a Use Case Modifier and it's enable and disable sequences. + * A use case verb can have N modifiers. +@@ -196,6 +202,10 @@ struct use_case_verb { + + /* value list */ + struct list_head value_list; ++ ++ /* temporary modifications lists */ ++ struct list_head rename_list; ++ struct list_head remove_list; + }; + + /* +@@ -252,6 +262,11 @@ int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg); + int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr); + int uc_mgr_scan_master_configs(const char **_list[]); + ++int uc_mgr_remove_device(struct use_case_verb *verb, const char *name); ++int uc_mgr_rename_device(struct use_case_verb *verb, const char *src, ++ const char *dst); ++ ++void uc_mgr_free_dev_name_list(struct list_head *base); + void uc_mgr_free_sequence_element(struct sequence_element *seq); + void uc_mgr_free_transition_element(struct transition_sequence *seq); + void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr); +diff --git a/src/ucm/utils.c b/src/ucm/utils.c +index daa568c1..60a59172 100644 +--- a/src/ucm/utils.c ++++ b/src/ucm/utils.c +@@ -328,6 +328,44 @@ void uc_mgr_free_dev_list(struct dev_list *dev_list) + } + } + ++int uc_mgr_rename_in_dev_list(struct dev_list *dev_list, const char *src, ++ const char *dst) ++{ ++ struct list_head *pos; ++ struct dev_list_node *dlist; ++ char *dst1; ++ ++ list_for_each(pos, &dev_list->list) { ++ dlist = list_entry(pos, struct dev_list_node, list); ++ if (strcmp(dlist->name, src) == 0) { ++ dst1 = strdup(dst); ++ if (dst1 == NULL) ++ return -ENOMEM; ++ free(dlist->name); ++ dlist->name = dst1; ++ return 0; ++ } ++ } ++ return -ENOENT; ++} ++ ++int uc_mgr_remove_from_dev_list(struct dev_list *dev_list, const char *name) ++{ ++ struct list_head *pos; ++ struct dev_list_node *dlist; ++ ++ list_for_each(pos, &dev_list->list) { ++ dlist = list_entry(pos, struct dev_list_node, list); ++ if (strcmp(dlist->name, name) == 0) { ++ free(dlist->name); ++ list_del(&dlist->list); ++ free(dlist); ++ return 0; ++ } ++ } ++ return -ENODEV; ++} ++ + void uc_mgr_free_sequence_element(struct sequence_element *seq) + { + if (seq == NULL) +@@ -381,6 +419,20 @@ void uc_mgr_free_transition(struct list_head *base) + } + } + ++void uc_mgr_free_dev_name_list(struct list_head *base) ++{ ++ struct list_head *pos, *npos; ++ struct ucm_dev_name *dev; ++ ++ list_for_each_safe(pos, npos, base) { ++ dev = list_entry(pos, struct ucm_dev_name, list); ++ list_del(&dev->list); ++ free(dev->name1); ++ free(dev->name2); ++ free(dev); ++ } ++} ++ + void uc_mgr_free_modifier(struct list_head *base) + { + struct list_head *pos, *npos; +@@ -400,23 +452,68 @@ void uc_mgr_free_modifier(struct list_head *base) + } + } + +-void uc_mgr_free_device(struct list_head *base) ++void uc_mgr_free_device(struct use_case_device *dev) ++{ ++ free(dev->name); ++ free(dev->comment); ++ uc_mgr_free_sequence(&dev->enable_list); ++ uc_mgr_free_sequence(&dev->disable_list); ++ uc_mgr_free_transition(&dev->transition_list); ++ uc_mgr_free_dev_list(&dev->dev_list); ++ uc_mgr_free_value(&dev->value_list); ++ list_del(&dev->list); ++ free(dev); ++} ++ ++void uc_mgr_free_device_list(struct list_head *base) + { + struct list_head *pos, *npos; + struct use_case_device *dev; + + list_for_each_safe(pos, npos, base) { + dev = list_entry(pos, struct use_case_device, list); +- free(dev->name); +- free(dev->comment); +- uc_mgr_free_sequence(&dev->enable_list); +- uc_mgr_free_sequence(&dev->disable_list); +- uc_mgr_free_transition(&dev->transition_list); +- uc_mgr_free_dev_list(&dev->dev_list); +- uc_mgr_free_value(&dev->value_list); +- list_del(&dev->list); +- free(dev); ++ uc_mgr_free_device(dev); ++ } ++} ++ ++int uc_mgr_rename_device(struct use_case_verb *verb, const char *src, ++ const char *dst) ++{ ++ struct use_case_device *device; ++ struct list_head *pos, *npos; ++ char *dst1; ++ ++ /* no errors when device is not found */ ++ list_for_each_safe(pos, npos, &verb->device_list) { ++ device = list_entry(pos, struct use_case_device, list); ++ if (strcmp(device->name, src) == 0) { ++ dst1 = strdup(dst); ++ if (dst1 == NULL) ++ return -ENOMEM; ++ free(device->name); ++ device->name = dst1; ++ continue; ++ } ++ uc_mgr_rename_in_dev_list(&device->dev_list, src, dst); ++ } ++ return 0; ++} ++ ++int uc_mgr_remove_device(struct use_case_verb *verb, const char *name) ++{ ++ struct use_case_device *device; ++ struct list_head *pos, *npos; ++ ++ list_for_each_safe(pos, npos, &verb->device_list) { ++ device = list_entry(pos, struct use_case_device, list); ++ if (strcmp(device->name, name) == 0) { ++ uc_mgr_free_device(device); ++ continue; ++ } ++ uc_mgr_remove_from_dev_list(&device->dev_list, name); ++ return 0; + } ++ return -ENOENT; + } + + void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr) +@@ -432,9 +529,11 @@ void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr) + uc_mgr_free_sequence(&verb->disable_list); + uc_mgr_free_transition(&verb->transition_list); + uc_mgr_free_value(&verb->value_list); +- uc_mgr_free_device(&verb->device_list); +- uc_mgr_free_device(&verb->cmpt_device_list); ++ uc_mgr_free_device_list(&verb->device_list); ++ uc_mgr_free_device_list(&verb->cmpt_device_list); + uc_mgr_free_modifier(&verb->modifier_list); ++ uc_mgr_free_dev_name_list(&verb->rename_list); ++ uc_mgr_free_dev_name_list(&verb->remove_list); + list_del(&verb->list); + free(verb); + } +-- +2.24.1 + + +From fdf96312fa3c9261db2954afcde8c6a15d2ebe44 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 7 Feb 2020 16:18:11 +0100 +Subject: [PATCH 69/69] ucm: fill missing device entries (conflicting / + supported) + +It is not necessary to maintain this information in sync in the configuration +files. Fill the missing entries to the complementary devices. + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 50 ++++++++++++++++++++++++++++++++++++++++++++- + src/ucm/ucm_local.h | 1 + + src/ucm/utils.c | 25 +++++++++++++++++++++++ + 3 files changed, 75 insertions(+), 1 deletion(-) + +diff --git a/src/ucm/parser.c b/src/ucm/parser.c +index f9a8f628..23bf6a63 100644 +--- a/src/ucm/parser.c ++++ b/src/ucm/parser.c +@@ -1112,6 +1112,52 @@ static int parse_modifier_name(snd_use_case_mgr_t *uc_mgr, + return parse_compound(uc_mgr, cfg, parse_modifier, data1, data2); + } + ++static int verb_dev_list_add(struct use_case_verb *verb, ++ enum dev_list_type dst_type, ++ const char *dst, ++ const char *src) ++{ ++ struct use_case_device *device; ++ struct list_head *pos; ++ ++ list_for_each(pos, &verb->device_list) { ++ device = list_entry(pos, struct use_case_device, list); ++ if (strcmp(device->name, dst) != 0) ++ continue; ++ if (device->dev_list.type != dst_type) { ++ if (list_empty(&device->dev_list.list)) { ++ device->dev_list.type = dst_type; ++ } else { ++ uc_error("error: incompatible device list type ('%s', '%s')", ++ device->name, src); ++ return -EINVAL; ++ } ++ } ++ return uc_mgr_put_to_dev_list(&device->dev_list, src); ++ } ++ return -ENOENT; ++} ++ ++static int verb_dev_list_check(struct use_case_verb *verb) ++{ ++ struct list_head *pos, *pos2; ++ struct use_case_device *device; ++ struct dev_list_node *dlist; ++ int err; ++ ++ list_for_each(pos, &verb->device_list) { ++ device = list_entry(pos, struct use_case_device, list); ++ list_for_each(pos2, &device->dev_list.list) { ++ dlist = list_entry(pos2, struct dev_list_node, list); ++ err = verb_dev_list_add(verb, device->dev_list.type, ++ dlist->name, device->name); ++ if (err < 0) ++ return err; ++ } ++ } ++ return 0; ++} ++ + static int verb_device_management(struct use_case_verb *verb) + { + struct list_head *pos; +@@ -1141,7 +1187,9 @@ static int verb_device_management(struct use_case_verb *verb) + /* those lists are no longer used */ + uc_mgr_free_dev_name_list(&verb->rename_list); + uc_mgr_free_dev_name_list(&verb->remove_list); +- return 0; ++ ++ /* handle conflicting/supported lists */ ++ return verb_dev_list_check(verb); + } + + /* +diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h +index ba8d2acb..acec4bf6 100644 +--- a/src/ucm/ucm_local.h ++++ b/src/ucm/ucm_local.h +@@ -262,6 +262,7 @@ int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg); + int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr); + int uc_mgr_scan_master_configs(const char **_list[]); + ++int uc_mgr_put_to_dev_list(struct dev_list *dev_list, const char *name); + int uc_mgr_remove_device(struct use_case_verb *verb, const char *name); + int uc_mgr_rename_device(struct use_case_verb *verb, const char *src, + const char *dst); +diff --git a/src/ucm/utils.c b/src/ucm/utils.c +index 60a59172..50b2a1df 100644 +--- a/src/ucm/utils.c ++++ b/src/ucm/utils.c +@@ -328,6 +328,31 @@ void uc_mgr_free_dev_list(struct dev_list *dev_list) + } + } + ++int uc_mgr_put_to_dev_list(struct dev_list *dev_list, const char *name) ++{ ++ struct list_head *pos; ++ struct dev_list_node *dlist; ++ char *n; ++ ++ list_for_each(pos, &dev_list->list) { ++ dlist = list_entry(pos, struct dev_list_node, list); ++ if (strcmp(dlist->name, name) == 0) ++ return 0; ++ } ++ ++ dlist = calloc(1, sizeof(*dlist)); ++ if (dlist == NULL) ++ return -ENOMEM; ++ n = strdup(name); ++ if (n == NULL) { ++ free(dlist); ++ return -ENOMEM; ++ } ++ dlist->name = n; ++ list_add(&dlist->list, &dev_list->list); ++ return 0; ++} ++ + int uc_mgr_rename_in_dev_list(struct dev_list *dev_list, const char *src, + const char *dst) + { +-- +2.24.1 diff --git a/alsa-lib.spec b/alsa-lib.spec index bb82196..b7ab286 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -163,6 +163,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Sun Feb 9 2020 Jaroslav Kysela - 1.2.1.2-5 +- More UCM2 related fixes + * Tue Jan 28 2020 Fedora Release Engineering - 1.2.1.2-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild diff --git a/alsa-ucm-conf.patch b/alsa-ucm-conf.patch index 3bccad3..fc1a184 100644 --- a/alsa-ucm-conf.patch +++ b/alsa-ucm-conf.patch @@ -1,7 +1,7 @@ From 2882eb5085db58b60ff6dd0f61912d32ccbdf911 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 5 Dec 2019 17:46:53 +0100 -Subject: [PATCH 1/3] sof-hda-dsp: Fix the Dmic0 CaptureMixerElem for v1.4.1 +Subject: [PATCH 01/36] sof-hda-dsp: Fix the Dmic0 CaptureMixerElem for v1.4.1 firmware Signed-off-by: Jaroslav Kysela @@ -23,13 +23,13 @@ index f1c81a1..500cbae 100644 CaptureSwitch "Dmic0 Capture Switch" } -- -2.20.1 +2.24.1 From adeb572487081f4f88318583d6eefb0ea1b61361 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 6 Dec 2019 11:12:39 +0100 -Subject: [PATCH 2/3] sof-hda-dsp: Use more strict names according latest +Subject: [PATCH 02/36] sof-hda-dsp: Use more strict names according latest use-case.h Also remove ConflictinDevice section from the digital microphone. @@ -99,4 +99,5550 @@ index 500cbae..5c7236d 100644 CapturePriority 100 CapturePCM "hw:${CardId},6" -- -2.20.1 +2.24.1 + + +From e852e235102b6132e7c873c2ff00bf3e01237af0 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 6 Jan 2020 14:11:59 +0100 +Subject: [PATCH 04/36] bytcht-es8316: Fix missing including of HeadPhones.conf + after ucm2 conversion + +The conversion to ucm2 format missed adding an include for: + +codecs/es8316/HeadPhones.conf + +Leading to no sound on the headphones output, this commit adds the missing +include fixing this. + +Cc: youling 257 +Reported-by: youling 257 +Signed-off-by: Hans de Goede +Signed-off-by: Jaroslav Kysela +--- + ucm2/bytcht-es8316/HiFi-Components.conf | 2 ++ + ucm2/bytcht-es8316/HiFi-LongName.conf | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/ucm2/bytcht-es8316/HiFi-Components.conf b/ucm2/bytcht-es8316/HiFi-Components.conf +index 314d355..c40bd49 100644 +--- a/ucm2/bytcht-es8316/HiFi-Components.conf ++++ b/ucm2/bytcht-es8316/HiFi-Components.conf +@@ -20,6 +20,8 @@ If.mono { + } + } + ++ ++ + If.in1 { + Condition { + Type String +diff --git a/ucm2/bytcht-es8316/HiFi-LongName.conf b/ucm2/bytcht-es8316/HiFi-LongName.conf +index ea7d1c3..03cf17b 100644 +--- a/ucm2/bytcht-es8316/HiFi-LongName.conf ++++ b/ucm2/bytcht-es8316/HiFi-LongName.conf +@@ -20,6 +20,8 @@ If.mono { + } + } + ++ ++ + If.in1 { + Condition { + Type String +-- +2.24.1 + + +From 74f2a0f0884df7b9f2d08d07456a3bc37d1a512e Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 13 Jan 2020 13:36:55 +0100 +Subject: [PATCH 05/36] ucm2: fix the verb path in + chtrt5645/chtrt5645-dmic2.conf + +Signed-off-by: Jaroslav Kysela +--- + ucm2/chtrt5645/chtrt5645-dmic2.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ucm2/chtrt5645/chtrt5645-dmic2.conf b/ucm2/chtrt5645/chtrt5645-dmic2.conf +index 9bbebfa..2ea095c 100644 +--- a/ucm2/chtrt5645/chtrt5645-dmic2.conf ++++ b/ucm2/chtrt5645/chtrt5645-dmic2.conf +@@ -1,6 +1,6 @@ + Syntax 2 + Comment "Intel SoC Audio Device" + SectionUseCase."HiFi" { +- File "../LENOVO-80XF-LenovoMIIX320_10ICR-LNVNB161216/HiFi.conf" ++ File "HiFi-dmic2.conf" + Comment "Default" + } +-- +2.24.1 + + +From be86627a9f4179979d208943bb497b10dfc679cb Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 10 Dec 2019 17:08:37 +0100 +Subject: [PATCH 06/36] broadwell-rt286: add support for hardware volume, + conformance fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/broadwell-rt286/HiFi.conf | 90 ++++++++++++++++------------------ + 1 file changed, 43 insertions(+), 47 deletions(-) + +diff --git a/ucm2/broadwell-rt286/HiFi.conf b/ucm2/broadwell-rt286/HiFi.conf +index 6cf31e7..e766250 100644 +--- a/ucm2/broadwell-rt286/HiFi.conf ++++ b/ucm2/broadwell-rt286/HiFi.conf +@@ -1,13 +1,31 @@ + # Use case Configuration for Nexus 7 + # Adapted to Ubuntu Touch by David Henningsson + +-SectionVerb { ++SectionDevice."Speaker" { ++ Comment "Speaker playback" ++ ++ ConflictingDevice [ ++ "Headphones" ++ ] ++ ++ EnableSequence [ ++ cset "name='SPO Switch' on" ++ cset "name='Speaker Playback Switch' on" ++ cset "name='Speaker Switch' on" ++ ] ++ ++ DisableSequence [ ++ cset "name='Speaker Switch' off" ++ cset "name='Speaker Playback Switch' off" ++ cset "name='SPO Switch' 0" ++ ] + +- # ALSA PCM + Value { +- # ALSA PCM device for HiFi ++ Priority 100 + PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" ++ PlaybackChannels 2 ++ PlaybackMixerElem "DAC0" ++ PlaybackMasterElem "Master" + } + } + +@@ -19,11 +37,9 @@ SectionDevice."Headphones" { + ] + + EnableSequence [ +- cset "name='Master Playback Volume' 30" + cset "name='HPO L Switch' on" + cset "name='HPO R Switch' on" + cset "name='Headphone Jack Switch' on" +- cset "name='DAC0 Playback Volume' 100" + ] + + DisableSequence [ +@@ -33,36 +49,38 @@ SectionDevice."Headphones" { + ] + + Value { +- PlaybackChannels "2" ++ Priority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 ++ PlaybackMixerElem "DAC0" ++ PlaybackMasterElem "Master" + JackDev "rt286-jack" + JackControl "Headphone Jack" + JackHWMute "Speaker" + } + } + +-SectionDevice."Speaker" { +- Comment "Speaker playback" ++SectionDevice."Mic" { ++ Comment "Microphone" + + ConflictingDevice [ +- "Headphones" ++ "Handset" + ] + + EnableSequence [ +- cset "name='Master Playback Volume' 30" +- cset "name='DAC0 Playback Volume' 127" +- cset "name='SPO Switch' on" +- cset "name='Speaker Playback Switch' on" +- cset "name='Speaker Switch' on" ++ cset "name='ADC 0 Mux' 2" + ] + + DisableSequence [ +- cset "name='Speaker Switch' off" +- cset "name='Speaker Playback Switch' off" +- cset "name='SPO Switch' 0" ++ cset "name='ADC0 Capture Switch' off" + ] + + Value { +- PlaybackChannels "2" ++ Priority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels "2" ++ CaptureMixerElem "Mic" ++ CaptureMasterElem "ADC0" + } + } + +@@ -70,14 +88,11 @@ SectionDevice."Handset" { + Comment "Handset Microphone" + + ConflictingDevice [ +- "Mainmic" ++ "Mic" + ] + + EnableSequence [ +- cset "name='Mic Capture Volume' 28" + cset "name='ADC 0 Mux' 0" +- cset "name='ADC0 Capture Switch' on" +- cset "name='ADC0 Capture Volume' 127" + cset "name='AMIC Volume' 1" + ] + +@@ -86,32 +101,13 @@ SectionDevice."Handset" { + ] + + Value { ++ Priority 200 ++ CapturePCM "hw:${CardId}" + CaptureChannels "2" ++ CaptureMixerElem "Mic" ++ CaptureMasterElem "ADC0" + JackDev "rt286-jack" + JackControl "Mic Jack" +- JackHWMute "Mainmic" +- } +-} +- +-SectionDevice."Mainmic" { +- Comment "Main Microphone" +- +- ConflictingDevice [ +- "Handset" +- ] +- +- EnableSequence [ +- cset "name='Mic Capture Volume' 30" +- cset "name='ADC 0 Mux' 2" +- cset "name='ADC0 Capture Switch' on" +- cset "name='ADC0 Capture Volume' 127" +- ] +- +- DisableSequence [ +- cset "name='ADC0 Capture Switch' off" +- ] +- +- Value { +- CaptureChannels "2" ++ JackHWMute "Mic" + } + } +-- +2.24.1 + + +From b70e91923bfa61989acb32801bee259a4c04674d Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 23 Jan 2020 14:13:10 +0100 +Subject: [PATCH 07/36] broxton-rt298: corrections, cleanups + +Signed-off-by: Jaroslav Kysela +--- + ucm2/broxton-rt298/Hdmi.conf | 43 ++++++++++++++++++ + ucm2/broxton-rt298/Hdmi1.conf | 23 ---------- + ucm2/broxton-rt298/Hdmi2.conf | 23 ---------- + ucm2/broxton-rt298/HiFi.conf | 63 ++++++++++++++++----------- + ucm2/broxton-rt298/broxton-rt298.conf | 18 ++------ + 5 files changed, 84 insertions(+), 86 deletions(-) + create mode 100644 ucm2/broxton-rt298/Hdmi.conf + delete mode 100644 ucm2/broxton-rt298/Hdmi1.conf + delete mode 100644 ucm2/broxton-rt298/Hdmi2.conf + +diff --git a/ucm2/broxton-rt298/Hdmi.conf b/ucm2/broxton-rt298/Hdmi.conf +new file mode 100644 +index 0000000..fc64fe7 +--- /dev/null ++++ b/ucm2/broxton-rt298/Hdmi.conf +@@ -0,0 +1,43 @@ ++# Usecase for device HDMI1/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms ++ ++SectionDevice."HDMI1" { ++ Comment "HDMI/Display Port 1 Stereo" ++ ++ Value { ++ PlaybackPCM "hw:${CardId},4" ++ PlaybackPriority 500 ++ If.1 { ++ Condition { ++ Type ControlExists ++ Control "iface=CARD,name='HDMI/DP,pcm=4 Jack'" ++ } ++ True { ++ JackControl "HDMI/DP,pcm=4 Jack" ++ } ++ False { ++ JackControl "HDMI/DP, pcm=4 Jack" ++ } ++ } ++ } ++} ++ ++SectionDevice."HDMI2" { ++ Comment "HDMI/Display Port 2 Stereo" ++ ++ Value { ++ PlaybackPCM "hw:${CardId},5" ++ PlaybackPriority 600 ++ If.1 { ++ Condition { ++ Type ControlExists ++ Control "iface=CARD,name='HDMI/DP,pcm=5 Jack'" ++ } ++ True { ++ JackControl "HDMI/DP,pcm=5 Jack" ++ } ++ False { ++ JackControl "HDMI/DP, pcm=5 Jack" ++ } ++ } ++ } ++} +diff --git a/ucm2/broxton-rt298/Hdmi1.conf b/ucm2/broxton-rt298/Hdmi1.conf +deleted file mode 100644 +index ede176b..0000000 +--- a/ucm2/broxton-rt298/Hdmi1.conf ++++ /dev/null +@@ -1,23 +0,0 @@ +-# Usecase for device HDMI1/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms +-# For Audio in I2S mode +- +-SectionDevice."Hdmi1" { +- Comment "HDMI/Display Port 1 Stereo" +- +- Value { +- PlaybackPCM "hw:${CardId},4" +- PlaybackPriority "3" +- If.1 { +- Condition { +- Type ControlExists +- Control "iface=CARD,name='HDMI/DP,pcm=4 Jack'" +- } +- True { +- JackControl "HDMI/DP,pcm=4 Jack" +- } +- False { +- JackControl "HDMI/DP, pcm=4 Jack" +- } +- } +- } +-} +diff --git a/ucm2/broxton-rt298/Hdmi2.conf b/ucm2/broxton-rt298/Hdmi2.conf +deleted file mode 100644 +index 9718bae..0000000 +--- a/ucm2/broxton-rt298/Hdmi2.conf ++++ /dev/null +@@ -1,23 +0,0 @@ +-# Usecase for device HDMI1/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms +-# For Audio in I2S mode +- +-SectionDevice."Hdmi2" { +- Comment "HDMI/Display Port 2 Stereo" +- +- Value { +- PlaybackPCM "hw:${CardId},5" +- PlaybackPriority "4" +- If.1 { +- Condition { +- Type ControlExists +- Control "iface=CARD,name='HDMI/DP,pcm=5 Jack'" +- } +- True { +- JackControl "HDMI/DP,pcm=5 Jack" +- } +- False { +- JackControl "HDMI/DP, pcm=5 Jack" +- } +- } +- } +-} +diff --git a/ucm2/broxton-rt298/HiFi.conf b/ucm2/broxton-rt298/HiFi.conf +index 630d5e1..6f5b9a5 100644 +--- a/ucm2/broxton-rt298/HiFi.conf ++++ b/ucm2/broxton-rt298/HiFi.conf +@@ -9,31 +9,29 @@ SectionVerb { + + Value { + TQ "HiFi" +- CapturePCM "hw:${CardId},1" +- PlaybackPCM "hw:${CardId},0" + } + } + +-SectionDevice."DigitalMic" { +- Comment "DMIC Stereo" ++SectionDevice."Speaker" { ++ Comment "Speaker" + + ConflictingDevice [ +- "Headset" ++ "Headphones" + ] + + EnableSequence [ +- cset "name='media0_out mo dmic01_hifi_in mi Switch' 1" +- cset "name='media0_out mo codec0_in mi Switch' 0" +- cset "name='Mic Jack Switch' 0" +- ++ cset "name='SPO Switch' 1" ++ cset "name='Speaker Playback Switch' 1,1" ++ cset "name='Speaker Switch' 1" ++ cset "name='HPO L Switch' 0" ++ cset "name='HPO R Switch' 0" + ] + +- DisableSequence [ +- cset "name='media0_out mo codec0_in mi Switch' 1" +- cset "name='media0_out mo dmic01_hifi_in mi Switch' 0" +- cset "name='Mic Jack Switch' 1" +- cset "name='ADC 0 Mux' 0" +- ] ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ JackHWMute "Headphones" ++ } + } + + SectionDevice."Headphones" { +@@ -51,36 +49,45 @@ SectionDevice."Headphones" { + ] + + Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" + JackControl "Headphone Jack" + JackHWMute "Speaker" + } + } + +-SectionDevice."Speaker" { +- Comment "Speaker" ++SectionDevice."Mic" { ++ Comment "Digital Microphone" + + ConflictingDevice [ +- "Headphones" ++ "Headset" + ] + + EnableSequence [ +- cset "name='SPO Switch' 1" +- cset "name='Speaker Playback Switch' 1,1" +- cset "name='Speaker Switch' 1" +- cset "name='HPO L Switch' 0" +- cset "name='HPO R Switch' 0" ++ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1" ++ cset "name='media0_out mo codec0_in mi Switch' 0" ++ cset "name='Mic Jack Switch' 0" ++ ++ ] ++ ++ DisableSequence [ ++ cset "name='media0_out mo codec0_in mi Switch' 1" ++ cset "name='media0_out mo dmic01_hifi_in mi Switch' 0" ++ cset "name='Mic Jack Switch' 1" ++ cset "name='ADC 0 Mux' 0" + ] + + Value { +- JackHWMute "Headphones" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},1" + } + } + + SectionDevice."Headset" { +- Comment "Headset Mic" ++ Comment "Headset Microphone" + + ConflictingDevice [ +- "DigitalMic" ++ "Mic" + ] + + EnableSequence [ +@@ -97,6 +104,10 @@ SectionDevice."Headset" { + ] + + Value { ++ CapturePriority 200 ++ CapturePCM "hw:${CardId},1" + JackControl "Mic Jack" + } + } ++ ++ +diff --git a/ucm2/broxton-rt298/broxton-rt298.conf b/ucm2/broxton-rt298/broxton-rt298.conf +index 8752e91..1332dc5 100644 +--- a/ucm2/broxton-rt298/broxton-rt298.conf ++++ b/ucm2/broxton-rt298/broxton-rt298.conf +@@ -8,21 +8,11 @@ SectionUseCase."HiFi" { + Comment "Play and record HiFi quality Music" + } + +-SectionUseCase."Hdmi1" { +- File "Hdmi1.conf" +- Comment "Play on Hdmi/DP 1" +-} +- +-SectionUseCase."Hdmi2" { +- File "Hdmi2.conf" +- Comment "Play on Hdmi/DP 2" +-} +- + ValueDefaults { +- PlaybackChannels "2" +- PlaybackPriority "1" +- CaptureChannels "2" +- CapturePriority "2" ++ PlaybackChannels 2 ++ PlaybackPriority 1 ++ CaptureChannels 2 ++ CapturePriority 2 + } + + SectionDefaults [ +-- +2.24.1 + + +From e1f9bdb95e1cf90c17a44fa5734b41b6656d648d Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 23 Jan 2020 19:03:53 +0100 +Subject: [PATCH 08/36] bytcr-rt5640: cleanups and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/codecs/rt5640/DigitalMics.conf | 8 ++++---- + ucm2/codecs/rt5640/HeadPhones.conf | 4 +++- + ucm2/codecs/rt5640/HeadsetMic.conf | 8 ++++---- + ucm2/codecs/rt5640/IN1-InternalMic.conf | 6 +++--- + ucm2/codecs/rt5640/IN3-InternalMic.conf | 8 ++++---- + ucm2/codecs/rt5640/MonoSpeaker.conf | 6 ++++-- + ucm2/codecs/rt5640/Speaker.conf | 4 +++- + 7 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/ucm2/codecs/rt5640/DigitalMics.conf b/ucm2/codecs/rt5640/DigitalMics.conf +index 36982c4..17cae19 100644 +--- a/ucm2/codecs/rt5640/DigitalMics.conf ++++ b/ucm2/codecs/rt5640/DigitalMics.conf +@@ -1,10 +1,8 @@ +-SectionDevice."DigitalMics" { ++SectionDevice."Mic" { + Comment "Internal Digital Microphones" + + ConflictingDevice [ +- "IN1-InternalMics" +- "IN3-InternalMics" +- "HeadsetMic" ++ "Headset" + ] + + EnableSequence [ +@@ -22,6 +20,8 @@ SectionDevice."DigitalMics" { + ] + + Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},0" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/HeadPhones.conf b/ucm2/codecs/rt5640/HeadPhones.conf +index e37442d..dccc943 100644 +--- a/ucm2/codecs/rt5640/HeadPhones.conf ++++ b/ucm2/codecs/rt5640/HeadPhones.conf +@@ -32,7 +32,9 @@ SectionDevice."Headphones" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 300 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/rt5640/HeadsetMic.conf b/ucm2/codecs/rt5640/HeadsetMic.conf +index a99b295..f6d9423 100644 +--- a/ucm2/codecs/rt5640/HeadsetMic.conf ++++ b/ucm2/codecs/rt5640/HeadsetMic.conf +@@ -1,10 +1,8 @@ +-SectionDevice."HeadsetMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + ConflictingDevice [ +- "IN1-InternalMics" +- "IN3-InternalMics" +- "DigitalMics" ++ "Mic" + ] + + EnableSequence [ +@@ -38,6 +36,8 @@ SectionDevice."HeadsetMic" { + ] + + Value { ++ CapturePriority 200 ++ CapturePCM "hw:${CardId},0" + CaptureChannels 2 + JackControl "Headset Mic Jack" + } +diff --git a/ucm2/codecs/rt5640/IN1-InternalMic.conf b/ucm2/codecs/rt5640/IN1-InternalMic.conf +index 95fc89e..435cce8 100644 +--- a/ucm2/codecs/rt5640/IN1-InternalMic.conf ++++ b/ucm2/codecs/rt5640/IN1-InternalMic.conf +@@ -1,10 +1,8 @@ +-SectionDevice."IN1-InternalMics" { ++SectionDevice."Mic" { + Comment "Internal Microphone on IN1" + + ConflictingDevice [ +- "DigitalMics" + "HeadsetMic" +- "IN3-InternalMics" + ] + + EnableSequence [ +@@ -41,6 +39,8 @@ SectionDevice."IN1-InternalMics" { + ] + + Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},0" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/IN3-InternalMic.conf b/ucm2/codecs/rt5640/IN3-InternalMic.conf +index b8270e9..4d4060e 100644 +--- a/ucm2/codecs/rt5640/IN3-InternalMic.conf ++++ b/ucm2/codecs/rt5640/IN3-InternalMic.conf +@@ -1,10 +1,8 @@ +-SectionDevice."IN3-InternalMics" { ++SectionDevice."Mic" { + Comment "Internal Microphone on IN3" + + ConflictingDevice [ +- "DigitalMics" +- "HeadsetMic" +- "IN1-InternalMics" ++ "Headset" + ] + + EnableSequence [ +@@ -41,6 +39,8 @@ SectionDevice."IN3-InternalMics" { + ] + + Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},0" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/MonoSpeaker.conf b/ucm2/codecs/rt5640/MonoSpeaker.conf +index ee4eff3..6ca51e2 100644 +--- a/ucm2/codecs/rt5640/MonoSpeaker.conf ++++ b/ucm2/codecs/rt5640/MonoSpeaker.conf +@@ -1,4 +1,4 @@ +-SectionDevice."MonoSpeaker" { ++SectionDevice."Speaker" { + Comment "Mono Speaker" + + ConflictingDevice [ +@@ -37,6 +37,8 @@ SectionDevice."MonoSpeaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/Speaker.conf b/ucm2/codecs/rt5640/Speaker.conf +index 564a6b3..09b99cf 100644 +--- a/ucm2/codecs/rt5640/Speaker.conf ++++ b/ucm2/codecs/rt5640/Speaker.conf +@@ -37,6 +37,8 @@ SectionDevice."Speaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackPriority 100 ++ PlaybackChannels 2 + } + } +-- +2.24.1 + + +From 38989bd8f548a5b79d53c8278a5f25a5b3904d5f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 23 Jan 2020 19:39:08 +0100 +Subject: [PATCH 09/36] bytcr-rt5651: cleanups and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/bytcr-rt5651/HiFi-Components.conf | 7 +++++-- + ucm2/bytcr-rt5651/HiFi-LongName.conf | 6 ++++-- + ucm2/bytcr-rt5651/HiFi.conf | 5 ----- + ucm2/codecs/rt5651/DigitalMic.conf | 12 +++--------- + ucm2/codecs/rt5651/HeadPhones-swapped.conf | 5 +++-- + ucm2/codecs/rt5651/HeadPhones.conf | 5 +++-- + ucm2/codecs/rt5651/IN1-InternalMic.conf | 14 ++++---------- + ucm2/codecs/rt5651/IN12-InternalMic.conf | 14 ++++---------- + ucm2/codecs/rt5651/IN2-HeadsetMic.conf | 12 +++++------- + ucm2/codecs/rt5651/IN2-InternalMic.conf | 14 ++++---------- + ucm2/codecs/rt5651/IN3-HeadsetMic.conf | 12 +++++------- + ucm2/codecs/rt5651/MonoSpeaker.conf | 7 ++++--- + ucm2/codecs/rt5651/Speaker.conf | 5 +++-- + 13 files changed, 47 insertions(+), 71 deletions(-) + +diff --git a/ucm2/bytcr-rt5651/HiFi-Components.conf b/ucm2/bytcr-rt5651/HiFi-Components.conf +index 235838e..53ebcbe 100644 +--- a/ucm2/bytcr-rt5651/HiFi-Components.conf ++++ b/ucm2/bytcr-rt5651/HiFi-Components.conf +@@ -42,6 +42,11 @@ If.dmic1 { + } + True { + ++ ++ SectionDevice."Mic".ConflictingDevice.0 "Headset" ++ } ++ False { ++ + } + } + +@@ -77,5 +82,3 @@ If.in12 { + + } + } +- +- +diff --git a/ucm2/bytcr-rt5651/HiFi-LongName.conf b/ucm2/bytcr-rt5651/HiFi-LongName.conf +index 58eb722..e6dd908 100644 +--- a/ucm2/bytcr-rt5651/HiFi-LongName.conf ++++ b/ucm2/bytcr-rt5651/HiFi-LongName.conf +@@ -42,6 +42,10 @@ If.dmic1 { + } + True { + ++ ++ } ++ False { ++ + } + } + +@@ -77,5 +81,3 @@ If.in12 { + + } + } +- +- +diff --git a/ucm2/bytcr-rt5651/HiFi.conf b/ucm2/bytcr-rt5651/HiFi.conf +index 1f031f2..8a9a402 100644 +--- a/ucm2/bytcr-rt5651/HiFi.conf ++++ b/ucm2/bytcr-rt5651/HiFi.conf +@@ -10,11 +10,6 @@ SectionVerb { + DisableSequence [ + + ] +- +- Value { +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" +- } + } + + If.0 { +diff --git a/ucm2/codecs/rt5651/DigitalMic.conf b/ucm2/codecs/rt5651/DigitalMic.conf +index 7a0c4d4..fa1de4c 100644 +--- a/ucm2/codecs/rt5651/DigitalMic.conf ++++ b/ucm2/codecs/rt5651/DigitalMic.conf +@@ -1,14 +1,6 @@ +-SectionDevice."DigitalMic" { ++SectionDevice."Mic" { + Comment "Internal Digital Microphone" + +- ConflictingDevice [ +- "InternalMic-IN1" +- "InternalMic-IN2" +- "InternalMic-IN12" +- "HeadsetMic-IN2" +- "HeadsetMic-IN3" +- ] +- + EnableSequence [ + cset "name='Stereo1 ADC MIXL ADC2 Switch' on" + cset "name='Stereo1 ADC MIXR ADC2 Switch' on" +@@ -22,6 +14,8 @@ SectionDevice."DigitalMic" { + ] + + Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/HeadPhones-swapped.conf b/ucm2/codecs/rt5651/HeadPhones-swapped.conf +index f5260a3..7e91aa2 100644 +--- a/ucm2/codecs/rt5651/HeadPhones-swapped.conf ++++ b/ucm2/codecs/rt5651/HeadPhones-swapped.conf +@@ -3,7 +3,6 @@ SectionDevice."Headphones" { + + ConflictingDevice [ + "Speaker" +- "MonoSpeaker" + ] + + EnableSequence [ +@@ -33,7 +32,9 @@ SectionDevice."Headphones" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackChannels 2 ++ PlaybackPCM "hw:${CardId}" + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/rt5651/HeadPhones.conf b/ucm2/codecs/rt5651/HeadPhones.conf +index 0a87b32..18a4108 100644 +--- a/ucm2/codecs/rt5651/HeadPhones.conf ++++ b/ucm2/codecs/rt5651/HeadPhones.conf +@@ -3,7 +3,6 @@ SectionDevice."Headphones" { + + ConflictingDevice [ + "Speaker" +- "MonoSpeaker" + ] + + EnableSequence [ +@@ -24,7 +23,9 @@ SectionDevice."Headphones" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/rt5651/IN1-InternalMic.conf b/ucm2/codecs/rt5651/IN1-InternalMic.conf +index 01b786e..13c7cb6 100644 +--- a/ucm2/codecs/rt5651/IN1-InternalMic.conf ++++ b/ucm2/codecs/rt5651/IN1-InternalMic.conf +@@ -1,14 +1,6 @@ +-SectionDevice."InternalMic-IN1" { ++SectionDevice."Mic" { + Comment "Internal Microphone on IN1" + +- ConflictingDevice [ +- "DigitalMic" +- "InternalMic-IN2" +- "InternalMic-IN12" +- "HeadsetMic-IN2" +- "HeadsetMic-IN3" +- ] +- + EnableSequence [ + cset "name='Internal Mic Switch' on" + cset "name='RECMIXL BST1 Switch' on" +@@ -26,6 +18,8 @@ SectionDevice."InternalMic-IN1" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/IN12-InternalMic.conf b/ucm2/codecs/rt5651/IN12-InternalMic.conf +index 44cc53a..e017541 100644 +--- a/ucm2/codecs/rt5651/IN12-InternalMic.conf ++++ b/ucm2/codecs/rt5651/IN12-InternalMic.conf +@@ -1,14 +1,6 @@ +-SectionDevice."InternalMic-IN12" { ++SectionDevice."Mic" { + Comment "Internal Microphones on IN1 and IN2" + +- ConflictingDevice [ +- "DigitalMic" +- "InternalMic-IN1" +- "InternalMic-IN2" +- "HeadsetMic-IN2" +- "HeadsetMic-IN3" +- ] +- + EnableSequence [ + cset "name='Internal Mic Switch' on" + cset "name='RECMIXL BST1 Switch' on" +@@ -30,6 +22,8 @@ SectionDevice."InternalMic-IN12" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/IN2-HeadsetMic.conf b/ucm2/codecs/rt5651/IN2-HeadsetMic.conf +index 177f70b..5b51439 100644 +--- a/ucm2/codecs/rt5651/IN2-HeadsetMic.conf ++++ b/ucm2/codecs/rt5651/IN2-HeadsetMic.conf +@@ -1,12 +1,8 @@ +-SectionDevice."HeadsetMic-IN2" { ++SectionDevice."Headset" { + Comment "Headset Microphone on IN2" + + ConflictingDevice [ +- "DigitalMic" +- "InternalMic-IN1" +- "InternalMic-IN2" +- "InternalMic-IN12" +- "HeadsetMic-IN3" ++ "Mic" + ] + + EnableSequence [ +@@ -26,7 +22,9 @@ SectionDevice."HeadsetMic-IN2" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/rt5651/IN2-InternalMic.conf b/ucm2/codecs/rt5651/IN2-InternalMic.conf +index 611ca6c..9eeef4d 100644 +--- a/ucm2/codecs/rt5651/IN2-InternalMic.conf ++++ b/ucm2/codecs/rt5651/IN2-InternalMic.conf +@@ -1,14 +1,6 @@ +-SectionDevice."InternalMic-IN2" { ++SectionDevice."Mic" { + Comment "Internal Microphone on IN2" + +- ConflictingDevice [ +- "DigitalMic" +- "InternalMic-IN1" +- "InternalMic-IN12" +- "HeadsetMic-IN2" +- "HeadsetMic-IN3" +- ] +- + EnableSequence [ + cset "name='Internal Mic Switch' on" + cset "name='RECMIXL BST2 Switch' on" +@@ -26,6 +18,8 @@ SectionDevice."InternalMic-IN2" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/IN3-HeadsetMic.conf b/ucm2/codecs/rt5651/IN3-HeadsetMic.conf +index 3231e78..d579dcd 100644 +--- a/ucm2/codecs/rt5651/IN3-HeadsetMic.conf ++++ b/ucm2/codecs/rt5651/IN3-HeadsetMic.conf +@@ -1,12 +1,8 @@ +-SectionDevice."HeadsetMic-IN3" { ++SectionDevice."Headset" { + Comment "Headset Microphone on IN3" + + ConflictingDevice [ +- "DigitalMic" +- "InternalMic-IN1" +- "InternalMic-IN2" +- "InternalMic-IN12" +- "HeadsetMic-IN2" ++ "Mic" + ] + + EnableSequence [ +@@ -26,7 +22,9 @@ SectionDevice."HeadsetMic-IN3" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/rt5651/MonoSpeaker.conf b/ucm2/codecs/rt5651/MonoSpeaker.conf +index c2276c6..9c780a0 100644 +--- a/ucm2/codecs/rt5651/MonoSpeaker.conf ++++ b/ucm2/codecs/rt5651/MonoSpeaker.conf +@@ -1,8 +1,7 @@ +-SectionDevice."MonoSpeaker" { ++SectionDevice."Speaker" { + Comment "Mono Speaker" + + ConflictingDevice [ +- "Speaker" + "Headphones" + ] + +@@ -42,6 +41,8 @@ SectionDevice."MonoSpeaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/Speaker.conf b/ucm2/codecs/rt5651/Speaker.conf +index 463d13b..efc12e5 100644 +--- a/ucm2/codecs/rt5651/Speaker.conf ++++ b/ucm2/codecs/rt5651/Speaker.conf +@@ -2,7 +2,6 @@ SectionDevice."Speaker" { + Comment "Speakers" + + ConflictingDevice [ +- "MonoSpeaker" + "Headphones" + ] + +@@ -24,6 +23,8 @@ SectionDevice."Speaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + } +-- +2.24.1 + + +From 9b0f31cc65b558c0eee98be583b8a8108341e53d Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 23 Jan 2020 19:45:00 +0100 +Subject: [PATCH 10/36] bytcht-cx2072x: cleanups and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/bytcht-cx2072x/HiFi.conf | 5 ----- + ucm2/codecs/cx2072x/HeadPhones.conf | 4 +++- + ucm2/codecs/cx2072x/HeadsetMic.conf | 8 +++++--- + ucm2/codecs/cx2072x/InternalMic.conf | 8 +++++--- + ucm2/codecs/cx2072x/Speaker.conf | 4 +++- + 5 files changed, 16 insertions(+), 13 deletions(-) + +diff --git a/ucm2/bytcht-cx2072x/HiFi.conf b/ucm2/bytcht-cx2072x/HiFi.conf +index 60e0229..b329ea4 100644 +--- a/ucm2/bytcht-cx2072x/HiFi.conf ++++ b/ucm2/bytcht-cx2072x/HiFi.conf +@@ -8,11 +8,6 @@ SectionVerb { + + + ] +- +- Value { +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" +- } + } + + +diff --git a/ucm2/codecs/cx2072x/HeadPhones.conf b/ucm2/codecs/cx2072x/HeadPhones.conf +index b5d3d3a..484d020 100644 +--- a/ucm2/codecs/cx2072x/HeadPhones.conf ++++ b/ucm2/codecs/cx2072x/HeadPhones.conf +@@ -16,7 +16,9 @@ SectionDevice."Headphones" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/cx2072x/HeadsetMic.conf b/ucm2/codecs/cx2072x/HeadsetMic.conf +index 0a59750..b1a7771 100644 +--- a/ucm2/codecs/cx2072x/HeadsetMic.conf ++++ b/ucm2/codecs/cx2072x/HeadsetMic.conf +@@ -1,8 +1,8 @@ +-SectionDevice."HeadsetMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + ConflictingDevice [ +- "InternalMic" ++ "Mic" + ] + + EnableSequence [ +@@ -17,7 +17,9 @@ SectionDevice."HeadsetMic" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/cx2072x/InternalMic.conf b/ucm2/codecs/cx2072x/InternalMic.conf +index e358c35..831c3cc 100644 +--- a/ucm2/codecs/cx2072x/InternalMic.conf ++++ b/ucm2/codecs/cx2072x/InternalMic.conf +@@ -1,8 +1,8 @@ +-SectionDevice."InternalMic" { ++SectionDevice."Mic" { + Comment "Internal Microphone" + + ConflictingDevice [ +- "HeadsetMic" ++ "Headset" + ] + + EnableSequence [ +@@ -17,6 +17,8 @@ SectionDevice."InternalMic" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/cx2072x/Speaker.conf b/ucm2/codecs/cx2072x/Speaker.conf +index a83aeae..f60e355 100644 +--- a/ucm2/codecs/cx2072x/Speaker.conf ++++ b/ucm2/codecs/cx2072x/Speaker.conf +@@ -16,6 +16,8 @@ SectionDevice."Speaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + } +-- +2.24.1 + + +From 7248ff84f18dc56d289937a81adfdc3852ee8a8f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 23 Jan 2020 19:53:52 +0100 +Subject: [PATCH 11/36] bytcht-es8316: cleanups and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/codecs/es8316/HeadPhones.conf | 7 ++++--- + ucm2/codecs/es8316/IN1-HeadsetMic.conf | 10 +++++----- + ucm2/codecs/es8316/IN1-InternalMic.conf | 10 +++++----- + ucm2/codecs/es8316/IN2-HeadsetMic.conf | 10 +++++----- + ucm2/codecs/es8316/IN2-InternalMic.conf | 6 ++++-- + ucm2/codecs/es8316/MonoSpeaker.conf | 7 ++++--- + ucm2/codecs/es8316/Speaker.conf | 4 +++- + 7 files changed, 30 insertions(+), 24 deletions(-) + +diff --git a/ucm2/codecs/es8316/HeadPhones.conf b/ucm2/codecs/es8316/HeadPhones.conf +index 3f3e591..603b40c 100644 +--- a/ucm2/codecs/es8316/HeadPhones.conf ++++ b/ucm2/codecs/es8316/HeadPhones.conf +@@ -3,7 +3,6 @@ SectionDevice."Headphones" { + + ConflictingDevice [ + "Speaker" +- "MonoSpeaker" + ] + + EnableSequence [ +@@ -15,8 +14,10 @@ SectionDevice."Headphones" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackChannels 2 + JackControl "Headphone Jack" +- JackHWMute "Speaker MonoSpeaker" ++ JackHWMute "Speaker" + } + } +diff --git a/ucm2/codecs/es8316/IN1-HeadsetMic.conf b/ucm2/codecs/es8316/IN1-HeadsetMic.conf +index 997a50b..d798270 100644 +--- a/ucm2/codecs/es8316/IN1-HeadsetMic.conf ++++ b/ucm2/codecs/es8316/IN1-HeadsetMic.conf +@@ -1,10 +1,8 @@ +-SectionDevice."HeadsetMic-IN1" { ++SectionDevice."Headset" { + Comment "Headset Microphone on IN1" + + ConflictingDevice [ +- "InternalMic-IN1" +- "InternalMic-IN2" +- "HeadsetMic-IN2" ++ "Mic" + ] + + EnableSequence [ +@@ -17,7 +15,9 @@ SectionDevice."HeadsetMic-IN1" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId},0" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/es8316/IN1-InternalMic.conf b/ucm2/codecs/es8316/IN1-InternalMic.conf +index 70a77b9..31c5cda 100644 +--- a/ucm2/codecs/es8316/IN1-InternalMic.conf ++++ b/ucm2/codecs/es8316/IN1-InternalMic.conf +@@ -1,10 +1,8 @@ +-SectionDevice."InternalMic-IN1" { ++SectionDevice."Mic" { + Comment "Internal Microphone on IN1" + + ConflictingDevice [ +- "InternalMic-IN2" +- "HeadsetMic-IN1" +- "HeadsetMic-IN2" ++ "Headset" + ] + + EnableSequence [ +@@ -17,6 +15,8 @@ SectionDevice."InternalMic-IN1" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/IN2-HeadsetMic.conf b/ucm2/codecs/es8316/IN2-HeadsetMic.conf +index 1ab1221..28f26f8 100644 +--- a/ucm2/codecs/es8316/IN2-HeadsetMic.conf ++++ b/ucm2/codecs/es8316/IN2-HeadsetMic.conf +@@ -1,10 +1,8 @@ +-SectionDevice."HeadsetMic-IN2" { ++SectionDevice."Headset" { + Comment "Headset Microphone on IN2" + + ConflictingDevice [ +- "InternalMic-IN1" +- "InternalMic-IN2" +- "HeadsetMic-IN1" ++ "Mic" + ] + + EnableSequence [ +@@ -17,7 +15,9 @@ SectionDevice."HeadsetMic-IN2" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId},0" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/es8316/IN2-InternalMic.conf b/ucm2/codecs/es8316/IN2-InternalMic.conf +index 7809f8a..8c0418f 100644 +--- a/ucm2/codecs/es8316/IN2-InternalMic.conf ++++ b/ucm2/codecs/es8316/IN2-InternalMic.conf +@@ -1,4 +1,4 @@ +-SectionDevice."InternalMic-IN2" { ++SectionDevice."Mic" { + Comment "Internal Microphone on IN2" + + ConflictingDevice [ +@@ -17,6 +17,8 @@ SectionDevice."InternalMic-IN2" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},0" ++ CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/MonoSpeaker.conf b/ucm2/codecs/es8316/MonoSpeaker.conf +index 704556a..f11f2b7 100644 +--- a/ucm2/codecs/es8316/MonoSpeaker.conf ++++ b/ucm2/codecs/es8316/MonoSpeaker.conf +@@ -1,8 +1,7 @@ +-SectionDevice."MonoSpeaker" { ++SectionDevice."Speaker" { + Comment "Mono Speaker" + + ConflictingDevice [ +- "Speaker" + "Headphones" + ] + +@@ -32,6 +31,8 @@ SectionDevice."MonoSpeaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/Speaker.conf b/ucm2/codecs/es8316/Speaker.conf +index 0e77746..a1e4491 100644 +--- a/ucm2/codecs/es8316/Speaker.conf ++++ b/ucm2/codecs/es8316/Speaker.conf +@@ -15,6 +15,8 @@ SectionDevice."Speaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackChannels 2 + } + } +-- +2.24.1 + + +From 2ccb7969e0be03c1a47260dbb34d0c7865c5593f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 23 Jan 2020 19:56:19 +0100 +Subject: [PATCH 12/36] DAISY-I2S: added back PCM devices + +Signed-off-by: Jaroslav Kysela +--- + ucm2/DAISY-I2S/HiFi.conf | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/ucm2/DAISY-I2S/HiFi.conf b/ucm2/DAISY-I2S/HiFi.conf +index 02292f2..877f6ff 100644 +--- a/ucm2/DAISY-I2S/HiFi.conf ++++ b/ucm2/DAISY-I2S/HiFi.conf +@@ -27,6 +27,11 @@ SectionDevice."Headphones" { + cset "name='Left Speaker Mixer Left DAC1 Switch' on" + cset "name='Right Speaker Mixer Right DAC1 Switch' on" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ } + } + + SectionDevice."Mic" { +@@ -43,4 +48,9 @@ SectionDevice."Mic" { + cset "name='DMIC1 Left Capture Switch' on" + cset "name='DMIC1 Right Capture Switch' on" + ] ++ ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ } + } +-- +2.24.1 + + +From 1a824b16b8fc26122deec2a6307b8294dc1bc497 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 24 Jan 2020 10:07:14 +0100 +Subject: [PATCH 13/36] DB410c: cleanups and corrections + +--- + ucm2/DB410c/HDMI.conf | 9 +++++--- + ucm2/DB410c/HiFi.conf | 50 ++++++++++++++++++++++++++++++++++--------- + 2 files changed, 46 insertions(+), 13 deletions(-) + +diff --git a/ucm2/DB410c/HDMI.conf b/ucm2/DB410c/HDMI.conf +index d08a50b..fa44132 100644 +--- a/ucm2/DB410c/HDMI.conf ++++ b/ucm2/DB410c/HDMI.conf +@@ -4,12 +4,15 @@ + SectionVerb { + Value { + TQ "HiFi" +- PlaybackPCM "plughw:${CardId},0" +- PlaybackChannels "2" ++ PlaybackChannels 2 + } + } + +-SectionDevice."HDMI-stereo" { ++SectionDevice."HDMI" { + # Name "HDMI-stereo" + Comment "HDMI Digital Stereo Output" ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "plughw:${CardId}" ++ } + } +diff --git a/ucm2/DB410c/HiFi.conf b/ucm2/DB410c/HiFi.conf +index 848d02f..1b2716a 100644 +--- a/ucm2/DB410c/HiFi.conf ++++ b/ucm2/DB410c/HiFi.conf +@@ -2,14 +2,9 @@ + # Author: Srinivas Kandagatla + + SectionVerb { +- +- # ALSA PCM + Value { +- # ALSA PCM device for HiFi +- PlaybackPCM "plughw:${CardId},1" +- CapturePCM "plughw:${CardId},2" +- PlaybackChannels "2" +- CaptureChannels "2" ++ PlaybackChannels 2 ++ CaptureChannels 2 + } + } + +@@ -33,6 +28,11 @@ SectionDevice."Speaker" { + cset "name='SPK DAC Switch' 0" + cset "name='RX3 MIX1 INP1' ZERO" + ] ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "plughw:${CardId},1" ++ } + } + + +@@ -64,6 +64,11 @@ SectionDevice."Headphones" { + cset "name='RX1 MIX1 INP1' ZERO" + cset "name='RX2 MIX1 INP1' ZERO" + ] ++ ++ Value { ++ PlaybackPriority 300 ++ PlaybackPCM "plughw:${CardId},1" ++ } + } + + SectionDevice."Earpiece" { +@@ -73,6 +78,11 @@ SectionDevice."Earpiece" { + "Speaker" + "Headphones" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "plughw:${CardId},1" ++ } + } + + SectionDevice."Handset" { +@@ -90,9 +100,14 @@ SectionDevice."Handset" { + cset "name='ADC2 Volume' 0" + cset "name='DEC1 MUX' ZERO" + ] ++ ++ Value { ++ CapturePriority 400 ++ CapturePCM "plughw:${CardId},2" ++ } + } + +-SectionDevice."PrimaryMic" { ++SectionDevice."Mic1" { + Comment "Primary Microphone" + + EnableSequence [ +@@ -105,9 +120,14 @@ SectionDevice."PrimaryMic" { + cset "name='DEC1 MUX' ZERO" + cset "name='ADC1 Volume' 0" + ] ++ ++ Value { ++ CapturePriority 300 ++ CapturePCM "plughw:${CardId},2" ++ } + } + +-SectionDevice."SecondaryMic" { ++SectionDevice."Mic2" { + Comment "Secondary Microphone" + + EnableSequence [ +@@ -122,9 +142,14 @@ SectionDevice."SecondaryMic" { + cset "name='ADC2 Volume' 0" + cset "name='ADC2 MUX' ZERO" + ] ++ ++ Value { ++ CapturePriority 200 ++ CapturePCM "plughw:${CardId},2" ++ } + } + +-SectionDevice."DigitalMic" { ++SectionDevice."Mic3" { + Comment "Digital Microphone" + + EnableSequence [ +@@ -135,4 +160,9 @@ SectionDevice."DigitalMic" { + DisableSequence [ + cset "name='DEC1 MUX' ZERO" + ] ++ ++ Value { ++ CapturePriority 100 ++ CapturePCM "plughw:${CardId},2" ++ } + } +-- +2.24.1 + + +From 86a9fad7760fa40282821a3d7818ac881dd2f92d Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 24 Jan 2020 10:14:41 +0100 +Subject: [PATCH 14/36] DB820c: cleanups and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/DB820c/HDMI.conf | 10 ++++++---- + ucm2/DB820c/HiFi.conf | 8 +++++--- + 2 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/ucm2/DB820c/HDMI.conf b/ucm2/DB820c/HDMI.conf +index 76c0e92..c0d40f6 100644 +--- a/ucm2/DB820c/HDMI.conf ++++ b/ucm2/DB820c/HDMI.conf +@@ -8,14 +8,14 @@ SectionVerb { + + DisableSequence [ + cset "name='HDMI Mixer MultiMedia1' 0" ++ ] ++ + Value { + TQ "HiFi" +- PlaybackPCM "plughw:${CardId},0" + } + } + +-SectionDevice."HDMI-stereo" { +- #Name "HDMI-stereo" ++SectionDevice."HDMI" { + Comment "HDMI Digital Stereo Output" + + EnableSequence [ +@@ -27,6 +27,8 @@ SectionDevice."HDMI-stereo" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "plughw:${CardId}" ++ PlaybackChannels 2 + } + } +diff --git a/ucm2/DB820c/HiFi.conf b/ucm2/DB820c/HiFi.conf +index fa7770e..501c263 100644 +--- a/ucm2/DB820c/HiFi.conf ++++ b/ucm2/DB820c/HiFi.conf +@@ -67,12 +67,13 @@ SectionDevice."Headphones" { + ] + + Value { ++ PlaybackPriority 100 + PlaybackPCM "plughw:${CardId},1" +- PlaybackChannels "2" ++ PlaybackChannels 2 + } + } + +-SectionDevice."HandsetMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + EnableSequence [ +@@ -93,7 +94,8 @@ SectionDevice."HandsetMic" { + ] + + Value { ++ CapturePriority 100 + CapturePCM "plughw:${CardId},2" +- CaptureChannels "1" ++ CaptureChannels 1 + } + } +-- +2.24.1 + + +From 42d0227c417e732ac76328e4168d885b07211f92 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 24 Jan 2020 10:15:58 +0100 +Subject: [PATCH 15/36] Dell-WD15-Dock: cleaups and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/Dell-WD15-Dock/Dell-WD15-Dock.conf | 6 ----- + ucm2/Dell-WD15-Dock/HiFi.conf | 26 ---------------------- + ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf | 29 +++++++++++++++++++++++++ + ucm2/USB-Audio/Dell-WD15-Dock.conf | 6 +++++ + 4 files changed, 35 insertions(+), 32 deletions(-) + delete mode 100644 ucm2/Dell-WD15-Dock/Dell-WD15-Dock.conf + delete mode 100644 ucm2/Dell-WD15-Dock/HiFi.conf + create mode 100644 ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf + create mode 100644 ucm2/USB-Audio/Dell-WD15-Dock.conf + +diff --git a/ucm2/Dell-WD15-Dock/Dell-WD15-Dock.conf b/ucm2/Dell-WD15-Dock/Dell-WD15-Dock.conf +deleted file mode 100644 +index 7b96a54..0000000 +--- a/ucm2/Dell-WD15-Dock/Dell-WD15-Dock.conf ++++ /dev/null +@@ -1,6 +0,0 @@ +-Syntax 2 +-Comment "USB-audio on Dell WD15 docking station" +-SectionUseCase."HiFi" { +- File "HiFi.conf" +- Comment "Default" +-} +diff --git a/ucm2/Dell-WD15-Dock/HiFi.conf b/ucm2/Dell-WD15-Dock/HiFi.conf +deleted file mode 100644 +index 3b02f81..0000000 +--- a/ucm2/Dell-WD15-Dock/HiFi.conf ++++ /dev/null +@@ -1,26 +0,0 @@ +-SectionDevice."Headphones" { +- Comment "Headphones" +- +- Value { +- PlaybackChannels "2" +- PlaybackPCM "hw:${CardId},0" +- } +-} +- +-SectionDevice."LineOut" { +- Comment "Line Out" +- +- Value { +- PlaybackChannels "2" +- PlaybackPCM "hw:${CardId},1" +- } +-} +- +-SectionDevice."Mic" { +- Comment "Microphone" +- +- Value { +- CaptureChannels "2" +- CapturePCM "hw:${CardId},0" +- } +-} +diff --git a/ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf b/ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf +new file mode 100644 +index 0000000..37b7e0d +--- /dev/null ++++ b/ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf +@@ -0,0 +1,29 @@ ++SectionDevice."Headphones" { ++ Comment "Headphones" ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackChannels 2 ++ PlaybackPCM "hw:${CardId}" ++ } ++} ++ ++SectionDevice."Line" { ++ Comment "Line Out" ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackChannels 2 ++ PlaybackPCM "hw:${CardId},1" ++ } ++} ++ ++SectionDevice."Mic" { ++ Comment "Microphone" ++ ++ Value { ++ CapturePriority 100 ++ CaptureChannels 2 ++ CapturePCM "hw:${CardId}" ++ } ++} +diff --git a/ucm2/USB-Audio/Dell-WD15-Dock.conf b/ucm2/USB-Audio/Dell-WD15-Dock.conf +new file mode 100644 +index 0000000..1fbac9e +--- /dev/null ++++ b/ucm2/USB-Audio/Dell-WD15-Dock.conf +@@ -0,0 +1,6 @@ ++Syntax 2 ++Comment "USB-audio on Dell WD15 docking station" ++SectionUseCase."HiFi" { ++ File "Dell-WD15-Dock-HiFi.conf" ++ Comment "Default" ++} +-- +2.24.1 + + +From dfad18452427460bf50c55a2c06f9460b2db2123 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 24 Jan 2020 11:06:29 +0100 +Subject: [PATCH 16/36] HDA-Intel/HiFi-dual: fixes and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/HDA Intel PCH/HDAudio-DualCodecs.conf | 6 - + .../HDAudio-Gigabyte-ALC1220DualCodecs.conf | 1 - + .../HDAudio-Lenovo-DualCodecs.conf | 1 - + ucm2/HDA Intel PCH/HiFi-dual.conf | 144 ------------------ + ucm2/HDA-Intel/HDAudio-DualCodecs.conf | 6 + + .../HDAudio-Gigabyte-ALC1220DualCodecs.conf | 1 + + ucm2/HDA-Intel/HDAudio-Lenovo-DualCodecs.conf | 1 + + ucm2/HDA-Intel/HiFi-dual.conf | 118 ++++++++++++++ + 8 files changed, 126 insertions(+), 152 deletions(-) + delete mode 100644 ucm2/HDA Intel PCH/HDAudio-DualCodecs.conf + delete mode 120000 ucm2/HDA Intel PCH/HDAudio-Gigabyte-ALC1220DualCodecs.conf + delete mode 120000 ucm2/HDA Intel PCH/HDAudio-Lenovo-DualCodecs.conf + delete mode 100644 ucm2/HDA Intel PCH/HiFi-dual.conf + create mode 100644 ucm2/HDA-Intel/HDAudio-DualCodecs.conf + create mode 120000 ucm2/HDA-Intel/HDAudio-Gigabyte-ALC1220DualCodecs.conf + create mode 120000 ucm2/HDA-Intel/HDAudio-Lenovo-DualCodecs.conf + create mode 100644 ucm2/HDA-Intel/HiFi-dual.conf + +diff --git a/ucm2/HDA Intel PCH/HDAudio-DualCodecs.conf b/ucm2/HDA Intel PCH/HDAudio-DualCodecs.conf +deleted file mode 100644 +index 8aaabd0..0000000 +--- a/ucm2/HDA Intel PCH/HDAudio-DualCodecs.conf ++++ /dev/null +@@ -1,6 +0,0 @@ +-Syntax 2 +-Comment "HDAudio with dual HD-audio codecs" +-SectionUseCase."HiFi" { +- File "HiFi-dual.conf" +- Comment "Default" +-} +diff --git a/ucm2/HDA Intel PCH/HDAudio-Gigabyte-ALC1220DualCodecs.conf b/ucm2/HDA Intel PCH/HDAudio-Gigabyte-ALC1220DualCodecs.conf +deleted file mode 120000 +index 89801aa..0000000 +--- a/ucm2/HDA Intel PCH/HDAudio-Gigabyte-ALC1220DualCodecs.conf ++++ /dev/null +@@ -1 +0,0 @@ +-HDAudio-DualCodecs.conf +\ No newline at end of file +diff --git a/ucm2/HDA Intel PCH/HDAudio-Lenovo-DualCodecs.conf b/ucm2/HDA Intel PCH/HDAudio-Lenovo-DualCodecs.conf +deleted file mode 120000 +index 89801aa..0000000 +--- a/ucm2/HDA Intel PCH/HDAudio-Lenovo-DualCodecs.conf ++++ /dev/null +@@ -1 +0,0 @@ +-HDAudio-DualCodecs.conf +\ No newline at end of file +diff --git a/ucm2/HDA Intel PCH/HiFi-dual.conf b/ucm2/HDA Intel PCH/HiFi-dual.conf +deleted file mode 100644 +index 63b3fe6..0000000 +--- a/ucm2/HDA Intel PCH/HiFi-dual.conf ++++ /dev/null +@@ -1,144 +0,0 @@ +-SectionVerb { +- Value { +- TQ "HiFi" +- } +- +- EnableSequence [ +- cset "name='Front Playback Volume' 100%" +- cset "name='Front Playback Switch' on" +- cset "name='Rear-Panel Capture Volume' 100%" +- cset "name='Rear-Panel Capture Switch' on" +- ] +- +- DisableSequence [ +- cset "name='Front Playback Volume' 0" +- cset "name='Front Playback Switch' off" +- cset "name='Rear-Panel Capture Volume' 0" +- cset "name='Rear-Panel Capture Switch' off" +- ] +-} +- +-SectionDevice."Speaker" { +- Comment "Speaker" +- +- Value { +- PlaybackChannels "2" +- PlaybackPCM "hw:${CardId},4" +- } +- +- ConflictingDevice [ +- "Headphone" +- ] +- +- EnableSequence [ +- cset "name='Speaker Playback Switch' on" +- cset "name='Speaker Playback Volume' 100%" +- ] +- +- DisableSequence [ +- cset "name='Speaker Playback Volume' 0" +- cset "name='Speaker Playback Switch' off" +- ] +-} +- +-SectionDevice."LineOut" { +- Comment "Line Out" +- +- Value { +- PlaybackChannels "2" +- PlaybackPCM "hw:${CardId},0" +- JackControl "Line Out Jack" +- JackHWMute "Speaker" +- } +-} +- +-SectionDevice."Headphones" { +- Comment "Headphones" +- +- Value { +- PlaybackChannels "2" +- PlaybackPCM "hw:${CardId},4" +- JackControl "Front Headphone Jack" +- JackHWMute "Speaker" +- } +- +- ConflictingDevice [ +- "Speaker" +- ] +- +- EnableSequence [ +- cset "name='Headphone Playback Switch' on" +- cset "name='Headphone Playback Volume' 100%" +- ] +- +- DisableSequence [ +- cset "name='Headphone Playback Volume' 0" +- cset "name='Headphone Playback Switch' off" +- ] +-} +- +-SectionDevice."LineIn" { +- Comment "Rear Line In" +- +- Value { +- CaptureChannels "2" +- CapturePCM "hw:${CardId},0" +- JackControl "Line Jack" +- } +- +- ConflictingDevice [ +- "RearMic" +- ] +- +- EnableSequence [ +- cset "name='Input Source' Line" +- If.0 { +- Condition { +- Type ControlExists +- Control "name='Line Boost Volume'" +- } +- True { +- cset "name='Line Boost Volume' 3" +- } +- } +- ] +-} +- +-SectionDevice."RearMic" { +- Comment "Rear Microphone" +- +- Value { +- CaptureChannels "2" +- CapturePCM "hw:${CardId},0" +- # CapturePriority "150" +- JackHWMute "LineIn" +- } +- +- ConflictingDevice [ +- "LineIn" +- ] +- +- EnableSequence [ +- cset "name='Input Source' Rear Mic" +- ] +-} +- +-SectionDevice."FrontMic" { +- Comment "Front Microphone" +- +- Value { +- CaptureChannels "2" +- CapturePCM "hw:${CardId},4" +- JackControl "Front Mic Jack" +- } +- +- EnableSequence [ +- cset "name='Front-Panel Capture Volume' 100%" +- cset "name='Front-Panel Capture Switch' on" +- ] +- +- DisableSequence [ +- cset "name='Front-Panel Capture Volume' 0" +- cset "name='Front-Panel Capture Switch' off" +- ] +-} +diff --git a/ucm2/HDA-Intel/HDAudio-DualCodecs.conf b/ucm2/HDA-Intel/HDAudio-DualCodecs.conf +new file mode 100644 +index 0000000..8aaabd0 +--- /dev/null ++++ b/ucm2/HDA-Intel/HDAudio-DualCodecs.conf +@@ -0,0 +1,6 @@ ++Syntax 2 ++Comment "HDAudio with dual HD-audio codecs" ++SectionUseCase."HiFi" { ++ File "HiFi-dual.conf" ++ Comment "Default" ++} +diff --git a/ucm2/HDA-Intel/HDAudio-Gigabyte-ALC1220DualCodecs.conf b/ucm2/HDA-Intel/HDAudio-Gigabyte-ALC1220DualCodecs.conf +new file mode 120000 +index 0000000..89801aa +--- /dev/null ++++ b/ucm2/HDA-Intel/HDAudio-Gigabyte-ALC1220DualCodecs.conf +@@ -0,0 +1 @@ ++HDAudio-DualCodecs.conf +\ No newline at end of file +diff --git a/ucm2/HDA-Intel/HDAudio-Lenovo-DualCodecs.conf b/ucm2/HDA-Intel/HDAudio-Lenovo-DualCodecs.conf +new file mode 120000 +index 0000000..89801aa +--- /dev/null ++++ b/ucm2/HDA-Intel/HDAudio-Lenovo-DualCodecs.conf +@@ -0,0 +1 @@ ++HDAudio-DualCodecs.conf +\ No newline at end of file +diff --git a/ucm2/HDA-Intel/HiFi-dual.conf b/ucm2/HDA-Intel/HiFi-dual.conf +new file mode 100644 +index 0000000..846c6db +--- /dev/null ++++ b/ucm2/HDA-Intel/HiFi-dual.conf +@@ -0,0 +1,118 @@ ++SectionVerb { ++ Value { ++ TQ "HiFi" ++ PlaybackChannels 2 ++ CaptureChannels 2 ++ } ++ ++ EnableSequence [ ++ cset "name='Front Playback Volume' 100%" ++ cset "name='Front Playback Switch' on" ++ cset "name='Rear-Panel Capture Volume' 100%" ++ cset "name='Rear-Panel Capture Switch' on" ++ ] ++ ++ DisableSequence [ ++ cset "name='Front Playback Volume' 0" ++ cset "name='Front Playback Switch' off" ++ cset "name='Rear-Panel Capture Volume' 0" ++ cset "name='Rear-Panel Capture Switch' off" ++ ] ++} ++ ++SectionDevice."Speaker" { ++ Comment "Speaker" ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},4" ++ PlaybackMixerElem "Speaker" ++ } ++ ++ ConflictingDevice [ ++ "Headphones" ++ ] ++} ++ ++SectionDevice."Line1" { ++ Comment "Line Out" ++ ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ JackControl "Line Out Jack" ++ JackHWMute "Speaker" ++ } ++} ++ ++SectionDevice."Headphones" { ++ Comment "Headphones" ++ ++ Value { ++ PlaybackPriority 300 ++ PlaybackPCM "hw:${CardId},4" ++ PlaybackMixerElem "Headphone" ++ JackControl "Front Headphone Jack" ++ JackHWMute "Speaker" ++ } ++ ++ ConflictingDevice [ ++ "Speaker" ++ ] ++} ++ ++SectionDevice."Line2" { ++ Comment "Rear Line In" ++ ++ Value { ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ JackControl "Line Jack" ++ } ++ ++ ConflictingDevice [ ++ "Mic2" ++ ] ++ ++ EnableSequence [ ++ cset "name='Input Source' Line" ++ If.0 { ++ Condition { ++ Type ControlExists ++ Control "name='Line Boost Volume'" ++ } ++ True { ++ cset "name='Line Boost Volume' 3" ++ } ++ } ++ ] ++} ++ ++SectionDevice."Mic2" { ++ Comment "Rear Microphone" ++ ++ Value { ++ CapturePriority 300 ++ CapturePCM "hw:${CardId}" ++ JackHWMute "Line2" ++ } ++ ++ ConflictingDevice [ ++ "Line2" ++ ] ++ ++ EnableSequence [ ++ cset "name='Input Source' Rear Mic" ++ ] ++} ++ ++SectionDevice."Mic1" { ++ Comment "Front Microphone" ++ ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},4" ++ CaptureMixerElem "Front-Panel" ++ JackControl "Front Mic Jack" ++ } ++} +-- +2.24.1 + + +From ffae896c7e958198b795c9680e4e4fb64b88c8ea Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 24 Jan 2020 14:35:10 +0100 +Subject: [PATCH 17/36] cht-bsw-rt5672: fixes and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/cht-bsw-rt5672/HiFi-stereo-dmic2.conf | 9 ++++----- + ucm2/cht-bsw-rt5672/HiFi.conf | 5 ----- + ucm2/codecs/rt5672/DMIC1.conf | 8 +++++--- + ucm2/codecs/rt5672/DMIC2.conf | 8 +++++--- + ucm2/codecs/rt5672/HeadPhones.conf | 8 +++++--- + ucm2/codecs/rt5672/HeadsetMic.conf | 10 ++++++---- + ucm2/codecs/rt5672/MonoSpeaker.conf | 8 +++++--- + ucm2/codecs/rt5672/Speaker.conf | 10 ++++++---- + 8 files changed, 36 insertions(+), 30 deletions(-) + +diff --git a/ucm2/cht-bsw-rt5672/HiFi-stereo-dmic2.conf b/ucm2/cht-bsw-rt5672/HiFi-stereo-dmic2.conf +index 2916490..82c976b 100644 +--- a/ucm2/cht-bsw-rt5672/HiFi-stereo-dmic2.conf ++++ b/ucm2/cht-bsw-rt5672/HiFi-stereo-dmic2.conf +@@ -9,15 +9,14 @@ SectionVerb { + DisableSequence [ + + ] +- +- Value { +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" +- } + } + + ++RenameDevice."Speaker1" "Speaker" ++RemoveDevice."Speaker2" "Speaker2" + + + ++RenameDevice."Mic2" "Mic" ++RemoveDevice."Mic1" "Mic1" + +diff --git a/ucm2/cht-bsw-rt5672/HiFi.conf b/ucm2/cht-bsw-rt5672/HiFi.conf +index 18c6932..9a64cc3 100644 +--- a/ucm2/cht-bsw-rt5672/HiFi.conf ++++ b/ucm2/cht-bsw-rt5672/HiFi.conf +@@ -9,11 +9,6 @@ SectionVerb { + DisableSequence [ + + ] +- +- Value { +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" +- } + } + + +diff --git a/ucm2/codecs/rt5672/DMIC1.conf b/ucm2/codecs/rt5672/DMIC1.conf +index b3da627..73983af 100644 +--- a/ucm2/codecs/rt5672/DMIC1.conf ++++ b/ucm2/codecs/rt5672/DMIC1.conf +@@ -1,9 +1,9 @@ +-SectionDevice."DigitalMic-DMIC1" { ++SectionDevice."Mic1" { + Comment "Internal Digital Microphone on DMIC1" + + ConflictingDevice [ +- "DigitalMic-DMIC2" +- "HeadsetMic" ++ "Mic2" ++ "Headset" + ] + + EnableSequence [ +@@ -21,6 +21,8 @@ SectionDevice."DigitalMic-DMIC1" { + ] + + Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5672/DMIC2.conf b/ucm2/codecs/rt5672/DMIC2.conf +index 38fe015..751c95c 100644 +--- a/ucm2/codecs/rt5672/DMIC2.conf ++++ b/ucm2/codecs/rt5672/DMIC2.conf +@@ -1,9 +1,9 @@ +-SectionDevice."DigitalMic-DMIC2" { ++SectionDevice."Mic2" { + Comment "Internal Digital Microphone on DMIC2" + + ConflictingDevice [ +- "DigitalMic-DMIC1" +- "HeadsetMic" ++ "Mic1" ++ "Headset" + ] + + EnableSequence [ +@@ -21,6 +21,8 @@ SectionDevice."DigitalMic-DMIC2" { + ] + + Value { ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5672/HeadPhones.conf b/ucm2/codecs/rt5672/HeadPhones.conf +index 350fb2b..0542f77 100644 +--- a/ucm2/codecs/rt5672/HeadPhones.conf ++++ b/ucm2/codecs/rt5672/HeadPhones.conf +@@ -2,8 +2,8 @@ SectionDevice."Headphones" { + Comment "Headphones" + + ConflictingDevice [ +- "Speaker" +- "MonoSpeaker" ++ "Speaker1" ++ "Speaker2" + ] + + EnableSequence [ +@@ -15,7 +15,9 @@ SectionDevice."Headphones" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 300 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/rt5672/HeadsetMic.conf b/ucm2/codecs/rt5672/HeadsetMic.conf +index fd02cb3..f407579 100644 +--- a/ucm2/codecs/rt5672/HeadsetMic.conf ++++ b/ucm2/codecs/rt5672/HeadsetMic.conf +@@ -1,9 +1,9 @@ +-SectionDevice."HeadsetMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + ConflictingDevice [ +- "DigitalMic-DMIC1" +- "DigitalMic-DMIC2" ++ "Mic1" ++ "Mic2" + ] + + EnableSequence [ +@@ -30,7 +30,9 @@ SectionDevice."HeadsetMic" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 300 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/rt5672/MonoSpeaker.conf b/ucm2/codecs/rt5672/MonoSpeaker.conf +index 6308ad9..0849c67 100644 +--- a/ucm2/codecs/rt5672/MonoSpeaker.conf ++++ b/ucm2/codecs/rt5672/MonoSpeaker.conf +@@ -1,8 +1,8 @@ +-SectionDevice."MonoSpeaker" { ++SectionDevice."Speaker2" { + Comment "Mono Speaker" + + ConflictingDevice [ +- "Speaker" ++ "Speaker1" + "Headphones" + ] + +@@ -19,6 +19,8 @@ SectionDevice."MonoSpeaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5672/Speaker.conf b/ucm2/codecs/rt5672/Speaker.conf +index e4391cc..44e73aa 100644 +--- a/ucm2/codecs/rt5672/Speaker.conf ++++ b/ucm2/codecs/rt5672/Speaker.conf +@@ -1,8 +1,8 @@ +-SectionDevice."Speaker" { +- Comment "Speakers" ++SectionDevice."Speaker1" { ++ Comment "Stereo Speakers" + + ConflictingDevice [ +- "MonoSpeaker" ++ "Speaker2" + "Headphones" + ] + +@@ -15,6 +15,8 @@ SectionDevice."Speaker" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + } +-- +2.24.1 + + +From 54f0ed010f7353b37a7b0eee109537675323b9d8 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 24 Jan 2020 14:39:26 +0100 +Subject: [PATCH 18/36] chtnau8824: fixes and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/chtnau8824/HiFi-mono.conf | 3 --- + ucm2/chtnau8824/HiFi.conf | 8 -------- + ucm2/codecs/nau8824/HeadPhones.conf | 5 +++-- + ucm2/codecs/nau8824/HeadsetMic.conf | 8 +++++--- + ucm2/codecs/nau8824/InternalMic.conf | 9 +++++---- + ucm2/codecs/nau8824/MonoSpeaker.conf | 7 ++++--- + ucm2/codecs/nau8824/Speaker.conf | 5 +++-- + 7 files changed, 20 insertions(+), 25 deletions(-) + +diff --git a/ucm2/chtnau8824/HiFi-mono.conf b/ucm2/chtnau8824/HiFi-mono.conf +index 3433d03..26d6a56 100644 +--- a/ucm2/chtnau8824/HiFi-mono.conf ++++ b/ucm2/chtnau8824/HiFi-mono.conf +@@ -3,9 +3,6 @@ SectionVerb { + + Value { + TQ "HiFi" +- # ALSA PCM device for HiFi +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" + } + + EnableSequence [ +diff --git a/ucm2/chtnau8824/HiFi.conf b/ucm2/chtnau8824/HiFi.conf +index 9f7ac74..fd8b741 100644 +--- a/ucm2/chtnau8824/HiFi.conf ++++ b/ucm2/chtnau8824/HiFi.conf +@@ -1,13 +1,5 @@ + + SectionVerb { +- +- Value { +- TQ "HiFi" +- # ALSA PCM device for HiFi +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" +- } +- + EnableSequence [ + + +diff --git a/ucm2/codecs/nau8824/HeadPhones.conf b/ucm2/codecs/nau8824/HeadPhones.conf +index f35f4e2..6623365 100644 +--- a/ucm2/codecs/nau8824/HeadPhones.conf ++++ b/ucm2/codecs/nau8824/HeadPhones.conf +@@ -2,12 +2,13 @@ SectionDevice."Headphones" { + Comment "Headphones" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + } + + ConflictingDevice [ +- "MonoSpeaker" + "Speaker" + ] + +diff --git a/ucm2/codecs/nau8824/HeadsetMic.conf b/ucm2/codecs/nau8824/HeadsetMic.conf +index bc17f9f..7381638 100644 +--- a/ucm2/codecs/nau8824/HeadsetMic.conf ++++ b/ucm2/codecs/nau8824/HeadsetMic.conf +@@ -1,13 +1,15 @@ +-SectionDevice."HeadsetMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + Value { +- CaptureChannels "2" ++ CapturePriority 300 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + } + + ConflictingDevice [ +- "InternalMic" ++ "Mic" + ] + + EnableSequence [ +diff --git a/ucm2/codecs/nau8824/InternalMic.conf b/ucm2/codecs/nau8824/InternalMic.conf +index 3793d64..731a261 100644 +--- a/ucm2/codecs/nau8824/InternalMic.conf ++++ b/ucm2/codecs/nau8824/InternalMic.conf +@@ -1,13 +1,14 @@ +-SectionDevice."InternalMic" { ++SectionDevice."Mic" { + Comment "Internal Microphone" + + Value { +- CaptureChannels "2" +- CapturePriority "150" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + + ConflictingDevice [ +- "HeadsetMic" ++ "Headset" + ] + + EnableSequence [ +diff --git a/ucm2/codecs/nau8824/MonoSpeaker.conf b/ucm2/codecs/nau8824/MonoSpeaker.conf +index 5321c8a..b02a22c 100644 +--- a/ucm2/codecs/nau8824/MonoSpeaker.conf ++++ b/ucm2/codecs/nau8824/MonoSpeaker.conf +@@ -1,12 +1,13 @@ +-SectionDevice."MonoSpeaker" { ++SectionDevice."Speaker" { + Comment "Mono Speaker" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + + ConflictingDevice [ +- "Speaker" + "Headphones" + ] + +diff --git a/ucm2/codecs/nau8824/Speaker.conf b/ucm2/codecs/nau8824/Speaker.conf +index 474c373..3658795 100644 +--- a/ucm2/codecs/nau8824/Speaker.conf ++++ b/ucm2/codecs/nau8824/Speaker.conf +@@ -2,11 +2,12 @@ SectionDevice."Speaker" { + Comment "Speaker" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + + ConflictingDevice [ +- "MonoSpeaker" + "Headphones" + ] + +-- +2.24.1 + + +From ed9918179e37e091a861cea57022d45ff50b2bca Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 27 Jan 2020 16:01:21 +0100 +Subject: [PATCH 19/36] skylake-rt286: fixes and corrections + +Signed-off-by: Jaroslav Kysela +--- + ucm2/skylake-rt286/Hdmi1.conf | 7 +++--- + ucm2/skylake-rt286/Hdmi2.conf | 7 +++--- + ucm2/skylake-rt286/HiFi.conf | 36 ++++++++++++--------------- + ucm2/skylake-rt286/skylake-rt286.conf | 14 ++--------- + 4 files changed, 24 insertions(+), 40 deletions(-) + +diff --git a/ucm2/skylake-rt286/Hdmi1.conf b/ucm2/skylake-rt286/Hdmi1.conf +index 975fd39..5a56943 100644 +--- a/ucm2/skylake-rt286/Hdmi1.conf ++++ b/ucm2/skylake-rt286/Hdmi1.conf +@@ -1,16 +1,15 @@ + # Usecase for device HDMI1/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms + # For Audio in I2S mode + +-SectionDevice."Hdmi1" { ++SectionDevice."HDMI1" { + Comment "HDMI/Display Port 1 Stereo" + + Value { ++ PlaybackPriority 300 + PlaybackPCM "hw:${CardId},4" +- PlaybackChannels "2" +- PlaybackPriority "3" + If.1 { + Condition { +- ControlExists ++ Type ControlExists + Control "iface=CARD,name='HDMI/DP,pcm=4 Jack'" + } + True { +diff --git a/ucm2/skylake-rt286/Hdmi2.conf b/ucm2/skylake-rt286/Hdmi2.conf +index d6ca62f..d2780b6 100644 +--- a/ucm2/skylake-rt286/Hdmi2.conf ++++ b/ucm2/skylake-rt286/Hdmi2.conf +@@ -1,16 +1,15 @@ + # Usecase for device HDMI2/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms + # For Audio in I2S mode + +-SectionDevice."Hdmi2" { ++SectionDevice."HDMI2" { + Comment "HDMI/Display Port 2 Stereo" + + Value { ++ PlaybackPriority 400 + PlaybackPCM "hw:${CardId},5" +- PlaybackChannels "2" +- PlaybackPriority "4" + If.1 { + Condition { +- ControlExists ++ Type ControlExists + Control "iface=CARD,name='HDMI/DP,pcm=5 Jack'" + } + True { +diff --git a/ucm2/skylake-rt286/HiFi.conf b/ucm2/skylake-rt286/HiFi.conf +index 489170f..9e94a1b 100644 +--- a/ucm2/skylake-rt286/HiFi.conf ++++ b/ucm2/skylake-rt286/HiFi.conf +@@ -2,15 +2,12 @@ + # For Audio in I2S mode on Intel SKYLAKE/KABYLAKE platforms + + SectionVerb { +- + EnableSequence [ + cset "name='media0_out mo dmic01_hifi_in mi Switch' 1" + ] + + Value { + TQ "HiFi" +- CapturePCM "hw:${CardId},1" +- PlaybackPCM "hw:${CardId},0" + } + } + +@@ -20,6 +17,7 @@ SectionDevice."Headphones" { + ConflictingDevice [ + "Speaker" + ] ++ + EnableSequence [ + cset "name='HPO L Switch' 1" + cset "name='HPO R Switch' 1" +@@ -27,11 +25,9 @@ SectionDevice."Headphones" { + cset "name='Speaker Playback Switch' 0,0" + ] + +- DisableSequence [ +- ] + Value { +- PlaybackChannels "2" +- PlaybackPriority "1" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -43,6 +39,7 @@ SectionDevice."Speaker" { + ConflictingDevice [ + "Headphones" + ] ++ + EnableSequence [ + cset "name='SPO Switch' 1" + cset "name='Speaker Playback Switch' 1,1" +@@ -51,20 +48,18 @@ SectionDevice."Speaker" { + cset "name='HPO R Switch' 0" + ] + +- DisableSequence [ +- ] + Value { +- PlaybackChannels "2" +- PlaybackPriority "1" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" + JackHWMute "Headphones" + } + } + + SectionDevice."Headset" { +- Comment "Headset Mic" ++ Comment "Headset Microphone" + + ConflictingDevice [ +- "dmiccap" ++ "Mic" + ] + EnableSequence [ + cset "name='media0_out mo codec0_in mi Switch' 1" +@@ -79,15 +74,14 @@ SectionDevice."Headset" { + cset "name='media0_out mo codec0_in mi Switch' 0" + ] + Value { +- CaptureChannels "2" +- CapturePriority "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId},1" + JackControl "Mic Jack" + } + } + +- +-SectionDevice."dmiccap" { +- Comment "DMIC Stereo" ++SectionDevice."Mic" { ++ Comment "Digital Stereo Microphone" + + ConflictingDevice [ + "Headset" +@@ -110,8 +104,10 @@ SectionDevice."dmiccap" { + cset "name='ADC 0 Mux' 2" + ] + Value { +- CaptureChannels "2" +- CapturePriority "2" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},1" + } + } + ++ ++ +diff --git a/ucm2/skylake-rt286/skylake-rt286.conf b/ucm2/skylake-rt286/skylake-rt286.conf +index efb8a20..4ea5777 100644 +--- a/ucm2/skylake-rt286/skylake-rt286.conf ++++ b/ucm2/skylake-rt286/skylake-rt286.conf +@@ -8,19 +8,9 @@ SectionUseCase."HiFi" { + Comment "Play and record HiFi quality Music" + } + +-SectionUseCase."Hdmi1" { +- File "Hdmi1.conf" +- Comment "Play on Hdmi/DP 1" +-} +- +-SectionUseCase."Hdmi2" { +- File "Hdmi2.conf" +- Comment "Play on Hdmi/DP 2" +-} +- + ValueDefaults { +- CaptureChannels "2" +- CapturePriority "2" ++ PlaybackChannels 2 ++ CaptureChannels 2 + } + + SectionDefaults [ +-- +2.24.1 + + +From 35c2bba4906a278d876503855c55c2e7f9247616 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 27 Jan 2020 16:06:25 +0100 +Subject: [PATCH 20/36] SDP4430: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/SDP4430/FMAnalog.conf | 11 +++---- + ucm2/SDP4430/HiFiLP.conf | 7 ++-- + ucm2/SDP4430/Record.conf | 5 ++- + ucm2/SDP4430/SDP4430.conf | 2 +- + ucm2/SDP4430/Voice.conf | 6 ++-- + ucm2/SDP4430/VoiceAll.conf | 63 ------------------------------------ + ucm2/SDP4430/VoiceCall.conf | 64 +++++++++++++++++++++++++++++++++++++ + 7 files changed, 82 insertions(+), 76 deletions(-) + delete mode 100644 ucm2/SDP4430/VoiceAll.conf + create mode 100644 ucm2/SDP4430/VoiceCall.conf + +diff --git a/ucm2/SDP4430/FMAnalog.conf b/ucm2/SDP4430/FMAnalog.conf +index 9681465..2cfabf9 100644 +--- a/ucm2/SDP4430/FMAnalog.conf ++++ b/ucm2/SDP4430/FMAnalog.conf +@@ -9,19 +9,12 @@ SectionVerb { + cset "name='Capture Volume' 4" + ] + +- + DisableSequence [ + cset "name='AMIC_UL PDM Switch' 0" + cset "name='MUX_UL00' 0" + cset "name='MUX_UL01' 0" + cset "name='Capture Volume' 0" + ] +- +- # Optional TQ and ALSA PCMs +- Value { +- TQ "Music" +- CapturePCM "hw:${CardId},0" +- } + } + + SectionDevice."Headset" { +@@ -38,5 +31,9 @@ SectionDevice."Headset" { + cset "name='Analog Right Capture Route' 3" + cset "name='Capture Preamplifier Volume' 0" + ] ++ ++ Value { ++ CapturePCM "hw:${CardId},0" ++ } + } + +diff --git a/ucm2/SDP4430/HiFiLP.conf b/ucm2/SDP4430/HiFiLP.conf +index 51380d9..731ac21 100644 +--- a/ucm2/SDP4430/HiFiLP.conf ++++ b/ucm2/SDP4430/HiFiLP.conf +@@ -18,10 +18,8 @@ SectionVerb { + cset "name='SDT DL Volume' 0" + ] + +- # Optional TQ and ALSA PCMs + Value { + TQ "Music" +- PlaybackPCM "hw:${CardId},6" + } + } + +@@ -39,4 +37,9 @@ SectionDevice."Headset" { + cset "name='HS Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},6" ++ } + } +diff --git a/ucm2/SDP4430/Record.conf b/ucm2/SDP4430/Record.conf +index 9f62fd1..d3c4955 100644 +--- a/ucm2/SDP4430/Record.conf ++++ b/ucm2/SDP4430/Record.conf +@@ -19,7 +19,6 @@ SectionVerb { + # Optional TQ and ALSA PCMs + Value { + TQ "Music" +- CapturePCM "hw:${CardId},0" + } + + } +@@ -38,4 +37,8 @@ SectionDevice."Headset" { + cset "name='Analog Right Capture Route' 3" + cset "name='Capture Preamplifier Volume' 0" + ] ++ ++ Value { ++ CapturePCM "hw:${CardId},0" ++ } + } +diff --git a/ucm2/SDP4430/SDP4430.conf b/ucm2/SDP4430/SDP4430.conf +index df5b5b9..fd95890 100644 +--- a/ucm2/SDP4430/SDP4430.conf ++++ b/ucm2/SDP4430/SDP4430.conf +@@ -13,7 +13,7 @@ SectionUseCase."HiFi" { + } + + SectionUseCase."HiFi_Low_Power" { +- File "HiHiLP.conf" ++ File "HiFiLP.conf" + Comment "Play HiFi quality Music in Low Power Mode" + } + +diff --git a/ucm2/SDP4430/Voice.conf b/ucm2/SDP4430/Voice.conf +index 7d10a17..15cd4f0 100644 +--- a/ucm2/SDP4430/Voice.conf ++++ b/ucm2/SDP4430/Voice.conf +@@ -18,10 +18,8 @@ SectionVerb { + cset "name='SDT DL Volume' 0" + ] + +- # Optional TQ and ALSA PCMs + Value { + TQ "Voice" +- PlaybackPCM "hw:${CardId},2" + } + } + +@@ -39,4 +37,8 @@ SectionDevice."Headset" { + cset "name='HS Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPCM "hw:${CardId},2" ++ } + } +diff --git a/ucm2/SDP4430/VoiceAll.conf b/ucm2/SDP4430/VoiceAll.conf +deleted file mode 100644 +index 07843c5..0000000 +--- a/ucm2/SDP4430/VoiceAll.conf ++++ /dev/null +@@ -1,63 +0,0 @@ +-# Use case Configuration for TI SDP4430 HiFi Music +-# By Liam Girdwood +- +-SectionVerb { +- EnableSequence [ +- cset "name='AMIC_UL PDM Switch' 1" +- cset "name='Sidetone Mixer Capture' 1" +- cset "name='MUX_VX0' 9" +- cset "name='MUX_VX1' 10" +- cset "name='DL1 Mixer Voice' 1" +- cset "name='Sidetone Mixer Playback' 1" +- cset "name='DL1 PDM Switch' 1" +- cset "name='DL1 Voice Playback Volume' 90,90" +- cset "name='Capture Volume' 4" +- cset "name='Capture Mixer Voice Capture' 90,90" +- cset "name='SDT DL Volume' 120" +- ] +- +- +- DisableSequence [ +- cset "name='AMIC_UL PDM Switch' 0" +- cset "name='Sidetone Mixer Capture' 0" +- cset "name='MUX_VX0' 0" +- cset "name='MUX_VX1' 0" +- cset "name='DL1 Mixer Voice' 0" +- cset "name='Sidetone Mixer Playback' 0" +- cset "name='DL1 PDM Switch' 0" +- cset "name='DL1 Voice Playback Volume' 0,0" +- cset "name='Capture Volume' 0" +- cset "name='DL1 Voice Playback Volume' 0,0" +- cset "name='SDT DL Volume' 0" +- ] +- +- # Optional TQ and ALSA PCMs +- Value { +- TQ "Voice" +- CapturePCM "hw:${CardId},2" +- PlaybackPCM "hw:${CardId},2" +- } +-} +- +-SectionDevice."Headset" { +- Comment "SDP4430 3.5mm Headset" +- +- EnableSequence [ +- cset "name='Analog Left Capture Route' 0" +- cset "name='Analog Right Capture Route' 0" +- cset "name='Capture Preamplifier Volume' 2" +- cset "name='HS Left Playback' 1" +- cset "name='HS Right Playback' 1" +- cset "name='Headset Playback Volume' 13" +- ] +- +- DisableSequence [ +- cset "name='Analog Left Capture Route' 3" +- cset "name='Analog Right Capture Route' 3" +- cset "name='Capture Preamplifier Volume' 0" +- cset "name='HS Right Playback' 0" +- cset "name='HS Left Playback' 0" +- cset "name='Headset Playback Volume' 0" +- ] +-} +- +diff --git a/ucm2/SDP4430/VoiceCall.conf b/ucm2/SDP4430/VoiceCall.conf +new file mode 100644 +index 0000000..2f02a2b +--- /dev/null ++++ b/ucm2/SDP4430/VoiceCall.conf +@@ -0,0 +1,64 @@ ++# Use case Configuration for TI SDP4430 HiFi Music ++# By Liam Girdwood ++ ++SectionVerb { ++ EnableSequence [ ++ cset "name='AMIC_UL PDM Switch' 1" ++ cset "name='Sidetone Mixer Capture' 1" ++ cset "name='MUX_VX0' 9" ++ cset "name='MUX_VX1' 10" ++ cset "name='DL1 Mixer Voice' 1" ++ cset "name='Sidetone Mixer Playback' 1" ++ cset "name='DL1 PDM Switch' 1" ++ cset "name='DL1 Voice Playback Volume' 90,90" ++ cset "name='Capture Volume' 4" ++ cset "name='Capture Mixer Voice Capture' 90,90" ++ cset "name='SDT DL Volume' 120" ++ ] ++ ++ ++ DisableSequence [ ++ cset "name='AMIC_UL PDM Switch' 0" ++ cset "name='Sidetone Mixer Capture' 0" ++ cset "name='MUX_VX0' 0" ++ cset "name='MUX_VX1' 0" ++ cset "name='DL1 Mixer Voice' 0" ++ cset "name='Sidetone Mixer Playback' 0" ++ cset "name='DL1 PDM Switch' 0" ++ cset "name='DL1 Voice Playback Volume' 0,0" ++ cset "name='Capture Volume' 0" ++ cset "name='DL1 Voice Playback Volume' 0,0" ++ cset "name='SDT DL Volume' 0" ++ ] ++ ++ Value { ++ TQ "Voice" ++ } ++} ++ ++SectionDevice."Headset" { ++ Comment "SDP4430 3.5mm Headset" ++ ++ EnableSequence [ ++ cset "name='Analog Left Capture Route' 0" ++ cset "name='Analog Right Capture Route' 0" ++ cset "name='Capture Preamplifier Volume' 2" ++ cset "name='HS Left Playback' 1" ++ cset "name='HS Right Playback' 1" ++ cset "name='Headset Playback Volume' 13" ++ ] ++ ++ DisableSequence [ ++ cset "name='Analog Left Capture Route' 3" ++ cset "name='Analog Right Capture Route' 3" ++ cset "name='Capture Preamplifier Volume' 0" ++ cset "name='HS Right Playback' 0" ++ cset "name='HS Left Playback' 0" ++ cset "name='Headset Playback Volume' 0" ++ ] ++ ++ Value { ++ CapturePCM "hw:${CardId},2" ++ PlaybackPCM "hw:${CardId},2" ++ } ++} +-- +2.24.1 + + +From 9de65f1f733d178be0e61e3c9f37df1031ab6a81 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 28 Jan 2020 17:57:43 +0100 +Subject: [PATCH 21/36] sof-hda-dsp: fix typo (PlaybackMixerMaster -> + PlaybackMasterElem) + +Signed-off-by: Jaroslav Kysela +--- + ucm2/sof-hda-dsp/HiFi.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ucm2/sof-hda-dsp/HiFi.conf b/ucm2/sof-hda-dsp/HiFi.conf +index 5c7236d..71cef49 100644 +--- a/ucm2/sof-hda-dsp/HiFi.conf ++++ b/ucm2/sof-hda-dsp/HiFi.conf +@@ -21,7 +21,7 @@ SectionDevice."Headphones1" { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId},0" + PlaybackMixerElem "Headphone" +- PlaybackMixerMaster "Master" ++ PlaybackMasterElem "Master" + PlaybackVolume "Headphone Playback Volume" + PlaybackSwitch "Headphone Playback Switch" + PlaybackChannels "2" +-- +2.24.1 + + +From 4fd064eb56bec3a47f8380fd1498bbc190cca703 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 28 Jan 2020 18:15:22 +0100 +Subject: [PATCH 22/36] broadwell-rt286: add correct prefix to Priority field + names + +Signed-off-by: Jaroslav Kysela +--- + ucm2/broadwell-rt286/HiFi.conf | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/ucm2/broadwell-rt286/HiFi.conf b/ucm2/broadwell-rt286/HiFi.conf +index e766250..96b89a0 100644 +--- a/ucm2/broadwell-rt286/HiFi.conf ++++ b/ucm2/broadwell-rt286/HiFi.conf +@@ -21,7 +21,7 @@ SectionDevice."Speaker" { + ] + + Value { +- Priority 100 ++ PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" + PlaybackChannels 2 + PlaybackMixerElem "DAC0" +@@ -49,7 +49,7 @@ SectionDevice."Headphones" { + ] + + Value { +- Priority 200 ++ PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" + PlaybackChannels 2 + PlaybackMixerElem "DAC0" +@@ -76,9 +76,9 @@ SectionDevice."Mic" { + ] + + Value { +- Priority 100 ++ CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels "2" ++ CaptureChannels 2 + CaptureMixerElem "Mic" + CaptureMasterElem "ADC0" + } +@@ -101,9 +101,9 @@ SectionDevice."Handset" { + ] + + Value { +- Priority 200 ++ CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels "2" ++ CaptureChannels 2 + CaptureMixerElem "Mic" + CaptureMasterElem "ADC0" + JackDev "rt286-jack" +-- +2.24.1 + + +From dbf9201ef6cc0008e3d1d10d28490c47689aed0e Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 28 Jan 2020 18:16:54 +0100 +Subject: [PATCH 23/36] GoogleNyan: comment CaptureControl, what is this? + +Signed-off-by: Jaroslav Kysela +--- + ucm2/GoogleNyan/HiFi.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ucm2/GoogleNyan/HiFi.conf b/ucm2/GoogleNyan/HiFi.conf +index 1f7e93c..0bcd8e8 100644 +--- a/ucm2/GoogleNyan/HiFi.conf ++++ b/ucm2/GoogleNyan/HiFi.conf +@@ -50,7 +50,7 @@ SectionDevice."Headphones" { + + SectionDevice."Mic" { + Value { +- CaptureControl "MIC2" ++ #CaptureControl "MIC2" + } + EnableSequence [ + cset "name='Int Mic Switch' off" +-- +2.24.1 + + +From eed10701463b605ba5b6587d897deff742cbb5a0 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 4 Feb 2020 17:48:10 +0100 +Subject: [PATCH 24/36] VEYRON-I2S: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/VEYRON-I2S/HiFi.conf | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/ucm2/VEYRON-I2S/HiFi.conf b/ucm2/VEYRON-I2S/HiFi.conf +index 8d07c73..bed87c5 100644 +--- a/ucm2/VEYRON-I2S/HiFi.conf ++++ b/ucm2/VEYRON-I2S/HiFi.conf +@@ -45,25 +45,31 @@ SectionDevice."Speaker" { + Comment "Speaker" + + Value { +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" + } ++ + EnableSequence [ + cset "name='Speaker Switch' on" + ] ++ + DisableSequence [ + cset "name='Speaker Switch' off" + ] + } + +-SectionDevice."Internal Mic" { +- Comment "Int Mic" ++SectionDevice."Mic" { ++ Comment "Internal Microphone" + + Value { +- CapturePCM "hw:${CardId},0" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" + } ++ + EnableSequence [ + cset "name='Int Mic Switch' on" + ] ++ + DisableSequence [ + cset "name='Int Mic Switch' off" + ] +@@ -73,7 +79,8 @@ SectionDevice."Headphones" { + Comment "Headphones" + + Value { +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" + } + + EnableSequence [ +@@ -88,11 +95,12 @@ SectionDevice."Headphones" { + ] + } + +-SectionDevice."Mic" { +- Comment "Headset Mic" ++SectionDevice."Headset" { ++ Comment "Headset Microphone" + + Value { +- CapturePCM "hw:${CardId},0" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" + } + + EnableSequence [ +-- +2.24.1 + + +From c44072f1e12f29de45484d9de946b505c1f4789b Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 4 Feb 2020 17:52:37 +0100 +Subject: [PATCH 25/36] SDP4430: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/SDP4430/FMAnalog.conf | 1 + + ucm2/SDP4430/Record.conf | 1 + + ucm2/SDP4430/Voice.conf | 1 + + ucm2/SDP4430/VoiceCall.conf | 2 ++ + 4 files changed, 5 insertions(+) + +diff --git a/ucm2/SDP4430/FMAnalog.conf b/ucm2/SDP4430/FMAnalog.conf +index 2cfabf9..da21ab1 100644 +--- a/ucm2/SDP4430/FMAnalog.conf ++++ b/ucm2/SDP4430/FMAnalog.conf +@@ -33,6 +33,7 @@ SectionDevice."Headset" { + ] + + Value { ++ CapturePriority 100 + CapturePCM "hw:${CardId},0" + } + } +diff --git a/ucm2/SDP4430/Record.conf b/ucm2/SDP4430/Record.conf +index d3c4955..44e722b 100644 +--- a/ucm2/SDP4430/Record.conf ++++ b/ucm2/SDP4430/Record.conf +@@ -39,6 +39,7 @@ SectionDevice."Headset" { + ] + + Value { ++ CapturePriority 100 + CapturePCM "hw:${CardId},0" + } + } +diff --git a/ucm2/SDP4430/Voice.conf b/ucm2/SDP4430/Voice.conf +index 15cd4f0..2110332 100644 +--- a/ucm2/SDP4430/Voice.conf ++++ b/ucm2/SDP4430/Voice.conf +@@ -39,6 +39,7 @@ SectionDevice."Headset" { + ] + + Value { ++ PlaybackPriority 100 + PlaybackPCM "hw:${CardId},2" + } + } +diff --git a/ucm2/SDP4430/VoiceCall.conf b/ucm2/SDP4430/VoiceCall.conf +index 2f02a2b..d7d5c90 100644 +--- a/ucm2/SDP4430/VoiceCall.conf ++++ b/ucm2/SDP4430/VoiceCall.conf +@@ -58,7 +58,9 @@ SectionDevice."Headset" { + ] + + Value { ++ CapturePriority 100 + CapturePCM "hw:${CardId},2" ++ PlaybackPriority 100 + PlaybackPCM "hw:${CardId},2" + } + } +-- +2.24.1 + + +From 4b7f489f6d2fa1e89592fbd1a01f87b725bc7c9c Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 4 Feb 2020 18:44:49 +0100 +Subject: [PATCH 26/36] chtrt5645: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/chtrt5645/HiFi-dmic1.conf | 32 +++++++++---------- + ucm2/chtrt5645/HiFi-dmic2.conf | 30 ++++++++--------- + .../HiFi-mono-speaker-analog-mic.conf | 21 ++++++------ + ucm2/chtrt5645/HiFi.conf | 21 ++++++------ + ucm2/codecs/rt5645/AnalogMic.conf | 5 +-- + 5 files changed, 54 insertions(+), 55 deletions(-) + +diff --git a/ucm2/chtrt5645/HiFi-dmic1.conf b/ucm2/chtrt5645/HiFi-dmic1.conf +index 86164c9..4748bd9 100644 +--- a/ucm2/chtrt5645/HiFi-dmic1.conf ++++ b/ucm2/chtrt5645/HiFi-dmic1.conf +@@ -2,10 +2,6 @@ SectionVerb { + # ALSA PCM + Value { + TQ "HiFi" +- +- # ALSA PCM device for HiFi +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" + } + + EnableSequence [ +@@ -29,7 +25,9 @@ SectionDevice."Speaker" { + Comment "Speaker" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + + ConflictingDevice [ +@@ -50,7 +48,9 @@ SectionDevice."Headphones" { + Comment "Headphones" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -69,12 +69,13 @@ SectionDevice."Headphones" { + ] + } + +-SectionDevice."DMic" { ++SectionDevice."Mic" { + Comment "Internal Microphone" + + Value { +- CaptureChannels "2" +- CapturePriority "150" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + + EnableSequence [ +@@ -91,13 +92,15 @@ SectionDevice."DMic" { + ] + } + +-SectionDevice."HSMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" +- JackHWMute "DMic" ++ JackHWMute "Mic" + } + + EnableSequence [ +@@ -113,9 +116,6 @@ SectionDevice."HSMic" { + ] + + DisableSequence [ +- +- +- cset "name='Mono ADC MIXL ADC1 Switch' on" +- cset "name='Mono ADC MIXR ADC1 Switch' on" ++ + ] + } +diff --git a/ucm2/chtrt5645/HiFi-dmic2.conf b/ucm2/chtrt5645/HiFi-dmic2.conf +index 5c947ae..459b9f5 100644 +--- a/ucm2/chtrt5645/HiFi-dmic2.conf ++++ b/ucm2/chtrt5645/HiFi-dmic2.conf +@@ -2,10 +2,6 @@ SectionVerb { + # ALSA PCM + Value { + TQ "HiFi" +- +- # ALSA PCM device for HiFi +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" + } + + EnableSequence [ +@@ -29,7 +25,9 @@ SectionDevice."Speaker" { + Comment "Speaker" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + + ConflictingDevice [ +@@ -50,7 +48,9 @@ SectionDevice."Headphones" { + Comment "Headphones" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -69,12 +69,13 @@ SectionDevice."Headphones" { + ] + } + +-SectionDevice."DMic" { ++SectionDevice."Mic" { + Comment "Internal Microphone" + + Value { +- CaptureChannels "2" +- CapturePriority "150" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + + EnableSequence [ +@@ -93,11 +94,13 @@ SectionDevice."DMic" { + ] + } + +-SectionDevice."HSMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + JackHWMute "DMic" + } +@@ -115,9 +118,6 @@ SectionDevice."HSMic" { + ] + + DisableSequence [ +- +- +- cset "name='Mono ADC MIXL ADC1 Switch' on" +- cset "name='Mono ADC MIXR ADC1 Switch' on" ++ + ] + } +diff --git a/ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf b/ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf +index a1bca67..fe410f3 100644 +--- a/ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf ++++ b/ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf +@@ -2,10 +2,6 @@ SectionVerb { + # ALSA PCM + Value { + TQ "HiFi" +- +- # ALSA PCM device for HiFi +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" + } + + EnableSequence [ +@@ -29,7 +25,9 @@ SectionDevice."Speaker" { + Comment "Speaker" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + + ConflictingDevice [ +@@ -54,7 +52,9 @@ SectionDevice."Headphones" { + Comment "Headphones" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -79,11 +79,13 @@ SectionDevice."Headphones" { + + + +-SectionDevice."HSMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + JackHWMute "Mic" + } +@@ -102,8 +104,5 @@ SectionDevice."HSMic" { + + DisableSequence [ + +- +- cset "name='Mono ADC MIXL ADC1 Switch' on" +- cset "name='Mono ADC MIXR ADC1 Switch' on" + ] + } +diff --git a/ucm2/chtrt5645/HiFi.conf b/ucm2/chtrt5645/HiFi.conf +index 7b2a663..954bf68 100644 +--- a/ucm2/chtrt5645/HiFi.conf ++++ b/ucm2/chtrt5645/HiFi.conf +@@ -2,10 +2,6 @@ SectionVerb { + # ALSA PCM + Value { + TQ "HiFi" +- +- # ALSA PCM device for HiFi +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" + } + + EnableSequence [ +@@ -29,7 +25,9 @@ SectionDevice."Speaker" { + Comment "Speaker" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + } + + ConflictingDevice [ +@@ -50,7 +48,9 @@ SectionDevice."Headphones" { + Comment "Headphones" + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -71,11 +71,13 @@ SectionDevice."Headphones" { + + + +-SectionDevice."HSMic" { ++SectionDevice."Headset" { + Comment "Headset Microphone" + + Value { +- CaptureChannels "2" ++ CapturePriority 200 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + JackControl "Headset Mic Jack" + JackHWMute "Mic" + } +@@ -94,8 +96,5 @@ SectionDevice."HSMic" { + + DisableSequence [ + +- +- cset "name='Mono ADC MIXL ADC1 Switch' on" +- cset "name='Mono ADC MIXR ADC1 Switch' on" + ] + } +diff --git a/ucm2/codecs/rt5645/AnalogMic.conf b/ucm2/codecs/rt5645/AnalogMic.conf +index d52fe61..5583cdb 100644 +--- a/ucm2/codecs/rt5645/AnalogMic.conf ++++ b/ucm2/codecs/rt5645/AnalogMic.conf +@@ -2,8 +2,9 @@ SectionDevice."Mic" { + Comment "Internal Analog Microphone" + + Value { +- CaptureChannels "2" +- CapturePriority "150" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ CaptureChannels 2 + } + + EnableSequence [ +-- +2.24.1 + + +From 3a92d95926e9289daf7b82335866b1561ccefc0d Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 4 Feb 2020 18:48:05 +0100 +Subject: [PATCH 27/36] GoogleNyan: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/GoogleNyan/HiFi.conf | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/ucm2/GoogleNyan/HiFi.conf b/ucm2/GoogleNyan/HiFi.conf +index 0bcd8e8..5428591 100644 +--- a/ucm2/GoogleNyan/HiFi.conf ++++ b/ucm2/GoogleNyan/HiFi.conf +@@ -38,6 +38,10 @@ SectionVerb { + } + + SectionDevice."Headphones" { ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ } + EnableSequence [ + cset "name='Speakers Switch' off" + cset "name='Headphones Switch' on" +@@ -50,6 +54,8 @@ SectionDevice."Headphones" { + + SectionDevice."Mic" { + Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" + #CaptureControl "MIC2" + } + EnableSequence [ +-- +2.24.1 + + +From c546a3466d0d801b3d5a8fb6c2cd840a068e72f2 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 4 Feb 2020 18:52:18 +0100 +Subject: [PATCH 28/36] PAZ00: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/PAZ00/HiFi.conf | 4 ++++ + ucm2/PAZ00/Record.conf | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/ucm2/PAZ00/HiFi.conf b/ucm2/PAZ00/HiFi.conf +index 6e30cbe..7f5de05 100644 +--- a/ucm2/PAZ00/HiFi.conf ++++ b/ucm2/PAZ00/HiFi.conf +@@ -32,4 +32,8 @@ SectionDevice."Headset" { + # Internal speaker + cset "name='Int Spk Switch' on" + ] ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ } + } +diff --git a/ucm2/PAZ00/Record.conf b/ucm2/PAZ00/Record.conf +index 3cb57b2..20dbac4 100644 +--- a/ucm2/PAZ00/Record.conf ++++ b/ucm2/PAZ00/Record.conf +@@ -52,4 +52,8 @@ SectionDevice."Headset" { + # Internal mic + cset "name='DMIC En Capture Switch' on" + ] ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ } + } +-- +2.24.1 + + +From 3b6bfaa6b5c08b78ee0cbb9b1b1137fc20f92a63 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 4 Feb 2020 18:58:27 +0100 +Subject: [PATCH 29/36] SDP4430: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/SDP4430/FMAnalog.conf | 2 +- + ucm2/SDP4430/HiFi.conf | 5 +++++ + ucm2/SDP4430/Record.conf | 2 +- + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/ucm2/SDP4430/FMAnalog.conf b/ucm2/SDP4430/FMAnalog.conf +index da21ab1..e2132d2 100644 +--- a/ucm2/SDP4430/FMAnalog.conf ++++ b/ucm2/SDP4430/FMAnalog.conf +@@ -34,7 +34,7 @@ SectionDevice."Headset" { + + Value { + CapturePriority 100 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + } + } + +diff --git a/ucm2/SDP4430/HiFi.conf b/ucm2/SDP4430/HiFi.conf +index af5b8fb..8e44a95 100644 +--- a/ucm2/SDP4430/HiFi.conf ++++ b/ucm2/SDP4430/HiFi.conf +@@ -49,4 +49,9 @@ SectionDevice."Headset" { + cset "name='HS Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ } + } +diff --git a/ucm2/SDP4430/Record.conf b/ucm2/SDP4430/Record.conf +index 44e722b..49837e2 100644 +--- a/ucm2/SDP4430/Record.conf ++++ b/ucm2/SDP4430/Record.conf +@@ -40,6 +40,6 @@ SectionDevice."Headset" { + + Value { + CapturePriority 100 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + } + } +-- +2.24.1 + + +From 1e7ea2a0d7afe51447e7efb71f8f03c39b6fcb64 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 4 Feb 2020 19:11:10 +0100 +Subject: [PATCH 30/36] PandaBoard: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/PandaBoard/FMAnalog.conf | 9 ++++++--- + ucm2/PandaBoard/HiFi.conf | 18 +++++++++++------- + ucm2/PandaBoard/HiFiLP.conf | 8 ++++++-- + ucm2/PandaBoard/Record.conf | 8 ++++++-- + ucm2/PandaBoard/Voice.conf | 8 ++++++-- + ucm2/PandaBoard/VoiceCall.conf | 12 ++++++++---- + 6 files changed, 43 insertions(+), 20 deletions(-) + +diff --git a/ucm2/PandaBoard/FMAnalog.conf b/ucm2/PandaBoard/FMAnalog.conf +index 11a2288..29cbbe8 100644 +--- a/ucm2/PandaBoard/FMAnalog.conf ++++ b/ucm2/PandaBoard/FMAnalog.conf +@@ -17,10 +17,9 @@ SectionVerb { + cset "name='Capture Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Music" +- CapturePCM "hw:${CardId},0" + } + } + +@@ -38,5 +37,9 @@ SectionDevice."Headset" { + cset "name='Analog Right Capture Route' 3" + cset "name='Capture Preamplifier Volume' 0" + ] +-} + ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ } ++} +diff --git a/ucm2/PandaBoard/HiFi.conf b/ucm2/PandaBoard/HiFi.conf +index 1b16125..5de0c8f 100644 +--- a/ucm2/PandaBoard/HiFi.conf ++++ b/ucm2/PandaBoard/HiFi.conf +@@ -26,13 +26,10 @@ SectionVerb { + cset "name='Headset Playback Volume' 0" + ] + +- # Optional TQ and ALSA PCMs +-# Value { +-# TQ "Music" +-# PlaybackPCM "hw:${CardId},0" +-# PlaybackVolume "name='DL1 Media Playback Volume' 90,90" +-# PlaybackSwitch "name='DL1 PDM Switch' 1" +-# } ++ # Optional TQ ++ Value { ++ TQ "Music" ++ } + } + + SectionDevice."Headset" { +@@ -49,4 +46,11 @@ SectionDevice."Headset" { + cset "name='Headset Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ # PlaybackVolume "name='DL1 Media Playback Volume' 90,90" ++ # PlaybackSwitch "name='DL1 PDM Switch' 1" ++ } + } +diff --git a/ucm2/PandaBoard/HiFiLP.conf b/ucm2/PandaBoard/HiFiLP.conf +index 92de382..c735248 100644 +--- a/ucm2/PandaBoard/HiFiLP.conf ++++ b/ucm2/PandaBoard/HiFiLP.conf +@@ -18,10 +18,9 @@ SectionVerb { + cset "name='SDT DL Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Music" +- PlaybackPCM "hw:${CardId},6" + } + } + +@@ -39,4 +38,9 @@ SectionDevice."Headset" { + cset "name='Headset Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},6" ++ } + } +diff --git a/ucm2/PandaBoard/Record.conf b/ucm2/PandaBoard/Record.conf +index 1fbe74c..e88d6c3 100644 +--- a/ucm2/PandaBoard/Record.conf ++++ b/ucm2/PandaBoard/Record.conf +@@ -18,10 +18,9 @@ SectionVerb { + cset "name='Capture Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Music" +- CapturePCM "hw:${CardId},0" + } + + } +@@ -40,4 +39,9 @@ SectionDevice."Headset" { + cset "name='Analog Right Capture Route' 3" + cset "name='Capture Preamplifier Volume' 0" + ] ++ ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ } + } +diff --git a/ucm2/PandaBoard/Voice.conf b/ucm2/PandaBoard/Voice.conf +index 42af48a..6843cc8 100644 +--- a/ucm2/PandaBoard/Voice.conf ++++ b/ucm2/PandaBoard/Voice.conf +@@ -18,10 +18,9 @@ SectionVerb { + cset "name='SDT DL Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Voice" +- PlaybackPCM "hw:${CardId},2" + } + } + +@@ -39,4 +38,9 @@ SectionDevice."Headset" { + cset "name='Headset Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},2" ++ } + } +diff --git a/ucm2/PandaBoard/VoiceCall.conf b/ucm2/PandaBoard/VoiceCall.conf +index c20bf5c..9a8099e 100644 +--- a/ucm2/PandaBoard/VoiceCall.conf ++++ b/ucm2/PandaBoard/VoiceCall.conf +@@ -31,11 +31,9 @@ SectionVerb { + cset "name='SDT DL Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Voice" +- CapturePCM "hw:${CardId},2" +- PlaybackPCM "hw:${CardId},2" + } + } + +@@ -59,5 +57,11 @@ SectionDevice."Headset" { + cset "name='Headset Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] +-} + ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},2" ++ } ++} +-- +2.24.1 + + +From 95f4da477fdb6a06ed321e6f2c0f7fc7d170b2e0 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 4 Feb 2020 19:21:47 +0100 +Subject: [PATCH 31/36] PandaBoardES: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/PandaBoardES/FMAnalog.conf | 9 ++++++--- + ucm2/PandaBoardES/HiFi.conf | 18 +++++++++++------- + ucm2/PandaBoardES/HiFiLP.conf | 8 ++++++-- + ucm2/PandaBoardES/Record.conf | 8 ++++++-- + ucm2/PandaBoardES/Voice.conf | 8 ++++++-- + ucm2/PandaBoardES/VoiceCall.conf | 10 +++++++--- + 6 files changed, 42 insertions(+), 19 deletions(-) + +diff --git a/ucm2/PandaBoardES/FMAnalog.conf b/ucm2/PandaBoardES/FMAnalog.conf +index a4d5a23..9920bcc 100644 +--- a/ucm2/PandaBoardES/FMAnalog.conf ++++ b/ucm2/PandaBoardES/FMAnalog.conf +@@ -17,10 +17,9 @@ SectionVerb { + cset "name='Capture Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Music" +- CapturePCM "hw:${CardId},0" + } + } + +@@ -38,5 +37,9 @@ SectionDevice."Headset" { + cset "name='Analog Right Capture Route' 3" + cset "name='Capture Preamplifier Volume' 0" + ] +-} + ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ } ++} +diff --git a/ucm2/PandaBoardES/HiFi.conf b/ucm2/PandaBoardES/HiFi.conf +index 856dd9f..aa78e47 100644 +--- a/ucm2/PandaBoardES/HiFi.conf ++++ b/ucm2/PandaBoardES/HiFi.conf +@@ -26,13 +26,10 @@ SectionVerb { + cset "name='Headset Playback Volume' 0" + ] + +- # Optional TQ and ALSA PCMs +-# Value { +-# TQ "Music" +-# PlaybackPCM "hw:${CardId},0" +-# PlaybackVolume "name='DL1 Media Playback Volume' 90,90" +-# PlaybackSwitch "name='DL1 PDM Switch' 1" +-# } ++ # Optional TQ ++ Value { ++ TQ "Music" ++ } + } + + SectionDevice."Headset" { +@@ -49,4 +46,11 @@ SectionDevice."Headset" { + cset "name='Headset Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ # PlaybackVolume "name='DL1 Media Playback Volume' 90,90" ++ # PlaybackSwitch "name='DL1 PDM Switch' 1" ++ } + } +diff --git a/ucm2/PandaBoardES/HiFiLP.conf b/ucm2/PandaBoardES/HiFiLP.conf +index a6a258d..23164ed 100644 +--- a/ucm2/PandaBoardES/HiFiLP.conf ++++ b/ucm2/PandaBoardES/HiFiLP.conf +@@ -18,10 +18,9 @@ SectionVerb { + cset "name='SDT DL Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Music" +- PlaybackPCM "hw:${CardId},6" + } + } + +@@ -39,4 +38,9 @@ SectionDevice."Headset" { + cset "name='Headset Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},6" ++ } + } +diff --git a/ucm2/PandaBoardES/Record.conf b/ucm2/PandaBoardES/Record.conf +index 57ad612..8cc6fdf 100644 +--- a/ucm2/PandaBoardES/Record.conf ++++ b/ucm2/PandaBoardES/Record.conf +@@ -17,10 +17,9 @@ SectionVerb { + cset "name='Capture Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Music" +- CapturePCM "hw:${CardId},0" + } + + } +@@ -39,4 +38,9 @@ SectionDevice."Headset" { + cset "name='Analog Right Capture Route' 3" + cset "name='Capture Preamplifier Volume' 0" + ] ++ ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId}" ++ } + } +diff --git a/ucm2/PandaBoardES/Voice.conf b/ucm2/PandaBoardES/Voice.conf +index a198c23..e37e7ec 100644 +--- a/ucm2/PandaBoardES/Voice.conf ++++ b/ucm2/PandaBoardES/Voice.conf +@@ -18,10 +18,9 @@ SectionVerb { + cset "name='SDT DL Volume' 0" + ] + +- # Optional TQ and ALSA PCMs ++ # Optional TQ + Value { + TQ "Voice" +- PlaybackPCM "hw:${CardId},2" + } + } + +@@ -39,4 +38,9 @@ SectionDevice."Headset" { + cset "name='Headset Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] ++ ++ Value { ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},2" ++ } + } +diff --git a/ucm2/PandaBoardES/VoiceCall.conf b/ucm2/PandaBoardES/VoiceCall.conf +index 4aed020..3e6e092 100644 +--- a/ucm2/PandaBoardES/VoiceCall.conf ++++ b/ucm2/PandaBoardES/VoiceCall.conf +@@ -34,8 +34,6 @@ SectionVerb { + # Optional TQ and ALSA PCMs + Value { + TQ "Voice" +- CapturePCM "hw:${CardId},2" +- PlaybackPCM "hw:${CardId},2" + } + } + +@@ -59,5 +57,11 @@ SectionDevice."Headset" { + cset "name='Headset Left Playback' 0" + cset "name='Headset Playback Volume' 0" + ] +-} + ++ Value { ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId},2" ++ } ++} +-- +2.24.1 + + +From d2f2b3649b2ea4caa2fc93cdabe9ed813efbae68 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 5 Feb 2020 02:54:11 +0100 +Subject: [PATCH 32/36] kblrt5660: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/kblrt5660/Hdmi1.conf | 28 +++++++++++++++++++--------- + ucm2/kblrt5660/Hdmi2.conf | 30 ++++++++++++++++++++---------- + ucm2/kblrt5660/HiFi.conf | 26 ++++++++++---------------- + 3 files changed, 49 insertions(+), 35 deletions(-) + +diff --git a/ucm2/kblrt5660/Hdmi1.conf b/ucm2/kblrt5660/Hdmi1.conf +index b6adbaa..ccf5118 100755 +--- a/ucm2/kblrt5660/Hdmi1.conf ++++ b/ucm2/kblrt5660/Hdmi1.conf +@@ -1,14 +1,24 @@ + # Usecase for device HDMI1/Display Port stereo playback on Intel KABYLAKE platforms + # For Audio in I2S mode + +-SectionDevice."Hdmi1" { +- Comment "HDMI/Display Port 1 Stereo" ++SectionDevice."HDMI1" { ++ Comment "HDMI/Display Port 1 Stereo" + +- Value { +- PlaybackPCM "hw:${CardId},2" +- PlaybackChannels "2" +- PlaybackPriority "2" +- JackControl "HDMI/DP, pcm=4 Jack" +- } ++ Value { ++ PlaybackPriority 200 ++ PlaybackPCM "hw:${CardId},2" ++ PlaybackChannels 2 ++ If.1 { ++ Condition { ++ Type ControlExists ++ Control "iface=CARD,name='HDMI/DP,pcm=4 Jack'" ++ } ++ True { ++ JackControl "HDMI/DP,pcm=4 Jack" ++ } ++ False { ++ JackControl "HDMI/DP, pcm=4 Jack" ++ } ++ } ++ } + } +- +diff --git a/ucm2/kblrt5660/Hdmi2.conf b/ucm2/kblrt5660/Hdmi2.conf +index 19e9bd0..c5e4001 100755 +--- a/ucm2/kblrt5660/Hdmi2.conf ++++ b/ucm2/kblrt5660/Hdmi2.conf +@@ -1,14 +1,24 @@ +-# Usecase for device HDMI2/Display Port stereo playback on Intel KABYLAKE platforms ++# Usecase for device HDMI1/Display Port stereo playback on Intel KABYLAKE platforms + # For Audio in I2S mode + +-SectionDevice."Hdmi2" { +- Comment "HDMI/Display Port 2 Stereo" ++SectionDevice."HDMI2" { ++ Comment "HDMI/Display Port 2 Stereo" + +- Value { +- PlaybackPCM "hw:${CardId},3" +- PlaybackChannels "2" +- PlaybackPriority "3" +- JackControl "HDMI/DP, pcm=5 Jack" +- } ++ Value { ++ PlaybackPriority 300 ++ PlaybackPCM "hw:${CardId},3" ++ PlaybackChannels 2 ++ If.1 { ++ Condition { ++ Type ControlExists ++ Control "iface=CARD,name='HDMI/DP,pcm=5 Jack'" ++ } ++ True { ++ JackControl "HDMI/DP,pcm=5 Jack" ++ } ++ False { ++ JackControl "HDMI/DP, pcm=5 Jack" ++ } ++ } ++ } + } +- +diff --git a/ucm2/kblrt5660/HiFi.conf b/ucm2/kblrt5660/HiFi.conf +index af0d805..0f5d46d 100755 +--- a/ucm2/kblrt5660/HiFi.conf ++++ b/ucm2/kblrt5660/HiFi.conf +@@ -1,18 +1,8 @@ + # UCM for Intel Kabylake platforms with RT5660 + # For Audio in I2S mode + +-SectionVerb { +- +- # ALSA PCM +- Value { +- # ALSA PCM device for HiFi +- PlaybackPCM "hw:${CardId},0" +- CapturePCM "hw:${CardId},1" +- } +-} +- +-SectionDevice."LineOut" { +- Comment "LineOut playback" ++SectionDevice."Line1" { ++ Comment "Line playback" + + EnableSequence [ + cset "name='DAC1 Playback Volume' 30" +@@ -36,14 +26,16 @@ SectionDevice."LineOut" { + ] + + Value { +- PlaybackChannels "2" ++ PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" ++ PlaybackChannels 2 + JackDev "rt5660-jack" + JackControl "Line Out Jack" + } + } + +-SectionDevice."LineIn" { +- Comment "LineIn capture" ++SectionDevice."Line2" { ++ Comment "Line capture" + + EnableSequence [ + cset "name='ADC Capture Volume' 30" +@@ -67,7 +59,9 @@ SectionDevice."LineIn" { + ] + + Value { +- CaptureChannels "2" ++ CapturePriority 100 ++ CapturePCM "hw:${CardId},1" ++ CaptureChannels 2 + JackDev "rt5660-jack" + JackControl "Line In Jack" + } +-- +2.24.1 + + +From 1e2eddb7e38474f239f9c8f9387c7a04a1bff7e3 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 5 Feb 2020 03:13:06 +0100 +Subject: [PATCH 33/36] bytcr-rt5640: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/bytcr-rt5640/HiFi.conf | 5 ----- + ucm2/codecs/rt5640/DigitalMics.conf | 2 +- + ucm2/codecs/rt5640/HeadPhones.conf | 3 +-- + ucm2/codecs/rt5640/HeadsetMic.conf | 2 +- + ucm2/codecs/rt5640/IN1-InternalMic.conf | 4 ++-- + ucm2/codecs/rt5640/IN3-InternalMic.conf | 2 +- + ucm2/codecs/rt5640/MonoSpeaker.conf | 3 +-- + ucm2/codecs/rt5640/Speaker.conf | 3 +-- + 8 files changed, 8 insertions(+), 16 deletions(-) + +diff --git a/ucm2/bytcr-rt5640/HiFi.conf b/ucm2/bytcr-rt5640/HiFi.conf +index a616106..e71eb22 100644 +--- a/ucm2/bytcr-rt5640/HiFi.conf ++++ b/ucm2/bytcr-rt5640/HiFi.conf +@@ -10,11 +10,6 @@ SectionVerb { + DisableSequence [ + + ] +- +- Value { +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" +- } + } + + If.0 { +diff --git a/ucm2/codecs/rt5640/DigitalMics.conf b/ucm2/codecs/rt5640/DigitalMics.conf +index 17cae19..9cd8a8c 100644 +--- a/ucm2/codecs/rt5640/DigitalMics.conf ++++ b/ucm2/codecs/rt5640/DigitalMics.conf +@@ -21,7 +21,7 @@ SectionDevice."Mic" { + + Value { + CapturePriority 100 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/HeadPhones.conf b/ucm2/codecs/rt5640/HeadPhones.conf +index dccc943..7859b7a 100644 +--- a/ucm2/codecs/rt5640/HeadPhones.conf ++++ b/ucm2/codecs/rt5640/HeadPhones.conf +@@ -3,7 +3,6 @@ SectionDevice."Headphones" { + + ConflictingDevice [ + "Speaker" +- "MonoSpeaker" + ] + + EnableSequence [ +@@ -33,7 +32,7 @@ SectionDevice."Headphones" { + + Value { + PlaybackPriority 300 +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPCM "hw:${CardId}" + PlaybackChannels 2 + JackControl "Headphone Jack" + } +diff --git a/ucm2/codecs/rt5640/HeadsetMic.conf b/ucm2/codecs/rt5640/HeadsetMic.conf +index f6d9423..40e0abe 100644 +--- a/ucm2/codecs/rt5640/HeadsetMic.conf ++++ b/ucm2/codecs/rt5640/HeadsetMic.conf +@@ -37,7 +37,7 @@ SectionDevice."Headset" { + + Value { + CapturePriority 200 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + JackControl "Headset Mic Jack" + } +diff --git a/ucm2/codecs/rt5640/IN1-InternalMic.conf b/ucm2/codecs/rt5640/IN1-InternalMic.conf +index 435cce8..7d76c4f 100644 +--- a/ucm2/codecs/rt5640/IN1-InternalMic.conf ++++ b/ucm2/codecs/rt5640/IN1-InternalMic.conf +@@ -2,7 +2,7 @@ SectionDevice."Mic" { + Comment "Internal Microphone on IN1" + + ConflictingDevice [ +- "HeadsetMic" ++ "Headset" + ] + + EnableSequence [ +@@ -40,7 +40,7 @@ SectionDevice."Mic" { + + Value { + CapturePriority 100 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/IN3-InternalMic.conf b/ucm2/codecs/rt5640/IN3-InternalMic.conf +index 4d4060e..2df2938 100644 +--- a/ucm2/codecs/rt5640/IN3-InternalMic.conf ++++ b/ucm2/codecs/rt5640/IN3-InternalMic.conf +@@ -40,7 +40,7 @@ SectionDevice."Mic" { + + Value { + CapturePriority 100 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/MonoSpeaker.conf b/ucm2/codecs/rt5640/MonoSpeaker.conf +index 6ca51e2..70ab809 100644 +--- a/ucm2/codecs/rt5640/MonoSpeaker.conf ++++ b/ucm2/codecs/rt5640/MonoSpeaker.conf +@@ -3,7 +3,6 @@ SectionDevice."Speaker" { + + ConflictingDevice [ + "Headphones" +- "Speaker" + ] + + EnableSequence [ +@@ -38,7 +37,7 @@ SectionDevice."Speaker" { + + Value { + PlaybackPriority 100 +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPCM "hw:${CardId}" + PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/Speaker.conf b/ucm2/codecs/rt5640/Speaker.conf +index 09b99cf..3b4b296 100644 +--- a/ucm2/codecs/rt5640/Speaker.conf ++++ b/ucm2/codecs/rt5640/Speaker.conf +@@ -3,7 +3,6 @@ SectionDevice."Speaker" { + + ConflictingDevice [ + "Headphones" +- "MonoSpeaker" + ] + + EnableSequence [ +@@ -37,8 +36,8 @@ SectionDevice."Speaker" { + ] + + Value { +- PlaybackPCM "hw:${CardId},0" + PlaybackPriority 100 ++ PlaybackPCM "hw:${CardId}" + PlaybackChannels 2 + } + } +-- +2.24.1 + + +From 6a1044da7b104251502421c56c9be42407bd9281 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 5 Feb 2020 03:19:33 +0100 +Subject: [PATCH 34/36] bytcht-es8316: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/bytcht-es8316/HiFi.conf | 5 ----- + ucm2/codecs/es8316/HeadPhones.conf | 2 +- + ucm2/codecs/es8316/IN1-HeadsetMic.conf | 2 +- + ucm2/codecs/es8316/IN2-HeadsetMic.conf | 2 +- + ucm2/codecs/es8316/IN2-InternalMic.conf | 6 ++---- + ucm2/codecs/es8316/MonoSpeaker.conf | 2 +- + ucm2/codecs/es8316/Speaker.conf | 3 +-- + 7 files changed, 7 insertions(+), 15 deletions(-) + +diff --git a/ucm2/bytcht-es8316/HiFi.conf b/ucm2/bytcht-es8316/HiFi.conf +index 768f010..af053d0 100644 +--- a/ucm2/bytcht-es8316/HiFi.conf ++++ b/ucm2/bytcht-es8316/HiFi.conf +@@ -7,11 +7,6 @@ SectionVerb { + DisableSequence [ + + ] +- +- Value { +- PlaybackPCM "hw:${CardId}" +- CapturePCM "hw:${CardId}" +- } + } + + If.0 { +diff --git a/ucm2/codecs/es8316/HeadPhones.conf b/ucm2/codecs/es8316/HeadPhones.conf +index 603b40c..6a05e54 100644 +--- a/ucm2/codecs/es8316/HeadPhones.conf ++++ b/ucm2/codecs/es8316/HeadPhones.conf +@@ -15,7 +15,7 @@ SectionDevice."Headphones" { + + Value { + PlaybackPriority 200 +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPCM "hw:${CardId}" + PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" +diff --git a/ucm2/codecs/es8316/IN1-HeadsetMic.conf b/ucm2/codecs/es8316/IN1-HeadsetMic.conf +index d798270..e9f9061 100644 +--- a/ucm2/codecs/es8316/IN1-HeadsetMic.conf ++++ b/ucm2/codecs/es8316/IN1-HeadsetMic.conf +@@ -16,7 +16,7 @@ SectionDevice."Headset" { + + Value { + CapturePriority 200 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + JackControl "Headset Mic Jack" + } +diff --git a/ucm2/codecs/es8316/IN2-HeadsetMic.conf b/ucm2/codecs/es8316/IN2-HeadsetMic.conf +index 28f26f8..377d84d 100644 +--- a/ucm2/codecs/es8316/IN2-HeadsetMic.conf ++++ b/ucm2/codecs/es8316/IN2-HeadsetMic.conf +@@ -16,7 +16,7 @@ SectionDevice."Headset" { + + Value { + CapturePriority 200 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + JackControl "Headset Mic Jack" + } +diff --git a/ucm2/codecs/es8316/IN2-InternalMic.conf b/ucm2/codecs/es8316/IN2-InternalMic.conf +index 8c0418f..f0ff6f1 100644 +--- a/ucm2/codecs/es8316/IN2-InternalMic.conf ++++ b/ucm2/codecs/es8316/IN2-InternalMic.conf +@@ -2,9 +2,7 @@ SectionDevice."Mic" { + Comment "Internal Microphone on IN2" + + ConflictingDevice [ +- "InternalMic-IN1" +- "HeadsetMic-IN1" +- "HeadsetMic-IN2" ++ "Headset" + ] + + EnableSequence [ +@@ -18,7 +16,7 @@ SectionDevice."Mic" { + + Value { + CapturePriority 100 +- CapturePCM "hw:${CardId},0" ++ CapturePCM "hw:${CardId}" + CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/MonoSpeaker.conf b/ucm2/codecs/es8316/MonoSpeaker.conf +index f11f2b7..64a7e76 100644 +--- a/ucm2/codecs/es8316/MonoSpeaker.conf ++++ b/ucm2/codecs/es8316/MonoSpeaker.conf +@@ -32,7 +32,7 @@ SectionDevice."Speaker" { + + Value { + PlaybackPriority 100 +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPCM "hw:${CardId}" + PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/Speaker.conf b/ucm2/codecs/es8316/Speaker.conf +index a1e4491..58fe078 100644 +--- a/ucm2/codecs/es8316/Speaker.conf ++++ b/ucm2/codecs/es8316/Speaker.conf +@@ -2,7 +2,6 @@ SectionDevice."Speaker" { + Comment "Speakers" + + ConflictingDevice [ +- "MonoSpeaker" + "Headphones" + ] + +@@ -16,7 +15,7 @@ SectionDevice."Speaker" { + + Value { + PlaybackPriority 100 +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPCM "hw:${CardId}" + PlaybackChannels 2 + } + } +-- +2.24.1 + + +From acf80f98692ab6f409e77cddb1bb55b387da4b17 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 5 Feb 2020 03:24:00 +0100 +Subject: [PATCH 35/36] sof-hda-dsp: corrections and fixes + +Signed-off-by: Jaroslav Kysela +--- + ucm2/sof-hda-dsp/HDA-Capture-value.conf | 4 ++-- + ucm2/sof-hda-dsp/Hdmi.conf | 6 +++--- + ucm2/sof-hda-dsp/HiFi.conf | 14 +++++++------- + 3 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/ucm2/sof-hda-dsp/HDA-Capture-value.conf b/ucm2/sof-hda-dsp/HDA-Capture-value.conf +index b3e90aa..5f3c2a3 100644 +--- a/ucm2/sof-hda-dsp/HDA-Capture-value.conf ++++ b/ucm2/sof-hda-dsp/HDA-Capture-value.conf +@@ -1,5 +1,5 @@ +-CapturePCM "hw:${CardId},0" ++CapturePCM "hw:${CardId}" + CaptureMixerElem "Capture" + CaptureVolume "Capture Volume" + CaptureSwitch "Capture Switch" +-CaptureChannels "2" ++CaptureChannels 2 +diff --git a/ucm2/sof-hda-dsp/Hdmi.conf b/ucm2/sof-hda-dsp/Hdmi.conf +index 7418fa7..1982c72 100644 +--- a/ucm2/sof-hda-dsp/Hdmi.conf ++++ b/ucm2/sof-hda-dsp/Hdmi.conf +@@ -14,7 +14,7 @@ SectionDevice."HDMI1" { + Value { + PlaybackPriority 500 + PlaybackPCM "hw:${CardId},3" +- PlaybackChannels "2" ++ PlaybackChannels 2 + JackControl "HDMI/DP,pcm=3 Jack" + } + } +@@ -33,7 +33,7 @@ SectionDevice."HDMI2" { + Value { + PlaybackPriority 600 + PlaybackPCM "hw:${CardId},4" +- PlaybackChannels "2" ++ PlaybackChannels 2 + JackControl "HDMI/DP,pcm=4 Jack" + } + } +@@ -52,7 +52,7 @@ SectionDevice."HDMI3" { + Value { + PlaybackPriority 700 + PlaybackPCM "hw:${CardId},5" +- PlaybackChannels "2" ++ PlaybackChannels 2 + JackControl "HDMI/DP,pcm=5 Jack" + } + } +diff --git a/ucm2/sof-hda-dsp/HiFi.conf b/ucm2/sof-hda-dsp/HiFi.conf +index 71cef49..6dfdabe 100644 +--- a/ucm2/sof-hda-dsp/HiFi.conf ++++ b/ucm2/sof-hda-dsp/HiFi.conf +@@ -19,12 +19,12 @@ SectionDevice."Headphones1" { + + Value { + PlaybackPriority 200 +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPCM "hw:${CardId}" + PlaybackMixerElem "Headphone" + PlaybackMasterElem "Master" + PlaybackVolume "Headphone Playback Volume" + PlaybackSwitch "Headphone Playback Switch" +- PlaybackChannels "2" ++ PlaybackChannels 2 + If.jack { + Condition { + Type ControlExists +@@ -72,12 +72,12 @@ SectionDevice."Speaker" { + + Value { + PlaybackPriority 100 +- PlaybackPCM "hw:${CardId},0" ++ PlaybackPCM "hw:${CardId}" + PlaybackMixerElem "Speaker" + PlaybackMasterElem "Master" + PlaybackVolume "Speaker Playback Volume" + PlaybackSwitch "Speaker Playback Switch" +- PlaybackChannels "2" ++ PlaybackChannels 2 + } + } + +@@ -93,7 +93,7 @@ If.monomic { + Comment "Headphones Stereo Microphone" + + ConflictingDevice [ +- "HeadsetMic" ++ "Headset" + ] + + EnableSequence [ +@@ -147,10 +147,10 @@ SectionDevice."Mic" { + Needle "cfg-dmics:4" + } + True { +- CaptureChannels "4" ++ CaptureChannels 4 + } + False { +- CaptureChannels "2" ++ CaptureChannels 2 + } + } + If.vol { +-- +2.24.1 + + +From 14c768eacd923c3b8bfe3dd027464a5d423e3773 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 6 Feb 2020 19:44:07 +0100 +Subject: [PATCH 36/36] ucm2: treewide - remove Playback and Capture channels=2 + assignments + +The value 2 is the default. + +Signed-off-by: Jaroslav Kysela +--- + ucm2/DB410c/HDMI.conf | 1 - + ucm2/DB410c/HiFi.conf | 9 --------- + ucm2/DB820c/HDMI.conf | 1 - + ucm2/DB820c/HiFi.conf | 1 - + ucm2/HDA-Intel/HiFi-dual.conf | 2 -- + ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf | 3 --- + ucm2/broadwell-rt286/HiFi.conf | 4 ---- + ucm2/broxton-rt298/broxton-rt298.conf | 7 ------- + ucm2/chtrt5645/HiFi-dmic1.conf | 4 ---- + ucm2/chtrt5645/HiFi-dmic2.conf | 4 ---- + ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf | 3 --- + ucm2/chtrt5645/HiFi.conf | 3 --- + ucm2/codecs/cx2072x/HeadPhones.conf | 1 - + ucm2/codecs/cx2072x/HeadsetMic.conf | 1 - + ucm2/codecs/cx2072x/InternalMic.conf | 1 - + ucm2/codecs/cx2072x/Speaker.conf | 1 - + ucm2/codecs/es8316/HeadPhones.conf | 1 - + ucm2/codecs/es8316/IN1-HeadsetMic.conf | 1 - + ucm2/codecs/es8316/IN1-InternalMic.conf | 1 - + ucm2/codecs/es8316/IN2-HeadsetMic.conf | 1 - + ucm2/codecs/es8316/IN2-InternalMic.conf | 1 - + ucm2/codecs/es8316/MonoSpeaker.conf | 1 - + ucm2/codecs/es8316/Speaker.conf | 1 - + ucm2/codecs/nau8824/HeadPhones.conf | 1 - + ucm2/codecs/nau8824/HeadsetMic.conf | 1 - + ucm2/codecs/nau8824/InternalMic.conf | 1 - + ucm2/codecs/nau8824/MonoSpeaker.conf | 1 - + ucm2/codecs/nau8824/Speaker.conf | 1 - + ucm2/codecs/rt5640/DigitalMics.conf | 1 - + ucm2/codecs/rt5640/HeadPhones.conf | 1 - + ucm2/codecs/rt5640/HeadsetMic.conf | 1 - + ucm2/codecs/rt5640/IN1-InternalMic.conf | 1 - + ucm2/codecs/rt5640/IN3-InternalMic.conf | 1 - + ucm2/codecs/rt5640/MonoSpeaker.conf | 1 - + ucm2/codecs/rt5640/Speaker.conf | 1 - + ucm2/codecs/rt5645/AnalogMic.conf | 1 - + ucm2/codecs/rt5651/DigitalMic.conf | 1 - + ucm2/codecs/rt5651/HeadPhones-swapped.conf | 1 - + ucm2/codecs/rt5651/HeadPhones.conf | 1 - + ucm2/codecs/rt5651/IN1-InternalMic.conf | 1 - + ucm2/codecs/rt5651/IN12-InternalMic.conf | 1 - + ucm2/codecs/rt5651/IN2-HeadsetMic.conf | 1 - + ucm2/codecs/rt5651/IN2-InternalMic.conf | 1 - + ucm2/codecs/rt5651/IN3-HeadsetMic.conf | 1 - + ucm2/codecs/rt5651/MonoSpeaker.conf | 1 - + ucm2/codecs/rt5651/Speaker.conf | 1 - + ucm2/codecs/rt5672/DMIC1.conf | 1 - + ucm2/codecs/rt5672/DMIC2.conf | 1 - + ucm2/codecs/rt5672/HeadPhones.conf | 1 - + ucm2/codecs/rt5672/HeadsetMic.conf | 1 - + ucm2/codecs/rt5672/MonoSpeaker.conf | 1 - + ucm2/codecs/rt5672/Speaker.conf | 1 - + ucm2/kblrt5660/Hdmi1.conf | 1 - + ucm2/kblrt5660/Hdmi2.conf | 1 - + ucm2/kblrt5660/HiFi.conf | 2 -- + ucm2/skylake-rt286/skylake-rt286.conf | 5 ----- + ucm2/sof-hda-dsp/HDA-Capture-value.conf | 1 - + ucm2/sof-hda-dsp/Hdmi.conf | 3 --- + ucm2/sof-hda-dsp/HiFi.conf | 5 ----- + 59 files changed, 100 deletions(-) + +diff --git a/ucm2/DB410c/HDMI.conf b/ucm2/DB410c/HDMI.conf +index fa44132..3335422 100644 +--- a/ucm2/DB410c/HDMI.conf ++++ b/ucm2/DB410c/HDMI.conf +@@ -4,7 +4,6 @@ + SectionVerb { + Value { + TQ "HiFi" +- PlaybackChannels 2 + } + } + +diff --git a/ucm2/DB410c/HiFi.conf b/ucm2/DB410c/HiFi.conf +index 1b2716a..62ddc8e 100644 +--- a/ucm2/DB410c/HiFi.conf ++++ b/ucm2/DB410c/HiFi.conf +@@ -1,14 +1,6 @@ + # Use case configuration for DB410c board. + # Author: Srinivas Kandagatla + +-SectionVerb { +- Value { +- PlaybackChannels 2 +- CaptureChannels 2 +- } +-} +- +- + SectionDevice."Speaker" { + Comment "Speaker playback" + +@@ -35,7 +27,6 @@ SectionDevice."Speaker" { + } + } + +- + SectionDevice."Headphones" { + Comment "Headphones playback" + +diff --git a/ucm2/DB820c/HDMI.conf b/ucm2/DB820c/HDMI.conf +index c0d40f6..f0ca015 100644 +--- a/ucm2/DB820c/HDMI.conf ++++ b/ucm2/DB820c/HDMI.conf +@@ -29,6 +29,5 @@ SectionDevice."HDMI" { + Value { + PlaybackPriority 200 + PlaybackPCM "plughw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/DB820c/HiFi.conf b/ucm2/DB820c/HiFi.conf +index 501c263..89280d7 100644 +--- a/ucm2/DB820c/HiFi.conf ++++ b/ucm2/DB820c/HiFi.conf +@@ -69,7 +69,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 100 + PlaybackPCM "plughw:${CardId},1" +- PlaybackChannels 2 + } + } + +diff --git a/ucm2/HDA-Intel/HiFi-dual.conf b/ucm2/HDA-Intel/HiFi-dual.conf +index 846c6db..174fef4 100644 +--- a/ucm2/HDA-Intel/HiFi-dual.conf ++++ b/ucm2/HDA-Intel/HiFi-dual.conf +@@ -1,8 +1,6 @@ + SectionVerb { + Value { + TQ "HiFi" +- PlaybackChannels 2 +- CaptureChannels 2 + } + + EnableSequence [ +diff --git a/ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf b/ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf +index 37b7e0d..2f625e4 100644 +--- a/ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf ++++ b/ucm2/USB-Audio/Dell-WD15-Dock-HiFi.conf +@@ -3,7 +3,6 @@ SectionDevice."Headphones" { + + Value { + PlaybackPriority 100 +- PlaybackChannels 2 + PlaybackPCM "hw:${CardId}" + } + } +@@ -13,7 +12,6 @@ SectionDevice."Line" { + + Value { + PlaybackPriority 200 +- PlaybackChannels 2 + PlaybackPCM "hw:${CardId},1" + } + } +@@ -23,7 +21,6 @@ SectionDevice."Mic" { + + Value { + CapturePriority 100 +- CaptureChannels 2 + CapturePCM "hw:${CardId}" + } + } +diff --git a/ucm2/broadwell-rt286/HiFi.conf b/ucm2/broadwell-rt286/HiFi.conf +index 96b89a0..611a03e 100644 +--- a/ucm2/broadwell-rt286/HiFi.conf ++++ b/ucm2/broadwell-rt286/HiFi.conf +@@ -23,7 +23,6 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + PlaybackMixerElem "DAC0" + PlaybackMasterElem "Master" + } +@@ -51,7 +50,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + PlaybackMixerElem "DAC0" + PlaybackMasterElem "Master" + JackDev "rt286-jack" +@@ -78,7 +76,6 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + CaptureMixerElem "Mic" + CaptureMasterElem "ADC0" + } +@@ -103,7 +100,6 @@ SectionDevice."Handset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + CaptureMixerElem "Mic" + CaptureMasterElem "ADC0" + JackDev "rt286-jack" +diff --git a/ucm2/broxton-rt298/broxton-rt298.conf b/ucm2/broxton-rt298/broxton-rt298.conf +index 1332dc5..95f9ac5 100644 +--- a/ucm2/broxton-rt298/broxton-rt298.conf ++++ b/ucm2/broxton-rt298/broxton-rt298.conf +@@ -8,13 +8,6 @@ SectionUseCase."HiFi" { + Comment "Play and record HiFi quality Music" + } + +-ValueDefaults { +- PlaybackChannels 2 +- PlaybackPriority 1 +- CaptureChannels 2 +- CapturePriority 2 +-} +- + SectionDefaults [ + cset "name='Headphone Jack Switch' 1" + cset "name='Speaker Switch' 1" +diff --git a/ucm2/chtrt5645/HiFi-dmic1.conf b/ucm2/chtrt5645/HiFi-dmic1.conf +index 4748bd9..1a8ee0a 100644 +--- a/ucm2/chtrt5645/HiFi-dmic1.conf ++++ b/ucm2/chtrt5645/HiFi-dmic1.conf +@@ -27,7 +27,6 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + + ConflictingDevice [ +@@ -50,7 +49,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -75,7 +73,6 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + + EnableSequence [ +@@ -98,7 +95,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + JackHWMute "Mic" + } +diff --git a/ucm2/chtrt5645/HiFi-dmic2.conf b/ucm2/chtrt5645/HiFi-dmic2.conf +index 459b9f5..c9fdd79 100644 +--- a/ucm2/chtrt5645/HiFi-dmic2.conf ++++ b/ucm2/chtrt5645/HiFi-dmic2.conf +@@ -27,7 +27,6 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + + ConflictingDevice [ +@@ -50,7 +49,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -75,7 +73,6 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + + EnableSequence [ +@@ -100,7 +97,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + JackHWMute "DMic" + } +diff --git a/ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf b/ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf +index fe410f3..db866cd 100644 +--- a/ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf ++++ b/ucm2/chtrt5645/HiFi-mono-speaker-analog-mic.conf +@@ -27,7 +27,6 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + + ConflictingDevice [ +@@ -54,7 +53,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -85,7 +83,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + JackHWMute "Mic" + } +diff --git a/ucm2/chtrt5645/HiFi.conf b/ucm2/chtrt5645/HiFi.conf +index 954bf68..58468a8 100644 +--- a/ucm2/chtrt5645/HiFi.conf ++++ b/ucm2/chtrt5645/HiFi.conf +@@ -27,7 +27,6 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + + ConflictingDevice [ +@@ -50,7 +49,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +@@ -77,7 +75,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + JackHWMute "Mic" + } +diff --git a/ucm2/codecs/cx2072x/HeadPhones.conf b/ucm2/codecs/cx2072x/HeadPhones.conf +index 484d020..adb70db 100644 +--- a/ucm2/codecs/cx2072x/HeadPhones.conf ++++ b/ucm2/codecs/cx2072x/HeadPhones.conf +@@ -18,7 +18,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/cx2072x/HeadsetMic.conf b/ucm2/codecs/cx2072x/HeadsetMic.conf +index b1a7771..5a6643e 100644 +--- a/ucm2/codecs/cx2072x/HeadsetMic.conf ++++ b/ucm2/codecs/cx2072x/HeadsetMic.conf +@@ -19,7 +19,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/cx2072x/InternalMic.conf b/ucm2/codecs/cx2072x/InternalMic.conf +index 831c3cc..9c083be 100644 +--- a/ucm2/codecs/cx2072x/InternalMic.conf ++++ b/ucm2/codecs/cx2072x/InternalMic.conf +@@ -19,6 +19,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/cx2072x/Speaker.conf b/ucm2/codecs/cx2072x/Speaker.conf +index f60e355..a641ba2 100644 +--- a/ucm2/codecs/cx2072x/Speaker.conf ++++ b/ucm2/codecs/cx2072x/Speaker.conf +@@ -18,6 +18,5 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/HeadPhones.conf b/ucm2/codecs/es8316/HeadPhones.conf +index 6a05e54..b68569a 100644 +--- a/ucm2/codecs/es8316/HeadPhones.conf ++++ b/ucm2/codecs/es8316/HeadPhones.conf +@@ -16,7 +16,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + JackHWMute "Speaker" + } +diff --git a/ucm2/codecs/es8316/IN1-HeadsetMic.conf b/ucm2/codecs/es8316/IN1-HeadsetMic.conf +index e9f9061..a76b275 100644 +--- a/ucm2/codecs/es8316/IN1-HeadsetMic.conf ++++ b/ucm2/codecs/es8316/IN1-HeadsetMic.conf +@@ -17,7 +17,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/es8316/IN1-InternalMic.conf b/ucm2/codecs/es8316/IN1-InternalMic.conf +index 31c5cda..ede0a8c 100644 +--- a/ucm2/codecs/es8316/IN1-InternalMic.conf ++++ b/ucm2/codecs/es8316/IN1-InternalMic.conf +@@ -17,6 +17,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/IN2-HeadsetMic.conf b/ucm2/codecs/es8316/IN2-HeadsetMic.conf +index 377d84d..b114c86 100644 +--- a/ucm2/codecs/es8316/IN2-HeadsetMic.conf ++++ b/ucm2/codecs/es8316/IN2-HeadsetMic.conf +@@ -17,7 +17,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/es8316/IN2-InternalMic.conf b/ucm2/codecs/es8316/IN2-InternalMic.conf +index f0ff6f1..c8fce62 100644 +--- a/ucm2/codecs/es8316/IN2-InternalMic.conf ++++ b/ucm2/codecs/es8316/IN2-InternalMic.conf +@@ -17,6 +17,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/MonoSpeaker.conf b/ucm2/codecs/es8316/MonoSpeaker.conf +index 64a7e76..f5f4273 100644 +--- a/ucm2/codecs/es8316/MonoSpeaker.conf ++++ b/ucm2/codecs/es8316/MonoSpeaker.conf +@@ -33,6 +33,5 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/es8316/Speaker.conf b/ucm2/codecs/es8316/Speaker.conf +index 58fe078..03c21b3 100644 +--- a/ucm2/codecs/es8316/Speaker.conf ++++ b/ucm2/codecs/es8316/Speaker.conf +@@ -16,6 +16,5 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/nau8824/HeadPhones.conf b/ucm2/codecs/nau8824/HeadPhones.conf +index 6623365..a807f84 100644 +--- a/ucm2/codecs/nau8824/HeadPhones.conf ++++ b/ucm2/codecs/nau8824/HeadPhones.conf +@@ -4,7 +4,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + } + +diff --git a/ucm2/codecs/nau8824/HeadsetMic.conf b/ucm2/codecs/nau8824/HeadsetMic.conf +index 7381638..1129a6b 100644 +--- a/ucm2/codecs/nau8824/HeadsetMic.conf ++++ b/ucm2/codecs/nau8824/HeadsetMic.conf +@@ -4,7 +4,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 300 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + } + +diff --git a/ucm2/codecs/nau8824/InternalMic.conf b/ucm2/codecs/nau8824/InternalMic.conf +index 731a261..409f01b 100644 +--- a/ucm2/codecs/nau8824/InternalMic.conf ++++ b/ucm2/codecs/nau8824/InternalMic.conf +@@ -4,7 +4,6 @@ SectionDevice."Mic" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + + ConflictingDevice [ +diff --git a/ucm2/codecs/nau8824/MonoSpeaker.conf b/ucm2/codecs/nau8824/MonoSpeaker.conf +index b02a22c..6b4ef8a 100644 +--- a/ucm2/codecs/nau8824/MonoSpeaker.conf ++++ b/ucm2/codecs/nau8824/MonoSpeaker.conf +@@ -4,7 +4,6 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + + ConflictingDevice [ +diff --git a/ucm2/codecs/nau8824/Speaker.conf b/ucm2/codecs/nau8824/Speaker.conf +index 3658795..a995873 100644 +--- a/ucm2/codecs/nau8824/Speaker.conf ++++ b/ucm2/codecs/nau8824/Speaker.conf +@@ -4,7 +4,6 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + + ConflictingDevice [ +diff --git a/ucm2/codecs/rt5640/DigitalMics.conf b/ucm2/codecs/rt5640/DigitalMics.conf +index 9cd8a8c..503c4a9 100644 +--- a/ucm2/codecs/rt5640/DigitalMics.conf ++++ b/ucm2/codecs/rt5640/DigitalMics.conf +@@ -22,6 +22,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/HeadPhones.conf b/ucm2/codecs/rt5640/HeadPhones.conf +index 7859b7a..42151d6 100644 +--- a/ucm2/codecs/rt5640/HeadPhones.conf ++++ b/ucm2/codecs/rt5640/HeadPhones.conf +@@ -33,7 +33,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 300 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/rt5640/HeadsetMic.conf b/ucm2/codecs/rt5640/HeadsetMic.conf +index 40e0abe..7a8dfb8 100644 +--- a/ucm2/codecs/rt5640/HeadsetMic.conf ++++ b/ucm2/codecs/rt5640/HeadsetMic.conf +@@ -38,7 +38,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/rt5640/IN1-InternalMic.conf b/ucm2/codecs/rt5640/IN1-InternalMic.conf +index 7d76c4f..ebb5b6d 100644 +--- a/ucm2/codecs/rt5640/IN1-InternalMic.conf ++++ b/ucm2/codecs/rt5640/IN1-InternalMic.conf +@@ -41,6 +41,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/IN3-InternalMic.conf b/ucm2/codecs/rt5640/IN3-InternalMic.conf +index 2df2938..172d909 100644 +--- a/ucm2/codecs/rt5640/IN3-InternalMic.conf ++++ b/ucm2/codecs/rt5640/IN3-InternalMic.conf +@@ -41,6 +41,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/MonoSpeaker.conf b/ucm2/codecs/rt5640/MonoSpeaker.conf +index 70ab809..ddc7ba8 100644 +--- a/ucm2/codecs/rt5640/MonoSpeaker.conf ++++ b/ucm2/codecs/rt5640/MonoSpeaker.conf +@@ -38,6 +38,5 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5640/Speaker.conf b/ucm2/codecs/rt5640/Speaker.conf +index 3b4b296..411cd13 100644 +--- a/ucm2/codecs/rt5640/Speaker.conf ++++ b/ucm2/codecs/rt5640/Speaker.conf +@@ -38,6 +38,5 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5645/AnalogMic.conf b/ucm2/codecs/rt5645/AnalogMic.conf +index 5583cdb..1793880 100644 +--- a/ucm2/codecs/rt5645/AnalogMic.conf ++++ b/ucm2/codecs/rt5645/AnalogMic.conf +@@ -4,7 +4,6 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + + EnableSequence [ +diff --git a/ucm2/codecs/rt5651/DigitalMic.conf b/ucm2/codecs/rt5651/DigitalMic.conf +index fa1de4c..aa40c1c 100644 +--- a/ucm2/codecs/rt5651/DigitalMic.conf ++++ b/ucm2/codecs/rt5651/DigitalMic.conf +@@ -16,6 +16,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/HeadPhones-swapped.conf b/ucm2/codecs/rt5651/HeadPhones-swapped.conf +index 7e91aa2..595f29c 100644 +--- a/ucm2/codecs/rt5651/HeadPhones-swapped.conf ++++ b/ucm2/codecs/rt5651/HeadPhones-swapped.conf +@@ -33,7 +33,6 @@ SectionDevice."Headphones" { + + Value { + PlaybackPriority 200 +- PlaybackChannels 2 + PlaybackPCM "hw:${CardId}" + JackControl "Headphone Jack" + } +diff --git a/ucm2/codecs/rt5651/HeadPhones.conf b/ucm2/codecs/rt5651/HeadPhones.conf +index 18a4108..266c851 100644 +--- a/ucm2/codecs/rt5651/HeadPhones.conf ++++ b/ucm2/codecs/rt5651/HeadPhones.conf +@@ -25,7 +25,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/rt5651/IN1-InternalMic.conf b/ucm2/codecs/rt5651/IN1-InternalMic.conf +index 13c7cb6..faa0bfa 100644 +--- a/ucm2/codecs/rt5651/IN1-InternalMic.conf ++++ b/ucm2/codecs/rt5651/IN1-InternalMic.conf +@@ -20,6 +20,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/IN12-InternalMic.conf b/ucm2/codecs/rt5651/IN12-InternalMic.conf +index e017541..79c72a3 100644 +--- a/ucm2/codecs/rt5651/IN12-InternalMic.conf ++++ b/ucm2/codecs/rt5651/IN12-InternalMic.conf +@@ -24,6 +24,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/IN2-HeadsetMic.conf b/ucm2/codecs/rt5651/IN2-HeadsetMic.conf +index 5b51439..86bbacb 100644 +--- a/ucm2/codecs/rt5651/IN2-HeadsetMic.conf ++++ b/ucm2/codecs/rt5651/IN2-HeadsetMic.conf +@@ -24,7 +24,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/rt5651/IN2-InternalMic.conf b/ucm2/codecs/rt5651/IN2-InternalMic.conf +index 9eeef4d..da15a6d 100644 +--- a/ucm2/codecs/rt5651/IN2-InternalMic.conf ++++ b/ucm2/codecs/rt5651/IN2-InternalMic.conf +@@ -20,6 +20,5 @@ SectionDevice."Mic" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/IN3-HeadsetMic.conf b/ucm2/codecs/rt5651/IN3-HeadsetMic.conf +index d579dcd..a40fefc 100644 +--- a/ucm2/codecs/rt5651/IN3-HeadsetMic.conf ++++ b/ucm2/codecs/rt5651/IN3-HeadsetMic.conf +@@ -24,7 +24,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/rt5651/MonoSpeaker.conf b/ucm2/codecs/rt5651/MonoSpeaker.conf +index 9c780a0..a83b481 100644 +--- a/ucm2/codecs/rt5651/MonoSpeaker.conf ++++ b/ucm2/codecs/rt5651/MonoSpeaker.conf +@@ -43,6 +43,5 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5651/Speaker.conf b/ucm2/codecs/rt5651/Speaker.conf +index efc12e5..18308b4 100644 +--- a/ucm2/codecs/rt5651/Speaker.conf ++++ b/ucm2/codecs/rt5651/Speaker.conf +@@ -25,6 +25,5 @@ SectionDevice."Speaker" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5672/DMIC1.conf b/ucm2/codecs/rt5672/DMIC1.conf +index 73983af..2018283 100644 +--- a/ucm2/codecs/rt5672/DMIC1.conf ++++ b/ucm2/codecs/rt5672/DMIC1.conf +@@ -23,6 +23,5 @@ SectionDevice."Mic1" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5672/DMIC2.conf b/ucm2/codecs/rt5672/DMIC2.conf +index 751c95c..48e6170 100644 +--- a/ucm2/codecs/rt5672/DMIC2.conf ++++ b/ucm2/codecs/rt5672/DMIC2.conf +@@ -23,6 +23,5 @@ SectionDevice."Mic2" { + Value { + CapturePriority 200 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + } + } +diff --git a/ucm2/codecs/rt5672/HeadPhones.conf b/ucm2/codecs/rt5672/HeadPhones.conf +index 0542f77..2c8d6e8 100644 +--- a/ucm2/codecs/rt5672/HeadPhones.conf ++++ b/ucm2/codecs/rt5672/HeadPhones.conf +@@ -17,7 +17,6 @@ SectionDevice."Headphones" { + Value { + PlaybackPriority 300 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackControl "Headphone Jack" + } + } +diff --git a/ucm2/codecs/rt5672/HeadsetMic.conf b/ucm2/codecs/rt5672/HeadsetMic.conf +index f407579..a764d82 100644 +--- a/ucm2/codecs/rt5672/HeadsetMic.conf ++++ b/ucm2/codecs/rt5672/HeadsetMic.conf +@@ -32,7 +32,6 @@ SectionDevice."Headset" { + Value { + CapturePriority 300 + CapturePCM "hw:${CardId}" +- CaptureChannels 2 + JackControl "Headset Mic Jack" + } + } +diff --git a/ucm2/codecs/rt5672/MonoSpeaker.conf b/ucm2/codecs/rt5672/MonoSpeaker.conf +index 0849c67..f08c9c6 100644 +--- a/ucm2/codecs/rt5672/MonoSpeaker.conf ++++ b/ucm2/codecs/rt5672/MonoSpeaker.conf +@@ -21,6 +21,5 @@ SectionDevice."Speaker2" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/codecs/rt5672/Speaker.conf b/ucm2/codecs/rt5672/Speaker.conf +index 44e73aa..8b7bcf8 100644 +--- a/ucm2/codecs/rt5672/Speaker.conf ++++ b/ucm2/codecs/rt5672/Speaker.conf +@@ -17,6 +17,5 @@ SectionDevice."Speaker1" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + } + } +diff --git a/ucm2/kblrt5660/Hdmi1.conf b/ucm2/kblrt5660/Hdmi1.conf +index ccf5118..561946f 100755 +--- a/ucm2/kblrt5660/Hdmi1.conf ++++ b/ucm2/kblrt5660/Hdmi1.conf +@@ -7,7 +7,6 @@ SectionDevice."HDMI1" { + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId},2" +- PlaybackChannels 2 + If.1 { + Condition { + Type ControlExists +diff --git a/ucm2/kblrt5660/Hdmi2.conf b/ucm2/kblrt5660/Hdmi2.conf +index c5e4001..756a346 100755 +--- a/ucm2/kblrt5660/Hdmi2.conf ++++ b/ucm2/kblrt5660/Hdmi2.conf +@@ -7,7 +7,6 @@ SectionDevice."HDMI2" { + Value { + PlaybackPriority 300 + PlaybackPCM "hw:${CardId},3" +- PlaybackChannels 2 + If.1 { + Condition { + Type ControlExists +diff --git a/ucm2/kblrt5660/HiFi.conf b/ucm2/kblrt5660/HiFi.conf +index 0f5d46d..c1e8a0f 100755 +--- a/ucm2/kblrt5660/HiFi.conf ++++ b/ucm2/kblrt5660/HiFi.conf +@@ -28,7 +28,6 @@ SectionDevice."Line1" { + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId}" +- PlaybackChannels 2 + JackDev "rt5660-jack" + JackControl "Line Out Jack" + } +@@ -61,7 +60,6 @@ SectionDevice."Line2" { + Value { + CapturePriority 100 + CapturePCM "hw:${CardId},1" +- CaptureChannels 2 + JackDev "rt5660-jack" + JackControl "Line In Jack" + } +diff --git a/ucm2/skylake-rt286/skylake-rt286.conf b/ucm2/skylake-rt286/skylake-rt286.conf +index 4ea5777..97f2a7c 100644 +--- a/ucm2/skylake-rt286/skylake-rt286.conf ++++ b/ucm2/skylake-rt286/skylake-rt286.conf +@@ -8,11 +8,6 @@ SectionUseCase."HiFi" { + Comment "Play and record HiFi quality Music" + } + +-ValueDefaults { +- PlaybackChannels 2 +- CaptureChannels 2 +-} +- + SectionDefaults [ + cset "name='Headphone Jack Switch' 1" + cset "name='Speaker Switch' 1" +diff --git a/ucm2/sof-hda-dsp/HDA-Capture-value.conf b/ucm2/sof-hda-dsp/HDA-Capture-value.conf +index 5f3c2a3..2f1316a 100644 +--- a/ucm2/sof-hda-dsp/HDA-Capture-value.conf ++++ b/ucm2/sof-hda-dsp/HDA-Capture-value.conf +@@ -2,4 +2,3 @@ CapturePCM "hw:${CardId}" + CaptureMixerElem "Capture" + CaptureVolume "Capture Volume" + CaptureSwitch "Capture Switch" +-CaptureChannels 2 +diff --git a/ucm2/sof-hda-dsp/Hdmi.conf b/ucm2/sof-hda-dsp/Hdmi.conf +index 1982c72..be6cb39 100644 +--- a/ucm2/sof-hda-dsp/Hdmi.conf ++++ b/ucm2/sof-hda-dsp/Hdmi.conf +@@ -14,7 +14,6 @@ SectionDevice."HDMI1" { + Value { + PlaybackPriority 500 + PlaybackPCM "hw:${CardId},3" +- PlaybackChannels 2 + JackControl "HDMI/DP,pcm=3 Jack" + } + } +@@ -33,7 +32,6 @@ SectionDevice."HDMI2" { + Value { + PlaybackPriority 600 + PlaybackPCM "hw:${CardId},4" +- PlaybackChannels 2 + JackControl "HDMI/DP,pcm=4 Jack" + } + } +@@ -52,7 +50,6 @@ SectionDevice."HDMI3" { + Value { + PlaybackPriority 700 + PlaybackPCM "hw:${CardId},5" +- PlaybackChannels 2 + JackControl "HDMI/DP,pcm=5 Jack" + } + } +diff --git a/ucm2/sof-hda-dsp/HiFi.conf b/ucm2/sof-hda-dsp/HiFi.conf +index 6dfdabe..60a8693 100644 +--- a/ucm2/sof-hda-dsp/HiFi.conf ++++ b/ucm2/sof-hda-dsp/HiFi.conf +@@ -24,7 +24,6 @@ SectionDevice."Headphones1" { + PlaybackMasterElem "Master" + PlaybackVolume "Headphone Playback Volume" + PlaybackSwitch "Headphone Playback Switch" +- PlaybackChannels 2 + If.jack { + Condition { + Type ControlExists +@@ -77,7 +76,6 @@ SectionDevice."Speaker" { + PlaybackMasterElem "Master" + PlaybackVolume "Speaker Playback Volume" + PlaybackSwitch "Speaker Playback Switch" +- PlaybackChannels 2 + } + } + +@@ -149,9 +147,6 @@ SectionDevice."Mic" { + True { + CaptureChannels 4 + } +- False { +- CaptureChannels 2 +- } + } + If.vol { + Condition { +-- +2.24.1 +