mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-02-18 22:05:17 -05:00
topology: Allow a data section to contain multiple tuples objects
It's easy to use a vendor tuples object to define a C structure instance as vendor specific parameter for kernel drivers. And sometimes the kernel drivers may want a group of structures. So this patch will allow user to define multiple vendor tuples objects in a data section, to avoid defining multiple data sections and each data section only has 1 vendor tuples object. There is no ABI change in this patch. Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com> Signed-off-by: Fuwei Tang <fuweix.tang@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
1cb217ead9
commit
0b8b6bb7d8
2 changed files with 74 additions and 18 deletions
|
|
@ -214,6 +214,20 @@ extern "C" {
|
||||||
* The keyword tuples is to define vendor specific tuples. Please refer to
|
* The keyword tuples is to define vendor specific tuples. Please refer to
|
||||||
* section Vendor Tokens and Vendor tuples.
|
* section Vendor Tokens and Vendor tuples.
|
||||||
*
|
*
|
||||||
|
* It's easy to use a vendor tuples object to define a C structure instance.
|
||||||
|
* And a data section can include multiple vendor tuples objects:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* SectionData."data element name" {
|
||||||
|
* index "1" #Index number
|
||||||
|
* tuples [
|
||||||
|
* "id of the 1st vendor tuples section"
|
||||||
|
* "id of the 2nd vendor tuples section"
|
||||||
|
* ...
|
||||||
|
* ]
|
||||||
|
* };
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <h5>How to define an element with private data</h5>
|
* <h5>How to define an element with private data</h5>
|
||||||
* An element can refer to a single data section or multiple data
|
* An element can refer to a single data section or multiple data
|
||||||
* sections.
|
* sections.
|
||||||
|
|
|
||||||
|
|
@ -408,7 +408,7 @@ static unsigned int get_tuple_size(int type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill a data element's private buffer with its tuples */
|
/* Add a tuples object to the private buffer of its parent data element */
|
||||||
static int copy_tuples(struct tplg_elem *elem,
|
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)
|
||||||
{
|
{
|
||||||
|
|
@ -423,12 +423,9 @@ static int copy_tuples(struct tplg_elem *elem,
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
int token_val;
|
int token_val;
|
||||||
|
|
||||||
if (priv) {
|
size = priv ? priv->size : 0; /* original private data size */
|
||||||
SNDERR("error: %s has more data than tuples\n", elem->id);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = 0;
|
/* scan each tuples set (one set per type) */
|
||||||
for (i = 0; i < tuples->num_sets ; i++) {
|
for (i = 0; i < tuples->num_sets ; i++) {
|
||||||
tuple_set = tuples->set[i];
|
tuple_set = tuples->set[i];
|
||||||
set_size = sizeof(struct snd_soc_tplg_vendor_array)
|
set_size = sizeof(struct snd_soc_tplg_vendor_array)
|
||||||
|
|
@ -448,7 +445,7 @@ static int copy_tuples(struct tplg_elem *elem,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
off = priv->size;
|
off = priv->size;
|
||||||
priv->size = size;
|
priv->size = size; /* update private data size */
|
||||||
|
|
||||||
array = (struct snd_soc_tplg_vendor_array *)(priv->data + off);
|
array = (struct snd_soc_tplg_vendor_array *)(priv->data + off);
|
||||||
array->size = set_size;
|
array->size = set_size;
|
||||||
|
|
@ -495,6 +492,7 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)
|
||||||
struct tplg_ref *ref;
|
struct tplg_ref *ref;
|
||||||
struct list_head *base, *pos;
|
struct list_head *base, *pos;
|
||||||
struct tplg_elem *tuples, *tokens;
|
struct tplg_elem *tuples, *tokens;
|
||||||
|
int err;
|
||||||
|
|
||||||
base = &elem->ref_list;
|
base = &elem->ref_list;
|
||||||
list_for_each(pos, base) {
|
list_for_each(pos, base) {
|
||||||
|
|
@ -504,23 +502,27 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)
|
||||||
if (!ref->id || ref->type != SND_TPLG_TYPE_TUPLE)
|
if (!ref->id || ref->type != SND_TPLG_TYPE_TUPLE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tplg_dbg("look up tuples %s\n", ref->id);
|
tplg_dbg("tuples '%s' used by data '%s'\n", ref->id, elem->id);
|
||||||
|
|
||||||
if (!ref->elem)
|
if (!ref->elem)
|
||||||
ref->elem = tplg_elem_lookup(&tplg->tuple_list,
|
ref->elem = tplg_elem_lookup(&tplg->tuple_list,
|
||||||
ref->id, SND_TPLG_TYPE_TUPLE, elem->index);
|
ref->id, SND_TPLG_TYPE_TUPLE, elem->index);
|
||||||
tuples = ref->elem;
|
tuples = ref->elem;
|
||||||
if (!tuples)
|
if (!tuples) {
|
||||||
|
SNDERR("error: cannot find tuples %s\n", ref->id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
tplg_dbg("found tuples %s\n", tuples->id);
|
|
||||||
tokens = get_tokens(tplg, tuples);
|
tokens = get_tokens(tplg, tuples);
|
||||||
if (!tokens)
|
if (!tokens) {
|
||||||
|
SNDERR("error: cannot find token for %s\n", ref->id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
tplg_dbg("found tokens %s\n", tokens->id);
|
/* a data object can have multiple tuples objects */
|
||||||
/* a data object can only have one tuples object */
|
err = copy_tuples(elem, tuples->tuples, tokens->tokens);
|
||||||
return copy_tuples(elem, tuples->tuples, tokens->tokens);
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -689,6 +691,47 @@ static int parse_tuple_sets(snd_config_t *cfg,
|
||||||
return 0;
|
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
|
/* Parse private data references for the element, either a single data section
|
||||||
* or a list of data sections.
|
* or a list of data sections.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1002,10 +1045,9 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(id, "tuples") == 0) {
|
if (strcmp(id, "tuples") == 0) {
|
||||||
if (snd_config_get_string(n, &val) < 0)
|
err = parse_tuples_refs(n, elem);
|
||||||
return -EINVAL;
|
if (err < 0)
|
||||||
tplg_dbg(" Data: %s\n", val);
|
return err;
|
||||||
tplg_ref_add(elem, SND_TPLG_TYPE_TUPLE, val);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue