|
13 | 13 | #include "sof-audio.h" |
14 | 14 | #include "ops.h" |
15 | 15 |
|
| 16 | +/* |
| 17 | + * Check if a DAI widget is an aggregated DAI. Aggregated DAI's have names ending in numbers |
| 18 | + * starting with 0. For example: in the case of a SDW speaker with 2 amps, the topology contains |
| 19 | + * 2 DAI's names alh-copier.SDW1.Playback.0 and alh-copier-SDW1.Playback.1. In this case, only the |
| 20 | + * DAI alh-copier.SDW1.Playback.0 is set up in the firmware. The other DAI, |
| 21 | + * alh-copier.SDW1.Playback.1 in topology is for the sake of completeness to show aggregation for |
| 22 | + * the speaker amp and does not need any firmware configuration. |
| 23 | + */ |
| 24 | +static bool is_aggregated_dai(struct snd_sof_widget *swidget) |
| 25 | +{ |
| 26 | + return (WIDGET_IS_DAI(swidget->id) && |
| 27 | + isdigit(swidget->widget->name[strlen(swidget->widget->name) - 1]) && |
| 28 | + swidget->widget->name[strlen(swidget->widget->name) - 1] != '0'); |
| 29 | +} |
| 30 | + |
16 | 31 | static bool is_virtual_widget(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, |
17 | 32 | const char *func) |
18 | 33 | { |
@@ -402,8 +417,9 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg |
402 | 417 | if (is_virtual_widget(sdev, widget, __func__)) |
403 | 418 | return; |
404 | 419 |
|
405 | | - /* skip if the widget is in use or if it is already unprepared */ |
406 | | - if (!swidget || !swidget->prepared || swidget->use_count > 0) |
| 420 | + /* skip if the widget in use or already unprepared or is an aggregated DAI */ |
| 421 | + if (!swidget || !swidget->prepared || swidget->use_count > 0 || |
| 422 | + is_aggregated_dai(swidget)) |
407 | 423 | goto sink_unprepare; |
408 | 424 |
|
409 | 425 | widget_ops = tplg_ops ? tplg_ops->widget : NULL; |
@@ -449,6 +465,10 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget |
449 | 465 | if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared) |
450 | 466 | goto sink_prepare; |
451 | 467 |
|
| 468 | + /* skip aggregated DAIs */ |
| 469 | + if (is_aggregated_dai(swidget)) |
| 470 | + goto sink_prepare; |
| 471 | + |
452 | 472 | /* prepare the source widget */ |
453 | 473 | ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params, |
454 | 474 | pipeline_params, dir); |
@@ -493,15 +513,19 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap |
493 | 513 | int dir, struct snd_sof_pcm *spcm) |
494 | 514 | { |
495 | 515 | struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; |
| 516 | + struct snd_sof_widget *swidget; |
496 | 517 | struct snd_soc_dapm_path *p; |
497 | 518 | int err; |
498 | 519 | int ret = 0; |
499 | 520 |
|
500 | 521 | if (is_virtual_widget(sdev, widget, __func__)) |
501 | 522 | return 0; |
502 | 523 |
|
503 | | - if (widget->dobj.private) { |
504 | | - err = sof_widget_free(sdev, widget->dobj.private); |
| 524 | + swidget = widget->dobj.private; |
| 525 | + |
| 526 | + /* no need to free aggregated DAI widgets */ |
| 527 | + if (swidget && !is_aggregated_dai(swidget)) { |
| 528 | + err = sof_widget_free(sdev, swidget); |
505 | 529 | if (err < 0) |
506 | 530 | ret = err; |
507 | 531 | } |
@@ -545,7 +569,10 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d |
545 | 569 | if (swidget) { |
546 | 570 | int i; |
547 | 571 |
|
548 | | - ret = sof_widget_setup(sdev, widget->dobj.private); |
| 572 | + if (is_aggregated_dai(swidget)) |
| 573 | + goto sink_setup; |
| 574 | + |
| 575 | + ret = sof_widget_setup(sdev, swidget); |
549 | 576 | if (ret < 0) |
550 | 577 | return ret; |
551 | 578 |
|
|
0 commit comments