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