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