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_audio_if_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 u32 val; 762 763 mod_elem = mod_array->value; 764 765 while (tkn_count < le32_to_cpu(mod_array->num_elems)) { 766 val = le32_to_cpu(mod_elem->value); 767 switch (le32_to_cpu(mod_elem->token)) { 768 case AR_TKN_U32_MODULE_HW_IF_IDX: 769 mod->hw_interface_idx = val; 770 break; 771 case AR_TKN_U32_MODULE_FMT_DATA: 772 mod->data_format = val; 773 break; 774 case AR_TKN_U16_MODULE_SYNC_SRC: 775 if (val > U16_MAX) 776 return -EINVAL; 777 mod->sync_src = (u16)val; 778 break; 779 case AR_TKN_U16_MODULE_CTRL_DATA_OUT_ENABLE: 780 if (val > U16_MAX) 781 return -EINVAL; 782 mod->ctrl_data_out_enable = (u16)val; 783 break; 784 case AR_TKN_U32_MODULE_SLOT_MASK: 785 mod->slot_mask = val; 786 break; 787 case AR_TKN_U16_MODULE_NSLOTS_PER_FRAME: 788 if (val > U16_MAX) 789 return -EINVAL; 790 mod->nslots_per_frame = (u16)val; 791 break; 792 case AR_TKN_U16_MODULE_SLOT_WIDTH: 793 if (val > U16_MAX) 794 return -EINVAL; 795 mod->slot_width = (u16)val; 796 break; 797 case AR_TKN_U16_MODULE_INTF_MODE: 798 if (val > U16_MAX) 799 return -EINVAL; 800 mod->intf_mode = (u16)val; 801 break; 802 case AR_TKN_U16_MODULE_SYNC_MODE: 803 if (val > U16_MAX) 804 return -EINVAL; 805 mod->sync_mode = (u16)val; 806 break; 807 case AR_TKN_U16_MODULE_CTRL_INVERT_SYNC_PULSE: 808 if (val > U16_MAX) 809 return -EINVAL; 810 mod->ctrl_invert_sync_pulse = (u16)val; 811 break; 812 case AR_TKN_U16_MODULE_CTRL_SYNC_DATA_DELAY: 813 if (val > U16_MAX) 814 return -EINVAL; 815 mod->ctrl_sync_data_delay = (u16)val; 816 break; 817 case AR_TKN_U16_MODULE_QAIF_TYPE: 818 if (val > U16_MAX) 819 return -EINVAL; 820 mod->qaif_type = (u16)val; 821 break; 822 case AR_TKN_U32_MODULE_ACTIVE_LANE_MASK: 823 mod->active_lane_mask = val; 824 break; 825 case AR_TKN_U32_MODULE_FRAME_SYNC_RATE: 826 mod->frame_sync_rate = val; 827 break; 828 case AR_TKN_U16_MODULE_BIT_CLK_TYPE: 829 if (val > U16_MAX) 830 return -EINVAL; 831 mod->bit_clk_type = (u16)val; 832 break; 833 case AR_TKN_U8_MODULE_INV_INT_BIT_CLK: 834 if (val > U8_MAX) 835 return -EINVAL; 836 mod->inv_int_bit_clk = (u8)val; 837 break; 838 case AR_TKN_U8_MODULE_INV_EXT_BIT_CLK: 839 if (val > U8_MAX) 840 return -EINVAL; 841 mod->inv_ext_bit_clk = (u8)val; 842 break; 843 default: 844 break; 845 } 846 tkn_count++; 847 mod_elem++; 848 } 849 850 return 0; 851 } 852 853 static int audioreach_widget_dp_module_load(struct audioreach_module *mod, 854 const struct snd_soc_tplg_vendor_array *mod_array) 855 { 856 const struct snd_soc_tplg_vendor_value_elem *mod_elem; 857 int tkn_count = 0; 858 859 mod_elem = mod_array->value; 860 861 while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 862 switch (le32_to_cpu(mod_elem->token)) { 863 case AR_TKN_U32_MODULE_FMT_DATA: 864 mod->data_format = le32_to_cpu(mod_elem->value); 865 break; 866 default: 867 break; 868 } 869 tkn_count++; 870 mod_elem++; 871 } 872 873 return 0; 874 } 875 876 static int audioreach_widget_load_buffer(struct snd_soc_component *component, 877 int index, struct snd_soc_dapm_widget *w, 878 const struct snd_soc_tplg_dapm_widget *tplg_w) 879 { 880 const struct snd_soc_tplg_vendor_array *mod_array; 881 struct audioreach_module *mod; 882 struct snd_soc_dobj *dobj; 883 int ret; 884 885 ret = audioreach_widget_load_module_common(component, index, w, tplg_w); 886 if (ret) 887 return ret; 888 889 dobj = &w->dobj; 890 mod = dobj->private; 891 892 mod_array = audioreach_get_module_array(&tplg_w->priv); 893 894 switch (mod->module_id) { 895 case MODULE_ID_CODEC_DMA_SINK: 896 case MODULE_ID_CODEC_DMA_SOURCE: 897 audioreach_widget_dma_module_load(mod, mod_array); 898 break; 899 case MODULE_ID_DATA_LOGGING: 900 audioreach_widget_log_module_load(mod, mod_array); 901 break; 902 case MODULE_ID_I2S_SINK: 903 case MODULE_ID_I2S_SOURCE: 904 audioreach_widget_i2s_module_load(mod, mod_array); 905 break; 906 case MODULE_ID_AUDIO_IF_SINK: 907 case MODULE_ID_AUDIO_IF_SOURCE: 908 ret = audioreach_widget_audio_if_module_load(mod, mod_array); 909 if (ret) 910 return ret; 911 break; 912 case MODULE_ID_DISPLAY_PORT_SINK: 913 audioreach_widget_dp_module_load(mod, mod_array); 914 break; 915 default: 916 return -EINVAL; 917 } 918 919 return 0; 920 } 921 922 static int audioreach_widget_load_mixer(struct snd_soc_component *component, 923 int index, struct snd_soc_dapm_widget *w, 924 const struct snd_soc_tplg_dapm_widget *tplg_w) 925 { 926 const struct snd_soc_tplg_vendor_value_elem *w_elem; 927 const struct snd_soc_tplg_vendor_array *w_array; 928 struct snd_ar_control *scontrol; 929 struct q6apm *data = dev_get_drvdata(component->dev); 930 struct snd_soc_dobj *dobj; 931 int tkn_count = 0; 932 933 w_array = &tplg_w->priv.array[0]; 934 935 scontrol = kzalloc_obj(*scontrol); 936 if (!scontrol) 937 return -ENOMEM; 938 939 scontrol->scomp = component; 940 dobj = &w->dobj; 941 dobj->private = scontrol; 942 943 w_elem = w_array->value; 944 while (tkn_count <= (le32_to_cpu(w_array->num_elems) - 1)) { 945 switch (le32_to_cpu(w_elem->token)) { 946 case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID: 947 scontrol->sgid = le32_to_cpu(w_elem->value); 948 break; 949 case AR_TKN_DAI_INDEX: 950 scontrol->graph_id = le32_to_cpu(w_elem->value); 951 break; 952 default: /* ignore other tokens */ 953 break; 954 } 955 tkn_count++; 956 w_elem++; 957 } 958 959 scontrol->w = w; 960 list_add_tail(&scontrol->node, &data->widget_list); 961 962 return 0; 963 } 964 965 static int audioreach_pga_event(struct snd_soc_dapm_widget *w, 966 struct snd_kcontrol *kcontrol, int event) 967 968 { 969 struct snd_soc_dapm_context *dapm = w->dapm; 970 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 971 struct audioreach_module *mod = w->dobj.private; 972 struct q6apm *apm = dev_get_drvdata(c->dev); 973 974 switch (event) { 975 case SND_SOC_DAPM_POST_PMU: 976 /* apply gain after power up of widget */ 977 audioreach_gain_set_vol_ctrl(apm, mod, mod->gain); 978 break; 979 default: 980 break; 981 } 982 983 return 0; 984 } 985 986 static const struct snd_soc_tplg_widget_events audioreach_widget_ops[] = { 987 { AR_PGA_DAPM_EVENT, audioreach_pga_event }, 988 }; 989 990 static int audioreach_widget_load_pga(struct snd_soc_component *component, 991 int index, struct snd_soc_dapm_widget *w, 992 const struct snd_soc_tplg_dapm_widget *tplg_w) 993 { 994 struct audioreach_module *mod; 995 struct snd_soc_dobj *dobj; 996 int ret; 997 998 ret = audioreach_widget_load_module_common(component, index, w, tplg_w); 999 if (ret) 1000 return ret; 1001 1002 dobj = &w->dobj; 1003 mod = dobj->private; 1004 mod->gain = VOL_CTRL_DEFAULT_GAIN; 1005 1006 ret = snd_soc_tplg_widget_bind_event(w, audioreach_widget_ops, 1007 ARRAY_SIZE(audioreach_widget_ops), 1008 le16_to_cpu(tplg_w->event_type)); 1009 if (ret) { 1010 dev_err(component->dev, "matching event handlers NOT found for %d\n", 1011 le16_to_cpu(tplg_w->event_type)); 1012 return -EINVAL; 1013 } 1014 1015 return 0; 1016 } 1017 1018 static int audioreach_widget_ready(struct snd_soc_component *component, 1019 int index, struct snd_soc_dapm_widget *w, 1020 struct snd_soc_tplg_dapm_widget *tplg_w) 1021 { 1022 switch (w->id) { 1023 case snd_soc_dapm_aif_in: 1024 case snd_soc_dapm_aif_out: 1025 audioreach_widget_load_buffer(component, index, w, tplg_w); 1026 break; 1027 case snd_soc_dapm_decoder: 1028 case snd_soc_dapm_encoder: 1029 case snd_soc_dapm_src: 1030 audioreach_widget_load_enc_dec_cnv(component, index, w, tplg_w); 1031 break; 1032 case snd_soc_dapm_buffer: 1033 audioreach_widget_load_buffer(component, index, w, tplg_w); 1034 break; 1035 case snd_soc_dapm_mixer: 1036 return audioreach_widget_load_mixer(component, index, w, tplg_w); 1037 case snd_soc_dapm_pga: 1038 return audioreach_widget_load_pga(component, index, w, tplg_w); 1039 case snd_soc_dapm_dai_link: 1040 case snd_soc_dapm_scheduler: 1041 case snd_soc_dapm_out_drv: 1042 default: 1043 dev_err(component->dev, "Widget type (0x%x) not yet supported\n", w->id); 1044 break; 1045 } 1046 1047 return 0; 1048 } 1049 1050 static int audioreach_widget_unload(struct snd_soc_component *scomp, 1051 struct snd_soc_dobj *dobj) 1052 { 1053 const struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj); 1054 struct q6apm *apm = dev_get_drvdata(scomp->dev); 1055 struct audioreach_container *cont; 1056 struct audioreach_module *mod; 1057 1058 if (w->id == snd_soc_dapm_mixer) { 1059 /* virtual widget */ 1060 struct snd_ar_control *scontrol = dobj->private; 1061 1062 list_del(&scontrol->node); 1063 kfree(scontrol); 1064 return 0; 1065 } 1066 mod = dobj->private; 1067 if (!mod) 1068 return 0; 1069 1070 cont = mod->container; 1071 1072 mutex_lock(&apm->lock); 1073 idr_remove(&apm->modules_idr, mod->instance_id); 1074 cont->num_modules--; 1075 1076 list_del(&mod->node); 1077 kfree(mod->data); 1078 kfree(mod); 1079 /* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */ 1080 if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */ 1081 struct audioreach_sub_graph *sg = cont->sub_graph; 1082 1083 idr_remove(&apm->containers_idr, cont->container_id); 1084 list_del(&cont->node); 1085 sg->num_containers--; 1086 kfree(cont); 1087 /* check if there are no more containers in the sub graph and remove it */ 1088 if (list_empty(&sg->container_list)) { 1089 struct audioreach_graph_info *info = sg->info; 1090 1091 idr_remove(&apm->sub_graphs_idr, sg->sub_graph_id); 1092 list_del(&sg->node); 1093 info->num_sub_graphs--; 1094 kfree(sg); 1095 /* Check if there are no more sub-graphs left then remove graph info */ 1096 if (list_empty(&info->sg_list)) { 1097 idr_remove(&apm->graph_info_idr, info->id); 1098 kfree(info); 1099 } 1100 } 1101 } 1102 1103 mutex_unlock(&apm->lock); 1104 1105 return 0; 1106 } 1107 1108 static struct snd_ar_control *audioreach_find_widget(struct snd_soc_component *comp, 1109 const char *name) 1110 { 1111 struct q6apm *apm = dev_get_drvdata(comp->dev); 1112 struct snd_ar_control *control; 1113 1114 list_for_each_entry(control, &apm->widget_list, node) { 1115 if (control->w && !strcmp(name, control->w->name)) 1116 return control; 1117 } 1118 1119 return NULL; 1120 } 1121 1122 static struct audioreach_module *audioreach_find_module(struct snd_soc_component *comp, 1123 const char *name) 1124 { 1125 struct q6apm *apm = dev_get_drvdata(comp->dev); 1126 struct audioreach_module *module; 1127 int id; 1128 1129 idr_for_each_entry(&apm->modules_idr, module, id) { 1130 if (!strcmp(name, module->widget->name)) 1131 return module; 1132 } 1133 1134 return NULL; 1135 } 1136 1137 static int audioreach_route_load(struct snd_soc_component *scomp, int index, 1138 struct snd_soc_dapm_route *route) 1139 { 1140 const struct audioreach_module *src_module, *sink_module; 1141 struct snd_ar_control *control; 1142 struct snd_soc_dapm_widget *w; 1143 int i; 1144 1145 /* check if these are actual modules */ 1146 src_module = audioreach_find_module(scomp, route->source); 1147 sink_module = audioreach_find_module(scomp, route->sink); 1148 1149 if (sink_module && !src_module) { 1150 control = audioreach_find_widget(scomp, route->source); 1151 if (control) 1152 control->module_instance_id = sink_module->instance_id; 1153 1154 } else if (!sink_module && src_module && route->control) { 1155 /* check if this is a virtual mixer */ 1156 control = audioreach_find_widget(scomp, route->sink); 1157 if (!control || !control->w) 1158 return 0; 1159 1160 w = control->w; 1161 1162 for (i = 0; i < w->num_kcontrols; i++) { 1163 if (!strcmp(route->control, w->kcontrol_news[i].name)) { 1164 struct soc_mixer_control *sm; 1165 struct snd_soc_dobj *dobj; 1166 struct snd_ar_control *scontrol; 1167 1168 sm = (struct soc_mixer_control *)w->kcontrol_news[i].private_value; 1169 dobj = &sm->dobj; 1170 scontrol = dobj->private; 1171 scontrol->module_instance_id = src_module->instance_id; 1172 } 1173 } 1174 1175 } 1176 1177 return 0; 1178 } 1179 1180 static int audioreach_route_unload(struct snd_soc_component *scomp, 1181 struct snd_soc_dobj *dobj) 1182 { 1183 return 0; 1184 } 1185 1186 static int audioreach_tplg_complete(struct snd_soc_component *component) 1187 { 1188 /* TBD */ 1189 return 0; 1190 } 1191 1192 /* DAI link - used for any driver specific init */ 1193 static int audioreach_link_load(struct snd_soc_component *component, int index, 1194 struct snd_soc_dai_link *link, 1195 struct snd_soc_tplg_link_config *cfg) 1196 { 1197 link->nonatomic = true; 1198 link->dynamic = true; 1199 link->platforms->name = NULL; 1200 link->platforms->of_node = of_get_compatible_child(component->dev->of_node, 1201 "qcom,q6apm-dais"); 1202 return 0; 1203 } 1204 1205 static void audioreach_connect_sub_graphs(struct q6apm *apm, 1206 const struct snd_ar_control *m1, 1207 const struct snd_ar_control *m2, 1208 bool connect) 1209 { 1210 struct audioreach_graph_info *info; 1211 1212 mutex_lock(&apm->lock); 1213 info = idr_find(&apm->graph_info_idr, m2->graph_id); 1214 mutex_unlock(&apm->lock); 1215 1216 if (connect) { 1217 info->src_mod_inst_id = m1->module_instance_id; 1218 info->src_mod_op_port_id = 1; 1219 info->dst_mod_inst_id = m2->module_instance_id; 1220 info->dst_mod_ip_port_id = 2; 1221 1222 } else { 1223 info->src_mod_inst_id = 0; 1224 info->src_mod_op_port_id = 0; 1225 info->dst_mod_inst_id = 0; 1226 info->dst_mod_ip_port_id = 0; 1227 } 1228 } 1229 1230 static bool audioreach_is_vmixer_connected(struct q6apm *apm, 1231 const struct snd_ar_control *m1, 1232 const struct snd_ar_control *m2) 1233 { 1234 const struct audioreach_graph_info *info; 1235 1236 mutex_lock(&apm->lock); 1237 info = idr_find(&apm->graph_info_idr, m2->graph_id); 1238 mutex_unlock(&apm->lock); 1239 1240 if (info->dst_mod_inst_id == m2->module_instance_id && 1241 info->src_mod_inst_id == m1->module_instance_id) 1242 return true; 1243 1244 return false; 1245 } 1246 1247 static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol, 1248 struct snd_ctl_elem_value *ucontrol) 1249 { 1250 struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 1251 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); 1252 const struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol); 1253 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 1254 const struct snd_ar_control *dapm_scontrol = dw->dobj.private; 1255 const struct snd_ar_control *scontrol = mc->dobj.private; 1256 struct q6apm *data = dev_get_drvdata(c->dev); 1257 bool connected; 1258 1259 connected = audioreach_is_vmixer_connected(data, scontrol, dapm_scontrol); 1260 if (connected) 1261 ucontrol->value.integer.value[0] = 1; 1262 else 1263 ucontrol->value.integer.value[0] = 0; 1264 1265 return 0; 1266 } 1267 1268 static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol, 1269 struct snd_ctl_elem_value *ucontrol) 1270 { 1271 struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 1272 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); 1273 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol); 1274 struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); 1275 const struct snd_ar_control *dapm_scontrol = dw->dobj.private; 1276 const struct snd_ar_control *scontrol = mc->dobj.private; 1277 struct q6apm *data = dev_get_drvdata(c->dev); 1278 1279 if (ucontrol->value.integer.value[0]) { 1280 audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, true); 1281 snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, NULL); 1282 } else { 1283 audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, false); 1284 snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, NULL); 1285 } 1286 return 0; 1287 } 1288 1289 static int audioreach_get_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, 1290 struct snd_ctl_elem_value *ucontrol) 1291 { 1292 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol); 1293 struct audioreach_module *mod = dw->dobj.private; 1294 1295 ucontrol->value.integer.value[0] = mod->gain; 1296 1297 return 0; 1298 } 1299 1300 static int audioreach_put_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, 1301 struct snd_ctl_elem_value *ucontrol) 1302 { 1303 struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol); 1304 struct audioreach_module *mod = dw->dobj.private; 1305 1306 mod->gain = ucontrol->value.integer.value[0]; 1307 1308 return 1; 1309 } 1310 1311 static int audioreach_control_load_mix(struct snd_soc_component *scomp, 1312 struct snd_ar_control *scontrol, 1313 struct snd_kcontrol_new *kc, 1314 const struct snd_soc_tplg_ctl_hdr *hdr) 1315 { 1316 const struct snd_soc_tplg_vendor_value_elem *c_elem; 1317 const struct snd_soc_tplg_vendor_array *c_array; 1318 const struct snd_soc_tplg_mixer_control *mc; 1319 int tkn_count = 0; 1320 1321 mc = container_of_const(hdr, struct snd_soc_tplg_mixer_control, hdr); 1322 c_array = (struct snd_soc_tplg_vendor_array *)mc->priv.data; 1323 1324 c_elem = c_array->value; 1325 1326 while (tkn_count <= (le32_to_cpu(c_array->num_elems) - 1)) { 1327 switch (le32_to_cpu(c_elem->token)) { 1328 case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID: 1329 scontrol->sgid = le32_to_cpu(c_elem->value); 1330 break; 1331 case AR_TKN_DAI_INDEX: 1332 scontrol->graph_id = le32_to_cpu(c_elem->value); 1333 break; 1334 default: 1335 /* Ignore other tokens */ 1336 break; 1337 } 1338 c_elem++; 1339 tkn_count++; 1340 } 1341 1342 return 0; 1343 } 1344 1345 static int audioreach_control_load(struct snd_soc_component *scomp, int index, 1346 struct snd_kcontrol_new *kc, 1347 struct snd_soc_tplg_ctl_hdr *hdr) 1348 { 1349 struct snd_ar_control *scontrol; 1350 struct soc_mixer_control *sm; 1351 struct snd_soc_dobj *dobj; 1352 int ret = 0; 1353 1354 scontrol = kzalloc_obj(*scontrol); 1355 if (!scontrol) 1356 return -ENOMEM; 1357 1358 scontrol->scomp = scomp; 1359 1360 switch (le32_to_cpu(hdr->ops.get)) { 1361 case SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX: 1362 sm = (struct soc_mixer_control *)kc->private_value; 1363 dobj = &sm->dobj; 1364 ret = audioreach_control_load_mix(scomp, scontrol, kc, hdr); 1365 break; 1366 case SND_SOC_AR_TPLG_VOL_CTL: 1367 sm = (struct soc_mixer_control *)kc->private_value; 1368 dobj = &sm->dobj; 1369 break; 1370 default: 1371 dev_warn(scomp->dev, "control type not supported %d:%d:%d\n", 1372 hdr->ops.get, hdr->ops.put, hdr->ops.info); 1373 kfree(scontrol); 1374 return -EINVAL; 1375 } 1376 1377 dobj->private = scontrol; 1378 return ret; 1379 } 1380 1381 static int audioreach_control_unload(struct snd_soc_component *scomp, 1382 struct snd_soc_dobj *dobj) 1383 { 1384 struct snd_ar_control *scontrol = dobj->private; 1385 1386 kfree(scontrol); 1387 1388 return 0; 1389 } 1390 1391 static const struct snd_soc_tplg_kcontrol_ops audioreach_io_ops[] = { 1392 {SND_SOC_AR_TPLG_FE_BE_GRAPH_CTL_MIX, audioreach_get_audio_mixer, 1393 audioreach_put_audio_mixer, snd_soc_info_volsw}, 1394 {SND_SOC_AR_TPLG_VOL_CTL, audioreach_get_vol_ctrl_audio_mixer, 1395 audioreach_put_vol_ctrl_audio_mixer, snd_soc_info_volsw}, 1396 }; 1397 1398 static const struct snd_soc_tplg_ops audioreach_tplg_ops = { 1399 .io_ops = audioreach_io_ops, 1400 .io_ops_count = ARRAY_SIZE(audioreach_io_ops), 1401 1402 .control_load = audioreach_control_load, 1403 .control_unload = audioreach_control_unload, 1404 1405 .widget_ready = audioreach_widget_ready, 1406 .widget_unload = audioreach_widget_unload, 1407 1408 .complete = audioreach_tplg_complete, 1409 .link_load = audioreach_link_load, 1410 1411 .dapm_route_load = audioreach_route_load, 1412 .dapm_route_unload = audioreach_route_unload, 1413 }; 1414 1415 int audioreach_tplg_init(struct snd_soc_component *component) 1416 { 1417 struct snd_soc_card *card = component->card; 1418 struct device *dev = component->dev; 1419 int ret; 1420 1421 /* Inline with Qualcomm UCM configs and linux-firmware path */ 1422 char *tplg_fw_name __free(kfree) = kasprintf(GFP_KERNEL, "qcom/%s/%s-tplg.bin", 1423 card->driver_name, 1424 card->name); 1425 if (!tplg_fw_name) 1426 return -ENOMEM; 1427 1428 const struct firmware *fw __free(firmware) = NULL; 1429 ret = request_firmware(&fw, tplg_fw_name, dev); 1430 if (ret < 0) { 1431 dev_err(dev, "tplg firmware loading %s failed %d\n", tplg_fw_name, ret); 1432 return ret; 1433 } 1434 1435 ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw); 1436 if (ret < 0) { 1437 if (ret != -EPROBE_DEFER) 1438 dev_err(dev, "tplg component load failed: %d\n", ret); 1439 } 1440 1441 return ret; 1442 } 1443 EXPORT_SYMBOL_GPL(audioreach_tplg_init); 1444