Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/qcom/qdsp6/topology.c
29268 views
1
// SPDX-License-Identifier: GPL-2.0
2
// Copyright (c) 2020, Linaro Limited
3
4
#include <linux/cleanup.h>
5
#include <sound/soc.h>
6
#include <sound/soc-dapm.h>
7
#include <sound/pcm.h>
8
#include <sound/control.h>
9
#include <sound/asound.h>
10
#include <linux/firmware.h>
11
#include <sound/soc-topology.h>
12
#include <sound/soc-dpcm.h>
13
#include <uapi/sound/snd_ar_tokens.h>
14
#include <linux/kernel.h>
15
#include <linux/wait.h>
16
#include "q6apm.h"
17
#include "audioreach.h"
18
19
struct snd_ar_control {
20
u32 graph_id; /* Graph ID */
21
u32 sgid; /* Sub Graph ID */
22
u32 module_instance_id; /* Connected Module Instance ID */
23
struct snd_soc_dapm_widget *w;
24
struct list_head node;
25
struct snd_soc_component *scomp;
26
};
27
28
static struct audioreach_graph_info *audioreach_tplg_alloc_graph_info(struct q6apm *apm,
29
uint32_t graph_id,
30
bool *found)
31
{
32
struct audioreach_graph_info *info;
33
int ret;
34
35
mutex_lock(&apm->lock);
36
info = idr_find(&apm->graph_info_idr, graph_id);
37
mutex_unlock(&apm->lock);
38
39
if (info) {
40
*found = true;
41
return info;
42
}
43
44
*found = false;
45
info = kzalloc(sizeof(*info), GFP_KERNEL);
46
if (!info)
47
return ERR_PTR(-ENOMEM);
48
49
INIT_LIST_HEAD(&info->sg_list);
50
51
mutex_lock(&apm->lock);
52
ret = idr_alloc_u32(&apm->graph_info_idr, info, &graph_id, graph_id, GFP_KERNEL);
53
mutex_unlock(&apm->lock);
54
55
if (ret < 0) {
56
dev_err(apm->dev, "Failed to allocate Graph ID (%x)\n", graph_id);
57
kfree(info);
58
return ERR_PTR(ret);
59
}
60
61
info->id = graph_id;
62
63
return info;
64
}
65
66
static void audioreach_tplg_add_sub_graph(struct audioreach_sub_graph *sg,
67
struct audioreach_graph_info *info)
68
{
69
list_add_tail(&sg->node, &info->sg_list);
70
sg->info = info;
71
info->num_sub_graphs++;
72
}
73
74
static struct audioreach_sub_graph *audioreach_tplg_alloc_sub_graph(struct q6apm *apm,
75
uint32_t sub_graph_id,
76
bool *found)
77
{
78
struct audioreach_sub_graph *sg;
79
int ret;
80
81
if (!sub_graph_id)
82
return ERR_PTR(-EINVAL);
83
84
/* Find if there is already a matching sub-graph */
85
mutex_lock(&apm->lock);
86
sg = idr_find(&apm->sub_graphs_idr, sub_graph_id);
87
mutex_unlock(&apm->lock);
88
89
if (sg) {
90
*found = true;
91
return sg;
92
}
93
94
*found = false;
95
sg = kzalloc(sizeof(*sg), GFP_KERNEL);
96
if (!sg)
97
return ERR_PTR(-ENOMEM);
98
99
INIT_LIST_HEAD(&sg->container_list);
100
101
mutex_lock(&apm->lock);
102
ret = idr_alloc_u32(&apm->sub_graphs_idr, sg, &sub_graph_id, sub_graph_id, GFP_KERNEL);
103
mutex_unlock(&apm->lock);
104
105
if (ret < 0) {
106
dev_err(apm->dev, "Failed to allocate Sub-Graph Instance ID (%x)\n", sub_graph_id);
107
kfree(sg);
108
return ERR_PTR(ret);
109
}
110
111
sg->sub_graph_id = sub_graph_id;
112
113
return sg;
114
}
115
116
static struct audioreach_container *audioreach_tplg_alloc_container(struct q6apm *apm,
117
struct audioreach_sub_graph *sg,
118
uint32_t container_id,
119
bool *found)
120
{
121
struct audioreach_container *cont;
122
int ret;
123
124
if (!container_id)
125
return ERR_PTR(-EINVAL);
126
127
mutex_lock(&apm->lock);
128
cont = idr_find(&apm->containers_idr, container_id);
129
mutex_unlock(&apm->lock);
130
131
if (cont) {
132
*found = true;
133
return cont;
134
}
135
*found = false;
136
137
cont = kzalloc(sizeof(*cont), GFP_KERNEL);
138
if (!cont)
139
return ERR_PTR(-ENOMEM);
140
141
INIT_LIST_HEAD(&cont->modules_list);
142
143
mutex_lock(&apm->lock);
144
ret = idr_alloc_u32(&apm->containers_idr, cont, &container_id, container_id, GFP_KERNEL);
145
mutex_unlock(&apm->lock);
146
147
if (ret < 0) {
148
dev_err(apm->dev, "Failed to allocate Container Instance ID (%x)\n", container_id);
149
kfree(cont);
150
return ERR_PTR(ret);
151
}
152
153
cont->container_id = container_id;
154
cont->sub_graph = sg;
155
/* add to container list */
156
list_add_tail(&cont->node, &sg->container_list);
157
sg->num_containers++;
158
159
return cont;
160
}
161
162
static struct audioreach_module *audioreach_tplg_alloc_module(struct q6apm *apm,
163
struct audioreach_container *cont,
164
struct snd_soc_dapm_widget *w,
165
uint32_t module_id, bool *found)
166
{
167
struct audioreach_module *mod;
168
int ret;
169
170
mutex_lock(&apm->lock);
171
mod = idr_find(&apm->modules_idr, module_id);
172
mutex_unlock(&apm->lock);
173
174
if (mod) {
175
*found = true;
176
return mod;
177
}
178
*found = false;
179
mod = kzalloc(sizeof(*mod), GFP_KERNEL);
180
if (!mod)
181
return ERR_PTR(-ENOMEM);
182
183
mutex_lock(&apm->lock);
184
if (!module_id) { /* alloc module id dynamically */
185
ret = idr_alloc_cyclic(&apm->modules_idr, mod,
186
AR_MODULE_DYNAMIC_INSTANCE_ID_START,
187
AR_MODULE_DYNAMIC_INSTANCE_ID_END, GFP_KERNEL);
188
} else {
189
ret = idr_alloc_u32(&apm->modules_idr, mod, &module_id, module_id, GFP_KERNEL);
190
}
191
mutex_unlock(&apm->lock);
192
193
if (ret < 0) {
194
dev_err(apm->dev, "Failed to allocate Module Instance ID (%x)\n", module_id);
195
kfree(mod);
196
return ERR_PTR(ret);
197
}
198
199
mod->instance_id = module_id;
200
/* add to module list */
201
list_add_tail(&mod->node, &cont->modules_list);
202
mod->container = cont;
203
mod->widget = w;
204
cont->num_modules++;
205
206
return mod;
207
}
208
209
static struct snd_soc_tplg_vendor_array *audioreach_get_sg_array(
210
struct snd_soc_tplg_private *private)
211
{
212
struct snd_soc_tplg_vendor_array *sg_array = NULL;
213
bool found = false;
214
int sz;
215
216
for (sz = 0; !found && (sz < le32_to_cpu(private->size)); ) {
217
struct snd_soc_tplg_vendor_value_elem *sg_elem;
218
int tkn_count = 0;
219
220
sg_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz);
221
sg_elem = sg_array->value;
222
sz = sz + le32_to_cpu(sg_array->size);
223
while (!found && tkn_count <= (le32_to_cpu(sg_array->num_elems) - 1)) {
224
switch (le32_to_cpu(sg_elem->token)) {
225
case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID:
226
found = true;
227
break;
228
default:
229
break;
230
}
231
tkn_count++;
232
sg_elem++;
233
}
234
}
235
236
if (found)
237
return sg_array;
238
239
return NULL;
240
}
241
242
static struct snd_soc_tplg_vendor_array *audioreach_get_cont_array(
243
struct snd_soc_tplg_private *private)
244
{
245
struct snd_soc_tplg_vendor_array *cont_array = NULL;
246
bool found = false;
247
int sz;
248
249
for (sz = 0; !found && (sz < le32_to_cpu(private->size)); ) {
250
struct snd_soc_tplg_vendor_value_elem *cont_elem;
251
int tkn_count = 0;
252
253
cont_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz);
254
cont_elem = cont_array->value;
255
sz = sz + le32_to_cpu(cont_array->size);
256
while (!found && tkn_count <= (le32_to_cpu(cont_array->num_elems) - 1)) {
257
switch (le32_to_cpu(cont_elem->token)) {
258
case AR_TKN_U32_CONTAINER_INSTANCE_ID:
259
found = true;
260
break;
261
default:
262
break;
263
}
264
tkn_count++;
265
cont_elem++;
266
}
267
}
268
269
if (found)
270
return cont_array;
271
272
return NULL;
273
}
274
275
static struct snd_soc_tplg_vendor_array *audioreach_get_module_array(
276
struct snd_soc_tplg_private *private)
277
{
278
struct snd_soc_tplg_vendor_array *mod_array = NULL;
279
bool found = false;
280
int sz = 0;
281
282
for (sz = 0; !found && (sz < le32_to_cpu(private->size)); ) {
283
struct snd_soc_tplg_vendor_value_elem *mod_elem;
284
int tkn_count = 0;
285
286
mod_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz);
287
mod_elem = mod_array->value;
288
sz = sz + le32_to_cpu(mod_array->size);
289
while (!found && tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) {
290
switch (le32_to_cpu(mod_elem->token)) {
291
case AR_TKN_U32_MODULE_INSTANCE_ID:
292
found = true;
293
break;
294
default:
295
break;
296
}
297
tkn_count++;
298
mod_elem++;
299
}
300
}
301
302
if (found)
303
return mod_array;
304
305
return NULL;
306
}
307
308
static struct audioreach_module_priv_data *audioreach_get_module_priv_data(
309
struct snd_soc_tplg_private *private)
310
{
311
int sz;
312
313
for (sz = 0; sz < le32_to_cpu(private->size); ) {
314
struct snd_soc_tplg_vendor_array *mod_array;
315
316
mod_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz);
317
if (le32_to_cpu(mod_array->type) == SND_SOC_AR_TPLG_MODULE_CFG_TYPE) {
318
struct audioreach_module_priv_data *pdata;
319
320
pdata = kzalloc(struct_size(pdata, data, le32_to_cpu(mod_array->size)),
321
GFP_KERNEL);
322
if (!pdata)
323
return ERR_PTR(-ENOMEM);
324
325
memcpy(pdata, ((u8 *)private->data + sz), struct_size(pdata, data,
326
le32_to_cpu(mod_array->size)));
327
return pdata;
328
}
329
330
sz = sz + le32_to_cpu(mod_array->size);
331
}
332
333
return NULL;
334
}
335
336
static struct audioreach_sub_graph *audioreach_parse_sg_tokens(struct q6apm *apm,
337
struct snd_soc_tplg_private *private)
338
{
339
struct snd_soc_tplg_vendor_value_elem *sg_elem;
340
struct snd_soc_tplg_vendor_array *sg_array;
341
struct audioreach_graph_info *info = NULL;
342
int graph_id, sub_graph_id, tkn_count = 0;
343
struct audioreach_sub_graph *sg;
344
bool found;
345
346
sg_array = audioreach_get_sg_array(private);
347
sg_elem = sg_array->value;
348
349
while (tkn_count <= (le32_to_cpu(sg_array->num_elems) - 1)) {
350
switch (le32_to_cpu(sg_elem->token)) {
351
case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID:
352
sub_graph_id = le32_to_cpu(sg_elem->value);
353
sg = audioreach_tplg_alloc_sub_graph(apm, sub_graph_id, &found);
354
if (IS_ERR(sg)) {
355
return sg;
356
} else if (found) {
357
/* Already parsed data for this sub-graph */
358
return sg;
359
}
360
break;
361
case AR_TKN_DAI_INDEX:
362
/* Sub graph is associated with predefined graph */
363
graph_id = le32_to_cpu(sg_elem->value);
364
info = audioreach_tplg_alloc_graph_info(apm, graph_id, &found);
365
if (IS_ERR(info))
366
return ERR_CAST(info);
367
break;
368
case AR_TKN_U32_SUB_GRAPH_PERF_MODE:
369
sg->perf_mode = le32_to_cpu(sg_elem->value);
370
break;
371
case AR_TKN_U32_SUB_GRAPH_DIRECTION:
372
sg->direction = le32_to_cpu(sg_elem->value);
373
break;
374
case AR_TKN_U32_SUB_GRAPH_SCENARIO_ID:
375
sg->scenario_id = le32_to_cpu(sg_elem->value);
376
break;
377
default:
378
dev_err(apm->dev, "Not a valid token %d for graph\n", sg_elem->token);
379
break;
380
381
}
382
tkn_count++;
383
sg_elem++;
384
}
385
386
/* Sub graph is associated with predefined graph */
387
if (info)
388
audioreach_tplg_add_sub_graph(sg, info);
389
390
return sg;
391
}
392
393
static struct audioreach_container *audioreach_parse_cont_tokens(struct q6apm *apm,
394
struct audioreach_sub_graph *sg,
395
struct snd_soc_tplg_private *private)
396
{
397
struct snd_soc_tplg_vendor_value_elem *cont_elem;
398
struct snd_soc_tplg_vendor_array *cont_array;
399
struct audioreach_container *cont;
400
int container_id, tkn_count = 0;
401
bool found = false;
402
403
cont_array = audioreach_get_cont_array(private);
404
cont_elem = cont_array->value;
405
406
while (tkn_count <= (le32_to_cpu(cont_array->num_elems) - 1)) {
407
switch (le32_to_cpu(cont_elem->token)) {
408
case AR_TKN_U32_CONTAINER_INSTANCE_ID:
409
container_id = le32_to_cpu(cont_elem->value);
410
cont = audioreach_tplg_alloc_container(apm, sg, container_id, &found);
411
if (IS_ERR(cont) || found)/* Error or Already parsed container data */
412
return cont;
413
break;
414
case AR_TKN_U32_CONTAINER_CAPABILITY_ID:
415
cont->capability_id = le32_to_cpu(cont_elem->value);
416
break;
417
case AR_TKN_U32_CONTAINER_STACK_SIZE:
418
cont->stack_size = le32_to_cpu(cont_elem->value);
419
break;
420
case AR_TKN_U32_CONTAINER_GRAPH_POS:
421
cont->graph_pos = le32_to_cpu(cont_elem->value);
422
break;
423
case AR_TKN_U32_CONTAINER_PROC_DOMAIN:
424
cont->proc_domain = le32_to_cpu(cont_elem->value);
425
break;
426
default:
427
dev_err(apm->dev, "Not a valid token %d for graph\n", cont_elem->token);
428
break;
429
430
}
431
tkn_count++;
432
cont_elem++;
433
}
434
435
return cont;
436
}
437
438
static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *apm,
439
struct audioreach_container *cont,
440
struct snd_soc_tplg_private *private,
441
struct snd_soc_dapm_widget *w)
442
{
443
uint32_t max_ip_port = 0, max_op_port = 0;
444
uint32_t src_mod_op_port_id[AR_MAX_MOD_LINKS] = { 0, };
445
uint32_t dst_mod_inst_id[AR_MAX_MOD_LINKS] = { 0, };
446
uint32_t dst_mod_ip_port_id[AR_MAX_MOD_LINKS] = { 0, };
447
uint32_t src_mod_inst_id = 0;
448
449
int module_id = 0, instance_id = 0, tkn_count = 0;
450
struct snd_soc_tplg_vendor_value_elem *mod_elem;
451
struct snd_soc_tplg_vendor_array *mod_array;
452
struct audioreach_module *mod = NULL;
453
uint32_t token;
454
bool found;
455
int max_tokens;
456
457
mod_array = audioreach_get_module_array(private);
458
mod_elem = mod_array->value;
459
max_tokens = le32_to_cpu(mod_array->num_elems);
460
while (tkn_count <= (max_tokens - 1)) {
461
token = le32_to_cpu(mod_elem->token);
462
switch (token) {
463
/* common module info */
464
case AR_TKN_U32_MODULE_ID:
465
module_id = le32_to_cpu(mod_elem->value);
466
break;
467
case AR_TKN_U32_MODULE_INSTANCE_ID:
468
instance_id = le32_to_cpu(mod_elem->value);
469
mod = audioreach_tplg_alloc_module(apm, cont, w,
470
instance_id, &found);
471
if (IS_ERR(mod)) {
472
return mod;
473
} else if (found) {
474
dev_err(apm->dev, "Duplicate Module Instance ID 0x%08x found\n",
475
instance_id);
476
return ERR_PTR(-EINVAL);
477
}
478
479
break;
480
case AR_TKN_U32_MODULE_MAX_IP_PORTS:
481
max_ip_port = le32_to_cpu(mod_elem->value);
482
break;
483
case AR_TKN_U32_MODULE_MAX_OP_PORTS:
484
max_op_port = le32_to_cpu(mod_elem->value);
485
break;
486
case AR_TKN_U32_MODULE_SRC_INSTANCE_ID:
487
src_mod_inst_id = le32_to_cpu(mod_elem->value);
488
break;
489
case AR_TKN_U32_MODULE_SRC_OP_PORT_ID:
490
src_mod_op_port_id[0] = le32_to_cpu(mod_elem->value);
491
break;
492
case AR_TKN_U32_MODULE_SRC_OP_PORT_ID1:
493
src_mod_op_port_id[1] = le32_to_cpu(mod_elem->value);
494
break;
495
case AR_TKN_U32_MODULE_SRC_OP_PORT_ID2:
496
src_mod_op_port_id[2] = le32_to_cpu(mod_elem->value);
497
break;
498
case AR_TKN_U32_MODULE_SRC_OP_PORT_ID3:
499
src_mod_op_port_id[3] = le32_to_cpu(mod_elem->value);
500
break;
501
case AR_TKN_U32_MODULE_SRC_OP_PORT_ID4:
502
src_mod_op_port_id[4] = le32_to_cpu(mod_elem->value);
503
break;
504
case AR_TKN_U32_MODULE_SRC_OP_PORT_ID5:
505
src_mod_op_port_id[5] = le32_to_cpu(mod_elem->value);
506
break;
507
case AR_TKN_U32_MODULE_SRC_OP_PORT_ID6:
508
src_mod_op_port_id[6] = le32_to_cpu(mod_elem->value);
509
break;
510
case AR_TKN_U32_MODULE_SRC_OP_PORT_ID7:
511
src_mod_op_port_id[7] = le32_to_cpu(mod_elem->value);
512
break;
513
case AR_TKN_U32_MODULE_DST_INSTANCE_ID:
514
dst_mod_inst_id[0] = le32_to_cpu(mod_elem->value);
515
break;
516
case AR_TKN_U32_MODULE_DST_INSTANCE_ID1:
517
dst_mod_inst_id[1] = le32_to_cpu(mod_elem->value);
518
break;
519
case AR_TKN_U32_MODULE_DST_INSTANCE_ID2:
520
dst_mod_inst_id[2] = le32_to_cpu(mod_elem->value);
521
break;
522
case AR_TKN_U32_MODULE_DST_INSTANCE_ID3:
523
dst_mod_inst_id[3] = le32_to_cpu(mod_elem->value);
524
break;
525
case AR_TKN_U32_MODULE_DST_INSTANCE_ID4:
526
dst_mod_inst_id[4] = le32_to_cpu(mod_elem->value);
527
break;
528
case AR_TKN_U32_MODULE_DST_INSTANCE_ID5:
529
dst_mod_inst_id[5] = le32_to_cpu(mod_elem->value);
530
break;
531
case AR_TKN_U32_MODULE_DST_INSTANCE_ID6:
532
dst_mod_inst_id[6] = le32_to_cpu(mod_elem->value);
533
break;
534
case AR_TKN_U32_MODULE_DST_INSTANCE_ID7:
535
dst_mod_inst_id[7] = le32_to_cpu(mod_elem->value);
536
break;
537
case AR_TKN_U32_MODULE_DST_IN_PORT_ID:
538
dst_mod_ip_port_id[0] = le32_to_cpu(mod_elem->value);
539
break;
540
case AR_TKN_U32_MODULE_DST_IN_PORT_ID1:
541
dst_mod_ip_port_id[1] = le32_to_cpu(mod_elem->value);
542
break;
543
case AR_TKN_U32_MODULE_DST_IN_PORT_ID2:
544
dst_mod_ip_port_id[2] = le32_to_cpu(mod_elem->value);
545
break;
546
case AR_TKN_U32_MODULE_DST_IN_PORT_ID3:
547
dst_mod_ip_port_id[3] = le32_to_cpu(mod_elem->value);
548
break;
549
case AR_TKN_U32_MODULE_DST_IN_PORT_ID4:
550
dst_mod_ip_port_id[4] = le32_to_cpu(mod_elem->value);
551
break;
552
case AR_TKN_U32_MODULE_DST_IN_PORT_ID5:
553
dst_mod_ip_port_id[5] = le32_to_cpu(mod_elem->value);
554
break;
555
case AR_TKN_U32_MODULE_DST_IN_PORT_ID6:
556
dst_mod_ip_port_id[6] = le32_to_cpu(mod_elem->value);
557
break;
558
case AR_TKN_U32_MODULE_DST_IN_PORT_ID7:
559
dst_mod_ip_port_id[7] = le32_to_cpu(mod_elem->value);
560
break;
561
default:
562
break;
563
564
}
565
tkn_count++;
566
mod_elem++;
567
}
568
569
if (mod) {
570
int pn, id = 0;
571
572
mod->module_id = module_id;
573
mod->max_ip_port = max_ip_port;
574
mod->max_op_port = max_op_port;
575
mod->src_mod_inst_id = src_mod_inst_id;
576
for (pn = 0; pn < mod->max_op_port; pn++) {
577
if (src_mod_op_port_id[pn] && dst_mod_inst_id[pn] &&
578
dst_mod_ip_port_id[pn]) {
579
mod->src_mod_op_port_id[id] = src_mod_op_port_id[pn];
580
mod->dst_mod_inst_id[id] = dst_mod_inst_id[pn];
581
mod->dst_mod_ip_port_id[id] = dst_mod_ip_port_id[pn];
582
id++;
583
mod->num_connections = id;
584
}
585
}
586
}
587
588
return mod;
589
}
590
591
static int audioreach_widget_load_module_common(struct snd_soc_component *component,
592
int index, struct snd_soc_dapm_widget *w,
593
struct snd_soc_tplg_dapm_widget *tplg_w)
594
{
595
struct q6apm *apm = dev_get_drvdata(component->dev);
596
struct audioreach_container *cont;
597
struct audioreach_sub_graph *sg;
598
struct audioreach_module *mod;
599
struct snd_soc_dobj *dobj;
600
601
sg = audioreach_parse_sg_tokens(apm, &tplg_w->priv);
602
if (IS_ERR(sg))
603
return PTR_ERR(sg);
604
605
cont = audioreach_parse_cont_tokens(apm, sg, &tplg_w->priv);
606
if (IS_ERR(cont))
607
return PTR_ERR(cont);
608
609
mod = audioreach_parse_common_tokens(apm, cont, &tplg_w->priv, w);
610
if (IS_ERR_OR_NULL(mod))
611
return mod ? PTR_ERR(mod) : -ENODEV;
612
613
mod->data = audioreach_get_module_priv_data(&tplg_w->priv);
614
615
dobj = &w->dobj;
616
dobj->private = mod;
617
618
return 0;
619
}
620
621
static int audioreach_widget_load_enc_dec_cnv(struct snd_soc_component *component,
622
int index, struct snd_soc_dapm_widget *w,
623
struct snd_soc_tplg_dapm_widget *tplg_w)
624
{
625
struct snd_soc_tplg_vendor_value_elem *mod_elem;
626
struct snd_soc_tplg_vendor_array *mod_array;
627
struct audioreach_module *mod;
628
struct snd_soc_dobj *dobj;
629
int tkn_count = 0;
630
int ret;
631
632
ret = audioreach_widget_load_module_common(component, index, w, tplg_w);
633
if (ret)
634
return ret;
635
636
dobj = &w->dobj;
637
mod = dobj->private;
638
mod_array = audioreach_get_module_array(&tplg_w->priv);
639
mod_elem = mod_array->value;
640
641
while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) {
642
switch (le32_to_cpu(mod_elem->token)) {
643
case AR_TKN_U32_MODULE_FMT_INTERLEAVE:
644
mod->interleave_type = le32_to_cpu(mod_elem->value);
645
break;
646
case AR_TKN_U32_MODULE_FMT_SAMPLE_RATE:
647
mod->rate = le32_to_cpu(mod_elem->value);
648
break;
649
case AR_TKN_U32_MODULE_FMT_BIT_DEPTH:
650
mod->bit_depth = le32_to_cpu(mod_elem->value);
651
break;
652
default:
653
break;
654
}
655
tkn_count++;
656
mod_elem++;
657
}
658
659
return 0;
660
}
661
662
static int audioreach_widget_log_module_load(struct audioreach_module *mod,
663
struct snd_soc_tplg_vendor_array *mod_array)
664
{
665
struct snd_soc_tplg_vendor_value_elem *mod_elem;
666
int tkn_count = 0;
667
668
mod_elem = mod_array->value;
669
670
while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) {
671
switch (le32_to_cpu(mod_elem->token)) {
672
673
case AR_TKN_U32_MODULE_LOG_CODE:
674
mod->log_code = le32_to_cpu(mod_elem->value);
675
break;
676
case AR_TKN_U32_MODULE_LOG_TAP_POINT_ID:
677
mod->log_tap_point_id = le32_to_cpu(mod_elem->value);
678
break;
679
case AR_TKN_U32_MODULE_LOG_MODE:
680
mod->log_mode = le32_to_cpu(mod_elem->value);
681
break;
682
default:
683
break;
684
}
685
tkn_count++;
686
mod_elem++;
687
}
688
689
return 0;
690
}
691
692
static int audioreach_widget_dma_module_load(struct audioreach_module *mod,
693
struct snd_soc_tplg_vendor_array *mod_array)
694
{
695
struct snd_soc_tplg_vendor_value_elem *mod_elem;
696
int tkn_count = 0;
697
698
mod_elem = mod_array->value;
699
700
while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) {
701
switch (le32_to_cpu(mod_elem->token)) {
702
case AR_TKN_U32_MODULE_HW_IF_IDX:
703
mod->hw_interface_idx = le32_to_cpu(mod_elem->value);
704
break;
705
case AR_TKN_U32_MODULE_FMT_DATA:
706
mod->data_format = le32_to_cpu(mod_elem->value);
707
break;
708
case AR_TKN_U32_MODULE_HW_IF_TYPE:
709
mod->hw_interface_type = le32_to_cpu(mod_elem->value);
710
break;
711
default:
712
break;
713
}
714
tkn_count++;
715
mod_elem++;
716
}
717
718
return 0;
719
}
720
721
static int audioreach_widget_i2s_module_load(struct audioreach_module *mod,
722
struct snd_soc_tplg_vendor_array *mod_array)
723
{
724
struct snd_soc_tplg_vendor_value_elem *mod_elem;
725
int tkn_count = 0;
726
727
mod_elem = mod_array->value;
728
729
while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) {
730
switch (le32_to_cpu(mod_elem->token)) {
731
case AR_TKN_U32_MODULE_HW_IF_IDX:
732
mod->hw_interface_idx = le32_to_cpu(mod_elem->value);
733
break;
734
case AR_TKN_U32_MODULE_FMT_DATA:
735
mod->data_format = le32_to_cpu(mod_elem->value);
736
break;
737
case AR_TKN_U32_MODULE_HW_IF_TYPE:
738
mod->hw_interface_type = le32_to_cpu(mod_elem->value);
739
break;
740
case AR_TKN_U32_MODULE_SD_LINE_IDX:
741
mod->sd_line_idx = le32_to_cpu(mod_elem->value);
742
break;
743
case AR_TKN_U32_MODULE_WS_SRC:
744
mod->ws_src = le32_to_cpu(mod_elem->value);
745
break;
746
default:
747
break;
748
}
749
tkn_count++;
750
mod_elem++;
751
}
752
753
return 0;
754
}
755
756
static int audioreach_widget_dp_module_load(struct audioreach_module *mod,
757
struct snd_soc_tplg_vendor_array *mod_array)
758
{
759
struct snd_soc_tplg_vendor_value_elem *mod_elem;
760
int tkn_count = 0;
761
762
mod_elem = mod_array->value;
763
764
while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) {
765
switch (le32_to_cpu(mod_elem->token)) {
766
case AR_TKN_U32_MODULE_FMT_DATA:
767
mod->data_format = le32_to_cpu(mod_elem->value);
768
break;
769
default:
770
break;
771
}
772
tkn_count++;
773
mod_elem++;
774
}
775
776
return 0;
777
}
778
779
static int audioreach_widget_load_buffer(struct snd_soc_component *component,
780
int index, struct snd_soc_dapm_widget *w,
781
struct snd_soc_tplg_dapm_widget *tplg_w)
782
{
783
struct snd_soc_tplg_vendor_array *mod_array;
784
struct audioreach_module *mod;
785
struct snd_soc_dobj *dobj;
786
int ret;
787
788
ret = audioreach_widget_load_module_common(component, index, w, tplg_w);
789
if (ret)
790
return ret;
791
792
dobj = &w->dobj;
793
mod = dobj->private;
794
795
mod_array = audioreach_get_module_array(&tplg_w->priv);
796
797
switch (mod->module_id) {
798
case MODULE_ID_CODEC_DMA_SINK:
799
case MODULE_ID_CODEC_DMA_SOURCE:
800
audioreach_widget_dma_module_load(mod, mod_array);
801
break;
802
case MODULE_ID_DATA_LOGGING:
803
audioreach_widget_log_module_load(mod, mod_array);
804
break;
805
case MODULE_ID_I2S_SINK:
806
case MODULE_ID_I2S_SOURCE:
807
audioreach_widget_i2s_module_load(mod, mod_array);
808
break;
809
case MODULE_ID_DISPLAY_PORT_SINK:
810
audioreach_widget_dp_module_load(mod, mod_array);
811
break;
812
default:
813
return -EINVAL;
814
}
815
816
return 0;
817
}
818
819
static int audioreach_widget_load_mixer(struct snd_soc_component *component,
820
int index, struct snd_soc_dapm_widget *w,
821
struct snd_soc_tplg_dapm_widget *tplg_w)
822
{
823
struct snd_soc_tplg_vendor_value_elem *w_elem;
824
struct snd_soc_tplg_vendor_array *w_array;
825
struct snd_ar_control *scontrol;
826
struct q6apm *data = dev_get_drvdata(component->dev);
827
struct snd_soc_dobj *dobj;
828
int tkn_count = 0;
829
830
w_array = &tplg_w->priv.array[0];
831
832
scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL);
833
if (!scontrol)
834
return -ENOMEM;
835
836
scontrol->scomp = component;
837
dobj = &w->dobj;
838
dobj->private = scontrol;
839
840
w_elem = w_array->value;
841
while (tkn_count <= (le32_to_cpu(w_array->num_elems) - 1)) {
842
switch (le32_to_cpu(w_elem->token)) {
843
case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID:
844
scontrol->sgid = le32_to_cpu(w_elem->value);
845
break;
846
case AR_TKN_DAI_INDEX:
847
scontrol->graph_id = le32_to_cpu(w_elem->value);
848
break;
849
default: /* ignore other tokens */
850
break;
851
}
852
tkn_count++;
853
w_elem++;
854
}
855
856
scontrol->w = w;
857
list_add_tail(&scontrol->node, &data->widget_list);
858
859
return 0;
860
}
861
862
static int audioreach_pga_event(struct snd_soc_dapm_widget *w,
863
struct snd_kcontrol *kcontrol, int event)
864
865
{
866
struct snd_soc_dapm_context *dapm = w->dapm;
867
struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
868
struct audioreach_module *mod = w->dobj.private;
869
struct q6apm *apm = dev_get_drvdata(c->dev);
870
871
switch (event) {
872
case SND_SOC_DAPM_POST_PMU:
873
/* apply gain after power up of widget */
874
audioreach_gain_set_vol_ctrl(apm, mod, mod->gain);
875
break;
876
default:
877
break;
878
}
879
880
return 0;
881
}
882
883
static const struct snd_soc_tplg_widget_events audioreach_widget_ops[] = {
884
{ AR_PGA_DAPM_EVENT, audioreach_pga_event },
885
};
886
887
static int audioreach_widget_load_pga(struct snd_soc_component *component,
888
int index, struct snd_soc_dapm_widget *w,
889
struct snd_soc_tplg_dapm_widget *tplg_w)
890
{
891
struct audioreach_module *mod;
892
struct snd_soc_dobj *dobj;
893
int ret;
894
895
ret = audioreach_widget_load_module_common(component, index, w, tplg_w);
896
if (ret)
897
return ret;
898
899
dobj = &w->dobj;
900
mod = dobj->private;
901
mod->gain = VOL_CTRL_DEFAULT_GAIN;
902
903
ret = snd_soc_tplg_widget_bind_event(w, audioreach_widget_ops,
904
ARRAY_SIZE(audioreach_widget_ops),
905
le16_to_cpu(tplg_w->event_type));
906
if (ret) {
907
dev_err(component->dev, "matching event handlers NOT found for %d\n",
908
le16_to_cpu(tplg_w->event_type));
909
return -EINVAL;
910
}
911
912
return 0;
913
}
914
915
static int audioreach_widget_ready(struct snd_soc_component *component,
916
int index, struct snd_soc_dapm_widget *w,
917
struct snd_soc_tplg_dapm_widget *tplg_w)
918
{
919
switch (w->id) {
920
case snd_soc_dapm_aif_in:
921
case snd_soc_dapm_aif_out:
922
audioreach_widget_load_buffer(component, index, w, tplg_w);
923
break;
924
case snd_soc_dapm_decoder:
925
case snd_soc_dapm_encoder:
926
case snd_soc_dapm_src:
927
audioreach_widget_load_enc_dec_cnv(component, index, w, tplg_w);
928
break;
929
case snd_soc_dapm_buffer:
930
audioreach_widget_load_buffer(component, index, w, tplg_w);
931
break;
932
case snd_soc_dapm_mixer:
933
return audioreach_widget_load_mixer(component, index, w, tplg_w);
934
case snd_soc_dapm_pga:
935
return audioreach_widget_load_pga(component, index, w, tplg_w);
936
case snd_soc_dapm_dai_link:
937
case snd_soc_dapm_scheduler:
938
case snd_soc_dapm_out_drv:
939
default:
940
dev_err(component->dev, "Widget type (0x%x) not yet supported\n", w->id);
941
break;
942
}
943
944
return 0;
945
}
946
947
static int audioreach_widget_unload(struct snd_soc_component *scomp,
948
struct snd_soc_dobj *dobj)
949
{
950
struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj);
951
struct q6apm *apm = dev_get_drvdata(scomp->dev);
952
struct audioreach_container *cont;
953
struct audioreach_module *mod;
954
955
mod = dobj->private;
956
cont = mod->container;
957
958
if (w->id == snd_soc_dapm_mixer) {
959
/* virtual widget */
960
struct snd_ar_control *scontrol = dobj->private;
961
962
list_del(&scontrol->node);
963
kfree(scontrol);
964
return 0;
965
}
966
967
mutex_lock(&apm->lock);
968
idr_remove(&apm->modules_idr, mod->instance_id);
969
cont->num_modules--;
970
971
list_del(&mod->node);
972
kfree(mod->data);
973
kfree(mod);
974
/* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */
975
if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */
976
struct audioreach_sub_graph *sg = cont->sub_graph;
977
978
idr_remove(&apm->containers_idr, cont->container_id);
979
list_del(&cont->node);
980
sg->num_containers--;
981
kfree(cont);
982
/* check if there are no more containers in the sub graph and remove it */
983
if (list_empty(&sg->container_list)) {
984
struct audioreach_graph_info *info = sg->info;
985
986
idr_remove(&apm->sub_graphs_idr, sg->sub_graph_id);
987
list_del(&sg->node);
988
info->num_sub_graphs--;
989
kfree(sg);
990
/* Check if there are no more sub-graphs left then remove graph info */
991
if (list_empty(&info->sg_list)) {
992
idr_remove(&apm->graph_info_idr, info->id);
993
kfree(info);
994
}
995
}
996
}
997
998
mutex_unlock(&apm->lock);
999
1000
return 0;
1001
}
1002
1003
static struct snd_ar_control *audioreach_find_widget(struct snd_soc_component *comp,
1004
const char *name)
1005
{
1006
struct q6apm *apm = dev_get_drvdata(comp->dev);
1007
struct snd_ar_control *control;
1008
1009
list_for_each_entry(control, &apm->widget_list, node) {
1010
if (control->w && !strcmp(name, control->w->name))
1011
return control;
1012
}
1013
1014
return NULL;
1015
}
1016
1017
static struct audioreach_module *audioreach_find_module(struct snd_soc_component *comp,
1018
const char *name)
1019
{
1020
struct q6apm *apm = dev_get_drvdata(comp->dev);
1021
struct audioreach_module *module;
1022
int id;
1023
1024
idr_for_each_entry(&apm->modules_idr, module, id) {
1025
if (!strcmp(name, module->widget->name))
1026
return module;
1027
}
1028
1029
return NULL;
1030
}
1031
1032
static int audioreach_route_load(struct snd_soc_component *scomp, int index,
1033
struct snd_soc_dapm_route *route)
1034
{
1035
struct audioreach_module *src_module, *sink_module;
1036
struct snd_ar_control *control;
1037
struct snd_soc_dapm_widget *w;
1038
int i;
1039
1040
/* check if these are actual modules */
1041
src_module = audioreach_find_module(scomp, route->source);
1042
sink_module = audioreach_find_module(scomp, route->sink);
1043
1044
if (sink_module && !src_module) {
1045
control = audioreach_find_widget(scomp, route->source);
1046
if (control)
1047
control->module_instance_id = sink_module->instance_id;
1048
1049
} else if (!sink_module && src_module && route->control) {
1050
/* check if this is a virtual mixer */
1051
control = audioreach_find_widget(scomp, route->sink);
1052
if (!control || !control->w)
1053
return 0;
1054
1055
w = control->w;
1056
1057
for (i = 0; i < w->num_kcontrols; i++) {
1058
if (!strcmp(route->control, w->kcontrol_news[i].name)) {
1059
struct soc_mixer_control *sm;
1060
struct snd_soc_dobj *dobj;
1061
struct snd_ar_control *scontrol;
1062
1063
sm = (struct soc_mixer_control *)w->kcontrol_news[i].private_value;
1064
dobj = &sm->dobj;
1065
scontrol = dobj->private;
1066
scontrol->module_instance_id = src_module->instance_id;
1067
}
1068
}
1069
1070
}
1071
1072
return 0;
1073
}
1074
1075
static int audioreach_route_unload(struct snd_soc_component *scomp,
1076
struct snd_soc_dobj *dobj)
1077
{
1078
return 0;
1079
}
1080
1081
static int audioreach_tplg_complete(struct snd_soc_component *component)
1082
{
1083
/* TBD */
1084
return 0;
1085
}
1086
1087
/* DAI link - used for any driver specific init */
1088
static int audioreach_link_load(struct snd_soc_component *component, int index,
1089
struct snd_soc_dai_link *link,
1090
struct snd_soc_tplg_link_config *cfg)
1091
{
1092
link->nonatomic = true;
1093
link->dynamic = true;
1094
link->platforms->name = NULL;
1095
link->platforms->of_node = of_get_compatible_child(component->dev->of_node,
1096
"qcom,q6apm-dais");
1097
return 0;
1098
}
1099
1100
static void audioreach_connect_sub_graphs(struct q6apm *apm,
1101
struct snd_ar_control *m1,
1102
struct snd_ar_control *m2,
1103
bool connect)
1104
{
1105
struct audioreach_graph_info *info;
1106
1107
mutex_lock(&apm->lock);
1108
info = idr_find(&apm->graph_info_idr, m2->graph_id);
1109
mutex_unlock(&apm->lock);
1110
1111
if (connect) {
1112
info->src_mod_inst_id = m1->module_instance_id;
1113
info->src_mod_op_port_id = 1;
1114
info->dst_mod_inst_id = m2->module_instance_id;
1115
info->dst_mod_ip_port_id = 2;
1116
1117
} else {
1118
info->src_mod_inst_id = 0;
1119
info->src_mod_op_port_id = 0;
1120
info->dst_mod_inst_id = 0;
1121
info->dst_mod_ip_port_id = 0;
1122
}
1123
}
1124
1125
static bool audioreach_is_vmixer_connected(struct q6apm *apm,
1126
struct snd_ar_control *m1,
1127
struct snd_ar_control *m2)
1128
{
1129
struct audioreach_graph_info *info;
1130
1131
mutex_lock(&apm->lock);
1132
info = idr_find(&apm->graph_info_idr, m2->graph_id);
1133
mutex_unlock(&apm->lock);
1134
1135
if (info->dst_mod_inst_id == m2->module_instance_id &&
1136
info->src_mod_inst_id == m1->module_instance_id)
1137
return true;
1138
1139
return false;
1140
}
1141
1142
static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol,
1143
struct snd_ctl_elem_value *ucontrol)
1144
{
1145
struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
1146
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
1147
struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol);
1148
struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
1149
struct snd_ar_control *dapm_scontrol = dw->dobj.private;
1150
struct snd_ar_control *scontrol = mc->dobj.private;
1151
struct q6apm *data = dev_get_drvdata(c->dev);
1152
bool connected;
1153
1154
connected = audioreach_is_vmixer_connected(data, scontrol, dapm_scontrol);
1155
if (connected)
1156
ucontrol->value.integer.value[0] = 1;
1157
else
1158
ucontrol->value.integer.value[0] = 0;
1159
1160
return 0;
1161
}
1162
1163
static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol,
1164
struct snd_ctl_elem_value *ucontrol)
1165
{
1166
struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
1167
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
1168
struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol);
1169
struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
1170
struct snd_ar_control *dapm_scontrol = dw->dobj.private;
1171
struct snd_ar_control *scontrol = mc->dobj.private;
1172
struct q6apm *data = dev_get_drvdata(c->dev);
1173
1174
if (ucontrol->value.integer.value[0]) {
1175
audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, true);
1176
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, NULL);
1177
} else {
1178
audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, false);
1179
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, NULL);
1180
}
1181
return 0;
1182
}
1183
1184
static int audioreach_get_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol,
1185
struct snd_ctl_elem_value *ucontrol)
1186
{
1187
struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol);
1188
struct audioreach_module *mod = dw->dobj.private;
1189
1190
ucontrol->value.integer.value[0] = mod->gain;
1191
1192
return 0;
1193
}
1194
1195
static int audioreach_put_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol,
1196
struct snd_ctl_elem_value *ucontrol)
1197
{
1198
struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol);
1199
struct audioreach_module *mod = dw->dobj.private;
1200
1201
mod->gain = ucontrol->value.integer.value[0];
1202
1203
return 1;
1204
}
1205
1206
static int audioreach_control_load_mix(struct snd_soc_component *scomp,
1207
struct snd_ar_control *scontrol,
1208
struct snd_kcontrol_new *kc,
1209
struct snd_soc_tplg_ctl_hdr *hdr)
1210
{
1211
struct snd_soc_tplg_vendor_value_elem *c_elem;
1212
struct snd_soc_tplg_vendor_array *c_array;
1213
struct snd_soc_tplg_mixer_control *mc;
1214
int tkn_count = 0;
1215
1216
mc = container_of(hdr, struct snd_soc_tplg_mixer_control, hdr);
1217
c_array = (struct snd_soc_tplg_vendor_array *)mc->priv.data;
1218
1219
c_elem = c_array->value;
1220
1221
while (tkn_count <= (le32_to_cpu(c_array->num_elems) - 1)) {
1222
switch (le32_to_cpu(c_elem->token)) {
1223
case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID:
1224
scontrol->sgid = le32_to_cpu(c_elem->value);
1225
break;
1226
case AR_TKN_DAI_INDEX:
1227
scontrol->graph_id = le32_to_cpu(c_elem->value);
1228
break;
1229
default:
1230
/* Ignore other tokens */
1231
break;
1232
}
1233
c_elem++;
1234
tkn_count++;
1235
}
1236
1237
return 0;
1238
}
1239
1240
static int audioreach_control_load(struct snd_soc_component *scomp, int index,
1241
struct snd_kcontrol_new *kc,
1242
struct snd_soc_tplg_ctl_hdr *hdr)
1243
{
1244
struct snd_ar_control *scontrol;
1245
struct soc_mixer_control *sm;
1246
struct snd_soc_dobj *dobj;
1247
int ret = 0;
1248
1249
scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL);
1250
if (!scontrol)
1251
return -ENOMEM;
1252
1253
scontrol->scomp = scomp;
1254
1255
switch (le32_to_cpu(hdr->ops.get)) {
1256
case SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX:
1257
sm = (struct soc_mixer_control *)kc->private_value;
1258
dobj = &sm->dobj;
1259
ret = audioreach_control_load_mix(scomp, scontrol, kc, hdr);
1260
break;
1261
case SND_SOC_AR_TPLG_VOL_CTL:
1262
sm = (struct soc_mixer_control *)kc->private_value;
1263
dobj = &sm->dobj;
1264
break;
1265
default:
1266
dev_warn(scomp->dev, "control type not supported %d:%d:%d\n",
1267
hdr->ops.get, hdr->ops.put, hdr->ops.info);
1268
kfree(scontrol);
1269
return -EINVAL;
1270
}
1271
1272
dobj->private = scontrol;
1273
return ret;
1274
}
1275
1276
static int audioreach_control_unload(struct snd_soc_component *scomp,
1277
struct snd_soc_dobj *dobj)
1278
{
1279
struct snd_ar_control *scontrol = dobj->private;
1280
1281
kfree(scontrol);
1282
1283
return 0;
1284
}
1285
1286
static const struct snd_soc_tplg_kcontrol_ops audioreach_io_ops[] = {
1287
{SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX, audioreach_get_audio_mixer,
1288
audioreach_put_audio_mixer, snd_soc_info_volsw},
1289
{SND_SOC_AR_TPLG_VOL_CTL, audioreach_get_vol_ctrl_audio_mixer,
1290
audioreach_put_vol_ctrl_audio_mixer, snd_soc_info_volsw},
1291
};
1292
1293
static const struct snd_soc_tplg_ops audioreach_tplg_ops = {
1294
.io_ops = audioreach_io_ops,
1295
.io_ops_count = ARRAY_SIZE(audioreach_io_ops),
1296
1297
.control_load = audioreach_control_load,
1298
.control_unload = audioreach_control_unload,
1299
1300
.widget_ready = audioreach_widget_ready,
1301
.widget_unload = audioreach_widget_unload,
1302
1303
.complete = audioreach_tplg_complete,
1304
.link_load = audioreach_link_load,
1305
1306
.dapm_route_load = audioreach_route_load,
1307
.dapm_route_unload = audioreach_route_unload,
1308
};
1309
1310
int audioreach_tplg_init(struct snd_soc_component *component)
1311
{
1312
struct snd_soc_card *card = component->card;
1313
struct device *dev = component->dev;
1314
const struct firmware *fw;
1315
int ret;
1316
1317
/* Inline with Qualcomm UCM configs and linux-firmware path */
1318
char *tplg_fw_name __free(kfree) = kasprintf(GFP_KERNEL, "qcom/%s/%s-tplg.bin",
1319
card->driver_name,
1320
card->name);
1321
if (!tplg_fw_name)
1322
return -ENOMEM;
1323
1324
ret = request_firmware(&fw, tplg_fw_name, dev);
1325
if (ret < 0) {
1326
dev_err(dev, "tplg firmware loading %s failed %d\n", tplg_fw_name, ret);
1327
return ret;
1328
}
1329
1330
ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw);
1331
if (ret < 0) {
1332
if (ret != -EPROBE_DEFER)
1333
dev_err(dev, "tplg component load failed: %d\n", ret);
1334
}
1335
1336
release_firmware(fw);
1337
1338
return ret;
1339
}
1340
EXPORT_SYMBOL_GPL(audioreach_tplg_init);
1341
1342