1 // SPDX-License-Identifier: GPL-2.0-only
3 // Copyright(c) 2021 Intel Corporation. All rights reserved.
5 // Authors: Cezary Rojewski <cezary.rojewski@intel.com>
6 // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
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>
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))
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)))
29 * Scan provided block of tuples for the specified token. If found,
30 * @offset is updated with position at which first matching token is
33 * Returns 0 on success, -ENOENT if not found and error code otherwise.
36 avs_tplg_vendor_array_lookup(struct snd_soc_tplg_vendor_array *tuples,
37 u32 block_size, u32 token, u32 *offset)
41 while (block_size > 0) {
42 struct snd_soc_tplg_vendor_value_elem *tuple;
43 u32 tuples_size = le32_to_cpu(tuples->size);
45 if (tuples_size > block_size)
48 tuple = tuples->value;
49 if (le32_to_cpu(tuple->token) == token) {
54 block_size -= tuples_size;
56 tuples = avs_tplg_vendor_array_next(tuples);
63 * See avs_tplg_vendor_array_lookup() for description.
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
72 avs_tplg_vendor_array_lookup_next(struct snd_soc_tplg_vendor_array *tuples,
73 u32 block_size, u32 token, u32 *offset)
75 u32 tuples_size = le32_to_cpu(tuples->size);
78 if (tuples_size > block_size)
81 tuples = avs_tplg_vendor_array_next(tuples);
82 block_size -= tuples_size;
84 ret = avs_tplg_vendor_array_lookup(tuples, block_size, token, offset);
86 *offset += tuples_size;
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
98 * Returns 0 on success, error code otherwise.
101 avs_tplg_vendor_entry_size(struct snd_soc_tplg_vendor_array *tuples,
102 u32 block_size, u32 entry_id_token, u32 *size)
106 ret = avs_tplg_vendor_array_lookup_next(tuples, block_size, entry_id_token, size);
107 if (ret == -ENOENT) {
116 * Vendor tuple parsing descriptor.
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
123 struct avs_tplg_token_parser {
124 enum avs_tplg_token token;
127 int (*parse)(struct snd_soc_component *comp, void *elem, void *object, u32 offset);
131 avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
133 struct snd_soc_tplg_vendor_uuid_elem *tuple = elem;
134 guid_t *val = (guid_t *)((u8 *)object + offset);
136 guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid);
142 avs_parse_bool_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
144 struct snd_soc_tplg_vendor_value_elem *tuple = elem;
145 bool *val = (bool *)((u8 *)object + offset);
147 *val = le32_to_cpu(tuple->value);
153 avs_parse_byte_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
155 struct snd_soc_tplg_vendor_value_elem *tuple = elem;
156 u8 *val = ((u8 *)object + offset);
158 *val = le32_to_cpu(tuple->value);
164 avs_parse_short_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
166 struct snd_soc_tplg_vendor_value_elem *tuple = elem;
167 u16 *val = (u16 *)((u8 *)object + offset);
169 *val = le32_to_cpu(tuple->value);
175 avs_parse_word_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
177 struct snd_soc_tplg_vendor_value_elem *tuple = elem;
178 u32 *val = (u32 *)((u8 *)object + offset);
180 *val = le32_to_cpu(tuple->value);
186 avs_parse_string_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
188 struct snd_soc_tplg_vendor_string_elem *tuple = elem;
189 char *val = (char *)((u8 *)object + offset);
191 snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s", tuple->string);
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)
200 struct snd_soc_tplg_vendor_uuid_elem *tuple;
203 /* Parse element by element. */
204 for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
205 tuple = &tuples->uuid[i];
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))
213 ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
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)
226 struct snd_soc_tplg_vendor_string_elem *tuple;
229 /* Parse element by element. */
230 for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
231 tuple = &tuples->string[i];
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))
239 ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
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)
252 struct snd_soc_tplg_vendor_value_elem *tuple;
255 /* Parse element by element. */
256 for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
257 tuple = &tuples->value[i];
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))
267 if (parsers[j].token != le32_to_cpu(tuple->token))
270 ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
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)
285 while (priv_size > 0) {
286 array_size = le32_to_cpu(tuples->size);
288 if (array_size <= 0) {
289 dev_err(comp->dev, "invalid array size 0x%x\n", array_size);
293 /* Make sure there is enough data before parsing. */
294 priv_size -= array_size;
296 dev_err(comp->dev, "invalid array size 0x%x\n", array_size);
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);
304 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
305 ret = avs_parse_string_tokens(comp, object, parsers, count, tuples);
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);
314 dev_err(comp->dev, "unknown token type %d\n", tuples->type);
319 dev_err(comp->dev, "parsing %zu tokens of %d type failed: %d\n",
320 count, tuples->type, ret);
324 tuples = avs_tplg_vendor_array_next(tuples);
330 #define AVS_DEFINE_PTR_PARSER(name, type, member) \
332 avs_parse_##name##_ptr(struct snd_soc_component *comp, void *elem, void *object, u32 offset) \
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); \
339 idx = le32_to_cpu(tuple->value); \
340 if (idx >= acomp->tplg->num_##member) \
343 *val = &acomp->tplg->member[idx]; \
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);
355 parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
357 struct snd_soc_tplg_vendor_value_elem *velem = elem;
358 struct avs_audio_format *audio_format = object;
361 case AVS_TKN_AFMT_NUM_CHANNELS_U32:
362 audio_format->num_channels = le32_to_cpu(velem->value);
364 case AVS_TKN_AFMT_VALID_BIT_DEPTH_U32:
365 audio_format->valid_bit_depth = le32_to_cpu(velem->value);
367 case AVS_TKN_AFMT_SAMPLE_TYPE_U32:
368 audio_format->sample_type = le32_to_cpu(velem->value);
375 static int avs_ssp_sprint(char *buf, size_t size, const char *fmt, int port, int tdm)
377 char *needle = strstr(fmt, "%d");
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
386 retsize = scnprintf(buf, min_t(size_t, size, needle - fmt + 1), "%s", fmt);
387 retsize += scnprintf(buf + retsize, size - retsize, "%d", port);
389 retsize += scnprintf(buf + retsize, size - retsize, ":%d", tdm);
390 retsize += scnprintf(buf + retsize, size - retsize, "%s", needle + 2);
394 return snprintf(buf, size, "%s", fmt);
397 static int parse_link_formatted_string(struct snd_soc_component *comp, void *elem,
398 void *object, u32 offset)
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;
406 * Dynamic naming - string formats, e.g.: ssp%d - supported only for
407 * topologies describing single device e.g.: an I2S codec on SSP0.
409 if (!avs_mach_singular_ssp(mach))
410 return avs_parse_string_token(comp, elem, object, offset);
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);
416 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
418 avs_ssp_sprint(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string, ssp_port, tdm_slot);
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)
429 struct snd_soc_tplg_vendor_value_elem *tuple;
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",
439 *num_entries = le32_to_cpu(tuple->value);
440 *dict = devm_kcalloc(comp->card->dev, *num_entries, entry_size, GFP_KERNEL);
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,
452 const struct avs_tplg_token_parser *parsers, size_t num_parsers)
457 for (i = 0; i < num_entries; i++) {
461 ret = avs_tplg_vendor_entry_size(tuples, block_size,
462 entry_id_token, &esize);
466 ret = avs_parse_tokens(comp, pos, parsers, num_parsers, tuples, esize);
468 dev_err(comp->dev, "parse entry: %d of type: %d failed: %d\n",
469 i, entry_id_token, ret);
475 tuples = avs_tplg_vendor_array_at(tuples, esize);
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)
489 ret = parse_dictionary_header(comp, tuples, dict, num_entries,
490 entry_size, num_entries_token);
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);
498 return parse_dictionary_entries(comp, tuples, block_size, *dict,
499 *num_entries, entry_size,
500 entry_id_token, parsers, num_parsers);
503 static const struct avs_tplg_token_parser library_parsers[] = {
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,
512 static int avs_tplg_parse_libraries(struct snd_soc_component *comp,
513 struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
515 struct avs_soc_component *acomp = to_avs_soc_component(comp);
516 struct avs_tplg *tplg = acomp->tplg;
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));
525 static const struct avs_tplg_token_parser audio_format_parsers[] = {
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,
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,
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,
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,
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,
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,
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,
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,
576 static int avs_tplg_parse_audio_formats(struct snd_soc_component *comp,
577 struct snd_soc_tplg_vendor_array *tuples,
580 struct avs_soc_component *acomp = to_avs_soc_component(comp);
581 struct avs_tplg *tplg = acomp->tplg;
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,
587 audio_format_parsers, ARRAY_SIZE(audio_format_parsers));
590 static const struct avs_tplg_token_parser modcfg_base_parsers[] = {
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,
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,
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,
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,
617 static int avs_tplg_parse_modcfgs_base(struct snd_soc_component *comp,
618 struct snd_soc_tplg_vendor_array *tuples,
621 struct avs_soc_component *acomp = to_avs_soc_component(comp);
622 struct avs_tplg *tplg = acomp->tplg;
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));
631 static const struct avs_tplg_token_parser modcfg_ext_parsers[] = {
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
820 static const struct avs_tplg_token_parser pin_format_parsers[] = {
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,
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,
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,
842 assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg)
844 struct snd_soc_acpi_mach *mach;
845 int ssp_port, tdm_slot;
847 if (!guid_equal(&cfg->type, &AVS_COPIER_MOD_UUID))
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:
859 /* If topology sets value don't overwrite it */
860 if (cfg->copier.vindex.i2s.instance)
863 mach = dev_get_platdata(comp->card->dev);
865 if (!avs_mach_singular_ssp(mach))
867 ssp_port = avs_mach_ssp_port(mach);
869 if (!avs_mach_singular_tdm(mach, ssp_port))
871 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
873 cfg->copier.vindex.i2s.instance = ssp_port;
874 cfg->copier.vindex.i2s.time_slot = tdm_slot;
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,
885 /* See where pin block starts. */
886 ret = avs_tplg_vendor_entry_size(tuples, block_size,
887 AVS_TKN_PIN_FMT_INDEX_U32, &esize);
891 ret = avs_parse_tokens(comp, cfg, modcfg_ext_parsers,
892 ARRAY_SIZE(modcfg_ext_parsers), tuples, esize);
896 /* Update copier gateway based on board's i2s_link_mask. */
897 assign_copier_gtw_instance(comp, cfg);
900 /* Parse trailing in/out pin formats if any. */
902 struct avs_tplg_pin_format *pins;
905 num_pins = cfg->generic.num_input_pins + cfg->generic.num_output_pins;
909 pins = devm_kcalloc(comp->card->dev, num_pins, sizeof(*pins), GFP_KERNEL);
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,
918 ARRAY_SIZE(pin_format_parsers));
921 cfg->generic.pin_fmts = pins;
927 static int avs_tplg_parse_modcfgs_ext(struct snd_soc_component *comp,
928 struct snd_soc_tplg_vendor_array *tuples,
931 struct avs_soc_component *acomp = to_avs_soc_component(comp);
932 struct avs_tplg *tplg = acomp->tplg;
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);
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);
946 for (i = 0; i < tplg->num_modcfgs_ext; i++) {
947 struct avs_tplg_modcfg_ext *cfg = &tplg->modcfgs_ext[i];
950 ret = avs_tplg_vendor_entry_size(tuples, block_size,
951 AVS_TKN_MODCFG_EXT_ID_U32, &esize);
955 ret = avs_tplg_parse_modcfg_ext(comp, cfg, tuples, esize);
960 tuples = avs_tplg_vendor_array_at(tuples, esize);
966 static const struct avs_tplg_token_parser pplcfg_parsers[] = {
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,
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,
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,
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,
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,
999 static int avs_tplg_parse_pplcfgs(struct snd_soc_component *comp,
1000 struct snd_soc_tplg_vendor_array *tuples,
1003 struct avs_soc_component *acomp = to_avs_soc_component(comp);
1004 struct avs_tplg *tplg = acomp->tplg;
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));
1013 static const struct avs_tplg_token_parser binding_parsers[] = {
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,
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,
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,
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,
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,
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,
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,
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,
1064 static int avs_tplg_parse_bindings(struct snd_soc_component *comp,
1065 struct snd_soc_tplg_vendor_array *tuples,
1068 struct avs_soc_component *acomp = to_avs_soc_component(comp);
1069 struct avs_tplg *tplg = acomp->tplg;
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));
1078 static const struct avs_tplg_token_parser module_parsers[] = {
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,
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,
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,
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,
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,
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,
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,
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)
1127 struct avs_tplg_module *module;
1130 module = devm_kzalloc(comp->card->dev, sizeof(*module), GFP_KERNEL);
1132 return ERR_PTR(-ENOMEM);
1134 ret = avs_parse_tokens(comp, module, module_parsers,
1135 ARRAY_SIZE(module_parsers), tuples, block_size);
1137 return ERR_PTR(ret);
1139 module->owner = owner;
1140 INIT_LIST_HEAD(&module->node);
1145 static const struct avs_tplg_token_parser pipeline_parsers[] = {
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,
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,
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,
1166 static const struct avs_tplg_token_parser bindings_parsers[] = {
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,
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)
1179 struct avs_tplg_pipeline *pipeline;
1180 u32 modblk_size, offset;
1183 pipeline = devm_kzalloc(comp->card->dev, sizeof(*pipeline), GFP_KERNEL);
1185 return ERR_PTR(-ENOMEM);
1187 pipeline->owner = owner;
1188 INIT_LIST_HEAD(&pipeline->mod_list);
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)
1196 return ERR_PTR(ret);
1198 /* Process header which precedes module sections. */
1199 ret = avs_parse_tokens(comp, pipeline, pipeline_parsers,
1200 ARRAY_SIZE(pipeline_parsers), tuples, offset);
1202 return ERR_PTR(ret);
1204 block_size -= offset;
1205 tuples = avs_tplg_vendor_array_at(tuples, offset);
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);
1212 return ERR_PTR(ret);
1214 /* Does header information match actual block layout? */
1215 if (pipeline->num_bindings)
1216 return ERR_PTR(-EINVAL);
1218 modblk_size = block_size;
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);
1225 modblk_size = offset;
1228 block_size -= modblk_size;
1230 struct avs_tplg_module *module;
1233 ret = avs_tplg_vendor_entry_size(tuples, modblk_size,
1234 AVS_TKN_MOD_ID_U32, &esize);
1236 return ERR_PTR(ret);
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",
1242 return ERR_CAST(module);
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);
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));
1256 return ERR_PTR(ret);
1261 static const struct avs_tplg_token_parser path_parsers[] = {
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,
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,
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,
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)
1287 struct avs_tplg_pipeline *pipeline;
1288 struct avs_tplg_path *path;
1292 path = devm_kzalloc(comp->card->dev, sizeof(*path), GFP_KERNEL);
1294 return ERR_PTR(-ENOMEM);
1296 path->owner = owner;
1297 INIT_LIST_HEAD(&path->ppl_list);
1298 INIT_LIST_HEAD(&path->node);
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);
1304 offset = block_size;
1306 return ERR_PTR(ret);
1308 return ERR_PTR(-EINVAL);
1310 /* Process header which precedes pipeline sections. */
1311 ret = avs_parse_tokens(comp, path, parsers, num_parsers, tuples, offset);
1313 return ERR_PTR(ret);
1315 block_size -= offset;
1316 tuples = avs_tplg_vendor_array_at(tuples, offset);
1317 while (block_size > 0) {
1320 ret = avs_tplg_vendor_entry_size(tuples, block_size,
1321 AVS_TKN_PPL_ID_U32, &esize);
1323 return ERR_PTR(ret);
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",
1329 return ERR_CAST(pipeline);
1332 list_add_tail(&pipeline->node, &path->ppl_list);
1333 block_size -= esize;
1334 tuples = avs_tplg_vendor_array_at(tuples, esize);
1340 static const struct avs_tplg_token_parser path_tmpl_parsers[] = {
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,
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)
1355 struct avs_tplg_path *path;
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);
1365 /* Process header which precedes path variants sections. */
1366 ret = avs_parse_tokens(comp, template, tmpl_tokens, num_tmpl_tokens, tuples, offset);
1370 block_size -= offset;
1371 tuples = avs_tplg_vendor_array_at(tuples, offset);
1375 ret = avs_tplg_vendor_entry_size(tuples, block_size,
1376 AVS_TKN_PATH_ID_U32, &esize);
1380 path = avs_tplg_path_create(comp, template, tuples, esize, path_tokens,
1383 dev_err(comp->dev, "parse path failed: %ld\n", PTR_ERR(path));
1384 return PTR_ERR(path);
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);
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)
1399 struct avs_tplg_path_template *template;
1402 template = devm_kzalloc(comp->card->dev, sizeof(*template), GFP_KERNEL);
1404 return ERR_PTR(-ENOMEM);
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);
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));
1414 return ERR_PTR(ret);
1419 static int avs_route_load(struct snd_soc_component *comp, int index,
1420 struct snd_soc_dapm_route *route)
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;
1427 /* See parse_link_formatted_string() for dynamic naming when(s). */
1428 if (!avs_mach_singular_ssp(mach))
1430 ssp_port = avs_mach_ssp_port(mach);
1432 if (!avs_mach_singular_tdm(mach, ssp_port))
1434 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
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);
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)
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;
1458 if (!le32_to_cpu(dw->priv.size))
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;
1467 mach = dev_get_platdata(comp->card->dev);
1468 if (!avs_mach_singular_ssp(mach))
1470 ssp_port = avs_mach_ssp_port(mach);
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;
1478 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
1480 buf = kmalloc(size, GFP_KERNEL);
1483 avs_ssp_sprint(buf, size, dw->name, ssp_port, tdm_slot);
1485 /* w->name is freed later by soc_tplg_dapm_widget_create() */
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,
1495 return PTR_ERR(template);
1498 w->priv = template; /* link path information to widget */
1499 list_add_tail(&template->node, &tplg->path_tmpl_list);
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)
1507 struct avs_tplg_path_template *template = w->priv;
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)
1518 dai_drv->ops = &avs_dai_fe_ops;
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)
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;
1530 if (!link->no_pcm) {
1531 /* Stream control handled by IPCs. */
1532 link->nonatomic = true;
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;
1542 static const struct avs_tplg_token_parser manifest_parsers[] = {
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,
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,
1557 static int avs_manifest(struct snd_soc_component *comp, int index,
1558 struct snd_soc_tplg_manifest *manifest)
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);
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)
1572 dev_err(comp->dev, "incorrect manifest format: %d\n", ret);
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);
1582 remaining -= offset;
1583 tuples = avs_tplg_vendor_array_at(tuples, offset);
1585 ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1586 AVS_TKN_MANIFEST_NUM_AFMTS_U32, &offset);
1588 dev_err(comp->dev, "audio formats lookup failed: %d\n", ret);
1592 /* Libraries dictionary. */
1593 ret = avs_tplg_parse_libraries(comp, tuples, offset);
1597 remaining -= offset;
1598 tuples = avs_tplg_vendor_array_at(tuples, offset);
1600 ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1601 AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32, &offset);
1603 dev_err(comp->dev, "modcfgs_base lookup failed: %d\n", ret);
1607 /* Audio formats dictionary. */
1608 ret = avs_tplg_parse_audio_formats(comp, tuples, offset);
1612 remaining -= offset;
1613 tuples = avs_tplg_vendor_array_at(tuples, offset);
1615 ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1616 AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32, &offset);
1618 dev_err(comp->dev, "modcfgs_ext lookup failed: %d\n", ret);
1622 /* Module configs-base dictionary. */
1623 ret = avs_tplg_parse_modcfgs_base(comp, tuples, offset);
1627 remaining -= offset;
1628 tuples = avs_tplg_vendor_array_at(tuples, offset);
1630 ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1631 AVS_TKN_MANIFEST_NUM_PPLCFGS_U32, &offset);
1633 dev_err(comp->dev, "pplcfgs lookup failed: %d\n", ret);
1637 /* Module configs-ext dictionary. */
1638 ret = avs_tplg_parse_modcfgs_ext(comp, tuples, offset);
1642 remaining -= offset;
1643 tuples = avs_tplg_vendor_array_at(tuples, offset);
1645 ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1646 AVS_TKN_MANIFEST_NUM_BINDINGS_U32, &offset);
1648 dev_err(comp->dev, "bindings lookup failed: %d\n", ret);
1652 /* Pipeline configs dictionary. */
1653 ret = avs_tplg_parse_pplcfgs(comp, tuples, offset);
1657 remaining -= offset;
1658 tuples = avs_tplg_vendor_array_at(tuples, offset);
1660 /* Bindings dictionary. */
1661 return avs_tplg_parse_bindings(comp, tuples, remaining);
1664 #define AVS_CONTROL_OPS_VOLUME 257
1666 static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = {
1668 .id = AVS_CONTROL_OPS_VOLUME,
1669 .get = avs_control_volume_get,
1670 .put = avs_control_volume_put,
1674 static const struct avs_tplg_token_parser control_parsers[] = {
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,
1684 avs_control_load(struct snd_soc_component *comp, int index, struct snd_kcontrol_new *ctmpl,
1685 struct snd_soc_tplg_ctl_hdr *hdr)
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;
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);
1704 ctl_data = devm_kzalloc(comp->card->dev, sizeof(*ctl_data), GFP_KERNEL);
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));
1714 mc = (struct soc_mixer_control *)ctmpl->private_value;
1715 mc->dobj.private = ctl_data;
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,
1731 struct avs_tplg *avs_tplg_new(struct snd_soc_component *comp)
1733 struct avs_tplg *tplg;
1735 tplg = devm_kzalloc(comp->card->dev, sizeof(*tplg), GFP_KERNEL);
1740 INIT_LIST_HEAD(&tplg->path_tmpl_list);
1745 int avs_load_topology(struct snd_soc_component *comp, const char *filename)
1747 const struct firmware *fw;
1750 ret = reject_firmware(&fw, filename, comp->dev);
1752 dev_err(comp->dev, "request topology \"%s\" failed: %d\n", filename, ret);
1756 ret = snd_soc_tplg_component_load(comp, &avs_tplg_ops, fw);
1758 dev_err(comp->dev, "load topology \"%s\" failed: %d\n", filename, ret);
1760 release_firmware(fw);
1764 int avs_remove_topology(struct snd_soc_component *comp)
1766 snd_soc_tplg_component_remove(comp);