xref: /linux/sound/soc/qcom/qdsp6/topology.c (revision e5c91aac491def6ab3f90c4cc246e3fcb0f8f058)
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_audio_if_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 	u32 val;
762 
763 	mod_elem = mod_array->value;
764 
765 	while (tkn_count < le32_to_cpu(mod_array->num_elems)) {
766 		val = le32_to_cpu(mod_elem->value);
767 		switch (le32_to_cpu(mod_elem->token)) {
768 		case AR_TKN_U32_MODULE_HW_IF_IDX:
769 			mod->hw_interface_idx = val;
770 			break;
771 		case AR_TKN_U32_MODULE_FMT_DATA:
772 			mod->data_format = val;
773 			break;
774 		case AR_TKN_U16_MODULE_SYNC_SRC:
775 			if (val > U16_MAX)
776 				return -EINVAL;
777 			mod->sync_src = (u16)val;
778 			break;
779 		case AR_TKN_U16_MODULE_CTRL_DATA_OUT_ENABLE:
780 			if (val > U16_MAX)
781 				return -EINVAL;
782 			mod->ctrl_data_out_enable = (u16)val;
783 			break;
784 		case AR_TKN_U32_MODULE_SLOT_MASK:
785 			mod->slot_mask = val;
786 			break;
787 		case AR_TKN_U16_MODULE_NSLOTS_PER_FRAME:
788 			if (val > U16_MAX)
789 				return -EINVAL;
790 			mod->nslots_per_frame = (u16)val;
791 			break;
792 		case AR_TKN_U16_MODULE_SLOT_WIDTH:
793 			if (val > U16_MAX)
794 				return -EINVAL;
795 			mod->slot_width = (u16)val;
796 			break;
797 		case AR_TKN_U16_MODULE_INTF_MODE:
798 			if (val > U16_MAX)
799 				return -EINVAL;
800 			mod->intf_mode = (u16)val;
801 			break;
802 		case AR_TKN_U16_MODULE_SYNC_MODE:
803 			if (val > U16_MAX)
804 				return -EINVAL;
805 			mod->sync_mode = (u16)val;
806 			break;
807 		case AR_TKN_U16_MODULE_CTRL_INVERT_SYNC_PULSE:
808 			if (val > U16_MAX)
809 				return -EINVAL;
810 			mod->ctrl_invert_sync_pulse = (u16)val;
811 			break;
812 		case AR_TKN_U16_MODULE_CTRL_SYNC_DATA_DELAY:
813 			if (val > U16_MAX)
814 				return -EINVAL;
815 			mod->ctrl_sync_data_delay = (u16)val;
816 			break;
817 		case AR_TKN_U16_MODULE_QAIF_TYPE:
818 			if (val > U16_MAX)
819 				return -EINVAL;
820 			mod->qaif_type = (u16)val;
821 			break;
822 		case AR_TKN_U32_MODULE_ACTIVE_LANE_MASK:
823 			mod->active_lane_mask = val;
824 			break;
825 		case AR_TKN_U32_MODULE_FRAME_SYNC_RATE:
826 			mod->frame_sync_rate = val;
827 			break;
828 		case AR_TKN_U16_MODULE_BIT_CLK_TYPE:
829 			if (val > U16_MAX)
830 				return -EINVAL;
831 			mod->bit_clk_type = (u16)val;
832 			break;
833 		case AR_TKN_U8_MODULE_INV_INT_BIT_CLK:
834 			if (val > U8_MAX)
835 				return -EINVAL;
836 			mod->inv_int_bit_clk = (u8)val;
837 			break;
838 		case AR_TKN_U8_MODULE_INV_EXT_BIT_CLK:
839 			if (val > U8_MAX)
840 				return -EINVAL;
841 			mod->inv_ext_bit_clk = (u8)val;
842 			break;
843 		default:
844 			break;
845 		}
846 		tkn_count++;
847 		mod_elem++;
848 	}
849 
850 	return 0;
851 }
852 
853 static int audioreach_widget_dp_module_load(struct audioreach_module *mod,
854 					    const struct snd_soc_tplg_vendor_array *mod_array)
855 {
856 	const struct snd_soc_tplg_vendor_value_elem *mod_elem;
857 	int tkn_count = 0;
858 
859 	mod_elem = mod_array->value;
860 
861 	while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) {
862 		switch (le32_to_cpu(mod_elem->token)) {
863 		case AR_TKN_U32_MODULE_FMT_DATA:
864 			mod->data_format = le32_to_cpu(mod_elem->value);
865 			break;
866 		default:
867 			break;
868 		}
869 		tkn_count++;
870 		mod_elem++;
871 	}
872 
873 	return 0;
874 }
875 
876 static int audioreach_widget_load_buffer(struct snd_soc_component *component,
877 					 int index, struct snd_soc_dapm_widget *w,
878 					 const struct snd_soc_tplg_dapm_widget *tplg_w)
879 {
880 	const struct snd_soc_tplg_vendor_array *mod_array;
881 	struct audioreach_module *mod;
882 	struct snd_soc_dobj *dobj;
883 	int ret;
884 
885 	ret = audioreach_widget_load_module_common(component, index, w, tplg_w);
886 	if (ret)
887 		return ret;
888 
889 	dobj = &w->dobj;
890 	mod = dobj->private;
891 
892 	mod_array = audioreach_get_module_array(&tplg_w->priv);
893 
894 	switch (mod->module_id) {
895 	case MODULE_ID_CODEC_DMA_SINK:
896 	case MODULE_ID_CODEC_DMA_SOURCE:
897 		audioreach_widget_dma_module_load(mod, mod_array);
898 		break;
899 	case MODULE_ID_DATA_LOGGING:
900 		audioreach_widget_log_module_load(mod, mod_array);
901 		break;
902 	case MODULE_ID_I2S_SINK:
903 	case MODULE_ID_I2S_SOURCE:
904 		audioreach_widget_i2s_module_load(mod, mod_array);
905 		break;
906 	case MODULE_ID_AUDIO_IF_SINK:
907 	case MODULE_ID_AUDIO_IF_SOURCE:
908 		ret = audioreach_widget_audio_if_module_load(mod, mod_array);
909 		if (ret)
910 			return ret;
911 		break;
912 	case MODULE_ID_DISPLAY_PORT_SINK:
913 		audioreach_widget_dp_module_load(mod, mod_array);
914 		break;
915 	default:
916 		return -EINVAL;
917 	}
918 
919 	return 0;
920 }
921 
922 static int audioreach_widget_load_mixer(struct snd_soc_component *component,
923 					int index, struct snd_soc_dapm_widget *w,
924 					const struct snd_soc_tplg_dapm_widget *tplg_w)
925 {
926 	const struct snd_soc_tplg_vendor_value_elem *w_elem;
927 	const struct snd_soc_tplg_vendor_array *w_array;
928 	struct snd_ar_control *scontrol;
929 	struct q6apm *data = dev_get_drvdata(component->dev);
930 	struct snd_soc_dobj *dobj;
931 	int tkn_count = 0;
932 
933 	w_array = &tplg_w->priv.array[0];
934 
935 	scontrol = kzalloc_obj(*scontrol);
936 	if (!scontrol)
937 		return -ENOMEM;
938 
939 	scontrol->scomp = component;
940 	dobj = &w->dobj;
941 	dobj->private = scontrol;
942 
943 	w_elem = w_array->value;
944 	while (tkn_count <= (le32_to_cpu(w_array->num_elems) - 1)) {
945 		switch (le32_to_cpu(w_elem->token)) {
946 		case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID:
947 			scontrol->sgid = le32_to_cpu(w_elem->value);
948 			break;
949 		case AR_TKN_DAI_INDEX:
950 			scontrol->graph_id = le32_to_cpu(w_elem->value);
951 			break;
952 		default: /* ignore other tokens */
953 			break;
954 		}
955 		tkn_count++;
956 		w_elem++;
957 	}
958 
959 	scontrol->w = w;
960 	list_add_tail(&scontrol->node, &data->widget_list);
961 
962 	return 0;
963 }
964 
965 static int audioreach_pga_event(struct snd_soc_dapm_widget *w,
966 				struct snd_kcontrol *kcontrol, int event)
967 
968 {
969 	struct snd_soc_dapm_context *dapm = w->dapm;
970 	struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
971 	struct audioreach_module *mod = w->dobj.private;
972 	struct q6apm *apm = dev_get_drvdata(c->dev);
973 
974 	switch (event) {
975 	case SND_SOC_DAPM_POST_PMU:
976 		/* apply gain after power up of widget */
977 		audioreach_gain_set_vol_ctrl(apm, mod, mod->gain);
978 		break;
979 	default:
980 		break;
981 	}
982 
983 	return 0;
984 }
985 
986 static const struct snd_soc_tplg_widget_events audioreach_widget_ops[] = {
987 	{ AR_PGA_DAPM_EVENT, audioreach_pga_event },
988 };
989 
990 static int audioreach_widget_load_pga(struct snd_soc_component *component,
991 				      int index, struct snd_soc_dapm_widget *w,
992 				      const struct snd_soc_tplg_dapm_widget *tplg_w)
993 {
994 	struct audioreach_module *mod;
995 	struct snd_soc_dobj *dobj;
996 	int ret;
997 
998 	ret = audioreach_widget_load_module_common(component, index, w, tplg_w);
999 	if (ret)
1000 		return ret;
1001 
1002 	dobj = &w->dobj;
1003 	mod = dobj->private;
1004 	mod->gain = VOL_CTRL_DEFAULT_GAIN;
1005 
1006 	ret = snd_soc_tplg_widget_bind_event(w, audioreach_widget_ops,
1007 					     ARRAY_SIZE(audioreach_widget_ops),
1008 					     le16_to_cpu(tplg_w->event_type));
1009 	if (ret) {
1010 		dev_err(component->dev, "matching event handlers NOT found for %d\n",
1011 			le16_to_cpu(tplg_w->event_type));
1012 		return -EINVAL;
1013 	}
1014 
1015 	return 0;
1016 }
1017 
1018 static int audioreach_widget_ready(struct snd_soc_component *component,
1019 				   int index, struct snd_soc_dapm_widget *w,
1020 				   struct snd_soc_tplg_dapm_widget *tplg_w)
1021 {
1022 	switch (w->id) {
1023 	case snd_soc_dapm_aif_in:
1024 	case snd_soc_dapm_aif_out:
1025 		audioreach_widget_load_buffer(component, index, w, tplg_w);
1026 		break;
1027 	case snd_soc_dapm_decoder:
1028 	case snd_soc_dapm_encoder:
1029 	case snd_soc_dapm_src:
1030 		audioreach_widget_load_enc_dec_cnv(component, index, w, tplg_w);
1031 		break;
1032 	case snd_soc_dapm_buffer:
1033 		audioreach_widget_load_buffer(component, index, w, tplg_w);
1034 		break;
1035 	case snd_soc_dapm_mixer:
1036 		return audioreach_widget_load_mixer(component, index, w, tplg_w);
1037 	case snd_soc_dapm_pga:
1038 		return audioreach_widget_load_pga(component, index, w, tplg_w);
1039 	case snd_soc_dapm_dai_link:
1040 	case snd_soc_dapm_scheduler:
1041 	case snd_soc_dapm_out_drv:
1042 	default:
1043 		dev_err(component->dev, "Widget type (0x%x) not yet supported\n", w->id);
1044 		break;
1045 	}
1046 
1047 	return 0;
1048 }
1049 
1050 static int audioreach_widget_unload(struct snd_soc_component *scomp,
1051 				    struct snd_soc_dobj *dobj)
1052 {
1053 	const struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj);
1054 	struct q6apm *apm = dev_get_drvdata(scomp->dev);
1055 	struct audioreach_container *cont;
1056 	struct audioreach_module *mod;
1057 
1058 	if (w->id == snd_soc_dapm_mixer) {
1059 		/* virtual widget */
1060 		struct snd_ar_control *scontrol = dobj->private;
1061 
1062 		list_del(&scontrol->node);
1063 		kfree(scontrol);
1064 		return 0;
1065 	}
1066 	mod = dobj->private;
1067 	if (!mod)
1068 		return 0;
1069 
1070 	cont = mod->container;
1071 
1072 	mutex_lock(&apm->lock);
1073 	idr_remove(&apm->modules_idr, mod->instance_id);
1074 	cont->num_modules--;
1075 
1076 	list_del(&mod->node);
1077 	kfree(mod->data);
1078 	kfree(mod);
1079 	/* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */
1080 	if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */
1081 		struct audioreach_sub_graph *sg = cont->sub_graph;
1082 
1083 		idr_remove(&apm->containers_idr, cont->container_id);
1084 		list_del(&cont->node);
1085 		sg->num_containers--;
1086 		kfree(cont);
1087 		/* check if there are no more containers in the sub graph and remove it */
1088 		if (list_empty(&sg->container_list)) {
1089 			struct audioreach_graph_info *info = sg->info;
1090 
1091 			idr_remove(&apm->sub_graphs_idr, sg->sub_graph_id);
1092 			list_del(&sg->node);
1093 			info->num_sub_graphs--;
1094 			kfree(sg);
1095 			/* Check if there are no more sub-graphs left then remove graph info */
1096 			if (list_empty(&info->sg_list)) {
1097 				idr_remove(&apm->graph_info_idr, info->id);
1098 				kfree(info);
1099 			}
1100 		}
1101 	}
1102 
1103 	mutex_unlock(&apm->lock);
1104 
1105 	return 0;
1106 }
1107 
1108 static struct snd_ar_control *audioreach_find_widget(struct snd_soc_component *comp,
1109 						     const char *name)
1110 {
1111 	struct q6apm *apm = dev_get_drvdata(comp->dev);
1112 	struct snd_ar_control *control;
1113 
1114 	list_for_each_entry(control, &apm->widget_list, node) {
1115 		if (control->w && !strcmp(name, control->w->name))
1116 			return control;
1117 	}
1118 
1119 	return NULL;
1120 }
1121 
1122 static struct audioreach_module *audioreach_find_module(struct snd_soc_component *comp,
1123 							const char *name)
1124 {
1125 	struct q6apm *apm = dev_get_drvdata(comp->dev);
1126 	struct audioreach_module *module;
1127 	int id;
1128 
1129 	idr_for_each_entry(&apm->modules_idr, module, id) {
1130 		if (!strcmp(name, module->widget->name))
1131 			return module;
1132 	}
1133 
1134 	return NULL;
1135 }
1136 
1137 static int audioreach_route_load(struct snd_soc_component *scomp, int index,
1138 				 struct snd_soc_dapm_route *route)
1139 {
1140 	const struct audioreach_module *src_module, *sink_module;
1141 	struct snd_ar_control *control;
1142 	struct snd_soc_dapm_widget *w;
1143 	int i;
1144 
1145 	/* check if these are actual modules */
1146 	src_module = audioreach_find_module(scomp, route->source);
1147 	sink_module = audioreach_find_module(scomp, route->sink);
1148 
1149 	if (sink_module && !src_module) {
1150 		control = audioreach_find_widget(scomp, route->source);
1151 		if (control)
1152 			control->module_instance_id = sink_module->instance_id;
1153 
1154 	} else if (!sink_module && src_module && route->control) {
1155 		/* check if this is a virtual mixer */
1156 		control = audioreach_find_widget(scomp, route->sink);
1157 		if (!control || !control->w)
1158 			return 0;
1159 
1160 		w = control->w;
1161 
1162 		for (i = 0; i < w->num_kcontrols; i++) {
1163 			if (!strcmp(route->control, w->kcontrol_news[i].name)) {
1164 				struct soc_mixer_control *sm;
1165 				struct snd_soc_dobj *dobj;
1166 				struct snd_ar_control *scontrol;
1167 
1168 				sm = (struct soc_mixer_control *)w->kcontrol_news[i].private_value;
1169 				dobj = &sm->dobj;
1170 				scontrol = dobj->private;
1171 				scontrol->module_instance_id = src_module->instance_id;
1172 			}
1173 		}
1174 
1175 	}
1176 
1177 	return 0;
1178 }
1179 
1180 static int audioreach_route_unload(struct snd_soc_component *scomp,
1181 				   struct snd_soc_dobj *dobj)
1182 {
1183 	return 0;
1184 }
1185 
1186 static int audioreach_tplg_complete(struct snd_soc_component *component)
1187 {
1188 	/* TBD */
1189 	return 0;
1190 }
1191 
1192 /* DAI link - used for any driver specific init */
1193 static int audioreach_link_load(struct snd_soc_component *component, int index,
1194 				struct snd_soc_dai_link *link,
1195 				struct snd_soc_tplg_link_config *cfg)
1196 {
1197 	link->nonatomic = true;
1198 	link->dynamic = true;
1199 	link->platforms->name = NULL;
1200 	link->platforms->of_node = of_get_compatible_child(component->dev->of_node,
1201 							   "qcom,q6apm-dais");
1202 	return 0;
1203 }
1204 
1205 static void audioreach_connect_sub_graphs(struct q6apm *apm,
1206 					  const struct snd_ar_control *m1,
1207 					  const struct snd_ar_control *m2,
1208 					  bool connect)
1209 {
1210 	struct audioreach_graph_info *info;
1211 
1212 	mutex_lock(&apm->lock);
1213 	info = idr_find(&apm->graph_info_idr, m2->graph_id);
1214 	mutex_unlock(&apm->lock);
1215 
1216 	if (connect) {
1217 		info->src_mod_inst_id = m1->module_instance_id;
1218 		info->src_mod_op_port_id = 1;
1219 		info->dst_mod_inst_id = m2->module_instance_id;
1220 		info->dst_mod_ip_port_id = 2;
1221 
1222 	} else {
1223 		info->src_mod_inst_id = 0;
1224 		info->src_mod_op_port_id = 0;
1225 		info->dst_mod_inst_id = 0;
1226 		info->dst_mod_ip_port_id = 0;
1227 	}
1228 }
1229 
1230 static bool audioreach_is_vmixer_connected(struct q6apm *apm,
1231 					   const struct snd_ar_control *m1,
1232 					   const struct snd_ar_control *m2)
1233 {
1234 	const struct audioreach_graph_info *info;
1235 
1236 	mutex_lock(&apm->lock);
1237 	info = idr_find(&apm->graph_info_idr, m2->graph_id);
1238 	mutex_unlock(&apm->lock);
1239 
1240 	if (info->dst_mod_inst_id == m2->module_instance_id &&
1241 	    info->src_mod_inst_id == m1->module_instance_id)
1242 		return true;
1243 
1244 	return false;
1245 }
1246 
1247 static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol,
1248 				      struct snd_ctl_elem_value *ucontrol)
1249 {
1250 	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
1251 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
1252 	const struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol);
1253 	struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
1254 	const struct snd_ar_control *dapm_scontrol = dw->dobj.private;
1255 	const struct snd_ar_control *scontrol = mc->dobj.private;
1256 	struct q6apm *data = dev_get_drvdata(c->dev);
1257 	bool connected;
1258 
1259 	connected = audioreach_is_vmixer_connected(data, scontrol, dapm_scontrol);
1260 	if (connected)
1261 		ucontrol->value.integer.value[0] = 1;
1262 	else
1263 		ucontrol->value.integer.value[0] = 0;
1264 
1265 	return 0;
1266 }
1267 
1268 static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol,
1269 				      struct snd_ctl_elem_value *ucontrol)
1270 {
1271 	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
1272 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
1273 	struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol);
1274 	struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
1275 	const struct snd_ar_control *dapm_scontrol = dw->dobj.private;
1276 	const struct snd_ar_control *scontrol = mc->dobj.private;
1277 	struct q6apm *data = dev_get_drvdata(c->dev);
1278 
1279 	if (ucontrol->value.integer.value[0]) {
1280 		audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, true);
1281 		snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, NULL);
1282 	} else {
1283 		audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, false);
1284 		snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, NULL);
1285 	}
1286 	return 0;
1287 }
1288 
1289 static int audioreach_get_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol,
1290 					       struct snd_ctl_elem_value *ucontrol)
1291 {
1292 	struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol);
1293 	struct audioreach_module *mod = dw->dobj.private;
1294 
1295 	ucontrol->value.integer.value[0] = mod->gain;
1296 
1297 	return 0;
1298 }
1299 
1300 static int audioreach_put_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol,
1301 					       struct snd_ctl_elem_value *ucontrol)
1302 {
1303 	struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol);
1304 	struct audioreach_module *mod = dw->dobj.private;
1305 
1306 	mod->gain = ucontrol->value.integer.value[0];
1307 
1308 	return 1;
1309 }
1310 
1311 static int audioreach_control_load_mix(struct snd_soc_component *scomp,
1312 				       struct snd_ar_control *scontrol,
1313 				       struct snd_kcontrol_new *kc,
1314 				       const struct snd_soc_tplg_ctl_hdr *hdr)
1315 {
1316 	const struct snd_soc_tplg_vendor_value_elem *c_elem;
1317 	const struct snd_soc_tplg_vendor_array *c_array;
1318 	const struct snd_soc_tplg_mixer_control *mc;
1319 	int tkn_count = 0;
1320 
1321 	mc = container_of_const(hdr, struct snd_soc_tplg_mixer_control, hdr);
1322 	c_array = (struct snd_soc_tplg_vendor_array *)mc->priv.data;
1323 
1324 	c_elem = c_array->value;
1325 
1326 	while (tkn_count <= (le32_to_cpu(c_array->num_elems) - 1)) {
1327 		switch (le32_to_cpu(c_elem->token)) {
1328 		case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID:
1329 			scontrol->sgid = le32_to_cpu(c_elem->value);
1330 			break;
1331 		case AR_TKN_DAI_INDEX:
1332 			scontrol->graph_id = le32_to_cpu(c_elem->value);
1333 			break;
1334 		default:
1335 			/* Ignore other tokens */
1336 			break;
1337 		}
1338 		c_elem++;
1339 		tkn_count++;
1340 	}
1341 
1342 	return 0;
1343 }
1344 
1345 static int audioreach_control_load(struct snd_soc_component *scomp, int index,
1346 				   struct snd_kcontrol_new *kc,
1347 				   struct snd_soc_tplg_ctl_hdr *hdr)
1348 {
1349 	struct snd_ar_control *scontrol;
1350 	struct soc_mixer_control *sm;
1351 	struct snd_soc_dobj *dobj;
1352 	int ret = 0;
1353 
1354 	scontrol = kzalloc_obj(*scontrol);
1355 	if (!scontrol)
1356 		return -ENOMEM;
1357 
1358 	scontrol->scomp = scomp;
1359 
1360 	switch (le32_to_cpu(hdr->ops.get)) {
1361 	case SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX:
1362 		sm = (struct soc_mixer_control *)kc->private_value;
1363 		dobj = &sm->dobj;
1364 		ret = audioreach_control_load_mix(scomp, scontrol, kc, hdr);
1365 		break;
1366 	case SND_SOC_AR_TPLG_VOL_CTL:
1367 		sm = (struct soc_mixer_control *)kc->private_value;
1368 		dobj = &sm->dobj;
1369 		break;
1370 	default:
1371 		dev_warn(scomp->dev, "control type not supported %d:%d:%d\n",
1372 			 hdr->ops.get, hdr->ops.put, hdr->ops.info);
1373 		kfree(scontrol);
1374 		return -EINVAL;
1375 	}
1376 
1377 	dobj->private = scontrol;
1378 	return ret;
1379 }
1380 
1381 static int audioreach_control_unload(struct snd_soc_component *scomp,
1382 				     struct snd_soc_dobj *dobj)
1383 {
1384 	struct snd_ar_control *scontrol = dobj->private;
1385 
1386 	kfree(scontrol);
1387 
1388 	return 0;
1389 }
1390 
1391 static const struct snd_soc_tplg_kcontrol_ops audioreach_io_ops[] = {
1392 	{SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX, audioreach_get_audio_mixer,
1393 		audioreach_put_audio_mixer, snd_soc_info_volsw},
1394 	{SND_SOC_AR_TPLG_VOL_CTL, audioreach_get_vol_ctrl_audio_mixer,
1395 		audioreach_put_vol_ctrl_audio_mixer, snd_soc_info_volsw},
1396 };
1397 
1398 static const struct snd_soc_tplg_ops audioreach_tplg_ops = {
1399 	.io_ops = audioreach_io_ops,
1400 	.io_ops_count = ARRAY_SIZE(audioreach_io_ops),
1401 
1402 	.control_load	= audioreach_control_load,
1403 	.control_unload	= audioreach_control_unload,
1404 
1405 	.widget_ready = audioreach_widget_ready,
1406 	.widget_unload = audioreach_widget_unload,
1407 
1408 	.complete = audioreach_tplg_complete,
1409 	.link_load = audioreach_link_load,
1410 
1411 	.dapm_route_load	= audioreach_route_load,
1412 	.dapm_route_unload	= audioreach_route_unload,
1413 };
1414 
1415 int audioreach_tplg_init(struct snd_soc_component *component)
1416 {
1417 	struct snd_soc_card *card = component->card;
1418 	struct device *dev = component->dev;
1419 	int ret;
1420 
1421 	/* Inline with Qualcomm UCM configs and linux-firmware path */
1422 	char *tplg_fw_name __free(kfree) = kasprintf(GFP_KERNEL, "qcom/%s/%s-tplg.bin",
1423 						     card->driver_name,
1424 						     card->name);
1425 	if (!tplg_fw_name)
1426 		return -ENOMEM;
1427 
1428 	const struct firmware *fw __free(firmware) = NULL;
1429 	ret = request_firmware(&fw, tplg_fw_name, dev);
1430 	if (ret < 0) {
1431 		dev_err(dev, "tplg firmware loading %s failed %d\n", tplg_fw_name, ret);
1432 		return ret;
1433 	}
1434 
1435 	ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw);
1436 	if (ret < 0) {
1437 		if (ret != -EPROBE_DEFER)
1438 			dev_err(dev, "tplg component load failed: %d\n", ret);
1439 	}
1440 
1441 	return ret;
1442 }
1443 EXPORT_SYMBOL_GPL(audioreach_tplg_init);
1444