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 mod->module_id = module_id; 549 mod->max_ip_port = max_ip_port; 550 mod->max_op_port = max_op_port; 551 mod->in_port = in_port; 552 mod->out_port = out_port; 553 mod->src_mod_inst_id = src_mod_inst_id; 554 for (pn = 0; pn < mod->max_op_port; pn++) { 555 if (src_mod_op_port_id[pn] && dst_mod_inst_id[pn] && 556 dst_mod_ip_port_id[pn]) { 557 mod->src_mod_op_port_id[id] = src_mod_op_port_id[pn]; 558 mod->dst_mod_inst_id[id] = dst_mod_inst_id[pn]; 559 mod->dst_mod_ip_port_id[id] = dst_mod_ip_port_id[pn]; 560 id++; 561 mod->num_connections = id; 562 } 563 } 564 } 565 566 return mod; 567 } 568 569 static int audioreach_widget_load_module_common(struct snd_soc_component *component, 570 int index, struct snd_soc_dapm_widget *w, 571 struct snd_soc_tplg_dapm_widget *tplg_w) 572 { 573 struct q6apm *apm = dev_get_drvdata(component->dev); 574 struct audioreach_container *cont; 575 struct audioreach_sub_graph *sg; 576 struct audioreach_module *mod; 577 struct snd_soc_dobj *dobj; 578 579 sg = audioreach_parse_sg_tokens(apm, &tplg_w->priv); 580 if (IS_ERR(sg)) 581 return PTR_ERR(sg); 582 583 cont = audioreach_parse_cont_tokens(apm, sg, &tplg_w->priv); 584 if (IS_ERR(cont)) 585 return PTR_ERR(cont); 586 587 mod = audioreach_parse_common_tokens(apm, cont, &tplg_w->priv, w); 588 if (IS_ERR(mod)) 589 return PTR_ERR(mod); 590 591 dobj = &w->dobj; 592 dobj->private = mod; 593 594 return 0; 595 } 596 597 static int audioreach_widget_load_enc_dec_cnv(struct snd_soc_component *component, 598 int index, struct snd_soc_dapm_widget *w, 599 struct snd_soc_tplg_dapm_widget *tplg_w) 600 { 601 struct snd_soc_tplg_vendor_value_elem *mod_elem; 602 struct snd_soc_tplg_vendor_array *mod_array; 603 struct audioreach_module *mod; 604 struct snd_soc_dobj *dobj; 605 int tkn_count = 0; 606 int ret; 607 608 ret = audioreach_widget_load_module_common(component, index, w, tplg_w); 609 if (ret) 610 return ret; 611 612 dobj = &w->dobj; 613 mod = dobj->private; 614 mod_array = audioreach_get_module_array(&tplg_w->priv); 615 mod_elem = mod_array->value; 616 617 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 618 switch (le32_to_cpu(mod_elem->token)) { 619 case AR_TKN_U32_MODULE_FMT_INTERLEAVE: 620 mod->interleave_type = le32_to_cpu(mod_elem->value); 621 break; 622 case AR_TKN_U32_MODULE_FMT_SAMPLE_RATE: 623 mod->rate = le32_to_cpu(mod_elem->value); 624 break; 625 case AR_TKN_U32_MODULE_FMT_BIT_DEPTH: 626 mod->bit_depth = le32_to_cpu(mod_elem->value); 627 break; 628 default: 629 break; 630 } 631 tkn_count++; 632 mod_elem++; 633 } 634 635 return 0; 636 } 637 638 static int audioreach_widget_log_module_load(struct audioreach_module *mod, 639 struct snd_soc_tplg_vendor_array *mod_array) 640 { 641 struct snd_soc_tplg_vendor_value_elem *mod_elem; 642 int tkn_count = 0; 643 644 mod_elem = mod_array->value; 645 646 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 647 switch (le32_to_cpu(mod_elem->token)) { 648 649 case AR_TKN_U32_MODULE_LOG_CODE: 650 mod->log_code = le32_to_cpu(mod_elem->value); 651 break; 652 case AR_TKN_U32_MODULE_LOG_TAP_POINT_ID: 653 mod->log_tap_point_id = le32_to_cpu(mod_elem->value); 654 break; 655 case AR_TKN_U32_MODULE_LOG_MODE: 656 mod->log_mode = le32_to_cpu(mod_elem->value); 657 break; 658 default: 659 break; 660 } 661 tkn_count++; 662 mod_elem++; 663 } 664 665 return 0; 666 } 667 668 static int audioreach_widget_dma_module_load(struct audioreach_module *mod, 669 struct snd_soc_tplg_vendor_array *mod_array) 670 { 671 struct snd_soc_tplg_vendor_value_elem *mod_elem; 672 int tkn_count = 0; 673 674 mod_elem = mod_array->value; 675 676 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 677 switch (le32_to_cpu(mod_elem->token)) { 678 case AR_TKN_U32_MODULE_HW_IF_IDX: 679 mod->hw_interface_idx = le32_to_cpu(mod_elem->value); 680 break; 681 case AR_TKN_U32_MODULE_FMT_DATA: 682 mod->data_format = le32_to_cpu(mod_elem->value); 683 break; 684 case AR_TKN_U32_MODULE_HW_IF_TYPE: 685 mod->hw_interface_type = le32_to_cpu(mod_elem->value); 686 break; 687 default: 688 break; 689 } 690 tkn_count++; 691 mod_elem++; 692 } 693 694 return 0; 695 } 696 697 static int audioreach_widget_i2s_module_load(struct audioreach_module *mod, 698 struct snd_soc_tplg_vendor_array *mod_array) 699 { 700 struct snd_soc_tplg_vendor_value_elem *mod_elem; 701 int tkn_count = 0; 702 703 mod_elem = mod_array->value; 704 705 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 706 switch (le32_to_cpu(mod_elem->token)) { 707 case AR_TKN_U32_MODULE_HW_IF_IDX: 708 mod->hw_interface_idx = le32_to_cpu(mod_elem->value); 709 break; 710 case AR_TKN_U32_MODULE_FMT_DATA: 711 mod->data_format = le32_to_cpu(mod_elem->value); 712 break; 713 case AR_TKN_U32_MODULE_HW_IF_TYPE: 714 mod->hw_interface_type = le32_to_cpu(mod_elem->value); 715 break; 716 case AR_TKN_U32_MODULE_SD_LINE_IDX: 717 mod->sd_line_idx = le32_to_cpu(mod_elem->value); 718 break; 719 case AR_TKN_U32_MODULE_WS_SRC: 720 mod->ws_src = le32_to_cpu(mod_elem->value); 721 break; 722 default: 723 break; 724 } 725 tkn_count++; 726 mod_elem++; 727 } 728 729 return 0; 730 } 731 732 static int audioreach_widget_load_buffer(struct snd_soc_component *component, 733 int index, struct snd_soc_dapm_widget *w, 734 struct snd_soc_tplg_dapm_widget *tplg_w) 735 { 736 struct snd_soc_tplg_vendor_array *mod_array; 737 struct audioreach_module *mod; 738 struct snd_soc_dobj *dobj; 739 int ret; 740 741 ret = audioreach_widget_load_module_common(component, index, w, tplg_w); 742 if (ret) 743 return ret; 744 745 dobj = &w->dobj; 746 mod = dobj->private; 747 748 mod_array = audioreach_get_module_array(&tplg_w->priv); 749 750 switch (mod->module_id) { 751 case MODULE_ID_CODEC_DMA_SINK: 752 case MODULE_ID_CODEC_DMA_SOURCE: 753 audioreach_widget_dma_module_load(mod, mod_array); 754 break; 755 case MODULE_ID_DATA_LOGGING: 756 audioreach_widget_log_module_load(mod, mod_array); 757 break; 758 case MODULE_ID_I2S_SINK: 759 case MODULE_ID_I2S_SOURCE: 760 audioreach_widget_i2s_module_load(mod, mod_array); 761 break; 762 default: 763 return -EINVAL; 764 } 765 766 return 0; 767 } 768 769 static int audioreach_widget_load_mixer(struct snd_soc_component *component, 770 int index, struct snd_soc_dapm_widget *w, 771 struct snd_soc_tplg_dapm_widget *tplg_w) 772 { 773 struct snd_soc_tplg_vendor_value_elem *w_elem; 774 struct snd_soc_tplg_vendor_array *w_array; 775 struct snd_ar_control *scontrol; 776 struct q6apm *data = dev_get_drvdata(component->dev); 777 struct snd_soc_dobj *dobj; 778 int tkn_count = 0; 779 780 w_array = &tplg_w->priv.array[0]; 781 782 scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL); 783 if (!scontrol) 784 return -ENOMEM; 785 786 scontrol->scomp = component; 787 dobj = &w->dobj; 788 dobj->private = scontrol; 789 790 w_elem = w_array->value; 791 while (tkn_count <= (le32_to_cpu(w_array->num_elems) - 1)) { 792 switch (le32_to_cpu(w_elem->token)) { 793 case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID: 794 scontrol->sgid = le32_to_cpu(w_elem->value); 795 break; 796 case AR_TKN_DAI_INDEX: 797 scontrol->graph_id = le32_to_cpu(w_elem->value); 798 break; 799 default: /* ignore other tokens */ 800 break; 801 } 802 tkn_count++; 803 w_elem++; 804 } 805 806 scontrol->w = w; 807 list_add_tail(&scontrol->node, &data->widget_list); 808 809 return 0; 810 } 811 812 static int audioreach_pga_event(struct snd_soc_dapm_widget *w, 813 struct snd_kcontrol *kcontrol, int event) 814 815 { 816 struct snd_soc_dapm_context *dapm = w->dapm; 817 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 818 struct audioreach_module *mod = w->dobj.private; 819 struct q6apm *apm = dev_get_drvdata(c->dev); 820 821 switch (event) { 822 case SND_SOC_DAPM_POST_PMU: 823 /* apply gain after power up of widget */ 824 audioreach_gain_set_vol_ctrl(apm, mod, mod->gain); 825 break; 826 default: 827 break; 828 } 829 830 return 0; 831 } 832 833 static const struct snd_soc_tplg_widget_events audioreach_widget_ops[] = { 834 { AR_PGA_DAPM_EVENT, audioreach_pga_event }, 835 }; 836 837 static int audioreach_widget_load_pga(struct snd_soc_component *component, 838 int index, struct snd_soc_dapm_widget *w, 839 struct snd_soc_tplg_dapm_widget *tplg_w) 840 { 841 struct audioreach_module *mod; 842 struct snd_soc_dobj *dobj; 843 int ret; 844 845 ret = audioreach_widget_load_module_common(component, index, w, tplg_w); 846 if (ret) 847 return ret; 848 849 dobj = &w->dobj; 850 mod = dobj->private; 851 mod->gain = VOL_CTRL_DEFAULT_GAIN; 852 853 ret = snd_soc_tplg_widget_bind_event(w, audioreach_widget_ops, 854 ARRAY_SIZE(audioreach_widget_ops), 855 le16_to_cpu(tplg_w->event_type)); 856 if (ret) { 857 dev_err(component->dev, "matching event handlers NOT found for %d\n", 858 le16_to_cpu(tplg_w->event_type)); 859 return -EINVAL; 860 } 861 862 return 0; 863 } 864 865 static int audioreach_widget_ready(struct snd_soc_component *component, 866 int index, struct snd_soc_dapm_widget *w, 867 struct snd_soc_tplg_dapm_widget *tplg_w) 868 { 869 switch (w->id) { 870 case snd_soc_dapm_aif_in: 871 case snd_soc_dapm_aif_out: 872 audioreach_widget_load_buffer(component, index, w, tplg_w); 873 break; 874 case snd_soc_dapm_decoder: 875 case snd_soc_dapm_encoder: 876 case snd_soc_dapm_src: 877 audioreach_widget_load_enc_dec_cnv(component, index, w, tplg_w); 878 break; 879 case snd_soc_dapm_buffer: 880 audioreach_widget_load_buffer(component, index, w, tplg_w); 881 break; 882 case snd_soc_dapm_mixer: 883 return audioreach_widget_load_mixer(component, index, w, tplg_w); 884 case snd_soc_dapm_pga: 885 return audioreach_widget_load_pga(component, index, w, tplg_w); 886 case snd_soc_dapm_dai_link: 887 case snd_soc_dapm_scheduler: 888 case snd_soc_dapm_out_drv: 889 default: 890 dev_err(component->dev, "Widget type (0x%x) not yet supported\n", w->id); 891 break; 892 } 893 894 return 0; 895 } 896 897 static int audioreach_widget_unload(struct snd_soc_component *scomp, 898 struct snd_soc_dobj *dobj) 899 { 900 struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj); 901 struct q6apm *apm = dev_get_drvdata(scomp->dev); 902 struct audioreach_container *cont; 903 struct audioreach_module *mod; 904 905 mod = dobj->private; 906 cont = mod->container; 907 908 if (w->id == snd_soc_dapm_mixer) { 909 /* virtual widget */ 910 struct snd_ar_control *scontrol = dobj->private; 911 912 list_del(&scontrol->node); 913 kfree(scontrol); 914 return 0; 915 } 916 917 mutex_lock(&apm->lock); 918 idr_remove(&apm->modules_idr, mod->instance_id); 919 cont->num_modules--; 920 921 list_del(&mod->node); 922 kfree(mod); 923 /* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */ 924 if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */ 925 struct audioreach_sub_graph *sg = cont->sub_graph; 926 927 idr_remove(&apm->containers_idr, cont->container_id); 928 list_del(&cont->node); 929 sg->num_containers--; 930 kfree(cont); 931 /* check if there are no more containers in the sub graph and remove it */ 932 if (list_empty(&sg->container_list)) { 933 struct audioreach_graph_info *info = sg->info; 934 935 idr_remove(&apm->sub_graphs_idr, sg->sub_graph_id); 936 list_del(&sg->node); 937 info->num_sub_graphs--; 938 kfree(sg); 939 /* Check if there are no more sub-graphs left then remove graph info */ 940 if (list_empty(&info->sg_list)) { 941 idr_remove(&apm->graph_info_idr, info->id); 942 kfree(info); 943 } 944 } 945 } 946 947 mutex_unlock(&apm->lock); 948 949 return 0; 950 } 951 952 static struct snd_ar_control *audioreach_find_widget(struct snd_soc_component *comp, 953 const char *name) 954 { 955 struct q6apm *apm = dev_get_drvdata(comp->dev); 956 struct snd_ar_control *control; 957 958 list_for_each_entry(control, &apm->widget_list, node) { 959 if (control->w && !strcmp(name, control->w->name)) 960 return control; 961 } 962 963 return NULL; 964 } 965 966 static struct audioreach_module *audioreach_find_module(struct snd_soc_component *comp, 967 const char *name) 968 { 969 struct q6apm *apm = dev_get_drvdata(comp->dev); 970 struct audioreach_module *module; 971 int id; 972 973 idr_for_each_entry(&apm->modules_idr, module, id) { 974 if (!strcmp(name, module->widget->name)) 975 return module; 976 } 977 978 return NULL; 979 } 980 981 static int audioreach_route_load(struct snd_soc_component *scomp, int index, 982 struct snd_soc_dapm_route *route) 983 { 984 struct audioreach_module *src_module, *sink_module; 985 struct snd_ar_control *control; 986 struct snd_soc_dapm_widget *w; 987 int i; 988 989 /* check if these are actual modules */ 990 src_module = audioreach_find_module(scomp, route->source); 991 sink_module = audioreach_find_module(scomp, route->sink); 992 993 if (sink_module && !src_module) { 994 control = audioreach_find_widget(scomp, route->source); 995 if (control) 996 control->module_instance_id = sink_module->instance_id; 997 998 } else if (!sink_module && src_module && route->control) { 999 /* check if this is a virtual mixer */ 1000 control = audioreach_find_widget(scomp, route->sink); 1001 if (!control || !control->w) 1002 return 0; 1003 1004 w = control->w; 1005 1006 for (i = 0; i < w->num_kcontrols; i++) { 1007 if (!strcmp(route->control, w->kcontrol_news[i].name)) { 1008 struct soc_mixer_control *sm; 1009 struct snd_soc_dobj *dobj; 1010 struct snd_ar_control *scontrol; 1011 1012 sm = (struct soc_mixer_control *)w->kcontrol_news[i].private_value; 1013 dobj = &sm->dobj; 1014 scontrol = dobj->private; 1015 scontrol->module_instance_id = src_module->instance_id; 1016 } 1017 } 1018 1019 } 1020 1021 return 0; 1022 } 1023 1024 static int audioreach_route_unload(struct snd_soc_component *scomp, 1025 struct snd_soc_dobj *dobj) 1026 { 1027 return 0; 1028 } 1029 1030 static int audioreach_tplg_complete(struct snd_soc_component *component) 1031 { 1032 /* TBD */ 1033 return 0; 1034 } 1035 1036 /* DAI link - used for any driver specific init */ 1037 static int audioreach_link_load(struct snd_soc_component *component, int index, 1038 struct snd_soc_dai_link *link, 1039 struct snd_soc_tplg_link_config *cfg) 1040 { 1041 link->nonatomic = true; 1042 link->dynamic = true; 1043 link->platforms->name = NULL; 1044 link->platforms->of_node = of_get_compatible_child(component->dev->of_node, 1045 "qcom,q6apm-dais"); 1046 return 0; 1047 } 1048 1049 static void audioreach_connect_sub_graphs(struct q6apm *apm, 1050 struct snd_ar_control *m1, 1051 struct snd_ar_control *m2, 1052 bool connect) 1053 { 1054 struct audioreach_graph_info *info; 1055 1056 mutex_lock(&apm->lock); 1057 info = idr_find(&apm->graph_info_idr, m2->graph_id); 1058 mutex_unlock(&apm->lock); 1059 1060 if (connect) { 1061 info->src_mod_inst_id = m1->module_instance_id; 1062 info->src_mod_op_port_id = 1; 1063 info->dst_mod_inst_id = m2->module_instance_id; 1064 info->dst_mod_ip_port_id = 2; 1065 1066 } else { 1067 info->src_mod_inst_id = 0; 1068 info->src_mod_op_port_id = 0; 1069 info->dst_mod_inst_id = 0; 1070 info->dst_mod_ip_port_id = 0; 1071 } 1072 } 1073 1074 static bool audioreach_is_vmixer_connected(struct q6apm *apm, 1075 struct snd_ar_control *m1, 1076 struct snd_ar_control *m2) 1077 { 1078 struct audioreach_graph_info *info; 1079 1080 mutex_lock(&apm->lock); 1081 info = idr_find(&apm->graph_info_idr, m2->graph_id); 1082 mutex_unlock(&apm->lock); 1083 1084 if (info->dst_mod_inst_id == m2->module_instance_id && 1085 info->src_mod_inst_id == m1->module_instance_id) 1086 return true; 1087 1088 return false; 1089 } 1090 1091 static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol, 1092 struct snd_ctl_elem_value *ucontrol) 1093 { 1094 struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 1095 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 1096 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); 1097 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 1098 struct snd_ar_control *dapm_scontrol = dw->dobj.private; 1099 struct snd_ar_control *scontrol = mc->dobj.private; 1100 struct q6apm *data = dev_get_drvdata(c->dev); 1101 bool connected; 1102 1103 connected = audioreach_is_vmixer_connected(data, scontrol, dapm_scontrol); 1104 if (connected) 1105 ucontrol->value.integer.value[0] = 1; 1106 else 1107 ucontrol->value.integer.value[0] = 0; 1108 1109 return 0; 1110 } 1111 1112 static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol, 1113 struct snd_ctl_elem_value *ucontrol) 1114 { 1115 struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 1116 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 1117 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); 1118 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 1119 struct snd_ar_control *dapm_scontrol = dw->dobj.private; 1120 struct snd_ar_control *scontrol = mc->dobj.private; 1121 struct q6apm *data = dev_get_drvdata(c->dev); 1122 1123 if (ucontrol->value.integer.value[0]) { 1124 audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, true); 1125 snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, NULL); 1126 } else { 1127 audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, false); 1128 snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, NULL); 1129 } 1130 return 0; 1131 } 1132 1133 static int audioreach_get_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, 1134 struct snd_ctl_elem_value *ucontrol) 1135 { 1136 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); 1137 struct audioreach_module *mod = dw->dobj.private; 1138 1139 ucontrol->value.integer.value[0] = mod->gain; 1140 1141 return 0; 1142 } 1143 1144 static int audioreach_put_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, 1145 struct snd_ctl_elem_value *ucontrol) 1146 { 1147 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); 1148 struct audioreach_module *mod = dw->dobj.private; 1149 1150 mod->gain = ucontrol->value.integer.value[0]; 1151 1152 return 1; 1153 } 1154 1155 static int audioreach_control_load_mix(struct snd_soc_component *scomp, 1156 struct snd_ar_control *scontrol, 1157 struct snd_kcontrol_new *kc, 1158 struct snd_soc_tplg_ctl_hdr *hdr) 1159 { 1160 struct snd_soc_tplg_vendor_value_elem *c_elem; 1161 struct snd_soc_tplg_vendor_array *c_array; 1162 struct snd_soc_tplg_mixer_control *mc; 1163 int tkn_count = 0; 1164 1165 mc = container_of(hdr, struct snd_soc_tplg_mixer_control, hdr); 1166 c_array = (struct snd_soc_tplg_vendor_array *)mc->priv.data; 1167 1168 c_elem = c_array->value; 1169 1170 while (tkn_count <= (le32_to_cpu(c_array->num_elems) - 1)) { 1171 switch (le32_to_cpu(c_elem->token)) { 1172 case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID: 1173 scontrol->sgid = le32_to_cpu(c_elem->value); 1174 break; 1175 case AR_TKN_DAI_INDEX: 1176 scontrol->graph_id = le32_to_cpu(c_elem->value); 1177 break; 1178 default: 1179 /* Ignore other tokens */ 1180 break; 1181 } 1182 c_elem++; 1183 tkn_count++; 1184 } 1185 1186 return 0; 1187 } 1188 1189 static int audioreach_control_load(struct snd_soc_component *scomp, int index, 1190 struct snd_kcontrol_new *kc, 1191 struct snd_soc_tplg_ctl_hdr *hdr) 1192 { 1193 struct snd_ar_control *scontrol; 1194 struct soc_mixer_control *sm; 1195 struct snd_soc_dobj *dobj; 1196 int ret = 0; 1197 1198 scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL); 1199 if (!scontrol) 1200 return -ENOMEM; 1201 1202 scontrol->scomp = scomp; 1203 1204 switch (le32_to_cpu(hdr->ops.get)) { 1205 case SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX: 1206 sm = (struct soc_mixer_control *)kc->private_value; 1207 dobj = &sm->dobj; 1208 ret = audioreach_control_load_mix(scomp, scontrol, kc, hdr); 1209 break; 1210 case SND_SOC_AR_TPLG_VOL_CTL: 1211 sm = (struct soc_mixer_control *)kc->private_value; 1212 dobj = &sm->dobj; 1213 break; 1214 default: 1215 dev_warn(scomp->dev, "control type not supported %d:%d:%d\n", 1216 hdr->ops.get, hdr->ops.put, hdr->ops.info); 1217 kfree(scontrol); 1218 return -EINVAL; 1219 } 1220 1221 dobj->private = scontrol; 1222 return ret; 1223 } 1224 1225 static int audioreach_control_unload(struct snd_soc_component *scomp, 1226 struct snd_soc_dobj *dobj) 1227 { 1228 struct snd_ar_control *scontrol = dobj->private; 1229 1230 kfree(scontrol); 1231 1232 return 0; 1233 } 1234 1235 static const struct snd_soc_tplg_kcontrol_ops audioreach_io_ops[] = { 1236 {SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX, audioreach_get_audio_mixer, 1237 audioreach_put_audio_mixer, snd_soc_info_volsw}, 1238 {SND_SOC_AR_TPLG_VOL_CTL, audioreach_get_vol_ctrl_audio_mixer, 1239 audioreach_put_vol_ctrl_audio_mixer, snd_soc_info_volsw}, 1240 }; 1241 1242 static struct snd_soc_tplg_ops audioreach_tplg_ops = { 1243 .io_ops = audioreach_io_ops, 1244 .io_ops_count = ARRAY_SIZE(audioreach_io_ops), 1245 1246 .control_load = audioreach_control_load, 1247 .control_unload = audioreach_control_unload, 1248 1249 .widget_ready = audioreach_widget_ready, 1250 .widget_unload = audioreach_widget_unload, 1251 1252 .complete = audioreach_tplg_complete, 1253 .link_load = audioreach_link_load, 1254 1255 .dapm_route_load = audioreach_route_load, 1256 .dapm_route_unload = audioreach_route_unload, 1257 }; 1258 1259 int audioreach_tplg_init(struct snd_soc_component *component) 1260 { 1261 struct snd_soc_card *card = component->card; 1262 struct device *dev = component->dev; 1263 const struct firmware *fw; 1264 char *tplg_fw_name; 1265 int ret; 1266 1267 /* Inline with Qualcomm UCM configs and linux-firmware path */ 1268 tplg_fw_name = kasprintf(GFP_KERNEL, "qcom/%s/%s-tplg.bin", card->driver_name, card->name); 1269 if (!tplg_fw_name) 1270 return -ENOMEM; 1271 1272 ret = request_firmware(&fw, tplg_fw_name, dev); 1273 if (ret < 0) { 1274 dev_err(dev, "tplg firmware loading %s failed %d \n", tplg_fw_name, ret); 1275 goto err; 1276 } 1277 1278 ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw); 1279 if (ret < 0) { 1280 if (ret != -EPROBE_DEFER) 1281 dev_err(dev, "tplg component load failed: %d\n", ret); 1282 } 1283 1284 release_firmware(fw); 1285 err: 1286 kfree(tplg_fw_name); 1287 1288 return ret; 1289 } 1290 EXPORT_SYMBOL_GPL(audioreach_tplg_init); 1291