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