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