1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2019 Intel Corporation. All rights reserved. 7 // 8 // Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> 9 // 10 11 #include <linux/bitfield.h> 12 #include <trace/events/sof.h> 13 #include "sof-audio.h" 14 #include "sof-of-dev.h" 15 #include "ops.h" 16 17 static bool is_virtual_widget(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, 18 const char *func) 19 { 20 switch (widget->id) { 21 case snd_soc_dapm_out_drv: 22 case snd_soc_dapm_output: 23 case snd_soc_dapm_input: 24 dev_dbg(sdev->dev, "%s: %s is a virtual widget\n", func, widget->name); 25 return true; 26 default: 27 return false; 28 } 29 } 30 31 static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_sof_widget *widget) 32 { 33 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 34 struct snd_sof_route *sroute; 35 36 list_for_each_entry(sroute, &sdev->route_list, list) 37 if (sroute->src_widget == widget || sroute->sink_widget == widget) { 38 if (sroute->setup && tplg_ops && tplg_ops->route_free) 39 tplg_ops->route_free(sdev, sroute); 40 41 sroute->setup = false; 42 } 43 } 44 45 static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, 46 struct snd_sof_widget *swidget) 47 { 48 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 49 struct snd_sof_pipeline *spipe = swidget->spipe; 50 struct snd_sof_widget *pipe_widget; 51 int err = 0; 52 int ret; 53 54 if (!swidget->private) 55 return 0; 56 57 trace_sof_widget_free(swidget); 58 59 /* only free when use_count is 0 */ 60 if (--swidget->use_count) 61 return 0; 62 63 pipe_widget = swidget->spipe->pipe_widget; 64 65 /* reset route setup status for all routes that contain this widget */ 66 sof_reset_route_setup_status(sdev, swidget); 67 68 /* free DAI config and continue to free widget even if it fails */ 69 if (WIDGET_IS_DAI(swidget->id)) { 70 struct snd_sof_dai_config_data data; 71 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_FREE; 72 73 data.dai_data = DMA_CHAN_INVALID; 74 75 if (tplg_ops && tplg_ops->dai_config) { 76 err = tplg_ops->dai_config(sdev, swidget, flags, &data); 77 if (err < 0) 78 dev_err(sdev->dev, "failed to free config for widget %s\n", 79 swidget->widget->name); 80 } 81 } 82 83 /* continue to disable core even if IPC fails */ 84 if (tplg_ops && tplg_ops->widget_free) { 85 ret = tplg_ops->widget_free(sdev, swidget); 86 if (ret < 0 && !err) 87 err = ret; 88 } 89 90 /* 91 * decrement ref count for cores associated with all modules in the pipeline and clear 92 * the complete flag 93 */ 94 if (swidget->id == snd_soc_dapm_scheduler) { 95 int i; 96 97 for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) { 98 ret = snd_sof_dsp_core_put(sdev, i); 99 if (ret < 0) { 100 dev_err(sdev->dev, "failed to disable target core: %d for pipeline %s\n", 101 i, swidget->widget->name); 102 if (!err) 103 err = ret; 104 } 105 } 106 swidget->spipe->complete = 0; 107 } 108 109 /* 110 * free the scheduler widget (same as pipe_widget) associated with the current swidget. 111 * skip for static pipelines 112 */ 113 if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) { 114 ret = sof_widget_free_unlocked(sdev, pipe_widget); 115 if (ret < 0 && !err) 116 err = ret; 117 } 118 119 if (!err) 120 dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name); 121 122 return err; 123 } 124 125 int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 126 { 127 int ret; 128 129 mutex_lock(&swidget->setup_mutex); 130 ret = sof_widget_free_unlocked(sdev, swidget); 131 mutex_unlock(&swidget->setup_mutex); 132 133 return ret; 134 } 135 EXPORT_SYMBOL(sof_widget_free); 136 137 static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, 138 struct snd_sof_widget *swidget) 139 { 140 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 141 struct snd_sof_pipeline *spipe = swidget->spipe; 142 bool use_count_decremented = false; 143 int ret; 144 int i; 145 146 /* skip if there is no private data */ 147 if (!swidget->private) 148 return 0; 149 150 trace_sof_widget_setup(swidget); 151 152 /* widget already set up */ 153 if (++swidget->use_count > 1) 154 return 0; 155 156 /* 157 * The scheduler widget for a pipeline is not part of the connected DAPM 158 * widget list and it needs to be set up before the widgets in the pipeline 159 * are set up. The use_count for the scheduler widget is incremented for every 160 * widget in a given pipeline to ensure that it is freed only after the last 161 * widget in the pipeline is freed. Skip setting up scheduler widget for static pipelines. 162 */ 163 if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) { 164 if (!swidget->spipe || !swidget->spipe->pipe_widget) { 165 dev_err(sdev->dev, "No pipeline set for %s\n", swidget->widget->name); 166 ret = -EINVAL; 167 goto use_count_dec; 168 } 169 170 ret = sof_widget_setup_unlocked(sdev, swidget->spipe->pipe_widget); 171 if (ret < 0) 172 goto use_count_dec; 173 } 174 175 /* update ref count for cores associated with all modules in the pipeline */ 176 if (swidget->id == snd_soc_dapm_scheduler) { 177 for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) { 178 ret = snd_sof_dsp_core_get(sdev, i); 179 if (ret < 0) { 180 dev_err(sdev->dev, "failed to enable target core %d for pipeline %s\n", 181 i, swidget->widget->name); 182 goto pipe_widget_free; 183 } 184 } 185 } 186 187 /* setup widget in the DSP */ 188 if (tplg_ops && tplg_ops->widget_setup) { 189 ret = tplg_ops->widget_setup(sdev, swidget); 190 if (ret < 0) 191 goto pipe_widget_free; 192 } 193 194 /* send config for DAI components */ 195 if (WIDGET_IS_DAI(swidget->id)) { 196 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 197 198 /* 199 * The config flags saved during BE DAI hw_params will be used for IPC3. IPC4 does 200 * not use the flags argument. 201 */ 202 if (tplg_ops && tplg_ops->dai_config) { 203 ret = tplg_ops->dai_config(sdev, swidget, flags, NULL); 204 if (ret < 0) 205 goto widget_free; 206 } 207 } 208 209 /* restore kcontrols for widget */ 210 if (tplg_ops && tplg_ops->control && tplg_ops->control->widget_kcontrol_setup) { 211 ret = tplg_ops->control->widget_kcontrol_setup(sdev, swidget); 212 if (ret < 0) 213 goto widget_free; 214 } 215 216 dev_dbg(sdev->dev, "widget %s setup complete\n", swidget->widget->name); 217 218 return 0; 219 220 widget_free: 221 /* widget use_count will be decremented by sof_widget_free() */ 222 sof_widget_free_unlocked(sdev, swidget); 223 use_count_decremented = true; 224 pipe_widget_free: 225 if (swidget->id != snd_soc_dapm_scheduler) { 226 sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); 227 } else { 228 int j; 229 230 /* decrement ref count for all cores that were updated previously */ 231 for_each_set_bit(j, &spipe->core_mask, sdev->num_cores) { 232 if (j >= i) 233 break; 234 snd_sof_dsp_core_put(sdev, j); 235 } 236 } 237 use_count_dec: 238 if (!use_count_decremented) 239 swidget->use_count--; 240 241 return ret; 242 } 243 244 int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 245 { 246 int ret; 247 248 mutex_lock(&swidget->setup_mutex); 249 ret = sof_widget_setup_unlocked(sdev, swidget); 250 mutex_unlock(&swidget->setup_mutex); 251 252 return ret; 253 } 254 EXPORT_SYMBOL(sof_widget_setup); 255 256 int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsource, 257 struct snd_soc_dapm_widget *wsink) 258 { 259 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 260 struct snd_sof_widget *src_widget = wsource->dobj.private; 261 struct snd_sof_widget *sink_widget = wsink->dobj.private; 262 struct snd_sof_route *sroute; 263 bool route_found = false; 264 265 /* ignore routes involving virtual widgets in topology */ 266 if (is_virtual_widget(sdev, src_widget->widget, __func__) || 267 is_virtual_widget(sdev, sink_widget->widget, __func__)) 268 return 0; 269 270 /* find route matching source and sink widgets */ 271 list_for_each_entry(sroute, &sdev->route_list, list) 272 if (sroute->src_widget == src_widget && sroute->sink_widget == sink_widget) { 273 route_found = true; 274 break; 275 } 276 277 if (!route_found) { 278 dev_err(sdev->dev, "error: cannot find SOF route for source %s -> %s sink\n", 279 wsource->name, wsink->name); 280 return -EINVAL; 281 } 282 283 /* nothing to do if route is already set up */ 284 if (sroute->setup) 285 return 0; 286 287 if (tplg_ops && tplg_ops->route_setup) { 288 int ret = tplg_ops->route_setup(sdev, sroute); 289 290 if (ret < 0) 291 return ret; 292 } 293 294 sroute->setup = true; 295 return 0; 296 } 297 298 static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, 299 struct snd_soc_dapm_widget_list *list, int dir) 300 { 301 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 302 struct snd_soc_dapm_widget *widget; 303 struct snd_sof_route *sroute; 304 struct snd_soc_dapm_path *p; 305 int ret = 0; 306 int i; 307 308 /* 309 * Set up connections between widgets in the sink/source paths based on direction. 310 * Some non-SOF widgets exist in topology either for compatibility or for the 311 * purpose of connecting a pipeline from a host to a DAI in order to receive the DAPM 312 * events. But they are not handled by the firmware. So ignore them. 313 */ 314 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 315 for_each_dapm_widgets(list, i, widget) { 316 if (!widget->dobj.private) 317 continue; 318 319 snd_soc_dapm_widget_for_each_sink_path(widget, p) { 320 if (!widget_in_list(list, p->sink)) 321 continue; 322 323 if (p->sink->dobj.private) { 324 ret = sof_route_setup(sdev, widget, p->sink); 325 if (ret < 0) 326 return ret; 327 } 328 } 329 } 330 } else { 331 for_each_dapm_widgets(list, i, widget) { 332 if (!widget->dobj.private) 333 continue; 334 335 snd_soc_dapm_widget_for_each_source_path(widget, p) { 336 if (!widget_in_list(list, p->source)) 337 continue; 338 339 if (p->source->dobj.private) { 340 ret = sof_route_setup(sdev, p->source, widget); 341 if (ret < 0) 342 return ret; 343 } 344 } 345 } 346 } 347 348 /* 349 * The above loop handles connections between widgets that belong to the DAPM widget list. 350 * This is not sufficient to handle loopback cases between pipelines configured with 351 * different directions, e.g. a sidetone or an amplifier feedback connected to a speaker 352 * protection module. 353 */ 354 list_for_each_entry(sroute, &sdev->route_list, list) { 355 bool src_widget_in_dapm_list, sink_widget_in_dapm_list; 356 struct snd_sof_widget *swidget; 357 358 if (sroute->setup) 359 continue; 360 361 src_widget_in_dapm_list = widget_in_list(list, sroute->src_widget->widget); 362 sink_widget_in_dapm_list = widget_in_list(list, sroute->sink_widget->widget); 363 364 /* 365 * if both source and sink are in the DAPM list, the route must already have been 366 * set up above. And if neither are in the DAPM list, the route shouldn't be 367 * handled now. 368 */ 369 if (src_widget_in_dapm_list == sink_widget_in_dapm_list) 370 continue; 371 372 /* 373 * At this point either the source widget or the sink widget is in the DAPM list 374 * with a route that might need to be set up. Check the use_count of the widget 375 * that is not in the DAPM list to confirm if it is in use currently before setting 376 * up the route. 377 */ 378 if (src_widget_in_dapm_list) 379 swidget = sroute->sink_widget; 380 else 381 swidget = sroute->src_widget; 382 383 mutex_lock(&swidget->setup_mutex); 384 if (!swidget->use_count) { 385 mutex_unlock(&swidget->setup_mutex); 386 continue; 387 } 388 389 if (tplg_ops && tplg_ops->route_setup) { 390 /* 391 * this route will get freed when either the source widget or the sink 392 * widget is freed during hw_free 393 */ 394 ret = tplg_ops->route_setup(sdev, sroute); 395 if (!ret) 396 sroute->setup = true; 397 } 398 399 mutex_unlock(&swidget->setup_mutex); 400 401 if (ret < 0) 402 return ret; 403 } 404 405 return 0; 406 } 407 408 static void 409 sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, 410 struct snd_soc_dapm_widget_list *list) 411 { 412 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 413 struct snd_sof_widget *swidget = widget->dobj.private; 414 const struct sof_ipc_tplg_widget_ops *widget_ops; 415 struct snd_soc_dapm_path *p; 416 417 if (is_virtual_widget(sdev, widget, __func__)) 418 return; 419 420 /* skip if the widget is in use or if it is already unprepared */ 421 if (!swidget || !swidget->prepared || swidget->use_count > 0) 422 goto sink_unprepare; 423 424 widget_ops = tplg_ops ? tplg_ops->widget : NULL; 425 if (widget_ops && widget_ops[widget->id].ipc_unprepare) 426 /* unprepare the source widget */ 427 widget_ops[widget->id].ipc_unprepare(swidget); 428 429 swidget->prepared = false; 430 431 sink_unprepare: 432 /* unprepare all widgets in the sink paths */ 433 snd_soc_dapm_widget_for_each_sink_path(widget, p) { 434 if (!widget_in_list(list, p->sink)) 435 continue; 436 if (!p->walking && p->sink->dobj.private) { 437 p->walking = true; 438 sof_unprepare_widgets_in_path(sdev, p->sink, list); 439 p->walking = false; 440 } 441 } 442 } 443 444 static int 445 sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, 446 struct snd_pcm_hw_params *fe_params, 447 struct snd_sof_platform_stream_params *platform_params, 448 struct snd_pcm_hw_params *pipeline_params, int dir, 449 struct snd_soc_dapm_widget_list *list) 450 { 451 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 452 struct snd_sof_widget *swidget = widget->dobj.private; 453 const struct sof_ipc_tplg_widget_ops *widget_ops; 454 struct snd_soc_dapm_path *p; 455 int ret; 456 457 if (is_virtual_widget(sdev, widget, __func__)) 458 return 0; 459 460 widget_ops = tplg_ops ? tplg_ops->widget : NULL; 461 if (!widget_ops) 462 return 0; 463 464 if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared) 465 goto sink_prepare; 466 467 /* prepare the source widget */ 468 ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params, 469 pipeline_params, dir); 470 if (ret < 0) { 471 dev_err(sdev->dev, "failed to prepare widget %s\n", widget->name); 472 return ret; 473 } 474 475 swidget->prepared = true; 476 477 sink_prepare: 478 /* prepare all widgets in the sink paths */ 479 snd_soc_dapm_widget_for_each_sink_path(widget, p) { 480 if (!widget_in_list(list, p->sink)) 481 continue; 482 if (!p->walking && p->sink->dobj.private) { 483 p->walking = true; 484 ret = sof_prepare_widgets_in_path(sdev, p->sink, fe_params, 485 platform_params, pipeline_params, dir, 486 list); 487 p->walking = false; 488 if (ret < 0) { 489 /* unprepare the source widget */ 490 if (widget_ops[widget->id].ipc_unprepare && 491 swidget && swidget->prepared && swidget->use_count == 0) { 492 widget_ops[widget->id].ipc_unprepare(swidget); 493 swidget->prepared = false; 494 } 495 return ret; 496 } 497 } 498 } 499 500 return 0; 501 } 502 503 /* 504 * free all widgets in the sink path starting from the source widget 505 * (DAI type for capture, AIF type for playback) 506 */ 507 static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, 508 int dir, struct snd_sof_pcm *spcm) 509 { 510 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; 511 struct snd_soc_dapm_path *p; 512 int err; 513 int ret = 0; 514 515 if (is_virtual_widget(sdev, widget, __func__)) 516 return 0; 517 518 if (widget->dobj.private) { 519 err = sof_widget_free(sdev, widget->dobj.private); 520 if (err < 0) 521 ret = err; 522 } 523 524 /* free all widgets in the sink paths even in case of error to keep use counts balanced */ 525 snd_soc_dapm_widget_for_each_sink_path(widget, p) { 526 if (!p->walking) { 527 if (!widget_in_list(list, p->sink)) 528 continue; 529 530 p->walking = true; 531 532 err = sof_free_widgets_in_path(sdev, p->sink, dir, spcm); 533 if (err < 0) 534 ret = err; 535 p->walking = false; 536 } 537 } 538 539 return ret; 540 } 541 542 /* 543 * set up all widgets in the sink path starting from the source widget 544 * (DAI type for capture, AIF type for playback). 545 * The error path in this function ensures that all successfully set up widgets getting freed. 546 */ 547 static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, 548 int dir, struct snd_sof_pcm *spcm) 549 { 550 struct snd_sof_pcm_stream_pipeline_list *pipeline_list = &spcm->stream[dir].pipeline_list; 551 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; 552 struct snd_sof_widget *swidget = widget->dobj.private; 553 struct snd_sof_pipeline *spipe; 554 struct snd_soc_dapm_path *p; 555 int ret; 556 557 if (is_virtual_widget(sdev, widget, __func__)) 558 return 0; 559 560 if (swidget) { 561 int i; 562 563 ret = sof_widget_setup(sdev, widget->dobj.private); 564 if (ret < 0) 565 return ret; 566 567 /* skip populating the pipe_widgets array if it is NULL */ 568 if (!pipeline_list->pipelines) 569 goto sink_setup; 570 571 /* 572 * Add the widget's pipe_widget to the list of pipelines to be triggered if not 573 * already in the list. This will result in the pipelines getting added in the 574 * order source to sink. 575 */ 576 for (i = 0; i < pipeline_list->count; i++) { 577 spipe = pipeline_list->pipelines[i]; 578 if (spipe == swidget->spipe) 579 break; 580 } 581 582 if (i == pipeline_list->count) { 583 pipeline_list->count++; 584 pipeline_list->pipelines[i] = swidget->spipe; 585 } 586 } 587 588 sink_setup: 589 snd_soc_dapm_widget_for_each_sink_path(widget, p) { 590 if (!p->walking) { 591 if (!widget_in_list(list, p->sink)) 592 continue; 593 594 p->walking = true; 595 596 ret = sof_set_up_widgets_in_path(sdev, p->sink, dir, spcm); 597 p->walking = false; 598 if (ret < 0) { 599 if (swidget) 600 sof_widget_free(sdev, swidget); 601 return ret; 602 } 603 } 604 } 605 606 return 0; 607 } 608 609 static int 610 sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, 611 struct snd_pcm_hw_params *fe_params, 612 struct snd_sof_platform_stream_params *platform_params, int dir, 613 enum sof_widget_op op) 614 { 615 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; 616 struct snd_soc_dapm_widget *widget; 617 char *str; 618 int ret = 0; 619 int i; 620 621 if (!list) 622 return 0; 623 624 for_each_dapm_widgets(list, i, widget) { 625 if (is_virtual_widget(sdev, widget, __func__)) 626 continue; 627 628 /* starting widget for playback is AIF type */ 629 if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in) 630 continue; 631 632 /* starting widget for capture is DAI type */ 633 if (dir == SNDRV_PCM_STREAM_CAPTURE && widget->id != snd_soc_dapm_dai_out) 634 continue; 635 636 switch (op) { 637 case SOF_WIDGET_SETUP: 638 ret = sof_set_up_widgets_in_path(sdev, widget, dir, spcm); 639 str = "set up"; 640 break; 641 case SOF_WIDGET_FREE: 642 ret = sof_free_widgets_in_path(sdev, widget, dir, spcm); 643 str = "free"; 644 break; 645 case SOF_WIDGET_PREPARE: 646 { 647 struct snd_pcm_hw_params pipeline_params; 648 649 str = "prepare"; 650 /* 651 * When walking the list of connected widgets, the pipeline_params for each 652 * widget is modified by the source widget in the path. Use a local 653 * copy of the runtime params as the pipeline_params so that the runtime 654 * params does not get overwritten. 655 */ 656 memcpy(&pipeline_params, fe_params, sizeof(*fe_params)); 657 658 ret = sof_prepare_widgets_in_path(sdev, widget, fe_params, platform_params, 659 &pipeline_params, dir, list); 660 break; 661 } 662 case SOF_WIDGET_UNPREPARE: 663 sof_unprepare_widgets_in_path(sdev, widget, list); 664 break; 665 default: 666 dev_err(sdev->dev, "Invalid widget op %d\n", op); 667 return -EINVAL; 668 } 669 if (ret < 0) { 670 dev_err(sdev->dev, "Failed to %s connected widgets\n", str); 671 return ret; 672 } 673 } 674 675 return 0; 676 } 677 678 int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, 679 struct snd_pcm_hw_params *fe_params, 680 struct snd_sof_platform_stream_params *platform_params, 681 int dir) 682 { 683 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 684 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; 685 struct snd_soc_dapm_widget *widget; 686 int i, ret; 687 688 /* nothing to set up */ 689 if (!list) 690 return 0; 691 692 /* 693 * Prepare widgets for set up. The prepare step is used to allocate memory, assign 694 * instance ID and pick the widget configuration based on the runtime PCM params. 695 */ 696 ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, 697 dir, SOF_WIDGET_PREPARE); 698 if (ret < 0) 699 return ret; 700 701 /* Set up is used to send the IPC to the DSP to create the widget */ 702 ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, 703 dir, SOF_WIDGET_SETUP); 704 if (ret < 0) { 705 sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, 706 dir, SOF_WIDGET_UNPREPARE); 707 return ret; 708 } 709 710 /* 711 * error in setting pipeline connections will result in route status being reset for 712 * routes that were successfully set up when the widgets are freed. 713 */ 714 ret = sof_setup_pipeline_connections(sdev, list, dir); 715 if (ret < 0) 716 goto widget_free; 717 718 /* complete pipelines */ 719 for_each_dapm_widgets(list, i, widget) { 720 struct snd_sof_widget *swidget = widget->dobj.private; 721 struct snd_sof_widget *pipe_widget; 722 struct snd_sof_pipeline *spipe; 723 724 if (!swidget || sdev->dspless_mode_selected) 725 continue; 726 727 spipe = swidget->spipe; 728 if (!spipe) { 729 dev_err(sdev->dev, "no pipeline found for %s\n", 730 swidget->widget->name); 731 ret = -EINVAL; 732 goto widget_free; 733 } 734 735 pipe_widget = spipe->pipe_widget; 736 if (!pipe_widget) { 737 dev_err(sdev->dev, "error: no pipeline widget found for %s\n", 738 swidget->widget->name); 739 ret = -EINVAL; 740 goto widget_free; 741 } 742 743 if (spipe->complete) 744 continue; 745 746 if (tplg_ops && tplg_ops->pipeline_complete) { 747 spipe->complete = tplg_ops->pipeline_complete(sdev, pipe_widget); 748 if (spipe->complete < 0) { 749 ret = spipe->complete; 750 goto widget_free; 751 } 752 } 753 } 754 755 return 0; 756 757 widget_free: 758 sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, dir, 759 SOF_WIDGET_FREE); 760 sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_UNPREPARE); 761 762 return ret; 763 } 764 765 int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir) 766 { 767 struct snd_sof_pcm_stream_pipeline_list *pipeline_list = &spcm->stream[dir].pipeline_list; 768 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; 769 int ret; 770 771 /* nothing to free */ 772 if (!list) 773 return 0; 774 775 /* send IPC to free widget in the DSP */ 776 ret = sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_FREE); 777 778 /* unprepare the widget */ 779 sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_UNPREPARE); 780 781 snd_soc_dapm_dai_free_widgets(&list); 782 spcm->stream[dir].list = NULL; 783 784 pipeline_list->count = 0; 785 786 return ret; 787 } 788 789 /* 790 * helper to determine if there are only D0i3 compatible 791 * streams active 792 */ 793 bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev) 794 { 795 struct snd_pcm_substream *substream; 796 struct snd_sof_pcm *spcm; 797 bool d0i3_compatible_active = false; 798 int dir; 799 800 list_for_each_entry(spcm, &sdev->pcm_list, list) { 801 for_each_pcm_streams(dir) { 802 substream = spcm->stream[dir].substream; 803 if (!substream || !substream->runtime) 804 continue; 805 806 /* 807 * substream->runtime being not NULL indicates 808 * that the stream is open. No need to check the 809 * stream state. 810 */ 811 if (!spcm->stream[dir].d0i3_compatible) 812 return false; 813 814 d0i3_compatible_active = true; 815 } 816 } 817 818 return d0i3_compatible_active; 819 } 820 EXPORT_SYMBOL(snd_sof_dsp_only_d0i3_compatible_stream_active); 821 822 bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev) 823 { 824 struct snd_sof_pcm *spcm; 825 826 list_for_each_entry(spcm, &sdev->pcm_list, list) { 827 if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].suspend_ignored || 828 spcm->stream[SNDRV_PCM_STREAM_CAPTURE].suspend_ignored) 829 return true; 830 } 831 832 return false; 833 } 834 835 int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, 836 struct snd_sof_pcm *spcm, int dir, bool free_widget_list) 837 { 838 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 839 int ret; 840 841 if (spcm->prepared[substream->stream]) { 842 /* stop DMA first if needed */ 843 if (pcm_ops && pcm_ops->platform_stop_during_hw_free) 844 snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); 845 846 /* Send PCM_FREE IPC to reset pipeline */ 847 if (pcm_ops && pcm_ops->hw_free) { 848 ret = pcm_ops->hw_free(sdev->component, substream); 849 if (ret < 0) 850 return ret; 851 } 852 853 spcm->prepared[substream->stream] = false; 854 } 855 856 /* reset the DMA */ 857 ret = snd_sof_pcm_platform_hw_free(sdev, substream); 858 if (ret < 0) 859 return ret; 860 861 /* free widget list */ 862 if (free_widget_list) { 863 ret = sof_widget_list_free(sdev, spcm, dir); 864 if (ret < 0) 865 dev_err(sdev->dev, "failed to free widgets during suspend\n"); 866 } 867 868 return ret; 869 } 870 871 /* 872 * Generic object lookup APIs. 873 */ 874 875 struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp, 876 const char *name) 877 { 878 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 879 struct snd_sof_pcm *spcm; 880 881 list_for_each_entry(spcm, &sdev->pcm_list, list) { 882 /* match with PCM dai name */ 883 if (strcmp(spcm->pcm.dai_name, name) == 0) 884 return spcm; 885 886 /* match with playback caps name if set */ 887 if (*spcm->pcm.caps[0].name && 888 !strcmp(spcm->pcm.caps[0].name, name)) 889 return spcm; 890 891 /* match with capture caps name if set */ 892 if (*spcm->pcm.caps[1].name && 893 !strcmp(spcm->pcm.caps[1].name, name)) 894 return spcm; 895 } 896 897 return NULL; 898 } 899 900 struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp, 901 unsigned int comp_id, 902 int *direction) 903 { 904 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 905 struct snd_sof_pcm *spcm; 906 int dir; 907 908 list_for_each_entry(spcm, &sdev->pcm_list, list) { 909 for_each_pcm_streams(dir) { 910 if (spcm->stream[dir].comp_id == comp_id) { 911 *direction = dir; 912 return spcm; 913 } 914 } 915 } 916 917 return NULL; 918 } 919 920 struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp, 921 const char *name) 922 { 923 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 924 struct snd_sof_widget *swidget; 925 926 list_for_each_entry(swidget, &sdev->widget_list, list) { 927 if (strcmp(name, swidget->widget->name) == 0) 928 return swidget; 929 } 930 931 return NULL; 932 } 933 934 /* find widget by stream name and direction */ 935 struct snd_sof_widget * 936 snd_sof_find_swidget_sname(struct snd_soc_component *scomp, 937 const char *pcm_name, int dir) 938 { 939 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 940 struct snd_sof_widget *swidget; 941 enum snd_soc_dapm_type type; 942 943 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 944 type = snd_soc_dapm_aif_in; 945 else 946 type = snd_soc_dapm_aif_out; 947 948 list_for_each_entry(swidget, &sdev->widget_list, list) { 949 if (!strcmp(pcm_name, swidget->widget->sname) && 950 swidget->id == type) 951 return swidget; 952 } 953 954 return NULL; 955 } 956 957 struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, 958 const char *name) 959 { 960 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 961 struct snd_sof_dai *dai; 962 963 list_for_each_entry(dai, &sdev->dai_list, list) { 964 if (dai->name && (strcmp(name, dai->name) == 0)) 965 return dai; 966 } 967 968 return NULL; 969 } 970 971 static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type) 972 { 973 struct snd_soc_component *component = 974 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); 975 struct snd_sof_dai *dai = 976 snd_sof_find_dai(component, (char *)rtd->dai_link->name); 977 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 978 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 979 980 /* use the tplg configured mclk if existed */ 981 if (!dai) 982 return 0; 983 984 if (tplg_ops && tplg_ops->dai_get_clk) 985 return tplg_ops->dai_get_clk(sdev, dai, clk_type); 986 987 return 0; 988 } 989 990 /* 991 * Helper to get SSP MCLK from a pcm_runtime. 992 * Return 0 if not exist. 993 */ 994 int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd) 995 { 996 return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_MCLK); 997 } 998 EXPORT_SYMBOL(sof_dai_get_mclk); 999 1000 /* 1001 * Helper to get SSP BCLK from a pcm_runtime. 1002 * Return 0 if not exist. 1003 */ 1004 int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd) 1005 { 1006 return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_BCLK); 1007 } 1008 EXPORT_SYMBOL(sof_dai_get_bclk); 1009 1010 static struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev) 1011 { 1012 struct snd_sof_pdata *sof_pdata = sdev->pdata; 1013 const struct sof_dev_desc *desc = sof_pdata->desc; 1014 struct snd_sof_of_mach *mach = desc->of_machines; 1015 1016 if (!mach) 1017 return NULL; 1018 1019 for (; mach->compatible; mach++) { 1020 if (of_machine_is_compatible(mach->compatible)) { 1021 sof_pdata->tplg_filename = mach->sof_tplg_filename; 1022 if (mach->fw_filename) 1023 sof_pdata->fw_filename = mach->fw_filename; 1024 1025 return mach; 1026 } 1027 } 1028 1029 return NULL; 1030 } 1031 1032 /* 1033 * SOF Driver enumeration. 1034 */ 1035 int sof_machine_check(struct snd_sof_dev *sdev) 1036 { 1037 struct snd_sof_pdata *sof_pdata = sdev->pdata; 1038 const struct sof_dev_desc *desc = sof_pdata->desc; 1039 struct snd_soc_acpi_mach *mach; 1040 1041 if (!IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)) { 1042 const struct snd_sof_of_mach *of_mach; 1043 1044 if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) && 1045 sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC)) 1046 goto nocodec; 1047 1048 /* find machine */ 1049 mach = snd_sof_machine_select(sdev); 1050 if (mach) { 1051 sof_pdata->machine = mach; 1052 1053 if (sof_pdata->subsystem_id_set) { 1054 mach->mach_params.subsystem_vendor = sof_pdata->subsystem_vendor; 1055 mach->mach_params.subsystem_device = sof_pdata->subsystem_device; 1056 mach->mach_params.subsystem_id_set = true; 1057 } 1058 1059 snd_sof_set_mach_params(mach, sdev); 1060 return 0; 1061 } 1062 1063 of_mach = sof_of_machine_select(sdev); 1064 if (of_mach) { 1065 sof_pdata->of_machine = of_mach; 1066 return 0; 1067 } 1068 1069 if (!IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)) { 1070 dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); 1071 return -ENODEV; 1072 } 1073 } else { 1074 dev_warn(sdev->dev, "Force to use nocodec mode\n"); 1075 } 1076 1077 nocodec: 1078 /* select nocodec mode */ 1079 dev_warn(sdev->dev, "Using nocodec machine driver\n"); 1080 mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL); 1081 if (!mach) 1082 return -ENOMEM; 1083 1084 mach->drv_name = "sof-nocodec"; 1085 if (!sof_pdata->tplg_filename) 1086 sof_pdata->tplg_filename = desc->nocodec_tplg_filename; 1087 1088 sof_pdata->machine = mach; 1089 snd_sof_set_mach_params(mach, sdev); 1090 1091 return 0; 1092 } 1093 EXPORT_SYMBOL(sof_machine_check); 1094 1095 int sof_machine_register(struct snd_sof_dev *sdev, void *pdata) 1096 { 1097 struct snd_sof_pdata *plat_data = pdata; 1098 const char *drv_name; 1099 const void *mach; 1100 int size; 1101 1102 drv_name = plat_data->machine->drv_name; 1103 mach = plat_data->machine; 1104 size = sizeof(*plat_data->machine); 1105 1106 /* register machine driver, pass machine info as pdata */ 1107 plat_data->pdev_mach = 1108 platform_device_register_data(sdev->dev, drv_name, 1109 PLATFORM_DEVID_NONE, mach, size); 1110 if (IS_ERR(plat_data->pdev_mach)) 1111 return PTR_ERR(plat_data->pdev_mach); 1112 1113 dev_dbg(sdev->dev, "created machine %s\n", 1114 dev_name(&plat_data->pdev_mach->dev)); 1115 1116 return 0; 1117 } 1118 EXPORT_SYMBOL(sof_machine_register); 1119 1120 void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata) 1121 { 1122 struct snd_sof_pdata *plat_data = pdata; 1123 1124 if (!IS_ERR_OR_NULL(plat_data->pdev_mach)) 1125 platform_device_unregister(plat_data->pdev_mach); 1126 } 1127 EXPORT_SYMBOL(sof_machine_unregister); 1128