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