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