Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/intel/avs/topology.c
26583 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 struct avs_tplg_path *
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
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 *
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
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
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
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
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
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
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
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
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
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
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
2025
int avs_remove_topology(struct snd_soc_component *comp)
2026
{
2027
snd_soc_tplg_component_remove(comp);
2028
2029
return 0;
2030
}
2031
2032