~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/avs/topology.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 //
  3 // Copyright(c) 2021 Intel Corporation
  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.val)
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                 .token = AVS_TKN_MOD_INIT_CONFIG_NUM_IDS_U32,
1123                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1124                 .offset = offsetof(struct avs_tplg_module, num_config_ids),
1125                 .parse = avs_parse_byte_token,
1126         },
1127 };
1128 
1129 static const struct avs_tplg_token_parser init_config_parsers[] = {
1130         {
1131                 .token = AVS_TKN_MOD_INIT_CONFIG_ID_U32,
1132                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1133                 .offset = 0,
1134                 .parse = avs_parse_word_token,
1135         },
1136 };
1137 
1138 static struct avs_tplg_module *
1139 avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline *owner,
1140                        struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1141 {
1142         struct avs_tplg_module *module;
1143         u32 esize;
1144         int ret;
1145 
1146         /* See where config id block starts. */
1147         ret = avs_tplg_vendor_entry_size(tuples, block_size,
1148                                          AVS_TKN_MOD_INIT_CONFIG_ID_U32, &esize);
1149         if (ret)
1150                 return ERR_PTR(ret);
1151 
1152         module = devm_kzalloc(comp->card->dev, sizeof(*module), GFP_KERNEL);
1153         if (!module)
1154                 return ERR_PTR(-ENOMEM);
1155 
1156         ret = avs_parse_tokens(comp, module, module_parsers,
1157                                ARRAY_SIZE(module_parsers), tuples, esize);
1158         if (ret < 0)
1159                 return ERR_PTR(ret);
1160 
1161         block_size -= esize;
1162         /* Parse trailing config ids if any. */
1163         if (block_size) {
1164                 u32 num_config_ids = module->num_config_ids;
1165                 u32 *config_ids;
1166 
1167                 if (!num_config_ids)
1168                         return ERR_PTR(-EINVAL);
1169 
1170                 config_ids = devm_kcalloc(comp->card->dev, num_config_ids, sizeof(*config_ids),
1171                                            GFP_KERNEL);
1172                 if (!config_ids)
1173                         return ERR_PTR(-ENOMEM);
1174 
1175                 tuples = avs_tplg_vendor_array_at(tuples, esize);
1176                 ret = parse_dictionary_entries(comp, tuples, block_size,
1177                                                config_ids, num_config_ids, sizeof(*config_ids),
1178                                                AVS_TKN_MOD_INIT_CONFIG_ID_U32,
1179                                                init_config_parsers,
1180                                                ARRAY_SIZE(init_config_parsers));
1181                 if (ret)
1182                         return ERR_PTR(ret);
1183 
1184                 module->config_ids = config_ids;
1185         }
1186 
1187         module->owner = owner;
1188         INIT_LIST_HEAD(&module->node);
1189 
1190         return module;
1191 }
1192 
1193 static const struct avs_tplg_token_parser pipeline_parsers[] = {
1194         {
1195                 .token = AVS_TKN_PPL_ID_U32,
1196                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1197                 .offset = offsetof(struct avs_tplg_pipeline, id),
1198                 .parse = avs_parse_word_token,
1199         },
1200         {
1201                 .token = AVS_TKN_PPL_PPLCFG_ID_U32,
1202                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1203                 .offset = offsetof(struct avs_tplg_pipeline, cfg),
1204                 .parse = avs_parse_pplcfg_ptr,
1205         },
1206         {
1207                 .token = AVS_TKN_PPL_NUM_BINDING_IDS_U32,
1208                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1209                 .offset = offsetof(struct avs_tplg_pipeline, num_bindings),
1210                 .parse = avs_parse_word_token,
1211         },
1212 };
1213 
1214 static const struct avs_tplg_token_parser bindings_parsers[] = {
1215         {
1216                 .token = AVS_TKN_PPL_BINDING_ID_U32,
1217                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1218                 .offset = 0, /* to treat pipeline->bindings as dictionary */
1219                 .parse = avs_parse_binding_ptr,
1220         },
1221 };
1222 
1223 static struct avs_tplg_pipeline *
1224 avs_tplg_pipeline_create(struct snd_soc_component *comp, struct avs_tplg_path *owner,
1225                          struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1226 {
1227         struct avs_tplg_pipeline *pipeline;
1228         u32 modblk_size, offset;
1229         int ret;
1230 
1231         pipeline = devm_kzalloc(comp->card->dev, sizeof(*pipeline), GFP_KERNEL);
1232         if (!pipeline)
1233                 return ERR_PTR(-ENOMEM);
1234 
1235         pipeline->owner = owner;
1236         INIT_LIST_HEAD(&pipeline->mod_list);
1237 
1238         /* Pipeline header MUST be followed by at least one module. */
1239         ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1240                                            AVS_TKN_MOD_ID_U32, &offset);
1241         if (!ret && !offset)
1242                 ret = -EINVAL;
1243         if (ret)
1244                 return ERR_PTR(ret);
1245 
1246         /* Process header which precedes module sections. */
1247         ret = avs_parse_tokens(comp, pipeline, pipeline_parsers,
1248                                ARRAY_SIZE(pipeline_parsers), tuples, offset);
1249         if (ret < 0)
1250                 return ERR_PTR(ret);
1251 
1252         block_size -= offset;
1253         tuples = avs_tplg_vendor_array_at(tuples, offset);
1254 
1255         /* Optionally, binding sections follow module ones. */
1256         ret = avs_tplg_vendor_array_lookup_next(tuples, block_size,
1257                                                 AVS_TKN_PPL_BINDING_ID_U32, &offset);
1258         if (ret) {
1259                 if (ret != -ENOENT)
1260                         return ERR_PTR(ret);
1261 
1262                 /* Does header information match actual block layout? */
1263                 if (pipeline->num_bindings)
1264                         return ERR_PTR(-EINVAL);
1265 
1266                 modblk_size = block_size;
1267         } else {
1268                 pipeline->bindings = devm_kcalloc(comp->card->dev, pipeline->num_bindings,
1269                                                   sizeof(*pipeline->bindings), GFP_KERNEL);
1270                 if (!pipeline->bindings)
1271                         return ERR_PTR(-ENOMEM);
1272 
1273                 modblk_size = offset;
1274         }
1275 
1276         block_size -= modblk_size;
1277         do {
1278                 struct avs_tplg_module *module;
1279                 u32 esize;
1280 
1281                 ret = avs_tplg_vendor_entry_size(tuples, modblk_size,
1282                                                  AVS_TKN_MOD_ID_U32, &esize);
1283                 if (ret)
1284                         return ERR_PTR(ret);
1285 
1286                 module = avs_tplg_module_create(comp, pipeline, tuples, esize);
1287                 if (IS_ERR(module)) {
1288                         dev_err(comp->dev, "parse module failed: %ld\n",
1289                                 PTR_ERR(module));
1290                         return ERR_CAST(module);
1291                 }
1292 
1293                 list_add_tail(&module->node, &pipeline->mod_list);
1294                 modblk_size -= esize;
1295                 tuples = avs_tplg_vendor_array_at(tuples, esize);
1296         } while (modblk_size > 0);
1297 
1298         /* What's left is optional range of bindings. */
1299         ret = parse_dictionary_entries(comp, tuples, block_size, pipeline->bindings,
1300                                        pipeline->num_bindings, sizeof(*pipeline->bindings),
1301                                        AVS_TKN_PPL_BINDING_ID_U32,
1302                                        bindings_parsers, ARRAY_SIZE(bindings_parsers));
1303         if (ret)
1304                 return ERR_PTR(ret);
1305 
1306         return pipeline;
1307 }
1308 
1309 static const struct avs_tplg_token_parser path_parsers[] = {
1310         {
1311                 .token = AVS_TKN_PATH_ID_U32,
1312                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1313                 .offset = offsetof(struct avs_tplg_path, id),
1314                 .parse = avs_parse_word_token,
1315         },
1316         {
1317                 .token = AVS_TKN_PATH_FE_FMT_ID_U32,
1318                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1319                 .offset = offsetof(struct avs_tplg_path, fe_fmt),
1320                 .parse = avs_parse_audio_format_ptr,
1321         },
1322         {
1323                 .token = AVS_TKN_PATH_BE_FMT_ID_U32,
1324                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1325                 .offset = offsetof(struct avs_tplg_path, be_fmt),
1326                 .parse = avs_parse_audio_format_ptr,
1327         },
1328 };
1329 
1330 static struct avs_tplg_path *
1331 avs_tplg_path_create(struct snd_soc_component *comp, struct avs_tplg_path_template *owner,
1332                      struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
1333                      const struct avs_tplg_token_parser *parsers, u32 num_parsers)
1334 {
1335         struct avs_tplg_pipeline *pipeline;
1336         struct avs_tplg_path *path;
1337         u32 offset;
1338         int ret;
1339 
1340         path = devm_kzalloc(comp->card->dev, sizeof(*path), GFP_KERNEL);
1341         if (!path)
1342                 return ERR_PTR(-ENOMEM);
1343 
1344         path->owner = owner;
1345         INIT_LIST_HEAD(&path->ppl_list);
1346         INIT_LIST_HEAD(&path->node);
1347 
1348         /* Path header MAY be followed by one or more pipelines. */
1349         ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1350                                            AVS_TKN_PPL_ID_U32, &offset);
1351         if (ret == -ENOENT)
1352                 offset = block_size;
1353         else if (ret)
1354                 return ERR_PTR(ret);
1355         else if (!offset)
1356                 return ERR_PTR(-EINVAL);
1357 
1358         /* Process header which precedes pipeline sections. */
1359         ret = avs_parse_tokens(comp, path, parsers, num_parsers, tuples, offset);
1360         if (ret < 0)
1361                 return ERR_PTR(ret);
1362 
1363         block_size -= offset;
1364         tuples = avs_tplg_vendor_array_at(tuples, offset);
1365         while (block_size > 0) {
1366                 u32 esize;
1367 
1368                 ret = avs_tplg_vendor_entry_size(tuples, block_size,
1369                                                  AVS_TKN_PPL_ID_U32, &esize);
1370                 if (ret)
1371                         return ERR_PTR(ret);
1372 
1373                 pipeline = avs_tplg_pipeline_create(comp, path, tuples, esize);
1374                 if (IS_ERR(pipeline)) {
1375                         dev_err(comp->dev, "parse pipeline failed: %ld\n",
1376                                 PTR_ERR(pipeline));
1377                         return ERR_CAST(pipeline);
1378                 }
1379 
1380                 list_add_tail(&pipeline->node, &path->ppl_list);
1381                 block_size -= esize;
1382                 tuples = avs_tplg_vendor_array_at(tuples, esize);
1383         }
1384 
1385         return path;
1386 }
1387 
1388 static const struct avs_tplg_token_parser path_tmpl_parsers[] = {
1389         {
1390                 .token = AVS_TKN_PATH_TMPL_ID_U32,
1391                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1392                 .offset = offsetof(struct avs_tplg_path_template, id),
1393                 .parse = avs_parse_word_token,
1394         },
1395 };
1396 
1397 static int parse_path_template(struct snd_soc_component *comp,
1398                                struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
1399                                struct avs_tplg_path_template *template,
1400                                const struct avs_tplg_token_parser *tmpl_tokens, u32 num_tmpl_tokens,
1401                                const struct avs_tplg_token_parser *path_tokens, u32 num_path_tokens)
1402 {
1403         struct avs_tplg_path *path;
1404         u32 offset;
1405         int ret;
1406 
1407         /* Path template header MUST be followed by at least one path variant. */
1408         ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1409                                            AVS_TKN_PATH_ID_U32, &offset);
1410         if (ret)
1411                 return ret;
1412 
1413         /* Process header which precedes path variants sections. */
1414         ret = avs_parse_tokens(comp, template, tmpl_tokens, num_tmpl_tokens, tuples, offset);
1415         if (ret < 0)
1416                 return ret;
1417 
1418         block_size -= offset;
1419         tuples = avs_tplg_vendor_array_at(tuples, offset);
1420         do {
1421                 u32 esize;
1422 
1423                 ret = avs_tplg_vendor_entry_size(tuples, block_size,
1424                                                  AVS_TKN_PATH_ID_U32, &esize);
1425                 if (ret)
1426                         return ret;
1427 
1428                 path = avs_tplg_path_create(comp, template, tuples, esize, path_tokens,
1429                                             num_path_tokens);
1430                 if (IS_ERR(path)) {
1431                         dev_err(comp->dev, "parse path failed: %ld\n", PTR_ERR(path));
1432                         return PTR_ERR(path);
1433                 }
1434 
1435                 list_add_tail(&path->node, &template->path_list);
1436                 block_size -= esize;
1437                 tuples = avs_tplg_vendor_array_at(tuples, esize);
1438         } while (block_size > 0);
1439 
1440         return 0;
1441 }
1442 
1443 static struct avs_tplg_path_template *
1444 avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *owner,
1445                               struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1446 {
1447         struct avs_tplg_path_template *template;
1448         int ret;
1449 
1450         template = devm_kzalloc(comp->card->dev, sizeof(*template), GFP_KERNEL);
1451         if (!template)
1452                 return ERR_PTR(-ENOMEM);
1453 
1454         template->owner = owner; /* Used to access component tplg is assigned to. */
1455         INIT_LIST_HEAD(&template->path_list);
1456         INIT_LIST_HEAD(&template->node);
1457 
1458         ret = parse_path_template(comp, tuples, block_size, template, path_tmpl_parsers,
1459                                   ARRAY_SIZE(path_tmpl_parsers), path_parsers,
1460                                   ARRAY_SIZE(path_parsers));
1461         if (ret)
1462                 return ERR_PTR(ret);
1463 
1464         return template;
1465 }
1466 
1467 static const struct avs_tplg_token_parser mod_init_config_parsers[] = {
1468         {
1469                 .token = AVS_TKN_MOD_INIT_CONFIG_ID_U32,
1470                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1471                 .offset = offsetof(struct avs_tplg_init_config, id),
1472                 .parse = avs_parse_word_token,
1473         },
1474         {
1475                 .token = AVS_TKN_INIT_CONFIG_PARAM_U8,
1476                 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1477                 .offset = offsetof(struct avs_tplg_init_config, param),
1478                 .parse = avs_parse_byte_token,
1479         },
1480         {
1481                 .token = AVS_TKN_INIT_CONFIG_LENGTH_U32,
1482                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1483                 .offset = offsetof(struct avs_tplg_init_config, length),
1484                 .parse = avs_parse_word_token,
1485         },
1486 };
1487 
1488 static int avs_tplg_parse_initial_configs(struct snd_soc_component *comp,
1489                                            struct snd_soc_tplg_vendor_array *tuples,
1490                                            u32 block_size)
1491 {
1492         struct avs_soc_component *acomp = to_avs_soc_component(comp);
1493         struct avs_tplg *tplg = acomp->tplg;
1494         int ret, i;
1495 
1496         /* Parse tuple section telling how many init configs there are. */
1497         ret = parse_dictionary_header(comp, tuples, (void **)&tplg->init_configs,
1498                                       &tplg->num_init_configs,
1499                                       sizeof(*tplg->init_configs),
1500                                       AVS_TKN_MANIFEST_NUM_INIT_CONFIGS_U32);
1501         if (ret)
1502                 return ret;
1503 
1504         block_size -= le32_to_cpu(tuples->size);
1505         /* With header parsed, move on to parsing entries. */
1506         tuples = avs_tplg_vendor_array_next(tuples);
1507 
1508         for (i = 0; i < tplg->num_init_configs && block_size > 0; i++) {
1509                 struct avs_tplg_init_config *config = &tplg->init_configs[i];
1510                 struct snd_soc_tplg_vendor_array *tmp;
1511                 void *init_config_data;
1512                 u32 esize;
1513 
1514                 /*
1515                  * Usually to get section length we search for first token of next group of data,
1516                  * but in this case we can't as tuples are followed by raw data.
1517                  */
1518                 tmp = avs_tplg_vendor_array_next(tuples);
1519                 esize = le32_to_cpu(tuples->size) + le32_to_cpu(tmp->size);
1520 
1521                 ret = parse_dictionary_entries(comp, tuples, esize, config, 1, sizeof(*config),
1522                                                AVS_TKN_MOD_INIT_CONFIG_ID_U32,
1523                                                mod_init_config_parsers,
1524                                                ARRAY_SIZE(mod_init_config_parsers));
1525 
1526                 block_size -= esize;
1527 
1528                 /* handle raw data section */
1529                 init_config_data = (void *)tuples + esize;
1530                 esize = config->length;
1531 
1532                 config->data = devm_kmemdup(comp->card->dev, init_config_data, esize, GFP_KERNEL);
1533                 if (!config->data)
1534                         return -ENOMEM;
1535 
1536                 tuples = init_config_data + esize;
1537                 block_size -= esize;
1538         }
1539 
1540         return 0;
1541 }
1542 
1543 static int avs_route_load(struct snd_soc_component *comp, int index,
1544                           struct snd_soc_dapm_route *route)
1545 {
1546         struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
1547         size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
1548         int ssp_port, tdm_slot;
1549         char *buf;
1550 
1551         /* See parse_link_formatted_string() for dynamic naming when(s). */
1552         if (!avs_mach_singular_ssp(mach))
1553                 return 0;
1554         ssp_port = avs_mach_ssp_port(mach);
1555 
1556         if (!avs_mach_singular_tdm(mach, ssp_port))
1557                 return 0;
1558         tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
1559 
1560         buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
1561         if (!buf)
1562                 return -ENOMEM;
1563         avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot);
1564         route->source = buf;
1565 
1566         buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
1567         if (!buf)
1568                 return -ENOMEM;
1569         avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot);
1570         route->sink = buf;
1571 
1572         if (route->control) {
1573                 buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
1574                 if (!buf)
1575                         return -ENOMEM;
1576                 avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot);
1577                 route->control = buf;
1578         }
1579 
1580         return 0;
1581 }
1582 
1583 static int avs_widget_load(struct snd_soc_component *comp, int index,
1584                            struct snd_soc_dapm_widget *w,
1585                            struct snd_soc_tplg_dapm_widget *dw)
1586 {
1587         struct snd_soc_acpi_mach *mach;
1588         struct avs_tplg_path_template *template;
1589         struct avs_soc_component *acomp = to_avs_soc_component(comp);
1590         struct avs_tplg *tplg;
1591         int ssp_port, tdm_slot;
1592 
1593         if (!le32_to_cpu(dw->priv.size))
1594                 return 0;
1595 
1596         w->no_wname_in_kcontrol_name = true;
1597 
1598         if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) {
1599                 dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n");
1600                 w->ignore_suspend = false;
1601         }
1602 
1603         tplg = acomp->tplg;
1604         mach = dev_get_platdata(comp->card->dev);
1605         if (!avs_mach_singular_ssp(mach))
1606                 goto static_name;
1607         ssp_port = avs_mach_ssp_port(mach);
1608 
1609         /* See parse_link_formatted_string() for dynamic naming when(s). */
1610         if (avs_mach_singular_tdm(mach, ssp_port)) {
1611                 /* size is based on possible %d -> SSP:TDM, where SSP and TDM < 10 + '\0' */
1612                 size_t size = strlen(dw->name) + 2;
1613                 char *buf;
1614 
1615                 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
1616 
1617                 buf = kmalloc(size, GFP_KERNEL);
1618                 if (!buf)
1619                         return -ENOMEM;
1620                 avs_ssp_sprint(buf, size, dw->name, ssp_port, tdm_slot);
1621                 kfree(w->name);
1622                 /* w->name is freed later by soc_tplg_dapm_widget_create() */
1623                 w->name = buf;
1624         }
1625 
1626 static_name:
1627         template = avs_tplg_path_template_create(comp, tplg, dw->priv.array,
1628                                                  le32_to_cpu(dw->priv.size));
1629         if (IS_ERR(template)) {
1630                 dev_err(comp->dev, "widget %s load failed: %ld\n", dw->name,
1631                         PTR_ERR(template));
1632                 return PTR_ERR(template);
1633         }
1634 
1635         w->priv = template; /* link path information to widget */
1636         list_add_tail(&template->node, &tplg->path_tmpl_list);
1637         return 0;
1638 }
1639 
1640 static int avs_widget_ready(struct snd_soc_component *comp, int index,
1641                             struct snd_soc_dapm_widget *w,
1642                             struct snd_soc_tplg_dapm_widget *dw)
1643 {
1644         struct avs_tplg_path_template *template = w->priv;
1645 
1646         template->w = w;
1647         return 0;
1648 }
1649 
1650 static int avs_dai_load(struct snd_soc_component *comp, int index,
1651                         struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm,
1652                         struct snd_soc_dai *dai)
1653 {
1654         u32 fe_subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1655                             SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1656                             SNDRV_PCM_SUBFMTBIT_MSBITS_MAX;
1657 
1658         if (pcm) {
1659                 dai_drv->ops = &avs_dai_fe_ops;
1660                 dai_drv->capture.subformats = fe_subformats;
1661                 dai_drv->playback.subformats = fe_subformats;
1662         }
1663 
1664         return 0;
1665 }
1666 
1667 static int avs_link_load(struct snd_soc_component *comp, int index, struct snd_soc_dai_link *link,
1668                          struct snd_soc_tplg_link_config *cfg)
1669 {
1670         if (link->ignore_suspend && !AVS_S0IX_SUPPORTED) {
1671                 dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n");
1672                 link->ignore_suspend = false;
1673         }
1674 
1675         if (!link->no_pcm) {
1676                 /* Stream control handled by IPCs. */
1677                 link->nonatomic = true;
1678 
1679                 /* Open LINK (BE) pipes last and close them first to prevent xruns. */
1680                 link->trigger[0] = SND_SOC_DPCM_TRIGGER_PRE;
1681                 link->trigger[1] = SND_SOC_DPCM_TRIGGER_PRE;
1682         } else {
1683                 /* Do not ignore codec capabilities. */
1684                 link->dpcm_merged_format = 1;
1685         }
1686 
1687         return 0;
1688 }
1689 
1690 static const struct avs_tplg_token_parser manifest_parsers[] = {
1691         {
1692                 .token = AVS_TKN_MANIFEST_NAME_STRING,
1693                 .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
1694                 .offset = offsetof(struct avs_tplg, name),
1695                 .parse = parse_link_formatted_string,
1696         },
1697         {
1698                 .token = AVS_TKN_MANIFEST_VERSION_U32,
1699                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1700                 .offset = offsetof(struct avs_tplg, version),
1701                 .parse = avs_parse_word_token,
1702         },
1703 };
1704 
1705 static int avs_manifest(struct snd_soc_component *comp, int index,
1706                         struct snd_soc_tplg_manifest *manifest)
1707 {
1708         struct snd_soc_tplg_vendor_array *tuples = manifest->priv.array;
1709         struct avs_soc_component *acomp = to_avs_soc_component(comp);
1710         size_t remaining = le32_to_cpu(manifest->priv.size);
1711         bool has_init_config = true;
1712         u32 offset;
1713         int ret;
1714 
1715         ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1716                                            AVS_TKN_MANIFEST_NUM_LIBRARIES_U32, &offset);
1717         /* Manifest MUST begin with a header. */
1718         if (!ret && !offset)
1719                 ret = -EINVAL;
1720         if (ret) {
1721                 dev_err(comp->dev, "incorrect manifest format: %d\n", ret);
1722                 return ret;
1723         }
1724 
1725         /* Process header which precedes any of the dictionaries. */
1726         ret = avs_parse_tokens(comp, acomp->tplg, manifest_parsers,
1727                                ARRAY_SIZE(manifest_parsers), tuples, offset);
1728         if (ret < 0)
1729                 return ret;
1730 
1731         remaining -= offset;
1732         tuples = avs_tplg_vendor_array_at(tuples, offset);
1733 
1734         ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1735                                            AVS_TKN_MANIFEST_NUM_AFMTS_U32, &offset);
1736         if (ret) {
1737                 dev_err(comp->dev, "audio formats lookup failed: %d\n", ret);
1738                 return ret;
1739         }
1740 
1741         /* Libraries dictionary. */
1742         ret = avs_tplg_parse_libraries(comp, tuples, offset);
1743         if (ret < 0)
1744                 return ret;
1745 
1746         remaining -= offset;
1747         tuples = avs_tplg_vendor_array_at(tuples, offset);
1748 
1749         ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1750                                            AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32, &offset);
1751         if (ret) {
1752                 dev_err(comp->dev, "modcfgs_base lookup failed: %d\n", ret);
1753                 return ret;
1754         }
1755 
1756         /* Audio formats dictionary. */
1757         ret = avs_tplg_parse_audio_formats(comp, tuples, offset);
1758         if (ret < 0)
1759                 return ret;
1760 
1761         remaining -= offset;
1762         tuples = avs_tplg_vendor_array_at(tuples, offset);
1763 
1764         ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1765                                            AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32, &offset);
1766         if (ret) {
1767                 dev_err(comp->dev, "modcfgs_ext lookup failed: %d\n", ret);
1768                 return ret;
1769         }
1770 
1771         /* Module configs-base dictionary. */
1772         ret = avs_tplg_parse_modcfgs_base(comp, tuples, offset);
1773         if (ret < 0)
1774                 return ret;
1775 
1776         remaining -= offset;
1777         tuples = avs_tplg_vendor_array_at(tuples, offset);
1778 
1779         ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1780                                            AVS_TKN_MANIFEST_NUM_PPLCFGS_U32, &offset);
1781         if (ret) {
1782                 dev_err(comp->dev, "pplcfgs lookup failed: %d\n", ret);
1783                 return ret;
1784         }
1785 
1786         /* Module configs-ext dictionary. */
1787         ret = avs_tplg_parse_modcfgs_ext(comp, tuples, offset);
1788         if (ret < 0)
1789                 return ret;
1790 
1791         remaining -= offset;
1792         tuples = avs_tplg_vendor_array_at(tuples, offset);
1793 
1794         ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1795                                            AVS_TKN_MANIFEST_NUM_BINDINGS_U32, &offset);
1796         if (ret) {
1797                 dev_err(comp->dev, "bindings lookup failed: %d\n", ret);
1798                 return ret;
1799         }
1800 
1801         /* Pipeline configs dictionary. */
1802         ret = avs_tplg_parse_pplcfgs(comp, tuples, offset);
1803         if (ret < 0)
1804                 return ret;
1805 
1806         remaining -= offset;
1807         tuples = avs_tplg_vendor_array_at(tuples, offset);
1808 
1809         ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1810                                            AVS_TKN_MANIFEST_NUM_CONDPATH_TMPLS_U32, &offset);
1811         if (ret) {
1812                 dev_err(comp->dev, "condpath lookup failed: %d\n", ret);
1813                 return ret;
1814         }
1815 
1816         /* Bindings dictionary. */
1817         ret = avs_tplg_parse_bindings(comp, tuples, offset);
1818         if (ret < 0)
1819                 return ret;
1820 
1821         remaining -= offset;
1822         tuples = avs_tplg_vendor_array_at(tuples, offset);
1823 
1824         ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1825                                            AVS_TKN_MANIFEST_NUM_INIT_CONFIGS_U32, &offset);
1826         if (ret == -ENOENT) {
1827                 dev_dbg(comp->dev, "init config lookup failed: %d\n", ret);
1828                 has_init_config = false;
1829         } else if (ret) {
1830                 dev_err(comp->dev, "init config lookup failed: %d\n", ret);
1831                 return ret;
1832         }
1833 
1834         if (!has_init_config)
1835                 return 0;
1836 
1837         remaining -= offset;
1838         tuples = avs_tplg_vendor_array_at(tuples, offset);
1839 
1840         /* Initial configs dictionary. */
1841         ret = avs_tplg_parse_initial_configs(comp, tuples, remaining);
1842         if (ret < 0)
1843                 return ret;
1844 
1845         return 0;
1846 }
1847 
1848 #define AVS_CONTROL_OPS_VOLUME  257
1849 
1850 static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = {
1851         {
1852                 .id = AVS_CONTROL_OPS_VOLUME,
1853                 .get = avs_control_volume_get,
1854                 .put = avs_control_volume_put,
1855         },
1856 };
1857 
1858 static const struct avs_tplg_token_parser control_parsers[] = {
1859         {
1860                 .token = AVS_TKN_KCONTROL_ID_U32,
1861                 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1862                 .offset = offsetof(struct avs_control_data, id),
1863                 .parse = avs_parse_word_token,
1864         },
1865 };
1866 
1867 static int
1868 avs_control_load(struct snd_soc_component *comp, int index, struct snd_kcontrol_new *ctmpl,
1869                  struct snd_soc_tplg_ctl_hdr *hdr)
1870 {
1871         struct snd_soc_tplg_vendor_array *tuples;
1872         struct snd_soc_tplg_mixer_control *tmc;
1873         struct avs_control_data *ctl_data;
1874         struct soc_mixer_control *mc;
1875         size_t block_size;
1876         int ret;
1877 
1878         switch (le32_to_cpu(hdr->type)) {
1879         case SND_SOC_TPLG_TYPE_MIXER:
1880                 tmc = container_of(hdr, typeof(*tmc), hdr);
1881                 tuples = tmc->priv.array;
1882                 block_size = le32_to_cpu(tmc->priv.size);
1883                 break;
1884         default:
1885                 return -EINVAL;
1886         }
1887 
1888         ctl_data = devm_kzalloc(comp->card->dev, sizeof(*ctl_data), GFP_KERNEL);
1889         if (!ctl_data)
1890                 return -ENOMEM;
1891 
1892         ret = parse_dictionary_entries(comp, tuples, block_size, ctl_data, 1, sizeof(*ctl_data),
1893                                        AVS_TKN_KCONTROL_ID_U32, control_parsers,
1894                                        ARRAY_SIZE(control_parsers));
1895         if (ret)
1896                 return ret;
1897 
1898         mc = (struct soc_mixer_control *)ctmpl->private_value;
1899         mc->dobj.private = ctl_data;
1900         return 0;
1901 }
1902 
1903 static const struct snd_soc_tplg_ops avs_tplg_ops = {
1904         .io_ops                 = avs_control_ops,
1905         .io_ops_count           = ARRAY_SIZE(avs_control_ops),
1906         .control_load           = avs_control_load,
1907         .dapm_route_load        = avs_route_load,
1908         .widget_load            = avs_widget_load,
1909         .widget_ready           = avs_widget_ready,
1910         .dai_load               = avs_dai_load,
1911         .link_load              = avs_link_load,
1912         .manifest               = avs_manifest,
1913 };
1914 
1915 struct avs_tplg *avs_tplg_new(struct snd_soc_component *comp)
1916 {
1917         struct avs_tplg *tplg;
1918 
1919         tplg = devm_kzalloc(comp->card->dev, sizeof(*tplg), GFP_KERNEL);
1920         if (!tplg)
1921                 return NULL;
1922 
1923         tplg->comp = comp;
1924         INIT_LIST_HEAD(&tplg->path_tmpl_list);
1925 
1926         return tplg;
1927 }
1928 
1929 int avs_load_topology(struct snd_soc_component *comp, const char *filename)
1930 {
1931         const struct firmware *fw;
1932         int ret;
1933 
1934         ret = request_firmware(&fw, filename, comp->dev);
1935         if (ret < 0) {
1936                 dev_err(comp->dev, "request topology \"%s\" failed: %d\n", filename, ret);
1937                 return ret;
1938         }
1939 
1940         ret = snd_soc_tplg_component_load(comp, &avs_tplg_ops, fw);
1941         if (ret < 0)
1942                 dev_err(comp->dev, "load topology \"%s\" failed: %d\n", filename, ret);
1943 
1944         release_firmware(fw);
1945         return ret;
1946 }
1947 
1948 int avs_remove_topology(struct snd_soc_component *comp)
1949 {
1950         snd_soc_tplg_component_remove(comp);
1951 
1952         return 0;
1953 }
1954 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php