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