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