Skip to content

Commit 9c00d76

Browse files
committed
ASoC: SOF: sof-audio: Traverse paths with virtual widgets
Today, we use virtual widgets in topology to represent aggregated DAI's in the graph. So, when walking the list of DAPM widgets, when we encounter a virtual widget, we end the walk there. Modify the logic to allow walking past the virtual widgets without handling them during prepare/unprepare/setup/free. This will be useful for the hostless pipelines that use the virtual widget as the start of the playback pipeline. For example, in the case of a tone generator playback pipeline, we could have virtual widget (type input) -> tone generator -> gain -> BE DAI The virtual widget exists only to establish a FE <-> BE connection for DPCM. So while walking the list of widgets, skip the virtual widget and move on so that the tone generator and all of the other widgets downstream can be handled. But in order for this to work with the current use of virtual widgets to represent aggregated DAI's, we also need to skip the aggregated DAI's from being handled during prepare/unprepare/free/setup. Add a new helper function to determine if a DAI widget is an aggregated DAI and skip past the widget when walking the list of connected DAPM widgets. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent e2f07ee commit 9c00d76

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

sound/soc/sof/ipc4-topology.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,9 +2773,9 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
27732773
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
27742774

27752775
out_ref_rate = in_fmt->sampling_frequency;
2776-
out_ref_channels =
2776+
out_ref_channels =
27772777
SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
2778-
out_ref_valid_bits =
2778+
out_ref_valid_bits =
27792779
SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
27802780
out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);
27812781
} else {

sound/soc/sof/sof-audio.c

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@
1313
#include "sof-audio.h"
1414
#include "ops.h"
1515

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+
1631
static bool is_virtual_widget(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
1732
const char *func)
1833
{
@@ -399,11 +414,13 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg
399414
const struct sof_ipc_tplg_widget_ops *widget_ops;
400415
struct snd_soc_dapm_path *p;
401416

402-
if (is_virtual_widget(sdev, widget, __func__))
403-
return;
404-
405417
/* skip if the widget is in use or if it is already unprepared */
406-
if (!swidget || !swidget->prepared || swidget->use_count > 0)
418+
if (!swidget || !swidget->prepared || swidget->use_count > 0 ||
419+
is_virtual_widget(sdev, widget, __func__))
420+
goto sink_unprepare;
421+
422+
/* skip aggregated DAIs */
423+
if(is_aggregated_dai(swidget))
407424
goto sink_unprepare;
408425

409426
widget_ops = tplg_ops ? tplg_ops->widget : NULL;
@@ -440,7 +457,7 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
440457
int ret;
441458

442459
if (is_virtual_widget(sdev, widget, __func__))
443-
return 0;
460+
goto sink_prepare;
444461

445462
widget_ops = tplg_ops ? tplg_ops->widget : NULL;
446463
if (!widget_ops)
@@ -449,6 +466,10 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
449466
if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared)
450467
goto sink_prepare;
451468

469+
/* skip aggregated DAIs */
470+
if(is_aggregated_dai(swidget))
471+
goto sink_prepare;
472+
452473
/* prepare the source widget */
453474
ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params,
454475
pipeline_params, dir);
@@ -493,15 +514,19 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap
493514
int dir, struct snd_sof_pcm *spcm)
494515
{
495516
struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
517+
struct snd_sof_widget *swidget;
496518
struct snd_soc_dapm_path *p;
497519
int err;
498520
int ret = 0;
499521

500522
if (is_virtual_widget(sdev, widget, __func__))
501-
return 0;
523+
goto sink_free;
502524

503-
if (widget->dobj.private) {
504-
err = sof_widget_free(sdev, widget->dobj.private);
525+
swidget = widget->dobj.private;
526+
527+
/* no need to free aggregated DAI widgets */
528+
if (swidget && !is_aggregated_dai(swidget)) {
529+
err = sof_widget_free(sdev, swidget);
505530
if (err < 0)
506531
ret = err;
507532
}
@@ -540,12 +565,15 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
540565
int ret;
541566

542567
if (is_virtual_widget(sdev, widget, __func__))
543-
return 0;
568+
goto sink_setup;
544569

545570
if (swidget) {
546571
int i;
547572

548-
ret = sof_widget_setup(sdev, widget->dobj.private);
573+
if(is_aggregated_dai(swidget))
574+
goto sink_setup;
575+
576+
ret = sof_widget_setup(sdev, swidget);
549577
if (ret < 0)
550578
return ret;
551579

0 commit comments

Comments
 (0)