Blame src/topology/elem.c

Packit 4a16fb
/*
Packit 4a16fb
  Copyright(c) 2014-2015 Intel Corporation
Packit 4a16fb
  All rights reserved.
Packit 4a16fb
Packit 4a16fb
  This library is free software; you can redistribute it and/or modify
Packit 4a16fb
  it under the terms of the GNU Lesser General Public License as
Packit 4a16fb
  published by the Free Software Foundation; either version 2.1 of
Packit 4a16fb
  the License, or (at your option) any later version.
Packit 4a16fb
Packit 4a16fb
  This program is distributed in the hope that it will be useful,
Packit 4a16fb
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 4a16fb
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 4a16fb
  GNU Lesser General Public License for more details.
Packit 4a16fb
Packit 4a16fb
  Authors: Mengdong Lin <mengdong.lin@intel.com>
Packit 4a16fb
           Yao Jin <yao.jin@intel.com>
Packit 4a16fb
           Liam Girdwood <liam.r.girdwood@linux.intel.com>
Packit 4a16fb
*/
Packit 4a16fb
Packit 4a16fb
#include "list.h"
Packit 4a16fb
#include "tplg_local.h"
Packit 4a16fb
Packit Service f36a15
struct tplg_table tplg_table[] = {
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "manifest",
Packit Service f36a15
		.id    = "SectionManifest",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, manifest_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_MANIFEST,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_MANIFEST,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_manifest),
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_manifest_data,
Packit Service f36a15
		.save  = tplg_save_manifest_data,
Packit Service f36a15
		.decod = tplg_decode_manifest_data,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "control mixer",
Packit Service f36a15
		.id    = "SectionControlMixer",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, mixer_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_MIXER,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_MIXER,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_mixer_control),
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_control_mixer,
Packit Service f36a15
		.save  = tplg_save_control_mixer,
Packit Service f36a15
		.decod = tplg_decode_control_mixer,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "control enum",
Packit Service f36a15
		.id    = "SectionControlEnum",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, enum_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_ENUM,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_ENUM,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_enum_control),
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_control_enum,
Packit Service f36a15
		.save  = tplg_save_control_enum,
Packit Service f36a15
		.decod = tplg_decode_control_enum,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "control extended (bytes)",
Packit Service f36a15
		.id    = "SectionControlBytes",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, bytes_ext_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_BYTES,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_BYTES,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_bytes_control),
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_control_bytes,
Packit Service f36a15
		.save  = tplg_save_control_bytes,
Packit Service f36a15
		.decod = tplg_decode_control_bytes,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "dapm widget",
Packit Service f36a15
		.id    = "SectionWidget",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, widget_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_DAPM_WIDGET,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_DAPM_WIDGET,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_dapm_widget),
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_dapm_widget,
Packit Service f36a15
		.save  = tplg_save_dapm_widget,
Packit Service f36a15
		.decod = tplg_decode_dapm_widget,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "pcm",
Packit Service f36a15
		.id    = "SectionPCM",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, pcm_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_PCM,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_PCM,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_pcm),
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_pcm,
Packit Service f36a15
		.save  = tplg_save_pcm,
Packit Service f36a15
		.decod = tplg_decode_pcm,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "physical dai",
Packit Service f36a15
		.id    = "SectionDAI",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, dai_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_DAI,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_DAI,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_dai),
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_dai,
Packit Service f36a15
		.save  = tplg_save_dai,
Packit Service f36a15
		.decod = tplg_decode_dai,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "be",
Packit Service f36a15
		.id    = "SectionBE",
Packit Service f36a15
		.id2   = "SectionLink",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, be_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_BE,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_BACKEND_LINK,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_link_config),
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_link,
Packit Service f36a15
		.save  = tplg_save_link,
Packit Service f36a15
		.decod = tplg_decode_link,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "cc",
Packit Service f36a15
		.id    = "SectionCC",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, cc_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_CC,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_CODEC_LINK,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_link_config),
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_cc,
Packit Service f36a15
		.save  = tplg_save_cc,
