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