* </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,
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
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);
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);
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;
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;
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;
}
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);
}
}
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);
}
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;
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;
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);
}
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;
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;
/* 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);
struct list_head *base, *pos;
int err;
- err = tplg_build_stream_caps(tplg, elem->id, elem->pcm->caps);
+ err = tplg_build_stream_caps(tplg, elem->id, elem->index,
+ elem->pcm->caps);
if (err < 0)
return err;
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;
}
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;
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;
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;
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",
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);