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