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