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