Packit Service f36a15
		.decod = tplg_decode_cc,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "route (dapm graph)",
Packit Service f36a15
		.id = "SectionGraph",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, route_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_DAPM_GRAPH,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_DAPM_GRAPH,
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.parse = tplg_parse_dapm_graph,
Packit Service f36a15
		.gsave = tplg_save_dapm_graph,
Packit Service f36a15
		.decod = tplg_decode_dapm_graph,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "private data",
Packit Service f36a15
		.id    = "SectionData",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, pdata_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_DATA,
Packit Service f36a15
		.tsoc  = SND_SOC_TPLG_TYPE_PDATA,
Packit Service f36a15
		.build = 1,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_data,
Packit Service f36a15
		.save  = tplg_save_data,
Packit Service f36a15
		.decod = tplg_decode_data,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "text",
Packit Service f36a15
		.id    = "SectionText",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, text_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_TEXT,
Packit Service f36a15
		.size  = sizeof(struct tplg_texts),
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_text,
Packit Service f36a15
		.save  = tplg_save_text,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "tlv",
Packit Service f36a15
		.id    = "SectionTLV",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, tlv_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_TLV,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_ctl_tlv),
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_tlv,
Packit Service f36a15
		.save  = tplg_save_tlv,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "stream config",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, pcm_config_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_STREAM_CONFIG,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_stream),
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "stream capabilities",
Packit Service f36a15
		.id    = "SectionPCMCapabilities",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, pcm_caps_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_STREAM_CAPS,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_stream_caps),
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_stream_caps,
Packit Service f36a15
		.save  = tplg_save_stream_caps,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "token",
Packit Service f36a15
		.id    = "SectionVendorTokens",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, token_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_TOKEN,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_tokens,
Packit Service f36a15
		.save  = tplg_save_tokens,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "tuple",
Packit Service f36a15
		.id    = "SectionVendorTuples",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, tuple_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_TUPLE,
Packit Service f36a15
		.free  = tplg_free_tuples,
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_tuples,
Packit Service f36a15
		.save  = tplg_save_tuples,
Packit Service f36a15
	},
Packit Service f36a15
	{
Packit Service f36a15
		.name  = "hw config",
Packit Service f36a15
		.id    = "SectionHWConfig",
Packit Service f36a15
		.loff  = offsetof(snd_tplg_t, hw_cfg_list),
Packit Service f36a15
		.type  = SND_TPLG_TYPE_HW_CONFIG,
Packit Service f36a15
		.size  = sizeof(struct snd_soc_tplg_hw_config),
Packit Service f36a15
		.enew  = 1,
Packit Service f36a15
		.parse = tplg_parse_hw_config,
Packit Service f36a15
		.save  = tplg_save_hw_config,
Packit Service f36a15
	}
