|
13 | 13 | #include "sof-audio.h" |
14 | 14 | #include "ops.h" |
15 | 15 |
|
| 16 | +/* |
| 17 | + * Check is a DAI widget is an aggregated DAI. Aggregated DAI's have names ending in numbers |
| 18 | + * starting with 0 and only the first DAI needs to be set up in the firmware. The rest of |
| 19 | + * the aggregated DAI's are represented in the topology graph for completeness but do not |
| 20 | + * need any firmware configuration. |
| 21 | + */ |
| 22 | +static bool is_aggregated_dai(struct snd_sof_widget *swidget) |
| 23 | +{ |
| 24 | + return (WIDGET_IS_DAI(swidget->id) && |
| 25 | + isdigit(swidget->widget->name[strlen(swidget->widget->name) - 1]) && |
| 26 | + swidget->widget->name[strlen(swidget->widget->name) - 1] != '0'); |
| 27 | +} |
| 28 | + |
16 | 29 | static bool is_virtual_widget(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, |
17 | 30 | const char *func) |
18 | 31 | { |
@@ -412,6 +425,10 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg |
412 | 425 | struct snd_soc_dapm_path *p; |
413 | 426 |
|
414 | 427 | if (is_virtual_widget(sdev, widget, __func__)) |
| 428 | + goto sink_unprepare; |
| 429 | + |
| 430 | + /* skip aggregated DAIs */ |
| 431 | + if (!swidget || is_aggregated_dai(swidget)) |
415 | 432 | return; |
416 | 433 |
|
417 | 434 | /* skip if the widget is in use or if it is already unprepared */ |
@@ -452,12 +469,16 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget |
452 | 469 | int ret; |
453 | 470 |
|
454 | 471 | if (is_virtual_widget(sdev, widget, __func__)) |
455 | | - return 0; |
| 472 | + goto sink_prepare; |
456 | 473 |
|
457 | 474 | widget_ops = tplg_ops ? tplg_ops->widget : NULL; |
458 | 475 | if (!widget_ops) |
459 | 476 | return 0; |
460 | 477 |
|
| 478 | + /* skip aggregated DAIs */ |
| 479 | + if (!swidget || is_aggregated_dai(swidget)) |
| 480 | + return 0; |
| 481 | + |
461 | 482 | if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared) |
462 | 483 | goto sink_prepare; |
463 | 484 |
|
@@ -506,18 +527,23 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap |
506 | 527 | { |
507 | 528 | struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; |
508 | 529 | struct snd_soc_dapm_path *p; |
| 530 | + struct snd_sof_widget *swidget; |
509 | 531 | int err; |
510 | 532 | int ret = 0; |
511 | 533 |
|
512 | 534 | if (is_virtual_widget(sdev, widget, __func__)) |
513 | | - return 0; |
| 535 | + goto sink_free; |
514 | 536 |
|
515 | | - if (widget->dobj.private) { |
516 | | - err = sof_widget_free(sdev, widget->dobj.private); |
517 | | - if (err < 0) |
518 | | - ret = err; |
519 | | - } |
| 537 | + swidget = widget->dobj.private; |
520 | 538 |
|
| 539 | + /* skip aggregated DAIs */ |
| 540 | + if (!swidget || is_aggregated_dai(swidget)) |
| 541 | + return 0; |
| 542 | + |
| 543 | + err = sof_widget_free(sdev, widget->dobj.private); |
| 544 | + if (err < 0) |
| 545 | + ret = err; |
| 546 | +sink_free: |
521 | 547 | /* free all widgets in the sink paths even in case of error to keep use counts balanced */ |
522 | 548 | snd_soc_dapm_widget_for_each_sink_path(widget, p) { |
523 | 549 | if (!p->walking) { |
@@ -552,11 +578,15 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d |
552 | 578 | int ret; |
553 | 579 |
|
554 | 580 | if (is_virtual_widget(sdev, widget, __func__)) |
555 | | - return 0; |
| 581 | + goto sink_setup; |
556 | 582 |
|
557 | 583 | if (swidget) { |
558 | 584 | int i; |
559 | 585 |
|
| 586 | + /* skip aggregated DAIs */ |
| 587 | + if (!swidget || is_aggregated_dai(swidget)) |
| 588 | + return 0; |
| 589 | + |
560 | 590 | ret = sof_widget_setup(sdev, widget->dobj.private); |
561 | 591 | if (ret < 0) |
562 | 592 | return ret; |
@@ -619,11 +649,10 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, |
619 | 649 | return 0; |
620 | 650 |
|
621 | 651 | for_each_dapm_widgets(list, i, widget) { |
622 | | - if (is_virtual_widget(sdev, widget, __func__)) |
623 | | - continue; |
624 | 652 |
|
625 | | - /* starting widget for playback is AIF type */ |
626 | | - if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in) |
| 653 | + /* starting widget for playback is of AIF or snd_soc_dapm_input type */ |
| 654 | + if (dir == SNDRV_PCM_STREAM_PLAYBACK && (widget->id != snd_soc_dapm_aif_in && |
| 655 | + widget->id != snd_soc_dapm_input)) |
627 | 656 | continue; |
628 | 657 |
|
629 | 658 | /* starting widget for capture is DAI type */ |
@@ -904,29 +933,41 @@ struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp, |
904 | 933 | return NULL; |
905 | 934 | } |
906 | 935 |
|
907 | | -/* find widget by stream name and direction */ |
908 | | -struct snd_sof_widget * |
909 | | -snd_sof_find_swidget_sname(struct snd_soc_component *scomp, |
910 | | - const char *pcm_name, int dir) |
| 936 | +static struct snd_sof_widget *snd_sof_find_swidget_sname_type(struct snd_soc_component *scomp, |
| 937 | + const char *sname, |
| 938 | + enum snd_soc_dapm_type type) |
911 | 939 | { |
912 | 940 | struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); |
913 | 941 | struct snd_sof_widget *swidget; |
914 | | - enum snd_soc_dapm_type type; |
915 | | - |
916 | | - if (dir == SNDRV_PCM_STREAM_PLAYBACK) |
917 | | - type = snd_soc_dapm_aif_in; |
918 | | - else |
919 | | - type = snd_soc_dapm_aif_out; |
920 | 942 |
|
921 | 943 | list_for_each_entry(swidget, &sdev->widget_list, list) { |
922 | | - if (!strcmp(pcm_name, swidget->widget->sname) && |
923 | | - swidget->id == type) |
| 944 | + if (!strcmp(sname, swidget->widget->sname) && swidget->id == type) |
924 | 945 | return swidget; |
925 | 946 | } |
926 | 947 |
|
927 | 948 | return NULL; |
928 | 949 | } |
929 | 950 |
|
| 951 | +/* find widget by stream name and direction */ |
| 952 | +struct snd_sof_widget * |
| 953 | +snd_sof_find_swidget_sname(struct snd_soc_component *scomp, |
| 954 | + const char *pcm_name, int dir) |
| 955 | +{ |
| 956 | + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { |
| 957 | + struct snd_sof_widget *swidget; |
| 958 | + |
| 959 | + /* first look for an aif_in type widget */ |
| 960 | + swidget = snd_sof_find_swidget_sname_type(scomp, pcm_name, snd_soc_dapm_aif_in); |
| 961 | + if (swidget) |
| 962 | + return swidget; |
| 963 | + |
| 964 | + /* if not found, look for an input type widget */ |
| 965 | + return snd_sof_find_swidget_sname_type(scomp, pcm_name, snd_soc_dapm_input); |
| 966 | + } |
| 967 | + |
| 968 | + return snd_sof_find_swidget_sname_type(scomp, pcm_name, snd_soc_dapm_aif_out); |
| 969 | +} |
| 970 | + |
930 | 971 | struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, |
931 | 972 | const char *name) |
932 | 973 | { |
|
0 commit comments