xref: /linux/sound/soc/qcom/qdsp6/topology.c (revision 05a54fa773284d1a7923cdfdd8f0c8dabb98bd26)
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