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