Packit Service f36a15
};
Packit Service f36a15
Packit Service f36a15
unsigned int tplg_table_items = ARRAY_SIZE(tplg_table);
Packit Service f36a15
Packit Service f36a15
int tplg_get_type(int asoc_type)
Packit Service f36a15
{
Packit Service f36a15
	unsigned int index;
Packit Service f36a15
Packit Service f36a15
	for (index = 0; index < tplg_table_items; index++)
Packit Service f36a15
		if (tplg_table[index].tsoc == asoc_type)
Packit Service f36a15
			return tplg_table[index].type;
Packit Service f36a15
	SNDERR("uknown asoc type %d", asoc_type);
Packit Service f36a15
	return -EINVAL;
Packit Service f36a15
}
Packit Service f36a15
Packit 4a16fb
int tplg_ref_add(struct tplg_elem *elem, int type, const char* id)
Packit 4a16fb
{
Packit 4a16fb
	struct tplg_ref *ref;
Packit 4a16fb
Packit 4a16fb
	ref = calloc(1, sizeof(*ref));
Packit 4a16fb
	if (!ref)
Packit 4a16fb
		return -ENOMEM;
Packit 4a16fb
Packit 4a16fb
	strncpy(ref->id, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
Packit 4a16fb
	ref->id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1] = 0;
Packit 4a16fb
	ref->type = type;
Packit 4a16fb
Packit 4a16fb
	list_add_tail(&ref->list, &elem->ref_list);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* directly add a reference elem */
Packit 4a16fb
int tplg_ref_add_elem(struct tplg_elem *elem, struct tplg_elem *elem_ref)
Packit 4a16fb
{
Packit 4a16fb
	struct tplg_ref *ref;
Packit 4a16fb
Packit 4a16fb
	ref = calloc(1, sizeof(*ref));
Packit 4a16fb
	if (!ref)
Packit 4a16fb
		return -ENOMEM;
Packit 4a16fb
Packit 4a16fb
	ref->type = elem_ref->type;
Packit 4a16fb
	ref->elem = elem_ref;
Packit 4a16fb
	snd_strlcpy(ref->id, elem_ref->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
Packit 4a16fb
Packit 4a16fb
	list_add_tail(&ref->list, &elem->ref_list);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
void tplg_ref_free_list(struct list_head *base)
Packit 4a16fb
{
Packit 4a16fb
	struct list_head *pos, *npos;
Packit 4a16fb
	struct tplg_ref *ref;
Packit 4a16fb
Packit 4a16fb
	list_for_each_safe(pos, npos, base) {
Packit 4a16fb
		ref = list_entry(pos, struct tplg_ref, list);
Packit 4a16fb
		list_del(&ref->list);
Packit 4a16fb
		free(ref);
Packit 4a16fb
	}
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
struct tplg_elem *tplg_elem_new(void)
Packit 4a16fb
{
Packit 4a16fb
	struct tplg_elem *elem;
Packit 4a16fb
Packit 4a16fb
	elem = calloc(1, sizeof(*elem));
Packit 4a16fb
	if (!elem)
Packit 4a16fb
		return NULL;
Packit 4a16fb
Packit 4a16fb
	INIT_LIST_HEAD(&elem->ref_list);
Packit 4a16fb
	return elem;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
void tplg_elem_free(struct tplg_elem *elem)
Packit 4a16fb
{
Packit Service f36a15
	list_del(&elem->list);
Packit Service f36a15
Packit 4a16fb
	tplg_ref_free_list(&elem->ref_list);
Packit 4a16fb
Packit 4a16fb
	/* free struct snd_tplg_ object,
Packit 4a16fb
	 * the union pointers share the same address
Packit 4a16fb
	 */
Packit 4a16fb
	if (elem->obj) {
Packit 4a16fb
		if (elem->free)
Packit 4a16fb
			elem->free(elem->obj);
Packit 4a16fb
Packit 4a16fb
		free(elem->obj);
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	free(elem);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
void tplg_elem_free_list(struct list_head *base)
Packit 4a16fb
{
Packit 4a16fb
	struct list_head *pos, *npos;
Packit 4a16fb
	struct tplg_elem *elem;
Packit 4a16fb
Packit 4a16fb
	list_for_each_safe(pos, npos, base) {
Packit 4a16fb
		elem = list_entry(pos, struct tplg_elem, list);
Packit 4a16fb
		tplg_elem_free(elem);
Packit 4a16fb
	}
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
Packit Service f36a15
				   unsigned int type, int index)
Packit 4a16fb
{
Packit 4a16fb
	struct list_head *pos;
Packit 4a16fb
	struct tplg_elem *elem;
Packit 4a16fb
Packit 4a16fb
	if (!base || !id)
Packit 4a16fb
		return NULL;
Packit 4a16fb
Packit 4a16fb
	list_for_each(pos, base) {
Packit 4a16fb
Packit 4a16fb
		elem = list_entry(pos, struct tplg_elem, list);
Packit 4a16fb
Packit 4a16fb
		if (!strcmp(elem->id, id) && elem->type == type)
Packit 4a16fb
			return elem;
Packit 4a16fb
		/* SND_TPLG_INDEX_ALL is the default value "0" and applicable
Packit 4a16fb
		   for all use cases */
Packit 4a16fb
		if ((index != SND_TPLG_INDEX_ALL)
Packit 4a16fb
			&& (elem->index > index))
Packit 4a16fb
			break;
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	return NULL;
Packit 4a16fb
}
Packit 4a16fb
Packit Service f36a15
/* find an element by type */
Packit Service f36a15
struct tplg_elem *tplg_elem_type_lookup(snd_tplg_t *tplg,
Packit Service f36a15
					enum snd_tplg_type type)
Packit Service f36a15
{
Packit Service f36a15
	struct tplg_table *tptr;
Packit Service f36a15
	struct list_head *pos, *list;
Packit Service f36a15
	struct tplg_elem *elem;
Packit Service f36a15
	unsigned int index;
Packit Service f36a15
Packit Service f36a15
	for (index = 0; index < tplg_table_items; index++) {
Packit Service f36a15
		tptr = &tplg_table[index];
Packit Service f36a15
		if (!tptr->enew)
Packit Service f36a15
			continue;
Packit Service f36a15
		if ((int)type != tptr->type)
Packit Service f36a15
			continue;
Packit Service f36a15
		break;
Packit Service f36a15
	}
Packit Service f36a15
	if (index >= tplg_table_items)
Packit Service f36a15
		return NULL;
Packit Service f36a15
Packit Service f36a15
	list = (struct list_head *)((void *)tplg + tptr->loff);
Packit Service f36a15
Packit Service f36a15
	/* return only first element */
Packit Service f36a15
	list_for_each(pos, list) {
Packit Service f36a15
		elem = list_entry(pos, struct tplg_elem, list);
Packit Service f36a15
		return elem;
Packit Service f36a15
	}
Packit Service f36a15
	return NULL;
Packit Service f36a15
}
Packit Service f36a15
Packit Service f36a15
/* insert a new element into list in the ascending order of index value */
Packit Service f36a15
void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
Packit 4a16fb
{
Packit 4a16fb
	struct list_head *pos, *p = &(elem_p->list);
Packit 4a16fb
	struct tplg_elem *elem;
Packit 4a16fb
Packit 4a16fb
	list_for_each(pos, list) {
Packit 4a16fb
		elem = list_entry(pos, struct tplg_elem, list);
Packit 4a16fb
		if (elem_p->index < elem->index)
Packit 4a16fb
			break;
Packit 4a16fb
	}
Packit Service f36a15
	/* insert item before pos */
Packit Service f36a15
	list_insert(p, pos->prev, pos);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* create a new common element and object */
Packit 4a16fb
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
Packit Service f36a15
				       snd_config_t *cfg,
Packit Service f36a15
				       const char *name,
Packit Service f36a15
				       enum snd_tplg_type type)
Packit 4a16fb
{
Packit Service f36a15
	struct tplg_table *tptr;
Packit 4a16fb
	struct tplg_elem *elem;
Packit Service f36a15
	struct list_head *list;
Packit Service f36a15
	const char *id;
Packit 4a16fb
	int obj_size = 0;
Packit Service f36a15
	unsigned index;
Packit 4a16fb
	void *obj;
Packit 4a16fb
	snd_config_iterator_t i, next;
Packit 4a16fb
	snd_config_t *n;
Packit 4a16fb
Packit 4a16fb
	if (!cfg && !name)
Packit 4a16fb
		return NULL;
Packit 4a16fb
Packit 4a16fb
	elem = tplg_elem_new();
Packit 4a16fb
	if (!elem)
Packit 4a16fb
		return NULL;
Packit 4a16fb
Packit 4a16fb
	/* do we get name from cfg */
Packit 4a16fb
	if (cfg) {
Packit 4a16fb
		snd_config_get_id(cfg, &id;;
Packit 4a16fb
		snd_strlcpy(elem->id, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
Packit 4a16fb
		elem->id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1] = 0;
Packit 4a16fb
		/* as we insert new elem based on the index value, move index
Packit 4a16fb
		   parsing here */
Packit 4a16fb
		snd_config_for_each(i, next, cfg) {
Packit 4a16fb
			n = snd_config_iterator_entry(i);
Packit 4a16fb
			if (snd_config_get_id(n, &id))
Packit 4a16fb
				continue;
Packit 4a16fb
			if (strcmp(id, "index") == 0) {
Packit Service f36a15
				if (tplg_get_integer(n, &elem->index, 0)) {
Packit Service f36a15
					free(elem);
Packit Service f36a15
					return NULL;
Packit Service f36a15
				}
Packit Service f36a15
				if (elem->index < 0) {
Packit 4a16fb
					free(elem);
Packit 4a16fb
					return NULL;
Packit 4a16fb
				}
Packit 4a16fb
			}
Packit 4a16fb
		}
Packit 4a16fb
	} else if (name != NULL)
Packit 4a16fb
		snd_strlcpy(elem->id, name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
Packit 4a16fb
Packit Service f36a15
	for (index = 0; index < tplg_table_items; index++) {
Packit Service f36a15
		tptr = &tplg_table[index];
Packit Service f36a15
		if (!tptr->enew)
Packit Service f36a15
			continue;
Packit Service f36a15
		if ((int)type != tptr->type)
Packit Service f36a15
			continue;
Packit 4a16fb
		break;
Packit Service f36a15
	}
Packit Service f36a15
	if (index >= tplg_table_items) {
Packit 4a16fb
		free(elem);
Packit 4a16fb
		return NULL;
Packit 4a16fb
	}
Packit 4a16fb
Packit Service f36a15
	list = (struct list_head *)((void *)tplg + tptr->loff);
Packit Service f36a15
	tplg_elem_insert(elem, list);
Packit Service f36a15
	obj_size = tptr->size;
Packit Service f36a15
	elem->free = tptr->free;
Packit Service f36a15
	elem->table = tptr;
Packit Service f36a15
Packit 4a16fb
	/* create new object too if required */
Packit 4a16fb
	if (obj_size > 0) {
Packit 4a16fb
		obj = calloc(1, obj_size);
Packit 4a16fb
		if (obj == NULL) {
Packit 4a16fb
			free(elem);
Packit 4a16fb
			return NULL;
Packit 4a16fb
		}
Packit 4a16fb
Packit 4a16fb
		elem->obj = obj;
Packit 4a16fb
		elem->size = obj_size;
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	elem->type = type;
Packit 4a16fb
	return elem;
Packit 4a16fb
}
Packit Service f36a15
Packit Service f36a15
struct tplg_alloc {
Packit Service f36a15
	struct list_head list;
Packit Service f36a15
	void *data[0];
Packit Service f36a15
};
Packit Service f36a15
Packit Service f36a15
void *tplg_calloc(struct list_head *heap, size_t size)
Packit Service f36a15
{
Packit Service f36a15
	struct tplg_alloc *a;
Packit Service f36a15
Packit Service f36a15
	a = calloc(1, sizeof(*a) + size);
Packit Service f36a15
	if (a == NULL)
Packit Service f36a15
		return NULL;
Packit Service f36a15
	list_add_tail(&a->list, heap);
Packit Service f36a15
	return a->data;
Packit Service f36a15
}
Packit Service f36a15
Packit Service f36a15
void tplg_free(struct list_head *heap)
Packit Service f36a15
{
Packit Service f36a15
	struct list_head *pos, *npos;
Packit Service f36a15
	struct tplg_alloc *a;
Packit Service f36a15
Packit Service f36a15
	list_for_each_safe(pos, npos, heap) {
Packit Service f36a15
		a = list_entry(pos, struct tplg_alloc, list);
Packit Service f36a15
		list_del(&a->list);
Packit Service f36a15
		free(a);
Packit Service f36a15
	}
Packit Service f36a15
}