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