xref: /linux/sound/soc/qcom/qdsp6/topology.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
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_obj(*info);
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_obj(*sg);
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_obj(*cont);
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_obj(*mod);
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 const struct snd_soc_tplg_vendor_array *
210 audioreach_get_sg_array(const struct snd_soc_tplg_private *private)
211 {
212 	const 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 		const 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 const struct snd_soc_tplg_vendor_array *
243 audioreach_get_cont_array(const struct snd_soc_tplg_private *private)
244 {
245 	const 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 		const 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 const struct snd_soc_tplg_vendor_array *
276 audioreach_get_module_array(const struct snd_soc_tplg_private *private)
277 {
278 	const 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 		const 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 *
309 audioreach_get_module_priv_data(const struct snd_soc_tplg_private *private)
310 {
311 	int sz;
312 
313 	for (sz = 0; sz < le32_to_cpu(private->size); ) {
314 		const 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_flex(*pdata, data,
321 					     le32_to_cpu(mod_array->size));
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 							       const struct snd_soc_tplg_private *private)
338 {
339 	const struct snd_soc_tplg_vendor_value_elem *sg_elem;
340 	const 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 							 const struct snd_soc_tplg_private *private)
396 {
397 	const struct snd_soc_tplg_vendor_value_elem *cont_elem;
398 	const 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 							const 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 	const struct snd_soc_tplg_vendor_value_elem *mod_elem;
451 	const 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 						const 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 					      const struct snd_soc_tplg_dapm_widget *tplg_w)
624 {
625 	const struct snd_soc_tplg_vendor_value_elem *mod_elem;
626 	const 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 					     const struct snd_soc_tplg_vendor_array *mod_array)
664 {
665 	const 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 					     const struct snd_soc_tplg_vendor_array *mod_array)
694 {
695 	const 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 					     const struct snd_soc_tplg_vendor_array *mod_array)
723 {
724 	const 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 					    const struct snd_soc_tplg_vendor_array *mod_array)
758 {
759 	const 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 					 const struct snd_soc_tplg_dapm_widget *tplg_w)
782 {
783 	const 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 					const struct snd_soc_tplg_dapm_widget *tplg_w)
822 {
823 	const struct snd_soc_tplg_vendor_value_elem *w_elem;
824 	const 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_obj(*scontrol);
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 				      const 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 	const 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 	if (w->id == snd_soc_dapm_mixer) {
956 		/* virtual widget */
957 		struct snd_ar_control *scontrol = dobj->private;
958 
959 		list_del(&scontrol->node);
960 		kfree(scontrol);
961 		return 0;
962 	}
963 	mod = dobj->private;
964 	if (!mod)
965 		return 0;
966 
967 	cont = mod->container;
968 
969 	mutex_lock(&apm->lock);
970 	idr_remove(&apm->modules_idr, mod->instance_id);
971 	cont->num_modules--;
972 
973 	list_del(&mod->node);
974 	kfree(mod->data);
975 	kfree(mod);
976 	/* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */
977 	if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */
978 		struct audioreach_sub_graph *sg = cont->sub_graph;
979 
980 		idr_remove(&apm->containers_idr, cont->container_id);
981 		list_del(&cont->node);
982 		sg->num_containers--;
983 		kfree(cont);
984 		/* check if there are no more containers in the sub graph and remove it */
985 		if (list_empty(&sg->container_list)) {
986 			struct audioreach_graph_info *info = sg->info;
987 
988 			idr_remove(&apm->sub_graphs_idr, sg->sub_graph_id);
989 			list_del(&sg->node);
990 			info->num_sub_graphs--;
991 			kfree(sg);
992 			/* Check if there are no more sub-graphs left then remove graph info */
993 			if (list_empty(&info->sg_list)) {
994 				idr_remove(&apm->graph_info_idr, info->id);
995 				kfree(info);
996 			}
997 		}
998 	}
999 
1000 	mutex_unlock(&apm->lock);
1001 
1002 	return 0;
1003 }
1004 
1005 static struct snd_ar_control *audioreach_find_widget(struct snd_soc_component *comp,
1006 						     const char *name)
1007 {
1008 	struct q6apm *apm = dev_get_drvdata(comp->dev);
1009 	struct snd_ar_control *control;
1010 
1011 	list_for_each_entry(control, &apm->widget_list, node) {
1012 		if (control->w && !strcmp(name, control->w->name))
1013 			return control;
1014 	}
1015 
1016 	return NULL;
1017 }
1018 
1019 static struct audioreach_module *audioreach_find_module(struct snd_soc_component *comp,
1020 							const char *name)
1021 {
1022 	struct q6apm *apm = dev_get_drvdata(comp->dev);
1023 	struct audioreach_module *module;
1024 	int id;
1025 
1026 	idr_for_each_entry(&apm->modules_idr, module, id) {
1027 		if (!strcmp(name, module->widget->name))
1028 			return module;
1029 	}
1030 
1031 	return NULL;
1032 }
1033 
1034 static int audioreach_route_load(struct snd_soc_component *scomp, int index,
1035 				 struct snd_soc_dapm_route *route)
1036 {
1037 	const struct audioreach_module *src_module, *sink_module;
1038 	struct snd_ar_control *control;
1039 	struct snd_soc_dapm_widget *w;
1040 	int i;
1041 
1042 	/* check if these are actual modules */
1043 	src_module = audioreach_find_module(scomp, route->source);
1044 	sink_module = audioreach_find_module(scomp, route->sink);
1045 
1046 	if (sink_module && !src_module) {
1047 		control = audioreach_find_widget(scomp, route->source);
1048 		if (control)
1049 			control->module_instance_id = sink_module->instance_id;
1050 
1051 	} else if (!sink_module && src_module && route->control) {
1052 		/* check if this is a virtual mixer */
1053 		control = audioreach_find_widget(scomp, route->sink);
1054 		if (!control || !control->w)
1055 			return 0;
1056 
1057 		w = control->w;
1058 
1059 		for (i = 0; i < w->num_kcontrols; i++) {
1060 			if (!strcmp(route->control, w->kcontrol_news[i].name)) {
1061 				struct soc_mixer_control *sm;
1062 				struct snd_soc_dobj *dobj;
1063 				struct snd_ar_control *scontrol;
1064 
1065 				sm = (struct soc_mixer_control *)w->kcontrol_news[i].private_value;
1066 				dobj = &sm->dobj;
1067 				scontrol = dobj->private;
1068 				scontrol->module_instance_id = src_module->instance_id;
1069 			}
1070 		}
1071 
1072 	}
1073 
1074 	return 0;
1075 }
1076 
1077 static int audioreach_route_unload(struct snd_soc_component *scomp,
1078 				   struct snd_soc_dobj *dobj)
1079 {
1080 	return 0;
1081 }
1082 
1083 static int audioreach_tplg_complete(struct snd_soc_component *component)
1084 {
1085 	/* TBD */
1086 	return 0;
1087 }
1088 
1089 /* DAI link - used for any driver specific init */
1090 static int audioreach_link_load(struct snd_soc_component *component, int index,
1091 				struct snd_soc_dai_link *link,
1092 				struct snd_soc_tplg_link_config *cfg)
1093 {
1094 	link->nonatomic = true;
1095 	link->dynamic = true;
1096 	link->platforms->name = NULL;
1097 	link->platforms->of_node = of_get_compatible_child(component->dev->of_node,
1098 							   "qcom,q6apm-dais");
1099 	return 0;
1100 }
1101 
1102 static void audioreach_connect_sub_graphs(struct q6apm *apm,
1103 					  const struct snd_ar_control *m1,
1104 					  const struct snd_ar_control *m2,
1105 					  bool connect)
1106 {
1107 	struct audioreach_graph_info *info;
1108 
1109 	mutex_lock(&apm->lock);
1110 	info = idr_find(&apm->graph_info_idr, m2->graph_id);
1111 	mutex_unlock(&apm->lock);
1112 
1113 	if (connect) {
1114 		info->src_mod_inst_id = m1->module_instance_id;
1115 		info->src_mod_op_port_id = 1;
1116 		info->dst_mod_inst_id = m2->module_instance_id;
1117 		info->dst_mod_ip_port_id = 2;
1118 
1119 	} else {
1120 		info->src_mod_inst_id = 0;
1121 		info->src_mod_op_port_id = 0;
1122 		info->dst_mod_inst_id = 0;
1123 		info->dst_mod_ip_port_id = 0;
1124 	}
1125 }
1126 
1127 static bool audioreach_is_vmixer_connected(struct q6apm *apm,
1128 					   const struct snd_ar_control *m1,
1129 					   const struct snd_ar_control *m2)
1130 {
1131 	const struct audioreach_graph_info *info;
1132 
1133 	mutex_lock(&apm->lock);
1134 	info = idr_find(&apm->graph_info_idr, m2->graph_id);
1135 	mutex_unlock(&apm->lock);
1136 
1137 	if (info->dst_mod_inst_id == m2->module_instance_id &&
1138 	    info->src_mod_inst_id == m1->module_instance_id)
1139 		return true;
1140 
1141 	return false;
1142 }
1143 
1144 static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol,
1145 				      struct snd_ctl_elem_value *ucontrol)
1146 {
1147 	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
1148 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
1149 	const struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol);
1150 	struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
1151 	const struct snd_ar_control *dapm_scontrol = dw->dobj.private;
1152 	const struct snd_ar_control *scontrol = mc->dobj.private;
1153 	struct q6apm *data = dev_get_drvdata(c->dev);
1154 	bool connected;
1155 
1156 	connected = audioreach_is_vmixer_connected(data, scontrol, dapm_scontrol);
1157 	if (connected)
1158 		ucontrol->value.integer.value[0] = 1;
1159 	else
1160 		ucontrol->value.integer.value[0] = 0;
1161 
1162 	return 0;
1163 }
1164 
1165 static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol,
1166 				      struct snd_ctl_elem_value *ucontrol)
1167 {
1168 	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
1169 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
1170 	struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol);
1171 	struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
1172 	const struct snd_ar_control *dapm_scontrol = dw->dobj.private;
1173 	const struct snd_ar_control *scontrol = mc->dobj.private;
1174 	struct q6apm *data = dev_get_drvdata(c->dev);
1175 
1176 	if (ucontrol->value.integer.value[0]) {
1177 		audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, true);
1178 		snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, NULL);
1179 	} else {
1180 		audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, false);
1181 		snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, NULL);
1182 	}
1183 	return 0;
1184 }
1185 
1186 static int audioreach_get_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol,
1187 					       struct snd_ctl_elem_value *ucontrol)
1188 {
1189 	struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol);
1190 	struct audioreach_module *mod = dw->dobj.private;
1191 
1192 	ucontrol->value.integer.value[0] = mod->gain;
1193 
1194 	return 0;
1195 }
1196 
1197 static int audioreach_put_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol,
1198 					       struct snd_ctl_elem_value *ucontrol)
1199 {
1200 	struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol);
1201 	struct audioreach_module *mod = dw->dobj.private;
1202 
1203 	mod->gain = ucontrol->value.integer.value[0];
1204 
1205 	return 1;
1206 }
1207 
1208 static int audioreach_control_load_mix(struct snd_soc_component *scomp,
1209 				       struct snd_ar_control *scontrol,
1210 				       struct snd_kcontrol_new *kc,
1211 				       const struct snd_soc_tplg_ctl_hdr *hdr)
1212 {
1213 	const struct snd_soc_tplg_vendor_value_elem *c_elem;
1214 	const struct snd_soc_tplg_vendor_array *c_array;
1215 	const struct snd_soc_tplg_mixer_control *mc;
1216 	int tkn_count = 0;
1217 
1218 	mc = container_of_const(hdr, struct snd_soc_tplg_mixer_control, hdr);
1219 	c_array = (struct snd_soc_tplg_vendor_array *)mc->priv.data;
1220 
1221 	c_elem = c_array->value;
1222 
1223 	while (tkn_count <= (le32_to_cpu(c_array->num_elems) - 1)) {
1224 		switch (le32_to_cpu(c_elem->token)) {
1225 		case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID:
1226 			scontrol->sgid = le32_to_cpu(c_elem->value);
1227 			break;
1228 		case AR_TKN_DAI_INDEX:
1229 			scontrol->graph_id = le32_to_cpu(c_elem->value);
1230 			break;
1231 		default:
1232 			/* Ignore other tokens */
1233 			break;
1234 		}
1235 		c_elem++;
1236 		tkn_count++;
1237 	}
1238 
1239 	return 0;
1240 }
1241 
1242 static int audioreach_control_load(struct snd_soc_component *scomp, int index,
1243 				   struct snd_kcontrol_new *kc,
1244 				   struct snd_soc_tplg_ctl_hdr *hdr)
1245 {
1246 	struct snd_ar_control *scontrol;
1247 	struct soc_mixer_control *sm;
1248 	struct snd_soc_dobj *dobj;
1249 	int ret = 0;
1250 
1251 	scontrol = kzalloc_obj(*scontrol);
1252 	if (!scontrol)
1253 		return -ENOMEM;
1254 
1255 	scontrol->scomp = scomp;
1256 
1257 	switch (le32_to_cpu(hdr->ops.get)) {
1258 	case SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX:
1259 		sm = (struct soc_mixer_control *)kc->private_value;
1260 		dobj = &sm->dobj;
1261 		ret = audioreach_control_load_mix(scomp, scontrol, kc, hdr);
1262 		break;
1263 	case SND_SOC_AR_TPLG_VOL_CTL:
1264 		sm = (struct soc_mixer_control *)kc->private_value;
1265 		dobj = &sm->dobj;
1266 		break;
1267 	default:
1268 		dev_warn(scomp->dev, "control type not supported %d:%d:%d\n",
1269 			 hdr->ops.get, hdr->ops.put, hdr->ops.info);
1270 		kfree(scontrol);
1271 		return -EINVAL;
1272 	}
1273 
1274 	dobj->private = scontrol;
1275 	return ret;
1276 }
1277 
1278 static int audioreach_control_unload(struct snd_soc_component *scomp,
1279 				     struct snd_soc_dobj *dobj)
1280 {
1281 	struct snd_ar_control *scontrol = dobj->private;
1282 
1283 	kfree(scontrol);
1284 
1285 	return 0;
1286 }
1287 
1288 static const struct snd_soc_tplg_kcontrol_ops audioreach_io_ops[] = {
1289 	{SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX, audioreach_get_audio_mixer,
1290 		audioreach_put_audio_mixer, snd_soc_info_volsw},
1291 	{SND_SOC_AR_TPLG_VOL_CTL, audioreach_get_vol_ctrl_audio_mixer,
1292 		audioreach_put_vol_ctrl_audio_mixer, snd_soc_info_volsw},
1293 };
1294 
1295 static const struct snd_soc_tplg_ops audioreach_tplg_ops = {
1296 	.io_ops = audioreach_io_ops,
1297 	.io_ops_count = ARRAY_SIZE(audioreach_io_ops),
1298 
1299 	.control_load	= audioreach_control_load,
1300 	.control_unload	= audioreach_control_unload,
1301 
1302 	.widget_ready = audioreach_widget_ready,
1303 	.widget_unload = audioreach_widget_unload,
1304 
1305 	.complete = audioreach_tplg_complete,
1306 	.link_load = audioreach_link_load,
1307 
1308 	.dapm_route_load	= audioreach_route_load,
1309 	.dapm_route_unload	= audioreach_route_unload,
1310 };
1311 
1312 int audioreach_tplg_init(struct snd_soc_component *component)
1313 {
1314 	struct snd_soc_card *card = component->card;
1315 	struct device *dev = component->dev;
1316 	const struct firmware *fw;
1317 	int ret;
1318 
1319 	/* Inline with Qualcomm UCM configs and linux-firmware path */
1320 	char *tplg_fw_name __free(kfree) = kasprintf(GFP_KERNEL, "qcom/%s/%s-tplg.bin",
1321 						     card->driver_name,
1322 						     card->name);
1323 	if (!tplg_fw_name)
1324 		return -ENOMEM;
1325 
1326 	ret = request_firmware(&fw, tplg_fw_name, dev);
1327 	if (ret < 0) {
1328 		dev_err(dev, "tplg firmware loading %s failed %d\n", tplg_fw_name, ret);
1329 		return ret;
1330 	}
1331 
1332 	ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw);
1333 	if (ret < 0) {
1334 		if (ret != -EPROBE_DEFER)
1335 			dev_err(dev, "tplg component load failed: %d\n", ret);
1336 	}
1337 
1338 	release_firmware(fw);
1339 
1340 	return ret;
1341 }
1342 EXPORT_SYMBOL_GPL(audioreach_tplg_init);
1343