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