[alsa-devel] [PATCH 0/4] topology: Support using "index" to group objects when generating binary for kernel
From: Fuwei Tang fuweix.tang@intel.com
The index value of an topology object can be used to group objects for different use cases. And so the audio kernel driver can ask topology core to load all objects of the specified index value(use case). The function is already supported in kernel. So in the user space, for topology objects of the same type but with different index values, they should be written into different blocks in the binary for kernel. The index value is stored in the block header.
Fuwei Tang (4): topology: Insert new element based on its index value topology: Remove code parsing index value in paring each object topology: Look up references for an object based on its index topology: Group elements with the same index value into a block
include/topology.h | 10 +++-- src/topology/builder.c | 94 +++++++++++++++++++++++++---------------------- src/topology/ctl.c | 31 +--------------- src/topology/dapm.c | 27 +++++--------- src/topology/data.c | 15 ++------ src/topology/elem.c | 74 +++++++++++++++++++++++++++---------- src/topology/pcm.c | 58 ++++++----------------------- src/topology/tplg_local.h | 3 +- 8 files changed, 141 insertions(+), 171 deletions(-)
From: Fuwei Tang fuweix.tang@intel.com
When creating a new element, insert it into the list in the ascending order of index value.
Signed-off-by: Fuwei Tang fuweix.tang@intel.com Reviewed-by: Mengdong Lin mengdong.lin@linux.intel.com --- src/topology/elem.c | 67 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 18 deletions(-)
diff --git a/src/topology/elem.c b/src/topology/elem.c index efcf3e9..3ed655a 100644 --- a/src/topology/elem.c +++ b/src/topology/elem.c @@ -126,14 +126,33 @@ 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*/ +static 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; + + list_for_each(pos, list) { + elem = list_entry(pos, struct tplg_elem, list); + if (elem_p->index < elem->index) + break; + } + p->prev = pos->prev; + pos->prev->next = p; + pos->prev = p; + p->next = pos; +} + /* 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) { struct tplg_elem *elem; - const char *id; + const char *id, *val = NULL; int obj_size = 0; void *obj; + snd_config_iterator_t i, next; + snd_config_t *n;
if (!cfg && !name) return NULL; @@ -147,75 +166,87 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, snd_config_get_id(cfg, &id); elem_copy_text(elem->id, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); elem->id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1] = 0; + /* as we insert new elem based on the index value, move index + parsing here */ + snd_config_for_each(i, next, cfg) { + n = snd_config_iterator_entry(i); + if (snd_config_get_id(n, &id)) + continue; + if (strcmp(id, "index") == 0) { + if (snd_config_get_string(n, &val) < 0) + return NULL; + elem->index = atoi(val); + } + } } else if (name != NULL) elem_copy_text(elem->id, name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
switch (type) { case SND_TPLG_TYPE_DATA: - list_add_tail(&elem->list, &tplg->pdata_list); + tplg_elem_insert(elem, &tplg->pdata_list); break; case SND_TPLG_TYPE_MANIFEST: - list_add_tail(&elem->list, &tplg->manifest_list); + tplg_elem_insert(elem, &tplg->manifest_list); obj_size = sizeof(struct snd_soc_tplg_manifest); break; case SND_TPLG_TYPE_TEXT: - list_add_tail(&elem->list, &tplg->text_list); + tplg_elem_insert(elem, &tplg->text_list); obj_size = sizeof(struct tplg_texts); break; case SND_TPLG_TYPE_TLV: - list_add_tail(&elem->list, &tplg->tlv_list); + tplg_elem_insert(elem, &tplg->tlv_list); elem->size = sizeof(struct snd_soc_tplg_ctl_tlv); break; case SND_TPLG_TYPE_BYTES: - list_add_tail(&elem->list, &tplg->bytes_ext_list); + tplg_elem_insert(elem, &tplg->bytes_ext_list); obj_size = sizeof(struct snd_soc_tplg_bytes_control); break; case SND_TPLG_TYPE_ENUM: - list_add_tail(&elem->list, &tplg->enum_list); + tplg_elem_insert(elem, &tplg->enum_list); obj_size = sizeof(struct snd_soc_tplg_enum_control); break; case SND_TPLG_TYPE_MIXER: - list_add_tail(&elem->list, &tplg->mixer_list); + tplg_elem_insert(elem, &tplg->mixer_list); obj_size = sizeof(struct snd_soc_tplg_mixer_control); break; case SND_TPLG_TYPE_DAPM_WIDGET: - list_add_tail(&elem->list, &tplg->widget_list); + tplg_elem_insert(elem, &tplg->widget_list); obj_size = sizeof(struct snd_soc_tplg_dapm_widget); break; case SND_TPLG_TYPE_STREAM_CONFIG: - list_add_tail(&elem->list, &tplg->pcm_config_list); + tplg_elem_insert(elem, &tplg->pcm_config_list); obj_size = sizeof(struct snd_soc_tplg_stream); break; case SND_TPLG_TYPE_STREAM_CAPS: - list_add_tail(&elem->list, &tplg->pcm_caps_list); + tplg_elem_insert(elem, &tplg->pcm_caps_list); obj_size = sizeof(struct snd_soc_tplg_stream_caps); break; case SND_TPLG_TYPE_PCM: - list_add_tail(&elem->list, &tplg->pcm_list); + tplg_elem_insert(elem, &tplg->pcm_list); obj_size = sizeof(struct snd_soc_tplg_pcm); break; case SND_TPLG_TYPE_DAI: - list_add_tail(&elem->list, &tplg->dai_list); + 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: - list_add_tail(&elem->list, &tplg->be_list); + tplg_elem_insert(elem, &tplg->be_list); obj_size = sizeof(struct snd_soc_tplg_link_config); break; case SND_TPLG_TYPE_CC: - list_add_tail(&elem->list, &tplg->cc_list); + tplg_elem_insert(elem, &tplg->cc_list); obj_size = sizeof(struct snd_soc_tplg_link_config); break; case SND_TPLG_TYPE_TOKEN: - list_add_tail(&elem->list, &tplg->token_list); + tplg_elem_insert(elem, &tplg->token_list); break; case SND_TPLG_TYPE_TUPLE: - list_add_tail(&elem->list, &tplg->tuple_list); + tplg_elem_insert(elem, &tplg->tuple_list); elem->free = tplg_free_tuples; break; case SND_TPLG_TYPE_HW_CONFIG: - list_add_tail(&elem->list, &tplg->hw_cfg_list); + tplg_elem_insert(elem, &tplg->hw_cfg_list); obj_size = sizeof(struct snd_soc_tplg_hw_config); break; default:
From: Fuwei Tang fuweix.tang@intel.com
We insert a new element into the object list based on its index value, so we parse index value in "tplg_elem_new_common" before insert it, and then remove code parsing index value in parsing each object.
Signed-off-by: Fuwei Tang fuweix.tang@intel.com Reviewed-by: Mengdong Lin mengdong.lin@linux.intel.com --- src/topology/ctl.c | 27 --------------------------- src/topology/dapm.c | 9 --------- src/topology/data.c | 9 --------- src/topology/pcm.c | 36 ------------------------------------ 4 files changed, 81 deletions(-)
diff --git a/src/topology/ctl.c b/src/topology/ctl.c index 1da3d18..1b160a2 100644 --- a/src/topology/ctl.c +++ b/src/topology/ctl.c @@ -397,15 +397,6 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg, if (id[0] == '#') continue;
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "base") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL; @@ -538,15 +529,6 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, if (id[0] == '#') continue;
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "texts") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL; @@ -648,15 +630,6 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg, if (id[0] == '#') continue;
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "channel") == 0) { if (mc->num_channels >= SND_SOC_TPLG_MAX_CHAN) { SNDERR("error: too many channels %s\n", diff --git a/src/topology/dapm.c b/src/topology/dapm.c index eef72bb..ba5d9fe 100644 --- a/src/topology/dapm.c +++ b/src/topology/dapm.c @@ -483,15 +483,6 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, if (id[0] == '#') continue;
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "type") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL; diff --git a/src/topology/data.c b/src/topology/data.c index e2aa38c..7b92cea 100644 --- a/src/topology/data.c +++ b/src/topology/data.c @@ -1009,15 +1009,6 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, continue; }
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "type") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL; diff --git a/src/topology/pcm.c b/src/topology/pcm.c index 5568d57..ed50c9c 100644 --- a/src/topology/pcm.c +++ b/src/topology/pcm.c @@ -554,15 +554,6 @@ int tplg_parse_pcm(snd_tplg_t *tplg, if (id[0] == '#') continue;
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "id") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL; @@ -654,15 +645,6 @@ int tplg_parse_dai(snd_tplg_t *tplg, if (id[0] == '#') continue;
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "id") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL; @@ -804,15 +786,6 @@ int tplg_parse_link(snd_tplg_t *tplg, if (id[0] == '#') continue;
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "id") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL; @@ -918,15 +891,6 @@ int tplg_parse_cc(snd_tplg_t *tplg, if (id[0] == '#') continue;
- if (strcmp(id, "index") == 0) { - if (snd_config_get_string(n, &val) < 0) - return -EINVAL; - - elem->index = atoi(val); - tplg_dbg("\t%s: %d\n", id, elem->index); - continue; - } - if (strcmp(id, "id") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL;
From: Fuwei Tang fuweix.tang@intel.com
We can distinguish different use cases by the object index value, the default value is 0, meaning applicable for all use cases, defined by macro "SND_TOLG_INDEX_ALL". An element can only refer to other elements for "all" use cases or the same use cases, i.e. it can only refer to elements with index value "SND_TOLG_INDEX_ALL" or the same index value as itself. The object list has been sorted in ascending order of index, so when we look up a reference for an object, we traverse the object list it depends on, if we have not found the reference until index of the object list is greater than index of the object, we give up and return an error.
Signed-off-by: Fuwei Tang fuweix.tang@intel.com Reviewed-by: Mengdong Lin mengdong.lin@linux.intel.com --- include/topology.h | 10 +++++++--- src/topology/ctl.c | 4 ++-- src/topology/dapm.c | 18 +++++++++--------- src/topology/data.c | 6 +++--- src/topology/elem.c | 7 ++++++- src/topology/pcm.c | 22 ++++++++++++---------- src/topology/tplg_local.h | 3 ++- 7 files changed, 41 insertions(+), 29 deletions(-)
diff --git a/include/topology.h b/include/topology.h index 593eaa6..1bebe1e 100644 --- a/include/topology.h +++ b/include/topology.h @@ -356,9 +356,10 @@ extern "C" { * </pre> * * The section name is used to define the mixer name. The index number can be - * used to identify topology objects groups. This allows driver operations on - * objects with index number N and can be used to add/remove pipelines of - * objects whilst other objects are unaffected. + * used to identify topology objects groups(index "0" is common, fit for all + * user cases).This allows driver operations on objects with index number N and + * can be used to add/remove pipelines of objects whilst other objects are + * unaffected. * * <h5>Byte Controls</h5> * A byte control is defined as a new section that can include channel mapping, @@ -752,6 +753,9 @@ enum snd_tplg_type { SND_TPLG_TYPE_DAI, /*!< Physical DAI */ };
+/** Fit for all user cases */ +#define SND_TPLG_INDEX_ALL 0 + /** * \brief Create a new topology parser instance. * \return New topology parser instance diff --git a/src/topology/ctl.c b/src/topology/ctl.c index 1b160a2..f09fb68 100644 --- a/src/topology/ctl.c +++ b/src/topology/ctl.c @@ -135,7 +135,7 @@ static int tplg_build_mixer_control(snd_tplg_t *tplg,
if (ref->type == SND_TPLG_TYPE_TLV) { ref->elem = tplg_elem_lookup(&tplg->tlv_list, - ref->id, SND_TPLG_TYPE_TLV); + ref->id, SND_TPLG_TYPE_TLV, elem->index); if (ref->elem) err = copy_tlv(elem, ref->elem);
@@ -185,7 +185,7 @@ static int tplg_build_enum_control(snd_tplg_t *tplg,
if (ref->type == SND_TPLG_TYPE_TEXT) { ref->elem = tplg_elem_lookup(&tplg->text_list, - ref->id, SND_TPLG_TYPE_TEXT); + ref->id, SND_TPLG_TYPE_TEXT, elem->index); if (ref->elem) copy_enum_texts(elem, ref->elem);
diff --git a/src/topology/dapm.c b/src/topology/dapm.c index ba5d9fe..13aa1c4 100644 --- a/src/topology/dapm.c +++ b/src/topology/dapm.c @@ -176,7 +176,7 @@ static int tplg_build_widget(snd_tplg_t *tplg, case SND_TPLG_TYPE_MIXER: if (!ref->elem) ref->elem = tplg_elem_lookup(&tplg->mixer_list, - ref->id, SND_TPLG_TYPE_MIXER); + ref->id, SND_TPLG_TYPE_MIXER, elem->index); if (ref->elem) err = copy_dapm_control(elem, ref->elem); break; @@ -184,7 +184,7 @@ static int tplg_build_widget(snd_tplg_t *tplg, case SND_TPLG_TYPE_ENUM: if (!ref->elem) ref->elem = tplg_elem_lookup(&tplg->enum_list, - ref->id, SND_TPLG_TYPE_ENUM); + ref->id, SND_TPLG_TYPE_ENUM, elem->index); if (ref->elem) err = copy_dapm_control(elem, ref->elem); break; @@ -192,7 +192,7 @@ static int tplg_build_widget(snd_tplg_t *tplg, case SND_TPLG_TYPE_BYTES: if (!ref->elem) ref->elem = tplg_elem_lookup(&tplg->bytes_ext_list, - ref->id, SND_TPLG_TYPE_BYTES); + ref->id, SND_TPLG_TYPE_BYTES, elem->index); if (ref->elem) err = copy_dapm_control(elem, ref->elem); break; @@ -271,17 +271,17 @@ int tplg_build_routes(snd_tplg_t *tplg)
} if (!tplg_elem_lookup(&tplg->widget_list, route->sink, - SND_TPLG_TYPE_DAPM_WIDGET)) { + SND_TPLG_TYPE_DAPM_WIDGET, elem->index)) { SNDERR("warning: undefined sink widget/stream '%s'\n", route->sink); }
/* validate control name */ if (strlen(route->control)) { - if (!tplg_elem_lookup(&tplg->mixer_list, - route->control, SND_TPLG_TYPE_MIXER) && - !tplg_elem_lookup(&tplg->enum_list, - route->control, SND_TPLG_TYPE_ENUM)) { + if (!tplg_elem_lookup(&tplg->mixer_list, route->control, + 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); } @@ -294,7 +294,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_TYPE_DAPM_WIDGET, elem->index)) { SNDERR("warning: Undefined source widget/stream '%s'\n", route->source); } diff --git a/src/topology/data.c b/src/topology/data.c index 7b92cea..61882b8 100644 --- a/src/topology/data.c +++ b/src/topology/data.c @@ -366,7 +366,7 @@ static struct tplg_elem *get_tokens(snd_tplg_t *tplg, struct tplg_elem *elem)
if (!ref->elem) { ref->elem = tplg_elem_lookup(&tplg->token_list, - ref->id, SND_TPLG_TYPE_TOKEN); + ref->id, SND_TPLG_TYPE_TOKEN, elem->index); }
return ref->elem; @@ -508,7 +508,7 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)
if (!ref->elem) ref->elem = tplg_elem_lookup(&tplg->tuple_list, - ref->id, SND_TPLG_TYPE_TUPLE); + ref->id, SND_TPLG_TYPE_TUPLE, elem->index); tuples = ref->elem; if (!tuples) return -EINVAL; @@ -1036,7 +1036,7 @@ int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem, void *obj;
ref_elem = tplg_elem_lookup(&tplg->pdata_list, - ref->id, SND_TPLG_TYPE_DATA); + 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); diff --git a/src/topology/elem.c b/src/topology/elem.c index 3ed655a..89a4ac9 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) + unsigned int type, int index) { struct list_head *pos; struct tplg_elem *elem; @@ -121,6 +121,11 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
if (!strcmp(elem->id, id) && elem->type == type) return elem; + /* SND_TPLG_INDEX_ALL is the default value "0" and applicable + for all use cases */ + if ((elem->index != SND_TPLG_INDEX_ALL) + && (elem->index > index)) + break; }
return NULL; diff --git a/src/topology/pcm.c b/src/topology/pcm.c index ed50c9c..788cc8c 100644 --- a/src/topology/pcm.c +++ b/src/topology/pcm.c @@ -55,14 +55,14 @@ static void copy_stream_caps(const char *id,
/* find and copy the referenced stream caps */ static int tplg_build_stream_caps(snd_tplg_t *tplg, - const char *id, struct snd_soc_tplg_stream_caps *caps) + const char *id, int index, struct snd_soc_tplg_stream_caps *caps) { struct tplg_elem *ref_elem = NULL; unsigned int i;
for (i = 0; i < 2; i++) { ref_elem = tplg_elem_lookup(&tplg->pcm_caps_list, - caps[i].name, SND_TPLG_TYPE_STREAM_CAPS); + caps[i].name, SND_TPLG_TYPE_STREAM_CAPS, index);
if (ref_elem != NULL) copy_stream_caps(id, &caps[i], ref_elem); @@ -78,9 +78,10 @@ static int build_pcm(snd_tplg_t *tplg, struct tplg_elem *elem) struct list_head *base, *pos; int err;
- err = tplg_build_stream_caps(tplg, elem->id, elem->pcm->caps); - if (err < 0) - return err; + err = tplg_build_stream_caps(tplg, elem->id, elem->index, + elem->pcm->caps); + if (err < 0) + return err;
/* merge private data from the referenced data elements */ base = &elem->ref_list; @@ -138,7 +139,8 @@ static int tplg_build_dai(snd_tplg_t *tplg, struct tplg_elem *elem) int err = 0;
/* get playback & capture stream caps */ - err = tplg_build_stream_caps(tplg, elem->id, elem->dai->caps); + err = tplg_build_stream_caps(tplg, elem->id, elem->index, + elem->dai->caps); if (err < 0) return err;
@@ -186,7 +188,7 @@ 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) + struct snd_soc_tplg_stream *stream, int num_streams, int index) { struct snd_soc_tplg_stream *strm; struct tplg_elem *ref_elem; @@ -195,7 +197,7 @@ static int tplg_build_stream_cfg(snd_tplg_t *tplg, for (i = 0; i < num_streams; i++) { strm = stream + i; ref_elem = tplg_elem_lookup(&tplg->pcm_config_list, - strm->name, SND_TPLG_TYPE_STREAM_CONFIG); + strm->name, SND_TPLG_TYPE_STREAM_CONFIG, index);
if (ref_elem && ref_elem->stream_cfg) *strm = *ref_elem->stream_cfg; @@ -212,7 +214,7 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem) int num_hw_configs = 0, err = 0;
err = tplg_build_stream_cfg(tplg, link->stream, - link->num_streams); + link->num_streams, elem->index); if (err < 0) return err;
@@ -225,7 +227,7 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem) switch (ref->type) { case SND_TPLG_TYPE_HW_CONFIG: ref->elem = tplg_elem_lookup(&tplg->hw_cfg_list, - ref->id, SND_TPLG_TYPE_HW_CONFIG); + ref->id, SND_TPLG_TYPE_HW_CONFIG, elem->index); if (!ref->elem) { SNDERR("error: cannot find HW config '%s'" " referenced by link '%s'\n", diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h index eb2f7bd..eb7eac5 100644 --- a/src/topology/tplg_local.h +++ b/src/topology/tplg_local.h @@ -259,7 +259,8 @@ void tplg_elem_free(struct tplg_elem *elem); 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); + unsigned int type, + int index); struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, snd_config_t *cfg, const char *name, enum snd_tplg_type type);
From: Fuwei Tang fuweix.tang@intel.com
Topology objects(widgets,controls) with different index value should be grouped into different blocks and the block headers contain the index value.
Signed-off-by: Fuwei Tang fuweix.tang@intel.com Reviewed-by: Mengdong Lin mengdong.lin@linux.intel.com --- src/topology/builder.c | 94 +++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 43 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c index dcd9e2a..ca5cbe1 100644 --- a/src/topology/builder.c +++ b/src/topology/builder.c @@ -86,58 +86,66 @@ static int write_block_header(snd_tplg_t *tplg, unsigned int type, static int write_elem_block(snd_tplg_t *tplg, struct list_head *base, int size, int tplg_type, const char *obj_name) { - struct list_head *pos; - struct tplg_elem *elem; - int ret, wsize = 0, count = 0, vendor_type; + 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;
- /* count number of elements */ - list_for_each(pos, base) - count++; - if (!count) - return 0; - - /* write the header for this block */ - elem = list_entry(base->next, struct tplg_elem, list); - vendor_type = elem->vendor_type; - - ret = write_block_header(tplg, tplg_type, vendor_type, - tplg->version, 0, size, count); - if (ret < 0) { - SNDERR("error: failed to write %s block %d\n", - obj_name, ret); - return ret; - } - - /* write each elem to block */ + sub_base = base; list_for_each(pos, base) { - + /* find elems with the same index to make a block */ elem = list_entry(pos, struct tplg_elem, list); + elem_next = list_entry(pos->next, struct tplg_elem, list); + block_size += elem->size; + count++;
- /* compound elems have already been copied to other elems */ - if (elem->compound_elem) - continue; - - if (elem->type != SND_TPLG_TYPE_DAPM_GRAPH) - verbose(tplg, " %s '%s': write %d bytes\n", - obj_name, elem->id, elem->size); - else - verbose(tplg, " %s '%s': write %d bytes\n", - obj_name, elem->route->source, elem->size); - - count = write(tplg->out_fd, elem->obj, elem->size); - if (count < 0) { - SNDERR("error: failed to write %s %d\n", - obj_name, ret); - return ret; + if ((pos->next == base) || (elem_next->index != elem->index)) { + /* write header for the block */ + 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", + obj_name, ret); + return ret; + } + + /* write elems for the block */ + list_for_each(sub_pos, sub_base) { + elem = list_entry(sub_pos, struct tplg_elem, list); + /* compound elems have already been copied to other elems */ + if (elem->compound_elem) + continue; + + if (elem->type != SND_TPLG_TYPE_DAPM_GRAPH) + verbose(tplg, " %s '%s': write %d bytes\n", + obj_name, elem->id, elem->size); + else + verbose(tplg, " %s '%s': write %d bytes\n", + obj_name, elem->route->source, elem->size); + + 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; + } + + total_size += wsize; + /* get to the end of sub list */ + if (sub_pos == pos) + break; + } + /* the last elem of the current sub list as the head of + next sub list*/ + sub_base = pos; + count = 0; + block_size = 0; } - - wsize += count; }
/* make sure we have written the correct size */ - if (wsize != size) { + if (total_size != size) { SNDERR("error: size mismatch. Expected %d wrote %d\n", - size, wsize); + size, total_size); return -EIO; }
On Thu, 13 Apr 2017 08:52:43 +0200, fuweix.tang@intel.com wrote:
From: Fuwei Tang fuweix.tang@intel.com
The index value of an topology object can be used to group objects for different use cases. And so the audio kernel driver can ask topology core to load all objects of the specified index value(use case). The function is already supported in kernel. So in the user space, for topology objects of the same type but with different index values, they should be written into different blocks in the binary for kernel. The index value is stored in the block header.
Fuwei Tang (4): topology: Insert new element based on its index value topology: Remove code parsing index value in paring each object topology: Look up references for an object based on its index topology: Group elements with the same index value into a block
Applied these four patches now. Thanks.
Takashi
participants (2)
-
fuweix.tang@intel.com
-
Takashi Iwai