]> git.alsa-project.org Git - alsa-utils.git/commitdiff
topology: pre-process-object: add data section for attributes with token reference
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Mon, 26 Apr 2021 18:30:07 +0000 (11:30 -0700)
committerJaroslav Kysela <perex@perex.cz>
Tue, 25 May 2021 16:26:51 +0000 (18:26 +0200)
Objects that have attributes with token_ref need
to have separate SectionData and SectionVendorTuples
for each unique token_ref based on the attribute_sets
in the object's attribute_set_list.

Add the tplg_pp_add_object_data()
function to add the data[] refs in the object and also
the respective SectionData and SectionVendorTuples.

For example for the pga object:

Object.Widget.pga."0" {
pipeline_id 2
format s24le
type pga
no_pm 1
uuid    "7e:67:7e:b7:f4:5f:88:41:af:14:fb:a8:bd:bf:8"
period_sink_count 2
period_source_count 2
ramp_step_ms 250
        ramp_step_type "linear"
mixer.0 {
....
}
mixer.0.name "2 Master Playback Volume"
}

The following sections will be added:
SectionWidget.'pga.2.0' {
index 2
type pga
no_pm 1
mixer [
"2 Master Playback Volume"
]
bytes [
]
data [
"pga.2.0.sof_tkn_comp.word"
"pga.2.0.sof_tkn_comp.string"
"pga.2.0.sof_tkn_comp.uuid"
"pga.2.0.sof_tkn_volume.word"
]
}

SectionData."pga.2.0.sof_tkn_comp.word" {
tuples "pga.2.0.sof_tkn_comp.word"
}

SectionData."pga.2.0.sof_tkn_comp.string" {
tuples "pga.2.0.sof_tkn_comp.string"
}

SectionData."pga.2.0.sof_tkn_comp.uuid" {
tuples "pga.2.0.sof_tkn_comp.uuid"
}

SectionData."pga.2.0.sof_tkn_volume.word" {
tuples "pga.2.0.sof_tkn_volume.word"
}

SectionVendorTuples."pga.2.0.sof_tkn_comp.word" {
tokens "sof_tkn_comp"
tuples."word" {
period_source_count "2"
period_sink_count "2"
}
}

SectionVendorTuples."pga.2.0.sof_tkn_comp.string" {
tokens "sof_tkn_comp"
tuples."string" {
format "s24le"
}
}

SectionVendorTuples."pga.2.0.sof_tkn_comp.uuid" {
tokens "sof_tkn_comp"
tuples."uuid" {
uuid "7e:67:7e:b7:f4:5f:88:41:af:14:fb:a8:bd:bf:8"
}
}

SectionVendorTuples."pga.2.0.sof_tkn_volume.word" {
tokens "sof_tkn_volume"
tuples."word" {
ramp_step_ms "250"
ramp_step_type "0"
}
}

Note that the ramp_step_type of "linear" is converted
to the tuple value 0.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
topology/pre-process-object.c

index 609e1ec125d29741f3a969f057708297e0be8fc7..249bd7dfcf0107937c00a9e545d1c3dc1f0db524 100644 (file)
@@ -309,6 +309,247 @@ static snd_config_t *tplg_object_lookup_in_config(struct tplg_pre_processor *tpl
        return obj_cfg;
 }
 
