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