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