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
avs_tplg_vendor_array_lookup(struct snd_soc_tplg_vendor_array * tuples,u32 block_size,u32 token,u32 * offset)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
avs_tplg_vendor_array_lookup_next(struct snd_soc_tplg_vendor_array * tuples,u32 block_size,u32 token,u32 * offset)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
avs_tplg_vendor_entry_size(struct snd_soc_tplg_vendor_array * tuples,u32 block_size,u32 entry_id_token,u32 * size)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
avs_parse_uuid_token(struct snd_soc_component * comp,void * elem,void * object,u32 offset)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
avs_parse_bool_token(struct snd_soc_component * comp,void * elem,void * object,u32 offset)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
avs_parse_byte_token(struct snd_soc_component * comp,void * elem,void * object,u32 offset)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
avs_parse_short_token(struct snd_soc_component * comp,void * elem,void * object,u32 offset)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
avs_parse_word_token(struct snd_soc_component * comp,void * elem,void * object,u32 offset)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
avs_parse_string_token(struct snd_soc_component * comp,void * elem,void * object,u32 offset)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 
avs_parse_uuid_tokens(struct snd_soc_component * comp,void * object,const struct avs_tplg_token_parser * parsers,int count,struct snd_soc_tplg_vendor_array * tuples)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 
avs_parse_string_tokens(struct snd_soc_component * comp,void * object,const struct avs_tplg_token_parser * parsers,int count,struct snd_soc_tplg_vendor_array * tuples)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 
avs_parse_word_tokens(struct snd_soc_component * comp,void * object,const struct avs_tplg_token_parser * parsers,int count,struct snd_soc_tplg_vendor_array * tuples)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 
avs_parse_tokens(struct snd_soc_component * comp,void * object,const struct avs_tplg_token_parser * parsers,size_t count,struct snd_soc_tplg_vendor_array * tuples,int priv_size)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
parse_audio_format_bitfield(struct snd_soc_component * comp,void * elem,void * object,u32 offset)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 
parse_link_formatted_string(struct snd_soc_component * comp,void * elem,void * object,u32 offset)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
parse_dictionary_header(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,void ** dict,u32 * num_entries,size_t entry_size,u32 num_entries_token)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
parse_dictionary_entries(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size,void * dict,u32 num_entries,size_t entry_size,u32 entry_id_token,const struct avs_tplg_token_parser * parsers,size_t num_parsers)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 
parse_dictionary(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size,void ** dict,u32 * num_entries,size_t entry_size,u32 num_entries_token,u32 entry_id_token,const struct avs_tplg_token_parser * parsers,size_t num_parsers)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 
avs_tplg_parse_libraries(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)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 
avs_tplg_parse_audio_formats(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)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 
avs_tplg_parse_modcfgs_base(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)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 void
assign_copier_gtw_instance(struct snd_soc_component * comp,struct avs_tplg_modcfg_ext * cfg)812 assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg)
813 {
814 	struct snd_soc_acpi_mach *mach;
815 
816 	if (!guid_equal(&cfg->type, &AVS_COPIER_MOD_UUID))
817 		return;
818 
819 	/* Only I2S boards assign port instance in ->i2s_link_mask. */
820 	switch (cfg->copier.dma_type) {
821 	case AVS_DMA_I2S_LINK_OUTPUT:
822 	case AVS_DMA_I2S_LINK_INPUT:
823 		break;
824 	default:
825 		return;
826 	}
827 
828 	mach = dev_get_platdata(comp->card->dev);
829 
830 	/* Automatic assignment only when board describes single SSP. */
831 	if (hweight_long(mach->mach_params.i2s_link_mask) == 1 && !cfg->copier.vindex.i2s.instance)
832 		cfg->copier.vindex.i2s.instance = __ffs(mach->mach_params.i2s_link_mask);
833 }
834 
avs_tplg_parse_modcfg_ext(struct snd_soc_component * comp,struct avs_tplg_modcfg_ext * cfg,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)835 static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp,
836 				     struct avs_tplg_modcfg_ext *cfg,
837 				     struct snd_soc_tplg_vendor_array *tuples,
838 				     u32 block_size)
839 {
840 	u32 esize;
841 	int ret;
842 
843 	/* See where pin block starts. */
844 	ret = avs_tplg_vendor_entry_size(tuples, block_size,
845 					 AVS_TKN_PIN_FMT_INDEX_U32, &esize);
846 	if (ret)
847 		return ret;
848 
849 	ret = avs_parse_tokens(comp, cfg, modcfg_ext_parsers,
850 			       ARRAY_SIZE(modcfg_ext_parsers), tuples, esize);
851 	if (ret)
852 		return ret;
853 
854 	/* Update copier gateway based on board's i2s_link_mask. */
855 	assign_copier_gtw_instance(comp, cfg);
856 
857 	block_size -= esize;
858 	/* Parse trailing in/out pin formats if any. */
859 	if (block_size) {
860 		struct avs_tplg_pin_format *pins;
861 		u32 num_pins;
862 
863 		num_pins = cfg->generic.num_input_pins + cfg->generic.num_output_pins;
864 		if (!num_pins)
865 			return -EINVAL;
866 
867 		pins = devm_kcalloc(comp->card->dev, num_pins, sizeof(*pins), GFP_KERNEL);
868 		if (!pins)
869 			return -ENOMEM;
870 
871 		tuples = avs_tplg_vendor_array_at(tuples, esize);
872 		ret = parse_dictionary_entries(comp, tuples, block_size,
873 					       pins, num_pins, sizeof(*pins),
874 					       AVS_TKN_PIN_FMT_INDEX_U32,
875 					       pin_format_parsers,
876 					       ARRAY_SIZE(pin_format_parsers));
877 		if (ret)
878 			return ret;
879 		cfg->generic.pin_fmts = pins;
880 	}
881 
882 	return 0;
883 }
884 
avs_tplg_parse_modcfgs_ext(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)885 static int avs_tplg_parse_modcfgs_ext(struct snd_soc_component *comp,
886 				      struct snd_soc_tplg_vendor_array *tuples,
887 				      u32 block_size)
888 {
889 	struct avs_soc_component *acomp = to_avs_soc_component(comp);
890 	struct avs_tplg *tplg = acomp->tplg;
891 	int ret, i;
892 
893 	ret = parse_dictionary_header(comp, tuples, (void **)&tplg->modcfgs_ext,
894 				      &tplg->num_modcfgs_ext,
895 				      sizeof(*tplg->modcfgs_ext),
896 				      AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32);
897 	if (ret)
898 		return ret;
899 
900 	block_size -= le32_to_cpu(tuples->size);
901 	/* With header parsed, move on to parsing entries. */
902 	tuples = avs_tplg_vendor_array_next(tuples);
903 
904 	for (i = 0; i < tplg->num_modcfgs_ext; i++) {
905 		struct avs_tplg_modcfg_ext *cfg = &tplg->modcfgs_ext[i];
906 		u32 esize;
907 
908 		ret = avs_tplg_vendor_entry_size(tuples, block_size,
909 						 AVS_TKN_MODCFG_EXT_ID_U32, &esize);
910 		if (ret)
911 			return ret;
912 
913 		ret = avs_tplg_parse_modcfg_ext(comp, cfg, tuples, esize);
914 		if (ret)
915 			return ret;
916 
917 		block_size -= esize;
918 		tuples = avs_tplg_vendor_array_at(tuples, esize);
919 	}
920 
921 	return 0;
922 }
923 
924 static const struct avs_tplg_token_parser pplcfg_parsers[] = {
925 	{
926 		.token = AVS_TKN_PPLCFG_REQ_SIZE_U16,
927 		.type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
928 		.offset = offsetof(struct avs_tplg_pplcfg, req_size),
929 		.parse = avs_parse_short_token,
930 	},
931 	{
932 		.token = AVS_TKN_PPLCFG_PRIORITY_U8,
933 		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
934 		.offset = offsetof(struct avs_tplg_pplcfg, priority),
935 		.parse = avs_parse_byte_token,
936 	},
937 	{
938 		.token = AVS_TKN_PPLCFG_LOW_POWER_BOOL,
939 		.type = SND_SOC_TPLG_TUPLE_TYPE_BOOL,
940 		.offset = offsetof(struct avs_tplg_pplcfg, lp),
941 		.parse = avs_parse_bool_token,
942 	},
943 	{
944 		.token = AVS_TKN_PPLCFG_ATTRIBUTES_U16,
945 		.type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
946 		.offset = offsetof(struct avs_tplg_pplcfg, attributes),
947 		.parse = avs_parse_short_token,
948 	},
949 	{
950 		.token = AVS_TKN_PPLCFG_TRIGGER_U32,
951 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
952 		.offset = offsetof(struct avs_tplg_pplcfg, trigger),
953 		.parse = avs_parse_word_token,
954 	},
955 };
956 
avs_tplg_parse_pplcfgs(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)957 static int avs_tplg_parse_pplcfgs(struct snd_soc_component *comp,
958 				  struct snd_soc_tplg_vendor_array *tuples,
959 				  u32 block_size)
960 {
961 	struct avs_soc_component *acomp = to_avs_soc_component(comp);
962 	struct avs_tplg *tplg = acomp->tplg;
963 
964 	return parse_dictionary(comp, tuples, block_size, (void **)&tplg->pplcfgs,
965 				&tplg->num_pplcfgs, sizeof(*tplg->pplcfgs),
966 				AVS_TKN_MANIFEST_NUM_PPLCFGS_U32,
967 				AVS_TKN_PPLCFG_ID_U32,
968 				pplcfg_parsers, ARRAY_SIZE(pplcfg_parsers));
969 }
970 
971 static const struct avs_tplg_token_parser binding_parsers[] = {
972 	{
973 		.token = AVS_TKN_BINDING_TARGET_TPLG_NAME_STRING,
974 		.type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
975 		.offset = offsetof(struct avs_tplg_binding, target_tplg_name),
976 		.parse = parse_link_formatted_string,
977 	},
978 	{
979 		.token = AVS_TKN_BINDING_TARGET_PATH_TMPL_ID_U32,
980 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
981 		.offset = offsetof(struct avs_tplg_binding, target_path_tmpl_id),
982 		.parse = avs_parse_word_token,
983 	},
984 	{
985 		.token = AVS_TKN_BINDING_TARGET_PPL_ID_U32,
986 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
987 		.offset = offsetof(struct avs_tplg_binding, target_ppl_id),
988 		.parse = avs_parse_word_token,
989 	},
990 	{
991 		.token = AVS_TKN_BINDING_TARGET_MOD_ID_U32,
992 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
993 		.offset = offsetof(struct avs_tplg_binding, target_mod_id),
994 		.parse = avs_parse_word_token,
995 	},
996 	{
997 		.token = AVS_TKN_BINDING_TARGET_MOD_PIN_U8,
998 		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
999 		.offset = offsetof(struct avs_tplg_binding, target_mod_pin),
1000 		.parse = avs_parse_byte_token,
1001 	},
1002 	{
1003 		.token = AVS_TKN_BINDING_MOD_ID_U32,
1004 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1005 		.offset = offsetof(struct avs_tplg_binding, mod_id),
1006 		.parse = avs_parse_word_token,
1007 	},
1008 	{
1009 		.token = AVS_TKN_BINDING_MOD_PIN_U8,
1010 		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1011 		.offset = offsetof(struct avs_tplg_binding, mod_pin),
1012 		.parse = avs_parse_byte_token,
1013 	},
1014 	{
1015 		.token = AVS_TKN_BINDING_IS_SINK_U8,
1016 		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1017 		.offset = offsetof(struct avs_tplg_binding, is_sink),
1018 		.parse = avs_parse_byte_token,
1019 	},
1020 };
1021 
avs_tplg_parse_bindings(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)1022 static int avs_tplg_parse_bindings(struct snd_soc_component *comp,
1023 				   struct snd_soc_tplg_vendor_array *tuples,
1024 				   u32 block_size)
1025 {
1026 	struct avs_soc_component *acomp = to_avs_soc_component(comp);
1027 	struct avs_tplg *tplg = acomp->tplg;
1028 
1029 	return parse_dictionary(comp, tuples, block_size, (void **)&tplg->bindings,
1030 				&tplg->num_bindings, sizeof(*tplg->bindings),
1031 				AVS_TKN_MANIFEST_NUM_BINDINGS_U32,
1032 				AVS_TKN_BINDING_ID_U32,
1033 				binding_parsers, ARRAY_SIZE(binding_parsers));
1034 }
1035 
1036 static const struct avs_tplg_token_parser module_parsers[] = {
1037 	{
1038 		.token = AVS_TKN_MOD_ID_U32,
1039 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1040 		.offset = offsetof(struct avs_tplg_module, id),
1041 		.parse = avs_parse_word_token,
1042 	},
1043 	{
1044 		.token = AVS_TKN_MOD_MODCFG_BASE_ID_U32,
1045 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1046 		.offset = offsetof(struct avs_tplg_module, cfg_base),
1047 		.parse = avs_parse_modcfg_base_ptr,
1048 	},
1049 	{
1050 		.token = AVS_TKN_MOD_IN_AFMT_ID_U32,
1051 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1052 		.offset = offsetof(struct avs_tplg_module, in_fmt),
1053 		.parse = avs_parse_audio_format_ptr,
1054 	},
1055 	{
1056 		.token = AVS_TKN_MOD_CORE_ID_U8,
1057 		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1058 		.offset = offsetof(struct avs_tplg_module, core_id),
1059 		.parse = avs_parse_byte_token,
1060 	},
1061 	{
1062 		.token = AVS_TKN_MOD_PROC_DOMAIN_U8,
1063 		.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1064 		.offset = offsetof(struct avs_tplg_module, domain),
1065 		.parse = avs_parse_byte_token,
1066 	},
1067 	{
1068 		.token = AVS_TKN_MOD_MODCFG_EXT_ID_U32,
1069 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1070 		.offset = offsetof(struct avs_tplg_module, cfg_ext),
1071 		.parse = avs_parse_modcfg_ext_ptr,
1072 	},
1073 };
1074 
1075 static struct avs_tplg_module *
avs_tplg_module_create(struct snd_soc_component * comp,struct avs_tplg_pipeline * owner,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)1076 avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline *owner,
1077 		       struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1078 {
1079 	struct avs_tplg_module *module;
1080 	int ret;
1081 
1082 	module = devm_kzalloc(comp->card->dev, sizeof(*module), GFP_KERNEL);
1083 	if (!module)
1084 		return ERR_PTR(-ENOMEM);
1085 
1086 	ret = avs_parse_tokens(comp, module, module_parsers,
1087 			       ARRAY_SIZE(module_parsers), tuples, block_size);
1088 	if (ret < 0)
1089 		return ERR_PTR(ret);
1090 
1091 	module->owner = owner;
1092 	INIT_LIST_HEAD(&module->node);
1093 
1094 	return module;
1095 }
1096 
1097 static const struct avs_tplg_token_parser pipeline_parsers[] = {
1098 	{
1099 		.token = AVS_TKN_PPL_ID_U32,
1100 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1101 		.offset = offsetof(struct avs_tplg_pipeline, id),
1102 		.parse = avs_parse_word_token,
1103 	},
1104 	{
1105 		.token = AVS_TKN_PPL_PPLCFG_ID_U32,
1106 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1107 		.offset = offsetof(struct avs_tplg_pipeline, cfg),
1108 		.parse = avs_parse_pplcfg_ptr,
1109 	},
1110 	{
1111 		.token = AVS_TKN_PPL_NUM_BINDING_IDS_U32,
1112 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1113 		.offset = offsetof(struct avs_tplg_pipeline, num_bindings),
1114 		.parse = avs_parse_word_token,
1115 	},
1116 };
1117 
1118 static const struct avs_tplg_token_parser bindings_parsers[] = {
1119 	{
1120 		.token = AVS_TKN_PPL_BINDING_ID_U32,
1121 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1122 		.offset = 0, /* to treat pipeline->bindings as dictionary */
1123 		.parse = avs_parse_binding_ptr,
1124 	},
1125 };
1126 
1127 static struct avs_tplg_pipeline *
avs_tplg_pipeline_create(struct snd_soc_component * comp,struct avs_tplg_path * owner,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)1128 avs_tplg_pipeline_create(struct snd_soc_component *comp, struct avs_tplg_path *owner,
1129 			 struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1130 {
1131 	struct avs_tplg_pipeline *pipeline;
1132 	u32 modblk_size, offset;
1133 	int ret;
1134 
1135 	pipeline = devm_kzalloc(comp->card->dev, sizeof(*pipeline), GFP_KERNEL);
1136 	if (!pipeline)
1137 		return ERR_PTR(-ENOMEM);
1138 
1139 	pipeline->owner = owner;
1140 	INIT_LIST_HEAD(&pipeline->mod_list);
1141 
1142 	/* Pipeline header MUST be followed by at least one module. */
1143 	ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1144 					   AVS_TKN_MOD_ID_U32, &offset);
1145 	if (!ret && !offset)
1146 		ret = -EINVAL;
1147 	if (ret)
1148 		return ERR_PTR(ret);
1149 
1150 	/* Process header which precedes module sections. */
1151 	ret = avs_parse_tokens(comp, pipeline, pipeline_parsers,
1152 			       ARRAY_SIZE(pipeline_parsers), tuples, offset);
1153 	if (ret < 0)
1154 		return ERR_PTR(ret);
1155 
1156 	block_size -= offset;
1157 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1158 
1159 	/* Optionally, binding sections follow module ones. */
1160 	ret = avs_tplg_vendor_array_lookup_next(tuples, block_size,
1161 						AVS_TKN_PPL_BINDING_ID_U32, &offset);
1162 	if (ret) {
1163 		if (ret != -ENOENT)
1164 			return ERR_PTR(ret);
1165 
1166 		/* Does header information match actual block layout? */
1167 		if (pipeline->num_bindings)
1168 			return ERR_PTR(-EINVAL);
1169 
1170 		modblk_size = block_size;
1171 	} else {
1172 		pipeline->bindings = devm_kcalloc(comp->card->dev, pipeline->num_bindings,
1173 						  sizeof(*pipeline->bindings), GFP_KERNEL);
1174 		if (!pipeline->bindings)
1175 			return ERR_PTR(-ENOMEM);
1176 
1177 		modblk_size = offset;
1178 	}
1179 
1180 	block_size -= modblk_size;
1181 	do {
1182 		struct avs_tplg_module *module;
1183 		u32 esize;
1184 
1185 		ret = avs_tplg_vendor_entry_size(tuples, modblk_size,
1186 						 AVS_TKN_MOD_ID_U32, &esize);
1187 		if (ret)
1188 			return ERR_PTR(ret);
1189 
1190 		module = avs_tplg_module_create(comp, pipeline, tuples, esize);
1191 		if (IS_ERR(module)) {
1192 			dev_err(comp->dev, "parse module failed: %ld\n",
1193 				PTR_ERR(module));
1194 			return ERR_CAST(module);
1195 		}
1196 
1197 		list_add_tail(&module->node, &pipeline->mod_list);
1198 		modblk_size -= esize;
1199 		tuples = avs_tplg_vendor_array_at(tuples, esize);
1200 	} while (modblk_size > 0);
1201 
1202 	/* What's left is optional range of bindings. */
1203 	ret = parse_dictionary_entries(comp, tuples, block_size, pipeline->bindings,
1204 				       pipeline->num_bindings, sizeof(*pipeline->bindings),
1205 				       AVS_TKN_PPL_BINDING_ID_U32,
1206 				       bindings_parsers, ARRAY_SIZE(bindings_parsers));
1207 	if (ret)
1208 		return ERR_PTR(ret);
1209 
1210 	return pipeline;
1211 }
1212 
1213 static const struct avs_tplg_token_parser path_parsers[] = {
1214 	{
1215 		.token = AVS_TKN_PATH_ID_U32,
1216 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1217 		.offset = offsetof(struct avs_tplg_path, id),
1218 		.parse = avs_parse_word_token,
1219 	},
1220 	{
1221 		.token = AVS_TKN_PATH_FE_FMT_ID_U32,
1222 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1223 		.offset = offsetof(struct avs_tplg_path, fe_fmt),
1224 		.parse = avs_parse_audio_format_ptr,
1225 	},
1226 	{
1227 		.token = AVS_TKN_PATH_BE_FMT_ID_U32,
1228 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1229 		.offset = offsetof(struct avs_tplg_path, be_fmt),
1230 		.parse = avs_parse_audio_format_ptr,
1231 	},
1232 };
1233 
1234 static struct avs_tplg_path *
avs_tplg_path_create(struct snd_soc_component * comp,struct avs_tplg_path_template * owner,struct snd_soc_tplg_vendor_array * tuples,u32 block_size,const struct avs_tplg_token_parser * parsers,u32 num_parsers)1235 avs_tplg_path_create(struct snd_soc_component *comp, struct avs_tplg_path_template *owner,
1236 		     struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
1237 		     const struct avs_tplg_token_parser *parsers, u32 num_parsers)
1238 {
1239 	struct avs_tplg_pipeline *pipeline;
1240 	struct avs_tplg_path *path;
1241 	u32 offset;
1242 	int ret;
1243 
1244 	path = devm_kzalloc(comp->card->dev, sizeof(*path), GFP_KERNEL);
1245 	if (!path)
1246 		return ERR_PTR(-ENOMEM);
1247 
1248 	path->owner = owner;
1249 	INIT_LIST_HEAD(&path->ppl_list);
1250 	INIT_LIST_HEAD(&path->node);
1251 
1252 	/* Path header MAY be followed by one or more pipelines. */
1253 	ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1254 					   AVS_TKN_PPL_ID_U32, &offset);
1255 	if (ret == -ENOENT)
1256 		offset = block_size;
1257 	else if (ret)
1258 		return ERR_PTR(ret);
1259 	else if (!offset)
1260 		return ERR_PTR(-EINVAL);
1261 
1262 	/* Process header which precedes pipeline sections. */
1263 	ret = avs_parse_tokens(comp, path, parsers, num_parsers, tuples, offset);
1264 	if (ret < 0)
1265 		return ERR_PTR(ret);
1266 
1267 	block_size -= offset;
1268 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1269 	while (block_size > 0) {
1270 		u32 esize;
1271 
1272 		ret = avs_tplg_vendor_entry_size(tuples, block_size,
1273 						 AVS_TKN_PPL_ID_U32, &esize);
1274 		if (ret)
1275 			return ERR_PTR(ret);
1276 
1277 		pipeline = avs_tplg_pipeline_create(comp, path, tuples, esize);
1278 		if (IS_ERR(pipeline)) {
1279 			dev_err(comp->dev, "parse pipeline failed: %ld\n",
1280 				PTR_ERR(pipeline));
1281 			return ERR_CAST(pipeline);
1282 		}
1283 
1284 		list_add_tail(&pipeline->node, &path->ppl_list);
1285 		block_size -= esize;
1286 		tuples = avs_tplg_vendor_array_at(tuples, esize);
1287 	}
1288 
1289 	return path;
1290 }
1291 
1292 static const struct avs_tplg_token_parser path_tmpl_parsers[] = {
1293 	{
1294 		.token = AVS_TKN_PATH_TMPL_ID_U32,
1295 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1296 		.offset = offsetof(struct avs_tplg_path_template, id),
1297 		.parse = avs_parse_word_token,
1298 	},
1299 };
1300 
parse_path_template(struct snd_soc_component * comp,struct snd_soc_tplg_vendor_array * tuples,u32 block_size,struct avs_tplg_path_template * template,const struct avs_tplg_token_parser * tmpl_tokens,u32 num_tmpl_tokens,const struct avs_tplg_token_parser * path_tokens,u32 num_path_tokens)1301 static int parse_path_template(struct snd_soc_component *comp,
1302 			       struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
1303 			       struct avs_tplg_path_template *template,
1304 			       const struct avs_tplg_token_parser *tmpl_tokens, u32 num_tmpl_tokens,
1305 			       const struct avs_tplg_token_parser *path_tokens, u32 num_path_tokens)
1306 {
1307 	struct avs_tplg_path *path;
1308 	u32 offset;
1309 	int ret;
1310 
1311 	/* Path template header MUST be followed by at least one path variant. */
1312 	ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1313 					   AVS_TKN_PATH_ID_U32, &offset);
1314 	if (ret)
1315 		return ret;
1316 
1317 	/* Process header which precedes path variants sections. */
1318 	ret = avs_parse_tokens(comp, template, tmpl_tokens, num_tmpl_tokens, tuples, offset);
1319 	if (ret < 0)
1320 		return ret;
1321 
1322 	block_size -= offset;
1323 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1324 	do {
1325 		u32 esize;
1326 
1327 		ret = avs_tplg_vendor_entry_size(tuples, block_size,
1328 						 AVS_TKN_PATH_ID_U32, &esize);
1329 		if (ret)
1330 			return ret;
1331 
1332 		path = avs_tplg_path_create(comp, template, tuples, esize, path_tokens,
1333 					    num_path_tokens);
1334 		if (IS_ERR(path)) {
1335 			dev_err(comp->dev, "parse path failed: %ld\n", PTR_ERR(path));
1336 			return PTR_ERR(path);
1337 		}
1338 
1339 		list_add_tail(&path->node, &template->path_list);
1340 		block_size -= esize;
1341 		tuples = avs_tplg_vendor_array_at(tuples, esize);
1342 	} while (block_size > 0);
1343 
1344 	return 0;
1345 }
1346 
1347 static struct avs_tplg_path_template *
avs_tplg_path_template_create(struct snd_soc_component * comp,struct avs_tplg * owner,struct snd_soc_tplg_vendor_array * tuples,u32 block_size)1348 avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *owner,
1349 			      struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1350 {
1351 	struct avs_tplg_path_template *template;
1352 	int ret;
1353 
1354 	template = devm_kzalloc(comp->card->dev, sizeof(*template), GFP_KERNEL);
1355 	if (!template)
1356 		return ERR_PTR(-ENOMEM);
1357 
1358 	template->owner = owner; /* Used to access component tplg is assigned to. */
1359 	INIT_LIST_HEAD(&template->path_list);
1360 	INIT_LIST_HEAD(&template->node);
1361 
1362 	ret = parse_path_template(comp, tuples, block_size, template, path_tmpl_parsers,
1363 				  ARRAY_SIZE(path_tmpl_parsers), path_parsers,
1364 				  ARRAY_SIZE(path_parsers));
1365 	if (ret)
1366 		return ERR_PTR(ret);
1367 
1368 	return template;
1369 }
1370 
avs_route_load(struct snd_soc_component * comp,int index,struct snd_soc_dapm_route * route)1371 static int avs_route_load(struct snd_soc_component *comp, int index,
1372 			  struct snd_soc_dapm_route *route)
1373 {
1374 	struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
1375 	size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
1376 	char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1377 	u32 port;
1378 
1379 	/* See parse_link_formatted_string() for dynamic naming when(s). */
1380 	if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
1381 		port = __ffs(mach->mach_params.i2s_link_mask);
1382 
1383 		snprintf(buf, len, route->source, port);
1384 		strncpy((char *)route->source, buf, len);
1385 		snprintf(buf, len, route->sink, port);
1386 		strncpy((char *)route->sink, buf, len);
1387 		if (route->control) {
1388 			snprintf(buf, len, route->control, port);
1389 			strncpy((char *)route->control, buf, len);
1390 		}
1391 	}
1392 
1393 	return 0;
1394 }
1395 
avs_widget_load(struct snd_soc_component * comp,int index,struct snd_soc_dapm_widget * w,struct snd_soc_tplg_dapm_widget * dw)1396 static int avs_widget_load(struct snd_soc_component *comp, int index,
1397 			   struct snd_soc_dapm_widget *w,
1398 			   struct snd_soc_tplg_dapm_widget *dw)
1399 {
1400 	struct snd_soc_acpi_mach *mach;
1401 	struct avs_tplg_path_template *template;
1402 	struct avs_soc_component *acomp = to_avs_soc_component(comp);
1403 	struct avs_tplg *tplg;
1404 
1405 	if (!le32_to_cpu(dw->priv.size))
1406 		return 0;
1407 
1408 	tplg = acomp->tplg;
1409 	mach = dev_get_platdata(comp->card->dev);
1410 
1411 	/* See parse_link_formatted_string() for dynamic naming when(s). */
1412 	if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
1413 		kfree(w->name);
1414 		/* w->name is freed later by soc_tplg_dapm_widget_create() */
1415 		w->name = kasprintf(GFP_KERNEL, dw->name, __ffs(mach->mach_params.i2s_link_mask));
1416 		if (!w->name)
1417 			return -ENOMEM;
1418 	}
1419 
1420 	template = avs_tplg_path_template_create(comp, tplg, dw->priv.array,
1421 						 le32_to_cpu(dw->priv.size));
1422 	if (IS_ERR(template)) {
1423 		dev_err(comp->dev, "widget %s load failed: %ld\n", dw->name,
1424 			PTR_ERR(template));
1425 		return PTR_ERR(template);
1426 	}
1427 
1428 	w->priv = template; /* link path information to widget */
1429 	list_add_tail(&template->node, &tplg->path_tmpl_list);
1430 	return 0;
1431 }
1432 
avs_dai_load(struct snd_soc_component * comp,int index,struct snd_soc_dai_driver * dai_drv,struct snd_soc_tplg_pcm * pcm,struct snd_soc_dai * dai)1433 static int avs_dai_load(struct snd_soc_component *comp, int index,
1434 			struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm,
1435 			struct snd_soc_dai *dai)
1436 {
1437 	if (pcm)
1438 		dai_drv->ops = &avs_dai_fe_ops;
1439 	return 0;
1440 }
1441 
avs_link_load(struct snd_soc_component * comp,int index,struct snd_soc_dai_link * link,struct snd_soc_tplg_link_config * cfg)1442 static int avs_link_load(struct snd_soc_component *comp, int index, struct snd_soc_dai_link *link,
1443 			 struct snd_soc_tplg_link_config *cfg)
1444 {
1445 	if (!link->no_pcm) {
1446 		/* Stream control handled by IPCs. */
1447 		link->nonatomic = true;
1448 
1449 		/* Open LINK (BE) pipes last and close them first to prevent xruns. */
1450 		link->trigger[0] = SND_SOC_DPCM_TRIGGER_PRE;
1451 		link->trigger[1] = SND_SOC_DPCM_TRIGGER_PRE;
1452 	}
1453 
1454 	return 0;
1455 }
1456 
1457 static const struct avs_tplg_token_parser manifest_parsers[] = {
1458 	{
1459 		.token = AVS_TKN_MANIFEST_NAME_STRING,
1460 		.type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
1461 		.offset = offsetof(struct avs_tplg, name),
1462 		.parse = parse_link_formatted_string,
1463 	},
1464 	{
1465 		.token = AVS_TKN_MANIFEST_VERSION_U32,
1466 		.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1467 		.offset = offsetof(struct avs_tplg, version),
1468 		.parse = avs_parse_word_token,
1469 	},
1470 };
1471 
avs_manifest(struct snd_soc_component * comp,int index,struct snd_soc_tplg_manifest * manifest)1472 static int avs_manifest(struct snd_soc_component *comp, int index,
1473 			struct snd_soc_tplg_manifest *manifest)
1474 {
1475 	struct snd_soc_tplg_vendor_array *tuples = manifest->priv.array;
1476 	struct avs_soc_component *acomp = to_avs_soc_component(comp);
1477 	size_t remaining = le32_to_cpu(manifest->priv.size);
1478 	u32 offset;
1479 	int ret;
1480 
1481 	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1482 					   AVS_TKN_MANIFEST_NUM_LIBRARIES_U32, &offset);
1483 	/* Manifest MUST begin with a header. */
1484 	if (!ret && !offset)
1485 		ret = -EINVAL;
1486 	if (ret) {
1487 		dev_err(comp->dev, "incorrect manifest format: %d\n", ret);
1488 		return ret;
1489 	}
1490 
1491 	/* Process header which precedes any of the dictionaries. */
1492 	ret = avs_parse_tokens(comp, acomp->tplg, manifest_parsers,
1493 			       ARRAY_SIZE(manifest_parsers), tuples, offset);
1494 	if (ret < 0)
1495 		return ret;
1496 
1497 	remaining -= offset;
1498 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1499 
1500 	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1501 					   AVS_TKN_MANIFEST_NUM_AFMTS_U32, &offset);
1502 	if (ret) {
1503 		dev_err(comp->dev, "audio formats lookup failed: %d\n", ret);
1504 		return ret;
1505 	}
1506 
1507 	/* Libraries dictionary. */
1508 	ret = avs_tplg_parse_libraries(comp, tuples, offset);
1509 	if (ret < 0)
1510 		return ret;
1511 
1512 	remaining -= offset;
1513 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1514 
1515 	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1516 					   AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32, &offset);
1517 	if (ret) {
1518 		dev_err(comp->dev, "modcfgs_base lookup failed: %d\n", ret);
1519 		return ret;
1520 	}
1521 
1522 	/* Audio formats dictionary. */
1523 	ret = avs_tplg_parse_audio_formats(comp, tuples, offset);
1524 	if (ret < 0)
1525 		return ret;
1526 
1527 	remaining -= offset;
1528 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1529 
1530 	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1531 					   AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32, &offset);
1532 	if (ret) {
1533 		dev_err(comp->dev, "modcfgs_ext lookup failed: %d\n", ret);
1534 		return ret;
1535 	}
1536 
1537 	/* Module configs-base dictionary. */
1538 	ret = avs_tplg_parse_modcfgs_base(comp, tuples, offset);
1539 	if (ret < 0)
1540 		return ret;
1541 
1542 	remaining -= offset;
1543 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1544 
1545 	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1546 					   AVS_TKN_MANIFEST_NUM_PPLCFGS_U32, &offset);
1547 	if (ret) {
1548 		dev_err(comp->dev, "pplcfgs lookup failed: %d\n", ret);
1549 		return ret;
1550 	}
1551 
1552 	/* Module configs-ext dictionary. */
1553 	ret = avs_tplg_parse_modcfgs_ext(comp, tuples, offset);
1554 	if (ret < 0)
1555 		return ret;
1556 
1557 	remaining -= offset;
1558 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1559 
1560 	ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1561 					   AVS_TKN_MANIFEST_NUM_BINDINGS_U32, &offset);
1562 	if (ret) {
1563 		dev_err(comp->dev, "bindings lookup failed: %d\n", ret);
1564 		return ret;
1565 	}
1566 
1567 	/* Pipeline configs dictionary. */
1568 	ret = avs_tplg_parse_pplcfgs(comp, tuples, offset);
1569 	if (ret < 0)
1570 		return ret;
1571 
1572 	remaining -= offset;
1573 	tuples = avs_tplg_vendor_array_at(tuples, offset);
1574 
1575 	/* Bindings dictionary. */
1576 	return avs_tplg_parse_bindings(comp, tuples, remaining);
1577 }
1578 
1579 static struct snd_soc_tplg_ops avs_tplg_ops = {
1580 	.dapm_route_load	= avs_route_load,
1581 	.widget_load		= avs_widget_load,
1582 	.dai_load		= avs_dai_load,
1583 	.link_load		= avs_link_load,
1584 	.manifest		= avs_manifest,
1585 };
1586 
avs_tplg_new(struct snd_soc_component * comp)1587 struct avs_tplg *avs_tplg_new(struct snd_soc_component *comp)
1588 {
1589 	struct avs_tplg *tplg;
1590 
1591 	tplg = devm_kzalloc(comp->card->dev, sizeof(*tplg), GFP_KERNEL);
1592 	if (!tplg)
1593 		return NULL;
1594 
1595 	tplg->comp = comp;
1596 	INIT_LIST_HEAD(&tplg->path_tmpl_list);
1597 
1598 	return tplg;
1599 }
1600 
avs_load_topology(struct snd_soc_component * comp,const char * filename)1601 int avs_load_topology(struct snd_soc_component *comp, const char *filename)
1602 {
1603 	const struct firmware *fw;
1604 	int ret;
1605 
1606 	ret = request_firmware(&fw, filename, comp->dev);
1607 	if (ret < 0) {
1608 		dev_err(comp->dev, "request topology \"%s\" failed: %d\n", filename, ret);
1609 		return ret;
1610 	}
1611 
1612 	ret = snd_soc_tplg_component_load(comp, &avs_tplg_ops, fw);
1613 	if (ret < 0)
1614 		dev_err(comp->dev, "load topology \"%s\" failed: %d\n", filename, ret);
1615 
1616 	release_firmware(fw);
1617 	return ret;
1618 }
1619 
avs_remove_topology(struct snd_soc_component * comp)1620 int avs_remove_topology(struct snd_soc_component *comp)
1621 {
1622 	snd_soc_tplg_component_remove(comp);
1623 
1624 	return 0;
1625 }
1626