Linux Audio

Check our new training course

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