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