22621 lines
716 KiB
Diff
22621 lines
716 KiB
Diff
From c79f09e1f5e8b559b58dacdb00708d995b2e3aa5 Mon Sep 17 00:00:00 2001
|
|
From: paulhsia <paulhsia@chromium.org>
|
|
Date: Sat, 30 Nov 2019 03:35:30 +0800
|
|
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().
|
|
|
|
Signed-off-by: paulhsia <paulhsia@chromium.org>
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/ucm/main.c | 8 +++++---
|
|
1 file changed, 5 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/ucm/main.c b/src/ucm/main.c
|
|
index b0b6ffb3..252e50d9 100644
|
|
--- a/src/ucm/main.c
|
|
+++ b/src/ucm/main.c
|
|
@@ -61,11 +61,13 @@ static int check_identifier(const char *identifier, const char *prefix)
|
|
{
|
|
int len;
|
|
|
|
- if (strcmp(identifier, prefix) == 0)
|
|
- return 1;
|
|
len = strlen(prefix);
|
|
- if (memcmp(identifier, prefix, len) == 0 && identifier[len] == '/')
|
|
+ if (strncmp(identifier, prefix, len) != 0)
|
|
+ return 0;
|
|
+
|
|
+ if (identifier[len] == 0 || identifier[len] == '/')
|
|
return 1;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From 9baf64da2f26844434ecea4825052937a3abe06c Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
Date: Fri, 29 Nov 2019 22:28:26 +0100
|
|
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 <perex@perex.cz>
|
|
---
|
|
src/ucm/main.c | 8 ++++++--
|
|
1 file changed, 6 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/ucm/main.c b/src/ucm/main.c
|
|
index 252e50d9..b80db65f 100644
|
|
--- a/src/ucm/main.c
|
|
+++ b/src/ucm/main.c
|
|
@@ -1160,8 +1160,10 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr,
|
|
|
|
modifier = find_modifier(uc_mgr, verb, name, 0);
|
|
if (modifier) {
|
|
- if (modifier->dev_list.type != type)
|
|
+ if (modifier->dev_list.type != type) {
|
|
+ *list = NULL;
|
|
return 0;
|
|
+ }
|
|
return get_list(&modifier->dev_list.list, list,
|
|
struct dev_list_node, list,
|
|
name);
|
|
@@ -1169,8 +1171,10 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr,
|
|
|
|
device = find_device(uc_mgr, verb, name, 0);
|
|
if (device) {
|
|
- if (device->dev_list.type != type)
|
|
+ if (device->dev_list.type != type) {
|
|
+ *list = NULL;
|
|
return 0;
|
|
+ }
|
|
return get_list(&device->dev_list.list, list,
|
|
struct dev_list_node, list,
|
|
name);
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From ebdd2b6cdb8119cf75f0dd0a3b283d271b3a547e Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
Date: Sat, 30 Nov 2019 20:31:55 +0100
|
|
Subject: [PATCH 03/69] ucm: add _identifiers list
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 1 +
|
|
src/ucm/main.c | 268 ++++++++++++++++++++++++++++++++++-----------
|
|
2 files changed, 208 insertions(+), 61 deletions(-)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index 8e7e838c..85c58ac0 100644
|
|
--- a/include/use-case.h
|
|
+++ b/include/use-case.h
|
|
@@ -206,6 +206,7 @@ int snd_use_case_free_list(const char *list[], int items);
|
|
* - _enadevs - get list of enabled devices
|
|
* - _enamods - get list of enabled modifiers
|
|
*
|
|
+ * - _identifiers/{modifier}|{device}[/{verb}] - list of value identifiers
|
|
* - _supporteddevs/{modifier}|{device}[/{verb}] - list of supported devices
|
|
* - _conflictingdevs/{modifier}|{device}[/{verb}] - list of conflicting devices
|
|
*
|
|
diff --git a/src/ucm/main.c b/src/ucm/main.c
|
|
index b80db65f..d2078a23 100644
|
|
--- a/src/ucm/main.c
|
|
+++ b/src/ucm/main.c
|
|
@@ -1072,7 +1072,6 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
|
|
/**
|
|
* \brief Get list of verbs in pair verbname+comment
|
|
* \param list Returned list
|
|
- * \param verbname For verb (NULL = current)
|
|
* \return Number of list entries if success, otherwise a negative error code
|
|
*/
|
|
static int get_verb_list(snd_use_case_mgr_t *uc_mgr, const char **list[])
|
|
@@ -1181,7 +1180,6 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr,
|
|
}
|
|
|
|
return -ENOENT;
|
|
-
|
|
}
|
|
|
|
/**
|
|
@@ -1210,41 +1208,201 @@ static int get_conflicting_device_list(snd_use_case_mgr_t *uc_mgr,
|
|
|
|
#ifndef DOC_HIDDEN
|
|
struct myvalue {
|
|
- struct list_head list;
|
|
- char *value;
|
|
+ struct list_head list;
|
|
+ const char *text;
|
|
};
|
|
#endif
|
|
|
|
+/**
|
|
+ * \brief Convert myvalue list string list
|
|
+ * \param list myvalue list
|
|
+ * \param res string list
|
|
+ * \retval Number of list entries if success, otherwise a negativer error code
|
|
+ */
|
|
+static int myvalue_to_str_list(struct list_head *list, char ***res)
|
|
+{
|
|
+ struct list_head *pos;
|
|
+ struct myvalue *value;
|
|
+ char **p;
|
|
+ int cnt;
|
|
+
|
|
+ cnt = alloc_str_list(list, 1, res);
|
|
+ if (cnt < 0)
|
|
+ return cnt;
|
|
+ p = *res;
|
|
+ list_for_each(pos, list) {
|
|
+ value = list_entry(pos, struct myvalue, list);
|
|
+ *p = strdup(value->text);
|
|
+ if (*p == NULL) {
|
|
+ snd_use_case_free_list((const char **)p, cnt);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ p++;
|
|
+ }
|
|
+ return cnt;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Free myvalue list
|
|
+ * \param list myvalue list
|
|
+ */
|
|
+static void myvalue_list_free(struct list_head *list)
|
|
+{
|
|
+ struct list_head *pos, *npos;
|
|
+ struct myvalue *value;
|
|
+
|
|
+ list_for_each_safe(pos, npos, list) {
|
|
+ value = list_entry(pos, struct myvalue, list);
|
|
+ list_del(&value->list);
|
|
+ free(value);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Merge one value to the myvalue list
|
|
+ * \param list The list with values
|
|
+ * \param value The value to be merged (without duplicates)
|
|
+ * \return 1 if dup, 0 if success, otherwise a negative error code
|
|
+ */
|
|
+static int merge_value(struct list_head *list, const char *text)
|
|
+{
|
|
+ struct list_head *pos;
|
|
+ struct myvalue *value;
|
|
+
|
|
+ list_for_each(pos, list) {
|
|
+ value = list_entry(pos, struct myvalue, list);
|
|
+ if (strcmp(value->text, text) == 0)
|
|
+ return 1;
|
|
+ }
|
|
+ value = malloc(sizeof(*value));
|
|
+ if (value == NULL)
|
|
+ return -ENOMEM;
|
|
+ value->text = text;
|
|
+ list_add_tail(&value->list, list);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Find all values for given identifier
|
|
+ * \param list Returned list
|
|
+ * \param source Source list with ucm_value structures
|
|
+ * \return Zero if success, otherwise a negative error code
|
|
+ */
|
|
+static int add_identifiers(struct list_head *list,
|
|
+ struct list_head *source)
|
|
+{
|
|
+ struct ucm_value *v;
|
|
+ struct list_head *pos;
|
|
+ int err;
|
|
+
|
|
+ list_for_each(pos, source) {
|
|
+ v = list_entry(pos, struct ucm_value, list);
|
|
+ err = merge_value(list, v->name);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Find all values for given identifier
|
|
+ * \param list Returned list
|
|
+ * \param identifier Identifier
|
|
+ * \param source Source list with ucm_value structures
|
|
+ */
|
|
static int add_values(struct list_head *list,
|
|
const char *identifier,
|
|
struct list_head *source)
|
|
{
|
|
- struct ucm_value *v;
|
|
- struct myvalue *val;
|
|
- struct list_head *pos, *pos1;
|
|
- int match;
|
|
+ struct ucm_value *v;
|
|
+ struct list_head *pos;
|
|
+ int err;
|
|
|
|
- list_for_each(pos, source) {
|
|
- v = list_entry(pos, struct ucm_value, list);
|
|
- if (check_identifier(identifier, v->name)) {
|
|
- match = 0;
|
|
- list_for_each(pos1, list) {
|
|
- val = list_entry(pos1, struct myvalue, list);
|
|
- if (strcmp(val->value, v->data) == 0) {
|
|
- match = 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
- if (!match) {
|
|
- val = malloc(sizeof(struct myvalue));
|
|
- if (val == NULL)
|
|
- return -ENOMEM;
|
|
- val->value = v->data;
|
|
- list_add_tail(&val->list, list);
|
|
- }
|
|
- }
|
|
- }
|
|
- return 0;
|
|
+ list_for_each(pos, source) {
|
|
+ v = list_entry(pos, struct ucm_value, list);
|
|
+ if (check_identifier(identifier, v->name)) {
|
|
+ err = merge_value(list, v->data);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief compare two identifiers
|
|
+ */
|
|
+static int identifier_cmp(const void *_a, const void *_b)
|
|
+{
|
|
+ const char * const *a = _a;
|
|
+ const char * const *b = _b;
|
|
+ return strcmp(*a, *b);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Get list of available identifiers
|
|
+ * \param list Returned list
|
|
+ * \param name Name of verb or modifier to query
|
|
+ * \return Number of list entries if success, otherwise a negative error code
|
|
+ */
|
|
+static int get_identifiers_list(snd_use_case_mgr_t *uc_mgr,
|
|
+ const char **list[], char *name)
|
|
+{
|
|
+ struct use_case_verb *verb;
|
|
+ struct use_case_modifier *modifier;
|
|
+ struct use_case_device *device;
|
|
+ struct list_head mylist;
|
|
+ struct list_head *value_list;
|
|
+ char *str, **res;
|
|
+ int err;
|
|
+
|
|
+ if (!name)
|
|
+ return -ENOENT;
|
|
+
|
|
+ str = strchr(name, '/');
|
|
+ if (str) {
|
|
+ *str = '\0';
|
|
+ verb = find_verb(uc_mgr, str + 1);
|
|
+ }
|
|
+ else {
|
|
+ verb = uc_mgr->active_verb;
|
|
+ }
|
|
+ if (!verb)
|
|
+ return -ENOENT;
|
|
+
|
|
+ value_list = NULL;
|
|
+ modifier = find_modifier(uc_mgr, verb, name, 0);
|
|
+ if (modifier) {
|
|
+ value_list = &modifier->value_list;
|
|
+ } else {
|
|
+ device = find_device(uc_mgr, verb, name, 0);
|
|
+ if (device)
|
|
+ value_list = &device->value_list;
|
|
+ }
|
|
+ if (value_list == NULL)
|
|
+ return -ENOENT;
|
|
+
|
|
+ INIT_LIST_HEAD(&mylist);
|
|
+ err = add_identifiers(&mylist, &uc_mgr->value_list);
|
|
+ if (err < 0)
|
|
+ goto __fail;
|
|
+ err = add_identifiers(&mylist, &verb->value_list);
|
|
+ if (err < 0)
|
|
+ goto __fail;
|
|
+ err = add_identifiers(&mylist, value_list);
|
|
+ if (err < 0)
|
|
+ goto __fail;
|
|
+ err = myvalue_to_str_list(&mylist, &res);
|
|
+ if (err > 0)
|
|
+ *list = (const char **)res;
|
|
+ else if (err == 0)
|
|
+ *list = NULL;
|
|
+__fail:
|
|
+ myvalue_list_free(&mylist);
|
|
+ if (err <= 0)
|
|
+ return err;
|
|
+ qsort(*list, err, sizeof(char *), identifier_cmp);
|
|
+ return err;
|
|
}
|
|
|
|
/**
|
|
@@ -1258,8 +1416,7 @@ static int get_value_list(snd_use_case_mgr_t *uc_mgr,
|
|
const char **list[],
|
|
char *verbname)
|
|
{
|
|
- struct list_head mylist, *pos, *npos;
|
|
- struct myvalue *val;
|
|
+ struct list_head mylist, *pos;
|
|
struct use_case_verb *verb;
|
|
struct use_case_device *dev;
|
|
struct use_case_modifier *mod;
|
|
@@ -1292,26 +1449,13 @@ static int get_value_list(snd_use_case_mgr_t *uc_mgr,
|
|
if (err < 0)
|
|
goto __fail;
|
|
}
|
|
- err = alloc_str_list(&mylist, 1, &res);
|
|
- if (err >= 0) {
|
|
+ err = myvalue_to_str_list(&mylist, &res);
|
|
+ if (err > 0)
|
|
*list = (const char **)res;
|
|
- list_for_each(pos, &mylist) {
|
|
- val = list_entry(pos, struct myvalue, list);
|
|
- *res = strdup(val->value);
|
|
- if (*res == NULL) {
|
|
- snd_use_case_free_list((const char **)res, err);
|
|
- err = -ENOMEM;
|
|
- goto __fail;
|
|
- }
|
|
- res++;
|
|
- }
|
|
- }
|
|
+ else if (err == 0)
|
|
+ *list = NULL;
|
|
__fail:
|
|
- list_for_each_safe(pos, npos, &mylist) {
|
|
- val = list_entry(pos, struct myvalue, list);
|
|
- list_del(&val->list);
|
|
- free(val);
|
|
- }
|
|
+ myvalue_list_free(&mylist);
|
|
return err;
|
|
}
|
|
|
|
@@ -1381,21 +1525,23 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
|
} else {
|
|
str = NULL;
|
|
}
|
|
- if (check_identifier(identifier, "_devices"))
|
|
- err = get_device_list(uc_mgr, list, str);
|
|
+ if (check_identifier(identifier, "_devices"))
|
|
+ err = get_device_list(uc_mgr, list, str);
|
|
else if (check_identifier(identifier, "_modifiers"))
|
|
- err = get_modifier_list(uc_mgr, list, str);
|
|
- else if (check_identifier(identifier, "_supporteddevs"))
|
|
- err = get_supported_device_list(uc_mgr, list, str);
|
|
- else if (check_identifier(identifier, "_conflictingdevs"))
|
|
- err = get_conflicting_device_list(uc_mgr, list, str);
|
|
+ err = get_modifier_list(uc_mgr, list, str);
|
|
+ else if (check_identifier(identifier, "_identifiers"))
|
|
+ err = get_identifiers_list(uc_mgr, list, str);
|
|
+ else if (check_identifier(identifier, "_supporteddevs"))
|
|
+ err = get_supported_device_list(uc_mgr, list, str);
|
|
+ else if (check_identifier(identifier, "_conflictingdevs"))
|
|
+ err = get_conflicting_device_list(uc_mgr, list, str);
|
|
else if (identifier[0] == '_')
|
|
err = -ENOENT;
|
|
- else
|
|
- err = get_value_list(uc_mgr, identifier, list, str);
|
|
- if (str)
|
|
- free(str);
|
|
- }
|
|
+ else
|
|
+ err = get_value_list(uc_mgr, identifier, list, str);
|
|
+ if (str)
|
|
+ free(str);
|
|
+ }
|
|
__end:
|
|
pthread_mutex_unlock(&uc_mgr->mutex);
|
|
return err;
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From 5ee5ef31b5ff3fb7c904054cb9cac7478a727f7c Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
Date: Sun, 1 Dec 2019 14:26:40 +0100
|
|
Subject: [PATCH 04/69] namehint: correct the @args check
|
|
|
|
BugLink: https://github.com/alsa-project/alsa-plugins/issues/3
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/control/namehint.c | 6 ++++++
|
|
1 file changed, 6 insertions(+)
|
|
|
|
diff --git a/src/control/namehint.c b/src/control/namehint.c
|
|
index 808df6b5..4927ef97 100644
|
|
--- a/src/control/namehint.c
|
|
+++ b/src/control/namehint.c
|
|
@@ -348,6 +348,12 @@ static int try_config(snd_config_t *config,
|
|
goto __cleanup;
|
|
if (snd_config_search(res, "@args", &cfg) >= 0) {
|
|
snd_config_for_each(i, next, cfg) {
|
|
+ /* skip the argument list */
|
|
+ snd_config_get_id(snd_config_iterator_entry(i), &str);
|
|
+ while (*str && *str >= '0' && *str <= '9') str++;
|
|
+ if (*str == '\0')
|
|
+ continue;
|
|
+ /* the argument definition must have the default */
|
|
if (snd_config_search(snd_config_iterator_entry(i),
|
|
"default", NULL) < 0) {
|
|
err = -EINVAL;
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From 6055f8a584296abfc0cec0439ceb708f0eddcc9d Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
Date: Sun, 1 Dec 2019 14:30:54 +0100
|
|
Subject: [PATCH 05/69] namehint: improve the previous patch (check the
|
|
returned value)
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/control/namehint.c | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/control/namehint.c b/src/control/namehint.c
|
|
index 4927ef97..60c48ae3 100644
|
|
--- a/src/control/namehint.c
|
|
+++ b/src/control/namehint.c
|
|
@@ -349,7 +349,8 @@ static int try_config(snd_config_t *config,
|
|
if (snd_config_search(res, "@args", &cfg) >= 0) {
|
|
snd_config_for_each(i, next, cfg) {
|
|
/* skip the argument list */
|
|
- snd_config_get_id(snd_config_iterator_entry(i), &str);
|
|
+ if (snd_config_get_id(snd_config_iterator_entry(i), &str) < 0)
|
|
+ continue;
|
|
while (*str && *str >= '0' && *str <= '9') str++;
|
|
if (*str == '\0')
|
|
continue;
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From 4dddcf733d56a13f4d042fefa1fb6230c09f1f65 Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
Date: Mon, 2 Dec 2019 11:56:30 +0100
|
|
Subject: [PATCH 06/69] ucm: docs - allow spaces in device names for JackHWMute
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 25 +++++++++++++------------
|
|
1 file changed, 13 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index 85c58ac0..e1f58027 100644
|
|
--- a/include/use-case.h
|
|
+++ b/include/use-case.h
|
|
@@ -326,7 +326,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
|
* - Valid values: "soft" (software attenuation)
|
|
* - EDIDFile
|
|
* - Path to EDID file for HDMI devices
|
|
- * - JackControl, JackDev, JackHWMute
|
|
+ * - JackControl, JackDev
|
|
* - Jack information for a device. The jack status can be reported via
|
|
* a kcontrol and/or via an input device. **JackControl** is the
|
|
* kcontrol name of the jack, and **JackDev** is the input device id of
|
|
@@ -334,17 +334,18 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
|
* JackDev value should be "foo"). UCM configuration files should
|
|
* contain both JackControl and JackDev when possible, because
|
|
* applications are likely to support only one or the other.
|
|
- *
|
|
- * If **JackHWMute** is set, it indicates that when the jack is plugged
|
|
- * in, the hardware automatically mutes some other device(s). The
|
|
- * JackHWMute value is a space-separated list of device names (this
|
|
- * isn't compatible with device names with spaces in them, so don't use
|
|
- * such device names!). Note that JackHWMute should be used only when
|
|
- * the hardware enforces the automatic muting. If the hardware doesn't
|
|
- * enforce any muting, it may still be tempting to set JackHWMute to
|
|
- * trick upper software layers to e.g. automatically mute speakers when
|
|
- * headphones are plugged in, but that's application policy
|
|
- * configuration that doesn't belong to UCM configuration files.
|
|
+ * - JackHWMute
|
|
+ * If this value is set, it indicates that when the jack is plugged
|
|
+ * in, the hardware automatically mutes some other device(s). The
|
|
+ * value is a space-separated list of device names. If the device
|
|
+ * name contains space, it must be enclosed to ' or ", e.g.:
|
|
+ * JackHWMute "'Dock Headphone' Headphone"
|
|
+ * Note that JackHWMute should be used only when the hardware enforces
|
|
+ * the automatic muting. If the hardware doesn't enforce any muting, it
|
|
+ * may still be tempting to set JackHWMute to trick upper software layers
|
|
+ * to e.g. automatically mute speakers when headphones are plugged in,
|
|
+ * but that's application policy configuration that doesn't belong
|
|
+ * to UCM configuration files.
|
|
* - MinBufferLevel
|
|
* - This is used on platform where reported buffer level is not accurate.
|
|
* E.g. "512", which holds 512 samples in device buffer. Note: this will
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From 2a286ca9a8415571181ce58027686ec332a834e9 Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
Date: Mon, 2 Dec 2019 11:57:18 +0100
|
|
Subject: [PATCH 07/69] use-case: docs - add PlaybackMixerCopy and
|
|
CaptureMixerCopy
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 12 ++++++++++++
|
|
1 file changed, 12 insertions(+)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index e1f58027..71fcc949 100644
|
|
--- a/include/use-case.h
|
|
+++ b/include/use-case.h
|
|
@@ -309,8 +309,14 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
|
* - PlaybackMixerElem
|
|
* - mixer element playback identifier
|
|
* - can be parsed using snd_use_case_parse_selem_id()
|
|
+ * - PlaybackMixerCopy
|
|
+ * - additional mixer element playback identifier
|
|
+ * - can be parsed using snd_use_case_parse_selem_id()
|
|
+ * - those elements should copy the volume and switch settings
|
|
+ * - element identifiers are separated using the | character
|
|
* - PlaybackMasterElem
|
|
* - mixer element playback identifier for the master control
|
|
+ * - can be parsed using snd_use_case_parse_selem_id()
|
|
* - PlaybackMasterType
|
|
* - type of the master volume control
|
|
* - Valid values: "soft" (software attenuation)
|
|
@@ -319,8 +325,14 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
|
* - CaptureMixerElem
|
|
* - mixer element capture identifier
|
|
* - can be parsed using snd_use_case_parse_selem_id()
|
|
+ * - CaptureMixerCopy
|
|
+ * - additional mixer element capture identifier
|
|
+ * - can be parsed using snd_use_case_parse_selem_id()
|
|
+ * - those elements should copy the volume and switch settings
|
|
+ * - element identifiers are separated using the | character
|
|
* - CaptureMasterElem
|
|
* - mixer element playback identifier for the master control
|
|
+ * - can be parsed using snd_use_case_parse_selem_id()
|
|
* - CaptureMasterType
|
|
* - type of the master volume control
|
|
* - Valid values: "soft" (software attenuation)
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From a0fc4447bb7c7f9a850a0a85f3a5a32c1509caf4 Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
Date: Tue, 3 Dec 2019 15:01:04 +0100
|
|
Subject: [PATCH 08/69] ucm: docs - add JackCTL, rearrange JackControl and
|
|
JackDev
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 22 ++++++++++++++--------
|
|
1 file changed, 14 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index 71fcc949..25998cb9 100644
|
|
--- a/include/use-case.h
|
|
+++ b/include/use-case.h
|
|
@@ -338,14 +338,20 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
|
|
* - Valid values: "soft" (software attenuation)
|
|
* - EDIDFile
|
|
* - Path to EDID file for HDMI devices
|
|
- * - JackControl, JackDev
|
|
- * - Jack information for a device. The jack status can be reported via
|
|
- * a kcontrol and/or via an input device. **JackControl** is the
|
|
- * kcontrol name of the jack, and **JackDev** is the input device id of
|
|
- * the jack (if the full input device path is /dev/input/by-id/foo, the
|
|
- * JackDev value should be "foo"). UCM configuration files should
|
|
- * contain both JackControl and JackDev when possible, because
|
|
- * applications are likely to support only one or the other.
|
|
+ * - JackCTL
|
|
+ * - jack control device name
|
|
+ * - JackControl
|
|
+ * - jack control identificator
|
|
+ * - can be parsed using snd_use_case_parse_ctl_elem_id()
|
|
+ * - UCM configuration files should contain both JackControl and JackDev
|
|
+ * when possible, because applications are likely to support only one
|
|
+ * or the other
|
|
+ * - JackDev
|
|
+ * - the input device id of the jack (if the full input device path is
|
|
+ * /dev/input/by-id/foo, the JackDev value should be "foo")
|
|
+ * - UCM configuration files should contain both JackControl and JackDev
|
|
+ * when possible, because applications are likely to support only one
|
|
+ * or the other
|
|
* - JackHWMute
|
|
* If this value is set, it indicates that when the jack is plugged
|
|
* in, the hardware automatically mutes some other device(s). The
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From e59034a0bec257cc7422a1e9436d936be8696a6f Mon Sep 17 00:00:00 2001
|
|
From: Hans de Goede <hdegoede@redhat.com>
|
|
Date: Tue, 3 Dec 2019 18:27:39 +0100
|
|
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
|
|
moved over to UCM2, parsing them fails with:
|
|
|
|
ALSA lib ucm_subs.c:220:(uc_mgr_get_substituted_value) variable '${CardComponents}' is not defined in this context!
|
|
|
|
This completely breaks audio support on all Bay- and Cherry-Trail devices.
|
|
|
|
This is caused by these non-SOF ASoC using cards having an empty
|
|
CardComponents list. Which in itself is fine, but is rejected by
|
|
the ucm_subs.c code. This commit changes the ucm_subs code to accept
|
|
an empty string as a valid value for CardComponents restoring audio
|
|
functionality on these boards.
|
|
|
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/ucm/ucm_subs.c | 20 ++++++++++++--------
|
|
1 file changed, 12 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
|
|
index 00afa9e3..90e395f0 100644
|
|
--- a/src/ucm/ucm_subs.c
|
|
+++ b/src/ucm/ucm_subs.c
|
|
@@ -25,6 +25,7 @@
|
|
*/
|
|
|
|
#include "ucm_local.h"
|
|
+#include <stdbool.h>
|
|
#include <sys/stat.h>
|
|
#include <limits.h>
|
|
|
|
@@ -145,10 +146,11 @@ static char *rval_sysfs(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char
|
|
return strdup(path);
|
|
}
|
|
|
|
-#define MATCH_VARIABLE(name, id, fcn) \
|
|
+#define MATCH_VARIABLE(name, id, fcn, empty_ok) \
|
|
if (strncmp((name), (id), sizeof(id) - 1) == 0) { \
|
|
rval = fcn(uc_mgr); \
|
|
idsize = sizeof(id) - 1; \
|
|
+ allow_empty = (empty_ok); \
|
|
goto __rval; \
|
|
}
|
|
|
|
@@ -189,12 +191,14 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr,
|
|
|
|
while (*value) {
|
|
if (*value == '$' && *(value+1) == '{') {
|
|
- MATCH_VARIABLE(value, "${ConfName}", rval_conf_name);
|
|
- MATCH_VARIABLE(value, "${CardId}", rval_card_id);
|
|
- MATCH_VARIABLE(value, "${CardDriver}", rval_card_driver);
|
|
- MATCH_VARIABLE(value, "${CardName}", rval_card_name);
|
|
- MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname);
|
|
- MATCH_VARIABLE(value, "${CardComponents}", rval_card_components);
|
|
+ bool allow_empty = false;
|
|
+
|
|
+ MATCH_VARIABLE(value, "${ConfName}", rval_conf_name, false);
|
|
+ MATCH_VARIABLE(value, "${CardId}", rval_card_id, false);
|
|
+ MATCH_VARIABLE(value, "${CardDriver}", rval_card_driver, false);
|
|
+ MATCH_VARIABLE(value, "${CardName}", rval_card_name, false);
|
|
+ MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname, false);
|
|
+ MATCH_VARIABLE(value, "${CardComponents}", rval_card_components, true);
|
|
MATCH_VARIABLE2(value, "${env:", rval_env);
|
|
MATCH_VARIABLE2(value, "${sys:", rval_sysfs);
|
|
err = -EINVAL;
|
|
@@ -208,7 +212,7 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr,
|
|
}
|
|
goto __error;
|
|
__rval:
|
|
- if (rval == NULL || rval[0] == '\0') {
|
|
+ if (rval == NULL || (!allow_empty && rval[0] == '\0')) {
|
|
free(rval);
|
|
strncpy(r, value, idsize);
|
|
r[idsize] = '\0';
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From 8e2c70add782f997f7c269ed3f722888e56ff024 Mon Sep 17 00:00:00 2001
|
|
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
|
Date: Tue, 3 Dec 2019 18:56:40 +0100
|
|
Subject: [PATCH 10/69] src/ucm/main.c: fix build without mixer
|
|
|
|
Commit 4ce38a5ff466d18039b2606938f866ea3a6c9f3c breaks the build without
|
|
mixer on:
|
|
|
|
CCLD libasound.la
|
|
/home/buildroot/autobuild/instance-1/output-1/host/lib/gcc/xtensa-buildroot-linux-uclibc/8.3.0/../../../../xtensa-buildroot-linux-uclibc/bin/ld: ucm/.libs/libucm.a(main.o): in function `snd_use_case_set':
|
|
main.c:(.text+0x185c): undefined reference to `snd_mixer_selem_id_parse'
|
|
|
|
Fixes: http://autobuild.buildroot.org/results/4d91c9f82a2a61c50c457a851073b85cc09ea345
|
|
|
|
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/ucm/main.c | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/src/ucm/main.c b/src/ucm/main.c
|
|
index d2078a23..61922f10 100644
|
|
--- a/src/ucm/main.c
|
|
+++ b/src/ucm/main.c
|
|
@@ -2115,8 +2115,10 @@ int snd_use_case_parse_selem_id(snd_mixer_selem_id_t *dst,
|
|
const char *ucm_id,
|
|
const char *value)
|
|
{
|
|
+#ifdef BUILD_MIXER
|
|
if (strcmp(ucm_id, "PlaybackMixerId") == 0 ||
|
|
strcmp(ucm_id, "CaptureMixerId") == 0)
|
|
return snd_mixer_selem_id_parse(dst, value);
|
|
+#endif
|
|
return -EINVAL;
|
|
}
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From ad8527d81b09c4d0edd054b5b1468ce1c50b23cb Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 8 ++++++++
|
|
1 file changed, 8 insertions(+)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 3 +--
|
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
include/use-case.h | 18 ++++++------------
|
|
1 file changed, 6 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/include/use-case.h b/include/use-case.h
|
|
index 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 <libin.yang@linux.intel.com>
|
|
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 <libin.yang@linux.intel.com>
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/ucm/parser.c | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
src/topology/tplg_local.h | 5 -----
|
|
1 file changed, 5 deletions(-)
|
|
|
|
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
src/topology/builder.c | 121 ++++++++++++++++++--------------------
|
|
src/topology/tplg_local.h | 3 +-
|
|
2 files changed, 60 insertions(+), 64 deletions(-)
|
|
|
|
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
src/topology/builder.c | 146 +++++++++++++++++++----------------------
|
|
1 file changed, 67 insertions(+), 79 deletions(-)
|
|
|
|
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
src/topology/builder.c | 10 +++++-----
|
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
src/topology/builder.c | 95 +++++++++++++++---------------------------
|
|
1 file changed, 33 insertions(+), 62 deletions(-)
|
|
|
|
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
|
index 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 <perex@perex.cz>
|
|
Date: Fri, 13 Dec 2019 18:53:41 +0100
|
|
Subject: [PATCH 24/69] topology: make vebose output more nice
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/topology/builder.c | 18 ++++++++++--------
|
|
1 file changed, 10 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/topology/builder.c b/src/topology/builder.c
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
src/topology/elem.c | 8 +++-----
|
|
1 file changed, 3 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/src/topology/elem.c b/src/topology/elem.c
|
|
index 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 <perex@perex.cz>
|
|
Date: Fri, 13 Dec 2019 21:52:13 +0100
|
|
Subject: [PATCH 26/69] topology: dapm - coding fixes
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/topology/dapm.c | 15 +++++++--------
|
|
1 file changed, 7 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
|
|
index 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
src/topology/dapm.c | 14 +++++++-------
|
|
src/topology/elem.c | 2 +-
|
|
src/topology/tplg_local.h | 1 +
|
|
3 files changed, 9 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
|
|
index 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 <perex@perex.cz>
|
|
Date: Fri, 13 Dec 2019 22:07:46 +0100
|
|
Subject: [PATCH 28/69] topology: more coding fixes
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
src/topology/channel.c | 4 ++--
|
|
src/topology/ctl.c | 15 ++++++++-------
|
|
src/topology/elem.c | 6 ++++--
|
|
src/topology/ops.c | 6 +++---
|
|
src/topology/pcm.c | 20 ++++++++++++--------
|
|
src/topology/text.c | 2 +-
|
|
6 files changed, 30 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/src/topology/channel.c b/src/topology/channel.c
|
|
index 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 <tiwai@suse.de>
|
|
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 <linux/types.h> 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 <tiwai@suse.de>
|
|
---
|
|
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 <fvdpol@coil.demon.nl>
|
|
- * (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
|
|
- *
|
|
- *
|
|
- * 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 <sound/asound.h>
|
|
-
|
|
-/** 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 <alsa/sound/uapi/asequencer.h>
|
|
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 <linux/types.h>
|
|
-#include <sound/asound.h>
|
|
-
|
|
-/*
|
|
- * Maximum number of channels topology kcontrol can represent.
|
|
- */
|
|
-#define SND_SOC_TPLG_MAX_CHAN 8
|
|
-
|
|
-/*
|
|
- * Maximum number of PCM formats capability
|
|
- */
|
|
-#define SND_SOC_TPLG_MAX_FORMATS 16
|
|
-
|
|
-/*
|
|
- * Maximum number of PCM stream configs
|
|
- */
|
|
-#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8
|
|
-
|
|
-/*
|
|
- * 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 <alsa/sound/uapi/asoc.h>
|
|
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 <perex@perex.cz>,
|
|
- * Abramo Bagnara <abramo@alsa-project.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., 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 <linux/types.h>
|
|
-#else
|
|
-#include <sys/ioctl.h>
|
|
-#endif
|
|
-
|
|
-#ifndef __KERNEL__
|
|
-#include <stdlib.h>
|
|
-#include <time.h>
|
|
-#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 <alsa/sound/uapi/asound.h>
|
|
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 <perex@perex.cz>,
|
|
- * 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 <alsa/sound/uapi/asound_fm.h>
|
|
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 <perex@perex.cz>,
|
|
- * 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 <linux/types.h>
|
|
-#include <sound/asound.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
|
|
-
|
|
-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 <alsa/sound/type_compat.h>
|
|
+#include <alsa/sound/uapi/emu10k1.h>
|
|
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 <linux/types.h>
|
|
-
|
|
-#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 <alsa/sound/type_compat.h>
|
|
+#include <alsa/sound/uapi/hdsp.h>
|
|
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 <linux/types.h>
|
|
-
|
|
-/* 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 <alsa/sound/type_compat.h>
|
|
+#include <alsa/sound/uapi/hdspm.h>
|
|
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 <uros@kss-loka.si>
|
|
- * Takashi Iwai <tiwai@suse.de>
|
|
- *
|
|
- * 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 <alsa/sound/uapi/sb16_csp.h>
|
|
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 <alsa/sound/uapi/sscape_ioctl.h>
|
|
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: <min> <max> <TLV> */
|
|
-#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 <alsa/sound/uapi/tlv.h>
|
|
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 <stdint.h>
|
|
+#ifdef __linux__
|
|
+#include <linux/types.h>
|
|
+#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 <fvdpol@coil.demon.nl>
|
|
+ * (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
|
|
+ *
|
|
+ *
|
|
+ * 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 <sound/asound.h>
|
|
+
|
|
+/** 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 <linux/types.h>
|
|
+#include <sound/asound.h>
|
|
+
|
|
+/*
|
|
+ * Maximum number of channels topology kcontrol can represent.
|
|
+ */
|
|
+#define SND_SOC_TPLG_MAX_CHAN 8
|
|
+
|
|
+/*
|
|
+ * Maximum number of PCM formats capability
|
|
+ */
|
|
+#define SND_SOC_TPLG_MAX_FORMATS 16
|
|
+
|
|
+/*
|
|
+ * Maximum number of PCM stream configs
|
|
+ */
|
|
+#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8
|
|
+
|
|
+/*
|
|
+ * 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 <perex@perex.cz>,
|
|
+ * Abramo Bagnara <abramo@alsa-project.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., 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 <linux/types.h>
|
|
+#else
|
|
+#include <sys/ioctl.h>
|
|
+#endif
|
|
+
|
|
+#ifndef __KERNEL__
|
|
+#include <stdlib.h>
|
|
+#include <time.h>
|
|
+#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 <perex@perex.cz>,
|
|
+ * 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 <perex@perex.cz>,
|
|
+ * 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 <uros@kss-loka.si>
|
|
+ * Takashi Iwai <tiwai@suse.de>
|
|
+ *
|
|
+ * 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: <min> <max> <TLV> */
|
|
+#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 <sound/type_compat.h>
|
|
#include <sound/asound.h>
|
|
#include <sound/asoc.h>
|
|
#include <sound/tlv.h>
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From 75584fe660880b332fbf60dd7968e2ed8b49a38b Mon Sep 17 00:00:00 2001
|
|
From: Takashi Iwai <tiwai@suse.de>
|
|
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 <tiwai@suse.de>
|
|
---
|
|
include/sound/type_compat.h | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/include/sound/type_compat.h b/include/sound/type_compat.h
|
|
index 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 <endian.h>
|
|
#include <byteswap.h>
|
|
--
|
|
2.24.1
|
|
|
|
|
|
From 59792f467b38d6a4c4dffdb30528f7fb03d23d96 Mon Sep 17 00:00:00 2001
|
|
From: Takashi Iwai <tiwai@suse.de>
|
|
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 <tiwai@suse.de>
|
|
---
|
|
include/sound/emu10k1.h | 9 +++++++++
|
|
include/sound/hdsp.h | 10 ++++++++++
|
|
include/sound/hdspm.h | 8 ++++++++
|
|
include/sound/sb16_csp.h | 4 ++++
|
|
include/sound/uapi/emu10k1.h | 10 ----------
|
|
include/sound/uapi/hdsp.h | 9 ---------
|
|
include/sound/uapi/hdspm.h | 8 --------
|
|
7 files changed, 31 insertions(+), 27 deletions(-)
|
|
|
|
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
|
|
index f06ecee5..0832f95b 100644
|
|
--- a/include/sound/emu10k1.h
|
|
+++ b/include/sound/emu10k1.h
|
|
@@ -1,2 +1,11 @@
|
|
#include <alsa/sound/type_compat.h>
|
|
#include <alsa/sound/uapi/emu10k1.h>
|
|
+#ifndef __emu10k1_type_defined
|
|
+#define __emu10k1_type_defined
|
|
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
|
|
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
|
|
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
|
|
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
|
|
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
|
|
+typedef struct emu10k1_ctl_elem_id emu10k1_ctl_elem_id_t;
|
|
+#endif
|
|
diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h
|
|
index 78fb745b..e8f93156 100644
|
|
--- a/include/sound/hdsp.h
|
|
+++ b/include/sound/hdsp.h
|
|
@@ -1,2 +1,12 @@
|
|
#include <alsa/sound/type_compat.h>
|
|
#include <alsa/sound/uapi/hdsp.h>
|
|
+#ifndef __hdsp_type_defined
|
|
+#define __hdsp_type_defined
|
|
+typedef enum HDSP_IO_Type HDSP_IO_Type;
|
|
+typedef struct hdsp_peak_rms hdsp_peak_rms_t;
|
|
+typedef struct hdsp_config_info hdsp_config_info_t;
|
|
+typedef struct hdsp_firmware hdsp_firmware_t;
|
|
+typedef struct hdsp_version hdsp_version_t;
|
|
+typedef struct hdsp_mixer hdsp_mixer_t;
|
|
+typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
|
|
+#endif
|
|
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
|
|
index af6d19ed..d9095d9f 100644
|
|
--- a/include/sound/hdspm.h
|
|
+++ b/include/sound/hdspm.h
|
|
@@ -1,2 +1,10 @@
|
|
#include <alsa/sound/type_compat.h>
|
|
#include <alsa/sound/uapi/hdspm.h>
|
|
+#ifndef __hdspm_type_defined
|
|
+#define __hdspm_type_defined
|
|
+typedef struct hdspm_peak_rms hdspm_peak_rms_t;
|
|
+typedef struct hdspm_config_info hdspm_config_info_t;
|
|
+typedef struct hdspm_version hdspm_version_t;
|
|
+typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
|
|
+typedef struct hdspm_mixer hdspm_mixer_t;
|
|
+#endif
|
|
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
|
|
index 24121fcb..fd02bc56 100644
|
|
--- a/include/sound/sb16_csp.h
|
|
+++ b/include/sound/sb16_csp.h
|
|
@@ -1 +1,5 @@
|
|
#include <alsa/sound/uapi/sb16_csp.h>
|
|
+#ifndef __sb16_csp_type_defined
|
|
+#define __sb16_csp_type_defined
|
|
+typedef struct snd_sb_csp_microcode snd_sb_csp_microcode_t;
|
|
+#endif
|
|
diff --git a/include/sound/uapi/emu10k1.h b/include/sound/uapi/emu10k1.h
|
|
index 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 <david.ward@ll.mit.edu>
|
|
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ò <flameeyes@gmail.com>
|
|
Signed-off-by: David Ward <david.ward@ll.mit.edu>
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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ò <flameeyes@gmail.com>
|
|
-dnl Copyright (c) 2006-2007 xine project
|
|
+dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
|
|
+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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Sat, 14 Dec 2019 14:05:49 +0100
|
|
Subject: [PATCH 36/69] topology: add tplg_get_unsigned() function
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Sat, 14 Dec 2019 20:32:24 +0100
|
|
Subject: [PATCH 39/69] topology: parser - recode tplg_parse_config()
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Mon, 16 Dec 2019 14:26:31 +0100
|
|
Subject: [PATCH 43/69] topology: add snd_tplg_save()
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <ctype.h>
|
|
|
|
+#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 <perex@perex.cz>
|
|
+*/
|
|
+
|
|
+#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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Fri, 20 Dec 2019 21:28:30 +0100
|
|
Subject: [PATCH 45/69] topology: add snd_tplg_version() function
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Fri, 27 Dec 2019 19:32:03 +0100
|
|
Subject: [PATCH 47/69] topology: dapm - fix the SNDERR() - Undefined
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Sat, 28 Dec 2019 10:18:34 +0100
|
|
Subject: [PATCH 48/69] topology: fix the unitialized tuples
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <ctype.h>
|
|
|
|
#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 <perex@perex.cz>
|
|
Date: Sun, 29 Dec 2019 20:05:14 +0100
|
|
Subject: [PATCH 50/69] topology: fix the TPLG_DEBUG compilation
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Sun, 15 Dec 2019 15:24:57 +0100
|
|
Subject: [PATCH 53/69] topology: implement snd_tplg_decode
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
+*/
|
|
+
|
|
+#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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Fri, 3 Jan 2020 22:31:27 +0100
|
|
Subject: [PATCH 55/69] topology: unify the log mechanism
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
+*/
|
|
+
|
|
+#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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
Date: Fri, 3 Jan 2020 22:56:48 +0100
|
|
Subject: [PATCH 57/69] topology: cosmetic changes (functions)
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <David@Fries.net>
|
|
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 <David@Fries.net>
|
|
Reviewed-by: Takashi Iwai <tiwai@suse.de>
|
|
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
---
|
|
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 <bert.marcelis@outlook.com>
|
|
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 <bert.marcelis@outlook.com>
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <tanuk@iki.fi>
|
|
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 <tanuk@iki.fi>
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
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 <alsa/seq.h>" >> include/asoundlib.h
|
|
test "$build_seq" = "yes" && echo "#include <alsa/seqmid.h>" >> include/asoundlib.h
|
|
test "$build_seq" = "yes" && echo "#include <alsa/seq_midi_event.h>" >> 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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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 <perex@perex.cz>
|
|
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 <perex@perex.cz>
|
|
---
|
|
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
|
|
|