FILE
topology.c
File preview with syntax highlighting.
linux-6.19.14/sound/soc/intel/avs/topology.c
1// SPDX-License-Identifier: GPL-2.0-only 2// 3// Copyright(c) 2021 Intel Corporation 4// 5// Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7// 8 9#include <linux/firmware.h> 10#include <linux/uuid.h> 11#include <sound/soc.h> 12#include <sound/soc-acpi.h> 13#include <sound/soc-topology.h> 14#include <uapi/sound/intel/avs/tokens.h> 15#include "avs.h" 16#include "control.h" 17#include "topology.h" 18#include "utils.h" 19 20/* Get pointer to vendor array at the specified offset. */ 21#define avs_tplg_vendor_array_at(array, offset) \ 22 ((struct snd_soc_tplg_vendor_array *)((u8 *)array + offset)) 23 24/* Get pointer to vendor array that is next in line. */ 25#define avs_tplg_vendor_array_next(array) \ 26 (avs_tplg_vendor_array_at(array, le32_to_cpu((array)->size))) 27 28/* 29 * Scan provided block of tuples for the specified token. If found, 30 * @offset is updated with position at which first matching token is 31 * located. 32 * 33 * Returns 0 on success, -ENOENT if not found and error code otherwise. 34 */ 35static int 36avs_tplg_vendor_array_lookup(struct snd_soc_tplg_vendor_array *tuples, 37 u32 block_size, u32 token, u32 *offset) 38{ 39 u32 pos = 0; 40 41 while (block_size > 0) { 42 struct snd_soc_tplg_vendor_value_elem *tuple; 43 u32 tuples_size = le32_to_cpu(tuples->size); 44 45 if (tuples_size > block_size) 46 return -EINVAL; 47 48 tuple = tuples->value; 49 if (le32_to_cpu(tuple->token) == token) { 50 *offset = pos; 51 return 0; 52 } 53 54 block_size -= tuples_size; 55 pos += tuples_size; 56 tuples = avs_tplg_vendor_array_next(tuples); 57 } 58 59 return -ENOENT; 60} 61 62/* 63 * See avs_tplg_vendor_array_lookup() for description. 64 * 65 * Behaves exactly like avs_tplg_vendor_lookup() but starts from the 66 * next vendor array in line. Useful when searching for the finish line 67 * of an arbitrary entry in a list of entries where each is composed of 68 * several vendor tuples and a specific token marks the beginning of 69 * a new entry block. 70 */ 71static int 72avs_tplg_vendor_array_lookup_next(struct snd_soc_tplg_vendor_array *tuples, 73 u32 block_size, u32 token, u32 *offset) 74{ 75 u32 tuples_size = le32_to_cpu(tuples->size); 76 int ret; 77 78 if (tuples_size > block_size) 79 return -EINVAL; 80 81 tuples = avs_tplg_vendor_array_next(tuples); 82 block_size -= tuples_size; 83 84 ret = avs_tplg_vendor_array_lookup(tuples, block_size, token, offset); 85 if (!ret) 86 *offset += tuples_size; 87 return ret; 88} 89 90/* 91 * Scan provided block of tuples for the specified token which marks 92 * the border of an entry block. Behavior is similar to 93 * avs_tplg_vendor_array_lookup() except 0 is also returned if no 94 * matching token has been found. In such case, returned @size is 95 * assigned to @block_size as the entire block belongs to the current 96 * entry. 97 * 98 * Returns 0 on success, error code otherwise. 99 */ 100static int 101avs_tplg_vendor_entry_size(struct snd_soc_tplg_vendor_array *tuples, 102 u32 block_size, u32 entry_id_token, u32 *size) 103{ 104 int ret; 105 106 ret = avs_tplg_vendor_array_lookup_next(tuples, block_size, entry_id_token, size); 107 if (ret == -ENOENT) { 108 *size = block_size; 109 ret = 0; 110 } 111 112 return ret; 113} 114 115/* 116 * Vendor tuple parsing descriptor. 117 * 118 * @token: vendor specific token that identifies tuple 119 * @type: tuple type, one of SND_SOC_TPLG_TUPLE_TYPE_XXX 120 * @offset: offset of a struct's field to initialize 121 * @parse: parsing function, extracts and assigns value to object's field 122 */ 123struct avs_tplg_token_parser { 124 enum avs_tplg_token token; 125 u32 type; 126 u32 offset; 127 int (*parse)(struct snd_soc_component *comp, void *elem, void *object, u32 offset); 128}; 129 130static int 131avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) 132{ 133 struct snd_soc_tplg_vendor_uuid_elem *tuple = elem; 134 guid_t *val = (guid_t *)((u8 *)object + offset); 135 136 guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid); 137 138 return 0; 139} 140 141static int 142avs_parse_bool_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) 143{ 144 struct snd_soc_tplg_vendor_value_elem *tuple = elem; 145 bool *val = (bool *)((u8 *)object + offset); 146 147 *val = le32_to_cpu(tuple->value); 148 149 return 0; 150} 151 152static int 153avs_parse_byte_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) 154{ 155 struct snd_soc_tplg_vendor_value_elem *tuple = elem; 156 u8 *val = ((u8 *)object + offset); 157 158 *val = le32_to_cpu(tuple->value); 159 160 return 0; 161} 162 163static int 164avs_parse_short_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) 165{ 166 struct snd_soc_tplg_vendor_value_elem *tuple = elem; 167 u16 *val = (u16 *)((u8 *)object + offset); 168 169 *val = le32_to_cpu(tuple->value); 170 171 return 0; 172} 173 174static int 175avs_parse_word_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) 176{ 177 struct snd_soc_tplg_vendor_value_elem *tuple = elem; 178 u32 *val = (u32 *)((u8 *)object + offset); 179 180 *val = le32_to_cpu(tuple->value); 181 182 return 0; 183} 184 185static int 186avs_parse_string_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) 187{ 188 struct snd_soc_tplg_vendor_string_elem *tuple = elem; 189 char *val = (char *)((u8 *)object + offset); 190 191 snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s", tuple->string); 192 193 return 0; 194} 195 196static int avs_parse_uuid_tokens(struct snd_soc_component *comp, void *object, 197 const struct avs_tplg_token_parser *parsers, int count, 198 struct snd_soc_tplg_vendor_array *tuples) 199{ 200 struct snd_soc_tplg_vendor_uuid_elem *tuple; 201 int ret, i, j; 202 203 /* Parse element by element. */ 204 for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) { 205 tuple = &tuples->uuid[i]; 206 207 for (j = 0; j < count; j++) { 208 /* Ignore non-UUID tokens. */ 209 if (parsers[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID || 210 parsers[j].token != le32_to_cpu(tuple->token)) 211 continue; 212 213 ret = parsers[j].parse(comp, tuple, object, parsers[j].offset); 214 if (ret) 215 return ret; 216 } 217 } 218 219 return 0; 220} 221 222static int avs_parse_string_tokens(struct snd_soc_component *comp, void *object, 223 const struct avs_tplg_token_parser *parsers, int count, 224 struct snd_soc_tplg_vendor_array *tuples) 225{ 226 struct snd_soc_tplg_vendor_string_elem *tuple; 227 int ret, i, j; 228 229 /* Parse element by element. */ 230 for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) { 231 tuple = &tuples->string[i]; 232 233 for (j = 0; j < count; j++) { 234 /* Ignore non-string tokens. */ 235 if (parsers[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING || 236 parsers[j].token != le32_to_cpu(tuple->token)) 237 continue; 238 239 ret = parsers[j].parse(comp, tuple, object, parsers[j].offset); 240 if (ret) 241 return ret; 242 } 243 } 244 245 return 0; 246} 247 248static int avs_parse_word_tokens(struct snd_soc_component *comp, void *object, 249 const struct avs_tplg_token_parser *parsers, int count, 250 struct snd_soc_tplg_vendor_array *tuples) 251{ 252 struct snd_soc_tplg_vendor_value_elem *tuple; 253 int ret, i, j; 254 255 /* Parse element by element. */ 256 for (i = 0; i < le32_to_cpu(tuples->num_elems); i++) { 257 tuple = &tuples->value[i]; 258 259 for (j = 0; j < count; j++) { 260 /* Ignore non-integer tokens. */ 261 if (!(parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD || 262 parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT || 263 parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE || 264 parsers[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL)) 265 continue; 266 267 if (parsers[j].token != le32_to_cpu(tuple->token)) 268 continue; 269 270 ret = parsers[j].parse(comp, tuple, object, parsers[j].offset); 271 if (ret) 272 return ret; 273 } 274 } 275 276 return 0; 277} 278 279static int avs_parse_tokens(struct snd_soc_component *comp, void *object, 280 const struct avs_tplg_token_parser *parsers, size_t count, 281 struct snd_soc_tplg_vendor_array *tuples, int priv_size) 282{ 283 int array_size, ret; 284 285 while (priv_size > 0) { 286 array_size = le32_to_cpu(tuples->size); 287 288 if (array_size <= 0) { 289 dev_err(comp->dev, "invalid array size 0x%x\n", array_size); 290 return -EINVAL; 291 } 292 293 /* Make sure there is enough data before parsing. */ 294 priv_size -= array_size; 295 if (priv_size < 0) { 296 dev_err(comp->dev, "invalid array size 0x%x\n", array_size); 297 return -EINVAL; 298 } 299 300 switch (le32_to_cpu(tuples->type)) { 301 case SND_SOC_TPLG_TUPLE_TYPE_UUID: 302 ret = avs_parse_uuid_tokens(comp, object, parsers, count, tuples); 303 break; 304 case SND_SOC_TPLG_TUPLE_TYPE_STRING: 305 ret = avs_parse_string_tokens(comp, object, parsers, count, tuples); 306 break; 307 case SND_SOC_TPLG_TUPLE_TYPE_BOOL: 308 case SND_SOC_TPLG_TUPLE_TYPE_BYTE: 309 case SND_SOC_TPLG_TUPLE_TYPE_SHORT: 310 case SND_SOC_TPLG_TUPLE_TYPE_WORD: 311 ret = avs_parse_word_tokens(comp, object, parsers, count, tuples); 312 break; 313 default: 314 dev_err(comp->dev, "unknown token type %d\n", tuples->type); 315 ret = -EINVAL; 316 } 317 318 if (ret) { 319 dev_err(comp->dev, "parsing %zu tokens of %d type failed: %d\n", 320 count, tuples->type, ret); 321 return ret; 322 } 323 324 tuples = avs_tplg_vendor_array_next(tuples); 325 } 326 327 return 0; 328} 329 330#define AVS_DEFINE_PTR_PARSER(name, type, member) \ 331static int \ 332avs_parse_##name##_ptr(struct snd_soc_component *comp, void *elem, void *object, u32 offset) \ 333{ \ 334 struct snd_soc_tplg_vendor_value_elem *tuple = elem; \ 335 struct avs_soc_component *acomp = to_avs_soc_component(comp); \ 336 type **val = (type **)(object + offset); \ 337 u32 idx; \ 338 \ 339 idx = le32_to_cpu(tuple->value); \ 340 if (idx >= acomp->tplg->num_##member) \ 341 return -EINVAL; \ 342 \ 343 *val = &acomp->tplg->member[idx]; \ 344 \ 345 return 0; \ 346} 347 348AVS_DEFINE_PTR_PARSER(audio_format, struct avs_audio_format, fmts); 349AVS_DEFINE_PTR_PARSER(modcfg_base, struct avs_tplg_modcfg_base, modcfgs_base); 350AVS_DEFINE_PTR_PARSER(modcfg_ext, struct avs_tplg_modcfg_ext, modcfgs_ext); 351AVS_DEFINE_PTR_PARSER(pplcfg, struct avs_tplg_pplcfg, pplcfgs); 352AVS_DEFINE_PTR_PARSER(binding, struct avs_tplg_binding, bindings); 353AVS_DEFINE_PTR_PARSER(nhlt_config, struct avs_tplg_nhlt_config, nhlt_configs); 354 355static int 356parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *object, u32 offset) 357{ 358 struct snd_soc_tplg_vendor_value_elem *velem = elem; 359 struct avs_audio_format *audio_format = object; 360 361 switch (offset) { 362 case AVS_TKN_AFMT_NUM_CHANNELS_U32: 363 audio_format->num_channels = le32_to_cpu(velem->value); 364 break; 365 case AVS_TKN_AFMT_VALID_BIT_DEPTH_U32: 366 audio_format->valid_bit_depth = le32_to_cpu(velem->value); 367 break; 368 case AVS_TKN_AFMT_SAMPLE_TYPE_U32: 369 audio_format->sample_type = le32_to_cpu(velem->value); 370 break; 371 } 372 373 return 0; 374} 375 376static int avs_ssp_sprint(char *buf, size_t size, const char *fmt, int port, int tdm) 377{ 378 char *needle = strstr(fmt, "%d"); 379 int retsize; 380 381 /* 382 * If there is %d present in fmt string it should be replaced by either 383 * SSP or SSP:TDM, where SSP and TDM are numbers, all other formatting 384 * will be ignored. 385 */ 386 if (needle) { 387 retsize = scnprintf(buf, min_t(size_t, size, needle - fmt + 1), "%s", fmt); 388 retsize += scnprintf(buf + retsize, size - retsize, "%d", port); 389 if (tdm) 390 retsize += scnprintf(buf + retsize, size - retsize, ":%d", tdm); 391 retsize += scnprintf(buf + retsize, size - retsize, "%s", needle + 2); 392 return retsize; 393 } 394 395 return snprintf(buf, size, "%s", fmt); 396} 397 398static int parse_link_formatted_string(struct snd_soc_component *comp, void *elem, 399 void *object, u32 offset) 400{ 401 struct snd_soc_tplg_vendor_string_elem *tuple = elem; 402 struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev); 403 char *val = (char *)((u8 *)object + offset); 404 int ssp_port, tdm_slot; 405 406 /* 407 * Dynamic naming - string formats, e.g.: ssp%d - supported only for 408 * topologies describing single device e.g.: an I2S codec on SSP0. 409 */ 410 if (!avs_mach_singular_ssp(mach)) 411 return avs_parse_string_token(comp, elem, object, offset); 412 413 ssp_port = avs_mach_ssp_port(mach); 414 if (!avs_mach_singular_tdm(mach, ssp_port)) 415 return avs_parse_string_token(comp, elem, object, offset); 416 417 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); 418 419 avs_ssp_sprint(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string, ssp_port, tdm_slot); 420 421 return 0; 422} 423 424static int avs_parse_nhlt_config_size(struct snd_soc_component *comp, void *elem, void *object, 425 u32 offset) 426{ 427 struct snd_soc_tplg_vendor_value_elem *tuple = elem; 428 struct acpi_nhlt_config **blob = (struct acpi_nhlt_config **)((u8 *)object + offset); 429 u32 size; 430 431 size = le32_to_cpu(tuple->value); 432 *blob = devm_kzalloc(comp->card->dev, struct_size(*blob, capabilities, size), GFP_KERNEL); 433 if (!*blob) 434 return -ENOMEM; 435 436 (*blob)->capabilities_size = size; 437 return 0; 438} 439 440static int 441parse_dictionary_header(struct snd_soc_component *comp, 442 struct snd_soc_tplg_vendor_array *tuples, 443 void **dict, u32 *num_entries, size_t entry_size, 444 u32 num_entries_token) 445{ 446 struct snd_soc_tplg_vendor_value_elem *tuple; 447 448 /* Dictionary header consists of single tuple - entry count. */ 449 tuple = tuples->value; 450 if (le32_to_cpu(tuple->token) != num_entries_token) { 451 dev_err(comp->dev, "invalid dictionary header, expected: %d\n", 452 num_entries_token); 453 return -EINVAL; 454 } 455 456 *num_entries = le32_to_cpu(tuple->value); 457 *dict = devm_kcalloc(comp->card->dev, *num_entries, entry_size, GFP_KERNEL); 458 if (!*dict) 459 return -ENOMEM; 460 461 return 0; 462} 463 464static int 465parse_dictionary_entries(struct snd_soc_component *comp, 466 struct snd_soc_tplg_vendor_array *tuples, u32 block_size, 467 void *dict, u32 num_entries, size_t entry_size, 468 u32 entry_id_token, 469 const struct avs_tplg_token_parser *parsers, size_t num_parsers) 470{ 471 void *pos = dict; 472 int i; 473 474 for (i = 0; i < num_entries; i++) { 475 u32 esize; 476 int ret; 477 478 ret = avs_tplg_vendor_entry_size(tuples, block_size, 479 entry_id_token, &esize); 480 if (ret) 481 return ret; 482 483 ret = avs_parse_tokens(comp, pos, parsers, num_parsers, tuples, esize); 484 if (ret < 0) { 485 dev_err(comp->dev, "parse entry: %d of type: %d failed: %d\n", 486 i, entry_id_token, ret); 487 return ret; 488 } 489 490 pos += entry_size; 491 block_size -= esize; 492 tuples = avs_tplg_vendor_array_at(tuples, esize); 493 } 494 495 return 0; 496} 497 498static int parse_dictionary(struct snd_soc_component *comp, 499 struct snd_soc_tplg_vendor_array *tuples, u32 block_size, 500 void **dict, u32 *num_entries, size_t entry_size, 501 u32 num_entries_token, u32 entry_id_token, 502 const struct avs_tplg_token_parser *parsers, size_t num_parsers) 503{ 504 int ret; 505 506 ret = parse_dictionary_header(comp, tuples, dict, num_entries, 507 entry_size, num_entries_token); 508 if (ret) 509 return ret; 510 511 block_size -= le32_to_cpu(tuples->size); 512 /* With header parsed, move on to parsing entries. */ 513 tuples = avs_tplg_vendor_array_next(tuples); 514 515 return parse_dictionary_entries(comp, tuples, block_size, *dict, 516 *num_entries, entry_size, 517 entry_id_token, parsers, num_parsers); 518} 519 520static const struct avs_tplg_token_parser library_parsers[] = { 521 { 522 .token = AVS_TKN_LIBRARY_NAME_STRING, 523 .type = SND_SOC_TPLG_TUPLE_TYPE_STRING, 524 .offset = offsetof(struct avs_tplg_library, name), 525 .parse = avs_parse_string_token, 526 }, 527}; 528 529static int avs_tplg_parse_libraries(struct snd_soc_component *comp, 530 struct snd_soc_tplg_vendor_array *tuples, u32 block_size) 531{ 532 struct avs_soc_component *acomp = to_avs_soc_component(comp); 533 struct avs_tplg *tplg = acomp->tplg; 534 535 return parse_dictionary(comp, tuples, block_size, (void **)&tplg->libs, 536 &tplg->num_libs, sizeof(*tplg->libs), 537 AVS_TKN_MANIFEST_NUM_LIBRARIES_U32, 538 AVS_TKN_LIBRARY_ID_U32, 539 library_parsers, ARRAY_SIZE(library_parsers)); 540} 541 542static const struct avs_tplg_token_parser audio_format_parsers[] = { 543 { 544 .token = AVS_TKN_AFMT_SAMPLE_RATE_U32, 545 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 546 .offset = offsetof(struct avs_audio_format, sampling_freq), 547 .parse = avs_parse_word_token, 548 }, 549 { 550 .token = AVS_TKN_AFMT_BIT_DEPTH_U32, 551 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 552 .offset = offsetof(struct avs_audio_format, bit_depth), 553 .parse = avs_parse_word_token, 554 }, 555 { 556 .token = AVS_TKN_AFMT_CHANNEL_MAP_U32, 557 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 558 .offset = offsetof(struct avs_audio_format, channel_map), 559 .parse = avs_parse_word_token, 560 }, 561 { 562 .token = AVS_TKN_AFMT_CHANNEL_CFG_U32, 563 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 564 .offset = offsetof(struct avs_audio_format, channel_config), 565 .parse = avs_parse_word_token, 566 }, 567 { 568 .token = AVS_TKN_AFMT_INTERLEAVING_U32, 569 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 570 .offset = offsetof(struct avs_audio_format, interleaving), 571 .parse = avs_parse_word_token, 572 }, 573 { 574 .token = AVS_TKN_AFMT_NUM_CHANNELS_U32, 575 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 576 .offset = AVS_TKN_AFMT_NUM_CHANNELS_U32, 577 .parse = parse_audio_format_bitfield, 578 }, 579 { 580 .token = AVS_TKN_AFMT_VALID_BIT_DEPTH_U32, 581 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 582 .offset = AVS_TKN_AFMT_VALID_BIT_DEPTH_U32, 583 .parse = parse_audio_format_bitfield, 584 }, 585 { 586 .token = AVS_TKN_AFMT_SAMPLE_TYPE_U32, 587 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 588 .offset = AVS_TKN_AFMT_SAMPLE_TYPE_U32, 589 .parse = parse_audio_format_bitfield, 590 }, 591}; 592 593static int avs_tplg_parse_audio_formats(struct snd_soc_component *comp, 594 struct snd_soc_tplg_vendor_array *tuples, 595 u32 block_size) 596{ 597 struct avs_soc_component *acomp = to_avs_soc_component(comp); 598 struct avs_tplg *tplg = acomp->tplg; 599 600 return parse_dictionary(comp, tuples, block_size, (void **)&tplg->fmts, 601 &tplg->num_fmts, sizeof(*tplg->fmts), 602 AVS_TKN_MANIFEST_NUM_AFMTS_U32, 603 AVS_TKN_AFMT_ID_U32, 604 audio_format_parsers, ARRAY_SIZE(audio_format_parsers)); 605} 606 607static const struct avs_tplg_token_parser modcfg_base_parsers[] = { 608 { 609 .token = AVS_TKN_MODCFG_BASE_CPC_U32, 610 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 611 .offset = offsetof(struct avs_tplg_modcfg_base, cpc), 612 .parse = avs_parse_word_token, 613 }, 614 { 615 .token = AVS_TKN_MODCFG_BASE_IBS_U32, 616 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 617 .offset = offsetof(struct avs_tplg_modcfg_base, ibs), 618 .parse = avs_parse_word_token, 619 }, 620 { 621 .token = AVS_TKN_MODCFG_BASE_OBS_U32, 622 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 623 .offset = offsetof(struct avs_tplg_modcfg_base, obs), 624 .parse = avs_parse_word_token, 625 }, 626 { 627 .token = AVS_TKN_MODCFG_BASE_PAGES_U32, 628 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 629 .offset = offsetof(struct avs_tplg_modcfg_base, is_pages), 630 .parse = avs_parse_word_token, 631 }, 632}; 633 634static int avs_tplg_parse_modcfgs_base(struct snd_soc_component *comp, 635 struct snd_soc_tplg_vendor_array *tuples, 636 u32 block_size) 637{ 638 struct avs_soc_component *acomp = to_avs_soc_component(comp); 639 struct avs_tplg *tplg = acomp->tplg; 640 641 return parse_dictionary(comp, tuples, block_size, (void **)&tplg->modcfgs_base, 642 &tplg->num_modcfgs_base, sizeof(*tplg->modcfgs_base), 643 AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32, 644 AVS_TKN_MODCFG_BASE_ID_U32, 645 modcfg_base_parsers, ARRAY_SIZE(modcfg_base_parsers)); 646} 647 648static const struct avs_tplg_token_parser modcfg_ext_parsers[] = { 649 { 650 .token = AVS_TKN_MODCFG_EXT_TYPE_UUID, 651 .type = SND_SOC_TPLG_TUPLE_TYPE_UUID, 652 .offset = offsetof(struct avs_tplg_modcfg_ext, type), 653 .parse = avs_parse_uuid_token, 654 }, 655 { 656 .token = AVS_TKN_MODCFG_CPR_OUT_AFMT_ID_U32, 657 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 658 .offset = offsetof(struct avs_tplg_modcfg_ext, copier.out_fmt), 659 .parse = avs_parse_audio_format_ptr, 660 }, 661 { 662 .token = AVS_TKN_MODCFG_CPR_FEATURE_MASK_U32, 663 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 664 .offset = offsetof(struct avs_tplg_modcfg_ext, copier.feature_mask), 665 .parse = avs_parse_word_token, 666 }, 667 { 668 .token = AVS_TKN_MODCFG_CPR_VINDEX_U8, 669 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 670 .offset = offsetof(struct avs_tplg_modcfg_ext, copier.vindex), 671 .parse = avs_parse_byte_token, 672 }, 673 { 674 .token = AVS_TKN_MODCFG_CPR_DMA_TYPE_U32, 675 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 676 .offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_type), 677 .parse = avs_parse_word_token, 678 }, 679 { 680 .token = AVS_TKN_MODCFG_CPR_DMABUFF_SIZE_U32, 681 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 682 .offset = offsetof(struct avs_tplg_modcfg_ext, copier.dma_buffer_size), 683 .parse = avs_parse_word_token, 684 }, 685 { 686 .token = AVS_TKN_MODCFG_CPR_BLOB_FMT_ID_U32, 687 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 688 .offset = offsetof(struct avs_tplg_modcfg_ext, copier.blob_fmt), 689 .parse = avs_parse_audio_format_ptr, 690 }, 691 { 692 .token = AVS_TKN_MODCFG_MICSEL_OUT_AFMT_ID_U32, 693 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 694 .offset = offsetof(struct avs_tplg_modcfg_ext, micsel.out_fmt), 695 .parse = avs_parse_audio_format_ptr, 696 }, 697 { 698 .token = AVS_TKN_MODCFG_INTELWOV_CPC_LP_MODE_U32, 699 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 700 .offset = offsetof(struct avs_tplg_modcfg_ext, wov.cpc_lp_mode), 701 .parse = avs_parse_word_token, 702 }, 703 { 704 .token = AVS_TKN_MODCFG_SRC_OUT_FREQ_U32, 705 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 706 .offset = offsetof(struct avs_tplg_modcfg_ext, src.out_freq), 707 .parse = avs_parse_word_token, 708 }, 709 { 710 .token = AVS_TKN_MODCFG_MUX_REF_AFMT_ID_U32, 711 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 712 .offset = offsetof(struct avs_tplg_modcfg_ext, mux.ref_fmt), 713 .parse = avs_parse_audio_format_ptr, 714 }, 715 { 716 .token = AVS_TKN_MODCFG_MUX_OUT_AFMT_ID_U32, 717 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 718 .offset = offsetof(struct avs_tplg_modcfg_ext, mux.out_fmt), 719 .parse = avs_parse_audio_format_ptr, 720 }, 721 { 722 .token = AVS_TKN_MODCFG_AEC_REF_AFMT_ID_U32, 723 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 724 .offset = offsetof(struct avs_tplg_modcfg_ext, aec.ref_fmt), 725 .parse = avs_parse_audio_format_ptr, 726 }, 727 { 728 .token = AVS_TKN_MODCFG_AEC_OUT_AFMT_ID_U32, 729 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 730 .offset = offsetof(struct avs_tplg_modcfg_ext, aec.out_fmt), 731 .parse = avs_parse_audio_format_ptr, 732 }, 733 { 734 .token = AVS_TKN_MODCFG_AEC_CPC_LP_MODE_U32, 735 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 736 .offset = offsetof(struct avs_tplg_modcfg_ext, aec.cpc_lp_mode), 737 .parse = avs_parse_word_token, 738 }, 739 { 740 .token = AVS_TKN_MODCFG_ASRC_OUT_FREQ_U32, 741 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 742 .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.out_freq), 743 .parse = avs_parse_word_token, 744 }, 745 { 746 .token = AVS_TKN_MODCFG_ASRC_MODE_U8, 747 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 748 .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.mode), 749 .parse = avs_parse_byte_token, 750 }, 751 { 752 .token = AVS_TKN_MODCFG_ASRC_DISABLE_JITTER_U8, 753 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 754 .offset = offsetof(struct avs_tplg_modcfg_ext, asrc.disable_jitter_buffer), 755 .parse = avs_parse_byte_token, 756 }, 757 { 758 .token = AVS_TKN_MODCFG_UPDOWN_MIX_OUT_CHAN_CFG_U32, 759 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 760 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.out_channel_config), 761 .parse = avs_parse_word_token, 762 }, 763 { 764 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_SELECT_U32, 765 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 766 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients_select), 767 .parse = avs_parse_word_token, 768 }, 769 { 770 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_0_S32, 771 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 772 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[0]), 773 .parse = avs_parse_word_token, 774 }, 775 { 776 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_1_S32, 777 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 778 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[1]), 779 .parse = avs_parse_word_token, 780 }, 781 { 782 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_2_S32, 783 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 784 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[2]), 785 .parse = avs_parse_word_token, 786 }, 787 { 788 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_3_S32, 789 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 790 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[3]), 791 .parse = avs_parse_word_token, 792 }, 793 { 794 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_4_S32, 795 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 796 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[4]), 797 .parse = avs_parse_word_token, 798 }, 799 { 800 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_5_S32, 801 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 802 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[5]), 803 .parse = avs_parse_word_token, 804 }, 805 { 806 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_6_S32, 807 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 808 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[6]), 809 .parse = avs_parse_word_token, 810 }, 811 { 812 .token = AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_7_S32, 813 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 814 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.coefficients[7]), 815 .parse = avs_parse_word_token, 816 }, 817 { 818 .token = AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32, 819 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 820 .offset = offsetof(struct avs_tplg_modcfg_ext, updown_mix.channel_map), 821 .parse = avs_parse_word_token, 822 }, 823 { 824 .token = AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16, 825 .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT, 826 .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_input_pins), 827 .parse = avs_parse_short_token, 828 }, 829 { 830 .token = AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16, 831 .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT, 832 .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_output_pins), 833 .parse = avs_parse_short_token, 834 }, 835 { 836 .token = AVS_TKN_MODCFG_WHM_REF_AFMT_ID_U32, 837 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 838 .offset = offsetof(struct avs_tplg_modcfg_ext, whm.ref_fmt), 839 .parse = avs_parse_audio_format_ptr, 840 }, 841 { 842 .token = AVS_TKN_MODCFG_WHM_OUT_AFMT_ID_U32, 843 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 844 .offset = offsetof(struct avs_tplg_modcfg_ext, whm.out_fmt), 845 .parse = avs_parse_audio_format_ptr, 846 }, 847 { 848 .token = AVS_TKN_MODCFG_WHM_WAKE_TICK_PERIOD_U32, 849 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 850 .offset = offsetof(struct avs_tplg_modcfg_ext, whm.wake_tick_period), 851 .parse = avs_parse_word_token, 852 }, 853 { 854 .token = AVS_TKN_MODCFG_WHM_VINDEX_U8, 855 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 856 .offset = offsetof(struct avs_tplg_modcfg_ext, whm.vindex), 857 .parse = avs_parse_byte_token, 858 }, 859 { 860 .token = AVS_TKN_MODCFG_WHM_DMA_TYPE_U32, 861 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 862 .offset = offsetof(struct avs_tplg_modcfg_ext, whm.dma_type), 863 .parse = avs_parse_word_token, 864 }, 865 { 866 .token = AVS_TKN_MODCFG_WHM_DMABUFF_SIZE_U32, 867 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 868 .offset = offsetof(struct avs_tplg_modcfg_ext, whm.dma_buffer_size), 869 .parse = avs_parse_word_token, 870 }, 871 { 872 .token = AVS_TKN_MODCFG_WHM_BLOB_AFMT_ID_U32, 873 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 874 .offset = offsetof(struct avs_tplg_modcfg_ext, whm.blob_fmt), 875 .parse = avs_parse_audio_format_ptr, 876 }, 877 { 878 .token = AVS_TKN_MODCFG_PEAKVOL_VOLUME_U32, 879 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 880 .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.target_volume), 881 .parse = avs_parse_word_token, 882 }, 883 { 884 .token = AVS_TKN_MODCFG_PEAKVOL_CURVE_TYPE_U32, 885 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 886 .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.curve_type), 887 .parse = avs_parse_word_token, 888 }, 889 { 890 .token = AVS_TKN_MODCFG_PEAKVOL_CURVE_DURATION_U32, 891 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 892 .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.curve_duration), 893 .parse = avs_parse_word_token, 894 }, 895}; 896 897static const struct avs_tplg_token_parser pin_format_parsers[] = { 898 { 899 .token = AVS_TKN_PIN_FMT_INDEX_U32, 900 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 901 .offset = offsetof(struct avs_tplg_pin_format, pin_index), 902 .parse = avs_parse_word_token, 903 }, 904 { 905 .token = AVS_TKN_PIN_FMT_IOBS_U32, 906 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 907 .offset = offsetof(struct avs_tplg_pin_format, iobs), 908 .parse = avs_parse_word_token, 909 }, 910 { 911 .token = AVS_TKN_PIN_FMT_AFMT_ID_U32, 912 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 913 .offset = offsetof(struct avs_tplg_pin_format, fmt), 914 .parse = avs_parse_audio_format_ptr, 915 }, 916}; 917 918static void 919assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg) 920{ 921 struct snd_soc_acpi_mach *mach; 922 int ssp_port, tdm_slot; 923 924 if (!guid_equal(&cfg->type, &AVS_COPIER_MOD_UUID)) 925 return; 926 927 /* Only I2S boards assign port instance in ->i2s_link_mask. */ 928 switch (cfg->copier.dma_type) { 929 case AVS_DMA_I2S_LINK_OUTPUT: 930 case AVS_DMA_I2S_LINK_INPUT: 931 break; 932 default: 933 return; 934 } 935 936 /* If topology sets value don't overwrite it */ 937 if (cfg->copier.vindex.val) 938 return; 939 940 mach = dev_get_platdata(comp->card->dev); 941 942 if (!avs_mach_singular_ssp(mach)) 943 return; 944 ssp_port = avs_mach_ssp_port(mach); 945 946 if (!avs_mach_singular_tdm(mach, ssp_port)) 947 return; 948 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); 949 950 cfg->copier.vindex.i2s.instance = ssp_port; 951 cfg->copier.vindex.i2s.time_slot = tdm_slot; 952} 953 954static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp, 955 struct avs_tplg_modcfg_ext *cfg, 956 struct snd_soc_tplg_vendor_array *tuples, 957 u32 block_size) 958{ 959 u32 esize; 960 int ret; 961 962 /* See where pin block starts. */ 963 ret = avs_tplg_vendor_entry_size(tuples, block_size, 964 AVS_TKN_PIN_FMT_INDEX_U32, &esize); 965 if (ret) 966 return ret; 967 968 ret = avs_parse_tokens(comp, cfg, modcfg_ext_parsers, 969 ARRAY_SIZE(modcfg_ext_parsers), tuples, esize); 970 if (ret) 971 return ret; 972 973 /* Update copier gateway based on board's i2s_link_mask. */ 974 assign_copier_gtw_instance(comp, cfg); 975 976 block_size -= esize; 977 /* Parse trailing in/out pin formats if any. */ 978 if (block_size) { 979 struct avs_tplg_pin_format *pins; 980 u32 num_pins; 981 982 num_pins = cfg->generic.num_input_pins + cfg->generic.num_output_pins; 983 if (!num_pins) 984 return -EINVAL; 985 986 pins = devm_kcalloc(comp->card->dev, num_pins, sizeof(*pins), GFP_KERNEL); 987 if (!pins) 988 return -ENOMEM; 989 990 tuples = avs_tplg_vendor_array_at(tuples, esize); 991 ret = parse_dictionary_entries(comp, tuples, block_size, 992 pins, num_pins, sizeof(*pins), 993 AVS_TKN_PIN_FMT_INDEX_U32, 994 pin_format_parsers, 995 ARRAY_SIZE(pin_format_parsers)); 996 if (ret) 997 return ret; 998 cfg->generic.pin_fmts = pins; 999 } 1000 1001 return 0; 1002} 1003 1004static int avs_tplg_parse_modcfgs_ext(struct snd_soc_component *comp, 1005 struct snd_soc_tplg_vendor_array *tuples, 1006 u32 block_size) 1007{ 1008 struct avs_soc_component *acomp = to_avs_soc_component(comp); 1009 struct avs_tplg *tplg = acomp->tplg; 1010 int ret, i; 1011 1012 ret = parse_dictionary_header(comp, tuples, (void **)&tplg->modcfgs_ext, 1013 &tplg->num_modcfgs_ext, 1014 sizeof(*tplg->modcfgs_ext), 1015 AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32); 1016 if (ret) 1017 return ret; 1018 1019 block_size -= le32_to_cpu(tuples->size); 1020 /* With header parsed, move on to parsing entries. */ 1021 tuples = avs_tplg_vendor_array_next(tuples); 1022 1023 for (i = 0; i < tplg->num_modcfgs_ext; i++) { 1024 struct avs_tplg_modcfg_ext *cfg = &tplg->modcfgs_ext[i]; 1025 u32 esize; 1026 1027 ret = avs_tplg_vendor_entry_size(tuples, block_size, 1028 AVS_TKN_MODCFG_EXT_ID_U32, &esize); 1029 if (ret) 1030 return ret; 1031 1032 ret = avs_tplg_parse_modcfg_ext(comp, cfg, tuples, esize); 1033 if (ret) 1034 return ret; 1035 1036 block_size -= esize; 1037 tuples = avs_tplg_vendor_array_at(tuples, esize); 1038 } 1039 1040 return 0; 1041} 1042 1043static const struct avs_tplg_token_parser pplcfg_parsers[] = { 1044 { 1045 .token = AVS_TKN_PPLCFG_REQ_SIZE_U16, 1046 .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT, 1047 .offset = offsetof(struct avs_tplg_pplcfg, req_size), 1048 .parse = avs_parse_short_token, 1049 }, 1050 { 1051 .token = AVS_TKN_PPLCFG_PRIORITY_U8, 1052 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 1053 .offset = offsetof(struct avs_tplg_pplcfg, priority), 1054 .parse = avs_parse_byte_token, 1055 }, 1056 { 1057 .token = AVS_TKN_PPLCFG_LOW_POWER_BOOL, 1058 .type = SND_SOC_TPLG_TUPLE_TYPE_BOOL, 1059 .offset = offsetof(struct avs_tplg_pplcfg, lp), 1060 .parse = avs_parse_bool_token, 1061 }, 1062 { 1063 .token = AVS_TKN_PPLCFG_ATTRIBUTES_U16, 1064 .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT, 1065 .offset = offsetof(struct avs_tplg_pplcfg, attributes), 1066 .parse = avs_parse_short_token, 1067 }, 1068 { 1069 .token = AVS_TKN_PPLCFG_TRIGGER_U32, 1070 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1071 .offset = offsetof(struct avs_tplg_pplcfg, trigger), 1072 .parse = avs_parse_word_token, 1073 }, 1074}; 1075 1076static int avs_tplg_parse_pplcfgs(struct snd_soc_component *comp, 1077 struct snd_soc_tplg_vendor_array *tuples, 1078 u32 block_size) 1079{ 1080 struct avs_soc_component *acomp = to_avs_soc_component(comp); 1081 struct avs_tplg *tplg = acomp->tplg; 1082 1083 return parse_dictionary(comp, tuples, block_size, (void **)&tplg->pplcfgs, 1084 &tplg->num_pplcfgs, sizeof(*tplg->pplcfgs), 1085 AVS_TKN_MANIFEST_NUM_PPLCFGS_U32, 1086 AVS_TKN_PPLCFG_ID_U32, 1087 pplcfg_parsers, ARRAY_SIZE(pplcfg_parsers)); 1088} 1089 1090static const struct avs_tplg_token_parser binding_parsers[] = { 1091 { 1092 .token = AVS_TKN_BINDING_TARGET_TPLG_NAME_STRING, 1093 .type = SND_SOC_TPLG_TUPLE_TYPE_STRING, 1094 .offset = offsetof(struct avs_tplg_binding, target_tplg_name), 1095 .parse = parse_link_formatted_string, 1096 }, 1097 { 1098 .token = AVS_TKN_BINDING_TARGET_PATH_TMPL_ID_U32, 1099 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1100 .offset = offsetof(struct avs_tplg_binding, target_path_tmpl_id), 1101 .parse = avs_parse_word_token, 1102 }, 1103 { 1104 .token = AVS_TKN_BINDING_TARGET_PPL_ID_U32, 1105 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1106 .offset = offsetof(struct avs_tplg_binding, target_ppl_id), 1107 .parse = avs_parse_word_token, 1108 }, 1109 { 1110 .token = AVS_TKN_BINDING_TARGET_MOD_ID_U32, 1111 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1112 .offset = offsetof(struct avs_tplg_binding, target_mod_id), 1113 .parse = avs_parse_word_token, 1114 }, 1115 { 1116 .token = AVS_TKN_BINDING_TARGET_MOD_PIN_U8, 1117 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 1118 .offset = offsetof(struct avs_tplg_binding, target_mod_pin), 1119 .parse = avs_parse_byte_token, 1120 }, 1121 { 1122 .token = AVS_TKN_BINDING_MOD_ID_U32, 1123 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1124 .offset = offsetof(struct avs_tplg_binding, mod_id), 1125 .parse = avs_parse_word_token, 1126 }, 1127 { 1128 .token = AVS_TKN_BINDING_MOD_PIN_U8, 1129 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 1130 .offset = offsetof(struct avs_tplg_binding, mod_pin), 1131 .parse = avs_parse_byte_token, 1132 }, 1133 { 1134 .token = AVS_TKN_BINDING_IS_SINK_U8, 1135 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 1136 .offset = offsetof(struct avs_tplg_binding, is_sink), 1137 .parse = avs_parse_byte_token, 1138 }, 1139}; 1140 1141static int avs_tplg_parse_bindings(struct snd_soc_component *comp, 1142 struct snd_soc_tplg_vendor_array *tuples, 1143 u32 block_size) 1144{ 1145 struct avs_soc_component *acomp = to_avs_soc_component(comp); 1146 struct avs_tplg *tplg = acomp->tplg; 1147 1148 return parse_dictionary(comp, tuples, block_size, (void **)&tplg->bindings, 1149 &tplg->num_bindings, sizeof(*tplg->bindings), 1150 AVS_TKN_MANIFEST_NUM_BINDINGS_U32, 1151 AVS_TKN_BINDING_ID_U32, 1152 binding_parsers, ARRAY_SIZE(binding_parsers)); 1153} 1154 1155static const struct avs_tplg_token_parser module_parsers[] = { 1156 { 1157 .token = AVS_TKN_MOD_ID_U32, 1158 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1159 .offset = offsetof(struct avs_tplg_module, id), 1160 .parse = avs_parse_word_token, 1161 }, 1162 { 1163 .token = AVS_TKN_MOD_MODCFG_BASE_ID_U32, 1164 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1165 .offset = offsetof(struct avs_tplg_module, cfg_base), 1166 .parse = avs_parse_modcfg_base_ptr, 1167 }, 1168 { 1169 .token = AVS_TKN_MOD_IN_AFMT_ID_U32, 1170 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1171 .offset = offsetof(struct avs_tplg_module, in_fmt), 1172 .parse = avs_parse_audio_format_ptr, 1173 }, 1174 { 1175 .token = AVS_TKN_MOD_CORE_ID_U8, 1176 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 1177 .offset = offsetof(struct avs_tplg_module, core_id), 1178 .parse = avs_parse_byte_token, 1179 }, 1180 { 1181 .token = AVS_TKN_MOD_PROC_DOMAIN_U8, 1182 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 1183 .offset = offsetof(struct avs_tplg_module, domain), 1184 .parse = avs_parse_byte_token, 1185 }, 1186 { 1187 .token = AVS_TKN_MOD_MODCFG_EXT_ID_U32, 1188 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1189 .offset = offsetof(struct avs_tplg_module, cfg_ext), 1190 .parse = avs_parse_modcfg_ext_ptr, 1191 }, 1192 { 1193 .token = AVS_TKN_MOD_KCONTROL_ID_U32, 1194 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1195 .offset = offsetof(struct avs_tplg_module, ctl_id), 1196 .parse = avs_parse_byte_token, 1197 }, 1198 { 1199 .token = AVS_TKN_MOD_INIT_CONFIG_NUM_IDS_U32, 1200 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1201 .offset = offsetof(struct avs_tplg_module, num_config_ids), 1202 .parse = avs_parse_byte_token, 1203 }, 1204 { 1205 .token = AVS_TKN_MOD_NHLT_CONFIG_ID_U32, 1206 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1207 .offset = offsetof(struct avs_tplg_module, nhlt_config), 1208 .parse = avs_parse_nhlt_config_ptr, 1209 }, 1210}; 1211 1212static const struct avs_tplg_token_parser init_config_parsers[] = { 1213 { 1214 .token = AVS_TKN_MOD_INIT_CONFIG_ID_U32, 1215 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1216 .offset = 0, 1217 .parse = avs_parse_word_token, 1218 }, 1219}; 1220 1221static struct avs_tplg_module * 1222avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline *owner, 1223 struct snd_soc_tplg_vendor_array *tuples, u32 block_size) 1224{ 1225 struct avs_tplg_module *module; 1226 u32 esize; 1227 int ret; 1228 1229 /* See where config id block starts. */ 1230 ret = avs_tplg_vendor_entry_size(tuples, block_size, 1231 AVS_TKN_MOD_INIT_CONFIG_ID_U32, &esize); 1232 if (ret) 1233 return ERR_PTR(ret); 1234 1235 module = devm_kzalloc(comp->card->dev, sizeof(*module), GFP_KERNEL); 1236 if (!module) 1237 return ERR_PTR(-ENOMEM); 1238 1239 ret = avs_parse_tokens(comp, module, module_parsers, 1240 ARRAY_SIZE(module_parsers), tuples, esize); 1241 if (ret < 0) 1242 return ERR_PTR(ret); 1243 1244 block_size -= esize; 1245 /* Parse trailing config ids if any. */ 1246 if (block_size) { 1247 u32 num_config_ids = module->num_config_ids; 1248 u32 *config_ids; 1249 1250 if (!num_config_ids) 1251 return ERR_PTR(-EINVAL); 1252 1253 config_ids = devm_kcalloc(comp->card->dev, num_config_ids, sizeof(*config_ids), 1254 GFP_KERNEL); 1255 if (!config_ids) 1256 return ERR_PTR(-ENOMEM); 1257 1258 tuples = avs_tplg_vendor_array_at(tuples, esize); 1259 ret = parse_dictionary_entries(comp, tuples, block_size, 1260 config_ids, num_config_ids, sizeof(*config_ids), 1261 AVS_TKN_MOD_INIT_CONFIG_ID_U32, 1262 init_config_parsers, 1263 ARRAY_SIZE(init_config_parsers)); 1264 if (ret) 1265 return ERR_PTR(ret); 1266 1267 module->config_ids = config_ids; 1268 } 1269 1270 module->owner = owner; 1271 INIT_LIST_HEAD(&module->node); 1272 1273 return module; 1274} 1275 1276static const struct avs_tplg_token_parser pipeline_parsers[] = { 1277 { 1278 .token = AVS_TKN_PPL_ID_U32, 1279 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1280 .offset = offsetof(struct avs_tplg_pipeline, id), 1281 .parse = avs_parse_word_token, 1282 }, 1283 { 1284 .token = AVS_TKN_PPL_PPLCFG_ID_U32, 1285 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1286 .offset = offsetof(struct avs_tplg_pipeline, cfg), 1287 .parse = avs_parse_pplcfg_ptr, 1288 }, 1289 { 1290 .token = AVS_TKN_PPL_NUM_BINDING_IDS_U32, 1291 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1292 .offset = offsetof(struct avs_tplg_pipeline, num_bindings), 1293 .parse = avs_parse_word_token, 1294 }, 1295}; 1296 1297static const struct avs_tplg_token_parser bindings_parsers[] = { 1298 { 1299 .token = AVS_TKN_PPL_BINDING_ID_U32, 1300 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1301 .offset = 0, /* to treat pipeline->bindings as dictionary */ 1302 .parse = avs_parse_binding_ptr, 1303 }, 1304}; 1305 1306static struct avs_tplg_pipeline * 1307avs_tplg_pipeline_create(struct snd_soc_component *comp, struct avs_tplg_path *owner, 1308 struct snd_soc_tplg_vendor_array *tuples, u32 block_size) 1309{ 1310 struct avs_tplg_pipeline *pipeline; 1311 u32 modblk_size, offset; 1312 int ret; 1313 1314 pipeline = devm_kzalloc(comp->card->dev, sizeof(*pipeline), GFP_KERNEL); 1315 if (!pipeline) 1316 return ERR_PTR(-ENOMEM); 1317 1318 pipeline->owner = owner; 1319 INIT_LIST_HEAD(&pipeline->mod_list); 1320 1321 /* Pipeline header MUST be followed by at least one module. */ 1322 ret = avs_tplg_vendor_array_lookup(tuples, block_size, 1323 AVS_TKN_MOD_ID_U32, &offset); 1324 if (!ret && !offset) 1325 ret = -EINVAL; 1326 if (ret) 1327 return ERR_PTR(ret); 1328 1329 /* Process header which precedes module sections. */ 1330 ret = avs_parse_tokens(comp, pipeline, pipeline_parsers, 1331 ARRAY_SIZE(pipeline_parsers), tuples, offset); 1332 if (ret < 0) 1333 return ERR_PTR(ret); 1334 1335 block_size -= offset; 1336 tuples = avs_tplg_vendor_array_at(tuples, offset); 1337 1338 /* Optionally, binding sections follow module ones. */ 1339 ret = avs_tplg_vendor_array_lookup_next(tuples, block_size, 1340 AVS_TKN_PPL_BINDING_ID_U32, &offset); 1341 if (ret) { 1342 if (ret != -ENOENT) 1343 return ERR_PTR(ret); 1344 1345 /* Does header information match actual block layout? */ 1346 if (pipeline->num_bindings) 1347 return ERR_PTR(-EINVAL); 1348 1349 modblk_size = block_size; 1350 } else { 1351 pipeline->bindings = devm_kcalloc(comp->card->dev, pipeline->num_bindings, 1352 sizeof(*pipeline->bindings), GFP_KERNEL); 1353 if (!pipeline->bindings) 1354 return ERR_PTR(-ENOMEM); 1355 1356 modblk_size = offset; 1357 } 1358 1359 block_size -= modblk_size; 1360 do { 1361 struct avs_tplg_module *module; 1362 u32 esize; 1363 1364 ret = avs_tplg_vendor_entry_size(tuples, modblk_size, 1365 AVS_TKN_MOD_ID_U32, &esize); 1366 if (ret) 1367 return ERR_PTR(ret); 1368 1369 module = avs_tplg_module_create(comp, pipeline, tuples, esize); 1370 if (IS_ERR(module)) { 1371 dev_err(comp->dev, "parse module failed: %ld\n", 1372 PTR_ERR(module)); 1373 return ERR_CAST(module); 1374 } 1375 1376 list_add_tail(&module->node, &pipeline->mod_list); 1377 modblk_size -= esize; 1378 tuples = avs_tplg_vendor_array_at(tuples, esize); 1379 } while (modblk_size > 0); 1380 1381 /* What's left is optional range of bindings. */ 1382 ret = parse_dictionary_entries(comp, tuples, block_size, pipeline->bindings, 1383 pipeline->num_bindings, sizeof(*pipeline->bindings), 1384 AVS_TKN_PPL_BINDING_ID_U32, 1385 bindings_parsers, ARRAY_SIZE(bindings_parsers)); 1386 if (ret) 1387 return ERR_PTR(ret); 1388 1389 return pipeline; 1390} 1391 1392static const struct avs_tplg_token_parser path_parsers[] = { 1393 { 1394 .token = AVS_TKN_PATH_ID_U32, 1395 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1396 .offset = offsetof(struct avs_tplg_path, id), 1397 .parse = avs_parse_word_token, 1398 }, 1399 { 1400 .token = AVS_TKN_PATH_FE_FMT_ID_U32, 1401 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1402 .offset = offsetof(struct avs_tplg_path, fe_fmt), 1403 .parse = avs_parse_audio_format_ptr, 1404 }, 1405 { 1406 .token = AVS_TKN_PATH_BE_FMT_ID_U32, 1407 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1408 .offset = offsetof(struct avs_tplg_path, be_fmt), 1409 .parse = avs_parse_audio_format_ptr, 1410 }, 1411}; 1412 1413static const struct avs_tplg_token_parser condpath_parsers[] = { 1414 { 1415 .token = AVS_TKN_CONDPATH_ID_U32, 1416 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1417 .offset = offsetof(struct avs_tplg_path, id), 1418 .parse = avs_parse_word_token, 1419 }, 1420 { 1421 .token = AVS_TKN_CONDPATH_SOURCE_PATH_ID_U32, 1422 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1423 .offset = offsetof(struct avs_tplg_path, source_path_id), 1424 .parse = avs_parse_word_token, 1425 }, 1426 { 1427 .token = AVS_TKN_CONDPATH_SINK_PATH_ID_U32, 1428 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1429 .offset = offsetof(struct avs_tplg_path, sink_path_id), 1430 .parse = avs_parse_word_token, 1431 }, 1432}; 1433 1434static struct avs_tplg_path * 1435avs_tplg_path_create(struct snd_soc_component *comp, struct avs_tplg_path_template *owner, 1436 struct snd_soc_tplg_vendor_array *tuples, u32 block_size, 1437 const struct avs_tplg_token_parser *parsers, u32 num_parsers) 1438{ 1439 struct avs_tplg_pipeline *pipeline; 1440 struct avs_tplg_path *path; 1441 u32 offset; 1442 int ret; 1443 1444 path = devm_kzalloc(comp->card->dev, sizeof(*path), GFP_KERNEL); 1445 if (!path) 1446 return ERR_PTR(-ENOMEM); 1447 1448 path->owner = owner; 1449 INIT_LIST_HEAD(&path->ppl_list); 1450 INIT_LIST_HEAD(&path->node); 1451 1452 /* Path header MAY be followed by one or more pipelines. */ 1453 ret = avs_tplg_vendor_array_lookup(tuples, block_size, 1454 AVS_TKN_PPL_ID_U32, &offset); 1455 if (ret == -ENOENT) 1456 offset = block_size; 1457 else if (ret) 1458 return ERR_PTR(ret); 1459 else if (!offset) 1460 return ERR_PTR(-EINVAL); 1461 1462 /* Process header which precedes pipeline sections. */ 1463 ret = avs_parse_tokens(comp, path, parsers, num_parsers, tuples, offset); 1464 if (ret < 0) 1465 return ERR_PTR(ret); 1466 1467 block_size -= offset; 1468 tuples = avs_tplg_vendor_array_at(tuples, offset); 1469 while (block_size > 0) { 1470 u32 esize; 1471 1472 ret = avs_tplg_vendor_entry_size(tuples, block_size, 1473 AVS_TKN_PPL_ID_U32, &esize); 1474 if (ret) 1475 return ERR_PTR(ret); 1476 1477 pipeline = avs_tplg_pipeline_create(comp, path, tuples, esize); 1478 if (IS_ERR(pipeline)) { 1479 dev_err(comp->dev, "parse pipeline failed: %ld\n", 1480 PTR_ERR(pipeline)); 1481 return ERR_CAST(pipeline); 1482 } 1483 1484 list_add_tail(&pipeline->node, &path->ppl_list); 1485 block_size -= esize; 1486 tuples = avs_tplg_vendor_array_at(tuples, esize); 1487 } 1488 1489 return path; 1490} 1491 1492static const struct avs_tplg_token_parser path_tmpl_parsers[] = { 1493 { 1494 .token = AVS_TKN_PATH_TMPL_ID_U32, 1495 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1496 .offset = offsetof(struct avs_tplg_path_template, id), 1497 .parse = avs_parse_word_token, 1498 }, 1499}; 1500 1501static const struct avs_tplg_token_parser condpath_tmpl_parsers[] = { 1502 { 1503 .token = AVS_TKN_CONDPATH_TMPL_ID_U32, 1504 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1505 .offset = offsetof(struct avs_tplg_path_template, id), 1506 .parse = avs_parse_word_token, 1507 }, 1508 { 1509 .token = AVS_TKN_CONDPATH_TMPL_SOURCE_TPLG_NAME_STRING, 1510 .type = SND_SOC_TPLG_TUPLE_TYPE_STRING, 1511 .offset = offsetof(struct avs_tplg_path_template, source.tplg_name), 1512 .parse = avs_parse_string_token, 1513 }, 1514 { 1515 .token = AVS_TKN_CONDPATH_TMPL_SOURCE_PATH_TMPL_ID_U32, 1516 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1517 .offset = offsetof(struct avs_tplg_path_template, source.id), 1518 .parse = avs_parse_word_token, 1519 }, 1520 { 1521 .token = AVS_TKN_CONDPATH_TMPL_SINK_TPLG_NAME_STRING, 1522 .type = SND_SOC_TPLG_TUPLE_TYPE_STRING, 1523 .offset = offsetof(struct avs_tplg_path_template, sink.tplg_name), 1524 .parse = avs_parse_string_token, 1525 }, 1526 { 1527 .token = AVS_TKN_CONDPATH_TMPL_SINK_PATH_TMPL_ID_U32, 1528 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1529 .offset = offsetof(struct avs_tplg_path_template, sink.id), 1530 .parse = avs_parse_word_token, 1531 }, 1532}; 1533 1534static int parse_path_template(struct snd_soc_component *comp, 1535 struct snd_soc_tplg_vendor_array *tuples, u32 block_size, 1536 struct avs_tplg_path_template *template, 1537 const struct avs_tplg_token_parser *tmpl_tokens, u32 num_tmpl_tokens, 1538 const struct avs_tplg_token_parser *path_tokens, u32 num_path_tokens) 1539{ 1540 struct avs_tplg_path *path; 1541 u32 offset; 1542 int ret; 1543 1544 /* Path template header MUST be followed by at least one path variant. */ 1545 ret = avs_tplg_vendor_array_lookup(tuples, block_size, 1546 AVS_TKN_PATH_ID_U32, &offset); 1547 if (ret) 1548 return ret; 1549 1550 /* Process header which precedes path variants sections. */ 1551 ret = avs_parse_tokens(comp, template, tmpl_tokens, num_tmpl_tokens, tuples, offset); 1552 if (ret < 0) 1553 return ret; 1554 1555 block_size -= offset; 1556 tuples = avs_tplg_vendor_array_at(tuples, offset); 1557 do { 1558 u32 esize; 1559 1560 ret = avs_tplg_vendor_entry_size(tuples, block_size, 1561 AVS_TKN_PATH_ID_U32, &esize); 1562 if (ret) 1563 return ret; 1564 1565 path = avs_tplg_path_create(comp, template, tuples, esize, path_tokens, 1566 num_path_tokens); 1567 if (IS_ERR(path)) { 1568 dev_err(comp->dev, "parse path failed: %ld\n", PTR_ERR(path)); 1569 return PTR_ERR(path); 1570 } 1571 1572 list_add_tail(&path->node, &template->path_list); 1573 block_size -= esize; 1574 tuples = avs_tplg_vendor_array_at(tuples, esize); 1575 } while (block_size > 0); 1576 1577 return 0; 1578} 1579 1580static struct avs_tplg_path_template * 1581avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *owner, 1582 struct snd_soc_tplg_vendor_array *tuples, u32 block_size) 1583{ 1584 struct avs_tplg_path_template *template; 1585 int ret; 1586 1587 template = devm_kzalloc(comp->card->dev, sizeof(*template), GFP_KERNEL); 1588 if (!template) 1589 return ERR_PTR(-ENOMEM); 1590 1591 template->owner = owner; /* Used to access component tplg is assigned to. */ 1592 INIT_LIST_HEAD(&template->path_list); 1593 INIT_LIST_HEAD(&template->node); 1594 1595 ret = parse_path_template(comp, tuples, block_size, template, path_tmpl_parsers, 1596 ARRAY_SIZE(path_tmpl_parsers), path_parsers, 1597 ARRAY_SIZE(path_parsers)); 1598 if (ret) 1599 return ERR_PTR(ret); 1600 1601 return template; 1602} 1603 1604static int avs_tplg_parse_condpath_templates(struct snd_soc_component *comp, 1605 struct snd_soc_tplg_vendor_array *tuples, 1606 u32 block_size) 1607{ 1608 struct avs_soc_component *acomp = to_avs_soc_component(comp); 1609 struct avs_tplg *tplg = acomp->tplg; 1610 int ret, i; 1611 1612 ret = parse_dictionary_header(comp, tuples, (void **)&tplg->condpath_tmpls, 1613 &tplg->num_condpath_tmpls, 1614 sizeof(*tplg->condpath_tmpls), 1615 AVS_TKN_MANIFEST_NUM_CONDPATH_TMPLS_U32); 1616 if (ret) 1617 return ret; 1618 1619 block_size -= le32_to_cpu(tuples->size); 1620 /* With header parsed, move on to parsing entries. */ 1621 tuples = avs_tplg_vendor_array_next(tuples); 1622 1623 for (i = 0; i < tplg->num_condpath_tmpls; i++) { 1624 struct avs_tplg_path_template *template; 1625 u32 esize; 1626 1627 template = &tplg->condpath_tmpls[i]; 1628 template->owner = tplg; /* Used when building sysfs hierarchy. */ 1629 INIT_LIST_HEAD(&template->path_list); 1630 INIT_LIST_HEAD(&template->node); 1631 1632 ret = avs_tplg_vendor_entry_size(tuples, block_size, 1633 AVS_TKN_CONDPATH_TMPL_ID_U32, &esize); 1634 if (ret) 1635 return ret; 1636 1637 ret = parse_path_template(comp, tuples, esize, template, 1638 condpath_tmpl_parsers, 1639 ARRAY_SIZE(condpath_tmpl_parsers), 1640 condpath_parsers, 1641 ARRAY_SIZE(condpath_parsers)); 1642 if (ret < 0) { 1643 dev_err(comp->dev, "parse condpath_tmpl: %d failed: %d\n", i, ret); 1644 return ret; 1645 } 1646 1647 block_size -= esize; 1648 tuples = avs_tplg_vendor_array_at(tuples, esize); 1649 } 1650 1651 return 0; 1652} 1653 1654static const struct avs_tplg_token_parser mod_init_config_parsers[] = { 1655 { 1656 .token = AVS_TKN_INIT_CONFIG_ID_U32, 1657 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1658 .offset = offsetof(struct avs_tplg_init_config, id), 1659 .parse = avs_parse_word_token, 1660 }, 1661 { 1662 .token = AVS_TKN_INIT_CONFIG_PARAM_U8, 1663 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, 1664 .offset = offsetof(struct avs_tplg_init_config, param), 1665 .parse = avs_parse_byte_token, 1666 }, 1667 { 1668 .token = AVS_TKN_INIT_CONFIG_LENGTH_U32, 1669 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1670 .offset = offsetof(struct avs_tplg_init_config, length), 1671 .parse = avs_parse_word_token, 1672 }, 1673}; 1674 1675static int avs_tplg_parse_initial_configs(struct snd_soc_component *comp, 1676 struct snd_soc_tplg_vendor_array *tuples, 1677 u32 block_size, u32 *offset) 1678{ 1679 struct avs_soc_component *acomp = to_avs_soc_component(comp); 1680 struct avs_tplg *tplg = acomp->tplg; 1681 int ret, i; 1682 1683 *offset = 0; 1684 1685 /* Parse tuple section telling how many init configs there are. */ 1686 ret = parse_dictionary_header(comp, tuples, (void **)&tplg->init_configs, 1687 &tplg->num_init_configs, 1688 sizeof(*tplg->init_configs), 1689 AVS_TKN_MANIFEST_NUM_INIT_CONFIGS_U32); 1690 if (ret) 1691 return ret; 1692 1693 block_size -= le32_to_cpu(tuples->size); 1694 *offset += le32_to_cpu(tuples->size); 1695 /* With header parsed, move on to parsing entries. */ 1696 tuples = avs_tplg_vendor_array_next(tuples); 1697 1698 for (i = 0; i < tplg->num_init_configs && block_size > 0; i++) { 1699 struct avs_tplg_init_config *config = &tplg->init_configs[i]; 1700 struct snd_soc_tplg_vendor_array *tmp; 1701 void *init_config_data; 1702 u32 esize; 1703 1704 /* 1705 * Usually to get section length we search for first token of next group of data, 1706 * but in this case we can't as tuples are followed by raw data. 1707 */ 1708 tmp = avs_tplg_vendor_array_next(tuples); 1709 esize = le32_to_cpu(tuples->size) + le32_to_cpu(tmp->size); 1710 *offset += esize; 1711 1712 ret = parse_dictionary_entries(comp, tuples, esize, config, 1, sizeof(*config), 1713 AVS_TKN_INIT_CONFIG_ID_U32, 1714 mod_init_config_parsers, 1715 ARRAY_SIZE(mod_init_config_parsers)); 1716 1717 block_size -= esize; 1718 1719 /* handle raw data section */ 1720 init_config_data = (void *)tuples + esize; 1721 esize = config->length; 1722 *offset += esize; 1723 1724 config->data = devm_kmemdup(comp->card->dev, init_config_data, esize, GFP_KERNEL); 1725 if (!config->data) 1726 return -ENOMEM; 1727 1728 tuples = init_config_data + esize; 1729 block_size -= esize; 1730 } 1731 1732 return 0; 1733} 1734 1735static const struct avs_tplg_token_parser mod_nhlt_config_parsers[] = { 1736 { 1737 .token = AVS_TKN_NHLT_CONFIG_ID_U32, 1738 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1739 .offset = offsetof(struct avs_tplg_nhlt_config, id), 1740 .parse = avs_parse_word_token, 1741 }, 1742 { 1743 .token = AVS_TKN_NHLT_CONFIG_SIZE_U32, 1744 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1745 .offset = offsetof(struct avs_tplg_nhlt_config, blob), 1746 .parse = avs_parse_nhlt_config_size, 1747 }, 1748}; 1749 1750static int avs_tplg_parse_nhlt_configs(struct snd_soc_component *comp, 1751 struct snd_soc_tplg_vendor_array *tuples, 1752 u32 block_size) 1753{ 1754 struct avs_soc_component *acomp = to_avs_soc_component(comp); 1755 struct avs_tplg *tplg = acomp->tplg; 1756 int ret, i; 1757 1758 /* Parse the header section to know how many entries there are. */ 1759 ret = parse_dictionary_header(comp, tuples, (void **)&tplg->nhlt_configs, 1760 &tplg->num_nhlt_configs, 1761 sizeof(*tplg->nhlt_configs), 1762 AVS_TKN_MANIFEST_NUM_NHLT_CONFIGS_U32); 1763 if (ret) 1764 return ret; 1765 1766 block_size -= le32_to_cpu(tuples->size); 1767 /* With the header parsed, move on to parsing entries. */ 1768 tuples = avs_tplg_vendor_array_next(tuples); 1769 1770 for (i = 0; i < tplg->num_nhlt_configs && block_size > 0; i++) { 1771 struct avs_tplg_nhlt_config *config; 1772 u32 esize; 1773 1774 config = &tplg->nhlt_configs[i]; 1775 esize = le32_to_cpu(tuples->size); 1776 1777 ret = parse_dictionary_entries(comp, tuples, esize, config, 1, sizeof(*config), 1778 AVS_TKN_NHLT_CONFIG_ID_U32, 1779 mod_nhlt_config_parsers, 1780 ARRAY_SIZE(mod_nhlt_config_parsers)); 1781 if (ret) 1782 return ret; 1783 /* With tuples parsed, the blob shall be allocated. */ 1784 if (!config->blob) 1785 return -EINVAL; 1786 1787 /* Consume the raw data and move to the next entry. */ 1788 memcpy(config->blob->capabilities, (u8 *)tuples + esize, 1789 config->blob->capabilities_size); 1790 esize += config->blob->capabilities_size; 1791 1792 block_size -= esize; 1793 tuples = avs_tplg_vendor_array_at(tuples, esize); 1794 } 1795 1796 return 0; 1797} 1798 1799static int avs_route_load(struct snd_soc_component *comp, int index, 1800 struct snd_soc_dapm_route *route) 1801{ 1802 struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev); 1803 size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN; 1804 int ssp_port, tdm_slot; 1805 char *buf; 1806 1807 /* See parse_link_formatted_string() for dynamic naming when(s). */ 1808 if (!avs_mach_singular_ssp(mach)) 1809 return 0; 1810 ssp_port = avs_mach_ssp_port(mach); 1811 1812 if (!avs_mach_singular_tdm(mach, ssp_port)) 1813 return 0; 1814 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); 1815 1816 buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL); 1817 if (!buf) 1818 return -ENOMEM; 1819 avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot); 1820 route->source = buf; 1821 1822 buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL); 1823 if (!buf) 1824 return -ENOMEM; 1825 avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot); 1826 route->sink = buf; 1827 1828 if (route->control) { 1829 buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL); 1830 if (!buf) 1831 return -ENOMEM; 1832 avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot); 1833 route->control = buf; 1834 } 1835 1836 return 0; 1837} 1838 1839static int avs_widget_load(struct snd_soc_component *comp, int index, 1840 struct snd_soc_dapm_widget *w, 1841 struct snd_soc_tplg_dapm_widget *dw) 1842{ 1843 struct snd_soc_acpi_mach *mach; 1844 struct avs_tplg_path_template *template; 1845 struct avs_soc_component *acomp = to_avs_soc_component(comp); 1846 struct avs_tplg *tplg; 1847 int ssp_port, tdm_slot; 1848 1849 if (!le32_to_cpu(dw->priv.size)) 1850 return 0; 1851 1852 w->no_wname_in_kcontrol_name = true; 1853 1854 if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) { 1855 dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n"); 1856 w->ignore_suspend = false; 1857 } 1858 1859 tplg = acomp->tplg; 1860 mach = dev_get_platdata(comp->card->dev); 1861 if (!avs_mach_singular_ssp(mach)) 1862 goto static_name; 1863 ssp_port = avs_mach_ssp_port(mach); 1864 1865 /* See parse_link_formatted_string() for dynamic naming when(s). */ 1866 if (avs_mach_singular_tdm(mach, ssp_port)) { 1867 /* size is based on possible %d -> SSP:TDM, where SSP and TDM < 16 + '\0' */ 1868 size_t size = strlen(dw->name) + 3; 1869 char *buf; 1870 1871 tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); 1872 1873 buf = kmalloc(size, GFP_KERNEL); 1874 if (!buf) 1875 return -ENOMEM; 1876 avs_ssp_sprint(buf, size, dw->name, ssp_port, tdm_slot); 1877 kfree(w->name); 1878 /* w->name is freed later by soc_tplg_dapm_widget_create() */ 1879 w->name = buf; 1880 } 1881 1882static_name: 1883 template = avs_tplg_path_template_create(comp, tplg, dw->priv.array, 1884 le32_to_cpu(dw->priv.size)); 1885 if (IS_ERR(template)) { 1886 dev_err(comp->dev, "widget %s load failed: %ld\n", dw->name, 1887 PTR_ERR(template)); 1888 return PTR_ERR(template); 1889 } 1890 1891 w->priv = template; /* link path information to widget */ 1892 list_add_tail(&template->node, &tplg->path_tmpl_list); 1893 return 0; 1894} 1895 1896static int avs_widget_ready(struct snd_soc_component *comp, int index, 1897 struct snd_soc_dapm_widget *w, 1898 struct snd_soc_tplg_dapm_widget *dw) 1899{ 1900 struct avs_tplg_path_template *template = w->priv; 1901 1902 template->w = w; 1903 return 0; 1904} 1905 1906static int avs_dai_load(struct snd_soc_component *comp, int index, 1907 struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm, 1908 struct snd_soc_dai *dai) 1909{ 1910 u32 fe_subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 | 1911 SNDRV_PCM_SUBFMTBIT_MSBITS_24 | 1912 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX; 1913 1914 if (pcm) { 1915 dai_drv->ops = &avs_dai_fe_ops; 1916 dai_drv->capture.subformats = fe_subformats; 1917 dai_drv->playback.subformats = fe_subformats; 1918 } 1919 1920 return 0; 1921} 1922 1923static int avs_link_load(struct snd_soc_component *comp, int index, struct snd_soc_dai_link *link, 1924 struct snd_soc_tplg_link_config *cfg) 1925{ 1926 if (link->ignore_suspend && !AVS_S0IX_SUPPORTED) { 1927 dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n"); 1928 link->ignore_suspend = false; 1929 } 1930 1931 if (!link->no_pcm) { 1932 /* Stream control handled by IPCs. */ 1933 link->nonatomic = true; 1934 1935 /* Open LINK (BE) pipes last and close them first to prevent xruns. */ 1936 link->trigger[0] = SND_SOC_DPCM_TRIGGER_PRE; 1937 link->trigger[1] = SND_SOC_DPCM_TRIGGER_PRE; 1938 } else { 1939 /* Do not ignore codec capabilities. */ 1940 link->dpcm_merged_format = 1; 1941 } 1942 1943 return 0; 1944} 1945 1946static const struct avs_tplg_token_parser manifest_parsers[] = { 1947 { 1948 .token = AVS_TKN_MANIFEST_NAME_STRING, 1949 .type = SND_SOC_TPLG_TUPLE_TYPE_STRING, 1950 .offset = offsetof(struct avs_tplg, name), 1951 .parse = parse_link_formatted_string, 1952 }, 1953 { 1954 .token = AVS_TKN_MANIFEST_VERSION_U32, 1955 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 1956 .offset = offsetof(struct avs_tplg, version), 1957 .parse = avs_parse_word_token, 1958 }, 1959}; 1960 1961static int avs_manifest(struct snd_soc_component *comp, int index, 1962 struct snd_soc_tplg_manifest *manifest) 1963{ 1964 struct snd_soc_tplg_vendor_array *tuples = manifest->priv.array; 1965 struct avs_soc_component *acomp = to_avs_soc_component(comp); 1966 size_t remaining = le32_to_cpu(manifest->priv.size); 1967 bool has_init_config = true; 1968 u32 offset; 1969 int ret; 1970 1971 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 1972 AVS_TKN_MANIFEST_NUM_LIBRARIES_U32, &offset); 1973 /* Manifest MUST begin with a header. */ 1974 if (!ret && !offset) 1975 ret = -EINVAL; 1976 if (ret) { 1977 dev_err(comp->dev, "incorrect manifest format: %d\n", ret); 1978 return ret; 1979 } 1980 1981 /* Process header which precedes any of the dictionaries. */ 1982 ret = avs_parse_tokens(comp, acomp->tplg, manifest_parsers, 1983 ARRAY_SIZE(manifest_parsers), tuples, offset); 1984 if (ret < 0) 1985 return ret; 1986 1987 remaining -= offset; 1988 tuples = avs_tplg_vendor_array_at(tuples, offset); 1989 1990 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 1991 AVS_TKN_MANIFEST_NUM_AFMTS_U32, &offset); 1992 if (ret) { 1993 dev_err(comp->dev, "audio formats lookup failed: %d\n", ret); 1994 return ret; 1995 } 1996 1997 /* Libraries dictionary. */ 1998 ret = avs_tplg_parse_libraries(comp, tuples, offset); 1999 if (ret < 0) 2000 return ret; 2001 2002 remaining -= offset; 2003 tuples = avs_tplg_vendor_array_at(tuples, offset); 2004 2005 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 2006 AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32, &offset); 2007 if (ret) { 2008 dev_err(comp->dev, "modcfgs_base lookup failed: %d\n", ret); 2009 return ret; 2010 } 2011 2012 /* Audio formats dictionary. */ 2013 ret = avs_tplg_parse_audio_formats(comp, tuples, offset); 2014 if (ret < 0) 2015 return ret; 2016 2017 remaining -= offset; 2018 tuples = avs_tplg_vendor_array_at(tuples, offset); 2019 2020 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 2021 AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32, &offset); 2022 if (ret) { 2023 dev_err(comp->dev, "modcfgs_ext lookup failed: %d\n", ret); 2024 return ret; 2025 } 2026 2027 /* Module configs-base dictionary. */ 2028 ret = avs_tplg_parse_modcfgs_base(comp, tuples, offset); 2029 if (ret < 0) 2030 return ret; 2031 2032 remaining -= offset; 2033 tuples = avs_tplg_vendor_array_at(tuples, offset); 2034 2035 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 2036 AVS_TKN_MANIFEST_NUM_PPLCFGS_U32, &offset); 2037 if (ret) { 2038 dev_err(comp->dev, "pplcfgs lookup failed: %d\n", ret); 2039 return ret; 2040 } 2041 2042 /* Module configs-ext dictionary. */ 2043 ret = avs_tplg_parse_modcfgs_ext(comp, tuples, offset); 2044 if (ret < 0) 2045 return ret; 2046 2047 remaining -= offset; 2048 tuples = avs_tplg_vendor_array_at(tuples, offset); 2049 2050 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 2051 AVS_TKN_MANIFEST_NUM_BINDINGS_U32, &offset); 2052 if (ret) { 2053 dev_err(comp->dev, "bindings lookup failed: %d\n", ret); 2054 return ret; 2055 } 2056 2057 /* Pipeline configs dictionary. */ 2058 ret = avs_tplg_parse_pplcfgs(comp, tuples, offset); 2059 if (ret < 0) 2060 return ret; 2061 2062 remaining -= offset; 2063 tuples = avs_tplg_vendor_array_at(tuples, offset); 2064 2065 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 2066 AVS_TKN_MANIFEST_NUM_CONDPATH_TMPLS_U32, &offset); 2067 if (ret) { 2068 dev_err(comp->dev, "condpath lookup failed: %d\n", ret); 2069 return ret; 2070 } 2071 2072 /* Bindings dictionary. */ 2073 ret = avs_tplg_parse_bindings(comp, tuples, offset); 2074 if (ret < 0) 2075 return ret; 2076 2077 remaining -= offset; 2078 tuples = avs_tplg_vendor_array_at(tuples, offset); 2079 2080 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 2081 AVS_TKN_MANIFEST_NUM_INIT_CONFIGS_U32, &offset); 2082 if (ret == -ENOENT) { 2083 dev_dbg(comp->dev, "init config lookup failed: %d\n", ret); 2084 has_init_config = false; 2085 } else if (ret) { 2086 dev_err(comp->dev, "init config lookup failed: %d\n", ret); 2087 return ret; 2088 } 2089 2090 /* Condpaths dictionary. */ 2091 ret = avs_tplg_parse_condpath_templates(comp, tuples, 2092 has_init_config ? offset : remaining); 2093 if (ret < 0) 2094 return ret; 2095 2096 if (!has_init_config) 2097 return 0; 2098 2099 remaining -= offset; 2100 tuples = avs_tplg_vendor_array_at(tuples, offset); 2101 2102 /* Initial configs dictionary. */ 2103 ret = avs_tplg_parse_initial_configs(comp, tuples, remaining, &offset); 2104 if (ret < 0) 2105 return ret; 2106 2107 remaining -= offset; 2108 tuples = avs_tplg_vendor_array_at(tuples, offset); 2109 2110 ret = avs_tplg_vendor_array_lookup(tuples, remaining, 2111 AVS_TKN_MANIFEST_NUM_NHLT_CONFIGS_U32, &offset); 2112 if (ret == -ENOENT) 2113 return 0; 2114 if (ret) { 2115 dev_err(comp->dev, "NHLT config lookup failed: %d\n", ret); 2116 return ret; 2117 } 2118 2119 tuples = avs_tplg_vendor_array_at(tuples, offset); 2120 2121 /* NHLT configs dictionary. */ 2122 return avs_tplg_parse_nhlt_configs(comp, tuples, remaining); 2123} 2124 2125enum { 2126 AVS_CONTROL_OPS_VOLUME = 257, 2127 AVS_CONTROL_OPS_MUTE, 2128}; 2129 2130static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = { 2131 { 2132 .id = AVS_CONTROL_OPS_VOLUME, 2133 .get = avs_control_volume_get, 2134 .put = avs_control_volume_put, 2135 .info = avs_control_volume_info, 2136 }, 2137 { 2138 .id = AVS_CONTROL_OPS_MUTE, 2139 .get = avs_control_mute_get, 2140 .put = avs_control_mute_put, 2141 .info = avs_control_mute_info, 2142 }, 2143}; 2144 2145static const struct avs_tplg_token_parser control_parsers[] = { 2146 { 2147 .token = AVS_TKN_KCONTROL_ID_U32, 2148 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 2149 .offset = offsetof(struct avs_control_data, id), 2150 .parse = avs_parse_word_token, 2151 }, 2152}; 2153 2154static int 2155avs_control_load(struct snd_soc_component *comp, int index, struct snd_kcontrol_new *ctmpl, 2156 struct snd_soc_tplg_ctl_hdr *hdr) 2157{ 2158 struct snd_soc_tplg_vendor_array *tuples; 2159 struct snd_soc_tplg_mixer_control *tmc; 2160 struct avs_control_data *ctl_data; 2161 struct soc_mixer_control *mc; 2162 size_t block_size; 2163 int ret, i; 2164 2165 switch (le32_to_cpu(hdr->type)) { 2166 case SND_SOC_TPLG_TYPE_MIXER: 2167 break; 2168 default: 2169 return -EINVAL; 2170 } 2171 2172 mc = (struct soc_mixer_control *)ctmpl->private_value; 2173 tmc = container_of(hdr, typeof(*tmc), hdr); 2174 tuples = tmc->priv.array; 2175 block_size = le32_to_cpu(tmc->priv.size); 2176 2177 ctl_data = devm_kzalloc(comp->card->dev, sizeof(*ctl_data), GFP_KERNEL); 2178 if (!ctl_data) 2179 return -ENOMEM; 2180 2181 ret = parse_dictionary_entries(comp, tuples, block_size, ctl_data, 1, sizeof(*ctl_data), 2182 AVS_TKN_KCONTROL_ID_U32, control_parsers, 2183 ARRAY_SIZE(control_parsers)); 2184 if (ret) 2185 return ret; 2186 2187 mc->dobj.private = ctl_data; 2188 if (tmc->invert) { 2189 ctl_data->values[0] = mc->max; 2190 for (i = 1; i < mc->num_channels; i++) 2191 ctl_data->values[i] = mc->max; 2192 } 2193 2194 return 0; 2195} 2196 2197static const struct snd_soc_tplg_ops avs_tplg_ops = { 2198 .io_ops = avs_control_ops, 2199 .io_ops_count = ARRAY_SIZE(avs_control_ops), 2200 .control_load = avs_control_load, 2201 .dapm_route_load = avs_route_load, 2202 .widget_load = avs_widget_load, 2203 .widget_ready = avs_widget_ready, 2204 .dai_load = avs_dai_load, 2205 .link_load = avs_link_load, 2206 .manifest = avs_manifest, 2207}; 2208 2209struct avs_tplg *avs_tplg_new(struct snd_soc_component *comp) 2210{ 2211 struct avs_tplg *tplg; 2212 2213 tplg = devm_kzalloc(comp->card->dev, sizeof(*tplg), GFP_KERNEL); 2214 if (!tplg) 2215 return NULL; 2216 2217 tplg->comp = comp; 2218 INIT_LIST_HEAD(&tplg->path_tmpl_list); 2219 2220 return tplg; 2221} 2222 2223int avs_load_topology(struct snd_soc_component *comp, const char *filename) 2224{ 2225 const struct firmware *fw; 2226 int ret; 2227 2228 ret = request_firmware(&fw, filename, comp->dev); 2229 if (ret < 0) { 2230 dev_err(comp->dev, "request topology \"%s\" failed: %d\n", filename, ret); 2231 return ret; 2232 } 2233 2234 ret = snd_soc_tplg_component_load(comp, &avs_tplg_ops, fw); 2235 if (ret < 0) 2236 dev_err(comp->dev, "load topology \"%s\" failed: %d\n", filename, ret); 2237 2238 release_firmware(fw); 2239 return ret; 2240} 2241 2242int avs_remove_topology(struct snd_soc_component *comp) 2243{ 2244 snd_soc_tplg_component_remove(comp); 2245 2246 return 0; 2247}
~/
Read-only file preview.