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