+static int tplg_pp_add_object_tuple_section(struct tplg_pre_processor *tplg_pp,
+                                           snd_config_t *class_cfg,
+                                           snd_config_t *attr, char *data_name,
+                                           const char *token_ref)
+{
+       snd_config_t *top, *tuple_cfg, *child, *cfg, *new;
+       const char *id;
+       char *token, *type;
+       long tuple_value;
+       int ret;
+
+       tplg_pp_debug("Building vendor tuples section: '%s' ...", data_name);
+
+       ret = snd_config_search(tplg_pp->output_cfg, "SectionVendorTuples", &top);
+       if (ret < 0) {
+               ret = tplg_config_make_add(&top, "SectionVendorTuples",
+                                         SND_CONFIG_TYPE_COMPOUND, tplg_pp->output_cfg);
+               if (ret < 0) {
+                       SNDERR("Error creating SectionVendorTuples config\n");
+                       return ret;
+               }
+       }
+
+       type = strchr(token_ref, '.');
+       token = calloc(1, strlen(token_ref) - strlen(type) + 1);
+       if (!token)
+               return -ENOMEM;
+       snprintf(token, strlen(token_ref) - strlen(type) + 1, "%s", token_ref);
+
+       tuple_cfg = tplg_find_config(top, data_name);
+       if (!tuple_cfg) {
+               /* add new SectionVendorTuples */
+               ret = tplg_config_make_add(&tuple_cfg, data_name, SND_CONFIG_TYPE_COMPOUND, top);
+               if (ret < 0) {
+                       SNDERR("Error creating new vendor tuples config %s\n", data_name);
+                       goto err;
+               }
+
+               ret = tplg_config_make_add(&child, "tokens", SND_CONFIG_TYPE_STRING,
+                                         tuple_cfg);
+               if (ret < 0) {
+                       SNDERR("Error creating tokens config for '%s'\n", data_name);
+                       goto err;
+               }
+
+               ret = snd_config_set_string(child, token);
+               if (ret < 0) {
+                       SNDERR("Error setting tokens config for '%s'\n", data_name);
+                       goto err;
+               }
+
+               ret = tplg_config_make_add(&child, "tuples", SND_CONFIG_TYPE_COMPOUND,
+                                         tuple_cfg);
+               if (ret < 0) {
+                       SNDERR("Error creating tuples config for '%s'\n", data_name);
+                       goto err;
+               }
+
+               ret = tplg_config_make_add(&cfg, type + 1, SND_CONFIG_TYPE_COMPOUND,
+                                         child);
+               if (ret < 0) {
+                       SNDERR("Error creating tuples type config for '%s'\n", data_name);
+                       goto err;
+               }
+       } else {
+               char *id;
+
+               id = tplg_snprintf("tuples.%s", type + 1);
+               if (!id) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               ret = snd_config_search(tuple_cfg, id , &cfg);
+               free(id);
+               if (ret < 0) {
+                       SNDERR("can't find type config %s\n", type + 1);
+                       goto err;
+               }
+       }
+
+       ret = snd_config_get_id(attr, &id);
+       if (ret < 0)
+               goto err;
+
+       /* tuple exists already? */
+       ret = snd_config_search(cfg, id, &child);
+       if (ret >=0)
+               goto err;
+
+       /* add attribute to tuples */
+       tuple_value = tplg_class_attribute_valid_tuple_value(tplg_pp, class_cfg, attr);
+       if (tuple_value < 0) {
+               /* just copy attribute cfg as is */
+               ret = snd_config_copy(&new, attr);
+               if (ret < 0) {
+                       SNDERR("can't copy attribute for %s\n", data_name);
+                       goto err;
+               }
+       } else {
+               ret = snd_config_make(&new, id, SND_CONFIG_TYPE_INTEGER);
+               if (ret < 0)
+                       goto err;
+
+               ret = snd_config_set_integer(new, tuple_value);
+               if (ret < 0)
+                       goto err;
+       }
+
+       ret = snd_config_add(cfg, new);
+       if (ret < 0)
+               goto err;
+
+err:
+       free(token);
+       return ret;
+}
+
+static int tplg_pp_add_object_data_section(struct tplg_pre_processor *tplg_pp,
+                                          snd_config_t *obj_data, char *data_name)
+{
+       snd_config_iterator_t i, next;
+       snd_config_t *top, *data_cfg, *child;
+       char *data_id;
+       int ret, id = 0;
+
+       ret = snd_config_search(tplg_pp->output_cfg, "SectionData", &top);
+       if (ret < 0) {
+               ret = tplg_config_make_add(&top, "SectionData", SND_CONFIG_TYPE_COMPOUND,
+                                         tplg_pp->output_cfg);
+               if (ret < 0) {
+                       SNDERR("Failed to add SectionData\n");
+                       return ret;
+               }
+       }
+
+       /* nothing to do if data section already exists */
+       data_cfg = tplg_find_config(top, data_name);
+       if (data_cfg)
+               return 0;
+
+       tplg_pp_debug("Building data section %s ...", data_name);
+
+       /* add new SectionData */
+       ret = tplg_config_make_add(&data_cfg, data_name, SND_CONFIG_TYPE_COMPOUND, top);
+       if (ret < 0)
+               return ret;
+
+       ret = tplg_config_make_add(&child, "tuples", SND_CONFIG_TYPE_STRING, data_cfg);
+       if (ret < 0) {
+               SNDERR("error adding data ref for %s\n", data_name);
+               return ret;
+       }
+
+       ret = snd_config_set_string(child, data_name);
+       if (ret < 0) {
+               SNDERR("error setting tuples ref for %s\n", data_name);
+               return ret;
+       }
+
+       /* add data item to object */
+       snd_config_for_each(i, next, obj_data)
+               id++;
+
+       data_id = tplg_snprintf("%d", id);
+       if (!data_id)
+               return -ENOMEM;
+
+       ret = tplg_config_make_add(&child, data_id, SND_CONFIG_TYPE_STRING, obj_data);
+       free(data_id);
+       if (ret < 0) {
+               SNDERR("error adding data ref %s\n", data_name);
+               return ret;
+       }
+
+       return snd_config_set_string(child, data_name);
+}
+
+static int tplg_add_object_data(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg,
+                               snd_config_t *top)
+{
+       snd_config_iterator_t i, next;
+       snd_config_t *data_cfg, *class_cfg, *n, *obj;
+       const char *object_id;
+       int ret;
+
+       if (snd_config_get_id(top, &object_id) < 0)
+               return 0;
+
+       obj = tplg_object_get_instance_config(tplg_pp, obj_cfg);
+
+       class_cfg = tplg_class_lookup(tplg_pp, obj_cfg);
+       if (!class_cfg)
+               return -EINVAL;
+
+       /* add data config to top */
+       ret = snd_config_search(top, "data", &data_cfg);
+       if (ret < 0) {
+               ret = tplg_config_make_add(&data_cfg, "data", SND_CONFIG_TYPE_COMPOUND, top);
+               if (ret < 0) {
+                       SNDERR("error creating data config for %s\n", object_id);
+                       return ret;
+               }
+       }
+
+       /* add data items to object's data section */
+       snd_config_for_each(i, next, obj) {
+               const char *id, *token;
+               char *data_cfg_name;
+
+               n = snd_config_iterator_entry(i);
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
+
+               token = tplg_class_get_attribute_token_ref(tplg_pp, class_cfg, id);
+               if (!token)
+                       continue;
+
+               data_cfg_name = tplg_snprintf("%s.%s", object_id, token);
+               if (!data_cfg_name)
+                       return -ENOMEM;
+
+               ret = tplg_pp_add_object_data_section(tplg_pp, data_cfg, data_cfg_name);
+               if (ret < 0) {
+                       SNDERR("Failed to add data section %s\n", data_cfg_name);
+                       free(data_cfg_name);
+                       return ret;
+               }
+
+               ret = tplg_pp_add_object_tuple_section(tplg_pp, class_cfg, n, data_cfg_name,
+                                                      token);
+               free(data_cfg_name);
+               if (ret < 0) {
+                       SNDERR("Failed to add data section %s\n", data_cfg_name);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 /* search for all template configs in the source config and copy them to the destination */
 static int tplg_object_add_attributes(snd_config_t *dst, snd_config_t *template,
                                      snd_config_t *src)
@@ -440,8 +681,22 @@ static int tplg_build_generic_object(struct tplg_pre_processor *tplg_pp, snd_con
                                     snd_config_t *parent)
 {
        snd_config_t *wtop;
+       const char *name;
+       int ret;
+
+       ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &wtop, NULL, false);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_config_get_id(wtop, &name);
+       if (ret < 0)
+               return ret;
 
-       return tplg_build_object_from_template(tplg_pp, obj_cfg, &wtop, NULL, false);
+       ret = tplg_add_object_data(tplg_pp, obj_cfg, wtop);
+       if (ret < 0)
+               SNDERR("Failed to add data section for %s\n", name);
+
+       return ret;
 }
 
 const struct build_function_map object_build_map[] = {
@@ -904,8 +1159,6 @@ static int tplg_build_object(struct tplg_pre_processor *tplg_pp, snd_config_t *n
                return ret;
        }
 
-       tplg_pp_config_debug(tplg_pp, obj_local);
-
        /* nothing to do if object is not supported */
        map = tplg_object_get_map(tplg_pp, new_obj);
        if (!map)