Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 //
0003 // Copyright(c) 2021 Intel Corporation. All rights reserved.
0004 //
0005 // Authors: Cezary Rojewski <cezary.rojewski@intel.com>
0006 //          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
0007 //
0008 
0009 #include <linux/firmware.h>
0010 #include <linux/uuid.h>
0011 #include <sound/soc.h>
0012 #include <sound/soc-acpi.h>
0013 #include <sound/soc-topology.h>
0014 #include <uapi/sound/intel/avs/tokens.h>
0015 #include "avs.h"
0016 #include "topology.h"
0017 
0018 /* Get pointer to vendor array at the specified offset. */
0019 #define avs_tplg_vendor_array_at(array, offset) \
0020     ((struct snd_soc_tplg_vendor_array *)((u8 *)array + offset))
0021 
0022 /* Get pointer to vendor array that is next in line. */
0023 #define avs_tplg_vendor_array_next(array) \
0024     (avs_tplg_vendor_array_at(array, le32_to_cpu((array)->size)))
0025 
0026 /*
0027  * Scan provided block of tuples for the specified token. If found,
0028  * @offset is updated with position at which first matching token is
0029  * located.
0030  *
0031  * Returns 0 on success, -ENOENT if not found and error code otherwise.
0032  */
0033 static int
0034 avs_tplg_vendor_array_lookup(struct snd_soc_tplg_vendor_array *tuples,
0035                  u32 block_size, u32 token, u32 *offset)
0036 {
0037     u32 pos = 0;
0038 
0039     while (block_size > 0) {
0040         struct snd_soc_tplg_vendor_value_elem *tuple;
0041         u32 tuples_size = le32_to_cpu(tuples->size);
0042 
0043         if (tuples_size > block_size)
0044             return -EINVAL;
0045 
0046         tuple = tuples->value;
0047         if (le32_to_cpu(tuple->token) == token) {
0048             *offset = pos;
0049             return 0;
0050         }
0051 
0052         block_size -= tuples_size;
0053         pos += tuples_size;
0054         tuples = avs_tplg_vendor_array_next(tuples);
0055     }
0056 
0057     return -ENOENT;
0058 }
0059 
0060 /*
0061  * See avs_tplg_vendor_array_lookup() for description.
0062  *
0063  * Behaves exactly like avs_tplg_vendor_lookup() but starts from the
0064  * next vendor array in line. Useful when searching for the finish line
0065  * of an arbitrary entry in a list of entries where each is composed of
0066  * several vendor tuples and a specific token marks the beginning of
0067  * a new entry block.
0068  */
0069 static int
0070 avs_tplg_vendor_array_lookup_next(struct snd_soc_tplg_vendor_array *tuples,
0071                   u32 block_size, u32 token, u32 *offset)
0072 {
0073     u32 tuples_size = le32_to_cpu(tuples->size);
0074     int ret;
0075 
0076     if (tuples_size > block_size)
0077         return -EINVAL;
0078 
0079     tuples = avs_tplg_vendor_array_next(tuples);
0080     block_size -= tuples_size;
0081 
0082     ret = avs_tplg_vendor_array_lookup(tuples, block_size, token, offset);
0083     if (!ret)
0084         *offset += tuples_size;
0085     return ret;
0086 }
0087 
0088 /*
0089  * Scan provided block of tuples for the specified token which marks
0090  * the border of an entry block. Behavior is similar to
0091  * avs_tplg_vendor_array_lookup() except 0 is also returned if no
0092  * matching token has been found. In such case, returned @size is
0093  * assigned to @block_size as the entire block belongs to the current
0094  * entry.
0095  *
0096  * Returns 0 on success, error code otherwise.
0097  */
0098 static int
0099 avs_tplg_vendor_entry_size(struct snd_soc_tplg_vendor_array *tuples,
0100                u32 block_size, u32 entry_id_token, u32 *size)
0101 {
0102     int ret;
0103 
0104     ret = avs_tplg_vendor_array_lookup_next(tuples, block_size, entry_id_token, size);
0105     if (ret == -ENOENT) {
0106         *size = block_size;
0107         ret = 0;
0108     }
0109 
0110     return ret;
0111 }
0112 
0113 /*
0114  * Vendor tuple parsing descriptor.
0115  *
0116  * @token: vendor specific token that identifies tuple
0117  * @type: tuple type, one of SND_SOC_TPLG_TUPLE_TYPE_XXX
0118  * @offset: offset of a struct's field to initialize
0119  * @parse: parsing function, extracts and assigns value to object's field
0120  */
0121 struct avs_tplg_token_parser {
0122     enum avs_tplg_token token;
0123     u32 type;
0124     u32 offset;
0125     int (*parse)(struct snd_soc_component *comp, void *elem, void *object, u32 offset);
0126 };
0127 
0128 static int
0129 avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
0130 {
0131     struct snd_soc_tplg_vendor_uuid_elem *tuple = elem;
0132     guid_t *val = (guid_t *)((u8 *)object + offset);
0133 
0134     guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid);
0135 
0136     return 0;
0137 }
0138 
0139 static int
0140 avs_parse_bool_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
0141 {
0142     struct snd_soc_tplg_vendor_value_elem *tuple = elem;
0143     bool *val = (bool *)((u8 *)object + offset);
0144 
0145     *val = le32_to_cpu(tuple->value);
0146 
0147     return 0;
0148 }
0149 
0150 static int
0151 avs_parse_byte_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
0152 {
0153     struct snd_soc_tplg_vendor_value_elem *tuple = elem;
0154     u8 *val = ((u8 *)object + offset);
0155 
0156     *val = le32_to_cpu(tuple->value);
0157 
0158     return 0;
0159 }
0160 
0161 static int
0162 avs_parse_short_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
0163 {
0164     struct snd_soc_tplg_vendor_value_elem *tuple = elem;
0165     u16 *val = (u16 *)((u8 *)object + offset);
0166 
0167     *val = le32_to_cpu(tuple->value);
0168 
0169     return 0;
0170 }
0171 
0172 static int
0173 avs_parse_word_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
0174 {
0175     struct snd_soc_tplg_vendor_value_elem *tuple = elem;
0176     u32 *val = (u32 *)((u8 *)object + offset);
0177 
0178     *val = le32_to_cpu(tuple->value);
0179 
0180     return 0;
0181 }
0182 
0183 static int
0184 avs_parse_string_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
0185 {
0186     struct snd_soc_tplg_vendor_string_elem *tuple = elem;
0187     char *val = (char *)((u8 *)object + offset);
0188 
0189     snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s", tuple->string);
0190 
0191     return 0;
0192 }
0193 
0194 static int avs_parse_uuid_tokens(struct snd_soc_component *comp, void *object,
0195                  const struct avs_tplg_token_parser *parsers, int count,
0196                  struct snd_soc_tplg_vendor_array *tuples)
0197 {
0198     struct snd_soc_tplg_vendor_uuid_elem *tuple;
0199     int ret, i, j;
0200 
0201     /* Parse element by element. */
0202     for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
0203         tuple = &tuples->uuid[i];
0204 
0205         for (j = 0; j < count; j++) {
0206             /* Ignore non-UUID tokens. */
0207             if (parsers[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID ||
0208                 parsers[j].token != le32_to_cpu(tuple->token))
0209                 continue;
0210 
0211             ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
0212             if (ret)
0213                 return ret;
0214         }
0215     }
0216 
0217     return 0;
0218 }
0219 
0220 static int avs_parse_string_tokens(struct snd_soc_component *comp, void *object,
0221                    const struct avs_tplg_token_parser *parsers, int count,
0222                    struct snd_soc_tplg_vendor_array *tuples)
0223 {
0224     struct snd_soc_tplg_vendor_string_elem *tuple;
0225     int ret, i, j;
0226 
0227     /* Parse element by element. */
0228     for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
0229         tuple = &tuples->string[i];
0230 
0231         for (j = 0; j < count; j++) {
0232             /* Ignore non-string tokens. */
0233             if (parsers[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING ||
0234                 parsers[j].token != le32_to_cpu(tuple->token))
0235                 continue;
0236 
0237             ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
0238             if (ret)
0239                 return ret;
0240         }
0241     }
0242 
0243     return 0;
0244 }
0245 
0246 static int avs_parse_word_tokens(struct snd_soc_component *comp, void *object,
0247                  const struct avs_tplg_token_parser *parsers, int count,
0248                  struct snd_soc_tplg_vendor_array *tuples)
0249 {
0250     struct snd_soc_tplg_vendor_value_elem *tuple;
0251     int ret, i, j;
0252 
0253     /* Parse element by element. */
0254     for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) {
0255         tuple = &tuples->value[i];
0256 
0257         for (j = 0; j < count; j++) {
0258             /* Ignore non-integer tokens. */
0259             if (!(parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD ||
0260                   parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT ||
0261                   parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE ||
0262                   parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL))
0263                 continue;
0264 
0265             if (parsers[j].token != le32_to_cpu(tuple->token))
0266                 continue;
0267 
0268             ret = parsers[j].parse(comp, tuple, object, parsers[j].offset);
0269             if (ret)
0270                 return ret;
0271         }
0272     }
0273 
0274     return 0;
0275 }
0276 
0277 static int avs_parse_tokens(struct snd_soc_component *comp, void *object,
0278                 const struct avs_tplg_token_parser *parsers, size_t count,
0279                 struct snd_soc_tplg_vendor_array *tuples, int priv_size)
0280 {
0281     int array_size, ret;
0282 
0283     while (priv_size > 0) {
0284         array_size = le32_to_cpu(tuples->size);
0285 
0286         if (array_size <= 0) {
0287             dev_err(comp->dev, "invalid array size 0x%x\n", array_size);
0288             return -EINVAL;
0289         }
0290 
0291         /* Make sure there is enough data before parsing. */
0292         priv_size -= array_size;
0293         if (priv_size < 0) {
0294             dev_err(comp->dev, "invalid array size 0x%x\n", array_size);
0295             return -EINVAL;
0296         }
0297 
0298         switch (le32_to_cpu(tuples->type)) {
0299         case SND_SOC_TPLG_TUPLE_TYPE_UUID:
0300             ret = avs_parse_uuid_tokens(comp, object, parsers, count, tuples);
0301             break;
0302         case SND_SOC_TPLG_TUPLE_TYPE_STRING:
0303             ret = avs_parse_string_tokens(comp, object, parsers, count, tuples);
0304             break;
0305         case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
0306         case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
0307         case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
0308         case SND_SOC_TPLG_TUPLE_TYPE_WORD:
0309             ret = avs_parse_word_tokens(comp, object, parsers, count, tuples);
0310             break;
0311         default:
0312             dev_err(comp->dev, "unknown token type %d\n", tuples->type);
0313             ret = -EINVAL;
0314         }
0315 
0316         if (ret) {
0317             dev_err(comp->dev, "parsing %zu tokens of %d type failed: %d\n",
0318                 count, tuples->type, ret);
0319             return ret;
0320         }
0321 
0322         tuples = avs_tplg_vendor_array_next(tuples);
0323     }
0324 
0325     return 0;
0326 }
0327 
0328 #define AVS_DEFINE_PTR_PARSER(name, type, member) \
0329 static int \
0330 avs_parse_##name##_ptr(struct snd_soc_component *comp, void *elem, void *object, u32 offset) \
0331 { \
0332     struct snd_soc_tplg_vendor_value_elem *tuple = elem;        \
0333     struct avs_soc_component *acomp = to_avs_soc_component(comp);   \
0334     type **val = (type **)(object + offset);            \
0335     u32 idx;                            \
0336                                     \
0337     idx = le32_to_cpu(tuple->value);                \
0338     if (idx >= acomp->tplg->num_##member)               \
0339         return -EINVAL;                     \
0340                                     \
0341     *val = &acomp->tplg->member[idx];               \
0342                                     \
0343     return 0;                           \
0344 }
0345 
0346 AVS_DEFINE_PTR_PARSER(audio_format, struct avs_audio_format, fmts);
0347 AVS_DEFINE_PTR_PARSER(modcfg_base, struct avs_tplg_modcfg_base, modcfgs_base);
0348 AVS_DEFINE_PTR_PARSER(modcfg_ext, struct avs_tplg_modcfg_ext, modcfgs_ext);
0349 AVS_DEFINE_PTR_PARSER(pplcfg, struct avs_tplg_pplcfg, pplcfgs);
0350 AVS_DEFINE_PTR_PARSER(binding, struct avs_tplg_binding, bindings);
0351 
0352 static int
0353 parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
0354 {
0355     struct snd_soc_tplg_vendor_value_elem *velem = elem;
0356     struct avs_audio_format *audio_format = object;
0357 
0358     switch (offset) {
0359     case AVS_TKN_AFMT_NUM_CHANNELS_U32:
0360         audio_format->num_channels = le32_to_cpu(velem->value);
0361         break;
0362     case AVS_TKN_AFMT_VALID_BIT_DEPTH_U32:
0363         audio_format->valid_bit_depth = le32_to_cpu(velem->value);
0364         break;
0365     case AVS_TKN_AFMT_SAMPLE_TYPE_U32:
0366         audio_format->sample_type = le32_to_cpu(velem->value);
0367         break;
0368     }
0369 
0370     return 0;
0371 }
0372 
0373 static int parse_link_formatted_string(struct snd_soc_component *comp, void *elem,
0374                        void *object, u32 offset)
0375 {
0376     struct snd_soc_tplg_vendor_string_elem *tuple = elem;
0377     struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
0378     char *val = (char *)((u8 *)object + offset);
0379 
0380     /*
0381      * Dynamic naming - string formats, e.g.: ssp%d - supported only for
0382      * topologies describing single device e.g.: an I2S codec on SSP0.
0383      */
0384     if (hweight_long(mach->mach_params.i2s_link_mask) != 1)
0385         return avs_parse_string_token(comp, elem, object, offset);
0386 
0387     snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string,
0388          __ffs(mach->mach_params.i2s_link_mask));
0389 
0390     return 0;
0391 }
0392 
0393 static int
0394 parse_dictionary_header(struct snd_soc_component *comp,
0395             struct snd_soc_tplg_vendor_array *tuples,
0396             void **dict, u32 *num_entries, size_t entry_size,
0397             u32 num_entries_token)
0398 {
0399     struct snd_soc_tplg_vendor_value_elem *tuple;
0400 
0401     /* Dictionary header consists of single tuple - entry count. */
0402     tuple = tuples->value;
0403     if (le32_to_cpu(tuple->token) != num_entries_token) {
0404         dev_err(comp->dev, "invalid dictionary header, expected: %d\n",
0405             num_entries_token);
0406         return -EINVAL;
0407     }
0408 
0409     *num_entries = le32_to_cpu(tuple->value);
0410     *dict = devm_kcalloc(comp->card->dev, *num_entries, entry_size, GFP_KERNEL);
0411     if (!*dict)
0412         return -ENOMEM;
0413 
0414     return 0;
0415 }
0416 
0417 static int
0418 parse_dictionary_entries(struct snd_soc_component *comp,
0419              struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
0420              void *dict, u32 num_entries, size_t entry_size,
0421              u32 entry_id_token,
0422              const struct avs_tplg_token_parser *parsers, size_t num_parsers)
0423 {
0424     void *pos = dict;
0425     int i;
0426 
0427     for (i = 0; i < num_entries; i++) {
0428         u32 esize;
0429         int ret;
0430 
0431         ret = avs_tplg_vendor_entry_size(tuples, block_size,
0432                          entry_id_token, &esize);
0433         if (ret)
0434             return ret;
0435 
0436         ret = avs_parse_tokens(comp, pos, parsers, num_parsers, tuples, esize);
0437         if (ret < 0) {
0438             dev_err(comp->dev, "parse entry: %d of type: %d failed: %d\n",
0439                 i, entry_id_token, ret);
0440             return ret;
0441         }
0442 
0443         pos += entry_size;
0444         block_size -= esize;
0445         tuples = avs_tplg_vendor_array_at(tuples, esize);
0446     }
0447 
0448     return 0;
0449 }
0450 
0451 static int parse_dictionary(struct snd_soc_component *comp,
0452                 struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
0453                 void **dict, u32 *num_entries, size_t entry_size,
0454                 u32 num_entries_token, u32 entry_id_token,
0455                 const struct avs_tplg_token_parser *parsers, size_t num_parsers)
0456 {
0457     int ret;
0458 
0459     ret = parse_dictionary_header(comp, tuples, dict, num_entries,
0460                       entry_size, num_entries_token);
0461     if (ret)
0462         return ret;
0463 
0464     block_size -= le32_to_cpu(tuples->size);
0465     /* With header parsed, move on to parsing entries. */
0466     tuples = avs_tplg_vendor_array_next(tuples);
0467 
0468     return parse_dictionary_entries(comp, tuples, block_size, *dict,
0469                     *num_entries, entry_size,
0470                     entry_id_token, parsers, num_parsers);
0471 }
0472 
0473 static const struct avs_tplg_token_parser library_parsers[] = {
0474     {
0475         .token = AVS_TKN_LIBRARY_NAME_STRING,
0476         .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
0477         .offset = offsetof(struct avs_tplg_library, name),
0478         .parse = avs_parse_string_token,
0479     },
0480 };
0481 
0482 static int avs_tplg_parse_libraries(struct snd_soc_component *comp,
0483                     struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
0484 {
0485     struct avs_soc_component *acomp = to_avs_soc_component(comp);
0486     struct avs_tplg *tplg = acomp->tplg;
0487 
0488     return parse_dictionary(comp, tuples, block_size, (void **)&tplg->libs,
0489                 &tplg->num_libs, sizeof(*tplg->libs),
0490                 AVS_TKN_MANIFEST_NUM_LIBRARIES_U32,
0491                 AVS_TKN_LIBRARY_ID_U32,
0492                 library_parsers, ARRAY_SIZE(library_parsers));
0493 }
0494 
0495 static const struct avs_tplg_token_parser audio_format_parsers[] = {
0496     {
0497         .token = AVS_TKN_AFMT_SAMPLE_RATE_U32,
0498         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0499         .offset = offsetof(struct avs_audio_format, sampling_freq),
0500         .parse = avs_parse_word_token,
0501     },
0502     {
0503         .token = AVS_TKN_AFMT_BIT_DEPTH_U32,
0504         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0505         .offset = offsetof(struct avs_audio_format, bit_depth),
0506         .parse = avs_parse_word_token,
0507     },
0508     {
0509         .token = AVS_TKN_AFMT_CHANNEL_MAP_U32,
0510         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0511         .offset = offsetof(struct avs_audio_format, channel_map),
0512         .parse = avs_parse_word_token,
0513     },
0514     {
0515         .token = AVS_TKN_AFMT_CHANNEL_CFG_U32,
0516         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0517         .offset = offsetof(struct avs_audio_format, channel_config),
0518         .parse = avs_parse_word_token,
0519     },
0520     {
0521         .token = AVS_TKN_AFMT_INTERLEAVING_U32,
0522         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0523         .offset = offsetof(struct avs_audio_format, interleaving),
0524         .parse = avs_parse_word_token,
0525     },
0526     {
0527         .token = AVS_TKN_AFMT_NUM_CHANNELS_U32,
0528         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0529         .offset = AVS_TKN_AFMT_NUM_CHANNELS_U32,
0530         .parse = parse_audio_format_bitfield,
0531     },
0532     {
0533         .token = AVS_TKN_AFMT_VALID_BIT_DEPTH_U32,
0534         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0535         .offset = AVS_TKN_AFMT_VALID_BIT_DEPTH_U32,
0536         .parse = parse_audio_format_bitfield,
0537     },
0538     {
0539         .token = AVS_TKN_AFMT_SAMPLE_TYPE_U32,
0540         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0541         .offset = AVS_TKN_AFMT_SAMPLE_TYPE_U32,
0542         .parse = parse_audio_format_bitfield,
0543     },
0544 };
0545 
0546 static int avs_tplg_parse_audio_formats(struct snd_soc_component *comp,
0547                     struct snd_soc_tplg_vendor_array *tuples,
0548                     u32 block_size)
0549 {
0550     struct avs_soc_component *acomp = to_avs_soc_component(comp);
0551     struct avs_tplg *tplg = acomp->tplg;
0552 
0553     return parse_dictionary(comp, tuples, block_size, (void **)&tplg->fmts,
0554                 &tplg->num_fmts, sizeof(*tplg->fmts),
0555                 AVS_TKN_MANIFEST_NUM_AFMTS_U32,
0556                 AVS_TKN_AFMT_ID_U32,
0557                 audio_format_parsers, ARRAY_SIZE(audio_format_parsers));
0558 }
0559 
0560 static const struct avs_tplg_token_parser modcfg_base_parsers[] = {
0561     {
0562         .token = AVS_TKN_MODCFG_BASE_CPC_U32,
0563         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0564         .offset = offsetof(struct avs_tplg_modcfg_base, cpc),
0565         .parse = avs_parse_word_token,
0566     },
0567     {
0568         .token = AVS_TKN_MODCFG_BASE_IBS_U32,
0569         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0570         .offset = offsetof(struct avs_tplg_modcfg_base, ibs),
0571         .parse = avs_parse_word_token,
0572     },
0573     {
0574         .token = AVS_TKN_MODCFG_BASE_OBS_U32,
0575         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0576         .offset = offsetof(struct avs_tplg_modcfg_base, obs),
0577         .parse = avs_parse_word_token,
0578     },
0579     {
0580         .token = AVS_TKN_MODCFG_BASE_PAGES_U32,
0581         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0582         .offset = offsetof(struct avs_tplg_modcfg_base, is_pages),
0583         .parse = avs_parse_word_token,
0584     },
0585 };
0586 
0587 static int avs_tplg_parse_modcfgs_base(struct snd_soc_component *comp,
0588                        struct snd_soc_tplg_vendor_array *tuples,
0589                        u32 block_size)
0590 {
0591     struct avs_soc_component *acomp = to_avs_soc_component(comp);
0592     struct avs_tplg *tplg = acomp->tplg;
0593 
0594     return parse_dictionary(comp, tuples, block_size, (void **)&tplg->modcfgs_base,
0595                 &tplg->num_modcfgs_base, sizeof(*tplg->modcfgs_base),
0596                 AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32,
0597                 AVS_TKN_MODCFG_BASE_ID_U32,
0598                 modcfg_base_parsers, ARRAY_SIZE(modcfg_base_parsers));
0599 }
0600 
0601 static const struct avs_tplg_token_parser modcfg_ext_parsers[] = {
0602     {
0603         .token = AVS_TKN_MODCFG_EXT_TYPE_UUID,
0604         .type = SND_SOC_TPLG_TUPLE_TYPE_UUID,
0605         .offset = offsetof(struct avs_tplg_modcfg_ext, type),
0606         .parse = avs_parse_uuid_token,
0607     },
0608     {
0609         .token = AVS_TKN_MODCFG_CPR_OUT_AFMT_ID_U32,
0610         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0611         .offset = offsetof(struct avs_tplg_modcfg_ext, copier.out_fmt),
0612         .parse = avs_parse_audio_format_ptr,
0613     },
0614     {
0615         .token = AVS_TKN_MODCFG_CPR_FEATURE_MASK_U32,
0616         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0617         .offset = offsetof(struct avs_tplg_modcfg_ext, copier.feature_mask),
0618         .parse = avs_parse_word_token,
0619     },
0620     {
0621         .token = AVS_TKN_MODCFG_CPR_VINDEX_U8,
0622         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
0623         .offset = offsetof(struct avs_tplg_modcfg_ext, copier.vindex),
0624         .parse = avs_parse_byte_token,
0625     },
0626     {
0627         .token = AVS_TKN_MODCFG_CPR_DMA_TYPE_U32,
0628         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0629         .offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_type),
0630         .parse = avs_parse_word_token,
0631     },
0632     {
0633         .token = AVS_TKN_MODCFG_CPR_DMABUFF_SIZE_U32,
0634         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0635         .offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_buffer_size),
0636         .parse = avs_parse_word_token,
0637     },
0638     {
0639         .token = AVS_TKN_MODCFG_CPR_BLOB_FMT_ID_U32,
0640         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0641         .offset = offsetof(struct avs_tplg_modcfg_ext, copier.blob_fmt),
0642         .parse = avs_parse_audio_format_ptr,
0643     },
0644     {
0645         .token = AVS_TKN_MODCFG_MICSEL_OUT_AFMT_ID_U32,
0646         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0647         .offset = offsetof(struct avs_tplg_modcfg_ext, micsel.out_fmt),
0648         .parse = avs_parse_audio_format_ptr,
0649     },
0650     {
0651         .token = AVS_TKN_MODCFG_INTELWOV_CPC_LP_MODE_U32,
0652         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0653         .offset = offsetof(struct avs_tplg_modcfg_ext, wov.cpc_lp_mode),
0654         .parse = avs_parse_word_token,
0655     },
0656     {
0657         .token = AVS_TKN_MODCFG_SRC_OUT_FREQ_U32,
0658         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0659         .offset = offsetof(struct avs_tplg_modcfg_ext, src.out_freq),
0660         .parse = avs_parse_word_token,
0661     },
0662     {
0663         .token = AVS_TKN_MODCFG_MUX_REF_AFMT_ID_U32,
0664         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0665         .offset = offsetof(struct avs_tplg_modcfg_ext, mux.ref_fmt),
0666         .parse = avs_parse_audio_format_ptr,
0667     },
0668     {
0669         .token = AVS_TKN_MODCFG_MUX_OUT_AFMT_ID_U32,
0670         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0671         .offset = offsetof(struct avs_tplg_modcfg_ext, mux.out_fmt),
0672         .parse = avs_parse_audio_format_ptr,
0673     },
0674     {
0675         .token = AVS_TKN_MODCFG_AEC_REF_AFMT_ID_U32,
0676         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0677         .offset = offsetof(struct avs_tplg_modcfg_ext, aec.ref_fmt),
0678         .parse = avs_parse_audio_format_ptr,
0679     },
0680     {
0681         .token = AVS_TKN_MODCFG_AEC_OUT_AFMT_ID_U32,
0682         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0683         .offset = offsetof(struct avs_tplg_modcfg_ext, aec.out_fmt),
0684         .parse = avs_parse_audio_format_ptr,
0685     },
0686     {
0687         .token = AVS_TKN_MODCFG_AEC_CPC_LP_MODE_U32,
0688         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0689         .offset = offsetof(struct avs_tplg_modcfg_ext, aec.cpc_lp_mode),
0690         .parse = avs_parse_word_token,
0691     },
0692     {
0693         .token = AVS_TKN_MODCFG_ASRC_OUT_FREQ_U32,
0694         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0695         .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.out_freq),
0696         .parse = avs_parse_word_token,
0697     },
0698     {
0699         .token = AVS_TKN_MODCFG_ASRC_MODE_U8,
0700         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
0701         .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.mode),
0702         .parse = avs_parse_byte_token,
0703     },
0704     {
0705         .token = AVS_TKN_MODCFG_ASRC_DISABLE_JITTER_U8,
0706         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
0707         .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.disable_jitter_buffer),
0708         .parse = avs_parse_byte_token,
0709     },
0710     {
0711         .token = AVS_TKN_MODCFG_UPDOWN_MIX_OUT_CHAN_CFG_U32,
0712         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0713         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.out_channel_config),
0714         .parse = avs_parse_word_token,
0715     },
0716     {
0717         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_SELECT_U32,
0718         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0719         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients_select),
0720         .parse = avs_parse_word_token,
0721     },
0722     {
0723         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_0_S32,
0724         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0725         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[0]),
0726         .parse = avs_parse_word_token,
0727     },
0728     {
0729         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_1_S32,
0730         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0731         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[1]),
0732         .parse = avs_parse_word_token,
0733     },
0734     {
0735         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_2_S32,
0736         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0737         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[2]),
0738         .parse = avs_parse_word_token,
0739     },
0740     {
0741         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_3_S32,
0742         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0743         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[3]),
0744         .parse = avs_parse_word_token,
0745     },
0746     {
0747         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_4_S32,
0748         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0749         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[4]),
0750         .parse = avs_parse_word_token,
0751     },
0752     {
0753         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_5_S32,
0754         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0755         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[5]),
0756         .parse = avs_parse_word_token,
0757     },
0758     {
0759         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_6_S32,
0760         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0761         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[6]),
0762         .parse = avs_parse_word_token,
0763     },
0764     {
0765         .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_7_S32,
0766         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0767         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[7]),
0768         .parse = avs_parse_word_token,
0769     },
0770     {
0771         .token = AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32,
0772         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0773         .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.channel_map),
0774         .parse = avs_parse_word_token,
0775     },
0776     {
0777         .token = AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16,
0778         .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
0779         .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_input_pins),
0780         .parse = avs_parse_short_token,
0781     },
0782     {
0783         .token = AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16,
0784         .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
0785         .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_output_pins),
0786         .parse = avs_parse_short_token,
0787     },
0788 };
0789 
0790 static const struct avs_tplg_token_parser pin_format_parsers[] = {
0791     {
0792         .token = AVS_TKN_PIN_FMT_INDEX_U32,
0793         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0794         .offset = offsetof(struct avs_tplg_pin_format, pin_index),
0795         .parse = avs_parse_word_token,
0796     },
0797     {
0798         .token = AVS_TKN_PIN_FMT_IOBS_U32,
0799         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0800         .offset = offsetof(struct avs_tplg_pin_format, iobs),
0801         .parse = avs_parse_word_token,
0802     },
0803     {
0804         .token = AVS_TKN_PIN_FMT_AFMT_ID_U32,
0805         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0806         .offset = offsetof(struct avs_tplg_pin_format, fmt),
0807         .parse = avs_parse_audio_format_ptr,
0808     },
0809 };
0810 
0811 static void
0812 assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg)
0813 {
0814     struct snd_soc_acpi_mach *mach;
0815 
0816     if (!guid_equal(&cfg->type, &AVS_COPIER_MOD_UUID))
0817         return;
0818 
0819     /* Only I2S boards assign port instance in ->i2s_link_mask. */
0820     switch (cfg->copier.dma_type) {
0821     case AVS_DMA_I2S_LINK_OUTPUT:
0822     case AVS_DMA_I2S_LINK_INPUT:
0823         break;
0824     default:
0825         return;
0826     }
0827 
0828     mach = dev_get_platdata(comp->card->dev);
0829 
0830     /* Automatic assignment only when board describes single SSP. */
0831     if (hweight_long(mach->mach_params.i2s_link_mask) == 1 && !cfg->copier.vindex.i2s.instance)
0832         cfg->copier.vindex.i2s.instance = __ffs(mach->mach_params.i2s_link_mask);
0833 }
0834 
0835 static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp,
0836                      struct avs_tplg_modcfg_ext *cfg,
0837                      struct snd_soc_tplg_vendor_array *tuples,
0838                      u32 block_size)
0839 {
0840     u32 esize;
0841     int ret;
0842 
0843     /* See where pin block starts. */
0844     ret = avs_tplg_vendor_entry_size(tuples, block_size,
0845                      AVS_TKN_PIN_FMT_INDEX_U32, &esize);
0846     if (ret)
0847         return ret;
0848 
0849     ret = avs_parse_tokens(comp, cfg, modcfg_ext_parsers,
0850                    ARRAY_SIZE(modcfg_ext_parsers), tuples, esize);
0851     if (ret)
0852         return ret;
0853 
0854     /* Update copier gateway based on board's i2s_link_mask. */
0855     assign_copier_gtw_instance(comp, cfg);
0856 
0857     block_size -= esize;
0858     /* Parse trailing in/out pin formats if any. */
0859     if (block_size) {
0860         struct avs_tplg_pin_format *pins;
0861         u32 num_pins;
0862 
0863         num_pins = cfg->generic.num_input_pins + cfg->generic.num_output_pins;
0864         if (!num_pins)
0865             return -EINVAL;
0866 
0867         pins = devm_kcalloc(comp->card->dev, num_pins, sizeof(*pins), GFP_KERNEL);
0868         if (!pins)
0869             return -ENOMEM;
0870 
0871         tuples = avs_tplg_vendor_array_at(tuples, esize);
0872         ret = parse_dictionary_entries(comp, tuples, block_size,
0873                            pins, num_pins, sizeof(*pins),
0874                            AVS_TKN_PIN_FMT_INDEX_U32,
0875                            pin_format_parsers,
0876                            ARRAY_SIZE(pin_format_parsers));
0877         if (ret)
0878             return ret;
0879         cfg->generic.pin_fmts = pins;
0880     }
0881 
0882     return 0;
0883 }
0884 
0885 static int avs_tplg_parse_modcfgs_ext(struct snd_soc_component *comp,
0886                       struct snd_soc_tplg_vendor_array *tuples,
0887                       u32 block_size)
0888 {
0889     struct avs_soc_component *acomp = to_avs_soc_component(comp);
0890     struct avs_tplg *tplg = acomp->tplg;
0891     int ret, i;
0892 
0893     ret = parse_dictionary_header(comp, tuples, (void **)&tplg->modcfgs_ext,
0894                       &tplg->num_modcfgs_ext,
0895                       sizeof(*tplg->modcfgs_ext),
0896                       AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32);
0897     if (ret)
0898         return ret;
0899 
0900     block_size -= le32_to_cpu(tuples->size);
0901     /* With header parsed, move on to parsing entries. */
0902     tuples = avs_tplg_vendor_array_next(tuples);
0903 
0904     for (i = 0; i < tplg->num_modcfgs_ext; i++) {
0905         struct avs_tplg_modcfg_ext *cfg = &tplg->modcfgs_ext[i];
0906         u32 esize;
0907 
0908         ret = avs_tplg_vendor_entry_size(tuples, block_size,
0909                          AVS_TKN_MODCFG_EXT_ID_U32, &esize);
0910         if (ret)
0911             return ret;
0912 
0913         ret = avs_tplg_parse_modcfg_ext(comp, cfg, tuples, esize);
0914         if (ret)
0915             return ret;
0916 
0917         block_size -= esize;
0918         tuples = avs_tplg_vendor_array_at(tuples, esize);
0919     }
0920 
0921     return 0;
0922 }
0923 
0924 static const struct avs_tplg_token_parser pplcfg_parsers[] = {
0925     {
0926         .token = AVS_TKN_PPLCFG_REQ_SIZE_U16,
0927         .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
0928         .offset = offsetof(struct avs_tplg_pplcfg, req_size),
0929         .parse = avs_parse_short_token,
0930     },
0931     {
0932         .token = AVS_TKN_PPLCFG_PRIORITY_U8,
0933         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
0934         .offset = offsetof(struct avs_tplg_pplcfg, priority),
0935         .parse = avs_parse_byte_token,
0936     },
0937     {
0938         .token = AVS_TKN_PPLCFG_LOW_POWER_BOOL,
0939         .type = SND_SOC_TPLG_TUPLE_TYPE_BOOL,
0940         .offset = offsetof(struct avs_tplg_pplcfg, lp),
0941         .parse = avs_parse_bool_token,
0942     },
0943     {
0944         .token = AVS_TKN_PPLCFG_ATTRIBUTES_U16,
0945         .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
0946         .offset = offsetof(struct avs_tplg_pplcfg, attributes),
0947         .parse = avs_parse_short_token,
0948     },
0949     {
0950         .token = AVS_TKN_PPLCFG_TRIGGER_U32,
0951         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0952         .offset = offsetof(struct avs_tplg_pplcfg, trigger),
0953         .parse = avs_parse_word_token,
0954     },
0955 };
0956 
0957 static int avs_tplg_parse_pplcfgs(struct snd_soc_component *comp,
0958                   struct snd_soc_tplg_vendor_array *tuples,
0959                   u32 block_size)
0960 {
0961     struct avs_soc_component *acomp = to_avs_soc_component(comp);
0962     struct avs_tplg *tplg = acomp->tplg;
0963 
0964     return parse_dictionary(comp, tuples, block_size, (void **)&tplg->pplcfgs,
0965                 &tplg->num_pplcfgs, sizeof(*tplg->pplcfgs),
0966                 AVS_TKN_MANIFEST_NUM_PPLCFGS_U32,
0967                 AVS_TKN_PPLCFG_ID_U32,
0968                 pplcfg_parsers, ARRAY_SIZE(pplcfg_parsers));
0969 }
0970 
0971 static const struct avs_tplg_token_parser binding_parsers[] = {
0972     {
0973         .token = AVS_TKN_BINDING_TARGET_TPLG_NAME_STRING,
0974         .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
0975         .offset = offsetof(struct avs_tplg_binding, target_tplg_name),
0976         .parse = parse_link_formatted_string,
0977     },
0978     {
0979         .token = AVS_TKN_BINDING_TARGET_PATH_TMPL_ID_U32,
0980         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0981         .offset = offsetof(struct avs_tplg_binding, target_path_tmpl_id),
0982         .parse = avs_parse_word_token,
0983     },
0984     {
0985         .token = AVS_TKN_BINDING_TARGET_PPL_ID_U32,
0986         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0987         .offset = offsetof(struct avs_tplg_binding, target_ppl_id),
0988         .parse = avs_parse_word_token,
0989     },
0990     {
0991         .token = AVS_TKN_BINDING_TARGET_MOD_ID_U32,
0992         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
0993         .offset = offsetof(struct avs_tplg_binding, target_mod_id),
0994         .parse = avs_parse_word_token,
0995     },
0996     {
0997         .token = AVS_TKN_BINDING_TARGET_MOD_PIN_U8,
0998         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
0999         .offset = offsetof(struct avs_tplg_binding, target_mod_pin),
1000         .parse = avs_parse_byte_token,
1001     },
1002     {
1003         .token = AVS_TKN_BINDING_MOD_ID_U32,
1004         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1005         .offset = offsetof(struct avs_tplg_binding, mod_id),
1006         .parse = avs_parse_word_token,
1007     },
1008     {
1009         .token = AVS_TKN_BINDING_MOD_PIN_U8,
1010         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1011         .offset = offsetof(struct avs_tplg_binding, mod_pin),
1012         .parse = avs_parse_byte_token,
1013     },
1014     {
1015         .token = AVS_TKN_BINDING_IS_SINK_U8,
1016         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1017         .offset = offsetof(struct avs_tplg_binding, is_sink),
1018         .parse = avs_parse_byte_token,
1019     },
1020 };
1021 
1022 static int avs_tplg_parse_bindings(struct snd_soc_component *comp,
1023                    struct snd_soc_tplg_vendor_array *tuples,
1024                    u32 block_size)
1025 {
1026     struct avs_soc_component *acomp = to_avs_soc_component(comp);
1027     struct avs_tplg *tplg = acomp->tplg;
1028 
1029     return parse_dictionary(comp, tuples, block_size, (void **)&tplg->bindings,
1030                 &tplg->num_bindings, sizeof(*tplg->bindings),
1031                 AVS_TKN_MANIFEST_NUM_BINDINGS_U32,
1032                 AVS_TKN_BINDING_ID_U32,
1033                 binding_parsers, ARRAY_SIZE(binding_parsers));
1034 }
1035 
1036 static const struct avs_tplg_token_parser module_parsers[] = {
1037     {
1038         .token = AVS_TKN_MOD_ID_U32,
1039         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1040         .offset = offsetof(struct avs_tplg_module, id),
1041         .parse = avs_parse_word_token,
1042     },
1043     {
1044         .token = AVS_TKN_MOD_MODCFG_BASE_ID_U32,
1045         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1046         .offset = offsetof(struct avs_tplg_module, cfg_base),
1047         .parse = avs_parse_modcfg_base_ptr,
1048     },
1049     {
1050         .token = AVS_TKN_MOD_IN_AFMT_ID_U32,
1051         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1052         .offset = offsetof(struct avs_tplg_module, in_fmt),
1053         .parse = avs_parse_audio_format_ptr,
1054     },
1055     {
1056         .token = AVS_TKN_MOD_CORE_ID_U8,
1057         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1058         .offset = offsetof(struct avs_tplg_module, core_id),
1059         .parse = avs_parse_byte_token,
1060     },
1061     {
1062         .token = AVS_TKN_MOD_PROC_DOMAIN_U8,
1063         .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
1064         .offset = offsetof(struct avs_tplg_module, domain),
1065         .parse = avs_parse_byte_token,
1066     },
1067     {
1068         .token = AVS_TKN_MOD_MODCFG_EXT_ID_U32,
1069         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1070         .offset = offsetof(struct avs_tplg_module, cfg_ext),
1071         .parse = avs_parse_modcfg_ext_ptr,
1072     },
1073 };
1074 
1075 static struct avs_tplg_module *
1076 avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline *owner,
1077                struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1078 {
1079     struct avs_tplg_module *module;
1080     int ret;
1081 
1082     module = devm_kzalloc(comp->card->dev, sizeof(*module), GFP_KERNEL);
1083     if (!module)
1084         return ERR_PTR(-ENOMEM);
1085 
1086     ret = avs_parse_tokens(comp, module, module_parsers,
1087                    ARRAY_SIZE(module_parsers), tuples, block_size);
1088     if (ret < 0)
1089         return ERR_PTR(ret);
1090 
1091     module->owner = owner;
1092     INIT_LIST_HEAD(&module->node);
1093 
1094     return module;
1095 }
1096 
1097 static const struct avs_tplg_token_parser pipeline_parsers[] = {
1098     {
1099         .token = AVS_TKN_PPL_ID_U32,
1100         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1101         .offset = offsetof(struct avs_tplg_pipeline, id),
1102         .parse = avs_parse_word_token,
1103     },
1104     {
1105         .token = AVS_TKN_PPL_PPLCFG_ID_U32,
1106         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1107         .offset = offsetof(struct avs_tplg_pipeline, cfg),
1108         .parse = avs_parse_pplcfg_ptr,
1109     },
1110     {
1111         .token = AVS_TKN_PPL_NUM_BINDING_IDS_U32,
1112         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1113         .offset = offsetof(struct avs_tplg_pipeline, num_bindings),
1114         .parse = avs_parse_word_token,
1115     },
1116 };
1117 
1118 static const struct avs_tplg_token_parser bindings_parsers[] = {
1119     {
1120         .token = AVS_TKN_PPL_BINDING_ID_U32,
1121         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1122         .offset = 0, /* to treat pipeline->bindings as dictionary */
1123         .parse = avs_parse_binding_ptr,
1124     },
1125 };
1126 
1127 static struct avs_tplg_pipeline *
1128 avs_tplg_pipeline_create(struct snd_soc_component *comp, struct avs_tplg_path *owner,
1129              struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1130 {
1131     struct avs_tplg_pipeline *pipeline;
1132     u32 modblk_size, offset;
1133     int ret;
1134 
1135     pipeline = devm_kzalloc(comp->card->dev, sizeof(*pipeline), GFP_KERNEL);
1136     if (!pipeline)
1137         return ERR_PTR(-ENOMEM);
1138 
1139     pipeline->owner = owner;
1140     INIT_LIST_HEAD(&pipeline->mod_list);
1141 
1142     /* Pipeline header MUST be followed by at least one module. */
1143     ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1144                        AVS_TKN_MOD_ID_U32, &offset);
1145     if (!ret && !offset)
1146         ret = -EINVAL;
1147     if (ret)
1148         return ERR_PTR(ret);
1149 
1150     /* Process header which precedes module sections. */
1151     ret = avs_parse_tokens(comp, pipeline, pipeline_parsers,
1152                    ARRAY_SIZE(pipeline_parsers), tuples, offset);
1153     if (ret < 0)
1154         return ERR_PTR(ret);
1155 
1156     block_size -= offset;
1157     tuples = avs_tplg_vendor_array_at(tuples, offset);
1158 
1159     /* Optionally, binding sections follow module ones. */
1160     ret = avs_tplg_vendor_array_lookup_next(tuples, block_size,
1161                         AVS_TKN_PPL_BINDING_ID_U32, &offset);
1162     if (ret) {
1163         if (ret != -ENOENT)
1164             return ERR_PTR(ret);
1165 
1166         /* Does header information match actual block layout? */
1167         if (pipeline->num_bindings)
1168             return ERR_PTR(-EINVAL);
1169 
1170         modblk_size = block_size;
1171     } else {
1172         pipeline->bindings = devm_kcalloc(comp->card->dev, pipeline->num_bindings,
1173                           sizeof(*pipeline->bindings), GFP_KERNEL);
1174         if (!pipeline->bindings)
1175             return ERR_PTR(-ENOMEM);
1176 
1177         modblk_size = offset;
1178     }
1179 
1180     block_size -= modblk_size;
1181     do {
1182         struct avs_tplg_module *module;
1183         u32 esize;
1184 
1185         ret = avs_tplg_vendor_entry_size(tuples, modblk_size,
1186                          AVS_TKN_MOD_ID_U32, &esize);
1187         if (ret)
1188             return ERR_PTR(ret);
1189 
1190         module = avs_tplg_module_create(comp, pipeline, tuples, esize);
1191         if (IS_ERR(module)) {
1192             dev_err(comp->dev, "parse module failed: %ld\n",
1193                 PTR_ERR(module));
1194             return ERR_CAST(module);
1195         }
1196 
1197         list_add_tail(&module->node, &pipeline->mod_list);
1198         modblk_size -= esize;
1199         tuples = avs_tplg_vendor_array_at(tuples, esize);
1200     } while (modblk_size > 0);
1201 
1202     /* What's left is optional range of bindings. */
1203     ret = parse_dictionary_entries(comp, tuples, block_size, pipeline->bindings,
1204                        pipeline->num_bindings, sizeof(*pipeline->bindings),
1205                        AVS_TKN_PPL_BINDING_ID_U32,
1206                        bindings_parsers, ARRAY_SIZE(bindings_parsers));
1207     if (ret)
1208         return ERR_PTR(ret);
1209 
1210     return pipeline;
1211 }
1212 
1213 static const struct avs_tplg_token_parser path_parsers[] = {
1214     {
1215         .token = AVS_TKN_PATH_ID_U32,
1216         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1217         .offset = offsetof(struct avs_tplg_path, id),
1218         .parse = avs_parse_word_token,
1219     },
1220     {
1221         .token = AVS_TKN_PATH_FE_FMT_ID_U32,
1222         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1223         .offset = offsetof(struct avs_tplg_path, fe_fmt),
1224         .parse = avs_parse_audio_format_ptr,
1225     },
1226     {
1227         .token = AVS_TKN_PATH_BE_FMT_ID_U32,
1228         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1229         .offset = offsetof(struct avs_tplg_path, be_fmt),
1230         .parse = avs_parse_audio_format_ptr,
1231     },
1232 };
1233 
1234 static struct avs_tplg_path *
1235 avs_tplg_path_create(struct snd_soc_component *comp, struct avs_tplg_path_template *owner,
1236              struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
1237              const struct avs_tplg_token_parser *parsers, u32 num_parsers)
1238 {
1239     struct avs_tplg_pipeline *pipeline;
1240     struct avs_tplg_path *path;
1241     u32 offset;
1242     int ret;
1243 
1244     path = devm_kzalloc(comp->card->dev, sizeof(*path), GFP_KERNEL);
1245     if (!path)
1246         return ERR_PTR(-ENOMEM);
1247 
1248     path->owner = owner;
1249     INIT_LIST_HEAD(&path->ppl_list);
1250     INIT_LIST_HEAD(&path->node);
1251 
1252     /* Path header MAY be followed by one or more pipelines. */
1253     ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1254                        AVS_TKN_PPL_ID_U32, &offset);
1255     if (ret == -ENOENT)
1256         offset = block_size;
1257     else if (ret)
1258         return ERR_PTR(ret);
1259     else if (!offset)
1260         return ERR_PTR(-EINVAL);
1261 
1262     /* Process header which precedes pipeline sections. */
1263     ret = avs_parse_tokens(comp, path, parsers, num_parsers, tuples, offset);
1264     if (ret < 0)
1265         return ERR_PTR(ret);
1266 
1267     block_size -= offset;
1268     tuples = avs_tplg_vendor_array_at(tuples, offset);
1269     while (block_size > 0) {
1270         u32 esize;
1271 
1272         ret = avs_tplg_vendor_entry_size(tuples, block_size,
1273                          AVS_TKN_PPL_ID_U32, &esize);
1274         if (ret)
1275             return ERR_PTR(ret);
1276 
1277         pipeline = avs_tplg_pipeline_create(comp, path, tuples, esize);
1278         if (IS_ERR(pipeline)) {
1279             dev_err(comp->dev, "parse pipeline failed: %ld\n",
1280                 PTR_ERR(pipeline));
1281             return ERR_CAST(pipeline);
1282         }
1283 
1284         list_add_tail(&pipeline->node, &path->ppl_list);
1285         block_size -= esize;
1286         tuples = avs_tplg_vendor_array_at(tuples, esize);
1287     }
1288 
1289     return path;
1290 }
1291 
1292 static const struct avs_tplg_token_parser path_tmpl_parsers[] = {
1293     {
1294         .token = AVS_TKN_PATH_TMPL_ID_U32,
1295         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1296         .offset = offsetof(struct avs_tplg_path_template, id),
1297         .parse = avs_parse_word_token,
1298     },
1299 };
1300 
1301 static int parse_path_template(struct snd_soc_component *comp,
1302                    struct snd_soc_tplg_vendor_array *tuples, u32 block_size,
1303                    struct avs_tplg_path_template *template,
1304                    const struct avs_tplg_token_parser *tmpl_tokens, u32 num_tmpl_tokens,
1305                    const struct avs_tplg_token_parser *path_tokens, u32 num_path_tokens)
1306 {
1307     struct avs_tplg_path *path;
1308     u32 offset;
1309     int ret;
1310 
1311     /* Path template header MUST be followed by at least one path variant. */
1312     ret = avs_tplg_vendor_array_lookup(tuples, block_size,
1313                        AVS_TKN_PATH_ID_U32, &offset);
1314     if (ret)
1315         return ret;
1316 
1317     /* Process header which precedes path variants sections. */
1318     ret = avs_parse_tokens(comp, template, tmpl_tokens, num_tmpl_tokens, tuples, offset);
1319     if (ret < 0)
1320         return ret;
1321 
1322     block_size -= offset;
1323     tuples = avs_tplg_vendor_array_at(tuples, offset);
1324     do {
1325         u32 esize;
1326 
1327         ret = avs_tplg_vendor_entry_size(tuples, block_size,
1328                          AVS_TKN_PATH_ID_U32, &esize);
1329         if (ret)
1330             return ret;
1331 
1332         path = avs_tplg_path_create(comp, template, tuples, esize, path_tokens,
1333                         num_path_tokens);
1334         if (IS_ERR(path)) {
1335             dev_err(comp->dev, "parse path failed: %ld\n", PTR_ERR(path));
1336             return PTR_ERR(path);
1337         }
1338 
1339         list_add_tail(&path->node, &template->path_list);
1340         block_size -= esize;
1341         tuples = avs_tplg_vendor_array_at(tuples, esize);
1342     } while (block_size > 0);
1343 
1344     return 0;
1345 }
1346 
1347 static struct avs_tplg_path_template *
1348 avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *owner,
1349                   struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
1350 {
1351     struct avs_tplg_path_template *template;
1352     int ret;
1353 
1354     template = devm_kzalloc(comp->card->dev, sizeof(*template), GFP_KERNEL);
1355     if (!template)
1356         return ERR_PTR(-ENOMEM);
1357 
1358     template->owner = owner; /* Used to access component tplg is assigned to. */
1359     INIT_LIST_HEAD(&template->path_list);
1360     INIT_LIST_HEAD(&template->node);
1361 
1362     ret = parse_path_template(comp, tuples, block_size, template, path_tmpl_parsers,
1363                   ARRAY_SIZE(path_tmpl_parsers), path_parsers,
1364                   ARRAY_SIZE(path_parsers));
1365     if (ret)
1366         return ERR_PTR(ret);
1367 
1368     return template;
1369 }
1370 
1371 static int avs_route_load(struct snd_soc_component *comp, int index,
1372               struct snd_soc_dapm_route *route)
1373 {
1374     struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
1375     size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
1376     char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1377     u32 port;
1378 
1379     /* See parse_link_formatted_string() for dynamic naming when(s). */
1380     if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
1381         port = __ffs(mach->mach_params.i2s_link_mask);
1382 
1383         snprintf(buf, len, route->source, port);
1384         strncpy((char *)route->source, buf, len);
1385         snprintf(buf, len, route->sink, port);
1386         strncpy((char *)route->sink, buf, len);
1387         if (route->control) {
1388             snprintf(buf, len, route->control, port);
1389             strncpy((char *)route->control, buf, len);
1390         }
1391     }
1392 
1393     return 0;
1394 }
1395 
1396 static int avs_widget_load(struct snd_soc_component *comp, int index,
1397                struct snd_soc_dapm_widget *w,
1398                struct snd_soc_tplg_dapm_widget *dw)
1399 {
1400     struct snd_soc_acpi_mach *mach;
1401     struct avs_tplg_path_template *template;
1402     struct avs_soc_component *acomp = to_avs_soc_component(comp);
1403     struct avs_tplg *tplg;
1404 
1405     if (!le32_to_cpu(dw->priv.size))
1406         return 0;
1407 
1408     tplg = acomp->tplg;
1409     mach = dev_get_platdata(comp->card->dev);
1410 
1411     /* See parse_link_formatted_string() for dynamic naming when(s). */
1412     if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
1413         kfree(w->name);
1414         /* w->name is freed later by soc_tplg_dapm_widget_create() */
1415         w->name = kasprintf(GFP_KERNEL, dw->name, __ffs(mach->mach_params.i2s_link_mask));
1416         if (!w->name)
1417             return -ENOMEM;
1418     }
1419 
1420     template = avs_tplg_path_template_create(comp, tplg, dw->priv.array,
1421                          le32_to_cpu(dw->priv.size));
1422     if (IS_ERR(template)) {
1423         dev_err(comp->dev, "widget %s load failed: %ld\n", dw->name,
1424             PTR_ERR(template));
1425         return PTR_ERR(template);
1426     }
1427 
1428     w->priv = template; /* link path information to widget */
1429     list_add_tail(&template->node, &tplg->path_tmpl_list);
1430     return 0;
1431 }
1432 
1433 static int avs_dai_load(struct snd_soc_component *comp, int index,
1434             struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm,
1435             struct snd_soc_dai *dai)
1436 {
1437     if (pcm)
1438         dai_drv->ops = &avs_dai_fe_ops;
1439     return 0;
1440 }
1441 
1442 static int avs_link_load(struct snd_soc_component *comp, int index, struct snd_soc_dai_link *link,
1443              struct snd_soc_tplg_link_config *cfg)
1444 {
1445     if (!link->no_pcm) {
1446         /* Stream control handled by IPCs. */
1447         link->nonatomic = true;
1448 
1449         /* Open LINK (BE) pipes last and close them first to prevent xruns. */
1450         link->trigger[0] = SND_SOC_DPCM_TRIGGER_PRE;
1451         link->trigger[1] = SND_SOC_DPCM_TRIGGER_PRE;
1452     }
1453 
1454     return 0;
1455 }
1456 
1457 static const struct avs_tplg_token_parser manifest_parsers[] = {
1458     {
1459         .token = AVS_TKN_MANIFEST_NAME_STRING,
1460         .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
1461         .offset = offsetof(struct avs_tplg, name),
1462         .parse = parse_link_formatted_string,
1463     },
1464     {
1465         .token = AVS_TKN_MANIFEST_VERSION_U32,
1466         .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
1467         .offset = offsetof(struct avs_tplg, version),
1468         .parse = avs_parse_word_token,
1469     },
1470 };
1471 
1472 static int avs_manifest(struct snd_soc_component *comp, int index,
1473             struct snd_soc_tplg_manifest *manifest)
1474 {
1475     struct snd_soc_tplg_vendor_array *tuples = manifest->priv.array;
1476     struct avs_soc_component *acomp = to_avs_soc_component(comp);
1477     size_t remaining = le32_to_cpu(manifest->priv.size);
1478     u32 offset;
1479     int ret;
1480 
1481     ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1482                        AVS_TKN_MANIFEST_NUM_LIBRARIES_U32, &offset);
1483     /* Manifest MUST begin with a header. */
1484     if (!ret && !offset)
1485         ret = -EINVAL;
1486     if (ret) {
1487         dev_err(comp->dev, "incorrect manifest format: %d\n", ret);
1488         return ret;
1489     }
1490 
1491     /* Process header which precedes any of the dictionaries. */
1492     ret = avs_parse_tokens(comp, acomp->tplg, manifest_parsers,
1493                    ARRAY_SIZE(manifest_parsers), tuples, offset);
1494     if (ret < 0)
1495         return ret;
1496 
1497     remaining -= offset;
1498     tuples = avs_tplg_vendor_array_at(tuples, offset);
1499 
1500     ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1501                        AVS_TKN_MANIFEST_NUM_AFMTS_U32, &offset);
1502     if (ret) {
1503         dev_err(comp->dev, "audio formats lookup failed: %d\n", ret);
1504         return ret;
1505     }
1506 
1507     /* Libraries dictionary. */
1508     ret = avs_tplg_parse_libraries(comp, tuples, offset);
1509     if (ret < 0)
1510         return ret;
1511 
1512     remaining -= offset;
1513     tuples = avs_tplg_vendor_array_at(tuples, offset);
1514 
1515     ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1516                        AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32, &offset);
1517     if (ret) {
1518         dev_err(comp->dev, "modcfgs_base lookup failed: %d\n", ret);
1519         return ret;
1520     }
1521 
1522     /* Audio formats dictionary. */
1523     ret = avs_tplg_parse_audio_formats(comp, tuples, offset);
1524     if (ret < 0)
1525         return ret;
1526 
1527     remaining -= offset;
1528     tuples = avs_tplg_vendor_array_at(tuples, offset);
1529 
1530     ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1531                        AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32, &offset);
1532     if (ret) {
1533         dev_err(comp->dev, "modcfgs_ext lookup failed: %d\n", ret);
1534         return ret;
1535     }
1536 
1537     /* Module configs-base dictionary. */
1538     ret = avs_tplg_parse_modcfgs_base(comp, tuples, offset);
1539     if (ret < 0)
1540         return ret;
1541 
1542     remaining -= offset;
1543     tuples = avs_tplg_vendor_array_at(tuples, offset);
1544 
1545     ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1546                        AVS_TKN_MANIFEST_NUM_PPLCFGS_U32, &offset);
1547     if (ret) {
1548         dev_err(comp->dev, "pplcfgs lookup failed: %d\n", ret);
1549         return ret;
1550     }
1551 
1552     /* Module configs-ext dictionary. */
1553     ret = avs_tplg_parse_modcfgs_ext(comp, tuples, offset);
1554     if (ret < 0)
1555         return ret;
1556 
1557     remaining -= offset;
1558     tuples = avs_tplg_vendor_array_at(tuples, offset);
1559 
1560     ret = avs_tplg_vendor_array_lookup(tuples, remaining,
1561                        AVS_TKN_MANIFEST_NUM_BINDINGS_U32, &offset);
1562     if (ret) {
1563         dev_err(comp->dev, "bindings lookup failed: %d\n", ret);
1564         return ret;
1565     }
1566 
1567     /* Pipeline configs dictionary. */
1568     ret = avs_tplg_parse_pplcfgs(comp, tuples, offset);
1569     if (ret < 0)
1570         return ret;
1571 
1572     remaining -= offset;
1573     tuples = avs_tplg_vendor_array_at(tuples, offset);
1574 
1575     /* Bindings dictionary. */
1576     return avs_tplg_parse_bindings(comp, tuples, remaining);
1577 }
1578 
1579 static struct snd_soc_tplg_ops avs_tplg_ops = {
1580     .dapm_route_load    = avs_route_load,
1581     .widget_load        = avs_widget_load,
1582     .dai_load       = avs_dai_load,
1583     .link_load      = avs_link_load,
1584     .manifest       = avs_manifest,
1585 };
1586 
1587 struct avs_tplg *avs_tplg_new(struct snd_soc_component *comp)
1588 {
1589     struct avs_tplg *tplg;
1590 
1591     tplg = devm_kzalloc(comp->card->dev, sizeof(*tplg), GFP_KERNEL);
1592     if (!tplg)
1593         return NULL;
1594 
1595     tplg->comp = comp;
1596     INIT_LIST_HEAD(&tplg->path_tmpl_list);
1597 
1598     return tplg;
1599 }
1600 
1601 int avs_load_topology(struct snd_soc_component *comp, const char *filename)
1602 {
1603     const struct firmware *fw;
1604     int ret;
1605 
1606     ret = request_firmware(&fw, filename, comp->dev);
1607     if (ret < 0) {
1608         dev_err(comp->dev, "request topology \"%s\" failed: %d\n", filename, ret);
1609         return ret;
1610     }
1611 
1612     ret = snd_soc_tplg_component_load(comp, &avs_tplg_ops, fw);
1613     if (ret < 0)
1614         dev_err(comp->dev, "load topology \"%s\" failed: %d\n", filename, ret);
1615 
1616     release_firmware(fw);
1617     return ret;
1618 }
1619 
1620 int avs_remove_topology(struct snd_soc_component *comp)
1621 {
1622     snd_soc_tplg_component_remove(comp);
1623 
1624     return 0;
1625 }