cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

topology.c (46242B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2//
      3// Copyright(c) 2021 Intel Corporation. All rights reserved.
      4//
      5// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
      6//          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
      7//
      8
      9#include <linux/firmware.h>
     10#include <linux/uuid.h>
     11#include <sound/soc.h>
     12#include <sound/soc-acpi.h>
     13#include <sound/soc-topology.h>
     14#include <uapi/sound/intel/avs/tokens.h>
     15#include "avs.h"
     16#include "topology.h"
     17
     18/* Get pointer to vendor array at the specified offset. */
     19#define avs_tplg_vendor_array_at(array, offset) \
     20	((struct snd_soc_tplg_vendor_array *)((u8 *)array + offset))
     21
     22/* Get pointer to vendor array that is next in line. */
     23#define avs_tplg_vendor_array_next(array) \
     24	(avs_tplg_vendor_array_at(array, le32_to_cpu((array)->size)))
     25
     26/*
     27 * Scan provided block of tuples for the specified token. If found,
     28 * @offset is updated with position at which first matching token is
     29 * located.
     30 *
     31 * Returns 0 on success, -ENOENT if not found and error code otherwise.
     32 */
     33static int
     34avs_tplg_vendor_array_lookup(struct snd_soc_tplg_vendor_array *tuples,
     35			     u32 block_size, u32 token, u32 *offset)
     36{
     37	u32 pos = 0;
     38
     39	while (block_size > 0) {
     40		struct snd_soc_tplg_vendor_value_elem *tuple;
     41		u32 tuples_size = le32_to_cpu(tuples->size);
     42
     43		if (tuples_size > block_size)
     44			return -EINVAL;
     45
     46		tuple = tuples->value;
     47		if (le32_to_cpu(tuple->token) == token) {
     48			*offset = pos;
     49			return 0;
     50		}
     51
     52		block_size -= tuples_size;
     53		pos += tuples_size;
     54		tuples = avs_tplg_vendor_array_next(tuples);
     55	}
     56
     57	return -ENOENT;
     58}
     59
     60/*
     61 * See avs_tplg_vendor_array_lookup() for description.
     62 *
     63 * Behaves exactly like avs_tplg_vendor_lookup() but starts from the
     64 * next vendor array in line. Useful when searching for the finish line
     65 * of an arbitrary entry in a list of entries where each is composed of
     66 * several vendor tuples and a specific token marks the beginning of
     67 * a new entry block.
     68 */
     69static int
     70avs_tplg_vendor_array_lookup_next(struct snd_soc_tplg_vendor_array *tuples,
     71				  u32 block_size, u32 token, u32 *offset)
     72{
     73	u32 tuples_size = le32_to_cpu(tuples->size);
     74	int ret;
     75
     76	if (tuples_size > block_size)
     77		return -EINVAL;
     78
     79	tuples = avs_tplg_vendor_array_next(tuples);
     80	block_size -= tuples_size;
     81
     82	ret = avs_tplg_vendor_array_lookup(tuples, block_size, token, offset);
     83	if (!ret)
     84		*offset += tuples_size;
     85	return ret;
     86}
     87
     88/*
     89 * Scan provided block of tuples for the specified token which marks
     90 * the border of an entry block. Behavior is similar to
     91 * avs_tplg_vendor_array_lookup() except 0 is also returned if no
     92 * matching token has been found. In such case, returned @size is
     93 * assigned to @block_size as the entire block belongs to the current
     94 * entry.
     95 *
     96 * Returns 0 on success, error code otherwise.
     97 */
     98static int
     99avs_tplg_vendor_entry_size(struct snd_soc_tplg_vendor_array *tuples,
    100			   u32 block_size, u32 entry_id_token, u32 *size)
    101{
    102	int ret;
    103
    104	ret = avs_tplg_vendor_array_lookup_next(tuples, block_size, entry_id_token, size);
    105	if (ret == -ENOENT) {
    106		*size = block_size;
    107		ret = 0;
    108	}
    109
    110	return ret;
    111}
    112
    113/*
    114 * Vendor tuple parsing descriptor.
    115 *
    116 * @token: vendor specific token that identifies tuple
    117 * @type: tuple type, one of SND_SOC_TPLG_TUPLE_TYPE_XXX
    118 * @offset: offset of a struct's field to initialize
    119 * @parse: parsing function, extracts and assigns value to object's field
    120 */
    121struct avs_tplg_token_parser {
    122	enum avs_tplg_token token;
    123	u32 type;
    124	u32 offset;
    125	int (*parse)(struct snd_soc_component *comp, void *elem, void *object, u32 offset);
    126};
    127
    128static int
    129avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
    130{
    131	struct snd_soc_tplg_vendor_uuid_elem *tuple = elem;
    132	guid_t *val = (guid_t *)((u8 *)object + offset);
    133
    134	guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid);
    135
    136	return 0;
    137}
    138
    139static int
    140avs_parse_bool_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
    141{
    142	struct snd_soc_tplg_vendor_value_elem *tuple = elem;
    143	bool *val = (bool *)((u8 *)object + offset);
    144
    145	*val = le32_to_cpu(tuple->value);
    146
    147	return 0;
    148}
    149
    150static int
    151avs_parse_byte_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
    152{
    153	struct snd_soc_tplg_vendor_value_elem *tuple = elem;
    154	u8 *val = ((u8 *)object + offset);
    155
    156	*val = le32_to_cpu(tuple->value);
    157
    158	return 0;
    159}
    160
    161static int
    162avs_parse_short_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
    163{
    164	struct snd_soc_tplg_vendor_value_elem *tuple = elem;
    165	u16 *val = (u16 *)((u8 *)object + offset);
    166
    167	*val = le32_to_cpu(tuple->value);
    168
    169	return 0;
    170}
    171
    172static int
    173avs_parse_word_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
    174{
    175	struct snd_soc_tplg_vendor_value_elem *tuple = elem;
    176	u32 *val = (u32 *)((u8 *)object + offset);
    177
    178	*val = le32_to_cpu(tuple->value);
    179
    180	return 0;
    181}
    182
    183static int
    184avs_parse_string_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
    185{
    186	struct snd_soc_tplg_vendor_string_elem *tuple = elem;
    187	char *val = (char *)((u8 *)object + offset);
    188
    189	snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s", tuple->string);
    190
    191	return 0;
    192}
    193
    194static int avs_parse_uuid_tokens(struct snd_soc_component *comp, void *object,
    195				 const struct avs_tplg_token_parser *parsers, int count,
    196				 struct snd_soc_tplg_vendor_array *tuples)
    197{
    198	struct snd_soc_tplg_vendor_uuid_elem *tuple;
    199	int ret, i, j;
    200
    201	/* Parse element by element. */
    202	for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
    203		tuple = &tuples->uuid[i];
    204
    205		for (j = 0; j < count; j++) {
    206			/* Ignore non-UUID tokens. */
    207			if (parsers[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID ||
    208			    parsers[j].token != le32_to_cpu(tuple->token))
    209				continue;
    210
    211			ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
    212			if (ret)
    213				return ret;
    214		}
    215	}
    216
    217	return 0;
    218}
    219
    220static int avs_parse_string_tokens(struct snd_soc_component *comp, void *object,
    221				   const struct avs_tplg_token_parser *parsers, int count,
    222				   struct snd_soc_tplg_vendor_array *tuples)
    223{
    224	struct snd_soc_tplg_vendor_string_elem *tuple;
    225	int ret, i, j;
    226
    227	/* Parse element by element. */
    228	for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
    229		tuple = &tuples->string[i];
    230
    231		for (j = 0; j < count; j++) {
    232			/* Ignore non-string tokens. */
    233			if (parsers[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING ||
    234			    parsers[j].token != le32_to_cpu(tuple->token))
    235				continue;
    236
    237			ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
    238			if (ret)
    239				return ret;
    240		}
    241	}
    242
    243	return 0;
    244}
    245
    246static int avs_parse_word_tokens(struct snd_soc_component *comp, void *object,
    247				 const struct avs_tplg_token_parser *parsers, int count,
    248				 struct snd_soc_tplg_vendor_array *tuples)
    249{
    250	struct snd_soc_tplg_vendor_value_elem *tuple;
    251	int ret, i, j;
    252
    253	/* Parse element by element. */
    254	for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
    255		tuple = &tuples->value[i];
    256
    257		for (j = 0; j < count; j++) {
    258			/* Ignore non-integer tokens. */
    259			if (!(parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD ||
    260			      parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT ||
    261			      parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE ||
    262			      parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL))
    263				continue;
    264
    265			if (parsers[j].token != le32_to_cpu(tuple->token))
    266				continue;
    267
    268			ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
    269			if (ret)
    270				return ret;
    271		}
    272	}
    273
    274	return 0;
    275}
    276
    277static int avs_parse_tokens(struct snd_soc_component *comp, void *object,
    278			    const struct avs_tplg_token_parser *parsers, size_t count,
    279			    struct snd_soc_tplg_vendor_array *tuples, int priv_size)
    280{
    281	int array_size, ret;
    282
    283	while (priv_size > 0) {
    284		array_size = le32_to_cpu(tuples->size);
    285
    286		if (array_size <= 0) {
    287			dev_err(comp->dev, "invalid array size 0x%x\n", array_size);
    288			return -EINVAL;
    289		}
    290
    291		/* Make sure there is enough data before parsing. */
    292		priv_size -= array_size;
    293		if (priv_size < 0) {
    294			dev_err(comp->dev, "invalid array size 0x%x\n", array_size);
    295			return -EINVAL;
    296		}
    297
    298		switch (le32_to_cpu(tuples->type)) {
    299		case SND_SOC_TPLG_TUPLE_TYPE_UUID:
    300			ret = avs_parse_uuid_tokens(comp, object, parsers, count, tuples);
    301			break;
    302		case SND_SOC_TPLG_TUPLE_TYPE_STRING:
    303			ret = avs_parse_string_tokens(comp, object, parsers, count, tuples);
    304			break;
    305		case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
    306		case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
    307		case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
    308		case SND_SOC_TPLG_TUPLE_TYPE_WORD:
    309			ret = avs_parse_word_tokens(comp, object, parsers, count, tuples);
    310			break;
    311		default:
    312			dev_err(comp->dev, "unknown token type %d\n", tuples->type);
    313			ret = -EINVAL;
    314		}
    315
    316		if (ret) {
    317			dev_err(comp->dev, "parsing %zu tokens of %d type failed: %d\n",
    318				count, tuples->type, ret);
    319			return ret;
    320		}
    321
    322		tuples = avs_tplg_vendor_array_next(tuples);
    323	}
    324
    325	return 0;
    326}
    327
    328#define AVS_DEFINE_PTR_PARSER(name, type, member) \
    329static int \
    330avs_parse_##name##_ptr(struct snd_soc_component *comp, void *elem, void *object, u32 offset) \
    331{ \
    332	struct snd_soc_tplg_vendor_value_elem *tuple = elem;		\
    333	struct avs_soc_component *acomp = to_avs_soc_component(comp);	\
    334	type **val = (type **)(object + offset);			\
    335	u32 idx;							\
    336									\
    337	idx = le32_to_cpu(tuple->value);				\
    338	if (idx >= acomp->tplg->num_##member)				\
    339		return -EINVAL;						\
    340									\
    341	*val = &acomp->tplg->member[idx];				\
    342									\
    343	return 0;							\
    344}
    345
    346AVS_DEFINE_PTR_PARSER(audio_format, struct avs_audio_format, fmts);
    347AVS_DEFINE_PTR_PARSER(modcfg_base, struct avs_tplg_modcfg_base, modcfgs_base);
    348AVS_DEFINE_PTR_PARSER(modcfg_ext, struct avs_tplg_modcfg_ext, modcfgs_ext);
    349AVS_DEFINE_PTR_PARSER(pplcfg, struct avs_tplg_pplcfg, pplcfgs);
    350AVS_DEFINE_PTR_PARSER(binding, struct avs_tplg_binding, bindings);
    351
    352static int
    353parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
    354{
    355	struct snd_soc_tplg_vendor_value_elem *velem = elem;
    356	struct avs_audio_format *audio_format = object;
    357
    358	switch (offset) {
    359	case AVS_TKN_AFMT_NUM_CHANNELS_U32:
    360		audio_format->num_channels = le32_to_cpu(velem->value);
    361		break;
    362	case AVS_TKN_AFMT_VALID_BIT_DEPTH_U32:
    363		audio_format->valid_bit_depth = le32_to_cpu(velem->value);
    364		break;
    365	case AVS_TKN_AFMT_SAMPLE_TYPE_U32:
    366		audio_format->sample_type = le32_to_cpu(velem->value);
    367		break;
    368	}
    369
    370	return 0;
    371}
    372
    373static int parse_link_formatted_string(struct snd_soc_component *comp, void *elem,
    374				       void *object, u32 offset)
    375{
    376	struct snd_soc_tplg_vendor_string_elem *tuple = elem;
    377	struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
    378	char *val = (char *)((u8 *)object + offset);
    379
    380	/*
    381	 * Dynamic naming - string formats, e.g.: ssp%d - supported only for
    382	 * topologies describing single device e.g.: an I2S codec on SSP0.
    383	 */
    384	if (hweight_long(mach->mach_params.i2s_link_mask) != 1)
    385		return avs_parse_string_token(comp, elem, object, offset);
    386
    387	snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string,
    388		 __ffs(mach->mach_params.i2s_link_mask));
    389
    390	return 0;
    391}
    392
    393static int
    394parse_dictionary_header(struct snd_soc_component *comp,
    395			struct snd_soc_tplg_vendor_array *tuples,
    396			void **dict, u32 *num_entries, size_t entry_size,
    397			u32 num_entries_token)
    398{
    399	struct snd_soc_tplg_vendor_value_elem *tuple;
    400
    401	/* Dictionary header consists of single tuple - entry count. */
    402	tuple = tuples->value;
    403	if (le32_to_cpu(tuple->token) != num_entries_token) {
    404		dev_err(comp->dev, "invalid dictionary header, expected: %d\n",
    405			num_entries_token);
    406		return -EINVAL;
    407	}
    408
    409	*num_entries = le32_to_cpu(tuple->value);
    410	*dict = devm_kcalloc(comp->card->dev, *num_entries, entry_size, GFP_KERNEL);
    411	if (!*dict)
    412		return -ENOMEM;
    413
    414	return 0;
    415}
    416
    417static int
    418parse_dictionary_entries(struct snd_soc_component *comp,
    419			 struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
    420			 void *dict, u32 num_entries, size_t entry_size,
    421			 u32 entry_id_token,
    422			 const struct avs_tplg_token_parser *parsers, size_t num_parsers)
    423{
    424	void *pos = dict;
    425	int i;
    426
    427	for (i = 0; i < num_entries; i++) {
    428		u32 esize;
    429		int ret;
    430
    431		ret = avs_tplg_vendor_entry_size(tuples, block_size,
    432						 entry_id_token, &esize);
    433		if (ret)
    434			return ret;
    435
    436		ret = avs_parse_tokens(comp, pos, parsers, num_parsers, tuples, esize);
    437		if (ret < 0) {
    438			dev_err(comp->dev, "parse entry: %d of type: %d failed: %d\n",
    439				i, entry_id_token, ret);
    440			return ret;
    441		}
    442
    443		pos += entry_size;
    444		block_size -= esize;
    445		tuples = avs_tplg_vendor_array_at(tuples, esize);
    446	}
    447
    448	return 0;
    449}
    450
    451static int parse_dictionary(struct snd_soc_component *comp,
    452			    struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
    453			    void **dict, u32 *num_entries, size_t entry_size,
    454			    u32 num_entries_token, u32 entry_id_token,
    455			    const struct avs_tplg_token_parser *parsers, size_t num_parsers)
    456{
    457	int ret;
    458
    459	ret = parse_dictionary_header(comp, tuples, dict, num_entries,
    460				      entry_size, num_entries_token);
    461	if (ret)
    462		return ret;
    463
    464	block_size -= le32_to_cpu(tuples->size);
    465	/* With header parsed, move on to parsing entries. */
    466	tuples = avs_tplg_vendor_array_next(tuples);
    467
    468	return parse_dictionary_entries(comp, tuples, block_size, *dict,
    469					*num_entries, entry_size,
    470					entry_id_token, parsers, num_parsers);
    471}
    472
    473static const struct avs_tplg_token_parser library_parsers[] = {
    474	{
    475		.token = AVS_TKN_LIBRARY_NAME_STRING,
    476		.type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
    477		.offset = offsetof(struct avs_tplg_library, name),
    478		.parse = avs_parse_string_token,
    479	},
    480};
    481
    482static int avs_tplg_parse_libraries(struct snd_soc_component *comp,
    483				    struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
    484{
    485	struct avs_soc_component *acomp = to_avs_soc_component(comp);
    486	struct avs_tplg *tplg = acomp->tplg;
    487
    488	return parse_dictionary(comp, tuples, block_size, (void **)&tplg->libs,
    489				&tplg->num_libs, sizeof(*tplg->libs),
    490				AVS_TKN_MANIFEST_NUM_LIBRARIES_U32,
    491				AVS_TKN_LIBRARY_ID_U32,
    492				library_parsers, ARRAY_SIZE(library_parsers));
    493}
    494
    495static const struct avs_tplg_token_parser audio_format_parsers[] = {
    496	{
    497		.token = AVS_TKN_AFMT_SAMPLE_RATE_U32,
    498		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    499		.offset = offsetof(struct avs_audio_format, sampling_freq),
    500		.parse = avs_parse_word_token,
    501	},
    502	{
    503		.token = AVS_TKN_AFMT_BIT_DEPTH_U32,
    504		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    505		.offset = offsetof(struct avs_audio_format, bit_depth),
    506		.parse = avs_parse_word_token,
    507	},
    508	{
    509		.token = AVS_TKN_AFMT_CHANNEL_MAP_U32,
    510		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    511		.offset = offsetof(struct avs_audio_format, channel_map),
    512		.parse = avs_parse_word_token,
    513	},
    514	{
    515		.token = AVS_TKN_AFMT_CHANNEL_CFG_U32,
    516		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    517		.offset = offsetof(struct avs_audio_format, channel_config),
    518		.parse = avs_parse_word_token,
    519	},
    520	{
    521		.token = AVS_TKN_AFMT_INTERLEAVING_U32,
    522		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    523		.offset = offsetof(struct avs_audio_format, interleaving),
    524		.parse = avs_parse_word_token,
    525	},
    526	{
    527		.token = AVS_TKN_AFMT_NUM_CHANNELS_U32,
    528		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    529		.offset = AVS_TKN_AFMT_NUM_CHANNELS_U32,
    530		.parse = parse_audio_format_bitfield,
    531	},
    532	{
    533		.token = AVS_TKN_AFMT_VALID_BIT_DEPTH_U32,
    534		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    535		.offset = AVS_TKN_AFMT_VALID_BIT_DEPTH_U32,
    536		.parse = parse_audio_format_bitfield,
    537	},
    538	{
    539		.token = AVS_TKN_AFMT_SAMPLE_TYPE_U32,
    540		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    541		.offset = AVS_TKN_AFMT_SAMPLE_TYPE_U32,
    542		.parse = parse_audio_format_bitfield,
    543	},
    544};
    545
    546static int avs_tplg_parse_audio_formats(struct snd_soc_component *comp,
    547					struct snd_soc_tplg_vendor_array *tuples,
    548					u32 block_size)
    549{
    550	struct avs_soc_component *acomp = to_avs_soc_component(comp);
    551	struct avs_tplg *tplg = acomp->tplg;
    552
    553	return parse_dictionary(comp, tuples, block_size, (void **)&tplg->fmts,
    554				&tplg->num_fmts, sizeof(*tplg->fmts),
    555				AVS_TKN_MANIFEST_NUM_AFMTS_U32,
    556				AVS_TKN_AFMT_ID_U32,
    557				audio_format_parsers, ARRAY_SIZE(audio_format_parsers));
    558}
    559
    560static const struct avs_tplg_token_parser modcfg_base_parsers[] = {
    561	{
    562		.token = AVS_TKN_MODCFG_BASE_CPC_U32,
    563		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    564		.offset = offsetof(struct avs_tplg_modcfg_base, cpc),
    565		.parse = avs_parse_word_token,
    566	},
    567	{
    568		.token = AVS_TKN_MODCFG_BASE_IBS_U32,
    569		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    570		.offset = offsetof(struct avs_tplg_modcfg_base, ibs),
    571		.parse = avs_parse_word_token,
    572	},
    573	{
    574		.token = AVS_TKN_MODCFG_BASE_OBS_U32,
    575		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    576		.offset = offsetof(struct avs_tplg_modcfg_base, obs),
    577		.parse = avs_parse_word_token,
    578	},
    579	{
    580		.token = AVS_TKN_MODCFG_BASE_PAGES_U32,
    581		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    582		.offset = offsetof(struct avs_tplg_modcfg_base, is_pages),
    583		.parse = avs_parse_word_token,
    584	},
    585};
    586
    587static int avs_tplg_parse_modcfgs_base(struct snd_soc_component *comp,
    588				       struct snd_soc_tplg_vendor_array *tuples,
    589				       u32 block_size)
    590{
    591	struct avs_soc_component *acomp = to_avs_soc_component(comp);
    592	struct avs_tplg *tplg = acomp->tplg;
    593
    594	return parse_dictionary(comp, tuples, block_size, (void **)&tplg->modcfgs_base,
    595				&tplg->num_modcfgs_base, sizeof(*tplg->modcfgs_base),
    596				AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32,
    597				AVS_TKN_MODCFG_BASE_ID_U32,
    598				modcfg_base_parsers, ARRAY_SIZE(modcfg_base_parsers));
    599}
    600
    601static const struct avs_tplg_token_parser modcfg_ext_parsers[] = {
    602	{
    603		.token = AVS_TKN_MODCFG_EXT_TYPE_UUID,
    604		.type = SND_SOC_TPLG_TUPLE_TYPE_UUID,
    605		.offset = offsetof(struct avs_tplg_modcfg_ext, type),
    606		.parse = avs_parse_uuid_token,
    607	},
    608	{
    609		.token = AVS_TKN_MODCFG_CPR_OUT_AFMT_ID_U32,
    610		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    611		.offset = offsetof(struct avs_tplg_modcfg_ext, copier.out_fmt),
    612		.parse = avs_parse_audio_format_ptr,
    613	},
    614	{
    615		.token = AVS_TKN_MODCFG_CPR_FEATURE_MASK_U32,
    616		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    617		.offset = offsetof(struct avs_tplg_modcfg_ext, copier.feature_mask),
    618		.parse = avs_parse_word_token,
    619	},
    620	{
    621		.token = AVS_TKN_MODCFG_CPR_VINDEX_U8,
    622		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
    623		.offset = offsetof(struct avs_tplg_modcfg_ext, copier.vindex),
    624		.parse = avs_parse_byte_token,
    625	},
    626	{
    627		.token = AVS_TKN_MODCFG_CPR_DMA_TYPE_U32,
    628		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    629		.offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_type),
    630		.parse = avs_parse_word_token,
    631	},
    632	{
    633		.token = AVS_TKN_MODCFG_CPR_DMABUFF_SIZE_U32,
    634		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    635		.offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_buffer_size),
    636		.parse = avs_parse_word_token,
    637	},
    638	{
    639		.token = AVS_TKN_MODCFG_CPR_BLOB_FMT_ID_U32,
    640		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    641		.offset = offsetof(struct avs_tplg_modcfg_ext, copier.blob_fmt),
    642		.parse = avs_parse_audio_format_ptr,
    643	},
    644	{
    645		.token = AVS_TKN_MODCFG_MICSEL_OUT_AFMT_ID_U32,
    646		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    647		.offset = offsetof(struct avs_tplg_modcfg_ext, micsel.out_fmt),
    648		.parse = avs_parse_audio_format_ptr,
    649	},
    650	{
    651		.token = AVS_TKN_MODCFG_INTELWOV_CPC_LP_MODE_U32,
    652		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    653		.offset = offsetof(struct avs_tplg_modcfg_ext, wov.cpc_lp_mode),
    654		.parse = avs_parse_word_token,
    655	},
    656	{
    657		.token = AVS_TKN_MODCFG_SRC_OUT_FREQ_U32,
    658		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    659		.offset = offsetof(struct avs_tplg_modcfg_ext, src.out_freq),
    660		.parse = avs_parse_word_token,
    661	},
    662	{
    663		.token = AVS_TKN_MODCFG_MUX_REF_AFMT_ID_U32,
    664		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    665		.offset = offsetof(struct avs_tplg_modcfg_ext, mux.ref_fmt),
    666		.parse = avs_parse_audio_format_ptr,
    667	},
    668	{
    669		.token = AVS_TKN_MODCFG_MUX_OUT_AFMT_ID_U32,
    670		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    671		.offset = offsetof(struct avs_tplg_modcfg_ext, mux.out_fmt),
    672		.parse = avs_parse_audio_format_ptr,
    673	},
    674	{
    675		.token = AVS_TKN_MODCFG_AEC_REF_AFMT_ID_U32,
    676		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    677		.offset = offsetof(struct avs_tplg_modcfg_ext, aec.ref_fmt),
    678		.parse = avs_parse_audio_format_ptr,
    679	},
    680	{
    681		.token = AVS_TKN_MODCFG_AEC_OUT_AFMT_ID_U32,
    682		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    683		.offset = offsetof(struct avs_tplg_modcfg_ext, aec.out_fmt),
    684		.parse = avs_parse_audio_format_ptr,
    685	},
    686	{
    687		.token = AVS_TKN_MODCFG_AEC_CPC_LP_MODE_U32,
    688		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    689		.offset = offsetof(struct avs_tplg_modcfg_ext, aec.cpc_lp_mode),
    690		.parse = avs_parse_word_token,
    691	},
    692	{
    693		.token = AVS_TKN_MODCFG_ASRC_OUT_FREQ_U32,
    694		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    695		.offset = offsetof(struct avs_tplg_modcfg_ext, asrc.out_freq),
    696		.parse = avs_parse_word_token,
    697	},
    698	{
    699		.token = AVS_TKN_MODCFG_ASRC_MODE_U8,
    700		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
    701		.offset = offsetof(struct avs_tplg_modcfg_ext, asrc.mode),
    702		.parse = avs_parse_byte_token,
    703	},
    704	{
    705		.token = AVS_TKN_MODCFG_ASRC_DISABLE_JITTER_U8,
    706		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
    707		.offset = offsetof(struct avs_tplg_modcfg_ext, asrc.disable_jitter_buffer),
    708		.parse = avs_parse_byte_token,
    709	},
    710	{
    711		.token = AVS_TKN_MODCFG_UPDOWN_MIX_OUT_CHAN_CFG_U32,
    712		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    713		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.out_channel_config),
    714		.parse = avs_parse_word_token,
    715	},
    716	{
    717		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_SELECT_U32,
    718		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    719		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients_select),
    720		.parse = avs_parse_word_token,
    721	},
    722	{
    723		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_0_S32,
    724		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    725		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[0]),
    726		.parse = avs_parse_word_token,
    727	},
    728	{
    729		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_1_S32,
    730		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    731		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[1]),
    732		.parse = avs_parse_word_token,
    733	},
    734	{
    735		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_2_S32,
    736		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    737		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[2]),
    738		.parse = avs_parse_word_token,
    739	},
    740	{
    741		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_3_S32,
    742		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    743		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[3]),
    744		.parse = avs_parse_word_token,
    745	},
    746	{
    747		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_4_S32,
    748		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    749		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[4]),
    750		.parse = avs_parse_word_token,
    751	},
    752	{
    753		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_5_S32,
    754		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    755		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[5]),
    756		.parse = avs_parse_word_token,
    757	},
    758	{
    759		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_6_S32,
    760		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    761		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[6]),
    762		.parse = avs_parse_word_token,
    763	},
    764	{
    765		.token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_7_S32,
    766		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    767		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[7]),
    768		.parse = avs_parse_word_token,
    769	},
    770	{
    771		.token = AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32,
    772		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    773		.offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.channel_map),
    774		.parse = avs_parse_word_token,
    775	},
    776	{
    777		.token = AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16,
    778		.type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
    779		.offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_input_pins),
    780		.parse = avs_parse_short_token,
    781	},
    782	{
    783		.token = AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16,
    784		.type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
    785		.offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_output_pins),
    786		.parse = avs_parse_short_token,
    787	},
    788};
    789
    790static const struct avs_tplg_token_parser pin_format_parsers[] = {
    791	{
    792		.token = AVS_TKN_PIN_FMT_INDEX_U32,
    793		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    794		.offset = offsetof(struct avs_tplg_pin_format, pin_index),
    795		.parse = avs_parse_word_token,
    796	},
    797	{
    798		.token = AVS_TKN_PIN_FMT_IOBS_U32,
    799		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    800		.offset = offsetof(struct avs_tplg_pin_format, iobs),
    801		.parse = avs_parse_word_token,
    802	},
    803	{
    804		.token = AVS_TKN_PIN_FMT_AFMT_ID_U32,
    805		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    806		.offset = offsetof(struct avs_tplg_pin_format, fmt),
    807		.parse = avs_parse_audio_format_ptr,
    808	},
    809};
    810
    811static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp,
    812				     struct avs_tplg_modcfg_ext *cfg,
    813				     struct snd_soc_tplg_vendor_array *tuples,
    814				     u32 block_size)
    815{
    816	u32 esize;
    817	int ret;
    818
    819	/* See where pin block starts. */
    820	ret = avs_tplg_vendor_entry_size(tuples, block_size,
    821					 AVS_TKN_PIN_FMT_INDEX_U32, &esize);
    822	if (ret)
    823		return ret;
    824
    825	ret = avs_parse_tokens(comp, cfg, modcfg_ext_parsers,
    826			       ARRAY_SIZE(modcfg_ext_parsers), tuples, esize);
    827	if (ret)
    828		return ret;
    829
    830	block_size -= esize;
    831	/* Parse trailing in/out pin formats if any. */
    832	if (block_size) {
    833		struct avs_tplg_pin_format *pins;
    834		u32 num_pins;
    835
    836		num_pins = cfg->generic.num_input_pins + cfg->generic.num_output_pins;
    837		if (!num_pins)
    838			return -EINVAL;
    839
    840		pins = devm_kcalloc(comp->card->dev, num_pins, sizeof(*pins), GFP_KERNEL);
    841		if (!pins)
    842			return -ENOMEM;
    843
    844		tuples = avs_tplg_vendor_array_at(tuples, esize);
    845		ret = parse_dictionary_entries(comp, tuples, block_size,
    846					       pins, num_pins, sizeof(*pins),
    847					       AVS_TKN_PIN_FMT_INDEX_U32,
    848					       pin_format_parsers,
    849					       ARRAY_SIZE(pin_format_parsers));
    850		if (ret)
    851			return ret;
    852		cfg->generic.pin_fmts = pins;
    853	}
    854
    855	return 0;
    856}
    857
    858static int avs_tplg_parse_modcfgs_ext(struct snd_soc_component *comp,
    859				      struct snd_soc_tplg_vendor_array *tuples,
    860				      u32 block_size)
    861{
    862	struct avs_soc_component *acomp = to_avs_soc_component(comp);
    863	struct avs_tplg *tplg = acomp->tplg;
    864	int ret, i;
    865
    866	ret = parse_dictionary_header(comp, tuples, (void **)&tplg->modcfgs_ext,
    867				      &tplg->num_modcfgs_ext,
    868				      sizeof(*tplg->modcfgs_ext),
    869				      AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32);
    870	if (ret)
    871		return ret;
    872
    873	block_size -= le32_to_cpu(tuples->size);
    874	/* With header parsed, move on to parsing entries. */
    875	tuples = avs_tplg_vendor_array_next(tuples);
    876
    877	for (i = 0; i < tplg->num_modcfgs_ext; i++) {
    878		struct avs_tplg_modcfg_ext *cfg = &tplg->modcfgs_ext[i];
    879		u32 esize;
    880
    881		ret = avs_tplg_vendor_entry_size(tuples, block_size,
    882						 AVS_TKN_MODCFG_EXT_ID_U32, &esize);
    883		if (ret)
    884			return ret;
    885
    886		ret = avs_tplg_parse_modcfg_ext(comp, cfg, tuples, esize);
    887		if (ret)
    888			return ret;
    889
    890		block_size -= esize;
    891		tuples = avs_tplg_vendor_array_at(tuples, esize);
    892	}
    893
    894	return 0;
    895}
    896
    897static const struct avs_tplg_token_parser pplcfg_parsers[] = {
    898	{
    899		.token = AVS_TKN_PPLCFG_REQ_SIZE_U16,
    900		.type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
    901		.offset = offsetof(struct avs_tplg_pplcfg, req_size),
    902		.parse = avs_parse_short_token,
    903	},
    904	{
    905		.token = AVS_TKN_PPLCFG_PRIORITY_U8,
    906		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
    907		.offset = offsetof(struct avs_tplg_pplcfg, priority),
    908		.parse = avs_parse_byte_token,
    909	},
    910	{
    911		.token = AVS_TKN_PPLCFG_LOW_POWER_BOOL,
    912		.type = SND_SOC_TPLG_TUPLE_TYPE_BOOL,
    913		.offset = offsetof(struct avs_tplg_pplcfg, lp),
    914		.parse = avs_parse_bool_token,
    915	},
    916	{
    917		.token = AVS_TKN_PPLCFG_ATTRIBUTES_U16,
    918		.type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
    919		.offset = offsetof(struct avs_tplg_pplcfg, attributes),
    920		.parse = avs_parse_short_token,
    921	},
    922	{
    923		.token = AVS_TKN_PPLCFG_TRIGGER_U32,
    924		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    925		.offset = offsetof(struct avs_tplg_pplcfg, trigger),
    926		.parse = avs_parse_word_token,
    927	},
    928};
    929
    930static int avs_tplg_parse_pplcfgs(struct snd_soc_component *comp,
    931				  struct snd_soc_tplg_vendor_array *tuples,
    932				  u32 block_size)
    933{
    934	struct avs_soc_component *acomp = to_avs_soc_component(comp);
    935	struct avs_tplg *tplg = acomp->tplg;
    936
    937	return parse_dictionary(comp, tuples, block_size, (void **)&tplg->pplcfgs,
    938				&tplg->num_pplcfgs, sizeof(*tplg->pplcfgs),
    939				AVS_TKN_MANIFEST_NUM_PPLCFGS_U32,
    940				AVS_TKN_PPLCFG_ID_U32,
    941				pplcfg_parsers, ARRAY_SIZE(pplcfg_parsers));
    942}
    943
    944static const struct avs_tplg_token_parser binding_parsers[] = {
    945	{
    946		.token = AVS_TKN_BINDING_TARGET_TPLG_NAME_STRING,
    947		.type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
    948		.offset = offsetof(struct avs_tplg_binding, target_tplg_name),
    949		.parse = parse_link_formatted_string,
    950	},
    951	{
    952		.token = AVS_TKN_BINDING_TARGET_PATH_TMPL_ID_U32,
    953		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    954		.offset = offsetof(struct avs_tplg_binding, target_path_tmpl_id),
    955		.parse = avs_parse_word_token,
    956	},
    957	{
    958		.token = AVS_TKN_BINDING_TARGET_PPL_ID_U32,
    959		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    960		.offset = offsetof(struct avs_tplg_binding, target_ppl_id),
    961		.parse = avs_parse_word_token,
    962	},
    963	{
    964		.token = AVS_TKN_BINDING_TARGET_MOD_ID_U32,
    965		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    966		.offset = offsetof(struct avs_tplg_binding, target_mod_id),
    967		.parse = avs_parse_word_token,
    968	},
    969	{
    970		.token = AVS_TKN_BINDING_TARGET_MOD_PIN_U8,
    971		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
    972		.offset = offsetof(struct avs_tplg_binding, target_mod_pin),
    973		.parse = avs_parse_byte_token,
    974	},
    975	{
    976		.token = AVS_TKN_BINDING_MOD_ID_U32,
    977		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
    978		.offset = offsetof(struct avs_tplg_binding, mod_id),
    979		.parse = avs_parse_word_token,
    980	},
    981	{
    982		.token = AVS_TKN_BINDING_MOD_PIN_U8,
    983		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
    984		.offset = offsetof(struct avs_tplg_binding, mod_pin),
    985		.parse = avs_parse_byte_token,
    986	},
    987	{
    988		.token = AVS_TKN_BINDING_IS_SINK_U8,
    989		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
    990		.offset = offsetof(struct avs_tplg_binding, is_sink),
    991		.parse = avs_parse_byte_token,
    992	},
    993};
    994
    995static int avs_tplg_parse_bindings(struct snd_soc_component *comp,
    996				   struct snd_soc_tplg_vendor_array *tuples,
    997				   u32 block_size)
    998{
    999	struct avs_soc_component *acomp = to_avs_soc_component(comp);
   1000	struct avs_tplg *tplg = acomp->tplg;
   1001
   1002	return parse_dictionary(comp, tuples, block_size, (void **)&tplg->bindings,
   1003				&tplg->num_bindings, sizeof(*tplg->bindings),
   1004				AVS_TKN_MANIFEST_NUM_BINDINGS_U32,
   1005				AVS_TKN_BINDING_ID_U32,
   1006				binding_parsers, ARRAY_SIZE(binding_parsers));
   1007}
   1008
   1009static const struct avs_tplg_token_parser module_parsers[] = {
   1010	{
   1011		.token = AVS_TKN_MOD_ID_U32,
   1012		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1013		.offset = offsetof(struct avs_tplg_module, id),
   1014		.parse = avs_parse_word_token,
   1015	},
   1016	{
   1017		.token = AVS_TKN_MOD_MODCFG_BASE_ID_U32,
   1018		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1019		.offset = offsetof(struct avs_tplg_module, cfg_base),
   1020		.parse = avs_parse_modcfg_base_ptr,
   1021	},
   1022	{
   1023		.token = AVS_TKN_MOD_IN_AFMT_ID_U32,
   1024		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1025		.offset = offsetof(struct avs_tplg_module, in_fmt),
   1026		.parse = avs_parse_audio_format_ptr,
   1027	},
   1028	{
   1029		.token = AVS_TKN_MOD_CORE_ID_U8,
   1030		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
   1031		.offset = offsetof(struct avs_tplg_module, core_id),
   1032		.parse = avs_parse_byte_token,
   1033	},
   1034	{
   1035		.token = AVS_TKN_MOD_PROC_DOMAIN_U8,
   1036		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
   1037		.offset = offsetof(struct avs_tplg_module, domain),
   1038		.parse = avs_parse_byte_token,
   1039	},
   1040	{
   1041		.token = AVS_TKN_MOD_MODCFG_EXT_ID_U32,
   1042		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1043		.offset = offsetof(struct avs_tplg_module, cfg_ext),
   1044		.parse = avs_parse_modcfg_ext_ptr,
   1045	},
   1046};
   1047
   1048static struct avs_tplg_module *
   1049avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline *owner,
   1050		       struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
   1051{
   1052	struct avs_tplg_module *module;
   1053	int ret;
   1054
   1055	module = devm_kzalloc(comp->card->dev, sizeof(*module), GFP_KERNEL);
   1056	if (!module)
   1057		return ERR_PTR(-ENOMEM);
   1058
   1059	ret = avs_parse_tokens(comp, module, module_parsers,
   1060			       ARRAY_SIZE(module_parsers), tuples, block_size);
   1061	if (ret < 0)
   1062		return ERR_PTR(ret);
   1063
   1064	module->owner = owner;
   1065	INIT_LIST_HEAD(&module->node);
   1066
   1067	return module;
   1068}
   1069
   1070static const struct avs_tplg_token_parser pipeline_parsers[] = {
   1071	{
   1072		.token = AVS_TKN_PPL_ID_U32,
   1073		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1074		.offset = offsetof(struct avs_tplg_pipeline, id),
   1075		.parse = avs_parse_word_token,
   1076	},
   1077	{
   1078		.token = AVS_TKN_PPL_PPLCFG_ID_U32,
   1079		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1080		.offset = offsetof(struct avs_tplg_pipeline, cfg),
   1081		.parse = avs_parse_pplcfg_ptr,
   1082	},
   1083	{
   1084		.token = AVS_TKN_PPL_NUM_BINDING_IDS_U32,
   1085		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1086		.offset = offsetof(struct avs_tplg_pipeline, num_bindings),
   1087		.parse = avs_parse_word_token,
   1088	},
   1089};
   1090
   1091static const struct avs_tplg_token_parser bindings_parsers[] = {
   1092	{
   1093		.token = AVS_TKN_PPL_BINDING_ID_U32,
   1094		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1095		.offset = 0, /* to treat pipeline->bindings as dictionary */
   1096		.parse = avs_parse_binding_ptr,
   1097	},
   1098};
   1099
   1100static struct avs_tplg_pipeline *
   1101avs_tplg_pipeline_create(struct snd_soc_component *comp, struct avs_tplg_path *owner,
   1102			 struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
   1103{
   1104	struct avs_tplg_pipeline *pipeline;
   1105	u32 modblk_size, offset;
   1106	int ret;
   1107
   1108	pipeline = devm_kzalloc(comp->card->dev, sizeof(*pipeline), GFP_KERNEL);
   1109	if (!pipeline)
   1110		return ERR_PTR(-ENOMEM);
   1111
   1112	pipeline->owner = owner;
   1113	INIT_LIST_HEAD(&pipeline->mod_list);
   1114
   1115	/* Pipeline header MUST be followed by at least one module. */
   1116	ret = avs_tplg_vendor_array_lookup(tuples, block_size,
   1117					   AVS_TKN_MOD_ID_U32, &offset);
   1118	if (!ret && !offset)
   1119		ret = -EINVAL;
   1120	if (ret)
   1121		return ERR_PTR(ret);
   1122
   1123	/* Process header which precedes module sections. */
   1124	ret = avs_parse_tokens(comp, pipeline, pipeline_parsers,
   1125			       ARRAY_SIZE(pipeline_parsers), tuples, offset);
   1126	if (ret < 0)
   1127		return ERR_PTR(ret);
   1128
   1129	block_size -= offset;
   1130	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1131
   1132	/* Optionally, binding sections follow module ones. */
   1133	ret = avs_tplg_vendor_array_lookup_next(tuples, block_size,
   1134						AVS_TKN_PPL_BINDING_ID_U32, &offset);
   1135	if (ret) {
   1136		if (ret != -ENOENT)
   1137			return ERR_PTR(ret);
   1138
   1139		/* Does header information match actual block layout? */
   1140		if (pipeline->num_bindings)
   1141			return ERR_PTR(-EINVAL);
   1142
   1143		modblk_size = block_size;
   1144	} else {
   1145		pipeline->bindings = devm_kcalloc(comp->card->dev, pipeline->num_bindings,
   1146						  sizeof(*pipeline->bindings), GFP_KERNEL);
   1147		if (!pipeline->bindings)
   1148			return ERR_PTR(-ENOMEM);
   1149
   1150		modblk_size = offset;
   1151	}
   1152
   1153	block_size -= modblk_size;
   1154	do {
   1155		struct avs_tplg_module *module;
   1156		u32 esize;
   1157
   1158		ret = avs_tplg_vendor_entry_size(tuples, modblk_size,
   1159						 AVS_TKN_MOD_ID_U32, &esize);
   1160		if (ret)
   1161			return ERR_PTR(ret);
   1162
   1163		module = avs_tplg_module_create(comp, pipeline, tuples, esize);
   1164		if (IS_ERR(module)) {
   1165			dev_err(comp->dev, "parse module failed: %ld\n",
   1166				PTR_ERR(module));
   1167			return ERR_CAST(module);
   1168		}
   1169
   1170		list_add_tail(&module->node, &pipeline->mod_list);
   1171		modblk_size -= esize;
   1172		tuples = avs_tplg_vendor_array_at(tuples, esize);
   1173	} while (modblk_size > 0);
   1174
   1175	/* What's left is optional range of bindings. */
   1176	ret = parse_dictionary_entries(comp, tuples, block_size, pipeline->bindings,
   1177				       pipeline->num_bindings, sizeof(*pipeline->bindings),
   1178				       AVS_TKN_PPL_BINDING_ID_U32,
   1179				       bindings_parsers, ARRAY_SIZE(bindings_parsers));
   1180	if (ret)
   1181		return ERR_PTR(ret);
   1182
   1183	return pipeline;
   1184}
   1185
   1186static const struct avs_tplg_token_parser path_parsers[] = {
   1187	{
   1188		.token = AVS_TKN_PATH_ID_U32,
   1189		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1190		.offset = offsetof(struct avs_tplg_path, id),
   1191		.parse = avs_parse_word_token,
   1192	},
   1193	{
   1194		.token = AVS_TKN_PATH_FE_FMT_ID_U32,
   1195		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1196		.offset = offsetof(struct avs_tplg_path, fe_fmt),
   1197		.parse = avs_parse_audio_format_ptr,
   1198	},
   1199	{
   1200		.token = AVS_TKN_PATH_BE_FMT_ID_U32,
   1201		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1202		.offset = offsetof(struct avs_tplg_path, be_fmt),
   1203		.parse = avs_parse_audio_format_ptr,
   1204	},
   1205};
   1206
   1207static struct avs_tplg_path *
   1208avs_tplg_path_create(struct snd_soc_component *comp, struct avs_tplg_path_template *owner,
   1209		     struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
   1210		     const struct avs_tplg_token_parser *parsers, u32 num_parsers)
   1211{
   1212	struct avs_tplg_pipeline *pipeline;
   1213	struct avs_tplg_path *path;
   1214	u32 offset;
   1215	int ret;
   1216
   1217	path = devm_kzalloc(comp->card->dev, sizeof(*path), GFP_KERNEL);
   1218	if (!path)
   1219		return ERR_PTR(-ENOMEM);
   1220
   1221	path->owner = owner;
   1222	INIT_LIST_HEAD(&path->ppl_list);
   1223	INIT_LIST_HEAD(&path->node);
   1224
   1225	/* Path header MAY be followed by one or more pipelines. */
   1226	ret = avs_tplg_vendor_array_lookup(tuples, block_size,
   1227					   AVS_TKN_PPL_ID_U32, &offset);
   1228	if (ret == -ENOENT)
   1229		offset = block_size;
   1230	else if (ret)
   1231		return ERR_PTR(ret);
   1232	else if (!offset)
   1233		return ERR_PTR(-EINVAL);
   1234
   1235	/* Process header which precedes pipeline sections. */
   1236	ret = avs_parse_tokens(comp, path, parsers, num_parsers, tuples, offset);
   1237	if (ret < 0)
   1238		return ERR_PTR(ret);
   1239
   1240	block_size -= offset;
   1241	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1242	while (block_size > 0) {
   1243		u32 esize;
   1244
   1245		ret = avs_tplg_vendor_entry_size(tuples, block_size,
   1246						 AVS_TKN_PPL_ID_U32, &esize);
   1247		if (ret)
   1248			return ERR_PTR(ret);
   1249
   1250		pipeline = avs_tplg_pipeline_create(comp, path, tuples, esize);
   1251		if (IS_ERR(pipeline)) {
   1252			dev_err(comp->dev, "parse pipeline failed: %ld\n",
   1253				PTR_ERR(pipeline));
   1254			return ERR_CAST(pipeline);
   1255		}
   1256
   1257		list_add_tail(&pipeline->node, &path->ppl_list);
   1258		block_size -= esize;
   1259		tuples = avs_tplg_vendor_array_at(tuples, esize);
   1260	}
   1261
   1262	return path;
   1263}
   1264
   1265static const struct avs_tplg_token_parser path_tmpl_parsers[] = {
   1266	{
   1267		.token = AVS_TKN_PATH_TMPL_ID_U32,
   1268		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1269		.offset = offsetof(struct avs_tplg_path_template, id),
   1270		.parse = avs_parse_word_token,
   1271	},
   1272};
   1273
   1274static int parse_path_template(struct snd_soc_component *comp,
   1275			       struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
   1276			       struct avs_tplg_path_template *template,
   1277			       const struct avs_tplg_token_parser *tmpl_tokens, u32 num_tmpl_tokens,
   1278			       const struct avs_tplg_token_parser *path_tokens, u32 num_path_tokens)
   1279{
   1280	struct avs_tplg_path *path;
   1281	u32 offset;
   1282	int ret;
   1283
   1284	/* Path template header MUST be followed by at least one path variant. */
   1285	ret = avs_tplg_vendor_array_lookup(tuples, block_size,
   1286					   AVS_TKN_PATH_ID_U32, &offset);
   1287	if (ret)
   1288		return ret;
   1289
   1290	/* Process header which precedes path variants sections. */
   1291	ret = avs_parse_tokens(comp, template, tmpl_tokens, num_tmpl_tokens, tuples, offset);
   1292	if (ret < 0)
   1293		return ret;
   1294
   1295	block_size -= offset;
   1296	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1297	do {
   1298		u32 esize;
   1299
   1300		ret = avs_tplg_vendor_entry_size(tuples, block_size,
   1301						 AVS_TKN_PATH_ID_U32, &esize);
   1302		if (ret)
   1303			return ret;
   1304
   1305		path = avs_tplg_path_create(comp, template, tuples, esize, path_tokens,
   1306					    num_path_tokens);
   1307		if (IS_ERR(path)) {
   1308			dev_err(comp->dev, "parse path failed: %ld\n", PTR_ERR(path));
   1309			return PTR_ERR(path);
   1310		}
   1311
   1312		list_add_tail(&path->node, &template->path_list);
   1313		block_size -= esize;
   1314		tuples = avs_tplg_vendor_array_at(tuples, esize);
   1315	} while (block_size > 0);
   1316
   1317	return 0;
   1318}
   1319
   1320static struct avs_tplg_path_template *
   1321avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *owner,
   1322			      struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
   1323{
   1324	struct avs_tplg_path_template *template;
   1325	int ret;
   1326
   1327	template = devm_kzalloc(comp->card->dev, sizeof(*template), GFP_KERNEL);
   1328	if (!template)
   1329		return ERR_PTR(-ENOMEM);
   1330
   1331	template->owner = owner; /* Used to access component tplg is assigned to. */
   1332	INIT_LIST_HEAD(&template->path_list);
   1333	INIT_LIST_HEAD(&template->node);
   1334
   1335	ret = parse_path_template(comp, tuples, block_size, template, path_tmpl_parsers,
   1336				  ARRAY_SIZE(path_tmpl_parsers), path_parsers,
   1337				  ARRAY_SIZE(path_parsers));
   1338	if (ret)
   1339		return ERR_PTR(ret);
   1340
   1341	return template;
   1342}
   1343
   1344static int avs_route_load(struct snd_soc_component *comp, int index,
   1345			  struct snd_soc_dapm_route *route)
   1346{
   1347	struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
   1348	size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
   1349	char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
   1350	u32 port;
   1351
   1352	/* See parse_link_formatted_string() for dynamic naming when(s). */
   1353	if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
   1354		port = __ffs(mach->mach_params.i2s_link_mask);
   1355
   1356		snprintf(buf, len, route->source, port);
   1357		strncpy((char *)route->source, buf, len);
   1358		snprintf(buf, len, route->sink, port);
   1359		strncpy((char *)route->sink, buf, len);
   1360		if (route->control) {
   1361			snprintf(buf, len, route->control, port);
   1362			strncpy((char *)route->control, buf, len);
   1363		}
   1364	}
   1365
   1366	return 0;
   1367}
   1368
   1369static int avs_widget_load(struct snd_soc_component *comp, int index,
   1370			   struct snd_soc_dapm_widget *w,
   1371			   struct snd_soc_tplg_dapm_widget *dw)
   1372{
   1373	struct snd_soc_acpi_mach *mach;
   1374	struct avs_tplg_path_template *template;
   1375	struct avs_soc_component *acomp = to_avs_soc_component(comp);
   1376	struct avs_tplg *tplg;
   1377
   1378	if (!le32_to_cpu(dw->priv.size))
   1379		return 0;
   1380
   1381	tplg = acomp->tplg;
   1382	mach = dev_get_platdata(comp->card->dev);
   1383
   1384	/* See parse_link_formatted_string() for dynamic naming when(s). */
   1385	if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
   1386		kfree(w->name);
   1387		/* w->name is freed later by soc_tplg_dapm_widget_create() */
   1388		w->name = kasprintf(GFP_KERNEL, dw->name, __ffs(mach->mach_params.i2s_link_mask));
   1389		if (!w->name)
   1390			return -ENOMEM;
   1391	}
   1392
   1393	template = avs_tplg_path_template_create(comp, tplg, dw->priv.array,
   1394						 le32_to_cpu(dw->priv.size));
   1395	if (IS_ERR(template)) {
   1396		dev_err(comp->dev, "widget %s load failed: %ld\n", dw->name,
   1397			PTR_ERR(template));
   1398		return PTR_ERR(template);
   1399	}
   1400
   1401	w->priv = template; /* link path information to widget */
   1402	list_add_tail(&template->node, &tplg->path_tmpl_list);
   1403	return 0;
   1404}
   1405
   1406static int avs_dai_load(struct snd_soc_component *comp, int index,
   1407			struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm,
   1408			struct snd_soc_dai *dai)
   1409{
   1410	if (pcm)
   1411		dai_drv->ops = &avs_dai_fe_ops;
   1412	return 0;
   1413}
   1414
   1415static int avs_link_load(struct snd_soc_component *comp, int index, struct snd_soc_dai_link *link,
   1416			 struct snd_soc_tplg_link_config *cfg)
   1417{
   1418	if (!link->no_pcm) {
   1419		/* Stream control handled by IPCs. */
   1420		link->nonatomic = true;
   1421
   1422		/* Open LINK (BE) pipes last and close them first to prevent xruns. */
   1423		link->trigger[0] = SND_SOC_DPCM_TRIGGER_PRE;
   1424		link->trigger[1] = SND_SOC_DPCM_TRIGGER_PRE;
   1425	}
   1426
   1427	return 0;
   1428}
   1429
   1430static const struct avs_tplg_token_parser manifest_parsers[] = {
   1431	{
   1432		.token = AVS_TKN_MANIFEST_NAME_STRING,
   1433		.type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
   1434		.offset = offsetof(struct avs_tplg, name),
   1435		.parse = parse_link_formatted_string,
   1436	},
   1437	{
   1438		.token = AVS_TKN_MANIFEST_VERSION_U32,
   1439		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
   1440		.offset = offsetof(struct avs_tplg, version),
   1441		.parse = avs_parse_word_token,
   1442	},
   1443};
   1444
   1445static int avs_manifest(struct snd_soc_component *comp, int index,
   1446			struct snd_soc_tplg_manifest *manifest)
   1447{
   1448	struct snd_soc_tplg_vendor_array *tuples = manifest->priv.array;
   1449	struct avs_soc_component *acomp = to_avs_soc_component(comp);
   1450	size_t remaining = le32_to_cpu(manifest->priv.size);
   1451	u32 offset;
   1452	int ret;
   1453
   1454	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
   1455					   AVS_TKN_MANIFEST_NUM_LIBRARIES_U32, &offset);
   1456	/* Manifest MUST begin with a header. */
   1457	if (!ret && !offset)
   1458		ret = -EINVAL;
   1459	if (ret) {
   1460		dev_err(comp->dev, "incorrect manifest format: %d\n", ret);
   1461		return ret;
   1462	}
   1463
   1464	/* Process header which precedes any of the dictionaries. */
   1465	ret = avs_parse_tokens(comp, acomp->tplg, manifest_parsers,
   1466			       ARRAY_SIZE(manifest_parsers), tuples, offset);
   1467	if (ret < 0)
   1468		return ret;
   1469
   1470	remaining -= offset;
   1471	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1472
   1473	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
   1474					   AVS_TKN_MANIFEST_NUM_AFMTS_U32, &offset);
   1475	if (ret) {
   1476		dev_err(comp->dev, "audio formats lookup failed: %d\n", ret);
   1477		return ret;
   1478	}
   1479
   1480	/* Libraries dictionary. */
   1481	ret = avs_tplg_parse_libraries(comp, tuples, offset);
   1482	if (ret < 0)
   1483		return ret;
   1484
   1485	remaining -= offset;
   1486	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1487
   1488	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
   1489					   AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32, &offset);
   1490	if (ret) {
   1491		dev_err(comp->dev, "modcfgs_base lookup failed: %d\n", ret);
   1492		return ret;
   1493	}
   1494
   1495	/* Audio formats dictionary. */
   1496	ret = avs_tplg_parse_audio_formats(comp, tuples, offset);
   1497	if (ret < 0)
   1498		return ret;
   1499
   1500	remaining -= offset;
   1501	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1502
   1503	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
   1504					   AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32, &offset);
   1505	if (ret) {
   1506		dev_err(comp->dev, "modcfgs_ext lookup failed: %d\n", ret);
   1507		return ret;
   1508	}
   1509
   1510	/* Module configs-base dictionary. */
   1511	ret = avs_tplg_parse_modcfgs_base(comp, tuples, offset);
   1512	if (ret < 0)
   1513		return ret;
   1514
   1515	remaining -= offset;
   1516	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1517
   1518	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
   1519					   AVS_TKN_MANIFEST_NUM_PPLCFGS_U32, &offset);
   1520	if (ret) {
   1521		dev_err(comp->dev, "pplcfgs lookup failed: %d\n", ret);
   1522		return ret;
   1523	}
   1524
   1525	/* Module configs-ext dictionary. */
   1526	ret = avs_tplg_parse_modcfgs_ext(comp, tuples, offset);
   1527	if (ret < 0)
   1528		return ret;
   1529
   1530	remaining -= offset;
   1531	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1532
   1533	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
   1534					   AVS_TKN_MANIFEST_NUM_BINDINGS_U32, &offset);
   1535	if (ret) {
   1536		dev_err(comp->dev, "bindings lookup failed: %d\n", ret);
   1537		return ret;
   1538	}
   1539
   1540	/* Pipeline configs dictionary. */
   1541	ret = avs_tplg_parse_pplcfgs(comp, tuples, offset);
   1542	if (ret < 0)
   1543		return ret;
   1544
   1545	remaining -= offset;
   1546	tuples = avs_tplg_vendor_array_at(tuples, offset);
   1547
   1548	/* Bindings dictionary. */
   1549	return avs_tplg_parse_bindings(comp, tuples, remaining);
   1550}
   1551
   1552static struct snd_soc_tplg_ops avs_tplg_ops = {
   1553	.dapm_route_load	= avs_route_load,
   1554	.widget_load		= avs_widget_load,
   1555	.dai_load		= avs_dai_load,
   1556	.link_load		= avs_link_load,
   1557	.manifest		= avs_manifest,
   1558};
   1559
   1560struct avs_tplg *avs_tplg_new(struct snd_soc_component *comp)
   1561{
   1562	struct avs_tplg *tplg;
   1563
   1564	tplg = devm_kzalloc(comp->card->dev, sizeof(*tplg), GFP_KERNEL);
   1565	if (!tplg)
   1566		return NULL;
   1567
   1568	tplg->comp = comp;
   1569	INIT_LIST_HEAD(&tplg->path_tmpl_list);
   1570
   1571	return tplg;
   1572}
   1573
   1574int avs_load_topology(struct snd_soc_component *comp, const char *filename)
   1575{
   1576	const struct firmware *fw;
   1577	int ret;
   1578
   1579	ret = request_firmware(&fw, filename, comp->dev);
   1580	if (ret < 0) {
   1581		dev_err(comp->dev, "request topology \"%s\" failed: %d\n", filename, ret);
   1582		return ret;
   1583	}
   1584
   1585	ret = snd_soc_tplg_component_load(comp, &avs_tplg_ops, fw);
   1586	if (ret < 0)
   1587		dev_err(comp->dev, "load topology \"%s\" failed: %d\n", filename, ret);
   1588
   1589	release_firmware(fw);
   1590	return ret;
   1591}
   1592
   1593int avs_remove_topology(struct snd_soc_component *comp)
   1594{
   1595	snd_soc_tplg_component_remove(comp);
   1596
   1597	return 0;
   1598}