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_sub_graph *audioreach_parse_sg_tokens(struct q6apm *apm, 309 struct snd_soc_tplg_private *private) 310 { 311 struct snd_soc_tplg_vendor_value_elem *sg_elem; 312 struct snd_soc_tplg_vendor_array *sg_array; 313 struct audioreach_graph_info *info = NULL; 314 int graph_id, sub_graph_id, tkn_count = 0; 315 struct audioreach_sub_graph *sg; 316 bool found; 317 318 sg_array = audioreach_get_sg_array(private); 319 sg_elem = sg_array->value; 320 321 while (tkn_count <= (le32_to_cpu(sg_array->num_elems) - 1)) { 322 switch (le32_to_cpu(sg_elem->token)) { 323 case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID: 324 sub_graph_id = le32_to_cpu(sg_elem->value); 325 sg = audioreach_tplg_alloc_sub_graph(apm, sub_graph_id, &found); 326 if (IS_ERR(sg)) { 327 return sg; 328 } else if (found) { 329 /* Already parsed data for this sub-graph */ 330 return sg; 331 } 332 break; 333 case AR_TKN_DAI_INDEX: 334 /* Sub graph is associated with predefined graph */ 335 graph_id = le32_to_cpu(sg_elem->value); 336 info = audioreach_tplg_alloc_graph_info(apm, graph_id, &found); 337 if (IS_ERR(info)) 338 return ERR_CAST(info); 339 break; 340 case AR_TKN_U32_SUB_GRAPH_PERF_MODE: 341 sg->perf_mode = le32_to_cpu(sg_elem->value); 342 break; 343 case AR_TKN_U32_SUB_GRAPH_DIRECTION: 344 sg->direction = le32_to_cpu(sg_elem->value); 345 break; 346 case AR_TKN_U32_SUB_GRAPH_SCENARIO_ID: 347 sg->scenario_id = le32_to_cpu(sg_elem->value); 348 break; 349 default: 350 dev_err(apm->dev, "Not a valid token %d for graph\n", sg_elem->token); 351 break; 352 353 } 354 tkn_count++; 355 sg_elem++; 356 } 357 358 /* Sub graph is associated with predefined graph */ 359 if (info) 360 audioreach_tplg_add_sub_graph(sg, info); 361 362 return sg; 363 } 364 365 static struct audioreach_container *audioreach_parse_cont_tokens(struct q6apm *apm, 366 struct audioreach_sub_graph *sg, 367 struct snd_soc_tplg_private *private) 368 { 369 struct snd_soc_tplg_vendor_value_elem *cont_elem; 370 struct snd_soc_tplg_vendor_array *cont_array; 371 struct audioreach_container *cont; 372 int container_id, tkn_count = 0; 373 bool found = false; 374 375 cont_array = audioreach_get_cont_array(private); 376 cont_elem = cont_array->value; 377 378 while (tkn_count <= (le32_to_cpu(cont_array->num_elems) - 1)) { 379 switch (le32_to_cpu(cont_elem->token)) { 380 case AR_TKN_U32_CONTAINER_INSTANCE_ID: 381 container_id = le32_to_cpu(cont_elem->value); 382 cont = audioreach_tplg_alloc_container(apm, sg, container_id, &found); 383 if (IS_ERR(cont) || found)/* Error or Already parsed container data */ 384 return cont; 385 break; 386 case AR_TKN_U32_CONTAINER_CAPABILITY_ID: 387 cont->capability_id = le32_to_cpu(cont_elem->value); 388 break; 389 case AR_TKN_U32_CONTAINER_STACK_SIZE: 390 cont->stack_size = le32_to_cpu(cont_elem->value); 391 break; 392 case AR_TKN_U32_CONTAINER_GRAPH_POS: 393 cont->graph_pos = le32_to_cpu(cont_elem->value); 394 break; 395 case AR_TKN_U32_CONTAINER_PROC_DOMAIN: 396 cont->proc_domain = le32_to_cpu(cont_elem->value); 397 break; 398 default: 399 dev_err(apm->dev, "Not a valid token %d for graph\n", cont_elem->token); 400 break; 401 402 } 403 tkn_count++; 404 cont_elem++; 405 } 406 407 return cont; 408 } 409 410 static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *apm, 411 struct audioreach_container *cont, 412 struct snd_soc_tplg_private *private, 413 struct snd_soc_dapm_widget *w) 414 { 415 uint32_t max_ip_port = 0, max_op_port = 0, in_port = 0, out_port = 0; 416 uint32_t src_mod_op_port_id[AR_MAX_MOD_LINKS] = { 0, }; 417 uint32_t dst_mod_inst_id[AR_MAX_MOD_LINKS] = { 0, }; 418 uint32_t dst_mod_ip_port_id[AR_MAX_MOD_LINKS] = { 0, }; 419 uint32_t src_mod_inst_id = 0; 420 421 int module_id = 0, instance_id = 0, tkn_count = 0; 422 struct snd_soc_tplg_vendor_value_elem *mod_elem; 423 struct snd_soc_tplg_vendor_array *mod_array; 424 struct audioreach_module *mod = NULL; 425 uint32_t token; 426 bool found; 427 int max_tokens; 428 429 mod_array = audioreach_get_module_array(private); 430 mod_elem = mod_array->value; 431 max_tokens = le32_to_cpu(mod_array->num_elems); 432 while (tkn_count <= (max_tokens - 1)) { 433 token = le32_to_cpu(mod_elem->token); 434 switch (token) { 435 /* common module info */ 436 case AR_TKN_U32_MODULE_ID: 437 module_id = le32_to_cpu(mod_elem->value); 438 break; 439 case AR_TKN_U32_MODULE_INSTANCE_ID: 440 instance_id = le32_to_cpu(mod_elem->value); 441 mod = audioreach_tplg_alloc_module(apm, cont, w, 442 instance_id, &found); 443 if (IS_ERR(mod)) { 444 return mod; 445 } else if (found) { 446 dev_err(apm->dev, "Duplicate Module Instance ID 0x%08x found\n", 447 instance_id); 448 return ERR_PTR(-EINVAL); 449 } 450 451 break; 452 case AR_TKN_U32_MODULE_MAX_IP_PORTS: 453 max_ip_port = le32_to_cpu(mod_elem->value); 454 break; 455 case AR_TKN_U32_MODULE_MAX_OP_PORTS: 456 max_op_port = le32_to_cpu(mod_elem->value); 457 break; 458 case AR_TKN_U32_MODULE_IN_PORTS: 459 in_port = le32_to_cpu(mod_elem->value); 460 break; 461 case AR_TKN_U32_MODULE_OUT_PORTS: 462 out_port = le32_to_cpu(mod_elem->value); 463 break; 464 case AR_TKN_U32_MODULE_SRC_INSTANCE_ID: 465 src_mod_inst_id = le32_to_cpu(mod_elem->value); 466 break; 467 case AR_TKN_U32_MODULE_SRC_OP_PORT_ID: 468 src_mod_op_port_id[0] = le32_to_cpu(mod_elem->value); 469 break; 470 case AR_TKN_U32_MODULE_SRC_OP_PORT_ID1: 471 src_mod_op_port_id[1] = le32_to_cpu(mod_elem->value); 472 break; 473 case AR_TKN_U32_MODULE_SRC_OP_PORT_ID2: 474 src_mod_op_port_id[2] = le32_to_cpu(mod_elem->value); 475 break; 476 case AR_TKN_U32_MODULE_SRC_OP_PORT_ID3: 477 src_mod_op_port_id[3] = le32_to_cpu(mod_elem->value); 478 break; 479 case AR_TKN_U32_MODULE_SRC_OP_PORT_ID4: 480 src_mod_op_port_id[4] = le32_to_cpu(mod_elem->value); 481 break; 482 case AR_TKN_U32_MODULE_SRC_OP_PORT_ID5: 483 src_mod_op_port_id[5] = le32_to_cpu(mod_elem->value); 484 break; 485 case AR_TKN_U32_MODULE_SRC_OP_PORT_ID6: 486 src_mod_op_port_id[6] = le32_to_cpu(mod_elem->value); 487 break; 488 case AR_TKN_U32_MODULE_SRC_OP_PORT_ID7: 489 src_mod_op_port_id[7] = le32_to_cpu(mod_elem->value); 490 break; 491 case AR_TKN_U32_MODULE_DST_INSTANCE_ID: 492 dst_mod_inst_id[0] = le32_to_cpu(mod_elem->value); 493 break; 494 case AR_TKN_U32_MODULE_DST_INSTANCE_ID1: 495 dst_mod_inst_id[1] = le32_to_cpu(mod_elem->value); 496 break; 497 case AR_TKN_U32_MODULE_DST_INSTANCE_ID2: 498 dst_mod_inst_id[2] = le32_to_cpu(mod_elem->value); 499 break; 500 case AR_TKN_U32_MODULE_DST_INSTANCE_ID3: 501 dst_mod_inst_id[3] = le32_to_cpu(mod_elem->value); 502 break; 503 case AR_TKN_U32_MODULE_DST_INSTANCE_ID4: 504 dst_mod_inst_id[4] = le32_to_cpu(mod_elem->value); 505 break; 506 case AR_TKN_U32_MODULE_DST_INSTANCE_ID5: 507 dst_mod_inst_id[5] = le32_to_cpu(mod_elem->value); 508 break; 509 case AR_TKN_U32_MODULE_DST_INSTANCE_ID6: 510 dst_mod_inst_id[6] = le32_to_cpu(mod_elem->value); 511 break; 512 case AR_TKN_U32_MODULE_DST_INSTANCE_ID7: 513 dst_mod_inst_id[7] = le32_to_cpu(mod_elem->value); 514 break; 515 case AR_TKN_U32_MODULE_DST_IN_PORT_ID: 516 dst_mod_ip_port_id[0] = le32_to_cpu(mod_elem->value); 517 break; 518 case AR_TKN_U32_MODULE_DST_IN_PORT_ID1: 519 dst_mod_ip_port_id[1] = le32_to_cpu(mod_elem->value); 520 break; 521 case AR_TKN_U32_MODULE_DST_IN_PORT_ID2: 522 dst_mod_ip_port_id[2] = le32_to_cpu(mod_elem->value); 523 break; 524 case AR_TKN_U32_MODULE_DST_IN_PORT_ID3: 525 dst_mod_ip_port_id[3] = le32_to_cpu(mod_elem->value); 526 break; 527 case AR_TKN_U32_MODULE_DST_IN_PORT_ID4: 528 dst_mod_ip_port_id[4] = le32_to_cpu(mod_elem->value); 529 break; 530 case AR_TKN_U32_MODULE_DST_IN_PORT_ID5: 531 dst_mod_ip_port_id[5] = le32_to_cpu(mod_elem->value); 532 break; 533 case AR_TKN_U32_MODULE_DST_IN_PORT_ID6: 534 dst_mod_ip_port_id[6] = le32_to_cpu(mod_elem->value); 535 break; 536 case AR_TKN_U32_MODULE_DST_IN_PORT_ID7: 537 dst_mod_ip_port_id[7] = le32_to_cpu(mod_elem->value); 538 break; 539 default: 540 break; 541 542 } 543 tkn_count++; 544 mod_elem++; 545 } 546 547 if (mod) { 548 int pn, id = 0; 549 550 mod->module_id = module_id; 551 mod->max_ip_port = max_ip_port; 552 mod->max_op_port = max_op_port; 553 mod->in_port = in_port; 554 mod->out_port = out_port; 555 mod->src_mod_inst_id = src_mod_inst_id; 556 for (pn = 0; pn < mod->max_op_port; pn++) { 557 if (src_mod_op_port_id[pn] && dst_mod_inst_id[pn] && 558 dst_mod_ip_port_id[pn]) { 559 mod->src_mod_op_port_id[id] = src_mod_op_port_id[pn]; 560 mod->dst_mod_inst_id[id] = dst_mod_inst_id[pn]; 561 mod->dst_mod_ip_port_id[id] = dst_mod_ip_port_id[pn]; 562 id++; 563 mod->num_connections = id; 564 } 565 } 566 } 567 568 return mod; 569 } 570 571 static int audioreach_widget_load_module_common(struct snd_soc_component *component, 572 int index, struct snd_soc_dapm_widget *w, 573 struct snd_soc_tplg_dapm_widget *tplg_w) 574 { 575 struct q6apm *apm = dev_get_drvdata(component->dev); 576 struct audioreach_container *cont; 577 struct audioreach_sub_graph *sg; 578 struct audioreach_module *mod; 579 struct snd_soc_dobj *dobj; 580 581 sg = audioreach_parse_sg_tokens(apm, &tplg_w->priv); 582 if (IS_ERR(sg)) 583 return PTR_ERR(sg); 584 585 cont = audioreach_parse_cont_tokens(apm, sg, &tplg_w->priv); 586 if (IS_ERR(cont)) 587 return PTR_ERR(cont); 588 589 mod = audioreach_parse_common_tokens(apm, cont, &tplg_w->priv, w); 590 if (IS_ERR(mod)) 591 return PTR_ERR(mod); 592 593 dobj = &w->dobj; 594 dobj->private = mod; 595 596 return 0; 597 } 598 599 static int audioreach_widget_load_enc_dec_cnv(struct snd_soc_component *component, 600 int index, struct snd_soc_dapm_widget *w, 601 struct snd_soc_tplg_dapm_widget *tplg_w) 602 { 603 struct snd_soc_tplg_vendor_value_elem *mod_elem; 604 struct snd_soc_tplg_vendor_array *mod_array; 605 struct audioreach_module *mod; 606 struct snd_soc_dobj *dobj; 607 int tkn_count = 0; 608 int ret; 609 610 ret = audioreach_widget_load_module_common(component, index, w, tplg_w); 611 if (ret) 612 return ret; 613 614 dobj = &w->dobj; 615 mod = dobj->private; 616 mod_array = audioreach_get_module_array(&tplg_w->priv); 617 mod_elem = mod_array->value; 618 619 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 620 switch (le32_to_cpu(mod_elem->token)) { 621 case AR_TKN_U32_MODULE_FMT_INTERLEAVE: 622 mod->interleave_type = le32_to_cpu(mod_elem->value); 623 break; 624 case AR_TKN_U32_MODULE_FMT_SAMPLE_RATE: 625 mod->rate = le32_to_cpu(mod_elem->value); 626 break; 627 case AR_TKN_U32_MODULE_FMT_BIT_DEPTH: 628 mod->bit_depth = le32_to_cpu(mod_elem->value); 629 break; 630 default: 631 break; 632 } 633 tkn_count++; 634 mod_elem++; 635 } 636 637 return 0; 638 } 639 640 static int audioreach_widget_log_module_load(struct audioreach_module *mod, 641 struct snd_soc_tplg_vendor_array *mod_array) 642 { 643 struct snd_soc_tplg_vendor_value_elem *mod_elem; 644 int tkn_count = 0; 645 646 mod_elem = mod_array->value; 647 648 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 649 switch (le32_to_cpu(mod_elem->token)) { 650 651 case AR_TKN_U32_MODULE_LOG_CODE: 652 mod->log_code = le32_to_cpu(mod_elem->value); 653 break; 654 case AR_TKN_U32_MODULE_LOG_TAP_POINT_ID: 655 mod->log_tap_point_id = le32_to_cpu(mod_elem->value); 656 break; 657 case AR_TKN_U32_MODULE_LOG_MODE: 658 mod->log_mode = le32_to_cpu(mod_elem->value); 659 break; 660 default: 661 break; 662 } 663 tkn_count++; 664 mod_elem++; 665 } 666 667 return 0; 668 } 669 670 static int audioreach_widget_dma_module_load(struct audioreach_module *mod, 671 struct snd_soc_tplg_vendor_array *mod_array) 672 { 673 struct snd_soc_tplg_vendor_value_elem *mod_elem; 674 int tkn_count = 0; 675 676 mod_elem = mod_array->value; 677 678 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 679 switch (le32_to_cpu(mod_elem->token)) { 680 case AR_TKN_U32_MODULE_HW_IF_IDX: 681 mod->hw_interface_idx = le32_to_cpu(mod_elem->value); 682 break; 683 case AR_TKN_U32_MODULE_FMT_DATA: 684 mod->data_format = le32_to_cpu(mod_elem->value); 685 break; 686 case AR_TKN_U32_MODULE_HW_IF_TYPE: 687 mod->hw_interface_type = le32_to_cpu(mod_elem->value); 688 break; 689 default: 690 break; 691 } 692 tkn_count++; 693 mod_elem++; 694 } 695 696 return 0; 697 } 698 699 static int audioreach_widget_i2s_module_load(struct audioreach_module *mod, 700 struct snd_soc_tplg_vendor_array *mod_array) 701 { 702 struct snd_soc_tplg_vendor_value_elem *mod_elem; 703 int tkn_count = 0; 704 705 mod_elem = mod_array->value; 706 707 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 708 switch (le32_to_cpu(mod_elem->token)) { 709 case AR_TKN_U32_MODULE_HW_IF_IDX: 710 mod->hw_interface_idx = le32_to_cpu(mod_elem->value); 711 break; 712 case AR_TKN_U32_MODULE_FMT_DATA: 713 mod->data_format = le32_to_cpu(mod_elem->value); 714 break; 715 case AR_TKN_U32_MODULE_HW_IF_TYPE: 716 mod->hw_interface_type = le32_to_cpu(mod_elem->value); 717 break; 718 case AR_TKN_U32_MODULE_SD_LINE_IDX: 719 mod->sd_line_idx = le32_to_cpu(mod_elem->value); 720 break; 721 case AR_TKN_U32_MODULE_WS_SRC: 722 mod->ws_src = le32_to_cpu(mod_elem->value); 723 break; 724 default: 725 break; 726 } 727 tkn_count++; 728 mod_elem++; 729 } 730 731 return 0; 732 } 733 734 static int audioreach_widget_dp_module_load(struct audioreach_module *mod, 735 struct snd_soc_tplg_vendor_array *mod_array) 736 { 737 struct snd_soc_tplg_vendor_value_elem *mod_elem; 738 int tkn_count = 0; 739 740 mod_elem = mod_array->value; 741 742 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 743 switch (le32_to_cpu(mod_elem->token)) { 744 case AR_TKN_U32_MODULE_FMT_DATA: 745 mod->data_format = le32_to_cpu(mod_elem->value); 746 break; 747 default: 748 break; 749 } 750 tkn_count++; 751 mod_elem++; 752 } 753 754 return 0; 755 } 756 757 static int audioreach_widget_load_buffer(struct snd_soc_component *component, 758 int index, struct snd_soc_dapm_widget *w, 759 struct snd_soc_tplg_dapm_widget *tplg_w) 760 { 761 struct snd_soc_tplg_vendor_array *mod_array; 762 struct audioreach_module *mod; 763 struct snd_soc_dobj *dobj; 764 int ret; 765 766 ret = audioreach_widget_load_module_common(component, index, w, tplg_w); 767 if (ret) 768 return ret; 769 770 dobj = &w->dobj; 771 mod = dobj->private; 772 773 mod_array = audioreach_get_module_array(&tplg_w->priv); 774 775 switch (mod->module_id) { 776 case MODULE_ID_CODEC_DMA_SINK: 777 case MODULE_ID_CODEC_DMA_SOURCE: 778 audioreach_widget_dma_module_load(mod, mod_array); 779 break; 780 case MODULE_ID_DATA_LOGGING: 781 audioreach_widget_log_module_load(mod, mod_array); 782 break; 783 case MODULE_ID_I2S_SINK: 784 case MODULE_ID_I2S_SOURCE: 785 audioreach_widget_i2s_module_load(mod, mod_array); 786 break; 787 case MODULE_ID_DISPLAY_PORT_SINK: 788 audioreach_widget_dp_module_load(mod, mod_array); 789 break; 790 default: 791 return -EINVAL; 792 } 793 794 return 0; 795 } 796 797 static int audioreach_widget_load_mixer(struct snd_soc_component *component, 798 int index, struct snd_soc_dapm_widget *w, 799 struct snd_soc_tplg_dapm_widget *tplg_w) 800 { 801 struct snd_soc_tplg_vendor_value_elem *w_elem; 802 struct snd_soc_tplg_vendor_array *w_array; 803 struct snd_ar_control *scontrol; 804 struct q6apm *data = dev_get_drvdata(component->dev); 805 struct snd_soc_dobj *dobj; 806 int tkn_count = 0; 807 808 w_array = &tplg_w->priv.array[0]; 809 810 scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL); 811 if (!scontrol) 812 return -ENOMEM; 813 814 scontrol->scomp = component; 815 dobj = &w->dobj; 816 dobj->private = scontrol; 817 818 w_elem = w_array->value; 819 while (tkn_count <= (le32_to_cpu(w_array->num_elems) - 1)) { 820 switch (le32_to_cpu(w_elem->token)) { 821 case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID: 822 scontrol->sgid = le32_to_cpu(w_elem->value); 823 break; 824 case AR_TKN_DAI_INDEX: 825 scontrol->graph_id = le32_to_cpu(w_elem->value); 826 break; 827 default: /* ignore other tokens */ 828 break; 829 } 830 tkn_count++; 831 w_elem++; 832 } 833 834 scontrol->w = w; 835 list_add_tail(&scontrol->node, &data->widget_list); 836 837 return 0; 838 } 839 840 static int audioreach_pga_event(struct snd_soc_dapm_widget *w, 841 struct snd_kcontrol *kcontrol, int event) 842 843 { 844 struct snd_soc_dapm_context *dapm = w->dapm; 845 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 846 struct audioreach_module *mod = w->dobj.private; 847 struct q6apm *apm = dev_get_drvdata(c->dev); 848 849 switch (event) { 850 case SND_SOC_DAPM_POST_PMU: 851 /* apply gain after power up of widget */ 852 audioreach_gain_set_vol_ctrl(apm, mod, mod->gain); 853 break; 854 default: 855 break; 856 } 857 858 return 0; 859 } 860 861 static const struct snd_soc_tplg_widget_events audioreach_widget_ops[] = { 862 { AR_PGA_DAPM_EVENT, audioreach_pga_event }, 863 }; 864 865 static int audioreach_widget_load_pga(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 struct audioreach_module *mod; 870 struct snd_soc_dobj *dobj; 871 int ret; 872 873 ret = audioreach_widget_load_module_common(component, index, w, tplg_w); 874 if (ret) 875 return ret; 876 877 dobj = &w->dobj; 878 mod = dobj->private; 879 mod->gain = VOL_CTRL_DEFAULT_GAIN; 880 881 ret = snd_soc_tplg_widget_bind_event(w, audioreach_widget_ops, 882 ARRAY_SIZE(audioreach_widget_ops), 883 le16_to_cpu(tplg_w->event_type)); 884 if (ret) { 885 dev_err(component->dev, "matching event handlers NOT found for %d\n", 886 le16_to_cpu(tplg_w->event_type)); 887 return -EINVAL; 888 } 889 890 return 0; 891 } 892 893 static int audioreach_widget_ready(struct snd_soc_component *component, 894 int index, struct snd_soc_dapm_widget *w, 895 struct snd_soc_tplg_dapm_widget *tplg_w) 896 { 897 switch (w->id) { 898 case snd_soc_dapm_aif_in: 899 case snd_soc_dapm_aif_out: 900 audioreach_widget_load_buffer(component, index, w, tplg_w); 901 break; 902 case snd_soc_dapm_decoder: 903 case snd_soc_dapm_encoder: 904 case snd_soc_dapm_src: 905 audioreach_widget_load_enc_dec_cnv(component, index, w, tplg_w); 906 break; 907 case snd_soc_dapm_buffer: 908 audioreach_widget_load_buffer(component, index, w, tplg_w); 909 break; 910 case snd_soc_dapm_mixer: 911 return audioreach_widget_load_mixer(component, index, w, tplg_w); 912 case snd_soc_dapm_pga: 913 return audioreach_widget_load_pga(component, index, w, tplg_w); 914 case snd_soc_dapm_dai_link: 915 case snd_soc_dapm_scheduler: 916 case snd_soc_dapm_out_drv: 917 default: 918 dev_err(component->dev, "Widget type (0x%x) not yet supported\n", w->id); 919 break; 920 } 921 922 return 0; 923 } 924 925 static int audioreach_widget_unload(struct snd_soc_component *scomp, 926 struct snd_soc_dobj *dobj) 927 { 928 struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj); 929 struct q6apm *apm = dev_get_drvdata(scomp->dev); 930 struct audioreach_container *cont; 931 struct audioreach_module *mod; 932 933 mod = dobj->private; 934 cont = mod->container; 935 936 if (w->id == snd_soc_dapm_mixer) { 937 /* virtual widget */ 938 struct snd_ar_control *scontrol = dobj->private; 939 940 list_del(&scontrol->node); 941 kfree(scontrol); 942 return 0; 943 } 944 945 mutex_lock(&apm->lock); 946 idr_remove(&apm->modules_idr, mod->instance_id); 947 cont->num_modules--; 948 949 list_del(&mod->node); 950 kfree(mod); 951 /* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */ 952 if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */ 953 struct audioreach_sub_graph *sg = cont->sub_graph; 954 955 idr_remove(&apm->containers_idr, cont->container_id); 956 list_del(&cont->node); 957 sg->num_containers--; 958 kfree(cont); 959 /* check if there are no more containers in the sub graph and remove it */ 960 if (list_empty(&sg->container_list)) { 961 struct audioreach_graph_info *info = sg->info; 962 963 idr_remove(&apm->sub_graphs_idr, sg->sub_graph_id); 964 list_del(&sg->node); 965 info->num_sub_graphs--; 966 kfree(sg); 967 /* Check if there are no more sub-graphs left then remove graph info */ 968 if (list_empty(&info->sg_list)) { 969 idr_remove(&apm->graph_info_idr, info->id); 970 kfree(info); 971 } 972 } 973 } 974 975 mutex_unlock(&apm->lock); 976 977 return 0; 978 } 979 980 static struct snd_ar_control *audioreach_find_widget(struct snd_soc_component *comp, 981 const char *name) 982 { 983 struct q6apm *apm = dev_get_drvdata(comp->dev); 984 struct snd_ar_control *control; 985 986 list_for_each_entry(control, &apm->widget_list, node) { 987 if (control->w && !strcmp(name, control->w->name)) 988 return control; 989 } 990 991 return NULL; 992 } 993 994 static struct audioreach_module *audioreach_find_module(struct snd_soc_component *comp, 995 const char *name) 996 { 997 struct q6apm *apm = dev_get_drvdata(comp->dev); 998 struct audioreach_module *module; 999 int id; 1000 1001 idr_for_each_entry(&apm->modules_idr, module, id) { 1002 if (!strcmp(name, module->widget->name)) 1003 return module; 1004 } 1005 1006 return NULL; 1007 } 1008 1009 static int audioreach_route_load(struct snd_soc_component *scomp, int index, 1010 struct snd_soc_dapm_route *route) 1011 { 1012 struct audioreach_module *src_module, *sink_module; 1013 struct snd_ar_control *control; 1014 struct snd_soc_dapm_widget *w; 1015 int i; 1016 1017 /* check if these are actual modules */ 1018 src_module = audioreach_find_module(scomp, route->source); 1019 sink_module = audioreach_find_module(scomp, route->sink); 1020 1021 if (sink_module && !src_module) { 1022 control = audioreach_find_widget(scomp, route->source); 1023 if (control) 1024 control->module_instance_id = sink_module->instance_id; 1025 1026 } else if (!sink_module && src_module && route->control) { 1027 /* check if this is a virtual mixer */ 1028 control = audioreach_find_widget(scomp, route->sink); 1029 if (!control || !control->w) 1030 return 0; 1031 1032 w = control->w; 1033 1034 for (i = 0; i < w->num_kcontrols; i++) { 1035 if (!strcmp(route->control, w->kcontrol_news[i].name)) { 1036 struct soc_mixer_control *sm; 1037 struct snd_soc_dobj *dobj; 1038 struct snd_ar_control *scontrol; 1039 1040 sm = (struct soc_mixer_control *)w->kcontrol_news[i].private_value; 1041 dobj = &sm->dobj; 1042 scontrol = dobj->private; 1043 scontrol->module_instance_id = src_module->instance_id; 1044 } 1045 } 1046 1047 } 1048 1049 return 0; 1050 } 1051 1052 static int audioreach_route_unload(struct snd_soc_component *scomp, 1053 struct snd_soc_dobj *dobj) 1054 { 1055 return 0; 1056 } 1057 1058 static int audioreach_tplg_complete(struct snd_soc_component *component) 1059 { 1060 /* TBD */ 1061 return 0; 1062 } 1063 1064 /* DAI link - used for any driver specific init */ 1065 static int audioreach_link_load(struct snd_soc_component *component, int index, 1066 struct snd_soc_dai_link *link, 1067 struct snd_soc_tplg_link_config *cfg) 1068 { 1069 link->nonatomic = true; 1070 link->dynamic = true; 1071 link->platforms->name = NULL; 1072 link->platforms->of_node = of_get_compatible_child(component->dev->of_node, 1073 "qcom,q6apm-dais"); 1074 return 0; 1075 } 1076 1077 static void audioreach_connect_sub_graphs(struct q6apm *apm, 1078 struct snd_ar_control *m1, 1079 struct snd_ar_control *m2, 1080 bool connect) 1081 { 1082 struct audioreach_graph_info *info; 1083 1084 mutex_lock(&apm->lock); 1085 info = idr_find(&apm->graph_info_idr, m2->graph_id); 1086 mutex_unlock(&apm->lock); 1087 1088 if (connect) { 1089 info->src_mod_inst_id = m1->module_instance_id; 1090 info->src_mod_op_port_id = 1; 1091 info->dst_mod_inst_id = m2->module_instance_id; 1092 info->dst_mod_ip_port_id = 2; 1093 1094 } else { 1095 info->src_mod_inst_id = 0; 1096 info->src_mod_op_port_id = 0; 1097 info->dst_mod_inst_id = 0; 1098 info->dst_mod_ip_port_id = 0; 1099 } 1100 } 1101 1102 static bool audioreach_is_vmixer_connected(struct q6apm *apm, 1103 struct snd_ar_control *m1, 1104 struct snd_ar_control *m2) 1105 { 1106 struct audioreach_graph_info *info; 1107 1108 mutex_lock(&apm->lock); 1109 info = idr_find(&apm->graph_info_idr, m2->graph_id); 1110 mutex_unlock(&apm->lock); 1111 1112 if (info->dst_mod_inst_id == m2->module_instance_id && 1113 info->src_mod_inst_id == m1->module_instance_id) 1114 return true; 1115 1116 return false; 1117 } 1118 1119 static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol, 1120 struct snd_ctl_elem_value *ucontrol) 1121 { 1122 struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 1123 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 1124 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); 1125 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 1126 struct snd_ar_control *dapm_scontrol = dw->dobj.private; 1127 struct snd_ar_control *scontrol = mc->dobj.private; 1128 struct q6apm *data = dev_get_drvdata(c->dev); 1129 bool connected; 1130 1131 connected = audioreach_is_vmixer_connected(data, scontrol, dapm_scontrol); 1132 if (connected) 1133 ucontrol->value.integer.value[0] = 1; 1134 else 1135 ucontrol->value.integer.value[0] = 0; 1136 1137 return 0; 1138 } 1139 1140 static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol, 1141 struct snd_ctl_elem_value *ucontrol) 1142 { 1143 struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 1144 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 1145 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); 1146 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 1147 struct snd_ar_control *dapm_scontrol = dw->dobj.private; 1148 struct snd_ar_control *scontrol = mc->dobj.private; 1149 struct q6apm *data = dev_get_drvdata(c->dev); 1150 1151 if (ucontrol->value.integer.value[0]) { 1152 audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, true); 1153 snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, NULL); 1154 } else { 1155 audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, false); 1156 snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, NULL); 1157 } 1158 return 0; 1159 } 1160 1161 static int audioreach_get_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, 1162 struct snd_ctl_elem_value *ucontrol) 1163 { 1164 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); 1165 struct audioreach_module *mod = dw->dobj.private; 1166 1167 ucontrol->value.integer.value[0] = mod->gain; 1168 1169 return 0; 1170 } 1171 1172 static int audioreach_put_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, 1173 struct snd_ctl_elem_value *ucontrol) 1174 { 1175 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); 1176 struct audioreach_module *mod = dw->dobj.private; 1177 1178 mod->gain = ucontrol->value.integer.value[0]; 1179 1180 return 1; 1181 } 1182 1183 static int audioreach_control_load_mix(struct snd_soc_component *scomp, 1184 struct snd_ar_control *scontrol, 1185 struct snd_kcontrol_new *kc, 1186 struct snd_soc_tplg_ctl_hdr *hdr) 1187 { 1188 struct snd_soc_tplg_vendor_value_elem *c_elem; 1189 struct snd_soc_tplg_vendor_array *c_array; 1190 struct snd_soc_tplg_mixer_control *mc; 1191 int tkn_count = 0; 1192 1193 mc = container_of(hdr, struct snd_soc_tplg_mixer_control, hdr); 1194 c_array = (struct snd_soc_tplg_vendor_array *)mc->priv.data; 1195 1196 c_elem = c_array->value; 1197 1198 while (tkn_count <= (le32_to_cpu(c_array->num_elems) - 1)) { 1199 switch (le32_to_cpu(c_elem->token)) { 1200 case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID: 1201 scontrol->sgid = le32_to_cpu(c_elem->value); 1202 break; 1203 case AR_TKN_DAI_INDEX: 1204 scontrol->graph_id = le32_to_cpu(c_elem->value); 1205 break; 1206 default: 1207 /* Ignore other tokens */ 1208 break; 1209 } 1210 c_elem++; 1211 tkn_count++; 1212 } 1213 1214 return 0; 1215 } 1216 1217 static int audioreach_control_load(struct snd_soc_component *scomp, int index, 1218 struct snd_kcontrol_new *kc, 1219 struct snd_soc_tplg_ctl_hdr *hdr) 1220 { 1221 struct snd_ar_control *scontrol; 1222 struct soc_mixer_control *sm; 1223 struct snd_soc_dobj *dobj; 1224 int ret = 0; 1225 1226 scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL); 1227 if (!scontrol) 1228 return -ENOMEM; 1229 1230 scontrol->scomp = scomp; 1231 1232 switch (le32_to_cpu(hdr->ops.get)) { 1233 case SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX: 1234 sm = (struct soc_mixer_control *)kc->private_value; 1235 dobj = &sm->dobj; 1236 ret = audioreach_control_load_mix(scomp, scontrol, kc, hdr); 1237 break; 1238 case SND_SOC_AR_TPLG_VOL_CTL: 1239 sm = (struct soc_mixer_control *)kc->private_value; 1240 dobj = &sm->dobj; 1241 break; 1242 default: 1243 dev_warn(scomp->dev, "control type not supported %d:%d:%d\n", 1244 hdr->ops.get, hdr->ops.put, hdr->ops.info); 1245 kfree(scontrol); 1246 return -EINVAL; 1247 } 1248 1249 dobj->private = scontrol; 1250 return ret; 1251 } 1252 1253 static int audioreach_control_unload(struct snd_soc_component *scomp, 1254 struct snd_soc_dobj *dobj) 1255 { 1256 struct snd_ar_control *scontrol = dobj->private; 1257 1258 kfree(scontrol); 1259 1260 return 0; 1261 } 1262 1263 static const struct snd_soc_tplg_kcontrol_ops audioreach_io_ops[] = { 1264 {SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX, audioreach_get_audio_mixer, 1265 audioreach_put_audio_mixer, snd_soc_info_volsw}, 1266 {SND_SOC_AR_TPLG_VOL_CTL, audioreach_get_vol_ctrl_audio_mixer, 1267 audioreach_put_vol_ctrl_audio_mixer, snd_soc_info_volsw}, 1268 }; 1269 1270 static const struct snd_soc_tplg_ops audioreach_tplg_ops = { 1271 .io_ops = audioreach_io_ops, 1272 .io_ops_count = ARRAY_SIZE(audioreach_io_ops), 1273 1274 .control_load = audioreach_control_load, 1275 .control_unload = audioreach_control_unload, 1276 1277 .widget_ready = audioreach_widget_ready, 1278 .widget_unload = audioreach_widget_unload, 1279 1280 .complete = audioreach_tplg_complete, 1281 .link_load = audioreach_link_load, 1282 1283 .dapm_route_load = audioreach_route_load, 1284 .dapm_route_unload = audioreach_route_unload, 1285 }; 1286 1287 int audioreach_tplg_init(struct snd_soc_component *component) 1288 { 1289 struct snd_soc_card *card = component->card; 1290 struct device *dev = component->dev; 1291 const struct firmware *fw; 1292 int ret; 1293 1294 /* Inline with Qualcomm UCM configs and linux-firmware path */ 1295 char *tplg_fw_name __free(kfree) = kasprintf(GFP_KERNEL, "qcom/%s/%s-tplg.bin", 1296 card->driver_name, 1297 card->name); 1298 if (!tplg_fw_name) 1299 return -ENOMEM; 1300 1301 ret = request_firmware(&fw, tplg_fw_name, dev); 1302 if (ret < 0) { 1303 dev_err(dev, "tplg firmware loading %s failed %d\n", tplg_fw_name, ret); 1304 return ret; 1305 } 1306 1307 ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw); 1308 if (ret < 0) { 1309 if (ret != -EPROBE_DEFER) 1310 dev_err(dev, "tplg component load failed: %d\n", ret); 1311 } 1312 1313 release_firmware(fw); 1314 1315 return ret; 1316 } 1317 EXPORT_SYMBOL_GPL(audioreach_tplg_init); 1318
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.