0001
0002
0003
0004
0005
0006
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
0019 #define avs_tplg_vendor_array_at(array, offset) \
0020 ((struct snd_soc_tplg_vendor_array *)((u8 *)array + offset))
0021
0022
0023 #define avs_tplg_vendor_array_next(array) \
0024 (avs_tplg_vendor_array_at(array, le32_to_cpu((array)->size)))
0025
0026
0027
0028
0029
0030
0031
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
0062
0063
0064
0065
0066
0067
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
0090
0091
0092
0093
0094
0095
0096
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
0115
0116
0117
0118
0119
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
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
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
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
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
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
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
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
0382
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
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
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
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
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
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
0855 assign_copier_gtw_instance(comp, cfg);
0856
0857 block_size -= esize;
0858
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
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,
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
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
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
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
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
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
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
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
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
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;
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
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
1412 if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
1413 kfree(w->name);
1414
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;
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
1447 link->nonatomic = true;
1448
1449
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
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
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
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
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
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
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
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
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 }